| From 971b42c038dc83e3327872d294fe7131bab152fc Mon Sep 17 00:00:00 2001 |
| From: Eric Biggers <ebiggers@google.com> |
| Date: Thu, 22 Feb 2018 14:38:33 +0000 |
| Subject: PKCS#7: fix certificate chain verification |
| |
| From: Eric Biggers <ebiggers@google.com> |
| |
| commit 971b42c038dc83e3327872d294fe7131bab152fc upstream. |
| |
| When pkcs7_verify_sig_chain() is building the certificate chain for a |
| SignerInfo using the certificates in the PKCS#7 message, it is passing |
| the wrong arguments to public_key_verify_signature(). Consequently, |
| when the next certificate is supposed to be used to verify the previous |
| certificate, the next certificate is actually used to verify itself. |
| |
| An attacker can use this bug to create a bogus certificate chain that |
| has no cryptographic relationship between the beginning and end. |
| |
| Fortunately I couldn't quite find a way to use this to bypass the |
| overall signature verification, though it comes very close. Here's the |
| reasoning: due to the bug, every certificate in the chain beyond the |
| first actually has to be self-signed (where "self-signed" here refers to |
| the actual key and signature; an attacker might still manipulate the |
| certificate fields such that the self_signed flag doesn't actually get |
| set, and thus the chain doesn't end immediately). But to pass trust |
| validation (pkcs7_validate_trust()), either the SignerInfo or one of the |
| certificates has to actually be signed by a trusted key. Since only |
| self-signed certificates can be added to the chain, the only way for an |
| attacker to introduce a trusted signature is to include a self-signed |
| trusted certificate. |
| |
| But, when pkcs7_validate_trust_one() reaches that certificate, instead |
| of trying to verify the signature on that certificate, it will actually |
| look up the corresponding trusted key, which will succeed, and then try |
| to verify the *previous* certificate, which will fail. Thus, disaster |
| is narrowly averted (as far as I could tell). |
| |
| Fixes: 6c2dc5ae4ab7 ("X.509: Extract signature digest and make self-signed cert checks earlier") |
| Cc: <stable@vger.kernel.org> # v4.7+ |
| Signed-off-by: Eric Biggers <ebiggers@google.com> |
| Signed-off-by: David Howells <dhowells@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| crypto/asymmetric_keys/pkcs7_verify.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/crypto/asymmetric_keys/pkcs7_verify.c |
| +++ b/crypto/asymmetric_keys/pkcs7_verify.c |
| @@ -270,7 +270,7 @@ static int pkcs7_verify_sig_chain(struct |
| sinfo->index); |
| return 0; |
| } |
| - ret = public_key_verify_signature(p->pub, p->sig); |
| + ret = public_key_verify_signature(p->pub, x509->sig); |
| if (ret < 0) |
| return ret; |
| x509->signer = p; |