From fc84fca31c2ca641329417d0afac2a3b71c6af01 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 15 Jan 2013 15:33:39 +0000 Subject: [PATCH] PKCS#7: Verify internal certificate chain Verify certificate chain in the X.509 certificates contained within the PKCS#7 message as far as possible. If any signature that we should be able to verify fails, we reject the whole lot. Signed-off-by: David Howells Reviewed-by: Kees Cook --- crypto/asymmetric_keys/pkcs7_verify.c | 67 ++++++++++++++++++++++++++- crypto/asymmetric_keys/x509_parser.h | 1 + 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 3f6f0e2b5ed5..b3774bdee63d 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -164,6 +164,70 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7) return -ENOKEY; } +/* + * Verify the internal certificate chain as best we can. + */ +static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7) +{ + struct x509_certificate *x509 = pkcs7->signer, *p; + int ret; + + kenter(""); + + for (;;) { + pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint); + ret = x509_get_sig_params(x509); + if (ret < 0) + return ret; + + if (x509->issuer) + pr_debug("- issuer %s\n", x509->issuer); + if (x509->authority) + pr_debug("- authkeyid %s\n", x509->authority); + + if (!x509->authority || + (x509->subject && + strcmp(x509->subject, x509->authority) == 0)) { + /* If there's no authority certificate specified, then + * the certificate must be self-signed and is the root + * of the chain. Likewise if the cert is its own + * authority. + */ + pr_debug("- no auth?\n"); + if (x509->raw_subject_size != x509->raw_issuer_size || + memcmp(x509->raw_subject, x509->raw_issuer, + x509->raw_issuer_size) != 0) + return 0; + + ret = x509_check_signature(x509->pub, x509); + if (ret < 0) + return ret; + x509->signer = x509; + pr_debug("- self-signed\n"); + return 0; + } + + for (p = pkcs7->certs; p; p = p->next) + if (!p->signer && + p->raw_subject_size == x509->raw_issuer_size && + strcmp(p->fingerprint, x509->authority) == 0 && + memcmp(p->raw_subject, x509->raw_issuer, + x509->raw_issuer_size) == 0) + goto found_issuer; + pr_debug("- top\n"); + return 0; + + found_issuer: + pr_debug("- issuer %s\n", p->subject); + ret = x509_check_signature(p->pub, x509); + if (ret < 0) + return ret; + x509->signer = p; + x509 = p; + might_sleep(); + } +} + /* * Verify a PKCS#7 message */ @@ -190,6 +254,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7) pr_devel("Verified signature\n"); - return 0; + /* Verify the internal certificate chain */ + return pkcs7_verify_sig_chain(pkcs7); } EXPORT_SYMBOL_GPL(pkcs7_verify); diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 6b1d87791be7..5e35fba21245 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -14,6 +14,7 @@ struct x509_certificate { struct x509_certificate *next; + const struct x509_certificate *signer; /* Certificate that signed this one */ struct public_key *pub; /* Public key details */ char *issuer; /* Name of certificate issuer */ char *subject; /* Name of certificate subject */ -- 2.39.5