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
This commit is contained in:
Panu Matilainen 2020-03-02 14:47:26 +02:00
parent 91834e86e0
commit b1aeafef49
5 changed files with 64 additions and 9 deletions

View File

@ -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

View File

@ -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,

View File

@ -437,14 +437,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:
@ -575,6 +578,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);
@ -587,6 +596,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;
@ -596,7 +606,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,

View File

@ -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;

View File

@ -436,6 +436,40 @@ runroot rpmkeys -Kv /tmp/${pkg}
AT_CLEANUP
# ------------------------------
# Test --addsign
AT_SETUP([rpmsign --addsign --rpmv3 <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 --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
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
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
V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
POST-DELSIGN
/tmp/hello-2.0-1.x86_64.rpm:
],
[])
AT_CLEANUP
# Test --addsign
AT_SETUP([rpmsign --addsign <unsigned>])
AT_KEYWORDS([rpmsign signature])
@ -459,11 +493,9 @@ runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm|grep -v digest
[PRE-IMPORT
/tmp/hello-2.0-1.x86_64.rpm:
Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
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
V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
POST-DELSIGN
/tmp/hello-2.0-1.x86_64.rpm:
],