45afda
From 031b8481a0dfe875e9cf0f5d440b9379a62651a6 Mon Sep 17 00:00:00 2001
45afda
From: Panu Matilainen <pmatilai@redhat.com>
45afda
Date: Mon, 2 Mar 2020 14:47:26 +0200
45afda
Subject: [PATCH 12/33] Stop adding rpm v3 header+payload signatures by default
45afda
 where not needed
45afda
45afda
On packages where a separate payload digest exists (ie those built with
45afda
rpm >= 4.14), rpm v3 header+payload signatures are nothing but expensive
45afda
legacy baggage, as the payload digest will be signed by a header-only
45afda
signature already, without having to recalculate the entire file.
45afda
45afda
Automatically detect the payload digest presence and only add V3
45afda
signatures on packages that need it, but also add an override switch
45afda
to force their addition if needed for compatibility or so. A particular
45afda
use-case would be ability to signature-level verify the entire package
45afda
on rpm older than 4.14.
45afda
45afda
Fixes: #863
45afda
---
45afda
 doc/rpmsign.8      |  9 +++++++++
45afda
 rpmsign.c          |  3 +++
45afda
 sign/rpmgensig.c   | 24 +++++++++++++++++-------
45afda
 sign/rpmsign.h     |  1 +
45afda
 tests/rpmsigdig.at | 36 ++++++++++++++++++++++++++++++++++--
45afda
 5 files changed, 64 insertions(+), 9 deletions(-)
45afda
45afda
diff --git a/doc/rpmsign.8 b/doc/rpmsign.8
45afda
index d895a3b8c..f7ceae89b 100644
45afda
--- a/doc/rpmsign.8
45afda
+++ b/doc/rpmsign.8
45afda
@@ -11,6 +11,7 @@ rpmsign \- RPM Package Signing
45afda
 
45afda
 .SS "rpmsign-options"
45afda
 .PP
45afda
+[\fb--rpmv3\fR]
45afda
 [\fb--fskpath \fIKEY\fb\fR] [\fB--signfiles\fR]
45afda
 
45afda
 .SH DESCRIPTION
45afda
@@ -32,6 +33,14 @@ Delete all signatures from each package \fIPACKAGE_FILE\fR given.
45afda
 .SS "SIGN OPTIONS"
45afda
 .PP
45afda
 .TP
45afda
+\fB--rpmv3\fR
45afda
+Force RPM V3 header+payload signature addition.
45afda
+These are expensive and redundant baggage on packages where a separate
45afda
+payload digest exists (packages built with rpm >= 4.14).  Rpm will
45afda
+automatically detect the need for V3 signatures, but this option can be
45afda
+used to force their creation if the packages must be fully 
45afda
+signature verifiable with rpm < 4.14 or other interoperability reasons.
45afda
+.TP
45afda
 \fB--fskpath \fIKEY\fB\fR
45afda
 Used with \fB--signfiles\fR, use file signing key \fIKey\fR.
45afda
 .TP
45afda
diff --git a/rpmsign.c b/rpmsign.c
45afda
index 57cb36919..a74948ba8 100644
45afda
--- a/rpmsign.c
45afda
+++ b/rpmsign.c
45afda
@@ -32,6 +32,9 @@ static struct poptOption signOptsTable[] = {
45afda
 	N_("sign package(s) (identical to --addsign)"), NULL },
45afda
     { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
45afda
 	N_("delete package signatures"), NULL },
45afda
+    { "rpmv3", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR),
45afda
+	&sargs.signflags, RPMSIGN_FLAG_RPMV3,
45afda
+	N_("create rpm v3 header+payload signatures") },
45afda
 #ifdef WITH_IMAEVM
45afda
     { "signfiles", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR),
45afda
 	&sargs.signflags, RPMSIGN_FLAG_IMA,
45afda
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
45afda
index 1981981f4..4903a4de1 100644
45afda
--- a/sign/rpmgensig.c
45afda
+++ b/sign/rpmgensig.c
45afda
@@ -377,14 +377,17 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4)
45afda
 
45afda
     if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
45afda
 	goto exit;
45afda
-    rpmtdFree(sigtd);
45afda
 
45afda
-    /* Assume the same signature test holds for v3 signature too */
45afda
-    if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL)
45afda
-	goto exit;
45afda
+    if (sigt_v3) {
45afda
+	rpmtdFree(sigtd);
45afda
 
45afda
-    if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
45afda
-	goto exit;
45afda
+	/* Assume the same signature test holds for v3 signature too */
45afda
+	if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL)
45afda
+	    goto exit;
45afda
+
45afda
+	if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
45afda
+	    goto exit;
45afda
+    }
45afda
 
45afda
     rc = 0;
45afda
 exit:
45afda
@@ -528,6 +531,12 @@ static int rpmSign(const char *rpm, int deleting, int flags)
45afda
 	goto exit;
45afda
     }
45afda
 
