From fd3a7cec0b9278ffd513bb7af966509f5c26ed94 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Wed, 6 Nov 2024 09:44:34 +0200 Subject: [PATCH 1/6] Drop unused header arguments, update comments in signing internals The function comments are several generations old plain wrong. No functional changes. --- sign/rpmgensig.cc | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/sign/rpmgensig.cc b/sign/rpmgensig.cc index 469fe71b05..de6caa759f 100644 --- a/sign/rpmgensig.cc +++ b/sign/rpmgensig.cc @@ -129,13 +129,8 @@ static int copyFile(FD_t *sfdp, const char *sfnp, return rc; } -/* - * Validate generated signature and insert to header if it looks sane. - * RPM doesn't support everything GPG does. Basic tests to see if the - * generated signature is something we can use. - * Return generated signature tag data on success, NULL on failure. - */ -static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen) +/* Wrap a raw signature in an rpmtd and sanity check, return NULL on fail */ +static rpmtd makeSigTag(int ishdr, uint8_t *pkt, size_t pktlen) { pgpDigParams sigp = NULL; rpmTagVal sigtag; @@ -319,15 +314,8 @@ static int runGPG(sigTarget sigt, const char *sigfile) return rc; } -/** - * Generate GPG signature(s) for a header+payload file. - * @param sigh signature header - * @param ishdr header-only signature? - * @param sigt signature target - * @param passPhrase private key pass phrase - * @return generated sigtag on success, 0 on failure - */ -static rpmtd makeGPGSignature(Header sigh, int ishdr, sigTarget sigt) +/* Generate an OpenPGP signature(s) for a target */ +static rpmtd makeGPGSignature(int ishdr, sigTarget sigt) { char * sigfile = rstrscat(NULL, sigt->fileName, ".sig", NULL); struct stat st; @@ -366,7 +354,7 @@ static rpmtd makeGPGSignature(Header sigh, int ishdr, sigTarget sigt) rpmlog(RPMLOG_DEBUG, "Got %zd bytes of OpenPGP sig\n", pktlen); /* Parse the signature, change signature tag as appropriate. */ - sigtd = makeSigTag(sigh, ishdr, pkt, pktlen); + sigtd = makeSigTag(ishdr, pkt, pktlen); exit: (void) unlink(sigfile); free(sigfile); @@ -421,7 +409,7 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4) rpmtd sigtd = NULL; /* Make the cheaper v4 signature first */ - if ((sigtd = makeGPGSignature(sigh, 1, sigt_v4)) == NULL) + if ((sigtd = makeGPGSignature(1, sigt_v4)) == NULL) goto exit; /* See if we already have a signature by the same key and parameters */ @@ -439,7 +427,7 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4) rpmtdFree(sigtd); /* Assume the same signature test holds for v3 signature too */ - if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL) + if ((sigtd = makeGPGSignature(0, sigt_v3)) == NULL) goto exit; if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0) From 05b3bd0beee83e24eeb2854cd4852f8e2941b31b Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Wed, 6 Nov 2024 10:18:34 +0200 Subject: [PATCH 2/6] Refactor signature insertion to a helper function No functional changes, just a tiny refactoring bit for the next steps. --- sign/rpmgensig.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sign/rpmgensig.cc b/sign/rpmgensig.cc index de6caa759f..6bed916ef1 100644 --- a/sign/rpmgensig.cc +++ b/sign/rpmgensig.cc @@ -403,6 +403,11 @@ static int haveSignature(rpmtd sigtd, Header h) return rc; } +static int putSignature(Header sigh, rpmtd sigtd) +{ + return (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0); +} + static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4) { int rc = -1; @@ -420,7 +425,7 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4) /* Nuke all signature tags */ deleteSigs(sigh); - if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0) + if (putSignature(sigh, sigtd)) goto exit; if (sigt_v3) { @@ -430,7 +435,7 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4) if ((sigtd = makeGPGSignature(0, sigt_v3)) == NULL) goto exit; - if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0) + if (putSignature(sigh, sigtd)) goto exit; } From 5cc1cfdaa61fb306bba8832bc0f9471cf2ee28c9 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Wed, 6 Nov 2024 10:30:15 +0200 Subject: [PATCH 3/6] Simplify the v3 signature logic a bit Pass the flags down to the function that needs to do stuff. No functional changes. --- sign/rpmgensig.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sign/rpmgensig.cc b/sign/rpmgensig.cc index 6bed916ef1..90df052afd 100644 --- a/sign/rpmgensig.cc +++ b/sign/rpmgensig.cc @@ -408,7 +408,8 @@ static int putSignature(Header sigh, rpmtd sigtd) return (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0); } -static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4) +static int replaceSignature(Header sigh, rpmSignFlags flags, + sigTarget sigt_v3, sigTarget sigt_v4) { int rc = -1; rpmtd sigtd = NULL; @@ -428,7 +429,7 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4) if (putSignature(sigh, sigtd)) goto exit; - if (sigt_v3) { + if (flags & RPMSIGN_FLAG_RPMV3) { rpmtdFree(sigtd); /* Assume the same signature test holds for v3 signature too */ @@ -647,7 +648,6 @@ 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; @@ -657,7 +657,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, v3 ? &sigt_v3 : NULL, &sigt_v4); + res = replaceSignature(sigh, flags, &sigt_v3, &sigt_v4); if (res != 0) { if (res == 1) { rpmlog(RPMLOG_WARNING, From 2ff3b1f50a6cdc279edcf4eb8c66b9df976ad028 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Mon, 11 Nov 2024 12:11:13 +0200 Subject: [PATCH 4/6] Avoid trailing whitespace when outputing relocations in --info query --- rpmpopt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpmpopt.in b/rpmpopt.in index 0df8adacdd..40a173324f 100644 --- a/rpmpopt.in +++ b/rpmpopt.in @@ -100,7 +100,7 @@ Signature : %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig Source RPM : %{SOURCERPM}\n\ Build Date : %{BUILDTIME:date}\n\ Build Host : %{BUILDHOST}\n\ -%|PREFIXES?{Relocations : [%{PREFIXES} ]\n}|\ +%|PREFIXES?{Relocations :[ %{PREFIXES}]\n}|\ %|PACKAGER?{Packager : %{PACKAGER}\n}|\ %|VENDOR?{Vendor : %{VENDOR}\n}|\ %|VCS?{VCS : %{VCS}\n}|\ From ebd388477c419a38c05079295bf15bd68bcecdf3 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Wed, 30 Oct 2024 16:46:26 +0200 Subject: [PATCH 5/6] Add support for multiple OpenPGP signatures per package, part 1/2 Add support for multiple OpenPGP header signatures per package, base64 encoded in a string array, also known as rpm v6 signatures. --addsign no longer deletes any signatures, it only creates and adds a new signature if possible. --delete and --resign behave as before: they delete ALL signatures on the package, and the latter then creates and adds a new one. For v6 packages this is the default signature type, but if requested, one v4 compat signature can be created for compatible algorithms. v6 signatures on v4 packages are also supported, but have to be explicitly requested. In that case, v3/v4 signatures are only added if none already exist and a v4 compatible algorithm is used. v3 signatures on v6 packages are not supported (out of principle, not a technical limitation) On verification, if RPMTAG_OPENPGP exists then other signature tags are ignored because they're expected to only contain compat copies of the same content. As of now, all existing signatures must validate for signature checking of a package to pass, further policies are to be added later. Fixes: #3385 --- docs/man/rpmsign.8.md | 48 ++++++++-- docs/manual/tags.md | 2 + include/rpm/rpmsign.h | 3 + include/rpm/rpmtag.h | 2 + include/rpm/rpmts.h | 3 + lib/package.cc | 1 + lib/rpmvs.cc | 46 ++++++++-- sign/rpmgensig.cc | 131 +++++++++++++++++++++------- tests/rpmgeneral.at | 1 + tests/rpmsigdig.at | 198 +++++++++++++++++++++++++++++++++++++++++- tests/rpmvfylevel.at | 1 + tools/rpmsign.cc | 12 ++- 12 files changed, 397 insertions(+), 51 deletions(-) diff --git a/docs/man/rpmsign.8.md b/docs/man/rpmsign.8.md index adff642b3f..aa8c306007 100644 --- a/docs/man/rpmsign.8.md +++ b/docs/man/rpmsign.8.md @@ -25,22 +25,25 @@ SIGNING PACKAGES: rpmsign-options --------------- -\[**\--rpmv3**\] \[**\--fskpath ***KEY*\] \[**\--signfiles**\] +\[**\--rpmv3**\] \[**\--rpmv4**\] \[**\--fskpath ***KEY*\] \[**\--signfiles**\] DESCRIPTION =========== -Both of the **\--addsign** and **\--resign** options generate and insert -new signatures for each package *PACKAGE\_FILE* given, replacing any -existing signatures. There are two options for historical reasons, there -is no difference in behavior currently. +**rpmsign** **\--addsign** generates and inserts a new OpenPGP signature +for each *PACKAGE\_FILE* given unless a signature with identical +parameters already exists, in which case no action is taken. +Arbitrary number of V6 signatures can be added. + +**rpmsign** **\--resign** generates and inserts a new OpenPGP signature +for each *PACKAGE\_FILE*, replacing any and all previous signatures. To create a signature rpmsign needs to verify the package\'s checksum. As a -result packages with a MD5/SHA1 checksums cannot be signed in FIPS mode. +result V4 packages with MD5/SHA1 checksums cannot be signed in FIPS mode. **rpmsign** **\--delsign** *PACKAGE\_FILE \...* -Delete all signatures from each package *PACKAGE\_FILE* given. +Delete all OpenPGP signatures from each package *PACKAGE\_FILE* given. **rpmsign** **\--delfilesign** *PACKAGE\_FILE \...* @@ -52,13 +55,40 @@ SIGN OPTIONS **\--rpmv3** -: Force RPM V3 header+payload signature addition. These are expensive +: Request RPM V3 header+payload signature addition on V4 packages. + These signatures are expensive and redundant baggage on packages where a separate payload digest exists (packages built with rpm \>= 4.14). Rpmsign 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 + request their creation if the packages must be fully signature verifiable with rpm \< 4.14 or other interoperability reasons. + Has no effect when signing V6 packages. + +**\--rpmv4** + +: Request RPM V4 header signature addition on V6 packages. + Useful for making V6 packages signature verifiable + with rpm 4.x versions. + + V4 compatibility signatures are only ever added if the signing algorithm + is one of those known to V4: RSA, EcDSA, EdDSA (and original DSA). + Only one V4 signature can be present in a package, so this is + added only on the first **\--addsign** with a V4 compatible + algorithm, and ignored otherwise. + + Has no effect when signing V4 packages. + +**\--rpmv6** + +: Request RPM V6 header signature addition on V4 packages. + + This generally always succeeds as there can be arbitrary number of + V6 signatures on a package. A V3/V4 compatibility signatures are + added usign the same logic as **\--rpmv4** on a V6 package. + + Has no effect when signing V6 packages. + **\--fskpath ***KEY* : Used with **\--signfiles**, use file signing key *Key*. diff --git a/docs/manual/tags.md b/docs/manual/tags.md index 334e90fbbb..4880cfda41 100644 --- a/docs/manual/tags.md +++ b/docs/manual/tags.md @@ -306,6 +306,7 @@ Tag Name | Value| Type | Description ------------------|------|--------------|------------ Dsaheader | 267 | bin | OpenPGP DSA signature of the header (if thus signed) Longsigsize | 270 | int64 | Header+payload size if > 4GB. +Openpgp | 278 | string array | OpenPGP signature(s) of the header, base64 encoded Payloaddigest | 5092 | string array | Cryptographic digest of the compressed payload. Payloaddigestalgo | 5093 | int32 | ID of the payload digest algorithm. Payloaddigestalt | 5097 | string array | Cryptographic digest of the uncompressed payload. @@ -446,6 +447,7 @@ Longsigsize | Header+payload size in 64bit format Tag Name | Value| Type | Description ----------------------|------|--------------|------------ +Openpgp | 278 | string array | All OpenPGP signature(s) in the header, including legacy ones (base64 encoded) Origfilenames | 5007 | string array | Original Filenames in relocated packages. Providenevrs | 5042 | string array | Formatted `name [op version]` provide dependency strings. Conflictnevrs | 5044 | string array | Formatted `name [op version]` conflict dependency strings. diff --git a/include/rpm/rpmsign.h b/include/rpm/rpmsign.h index c876ef1bda..c0dbdab533 100644 --- a/include/rpm/rpmsign.h +++ b/include/rpm/rpmsign.h @@ -18,6 +18,9 @@ enum rpmSignFlags_e { RPMSIGN_FLAG_IMA = (1 << 0), RPMSIGN_FLAG_RPMV3 = (1 << 1), RPMSIGN_FLAG_FSVERITY = (1 << 2), + RPMSIGN_FLAG_RESIGN = (1 << 3), + RPMSIGN_FLAG_RPMV4 = (1 << 4), + RPMSIGN_FLAG_RPMV6 = (1 << 5), }; typedef rpmFlags rpmSignFlags; diff --git a/include/rpm/rpmtag.h b/include/rpm/rpmtag.h index 3a60516a30..c716bd3f43 100644 --- a/include/rpm/rpmtag.h +++ b/include/rpm/rpmtag.h @@ -68,6 +68,7 @@ typedef enum rpmTag_e { /* RPMTAG_SIG_BASE+19 reserved for RPMSIGTAG_FILESIGNATURELENGTH */ RPMTAG_VERITYSIGNATURES = RPMTAG_SIG_BASE+20, /* s[] */ RPMTAG_VERITYSIGNATUREALGO = RPMTAG_SIG_BASE+21, /* i */ + RPMTAG_OPENPGP = RPMTAG_SIG_BASE+22, /* s[] */ RPMTAG_SIG_TOP = HEADER_SIGTOP, RPMTAG_NAME = 1000, /* s */ @@ -455,6 +456,7 @@ typedef enum rpmSigTag_e { RPMSIGTAG_FILESIGNATURELENGTH = RPMTAG_SIG_BASE + 19, RPMSIGTAG_VERITYSIGNATURES = RPMTAG_VERITYSIGNATURES, RPMSIGTAG_VERITYSIGNATUREALGO = RPMTAG_VERITYSIGNATUREALGO, + RPMSIGTAG_OPENPGP = RPMTAG_OPENPGP, RPMSIGTAG_RESERVED = RPMTAG_SIG_TOP, } rpmSigTag; diff --git a/include/rpm/rpmts.h b/include/rpm/rpmts.h index dc5b31c55c..86ca62e0ef 100644 --- a/include/rpm/rpmts.h +++ b/include/rpm/rpmts.h @@ -106,6 +106,7 @@ enum rpmVSFlags_e { RPMVSF_NOSHA256HEADER = (1 << 9), RPMVSF_NODSAHEADER = (1 << 10), RPMVSF_NORSAHEADER = (1 << 11), + RPMVSF_NOOPENPGP = (1 << 12), /* bit(s) 12-15 unused */ RPMVSF_NOPAYLOAD = (1 << 16), RPMVSF_NOMD5 = (1 << 17), @@ -126,6 +127,7 @@ typedef rpmFlags rpmVSFlags; #define RPMVSF_MASK_NOSIGNATURES \ ( RPMVSF_NODSAHEADER | \ RPMVSF_NORSAHEADER | \ + RPMVSF_NOOPENPGP | \ RPMVSF_NODSA | \ RPMVSF_NORSA ) #define _RPMVSF_NOSIGNATURES RPMVSF_MASK_NOSIGNATURES @@ -133,6 +135,7 @@ typedef rpmFlags rpmVSFlags; #define RPMVSF_MASK_NOHEADER \ ( RPMVSF_NOSHA1HEADER | \ RPMVSF_NOSHA256HEADER | \ + RPMVSF_NOOPENPGP | \ RPMVSF_NODSAHEADER | \ RPMVSF_NORSAHEADER ) #define _RPMVSF_NOHEADER RPMVSF_MASK_NOHEADER diff --git a/lib/package.cc b/lib/package.cc index 83de81a93c..b16c52460f 100644 --- a/lib/package.cc +++ b/lib/package.cc @@ -58,6 +58,7 @@ static struct taglate_s { { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0, 0 }, { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1, 0 }, { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1, 0 }, + { RPMSIGTAG_OPENPGP, RPMTAG_OPENPGP, 0, 0 }, { 0 } }; diff --git a/lib/rpmvs.cc b/lib/rpmvs.cc index 53837720c4..e4909f0213 100644 --- a/lib/rpmvs.cc +++ b/lib/rpmvs.cc @@ -1,5 +1,6 @@ #include "system.h" +#include #include #include #include @@ -26,6 +27,7 @@ struct vfytag_s { }; static const struct vfytag_s rpmvfytags[] = { + { RPMTAG_OPENPGP, RPM_STRING_ARRAY_TYPE, 0, 0, }, { RPMSIGTAG_SIZE, RPM_BIN_TYPE, 0, 0, }, { RPMSIGTAG_PGP, RPM_BIN_TYPE, 0, 0, }, { RPMSIGTAG_MD5, RPM_BIN_TYPE, 0, 16, }, @@ -50,6 +52,9 @@ struct vfyinfo_s { }; static const struct vfyinfo_s rpmvfyitems[] = { + { RPMTAG_OPENPGP, 1, + { RPMSIG_SIGNATURE_TYPE, RPMVSF_NOOPENPGP, + (RPMSIG_HEADER), 0, 0, }, }, { RPMSIGTAG_SIZE, 1, { RPMSIG_OTHER_TYPE, 0, (RPMSIG_HEADER|RPMSIG_PAYLOAD), 0, 0, }, }, @@ -131,7 +136,7 @@ int rpmIsValidHex(const char *str, size_t slen) return valid; } -static void rpmsinfoInit(const struct vfyinfo_s *vinfo, +static rpmRC rpmsinfoInit(const struct vfyinfo_s *vinfo, const struct vfytag_s *tinfo, rpmtd td, const char *origin, struct rpmsinfo_s *sinfo) @@ -139,6 +144,8 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo, rpmRC rc = RPMRC_FAIL; const void *data = NULL; rpm_count_t dlen = 0; + uint8_t *pkt = NULL; + size_t pktlen = 0; *sinfo = vinfo->vi; /* struct assignment */ sinfo->wrapped = (vinfo->sigh == 0); @@ -193,6 +200,16 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo, } if (sinfo->type == RPMSIG_SIGNATURE_TYPE) { + if (td->type == RPM_STRING_ARRAY_TYPE) { + if (rpmBase64Decode((const char *)data, (void **)&pkt, &pktlen)) { + rasprintf(&sinfo->msg, _("%s tag %u: invalid base64"), + origin, td->tag); + goto exit; + } + data = pkt; + dlen = pktlen; + } + char *lints = NULL; int ec = pgpPrtParams2((const uint8_t *)data, dlen, PGPTAG_SIGNATURE, &sinfo->sig, &lints); @@ -234,8 +251,10 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo, rc = RPMRC_OK; exit: + if (pkt && pkt != td->data) + free(pkt); sinfo->rc = rc; - return; + return rc; } static void rpmsinfoFini(struct rpmsinfo_s *sinfo) @@ -291,11 +310,16 @@ const char *rpmsinfoDescr(struct rpmsinfo_s *sinfo) rangeName(sinfo->range), t); free(t); } else { - rasprintf(&sinfo->descr, _("%s OpenPGP %s%s %s"), - rangeName(sinfo->range), - pgpValString(PGPVAL_PUBKEYALGO, sinfo->sigalgo), - sinfo->alt ? " ALT" : "", - _("signature")); + if (sinfo->sigalgo) { + rasprintf(&sinfo->descr, _("%s OpenPGP %s %s"), + rangeName(sinfo->range), + pgpValString(PGPVAL_PUBKEYALGO, sinfo->sigalgo), + _("signature")); + } else { + rasprintf(&sinfo->descr, _("%s OpenPGP %s"), + rangeName(sinfo->range), + _("signature")); + } } break; } @@ -348,7 +372,13 @@ static void rpmvsAppend(struct rpmvs_s *sis, hdrblob blob, if (!rpmsinfoDisabled(&vi->vi, sis->vsflags) && rc == RPMRC_OK) { while (rpmtdNext(&td) >= 0) { - rpmsinfoInit(vi, ti, &td, o, &sis->sigs[sis->nsigs]); + if (!rpmsinfoInit(vi, ti, &td, o, &sis->sigs[sis->nsigs])) { + /* Don't bother with v3/v4 sigs when v6 sigs exist */ + if (td.tag == RPMSIGTAG_OPENPGP) { + sis->vsflags |= (RPMVSF_NODSAHEADER|RPMVSF_NORSAHEADER); + sis->vsflags |= (RPMVSF_NODSA|RPMVSF_NORSA); + } + } sis->nsigs++; } } else { diff --git a/sign/rpmgensig.cc b/sign/rpmgensig.cc index 90df052afd..85a515e3bd 100644 --- a/sign/rpmgensig.cc +++ b/sign/rpmgensig.cc @@ -17,6 +17,7 @@ #include "rpmsignfiles.hh" #endif +#include #include /* RPMSIGTAG & related */ #include #include @@ -175,11 +176,12 @@ static rpmtd makeSigTag(int ishdr, uint8_t *pkt, size_t pktlen) /* Looks sane, create the tag data */ sigtd = rpmtdNew(); + sigtd->tag = sigtag; + sigtd->flags |= RPMTD_ALLOCED; sigtd->count = pktlen; sigtd->data = memcpy(xmalloc(pktlen), pkt, pktlen);; - sigtd->type = RPM_BIN_TYPE; sigtd->tag = sigtag; - sigtd->flags |= RPMTD_ALLOCED; + sigtd->type = RPM_BIN_TYPE; exit: pgpDigParamsFree(sigp); @@ -370,6 +372,7 @@ static void deleteSigs(Header sigh) headerDel(sigh, RPMSIGTAG_DSA); headerDel(sigh, RPMSIGTAG_RSA); headerDel(sigh, RPMSIGTAG_PGP5); + headerDel(sigh, RPMSIGTAG_OPENPGP); } static void deleteFileSigs(Header sigh) @@ -380,41 +383,83 @@ static void deleteFileSigs(Header sigh) headerDel(sigh, RPMSIGTAG_VERITYSIGNATUREALGO); } -static int haveSignature(rpmtd sigtd, Header h) +static pgpDigParams tdParams(rpmtd td) +{ + pgpDigParams sig = NULL; + if (td->tag == RPMTAG_OPENPGP) { + uint8_t *pkt = NULL; + size_t pktlen = 0; + if (rpmBase64Decode(rpmtdGetString(td), (void **)&pkt, &pktlen) == 0) { + pgpPrtParams(pkt, pktlen, PGPTAG_SIGNATURE, &sig); + free(pkt); + } + } else { + pgpPrtParams((uint8_t *)td->data, td->count, PGPTAG_SIGNATURE, &sig); + } + return sig; +} + +static int haveSignature(rpmtd sigtd, Header sigh) { - pgpDigParams sig1 = NULL; - pgpDigParams sig2 = NULL; struct rpmtd_s oldtd; int rc = 0; /* assume no */ + rpmTagVal tag = headerIsEntry(sigh, RPMSIGTAG_RESERVED) ? + RPMTAG_OPENPGP : sigtd->tag; - if (!headerGet(h, rpmtdTag(sigtd), &oldtd, HEADERGET_DEFAULT)) + if (!headerGet(sigh, tag, &oldtd, HEADERGET_DEFAULT)) return rc; - pgpPrtParams((uint8_t *)sigtd->data, sigtd->count, PGPTAG_SIGNATURE, &sig1); + pgpDigParams newsig = tdParams(sigtd); while (rpmtdNext(&oldtd) >= 0 && rc == 0) { - pgpPrtParams((uint8_t *)oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2); - if (pgpDigParamsCmp(sig1, sig2) == 0) + pgpDigParams oldsig = tdParams(&oldtd); + if (pgpDigParamsCmp(newsig, oldsig) == 0) rc = 1; - sig2 = pgpDigParamsFree(sig2); + pgpDigParamsFree(oldsig); } - pgpDigParamsFree(sig1); + pgpDigParamsFree(newsig); rpmtdFreeData(&oldtd); return rc; } -static int putSignature(Header sigh, rpmtd sigtd) +static int putSignature(Header sigh, rpmtd sigtd, int multisig) +{ + int rc = 1; + if (multisig) { + char *b64 = rpmBase64Encode(sigtd->data, sigtd->count, 0); + char **arr = (char **)xmalloc(1 * sizeof(*arr)); + arr[0] = b64; + + rpmtd_s mtd = { + .tag = RPMSIGTAG_OPENPGP, + .type = RPM_STRING_ARRAY_TYPE, + .count = 1, + .data = arr, + .flags = RPMTD_ALLOCED|RPMTD_PTR_ALLOCED, + .ix = -1, + .size = 0, + }; + rc = (headerPut(sigh, &mtd, HEADERPUT_APPEND) == 0); + rpmtdFreeData(&mtd); + } else { + rc = (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0); + } + return rc; +} + +static int haveLegacySig(Header sigh) { - return (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0); + return headerIsEntry(sigh, RPMSIGTAG_RSA) || + headerIsEntry(sigh, RPMSIGTAG_DSA); } -static int replaceSignature(Header sigh, rpmSignFlags flags, +static int addSignature(Header sigh, rpmSignFlags flags, sigTarget sigt_v3, sigTarget sigt_v4) { int rc = -1; rpmtd sigtd = NULL; - /* Make the cheaper v4 signature first */ + /* Make a header signature */ if ((sigtd = makeGPGSignature(1, sigt_v4)) == NULL) goto exit; @@ -423,23 +468,31 @@ static int replaceSignature(Header sigh, rpmSignFlags flags, rc = 1; goto exit; } - /* Nuke all signature tags */ - deleteSigs(sigh); - if (putSignature(sigh, sigtd)) - goto exit; - - if (flags & RPMSIGN_FLAG_RPMV3) { - rpmtdFree(sigtd); - - /* Assume the same signature test holds for v3 signature too */ - if ((sigtd = makeGPGSignature(0, sigt_v3)) == NULL) + /* Add a v6 signature if requested */ + if (flags & RPMSIGN_FLAG_RPMV6) + if (putSignature(sigh, sigtd, 1)) goto exit; - if (putSignature(sigh, sigtd)) + /* Add a v4 signature if requested */ + if (flags & RPMSIGN_FLAG_RPMV4) { + if (putSignature(sigh, sigtd, 0)) goto exit; + + /* Only consider v3 signature if also adding v4 */ + if (flags & RPMSIGN_FLAG_RPMV3) { + rpmtdFree(sigtd); + + /* Assume the same signature test holds for v3 signature too */ + if ((sigtd = makeGPGSignature(0, sigt_v3)) == NULL) + goto exit; + + if (putSignature(sigh, sigtd, 0)) + goto exit; + } } + rc = 0; exit: rpmtdFree(sigtd); @@ -629,6 +682,23 @@ static int rpmSign(const char *rpm, int deleting, int flags) flags |= RPMSIGN_FLAG_RPMV3; } + /* Only v6 packages have this */ + if (headerIsEntry(sigh, RPMSIGTAG_RESERVED)) { + flags |= RPMSIGN_FLAG_RPMV6; + reserveTag = RPMSIGTAG_RESERVED; + /* v3 signatures are not welcome in v6 packages */ + if (flags & RPMSIGN_FLAG_RPMV3) { + rpmlog(RPMLOG_WARNING, + _("not generating v3 signature for v6 package: %s\n"), rpm); + flags &= ~RPMSIGN_FLAG_RPMV3; + } + } else { + flags |= RPMSIGN_FLAG_RPMV4; + /* Ensure only one legacy signature is added if adding v6 signatures */ + if ((flags & RPMSIGN_FLAG_RPMV6) && haveLegacySig(sigh)) + flags &= ~(RPMSIGN_FLAG_RPMV4|RPMSIGN_FLAG_RPMV3); + } + unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES); origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES); @@ -657,7 +727,10 @@ 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, flags, &sigt_v3, &sigt_v4); + if (flags & RPMSIGN_FLAG_RESIGN) + deleteSigs(sigh); + + res = addSignature(sigh, flags, &sigt_v3, &sigt_v4); if (res != 0) { if (res == 1) { rpmlog(RPMLOG_WARNING, @@ -671,10 +744,6 @@ static int rpmSign(const char *rpm, int deleting, int flags) res = -1; } - /* Only v6 packages have this */ - if (headerIsEntry(h, RPMSIGTAG_RESERVED)) - reserveTag = RPMSIGTAG_RESERVED; - /* Adjust reserved size for added/removed signatures */ if (headerGet(sigh, reserveTag, &utd, HEADERGET_MINMEM)) { int diff = headerSizeof(sigh, HEADER_MAGIC_YES) - origSigSize; diff --git a/tests/rpmgeneral.at b/tests/rpmgeneral.at index b31e322cd3..2c7f2c217b 100644 --- a/tests/rpmgeneral.at +++ b/tests/rpmgeneral.at @@ -191,6 +191,7 @@ OLDSUGGESTS OLDSUGGESTSFLAGS OLDSUGGESTSNAME OLDSUGGESTSVERSION +OPENPGP OPTFLAGS ORDERFLAGS ORDERNAME diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at index 7ce324af5a..7e3df2795d 100644 --- a/tests/rpmsigdig.at +++ b/tests/rpmsigdig.at @@ -641,6 +641,7 @@ runroot rpmkeys --define '_pkgverify_level all' -Kv --nosignature /data/RPMS/hel [[Checking package before importing key: /data/RPMS/hello-2.0-1.x86_64-signed-with-subkey.rpm: Header OpenPGP V4 RSA/SHA512 signature, key ID 1f71177215217ee0: NOKEY + Header OpenPGP signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Header SHA256 digest: OK Payload SHA256 digest: OK @@ -699,6 +700,7 @@ runroot rpmkeys --define '_pkgverify_level all' -Kv --nosignature /data/RPMS/hel [Checking package before importing key: /data/RPMS/hello-2.0-1.x86_64-signed-with-subkey.rpm: Header OpenPGP V4 RSA/SHA512 signature, key ID 1f71177215217ee0: NOKEY + Header OpenPGP signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Header SHA256 digest: OK Payload SHA256 digest: OK @@ -717,6 +719,7 @@ RPMOUTPUT_SEQUOIA([ Key 1F71177215217EE0 invalid: key is not alive])dnl RPMOUTPUT_SEQUOIA([ because: The subkey is not live])dnl RPMOUTPUT_SEQUOIA([ because: Expired on 2022-04-12T00:00:15Z])dnl Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: b6542f92f30650c36b6f41bcb3a771bfeb04e625: NOTTRUSTED + Header OpenPGP signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Header SHA256 digest: OK Payload SHA256 digest: OK @@ -731,6 +734,7 @@ RPMOUTPUT_SEQUOIA([ Key 1F71177215217EE0 invalid: key is not alive])dnl RPMOUTPUT_SEQUOIA([ because: The subkey is not live])dnl RPMOUTPUT_SEQUOIA([ because: Expired on 2022-04-12T00:00:15Z])dnl Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: b6542f92f30650c36b6f41bcb3a771bfeb04e625: NOTTRUSTED + Header OpenPGP signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Legacy OpenPGP RSA signature: NOTFOUND Legacy OpenPGP DSA signature: NOTFOUND @@ -769,6 +773,7 @@ runroot rpmkeys --define '_pkgverify_level all' -Kv --nosignature /data/RPMS/hel [Checking package before importing key: /data/RPMS/hello-2.0-1.x86_64-signed-with-subkey.rpm: Header OpenPGP V4 RSA/SHA512 signature, key ID 1f71177215217ee0: NOKEY + Header OpenPGP signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Header SHA256 digest: OK Payload SHA256 digest: OK @@ -785,6 +790,7 @@ RPMOUTPUT_LEGACY([error: Subkey 1f71177215217ee0 of key b3a771bfeb04e625 (Alice RPMOUTPUT_SEQUOIA([error: Verifying a signature using certificate B6542F92F30650C36B6F41BCB3A771BFEB04E625 (Alice ):])dnl RPMOUTPUT_SEQUOIA([ Key 1F71177215217EE0 is invalid: key is revoked])dnl Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: b6542f92f30650c36b6f41bcb3a771bfeb04e625: NOTTRUSTED + Header OpenPGP signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Header SHA256 digest: OK Payload SHA256 digest: OK @@ -797,6 +803,7 @@ RPMOUTPUT_LEGACY([error: Subkey 1f71177215217ee0 of key b3a771bfeb04e625 (Alice RPMOUTPUT_SEQUOIA([error: Verifying a signature using certificate B6542F92F30650C36B6F41BCB3A771BFEB04E625 (Alice ):])dnl RPMOUTPUT_SEQUOIA([ Key 1F71177215217EE0 is invalid: key is revoked])dnl Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: b6542f92f30650c36b6f41bcb3a771bfeb04e625: NOTTRUSTED + Header OpenPGP signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Legacy OpenPGP RSA signature: NOTFOUND Legacy OpenPGP DSA signature: NOTFOUND @@ -1387,7 +1394,7 @@ AT_SKIP_IF([test x$PGP = xdummy]) RPMDB_INIT RPMTEST_CHECK([ -cat << EOF > ${HOME}/.rpmmacros +cat << EOF >> ${HOME}/.rpmmacros %_openpgp_sign sq %_openpgp_sign_id 771B18D3D7BAA28734333C424344591E1964C5FC EOF @@ -1441,6 +1448,195 @@ runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm [ignore]) RPMTEST_CLEANUP +AT_SETUP([rpmsign --addsign multisig v4]) +AT_KEYWORDS([rpmsign signature multisig v4]) +AT_SKIP_IF([test x$PGP = xdummy]) +RPMDB_INIT + +RPMTEST_CHECK([ +cat << EOF >> ${HOME}/.rpmmacros +%_openpgp_sign sq +%_openpgp_sign_id 771B18D3D7BAA28734333C424344591E1964C5FC +EOF + +runroot_other sq key import /data/keys/*.secret +runroot rpmkeys --import /data/keys/*.pub +], +[0], +[ignore], +[ignore]) + +RPMTEST_CHECK([ +cp "${RPMTEST}"/data/RPMS/hello-2.0-1.x86_64.rpm "${RPMTEST}"/tmp/ +runroot rpmsign --addsign --rpmv6 /tmp/hello-2.0-1.x86_64.rpm &> /dev/null +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm +], +[0], +[/tmp/hello-2.0-1.x86_64.rpm: + Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK + Header SHA256 digest: OK + Payload SHA256 digest: OK +], +[]) + +RPMTEST_CHECK([ +# resigning with identical key shouldn't add anything +runroot rpmsign --addsign --rpmv6 /tmp/hello-2.0-1.x86_64.rpm &> /dev/null +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm +], +[0], +[/tmp/hello-2.0-1.x86_64.rpm: + Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK + Header SHA256 digest: OK + Payload SHA256 digest: OK +], +[]) + +RPMTEST_CHECK([ +runroot rpmsign --addsign --rpmv6 --key-id 152BB32FD9CA982797E835CFB0645AEC757BF69E /tmp/hello-2.0-1.x86_64.rpm &> /dev/null +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm +], +[0], +[/tmp/hello-2.0-1.x86_64.rpm: + Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 152bb32fd9ca982797e835cfb0645aec757bf69e: OK + Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK + Header SHA256 digest: OK + Payload SHA256 digest: OK +], +[]) + +RPMTEST_CHECK([ +runroot rpmsign --addsign --rpmv6 --key-id E8A62C0512B06B5D2183BA207F1C21F95F65BBE8 /tmp/hello-2.0-1.x86_64.rpm &> /dev/null +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm +], +[0], +[/tmp/hello-2.0-1.x86_64.rpm: + Header OpenPGP V4 ECDSA/SHA512 signature, key fingerprint: e8a62c0512b06b5d2183ba207f1c21f95f65bbe8: OK + Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 152bb32fd9ca982797e835cfb0645aec757bf69e: OK + Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK + Header SHA256 digest: OK + Payload SHA256 digest: OK +], +[]) + +RPMTEST_CHECK([ +runroot rpmkeys --delete 152bb32fd9ca982797e835cfb0645aec757bf69e +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm +], +[1], +[/tmp/hello-2.0-1.x86_64.rpm: + Header OpenPGP V4 ECDSA/SHA512 signature, key fingerprint: e8a62c0512b06b5d2183ba207f1c21f95f65bbe8: OK + Header OpenPGP V4 EdDSA/SHA512 signature, key ID b0645aec757bf69e: NOKEY + Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK + Header SHA256 digest: OK + Payload SHA256 digest: OK +], +[]) + +RPMTEST_CHECK([ +runroot rpmsign --resign --key-id E8A62C0512B06B5D2183BA207F1C21F95F65BBE8 /tmp/hello-2.0-1.x86_64.rpm &> /dev/null +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm +], +[0], +[/tmp/hello-2.0-1.x86_64.rpm: + Header OpenPGP V4 ECDSA/SHA512 signature, key fingerprint: e8a62c0512b06b5d2183ba207f1c21f95f65bbe8: OK + Header SHA256 digest: OK + Payload SHA256 digest: OK +], +[]) + +RPMTEST_CHECK([ +runroot rpmsign --delsign /tmp/hello-2.0-1.x86_64.rpm &> /dev/null +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64.rpm +], +[0], +[/tmp/hello-2.0-1.x86_64.rpm: + Header SHA256 digest: OK + Payload SHA256 digest: OK +], +[]) + +RPMTEST_CLEANUP + +AT_SETUP([rpmsign --addsign multisig v6]) +AT_KEYWORDS([rpmsign signature multisig v6]) +AT_SKIP_IF([test x$PGP = xdummy]) +RPMDB_INIT + +RPMTEST_CHECK([ +cat << EOF >> ${HOME}/.rpmmacros +%_openpgp_sign sq +%_openpgp_sign_id 771B18D3D7BAA28734333C424344591E1964C5FC +EOF + +runroot_other sq key import /data/keys/*.secret +runroot rpmkeys --import /data/keys/*.pub +], +[0], +[ignore], +[ignore]) + +RPMTEST_CHECK([ +runroot rpmbuild -bb --quiet \ + --define "_rpmfilever 6" \ + /data/SPECS/attrtest.spec +runroot rpmsign --addsign /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm +], +[0], +[], +[ignore]) + +RPMTEST_CHECK([ +runroot rpmkeys -K /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm +], +[0], +[/build/RPMS/noarch/attrtest-1.0-1.noarch.rpm: digests signatures OK +], +[]) + +RPMTEST_CHECK([ +for t in DSAHEADER RSAHEADER SIGGPG SIGPGP OPENPGP; do + runroot rpm -qp --qf "$t: %{$t}\n" /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm | grep \(none\) +done +], +[ignore], +[DSAHEADER: (none) +RSAHEADER: (none) +SIGGPG: (none) +SIGPGP: (none) +], +[]) + +RPMTEST_CHECK([ +runroot rpmsign --resign --rpmv4 \ + --key-id E8A62C0512B06B5D2183BA207F1C21F95F65BBE8 \ + /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm +], +[0], +[], +[ignore]) + +RPMTEST_CHECK([ +runroot rpmkeys -K /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm +], +[0], +[/build/RPMS/noarch/attrtest-1.0-1.noarch.rpm: digests signatures OK +], +[]) + +RPMTEST_CHECK([ +for t in DSAHEADER RSAHEADER SIGGPG SIGPGP OPENPGP; do + runroot rpm -qp --qf "$t: %{$t}\n" /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm | grep \(none\) +done +], +[ignore], +[RSAHEADER: (none) +SIGGPG: (none) +SIGPGP: (none) +], +[]) +RPMTEST_CLEANUP + # ------------------------------ # Test --delsign AT_SETUP([rpmsign --delsign]) diff --git a/tests/rpmvfylevel.at b/tests/rpmvfylevel.at index 3562d96dce..f34713153a 100644 --- a/tests/rpmvfylevel.at +++ b/tests/rpmvfylevel.at @@ -346,6 +346,7 @@ nohdrs 0 nosig /data/RPMS/hello-2.0-1.x86_64-signed.rpm: + Header OpenPGP signature: NOTFOUND Header OpenPGP RSA signature: NOTFOUND Header OpenPGP DSA signature: NOTFOUND Header SHA256 digest: OK diff --git a/tools/rpmsign.cc b/tools/rpmsign.cc index 16063991a3..006fb2d478 100644 --- a/tools/rpmsign.cc +++ b/tools/rpmsign.cc @@ -43,7 +43,13 @@ static struct poptOption signOptsTable[] = { #endif { "rpmv3", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &sargs.signflags, RPMSIGN_FLAG_RPMV3, - N_("create rpm v3 header+payload signatures") }, + N_("request legacy rpm v3 header+payload signatures on v4 packages") }, + { "rpmv4", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), + &sargs.signflags, RPMSIGN_FLAG_RPMV4, + N_("request legacy rpm v4 header signatures on v6 packages") }, + { "rpmv6", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), + &sargs.signflags, RPMSIGN_FLAG_RPMV6, + N_("request rpm v6 header signature on v4 packages") }, #ifdef WITH_IMAEVM { "signfiles", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &sargs.signflags, RPMSIGN_FLAG_IMA, @@ -207,8 +213,10 @@ int main(int argc, char *argv[]) #endif switch (mode) { - case MODE_ADDSIGN: case MODE_RESIGN: + sargs.signflags |= RPMSIGN_FLAG_RESIGN; + /* fallthrough */ + case MODE_ADDSIGN: ec = doSign(optCon, &sargs); break; case MODE_DELSIGN: From b8bc68c2c36cf7e3086ef86756e7e1a0f647804b Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Mon, 18 Nov 2024 15:50:06 +0200 Subject: [PATCH 6/6] Add support for multiple OpenPGP signatures per package, part 2/2 Add a tag extension for RPMTAG_OPENPGP (on top of the concrete tag) to handle compatibility with v3/v4 signatures: the extension collects all legacy signatures under the same umbrella so users don't need to query multiple different tags, you just query for RPMTAG_OPENPGP to get all them at once. Extend :pgpsig tag format to handle the new string array/base64 variant. Update --info/-i query to use the extension and output all existing signatures, one per line. The no-signature case of "Signature : (none)" is preserved as-is to help backwards compatibility with scripts parsing the output. Related: #3385 --- lib/formats.cc | 24 +++++++++++++++++++++--- lib/tagexts.cc | 34 ++++++++++++++++++++++++++++++++++ rpmpopt.in | 2 +- tests/rpmquery.at | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/lib/formats.cc b/lib/formats.cc index 61d04fe65e..a5e891d1ab 100644 --- a/lib/formats.cc +++ b/lib/formats.cc @@ -419,12 +419,12 @@ static char *jsonFormat(rpmtd td, char **emsg) } /* signature fingerprint and time formatting */ -static char * pgpsigFormat(rpmtd td, char **emsg) +static char * pgpsigFormatOne(uint8_t *pkt, size_t pktlen, char **emsg) { char * val = NULL; pgpDigParams sigp = NULL; - if (pgpPrtParams((uint8_t*)td->data, td->count, PGPTAG_SIGNATURE, &sigp)) { + if (pgpPrtParams(pkt, pktlen, PGPTAG_SIGNATURE, &sigp)) { *emsg = xstrdup(_("(not an OpenPGP signature)")); } else { char dbuf[BUFSIZ]; @@ -451,6 +451,24 @@ static char * pgpsigFormat(rpmtd td, char **emsg) return val; } +static char * pgpsigFormat(rpmtd td, char **emsg) +{ + char *val = NULL; + if (rpmtdType(td) == RPM_BIN_TYPE) { + val = pgpsigFormatOne((uint8_t *)td->data, td->count, emsg); + } else if (rpmtdType(td) == RPM_STRING_ARRAY_TYPE) { + uint8_t *pkt = NULL; + size_t pktlen = 0; + if (rpmBase64Decode(rpmtdGetString(td), (void **)&pkt, &pktlen) == 0) { + val = pgpsigFormatOne(pkt, pktlen, emsg); + free(pkt); + } + } else { + *emsg = xstrdup(_("(invalid type)")); + } + return val; +} + /* dependency flags formatting */ static char * depflagsFormat(rpmtd td, char **emsg) { @@ -581,7 +599,7 @@ static const struct headerFmt_s rpmHeaderFormats[] = { { RPMTD_FORMAT_BASE64, "base64", RPM_BINARY_CLASS, base64Format }, { RPMTD_FORMAT_PGPSIG, "pgpsig", - RPM_BINARY_CLASS, pgpsigFormat }, + RPM_NULL_CLASS, pgpsigFormat }, { RPMTD_FORMAT_DEPFLAGS, "depflags", RPM_NUMERIC_CLASS, depflagsFormat }, { RPMTD_FORMAT_DEPTYPE, "deptype", diff --git a/lib/tagexts.cc b/lib/tagexts.cc index ed2f678964..9f8386ffda 100644 --- a/lib/tagexts.cc +++ b/lib/tagexts.cc @@ -1052,6 +1052,39 @@ static int sysusersTag(Header h, rpmtd td, headerGetFlags hgflags) return (td->count > 0); } +static void trySigTag(Header h, rpmTagVal tag, ARGV_t *sigs) +{ + struct rpmtd_s td; + if (headerGet(h, tag, &td, HEADERGET_ALLOC)) { + char *b64 = rpmBase64Encode((uint8_t *)td.data, td.count, 0); + if (b64) { + argvAdd(sigs, b64); + free(b64); + } + rpmtdFreeData(&td); + } +} + +static int openpgpTag(Header h, rpmtd td, headerGetFlags hgflags) +{ + if (headerGet(h, RPMTAG_OPENPGP, td, HEADERGET_ALLOC)) + return 1; + + ARGV_t sigs = NULL; + trySigTag(h, RPMTAG_RSAHEADER, &sigs); + trySigTag(h, RPMTAG_DSAHEADER, &sigs); + trySigTag(h, RPMTAG_SIGPGP, &sigs); + trySigTag(h, RPMTAG_SIGGPG, &sigs); + + if (sigs) { + td->data = sigs; + td->count = argvCount(sigs); + td->type = RPM_STRING_ARRAY_TYPE; + td->flags = RPMTD_ALLOCED|RPMTD_PTR_ALLOCED; + } + return td->count != 0; +} + static const struct headerTagFunc_s rpmHeaderTagExtensions[] = { { RPMTAG_GROUP, groupTag }, { RPMTAG_DESCRIPTION, descriptionTag }, @@ -1093,6 +1126,7 @@ static const struct headerTagFunc_s rpmHeaderTagExtensions[] = { { RPMTAG_FILENLINKS, filenlinksTag }, { RPMTAG_SYSUSERS, sysusersTag }, { RPMTAG_FILEMIMES, filemimesTag }, + { RPMTAG_OPENPGP, openpgpTag }, { 0, NULL } }; diff --git a/rpmpopt.in b/rpmpopt.in index 40a173324f..259b187e40 100644 --- a/rpmpopt.in +++ b/rpmpopt.in @@ -96,7 +96,7 @@ Install Date: %|INSTALLTIME?{%{INSTALLTIME:date}}:{(not installed)}|\n\ Group : %{GROUP}\n\ Size : %{LONGSIZE}\n\ %|LICENSE?{License : %{LICENSE}}|\n\ -Signature : %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|\n\ +Signature :%|OPENPGP?{[\n %{OPENPGP:pgpsig}]}:{ (none)}|\n\ Source RPM : %{SOURCERPM}\n\ Build Date : %{BUILDTIME:date}\n\ Build Host : %{BUILDHOST}\n\ diff --git a/tests/rpmquery.at b/tests/rpmquery.at index 33c5708bc9..1f20bac9e5 100644 --- a/tests/rpmquery.at +++ b/tests/rpmquery.at @@ -420,6 +420,18 @@ rpm \ [RSA/SHA256, Thu Apr 6 13:02:33 2017, Key ID 4344591e1964c5fc], [warning: /data/RPMS/hello-2.0-1.x86_64-signed.rpm: Header OpenPGP V4 RSA/SHA256 signature, key ID 4344591e1964c5fc: NOKEY ]) + +RPMTEST_CHECK([[ +runroot rpm \ + --nosignature \ + --qf "[%{openpgp:pgpsig}\n]" \ + -qp /data/RPMS/hello-2.0-1.x86_64-signed.rpm +]], +[0], +[RSA/SHA256, Thu Apr 6 13:02:33 2017, Key ID 4344591e1964c5fc +RSA/SHA256, Thu Apr 6 13:02:32 2017, Key ID 4344591e1964c5fc +], +[]) RPMTEST_CLEANUP # ------------------------------ @@ -1396,3 +1408,32 @@ runroot rpm -qp --filemime /build/RPMS/noarch/filetypes-1.0-1.noarch.rpm | sed - ], []) RPMTEST_CLEANUP + +AT_SETUP([info query output]) +AT_KEYWORDS([query signature]) +RPMTEST_CHECK([ +runroot rpm -qi --nosignature /data/RPMS/hello-2.0-1.x86_64-signed.rpm +], +[0], +[[Name : hello +Version : 2.0 +Release : 1 +Architecture: x86_64 +Install Date: (not installed) +Group : Testing +Size : 7243 +License : GPL +Signature : + RSA/SHA256, Thu Apr 6 13:02:33 2017, Key ID 4344591e1964c5fc + RSA/SHA256, Thu Apr 6 13:02:32 2017, Key ID 4344591e1964c5fc +Source RPM : hello-2.0-1.src.rpm +Build Date : Sat Nov 22 12:00:00 2008 +Build Host : localhost +Relocations : /usr +Summary : hello -- hello, world rpm +Description : +Simple rpm demonstration. +]], +[]) +RPMTEST_CLEANUP +