summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2017-03-08 14:36:39 +0200
committerPanu Matilainen <pmatilai@redhat.com>2017-03-08 14:43:55 +0200
commit6eeb2f2963cb4ab5f7c24b0c7165336581e53117 (patch)
treeac468ab3caac21d86af4d153871b3c5a50482478
parent3cfd031832dd62459a5532f8b98021bb13820a9d (diff)
downloadrpm-6eeb2f2963cb4ab5f7c24b0c7165336581e53117.tar.gz
Implement SHA256 header digest, creation + verification
SHA1 has been getting a bit long in the tooth for many years by now, add a more modern digest to eventually supplant it, for now just prefer SHA256 over SHA1 if present when verifying. Using a hardwired algorithm instead of configurable one to keep things on the simple side when dealing with the signature header. Signing could add the new digest for older packages but we don't do that to avoid surprises when people are signing older packages.
-rw-r--r--build/pack.c10
-rw-r--r--lib/package.c8
-rw-r--r--lib/rpmchecksig.c3
-rw-r--r--lib/rpmtag.h3
-rw-r--r--lib/rpmts.h4
-rw-r--r--lib/signature.c24
-rw-r--r--lib/signature.h5
-rw-r--r--python/rpmmodule.c1
-rw-r--r--sign/rpmgensig.c14
-rw-r--r--tests/rpmgeneral.at1
10 files changed, 62 insertions, 11 deletions
diff --git a/build/pack.c b/build/pack.c
index 28150e5fd..7cc847e81 100644
--- a/build/pack.c
+++ b/build/pack.c
@@ -475,6 +475,7 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
FD_t fd = NULL;
char * rpmio_flags = NULL;
char * SHA1 = NULL;
+ char * SHA256 = NULL;
uint8_t * MD5 = NULL;
char * pld = NULL;
uint32_t pld_algo = PGPHASHALGO_SHA256; /* TODO: macro configuration */
@@ -526,10 +527,12 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
/* Generate and write a placeholder signature header */
SHA1 = nullDigest(PGPHASHALGO_SHA1, 1);
+ SHA256 = nullDigest(PGPHASHALGO_SHA256, 1);
MD5 = nullDigest(PGPHASHALGO_MD5, 0);
- if (rpmGenerateSignature(SHA1, MD5, 0, 0, fd))
+ if (rpmGenerateSignature(SHA256, SHA1, MD5, 0, 0, fd))
goto exit;
SHA1 = _free(SHA1);
+ SHA256 = _free(SHA256);
MD5 = _free(MD5);
/* Write a placeholder header. */
@@ -563,9 +566,11 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
/* Calculate digests: SHA on header, legacy MD5 on header + payload */
fdInitDigestID(fd, PGPHASHALGO_MD5, RPMTAG_SIGMD5, 0);
fdInitDigestID(fd, PGPHASHALGO_SHA1, RPMTAG_SHA1HEADER, 0);
+ fdInitDigestID(fd, PGPHASHALGO_SHA256, RPMTAG_SHA256HEADER, 0);
if (fdConsume(fd, hdrStart, payloadStart - hdrStart))
goto exit;
fdFiniDigest(fd, RPMTAG_SHA1HEADER, (void **)&SHA1, NULL, 1);
+ fdFiniDigest(fd, RPMTAG_SHA256HEADER, (void **)&SHA256, NULL, 1);
if (fdConsume(fd, 0, payloadEnd - payloadStart))
goto exit;
@@ -575,7 +580,7 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
goto exit;
/* Generate the signature. Now with right values */
- if (rpmGenerateSignature(SHA1, MD5, payloadEnd - hdrStart, archiveSize, fd))
+ if (rpmGenerateSignature(SHA256, SHA1, MD5, payloadEnd - hdrStart, archiveSize, fd))
goto exit;
rc = RPMRC_OK;
@@ -583,6 +588,7 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
exit:
free(rpmio_flags);
free(SHA1);
+ free(SHA256);
/* XXX Fish the pkgid out of the signature header. */
if (pkgidp != NULL) {
diff --git a/lib/package.c b/lib/package.c
index 4de639763..6beb203fd 100644
--- a/lib/package.c
+++ b/lib/package.c
@@ -55,6 +55,7 @@ static void headerMergeLegacySigs(Header h, Header sigh)
td.tag = RPMTAG_ARCHIVESIZE;
break;
case RPMSIGTAG_SHA1:
+ case RPMSIGTAG_SHA256:
case RPMSIGTAG_DSA:
case RPMSIGTAG_RSA:
default:
@@ -176,6 +177,13 @@ static rpmRC headerSigVerify(rpmKeyring keyring, rpmVSFlags vsflags,
ei2h(blob->pe+i, &einfo);
switch (einfo.tag) {
+ case RPMTAG_SHA256HEADER:
+ if (vsflags & RPMVSF_NOSHA256HEADER)
+ break;
+ /* Prefer SHA256 over SHA1 if both are present */
+ if (sigtd.tag == 0 || sigtd.tag == RPMTAG_SHA1HEADER)
+ ei2td(&einfo, blob->dataStart, 0, &sigtd);
+ break;
case RPMTAG_SHA1HEADER:
if (vsflags & RPMVSF_NOSHA1HEADER)
break;
diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
index 14bf7cf8b..42656d890 100644
--- a/lib/rpmchecksig.c
+++ b/lib/rpmchecksig.c
@@ -155,6 +155,9 @@ static const char *sigtagname(rpmTagVal sigtag, int upper)
case RPMSIGTAG_SHA1:
n = (upper ? "SHA1" : "sha1");
break;
+ case RPMSIGTAG_SHA256:
+ n = (upper ? "SHA256" : "sha256");
+ break;
case RPMSIGTAG_MD5:
n = (upper ? "MD5" : "md5");
break;
diff --git a/lib/rpmtag.h b/lib/rpmtag.h
index 6a8951d4e..ad65a8345 100644
--- a/lib/rpmtag.h
+++ b/lib/rpmtag.h
@@ -63,6 +63,8 @@ typedef enum rpmTag_e {
#define RPMTAG_HDRID RPMTAG_SHA1HEADER /* s */
RPMTAG_LONGSIGSIZE = RPMTAG_SIG_BASE+14, /* l */
RPMTAG_LONGARCHIVESIZE = RPMTAG_SIG_BASE+15, /* l */
+ /* RPMTAG_SIG_BASE+16 reserved */
+ RPMTAG_SHA256HEADER = RPMTAG_SIG_BASE+17, /* s */
RPMTAG_NAME = 1000, /* s */
#define RPMTAG_N RPMTAG_NAME /* s */
@@ -419,6 +421,7 @@ typedef enum rpmSigTag_e {
RPMSIGTAG_RSA = RPMTAG_RSAHEADER, /*!< internal RSA header signature. */
RPMSIGTAG_LONGSIZE = RPMTAG_LONGSIGSIZE, /*!< internal Header+Payload size (64bit) in bytes. */
RPMSIGTAG_LONGARCHIVESIZE = RPMTAG_LONGARCHIVESIZE, /*!< internal uncompressed payload size (64bit) in bytes. */
+ RPMSIGTAG_SHA256 = RPMTAG_SHA256HEADER,
} rpmSigTag;
diff --git a/lib/rpmts.h b/lib/rpmts.h
index 02850af4b..b6dac90f6 100644
--- a/lib/rpmts.h
+++ b/lib/rpmts.h
@@ -96,7 +96,7 @@ enum rpmVSFlags_e {
RPMVSF_NEEDPAYLOAD = (1 << 1),
/* bit(s) 2-7 unused */
RPMVSF_NOSHA1HEADER = (1 << 8),
- /* bit 9 unused */
+ RPMVSF_NOSHA256HEADER = (1 << 9),
RPMVSF_NODSAHEADER = (1 << 10),
RPMVSF_NORSAHEADER = (1 << 11),
/* bit(s) 12-16 unused */
@@ -110,6 +110,7 @@ typedef rpmFlags rpmVSFlags;
#define _RPMVSF_NODIGESTS \
( RPMVSF_NOSHA1HEADER | \
+ RPMVSF_NOSHA256HEADER | \
RPMVSF_NOMD5 )
#define _RPMVSF_NOSIGNATURES \
@@ -120,6 +121,7 @@ typedef rpmFlags rpmVSFlags;
#define _RPMVSF_NOHEADER \
( RPMVSF_NOSHA1HEADER | \
+ RPMVSF_NOSHA256HEADER | \
RPMVSF_NODSAHEADER | \
RPMVSF_NORSAHEADER )
diff --git a/lib/signature.c b/lib/signature.c
index e5e9c5214..a0a77a186 100644
--- a/lib/signature.c
+++ b/lib/signature.c
@@ -43,6 +43,14 @@ rpmRC rpmSigInfoParse(rpmtd td, const char *origin,
/* GPG/PGP are hdr+payload, RSA/DSA are hdr-only */
sinfo->range |= RPMSIG_HEADER;
break;
+ case RPMSIGTAG_SHA256:
+ tagsize = 65; /* includes trailing \0 */
+ tagtype = RPM_STRING_TYPE;
+ hexstring = 1;
+ sinfo->hashalgo = PGPHASHALGO_SHA256;
+ sinfo->type = RPMSIG_DIGEST_TYPE;
+ sinfo->range = RPMSIG_HEADER;
+ break;
case RPMSIGTAG_SHA1:
tagsize = 41; /* includes trailing \0 */
tagtype = RPM_STRING_TYPE;
@@ -221,8 +229,8 @@ int rpmWriteSignature(FD_t fd, Header sigh)
return rc;
}
-rpmRC rpmGenerateSignature(char *SHA1, uint8_t *MD5, rpm_loff_t size,
- rpm_loff_t payloadSize, FD_t fd)
+rpmRC rpmGenerateSignature(char *SHA256, char *SHA1, uint8_t *MD5,
+ rpm_loff_t size, rpm_loff_t payloadSize, FD_t fd)
{
Header sig = headerNew();
struct rpmtd_s td;
@@ -232,6 +240,15 @@ rpmRC rpmGenerateSignature(char *SHA1, uint8_t *MD5, rpm_loff_t size,
int gpgSize = rpmExpandNumeric("%{__gpg_reserved_space}");
/* Prepare signature */
+ if (SHA256) {
+ rpmtdReset(&td);
+ td.tag = RPMSIGTAG_SHA256;
+ td.count = 1;
+ td.type = RPM_STRING_TYPE;
+ td.data = SHA256;
+ headerPut(sig, &td, HEADERPUT_DEFAULT);
+ }
+
if (SHA1) {
rpmtdReset(&td);
td.tag = RPMSIGTAG_SHA1;
@@ -398,6 +415,9 @@ rpmVerifySignature(rpmKeyring keyring, rpmtd sigtd, pgpDigParams sig,
case RPMSIGTAG_SHA1:
res = verifyDigest(sigtd, ctx, _("Header SHA1 digest:"), &msg);
break;
+ case RPMSIGTAG_SHA256:
+ res = verifyDigest(sigtd, ctx, _("Header SHA256 digest:"), &msg);
+ break;
case RPMSIGTAG_RSA:
case RPMSIGTAG_DSA:
hdrsig = 1;
diff --git a/lib/signature.h b/lib/signature.h
index 6d484956f..db9dd97ba 100644
--- a/lib/signature.h
+++ b/lib/signature.h
@@ -65,14 +65,15 @@ rpmRC rpmVerifySignature(rpmKeyring keyring, rpmtd sigtd, pgpDigParams sig,
/** \ingroup signature
* Generate signature and write to file
+ * @param SHA256 SHA256 digest
* @param SHA1 SHA1 digest
* @param MD5 MD5 digest
* @param size size of header
* @param payloadSize size of archive
* @param fd output file
*/
-rpmRC rpmGenerateSignature(char *SHA1, uint8_t *MD5, rpm_loff_t size,
- rpm_loff_t payloadSize, FD_t fd);
+rpmRC rpmGenerateSignature(char *SHA256, char *SHA1, uint8_t *MD5,
+ rpm_loff_t size, rpm_loff_t payloadSize, FD_t fd);
RPM_GNUC_INTERNAL
rpmRC rpmSigInfoParse(rpmtd td, const char *origin,
diff --git a/python/rpmmodule.c b/python/rpmmodule.c
index e5cd7b1c7..66951d309 100644
--- a/python/rpmmodule.c
+++ b/python/rpmmodule.c
@@ -534,6 +534,7 @@ static int initModule(PyObject *m)
REGISTER_ENUM(RPMVSF_NOHDRCHK);
REGISTER_ENUM(RPMVSF_NEEDPAYLOAD);
REGISTER_ENUM(RPMVSF_NOSHA1HEADER);
+ REGISTER_ENUM(RPMVSF_NOSHA256HEADER);
REGISTER_ENUM(RPMVSF_NODSAHEADER);
REGISTER_ENUM(RPMVSF_NORSAHEADER);
REGISTER_ENUM(RPMVSF_NOMD5);
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index beb5476a9..a59320651 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -492,7 +492,7 @@ static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag)
static rpmRC replaceSigDigests(FD_t fd, const char *rpm, Header *sigp,
off_t sigStart, off_t sigTargetSize,
- char *SHA1, uint8_t *MD5)
+ char *SHA256, char *SHA1, uint8_t *MD5)
{
off_t archiveSize;
rpmRC rc = RPMRC_OK;
@@ -514,7 +514,7 @@ static rpmRC replaceSigDigests(FD_t fd, const char *rpm, Header *sigp,
rpmPushMacro(NULL, "__gpg_reserved_space", NULL, 0, RMIL_GLOBAL);
/* Replace old digests in sigh */
- rc = rpmGenerateSignature(SHA1, MD5, sigTargetSize, archiveSize, fd);
+ rc = rpmGenerateSignature(SHA256, SHA1, MD5, sigTargetSize, archiveSize, fd);
if (rc != RPMRC_OK) {
rpmlog(RPMLOG_ERR, _("generateSignature failed\n"));
goto exit;
@@ -547,6 +547,7 @@ static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
char *key;
char *keypass;
char *SHA1 = NULL;
+ char *SHA256 = NULL;
uint8_t *MD5 = NULL;
off_t sigTargetSize;
rpmRC rc = RPMRC_OK;
@@ -603,14 +604,18 @@ static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
/* Start MD5 calculation */
fdInitDigestID(fd, PGPHASHALGO_MD5, RPMSIGTAG_MD5, 0);
- /* Write header to rpm and recalculate SHA1 */
+ /* Write header to rpm and recalculate digests */
fdInitDigestID(fd, PGPHASHALGO_SHA1, RPMSIGTAG_SHA1, 0);
+ fdInitDigestID(fd, PGPHASHALGO_SHA256, RPMSIGTAG_SHA256, 0);
rc = headerWrite(fd, *hdrp, HEADER_MAGIC_YES);
if (rc != RPMRC_OK) {
rpmlog(RPMLOG_ERR, _("headerWrite failed\n"));
goto exit;
}
fdFiniDigest(fd, RPMSIGTAG_SHA1, (void **)&SHA1, NULL, 1);
+ /* Only add SHA256 if it was there to begin with */
+ if (headerIsEntry(*sigp, RPMSIGTAG_SHA256))
+ fdFiniDigest(fd, RPMSIGTAG_SHA256, (void **)&SHA256, NULL, 1);
/* Copy archive from temp file */
if (Fseek(ofd, 0, SEEK_SET) < 0) {
@@ -639,12 +644,13 @@ static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
_("%s already contains identical file signatures\n"),
rpm);
else
- replaceSigDigests(fd, rpm, sigp, sigStart, sigTargetSize, SHA1, MD5);
+ replaceSigDigests(fd, rpm, sigp, sigStart, sigTargetSize, SHA256, SHA1, MD5);
exit:
free(trpm);
free(MD5);
free(SHA1);
+ free(SHA256);
free(o_sha1);
free(keypass);
free(key);
diff --git a/tests/rpmgeneral.at b/tests/rpmgeneral.at
index 60f5efe70..509277f2c 100644
--- a/tests/rpmgeneral.at
+++ b/tests/rpmgeneral.at
@@ -242,6 +242,7 @@ REQUIREVERSION
RPMVERSION
RSAHEADER
SHA1HEADER
+SHA256HEADER
SIGGPG
SIGMD5
SIGPGP