malmond / rpms / rpm

Forked from rpms/rpm 4 years ago
Clone
Blob Blame History Raw
From 6052efe94992ee591b72b495b209777fc71d0f6a Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
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 <reconstructed> 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 <corrupted unsigned> 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