diff options
author | David Howells <dhowells@redhat.com> | 2014-07-01 11:40:19 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-07-08 08:50:11 -0400 |
commit | 8c76d79393ccc9b89d9af402d79a49a9cd43c5aa (patch) | |
tree | 482d70a25d548d0a82d08ac0bb9e2749b388d633 /crypto/asymmetric_keys | |
parent | a4730357ee724f8c64f0292541ba3da8a95510fb (diff) |
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 <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_verify.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 745e5c86a35e..51ff36f3a913 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c | |||
@@ -170,6 +170,91 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, | |||
170 | } | 170 | } |
171 | 171 | ||
172 | /* | 172 | /* |
173 | * Verify the internal certificate chain as best we can. | ||
174 | */ | ||
175 | static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | ||
176 | struct pkcs7_signed_info *sinfo) | ||
177 | { | ||
178 | struct x509_certificate *x509 = sinfo->signer, *p; | ||
179 | int ret; | ||
180 | |||
181 | kenter(""); | ||
182 | |||
183 | for (p = pkcs7->certs; p; p = p->next) | ||
184 | p->seen = false; | ||
185 | |||
186 | for (;;) { | ||
187 | pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint); | ||
188 | x509->seen = true; | ||
189 | ret = x509_get_sig_params(x509); | ||
190 | if (ret < 0) | ||
191 | return ret; | ||
192 | |||
193 | if (x509->issuer) | ||
194 | pr_debug("- issuer %s\n", x509->issuer); | ||
195 | if (x509->authority) | ||
196 | pr_debug("- authkeyid %s\n", x509->authority); | ||
197 | |||
198 | if (!x509->authority || | ||
199 | (x509->subject && | ||
200 | strcmp(x509->subject, x509->issuer) == 0)) { | ||
201 | /* If there's no authority certificate specified, then | ||
202 | * the certificate must be self-signed and is the root | ||
203 | * of the chain. Likewise if the cert is its own | ||
204 | * authority. | ||
205 | */ | ||
206 | pr_debug("- no auth?\n"); | ||
207 | if (x509->raw_subject_size != x509->raw_issuer_size || | ||
208 | memcmp(x509->raw_subject, x509->raw_issuer, | ||
209 | x509->raw_issuer_size) != 0) | ||
210 | return 0; | ||
211 | |||
212 | ret = x509_check_signature(x509->pub, x509); | ||
213 | if (ret < 0) | ||
214 | return ret; | ||
215 | x509->signer = x509; | ||
216 | pr_debug("- self-signed\n"); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /* Look through the X.509 certificates in the PKCS#7 message's | ||
221 | * list to see if the next one is there. | ||
222 | */ | ||
223 | pr_debug("- want %s\n", x509->authority); | ||
224 | for (p = pkcs7->certs; p; p = p->next) { | ||
225 | pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint); | ||
226 | if (p->raw_subject_size == x509->raw_issuer_size && | ||
227 | strcmp(p->fingerprint, x509->authority) == 0 && | ||
228 | memcmp(p->raw_subject, x509->raw_issuer, | ||
229 | x509->raw_issuer_size) == 0) | ||
230 | goto found_issuer; | ||
231 | } | ||
232 | |||
233 | /* We didn't find the root of this chain */ | ||
234 | pr_debug("- top\n"); | ||
235 | return 0; | ||
236 | |||
237 | found_issuer: | ||
238 | pr_debug("- issuer %s\n", p->subject); | ||
239 | if (p->seen) { | ||
240 | pr_warn("Sig %u: X.509 chain contains loop\n", | ||
241 | sinfo->index); | ||
242 | return 0; | ||
243 | } | ||
244 | ret = x509_check_signature(p->pub, x509); | ||
245 | if (ret < 0) | ||
246 | return ret; | ||
247 | x509->signer = p; | ||
248 | if (x509 == p) { | ||
249 | pr_debug("- self-signed\n"); | ||
250 | return 0; | ||
251 | } | ||
252 | x509 = p; | ||
253 | might_sleep(); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | /* | ||
173 | * Verify one signed information block from a PKCS#7 message. | 258 | * Verify one signed information block from a PKCS#7 message. |
174 | */ | 259 | */ |
175 | static int pkcs7_verify_one(struct pkcs7_message *pkcs7, | 260 | static int pkcs7_verify_one(struct pkcs7_message *pkcs7, |
@@ -201,7 +286,8 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, | |||
201 | 286 | ||
202 | pr_devel("Verified signature %u\n", sinfo->index); | 287 | pr_devel("Verified signature %u\n", sinfo->index); |
203 | 288 | ||
204 | return 0; | 289 | /* Verify the internal certificate chain */ |
290 | return pkcs7_verify_sig_chain(pkcs7, sinfo); | ||
205 | } | 291 | } |
206 | 292 | ||
207 | /** | 293 | /** |