45afda
+    /* Always add V3 signatures if no payload digest present */
45afda
+    if (!(headerIsEntry(h, RPMTAG_PAYLOADDIGEST) ||
45afda
+	  headerIsEntry(h, RPMTAG_PAYLOADDIGESTALT))) {
45afda
+	flags |= RPMSIGN_FLAG_RPMV3;
45afda
+    }
45afda
+
45afda
     unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES);
45afda
     origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
45afda
 
45afda
@@ -540,6 +549,7 @@ static int rpmSign(const char *rpm, int deleting, int flags)
45afda
 	deleteSigs(sigh);
45afda
     } else {
45afda
 	/* Signature target containing header + payload */
45afda
+	int v3 = (flags & RPMSIGN_FLAG_RPMV3);
45afda
 	sigt_v3.fd = fd;
45afda
 	sigt_v3.start = headerStart;
45afda
 	sigt_v3.fileName = rpm;
45afda
@@ -549,7 +559,7 @@ static int rpmSign(const char *rpm, int deleting, int flags)
45afda
 	sigt_v4 = sigt_v3;
45afda
 	sigt_v4.size = headerSizeof(h, HEADER_MAGIC_YES);
45afda
 
45afda
-	res = replaceSignature(sigh, &sigt_v3, &sigt_v4);
45afda
+	res = replaceSignature(sigh, v3 ? &sigt_v3 : NULL, &sigt_v4);
45afda
 	if (res != 0) {
45afda
 	    if (res == 1) {
45afda
 		rpmlog(RPMLOG_WARNING,
45afda
diff --git a/sign/rpmsign.h b/sign/rpmsign.h
45afda
index 545e80d2d..7a770d879 100644
45afda
--- a/sign/rpmsign.h
45afda
+++ b/sign/rpmsign.h
45afda
@@ -16,6 +16,7 @@ extern "C" {
45afda
 enum rpmSignFlags_e {
45afda
     RPMSIGN_FLAG_NONE		= 0,
45afda
     RPMSIGN_FLAG_IMA		= (1 << 0),
45afda
+    RPMSIGN_FLAG_RPMV3		= (1 << 1),
45afda
 };
45afda
 typedef rpmFlags rpmSignFlags;
45afda
 
45afda
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
45afda
index 880e5edd0..12e2221b3 100644
45afda
--- a/tests/rpmsigdig.at
45afda
+++ b/tests/rpmsigdig.at
45afda
@@ -391,7 +391,7 @@ AT_CLEANUP
45afda
 
45afda
 # ------------------------------
45afda
 # Test --addsign
45afda
-AT_SETUP([rpmsign --addsign <unsigned>])
45afda
+AT_SETUP([rpmsign --addsign --rpmv3 <unsigned>])
45afda
 AT_KEYWORDS([rpmsign signature])
45afda
 AT_CHECK([
45afda
 RPMDB_CLEAR
45afda
@@ -399,7 +399,7 @@ RPMDB_INIT
45afda
 rm -rf "${TOPDIR}"
45afda
 
45afda
 cp "${RPMTEST}"/data/RPMS/hello-2.0-1.x86_64.rpm "${RPMTEST}"/tmp/
45afda
-run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
45afda
+run rpmsign --key-id 1964C5FC --rpmv3 --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
45afda
 echo PRE-IMPORT
45afda
 runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
45afda
 echo POST-IMPORT
45afda
@@ -424,6 +424,38 @@ POST-DELSIGN
45afda
 [])
45afda
 AT_CLEANUP
45afda
 
45afda
+# Test --addsign
45afda
+AT_SETUP([rpmsign --addsign <unsigned>])
45afda
+AT_KEYWORDS([rpmsign signature])
45afda
+AT_CHECK([
45afda
+RPMDB_CLEAR
45afda
+RPMDB_INIT
45afda
+rm -rf "${TOPDIR}"
45afda
+
45afda
+cp "${RPMTEST}"/data/RPMS/hello-2.0-1.x86_64.rpm "${RPMTEST}"/tmp/
45afda
+run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
45afda
+echo PRE-IMPORT
45afda
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
45afda
+echo POST-IMPORT
45afda
+runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
45afda
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
45afda
+run rpmsign --delsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64.rpm > /dev/null
45afda
+echo POST-DELSIGN
45afda
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
45afda
+],
45afda
+[0],
45afda
+[PRE-IMPORT
45afda
+/tmp/hello-2.0-1.x86_64.rpm:
45afda
+    Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
45afda
+POST-IMPORT
45afda
+/tmp/hello-2.0-1.x86_64.rpm:
45afda
+    Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
45afda
+POST-DELSIGN
45afda
+/tmp/hello-2.0-1.x86_64.rpm:
45afda
+],
45afda
+[])
45afda
+AT_CLEANUP
45afda
+
45afda
 # ------------------------------
45afda
 # Test --delsign
45afda
 AT_SETUP([rpmsign --delsign <package>])
45afda
-- 
45afda
2.27.0
45afda