From 951ef4844f6b3245c03bc7ecd5f600374c854247 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Sun, 27 Nov 2022 16:05:16 +0000 Subject: [PATCH] Add support for verifying v3 signature packets We only support signature checking on v4+ keys, so hadn't any support for v3 signature packets. However keys have been observed in the wild where the key itself is a v4 key, but it's making v3 signatures (in particular as a revocation signature for the key). While this seems odd (anything that supports the key has to support v4, so why generate anything lower?) it's probably too strict a check to have in place. --- sigcheck.c | 57 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/sigcheck.c b/sigcheck.c index 31932bc..b59798b 100644 --- a/sigcheck.c +++ b/sigcheck.c @@ -290,6 +290,7 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, onak_status_t ret; struct onak_key_material pubkey; struct dsa_signature dsasig; + uint8_t sigkeytype; uint8_t edsig[64]; uint64_t keyid; int len, ofs; @@ -306,29 +307,51 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, goto out; } - /* Is the key the same type as the signature we're checking? */ - if (pubkey.type != sig->data[2]) { - ret = ONAK_E_INVALID_PARAM; - goto out; - } + if (sig->data[0] == 3) { + /* Must be 5 bytes hashed */ + if (sig->data[1] != 5) { + ret = ONAK_E_INVALID_PARAM; + goto out; + } - /* Skip the hashed data */ - ofs = (sig->data[4] << 8) + sig->data[5] + 6; - if (sig->length < ofs + 2) { - ret = ONAK_E_INVALID_PKT; + /* Need at least 19 bytes for the sig header */ + if (sig->length < 19) { + ret = ONAK_E_INVALID_PKT; + goto out; + } + + /* Skip to the signature material */ + ofs += 19; + sigkeytype = sig->data[15]; + } else if (sig->data[0] >= 4) { + /* Skip the hashed data */ + ofs = (sig->data[4] << 8) + sig->data[5] + 6; + if (sig->length < ofs + 2) { + ret = ONAK_E_INVALID_PKT; + goto out; + } + /* Skip the unhashed data */ + ofs += (sig->data[ofs] << 8) + sig->data[ofs + 1] + 2; + if (sig->length < ofs + 2) { + ret = ONAK_E_INVALID_PKT; + goto out; + } + /* Skip the sig hash bytes */ + ofs += 2; + sigkeytype = sig->data[2]; + } else { + ret = ONAK_E_UNSUPPORTED_FEATURE; goto out; } - /* Skip the unhashed data */ - ofs += (sig->data[ofs] << 8) + sig->data[ofs + 1] + 2; - if (sig->length < ofs + 2) { - ret = ONAK_E_INVALID_PKT; + + /* Is the key the same type as the signature we're checking? */ + if (pubkey.type != sigkeytype) { + ret = ONAK_E_INVALID_PARAM; goto out; } - /* Skip the sig hash bytes */ - ofs += 2; /* Parse the actual signature values */ - switch (sig->data[2]) { + switch (sigkeytype) { case OPENPGP_PKALGO_ECDSA: case OPENPGP_PKALGO_DSA: mpz_init(dsasig.r); @@ -478,7 +501,7 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, } sigerr: - switch (sig->data[2]) { + switch (sigkeytype) { case OPENPGP_PKALGO_ECDSA: case OPENPGP_PKALGO_EDDSA: case OPENPGP_PKALGO_DSA: -- 2.39.5