malmond / rpms / rpm

Forked from rpms/rpm 4 years ago
Clone
Blob Blame History Raw
From 4276d324bebf442299a90b5a9c4679829ab96385 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 2 Mar 2020 14:47:26 +0200
Subject: [PATCH 13/33] Stop adding rpm v3 header+payload signatures by default
 where not needed

On packages where a separate payload digest exists (ie those built with
rpm >= 4.14), rpm v3 header+payload signatures are nothing but expensive
legacy baggage, as the payload digest will be signed by a header-only
signature already, without having to recalculate the entire file.

Automatically detect the payload digest presence and only add V3
signatures on packages that need it, but also add an override switch
to force their addition if needed for compatibility or so. A particular
use-case would be ability to signature-level verify the entire package
on rpm older than 4.14.

Fixes: #863
---
 doc/rpmsign.8      |  9 +++++++++
 rpmsign.c          |  3 +++
 sign/rpmgensig.c   | 24 +++++++++++++++++-------
 sign/rpmsign.h     |  1 +
 tests/rpmsigdig.at | 36 ++++++++++++++++++++++++++++++++++--
 5 files changed, 64 insertions(+), 9 deletions(-)

diff --git a/doc/rpmsign.8 b/doc/rpmsign.8
index d895a3b8c..f7ceae89b 100644
--- a/doc/rpmsign.8
+++ b/doc/rpmsign.8
@@ -11,6 +11,7 @@ rpmsign \- RPM Package Signing
 
 .SS "rpmsign-options"
 .PP
+[\fb--rpmv3\fR]
 [\fb--fskpath \fIKEY\fb\fR] [\fB--signfiles\fR]
 
 .SH DESCRIPTION
@@ -32,6 +33,14 @@ Delete all signatures from each package \fIPACKAGE_FILE\fR given.
 .SS "SIGN OPTIONS"
 .PP
 .TP
+\fB--rpmv3\fR
+Force RPM V3 header+payload signature addition.
+These are expensive and redundant baggage on packages where a separate
+payload digest exists (packages built with rpm >= 4.14).  Rpm will
+automatically detect the need for V3 signatures, but this option can be
+used to force their creation if the packages must be fully 
+signature verifiable with rpm < 4.14 or other interoperability reasons.
+.TP
 \fB--fskpath \fIKEY\fB\fR
 Used with \fB--signfiles\fR, use file signing key \fIKey\fR.
 .TP
diff --git a/rpmsign.c b/rpmsign.c
index 57cb36919..a74948ba8 100644
--- a/rpmsign.c
+++ b/rpmsign.c
@@ -32,6 +32,9 @@ static struct poptOption signOptsTable[] = {
 	N_("sign package(s) (identical to --addsign)"), NULL },
     { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
 	N_("delete package signatures"), NULL },
+    { "rpmv3", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR),
+	&sargs.signflags, RPMSIGN_FLAG_RPMV3,
+	N_("create rpm v3 header+payload signatures") },
 #ifdef WITH_IMAEVM
     { "signfiles", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR),
 	&sargs.signflags, RPMSIGN_FLAG_IMA,
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index 6ab8c23fa..0c6646d85 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -377,14 +377,17 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4)
 
     if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
 	goto exit;
-    rpmtdFree(sigtd);
 
-    /* Assume the same signature test holds for v3 signature too */
-    if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL)
-	goto exit;
+    if (sigt_v3) {
+	rpmtdFree(sigtd);
 
-    if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
-	goto exit;
+	/* Assume the same signature test holds for v3 signature too */
+	if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL)
+	    goto exit;
+
+	if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
+	    goto exit;
+    }
 
     rc = 0;
 exit:
@@ -521,6 +524,12 @@ static int rpmSign(const char *rpm, int deleting, int flags)
 	goto exit;
     }
 
+    /* Always add V3 signatures if no payload digest present */
+    if (!(headerIsEntry(h, RPMTAG_PAYLOADDIGEST) ||
+	  headerIsEntry(h, RPMTAG_PAYLOADDIGESTALT))) {
+	flags |= RPMSIGN_FLAG_RPMV3;
+    }
+
     unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES);
     origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
 
@@ -533,6 +542,7 @@ static int rpmSign(const char *rpm, int deleting, int flags)
 	deleteSigs(sigh);
     } else {
 	/* Signature target containing header + payload */
+	int v3 = (flags & RPMSIGN_FLAG_RPMV3);
 	sigt_v3.fd = fd;
 	sigt_v3.start = headerStart;
 	sigt_v3.fileName = rpm;
@@ -542,7 +552,7 @@ static int rpmSign(const char *rpm, int deleting, int flags)
 	sigt_v4 = sigt_v3;
 	sigt_v4.size = headerSizeof(h, HEADER_MAGIC_YES);
 
-	res = replaceSignature(sigh, &sigt_v3, &sigt_v4);
+	res = replaceSignature(sigh, v3 ? &sigt_v3 : NULL, &sigt_v4);
 	if (res != 0) {
 	    if (res == 1) {
 		rpmlog(RPMLOG_WARNING,
diff --git a/sign/rpmsign.h b/sign/rpmsign.h
index 545e80d2d..7a770d879 100644
--- a/sign/rpmsign.h
+++ b/sign/rpmsign.h
@@ -16,6 +16,7 @@ extern "C" {
 enum rpmSignFlags_e {
     RPMSIGN_FLAG_NONE		= 0,
     RPMSIGN_FLAG_IMA		= (1 << 0),
+    RPMSIGN_FLAG_RPMV3		= (1 << 1),
 };
 typedef rpmFlags rpmSignFlags;
 
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
index f6ad72589..c6f95e997 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -423,7 +423,7 @@ AT_CLEANUP
 
 # ------------------------------
 # Test --addsign
-AT_SETUP([rpmsign --addsign <unsigned>])
+AT_SETUP([rpmsign --addsign --rpmv3 <unsigned>])
 AT_KEYWORDS([rpmsign signature])
 AT_CHECK([
 RPMDB_CLEAR
@@ -431,7 +431,7 @@ RPMDB_INIT
 rm -rf "${TOPDIR}"
 
 cp "${RPMTEST}"/data/RPMS/hello-2.0-1.x86_64.rpm "${RPMTEST}"/tmp/
-run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
+run rpmsign --key-id 1964C5FC --rpmv3 --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
 echo PRE-IMPORT
 runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
 echo POST-IMPORT
@@ -456,6 +456,38 @@ POST-DELSIGN
 [])
 AT_CLEANUP
 
+# Test --addsign
+AT_SETUP([rpmsign --addsign <unsigned>])
+AT_KEYWORDS([rpmsign signature])
+AT_CHECK([
+RPMDB_CLEAR
+RPMDB_INIT
+rm -rf "${TOPDIR}"
+
+cp "${RPMTEST}"/data/RPMS/hello-2.0-1.x86_64.rpm "${RPMTEST}"/tmp/
+run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
+echo PRE-IMPORT
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
+echo POST-IMPORT
+runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
+run rpmsign --delsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
+echo POST-DELSIGN
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
+],
+[0],
+[PRE-IMPORT
+/tmp/hello-2.0-1.x86_64.rpm:
+    Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
+POST-IMPORT
+/tmp/hello-2.0-1.x86_64.rpm:
+    Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
+POST-DELSIGN
+/tmp/hello-2.0-1.x86_64.rpm:
+],
+[])
+AT_CLEANUP
+
 # ------------------------------
 # Test --delsign
 AT_SETUP([rpmsign --delsign <package>])
-- 
2.13.5