From 6052efe94992ee591b72b495b209777fc71d0f6a Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Thu, 3 Oct 2019 14:58:11 +0300 Subject: [PATCH 03/33] Implement support for alternative (uncompressed) payload digest During build, also calculate a digest for the uncompressed payload data and add to packages. On verify side this is equivalent to the existing payload digest (through sharing the same disabler), which allows either one to be used for verification. This means deltarpm and similar don't need to recompress the data which is both expensive and error-prone due to minor differences in compressed stream despite the actual data being identical. Add a testcase for the basic behavior and update other test output expectations where necessary. --- build/pack.c | 16 ++++++++++++---- lib/rpmchecksig.c | 1 + lib/rpmtag.h | 1 + lib/rpmvs.c | 4 ++++ tests/rpmgeneral.at | 1 + tests/rpmsigdig.at | 32 ++++++++++++++++++++++++++++++++ tests/rpmvfylevel.at | 2 ++ 7 files changed, 53 insertions(+), 4 deletions(-) diff --git a/build/pack.c b/build/pack.c index c7c1d8f46..9293e98e4 100644 --- a/build/pack.c +++ b/build/pack.c @@ -70,7 +70,8 @@ static int rpmPackageFilesArchive(rpmfiles fi, int isSrc, * @todo Create transaction set *much* earlier. */ static rpmRC cpio_doio(FD_t fdo, Package pkg, const char * fmodeMacro, - rpm_loff_t *archiveSize) + int pld_algo, + rpm_loff_t *archiveSize, char ** pldig) { char *failedFile = NULL; FD_t cfd; @@ -81,9 +82,12 @@ static rpmRC cpio_doio(FD_t fdo, Package pkg, const char * fmodeMacro, if (cfd == NULL) return RPMRC_FAIL; + /* Calculate alternative (uncompressed) payload digest while writing */ + fdInitDigestID(cfd, pld_algo, RPMTAG_PAYLOADDIGESTALT, 0); fsmrc = rpmPackageFilesArchive(pkg->cpioList, headerIsSource(pkg->header), cfd, pkg->dpaths, archiveSize, &failedFile); + fdFiniDigest(cfd, RPMTAG_PAYLOADDIGESTALT, (void **)pldig, NULL, 1); if (fsmrc) { char *emsg = rpmfileStrerror(fsmrc); @@ -512,6 +516,7 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp, char * SHA256 = NULL; uint8_t * MD5 = NULL; char * pld = NULL; + char * upld = NULL; uint32_t pld_algo = PGPHASHALGO_SHA256; /* TODO: macro configuration */ rpmRC rc = RPMRC_FAIL; /* assume failure */ rpm_loff_t archiveSize = 0; @@ -532,10 +537,11 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp, headerPutString(pkg->header, RPMTAG_COOKIE, *cookie); } - /* Create a dummy payload digest to get the header size right */ + /* Create a dummy payload digests to get the header size right */ pld = nullDigest(pld_algo, 1); headerPutUint32(pkg->header, RPMTAG_PAYLOADDIGESTALGO, &pld_algo, 1); headerPutString(pkg->header, RPMTAG_PAYLOADDIGEST, pld); + headerPutString(pkg->header, RPMTAG_PAYLOADDIGESTALT, pld); pld = _free(pld); /* Check for UTF-8 encoding of string tags, add encoding tag if all good */ @@ -576,7 +582,7 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp, /* Write payload section (cpio archive) */ payloadStart = Ftell(fd); - if (cpio_doio(fd, pkg, rpmio_flags, &archiveSize)) + if (cpio_doio(fd, pkg, rpmio_flags, pld_algo, &archiveSize, &upld)) goto exit; payloadEnd = Ftell(fd); @@ -586,9 +592,11 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp, goto exit; fdFiniDigest(fd, RPMTAG_PAYLOADDIGEST, (void **)&pld, NULL, 1); - /* Insert the payload digest in main header */ + /* Insert the payload digests in main header */ headerDel(pkg->header, RPMTAG_PAYLOADDIGEST); headerPutString(pkg->header, RPMTAG_PAYLOADDIGEST, pld); + headerDel(pkg->header, RPMTAG_PAYLOADDIGESTALT); + headerPutString(pkg->header, RPMTAG_PAYLOADDIGESTALT, upld); pld = _free(pld); /* Write the final header */ diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c index beca0e7b2..c4986b99c 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c @@ -189,6 +189,7 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, /* Fish interesting tags from the main header. This is a bit hacky... */ rpmvsAppendTag(vs, blob, RPMTAG_PAYLOADDIGEST); + rpmvsAppendTag(vs, blob, RPMTAG_PAYLOADDIGESTALT); /* If needed and not explicitly disabled, read the payload as well. */ if (rpmvsRange(vs) & RPMSIG_PAYLOAD) { diff --git a/lib/rpmtag.h b/lib/rpmtag.h index 002492d20..8bdf34405 100644 --- a/lib/rpmtag.h +++ b/lib/rpmtag.h @@ -371,6 +371,7 @@ typedef enum rpmTag_e { RPMTAG_AUTOINSTALLED = 5094, /* i reservation (unimplemented) */ RPMTAG_IDENTITY = 5095, /* s reservation (unimplemented) */ RPMTAG_MODULARITYLABEL = 5096, /* s */ + RPMTAG_PAYLOADDIGESTALT = 5097, /* s[] */ RPMTAG_FIRSTFREE_TAG /*!< internal */ } rpmTag; diff --git a/lib/rpmvs.c b/lib/rpmvs.c index 0d475af86..9a90e2eb8 100644 --- a/lib/rpmvs.c +++ b/lib/rpmvs.c @@ -40,6 +40,7 @@ static const struct vfytag_s rpmvfytags[] = { { RPMSIGTAG_LONGARCHIVESIZE, RPM_INT64_TYPE, 1, 8, }, { RPMTAG_SHA256HEADER, RPM_STRING_TYPE, 1, 65, }, { RPMTAG_PAYLOADDIGEST, RPM_STRING_ARRAY_TYPE, 0, 0, }, + { RPMTAG_PAYLOADDIGESTALT, RPM_STRING_ARRAY_TYPE, 0, 0, }, { 0 } /* sentinel */ }; @@ -89,6 +90,9 @@ static const struct vfyinfo_s rpmvfyitems[] = { { RPMTAG_PAYLOADDIGEST, 0, { RPMSIG_DIGEST_TYPE, RPMVSF_NOPAYLOAD, (RPMSIG_PAYLOAD), PGPHASHALGO_SHA256, 0, }, }, + { RPMTAG_PAYLOADDIGESTALT, 0, + { RPMSIG_DIGEST_TYPE, RPMVSF_NOPAYLOAD, + (RPMSIG_PAYLOAD), PGPHASHALGO_SHA256, 0, 1, }, }, { 0 } /* sentinel */ }; diff --git a/tests/rpmgeneral.at b/tests/rpmgeneral.at index 45d38698b..7f100774c 100644 --- a/tests/rpmgeneral.at +++ b/tests/rpmgeneral.at @@ -192,6 +192,7 @@ PATCHESVERSION PAYLOADCOMPRESSOR PAYLOADDIGEST PAYLOADDIGESTALGO +PAYLOADDIGESTALT PAYLOADFLAGS PAYLOADFORMAT PKGID diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at index 880e5edd0..f6ad72589 100644 --- a/tests/rpmsigdig.at +++ b/tests/rpmsigdig.at @@ -26,6 +26,34 @@ runroot rpmkeys -Kv /data/RPMS/hello-2.0-1.x86_64.rpm /data/RPMS/hello-1.0-1.i38 []) AT_CLEANUP +AT_SETUP([rpmkeys -Kv 1]) +AT_KEYWORDS([rpmkeys digest]) +AT_CHECK([ +RPMDB_CLEAR +RPMDB_INIT +rm -rf "${TOPDIR}" + +cp "${RPMTEST}"/data/misc/hello.intro "${RPMTEST}"/data/misc/hello.payload . +gzip -cd < hello.payload > hello.uc-payload +cat hello.intro hello.payload > "${RPMTEST}"/tmp/hello-c.rpm +cat hello.intro hello.uc-payload > "${RPMTEST}"/tmp/hello-uc.rpm +runroot rpmkeys -Kv /tmp/hello-c.rpm /tmp/hello-uc.rpm +], +[1], +[/tmp/hello-c.rpm: + Header SHA256 digest: OK + Header SHA1 digest: OK + Payload SHA256 digest: OK + MD5 digest: OK +/tmp/hello-uc.rpm: + Header SHA256 digest: OK + Header SHA1 digest: OK + Payload SHA256 ALT digest: OK + MD5 digest: BAD (Expected 055607c4dee6464b9415ae726e7d81a7 != 839d24c30e5188e0b83599fbe3865919) +], +[]) +AT_CLEANUP + # ------------------------------ # Test corrupted package verification (corrupted signature) AT_SETUP([rpmkeys -Kv 1]) @@ -96,6 +124,7 @@ runroot rpmkeys -Kv /tmp/${pkg} Header SHA256 digest: OK Header SHA1 digest: OK Payload SHA256 digest: BAD (Expected 84a7338287bf19715c4eed0243f5cdb447eeb0ade37b2af718d4060aefca2f7c != bea903609dceac36e1f26a983c493c98064d320fdfeb423034ed63d649b2c8dc) + Payload SHA256 ALT digest: NOTFOUND MD5 digest: BAD (Expected 137ca1d8b35cca02a1854ba301c5432e != d662cd0d81601a7107312684ad1ddf38) ], []) @@ -145,6 +174,7 @@ runroot rpmkeys -Kv /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm [/build/RPMS/noarch/attrtest-1.0-1.noarch.rpm: Header SHA256 digest: OK Header SHA1 digest: OK + Payload SHA256 ALT digest: OK Payload SHA256 digest: OK MD5 digest: OK ], @@ -376,6 +406,7 @@ runroot rpmkeys -Kv /tmp/${pkg} Header SHA256 digest: OK Header SHA1 digest: OK Payload SHA256 digest: BAD (Expected 84a7338287bf19715c4eed0243f5cdb447eeb0ade37b2af718d4060aefca2f7c != bea903609dceac36e1f26a983c493c98064d320fdfeb423034ed63d649b2c8dc) + Payload SHA256 ALT digest: NOTFOUND V4 RSA/SHA256 Signature, key ID 1964c5fc: BAD MD5 digest: BAD (Expected 137ca1d8b35cca02a1854ba301c5432e != d662cd0d81601a7107312684ad1ddf38) /tmp/hello-2.0-1.x86_64-signed.rpm: @@ -383,6 +414,7 @@ runroot rpmkeys -Kv /tmp/${pkg} Header SHA256 digest: OK Header SHA1 digest: OK Payload SHA256 digest: BAD (Expected 84a7338287bf19715c4eed0243f5cdb447eeb0ade37b2af718d4060aefca2f7c != bea903609dceac36e1f26a983c493c98064d320fdfeb423034ed63d649b2c8dc) + Payload SHA256 ALT digest: NOTFOUND V4 RSA/SHA256 Signature, key ID 1964c5fc: BAD MD5 digest: BAD (Expected 137ca1d8b35cca02a1854ba301c5432e != d662cd0d81601a7107312684ad1ddf38) ], diff --git a/tests/rpmvfylevel.at b/tests/rpmvfylevel.at index 17531b0fe..cb5e48ad7 100644 --- a/tests/rpmvfylevel.at +++ b/tests/rpmvfylevel.at @@ -117,6 +117,7 @@ nopl Header SHA256 digest: OK Header SHA1 digest: OK Payload SHA256 digest: NOTFOUND + Payload SHA256 ALT digest: NOTFOUND MD5 digest: NOTFOUND 1 nosha1 @@ -338,6 +339,7 @@ noplds Header SHA256 digest: OK Header SHA1 digest: OK Payload SHA256 digest: NOTFOUND + Payload SHA256 ALT digest: NOTFOUND RSA signature: NOTFOUND DSA signature: NOTFOUND MD5 digest: OK -- 2.13.5