dcavalca / rpms / rpm

Forked from rpms/rpm a year ago
Clone
Blob Blame History Raw
From 031b8481a0dfe875e9cf0f5d440b9379a62651a6 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 2 Mar 2020 14:47:26 +0200
Subject: [PATCH 12/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 1981981f4..4903a4de1 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:
@@ -528,6 +531,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);
 
@@ -540,6 +549,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;
@@ -549,7 +559,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 880e5edd0..12e2221b3 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -391,7 +391,7 @@ AT_CLEANUP
 
 # ------------------------------
 # Test --addsign
-AT_SETUP([rpmsign --addsign <unsigned>])
+AT_SETUP([rpmsign --addsign --rpmv3 <unsigned>])
 AT_KEYWORDS([rpmsign signature])
 AT_CHECK([
 RPMDB_CLEAR
@@ -399,7 +399,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
@@ -424,6 +424,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.27.0