diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_trust.c | 48 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_verify.c | 16 |
2 files changed, 47 insertions, 17 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 8bd474e5e706..ae47be6128c4 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -55,13 +55,16 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, * keys. */ key = x509_request_asymmetric_key(trust_keyring, x509->id); - if (!IS_ERR(key)) + if (!IS_ERR(key)) { /* One of the X.509 certificates in the PKCS#7 message * is apparently the same as one we already trust. * Verify that the trusted variant can also validate * the signature on the descendant. */ + pr_devel("sinfo %u: Cert %u as key %x\n", + sinfo->index, x509->index, key_serial(key)); goto matched; + } if (key == ERR_PTR(-ENOMEM)) return -ENOMEM; @@ -81,15 +84,34 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, /* No match - see if the root certificate has a signer amongst the * trusted keys. */ - if (!last || !last->issuer || !last->authority) { - kleave(" = -ENOKEY [no backref]"); - return -ENOKEY; + if (last && last->authority) { + key = x509_request_asymmetric_key(trust_keyring, last->authority); + if (!IS_ERR(key)) { + x509 = last; + pr_devel("sinfo %u: Root cert %u signer is key %x\n", + sinfo->index, x509->index, key_serial(key)); + goto matched; + } + if (PTR_ERR(key) != -ENOKEY) + return PTR_ERR(key); } - key = x509_request_asymmetric_key(trust_keyring, last->authority); - if (IS_ERR(key)) - return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY; - x509 = last; + /* As a last resort, see if we have a trusted public key that matches + * the signed info directly. + */ + key = x509_request_asymmetric_key(trust_keyring, + sinfo->signing_cert_id); + if (!IS_ERR(key)) { + pr_devel("sinfo %u: Direct signer is key %x\n", + sinfo->index, key_serial(key)); + x509 = NULL; + goto matched; + } + if (PTR_ERR(key) != -ENOKEY) + return PTR_ERR(key); + + kleave(" = -ENOKEY [no backref]"); + return -ENOKEY; matched: ret = verify_signature(key, sig); @@ -103,10 +125,12 @@ matched: } verified: - x509->verified = true; - for (p = sinfo->signer; p != x509; p = p->signer) { - p->verified = true; - p->trusted = trusted; + if (x509) { + x509->verified = true; + for (p = sinfo->signer; p != x509; p = p->signer) { + p->verified = true; + p->trusted = trusted; + } } sinfo->trusted = trusted; kleave(" = 0"); diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index bd264052f751..cd455450b069 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -154,10 +154,13 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, return 0; } - pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n", - sinfo->index, - sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); - return -ENOKEY; + /* The relevant X.509 cert isn't found here, but it might be found in + * the trust keyring. + */ + pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", + sinfo->index, + sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); + return 0; } /* @@ -275,11 +278,14 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, if (ret < 0) return ret; - /* Find the key for the signature */ + /* Find the key for the signature if there is one */ ret = pkcs7_find_key(pkcs7, sinfo); if (ret < 0) return ret; + if (!sinfo->signer) + return 0; + pr_devel("Using X.509[%u] for sig %u\n", sinfo->signer->index, sinfo->index); |