diff options
author | David Howells <dhowells@redhat.com> | 2014-09-16 12:36:17 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-09-16 12:36:17 -0400 |
commit | 757932e6da6de05b91cc4cb85493b17de48c2667 (patch) | |
tree | ad9bf9a2fa35fa4dbb1a4402f1c3d6b092fc7f28 /crypto | |
parent | 41559420003cfe99522257dded7793192c77b4e9 (diff) |
PKCS#7: Handle PKCS#7 messages that contain no X.509 certs
The X.509 certificate list in a PKCS#7 message is optional. To save space, we
can omit the inclusion of any X.509 certificates if we are sure that we can
look the relevant public key up by the serial number and issuer given in a
signed info block.
This also supports use of a signed info block for which we can't find a
matching X.509 cert in the certificate list, though it be populated.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
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, | |||
55 | * keys. | 55 | * keys. |
56 | */ | 56 | */ |
57 | key = x509_request_asymmetric_key(trust_keyring, x509->id); | 57 | key = x509_request_asymmetric_key(trust_keyring, x509->id); |
58 | if (!IS_ERR(key)) | 58 | if (!IS_ERR(key)) { |
59 | /* One of the X.509 certificates in the PKCS#7 message | 59 | /* One of the X.509 certificates in the PKCS#7 message |
60 | * is apparently the same as one we already trust. | 60 | * is apparently the same as one we already trust. |
61 | * Verify that the trusted variant can also validate | 61 | * Verify that the trusted variant can also validate |
62 | * the signature on the descendant. | 62 | * the signature on the descendant. |
63 | */ | 63 | */ |
64 | pr_devel("sinfo %u: Cert %u as key %x\n", | ||
65 | sinfo->index, x509->index, key_serial(key)); | ||
64 | goto matched; | 66 | goto matched; |
67 | } | ||
65 | if (key == ERR_PTR(-ENOMEM)) | 68 | if (key == ERR_PTR(-ENOMEM)) |
66 | return -ENOMEM; | 69 | return -ENOMEM; |
67 | 70 | ||
@@ -81,15 +84,34 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |||
81 | /* No match - see if the root certificate has a signer amongst the | 84 | /* No match - see if the root certificate has a signer amongst the |
82 | * trusted keys. | 85 | * trusted keys. |
83 | */ | 86 | */ |
84 | if (!last || !last->issuer || !last->authority) { | 87 | if (last && last->authority) { |
85 | kleave(" = -ENOKEY [no backref]"); | 88 | key = x509_request_asymmetric_key(trust_keyring, last->authority); |
86 | return -ENOKEY; | 89 | if (!IS_ERR(key)) { |
90 | x509 = last; | ||
91 | pr_devel("sinfo %u: Root cert %u signer is key %x\n", | ||
92 | sinfo->index, x509->index, key_serial(key)); | ||
93 | goto matched; | ||
94 | } | ||
95 | if (PTR_ERR(key) != -ENOKEY) | ||
96 | return PTR_ERR(key); | ||
87 | } | 97 | } |
88 | 98 | ||
89 | key = x509_request_asymmetric_key(trust_keyring, last->authority); | 99 | /* As a last resort, see if we have a trusted public key that matches |
90 | if (IS_ERR(key)) | 100 | * the signed info directly. |
91 | return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY; | 101 | */ |
92 | x509 = last; | 102 | key = x509_request_asymmetric_key(trust_keyring, |
103 | sinfo->signing_cert_id); | ||
104 | if (!IS_ERR(key)) { | ||
105 | pr_devel("sinfo %u: Direct signer is key %x\n", | ||
106 | sinfo->index, key_serial(key)); | ||
107 | x509 = NULL; | ||
108 | goto matched; | ||
109 | } | ||
110 | if (PTR_ERR(key) != -ENOKEY) | ||
111 | return PTR_ERR(key); | ||
112 | |||
113 | kleave(" = -ENOKEY [no backref]"); | ||
114 | return -ENOKEY; | ||
93 | 115 | ||
94 | matched: | 116 | matched: |
95 | ret = verify_signature(key, sig); | 117 | ret = verify_signature(key, sig); |
@@ -103,10 +125,12 @@ matched: | |||
103 | } | 125 | } |
104 | 126 | ||
105 | verified: | 127 | verified: |
106 | x509->verified = true; | 128 | if (x509) { |
107 | for (p = sinfo->signer; p != x509; p = p->signer) { | 129 | x509->verified = true; |
108 | p->verified = true; | 130 | for (p = sinfo->signer; p != x509; p = p->signer) { |
109 | p->trusted = trusted; | 131 | p->verified = true; |
132 | p->trusted = trusted; | ||
133 | } | ||
110 | } | 134 | } |
111 | sinfo->trusted = trusted; | 135 | sinfo->trusted = trusted; |
112 | kleave(" = 0"); | 136 | 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, | |||
154 | return 0; | 154 | return 0; |
155 | } | 155 | } |
156 | 156 | ||
157 | pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n", | 157 | /* The relevant X.509 cert isn't found here, but it might be found in |
158 | sinfo->index, | 158 | * the trust keyring. |
159 | sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); | 159 | */ |
160 | return -ENOKEY; | 160 | pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", |
161 | sinfo->index, | ||
162 | sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); | ||
163 | return 0; | ||
161 | } | 164 | } |
162 | 165 | ||
163 | /* | 166 | /* |
@@ -275,11 +278,14 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, | |||
275 | if (ret < 0) | 278 | if (ret < 0) |
276 | return ret; | 279 | return ret; |
277 | 280 | ||
278 | /* Find the key for the signature */ | 281 | /* Find the key for the signature if there is one */ |
279 | ret = pkcs7_find_key(pkcs7, sinfo); | 282 | ret = pkcs7_find_key(pkcs7, sinfo); |
280 | if (ret < 0) | 283 | if (ret < 0) |
281 | return ret; | 284 | return ret; |
282 | 285 | ||
286 | if (!sinfo->signer) | ||
287 | return 0; | ||
288 | |||
283 | pr_devel("Using X.509[%u] for sig %u\n", | 289 | pr_devel("Using X.509[%u] for sig %u\n", |
284 | sinfo->signer->index, sinfo->index); | 290 | sinfo->signer->index, sinfo->index); |
285 | 291 | ||