summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDemi Marie Obenour <demi@invisiblethingslab.com>2022-02-06 15:52:48 -0500
committerMichal Domonkos <mdomonko@redhat.com>2022-07-01 10:52:14 +0200
commite4be244d252925ee32bcfce21452ef048391cf1b (patch)
treeab258234e4be5c3f214de600f3dfe5b8284edc49
parent6c195c67ecf7c23fa6f1c45d90058284d33c270e (diff)
downloadrpm-e4be244d252925ee32bcfce21452ef048391cf1b.tar.gz
Require creation time to be unique and hashed
According to RFC 4880 §5.2.3.4 the signature creation time MUST be a hashed subpacket. Enforce this requirement in RPM. Also set the saved flags to PGPDIG_SAVED_TIME | PGPDIG_SAVED_ID | PGPDIG_SAVED_CREATION_TIME for v3 signatures, and do not overwrite an already saved key ID with one taken from a v3 signature. (cherry picked from commit 7e7266c9af883ce49b3516a5bd099d218e8e3fac)
-rw-r--r--rpmio/digest.h4
-rw-r--r--rpmio/rpmpgp.c29
2 files changed, 22 insertions, 11 deletions
diff --git a/rpmio/digest.h b/rpmio/digest.h
index 3b72a2870..ec7f3392f 100644
--- a/rpmio/digest.h
+++ b/rpmio/digest.h
@@ -36,9 +36,11 @@ struct pgpDigParams_s {
uint32_t hashlen;
uint8_t signhash16[2];
pgpKeyID_t signid;
- uint8_t saved;
+ uint8_t saved; /*!< Various flags. `PGPDIG_SAVED_*` are never reset.
+ * `PGPDIG_SIG_HAS_*` are reset for each signature. */
#define PGPDIG_SAVED_TIME (1 << 0)
#define PGPDIG_SAVED_ID (1 << 1)
+#define PGPDIG_SIG_HAS_CREATION_TIME (1 << 2)
pgpDigAlg alg;
};
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
index 332be12d2..300540399 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -473,16 +473,16 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
for (i = 1; i < plen; i++)
pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
break;
- case PGPSUBTYPE_SIG_CREATE_TIME:
+ case PGPSUBTYPE_SIG_CREATE_TIME: /* signature creation time */
+ if (plen-1 != sizeof(_digp->time))
+ break; /* other lengths not understood */
+ if (_digp->saved & PGPDIG_SIG_HAS_CREATION_TIME)
+ return 1; /* duplicate timestamps not allowed */
impl = *p;
- if (!(_digp->saved & PGPDIG_SAVED_TIME) &&
- (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
- {
- if (plen-1 != sizeof(_digp->time))
- break;
- _digp->saved |= PGPDIG_SAVED_TIME;
+ if (!(_digp->saved & PGPDIG_SAVED_TIME))
_digp->time = pgpGrab(p+1, sizeof(_digp->time));
- }
+ _digp->saved |= PGPDIG_SAVED_TIME | PGPDIG_SIG_HAS_CREATION_TIME;
+ break;
case PGPSUBTYPE_SIG_EXPIRE_TIME:
case PGPSUBTYPE_KEY_EXPIRE_TIME:
pgpPrtTime(" ", p+1, plen-1);
@@ -592,6 +592,9 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
size_t plen;
int rc = 1;
+ /* Reset the saved flags */
+ _digp->saved &= PGPDIG_SAVED_TIME | PGPDIG_SAVED_ID;
+
if (pgpVersion(h, hlen, &version))
return rc;
@@ -619,8 +622,11 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
_digp->hashlen = v->hashlen;
_digp->sigtype = v->sigtype;
_digp->hash = memcpy(xmalloc(v->hashlen), &v->sigtype, v->hashlen);
- _digp->time = pgpGrab(v->time, sizeof(v->time));
- memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
+ if (!(_digp->saved & PGPDIG_SAVED_TIME))
+ _digp->time = pgpGrab(v->time, sizeof(v->time));
+ if (!(_digp->saved & PGPDIG_SAVED_ID))
+ memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
+ _digp->saved = PGPDIG_SAVED_TIME | PGPDIG_SIG_HAS_CREATION_TIME | PGPDIG_SAVED_ID;
_digp->pubkey_algo = v->pubkey_algo;
_digp->hash_algo = v->hash_algo;
memcpy(_digp->signhash16, v->signhash16, sizeof(_digp->signhash16));
@@ -658,6 +664,9 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
return 1;
p += plen;
+ if (!(_digp->saved & PGPDIG_SIG_HAS_CREATION_TIME))
+ return 1; /* RFC 4880 §5.2.3.4 creation time MUST be hashed */
+
if (pgpGet(p, 2, hend, &plen))
return 1;
p += 2;