diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 1288 |
1 files changed, 0 insertions, 1288 deletions
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c deleted file mode 100644 index f25e2b3f15..0000000000 --- a/src/lib/libcrypto/x509/x509_verify.c +++ /dev/null | |||
@@ -1,1288 +0,0 @@ | |||
1 | /* $OpenBSD: x509_verify.c,v 1.73 2025/02/08 10:12:00 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | /* x509_verify - inspired by golang's crypto/x509.Verify */ | ||
19 | |||
20 | #include <errno.h> | ||
21 | #include <stdio.h> | ||
22 | #include <string.h> | ||
23 | #include <time.h> | ||
24 | #include <unistd.h> | ||
25 | |||
26 | #include <openssl/safestack.h> | ||
27 | #include <openssl/x509.h> | ||
28 | #include <openssl/x509v3.h> | ||
29 | |||
30 | #include "asn1_local.h" | ||
31 | #include "x509_internal.h" | ||
32 | #include "x509_issuer_cache.h" | ||
33 | |||
34 | static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, | ||
35 | struct x509_verify_chain *current_chain); | ||
36 | static int x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, | ||
37 | char *name); | ||
38 | static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | ||
39 | struct x509_verify_chain *current_chain, int full_chain, char *name); | ||
40 | static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, | ||
41 | size_t depth, int error, int ok); | ||
42 | static void x509_verify_chain_free(struct x509_verify_chain *chain); | ||
43 | |||
44 | /* | ||
45 | * Parse an asn1 to a representable time_t as per RFC 5280 rules. | ||
46 | * Returns -1 if that can't be done for any reason. | ||
47 | */ | ||
48 | int | ||
49 | x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notAfter, | ||
50 | time_t *out) | ||
51 | { | ||
52 | struct tm tm = { 0 }; | ||
53 | int type; | ||
54 | |||
55 | if (atime == NULL) | ||
56 | return 0; | ||
57 | |||
58 | type = ASN1_time_parse(atime->data, atime->length, &tm, atime->type); | ||
59 | if (type == -1) | ||
60 | return 0; | ||
61 | |||
62 | /* RFC 5280 section 4.1.2.5 */ | ||
63 | if (tm.tm_year < 150 && type != V_ASN1_UTCTIME) | ||
64 | return 0; | ||
65 | if (tm.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME) | ||
66 | return 0; | ||
67 | |||
68 | if (notAfter) { | ||
69 | /* | ||
70 | * If we are a completely broken operating system with a | ||
71 | * 32 bit time_t, and we have been told this is a notAfter | ||
72 | * date, limit the date to a 32 bit representable value. | ||
73 | */ | ||
74 | if (!ASN1_time_tm_clamp_notafter(&tm)) | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Defensively fail if the time string is not representable as | ||
80 | * a time_t. A time_t must be sane if you care about times after | ||
81 | * Jan 19 2038. | ||
82 | */ | ||
83 | return asn1_time_tm_to_time_t(&tm, out); | ||
84 | } | ||
85 | |||
86 | struct x509_verify_chain * | ||
87 | x509_verify_chain_new(void) | ||
88 | { | ||
89 | struct x509_verify_chain *chain; | ||
90 | |||
91 | if ((chain = calloc(1, sizeof(*chain))) == NULL) | ||
92 | goto err; | ||
93 | if ((chain->certs = sk_X509_new_null()) == NULL) | ||
94 | goto err; | ||
95 | if ((chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS, | ||
96 | sizeof(int))) == NULL) | ||
97 | goto err; | ||
98 | if ((chain->names = | ||
99 | x509_constraints_names_new(X509_VERIFY_MAX_CHAIN_NAMES)) == NULL) | ||
100 | goto err; | ||
101 | |||
102 | return chain; | ||
103 | err: | ||
104 | x509_verify_chain_free(chain); | ||
105 | return NULL; | ||
106 | } | ||
107 | |||
108 | static void | ||
109 | x509_verify_chain_clear(struct x509_verify_chain *chain) | ||
110 | { | ||
111 | sk_X509_pop_free(chain->certs, X509_free); | ||
112 | chain->certs = NULL; | ||
113 | free(chain->cert_errors); | ||
114 | chain->cert_errors = NULL; | ||
115 | x509_constraints_names_free(chain->names); | ||
116 | chain->names = NULL; | ||
117 | } | ||
118 | |||
119 | static void | ||
120 | x509_verify_chain_free(struct x509_verify_chain *chain) | ||
121 | { | ||
122 | if (chain == NULL) | ||
123 | return; | ||
124 | x509_verify_chain_clear(chain); | ||
125 | free(chain); | ||
126 | } | ||
127 | |||
128 | static struct x509_verify_chain * | ||
129 | x509_verify_chain_dup(struct x509_verify_chain *chain) | ||
130 | { | ||
131 | struct x509_verify_chain *new_chain; | ||
132 | |||
133 | if ((new_chain = calloc(1, sizeof(*chain))) == NULL) | ||
134 | goto err; | ||
135 | if ((new_chain->certs = X509_chain_up_ref(chain->certs)) == NULL) | ||
136 | goto err; | ||
137 | if ((new_chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS, | ||
138 | sizeof(int))) == NULL) | ||
139 | goto err; | ||
140 | memcpy(new_chain->cert_errors, chain->cert_errors, | ||
141 | X509_VERIFY_MAX_CHAIN_CERTS * sizeof(int)); | ||
142 | if ((new_chain->names = | ||
143 | x509_constraints_names_dup(chain->names)) == NULL) | ||
144 | goto err; | ||
145 | return(new_chain); | ||
146 | err: | ||
147 | x509_verify_chain_free(new_chain); | ||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | static int | ||
152 | x509_verify_chain_append(struct x509_verify_chain *chain, X509 *cert, | ||
153 | int *error) | ||
154 | { | ||
155 | int verify_err = X509_V_ERR_UNSPECIFIED; | ||
156 | size_t idx; | ||
157 | |||
158 | if (!x509_constraints_extract_names(chain->names, cert, | ||
159 | sk_X509_num(chain->certs) == 0, &verify_err)) { | ||
160 | *error = verify_err; | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | X509_up_ref(cert); | ||
165 | if (!sk_X509_push(chain->certs, cert)) { | ||
166 | X509_free(cert); | ||
167 | *error = X509_V_ERR_OUT_OF_MEM; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | idx = sk_X509_num(chain->certs) - 1; | ||
172 | chain->cert_errors[idx] = *error; | ||
173 | |||
174 | /* | ||
175 | * We've just added the issuer for the previous certificate, | ||
176 | * clear its error if appropriate. | ||
177 | */ | ||
178 | if (idx > 1 && chain->cert_errors[idx - 1] == | ||
179 | X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) | ||
180 | chain->cert_errors[idx - 1] = X509_V_OK; | ||
181 | |||
182 | return 1; | ||
183 | } | ||
184 | |||
185 | static X509 * | ||
186 | x509_verify_chain_last(struct x509_verify_chain *chain) | ||
187 | { | ||
188 | int last; | ||
189 | |||
190 | if (chain->certs == NULL) | ||
191 | return NULL; | ||
192 | if ((last = sk_X509_num(chain->certs) - 1) < 0) | ||
193 | return NULL; | ||
194 | return sk_X509_value(chain->certs, last); | ||
195 | } | ||
196 | |||
197 | X509 * | ||
198 | x509_verify_chain_leaf(struct x509_verify_chain *chain) | ||
199 | { | ||
200 | if (chain->certs == NULL) | ||
201 | return NULL; | ||
202 | return sk_X509_value(chain->certs, 0); | ||
203 | } | ||
204 | |||
205 | static void | ||
206 | x509_verify_ctx_reset(struct x509_verify_ctx *ctx) | ||
207 | { | ||
208 | size_t i; | ||
209 | |||
210 | for (i = 0; i < ctx->chains_count; i++) | ||
211 | x509_verify_chain_free(ctx->chains[i]); | ||
212 | sk_X509_pop_free(ctx->saved_error_chain, X509_free); | ||
213 | ctx->saved_error = 0; | ||
214 | ctx->saved_error_depth = 0; | ||
215 | ctx->error = 0; | ||
216 | ctx->error_depth = 0; | ||
217 | ctx->chains_count = 0; | ||
218 | ctx->sig_checks = 0; | ||
219 | ctx->check_time = NULL; | ||
220 | } | ||
221 | |||
222 | static void | ||
223 | x509_verify_ctx_clear(struct x509_verify_ctx *ctx) | ||
224 | { | ||
225 | x509_verify_ctx_reset(ctx); | ||
226 | sk_X509_pop_free(ctx->intermediates, X509_free); | ||
227 | free(ctx->chains); | ||
228 | |||
229 | } | ||
230 | |||
231 | static int | ||
232 | x509_verify_cert_cache_extensions(X509 *cert) | ||
233 | { | ||
234 | return x509v3_cache_extensions(cert); | ||
235 | } | ||
236 | |||
237 | static int | ||
238 | x509_verify_cert_self_signed(X509 *cert) | ||
239 | { | ||
240 | return (cert->ex_flags & EXFLAG_SS) ? 1 : 0; | ||
241 | } | ||
242 | |||
243 | /* XXX beck - clean up this mess of is_root */ | ||
244 | static int | ||
245 | x509_verify_check_chain_end(X509 *cert, int full_chain) | ||
246 | { | ||
247 | if (full_chain) | ||
248 | return x509_verify_cert_self_signed(cert); | ||
249 | return 1; | ||
250 | } | ||
251 | |||
252 | static int | ||
253 | x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert, | ||
254 | int full_chain) | ||
255 | { | ||
256 | X509 *match = NULL; | ||
257 | int i; | ||
258 | |||
259 | if (!x509_verify_cert_cache_extensions(cert)) | ||
260 | return 0; | ||
261 | |||
262 | /* Check by lookup if we have a legacy xsc */ | ||
263 | if (ctx->xsc != NULL) { | ||
264 | /* | ||
265 | * "alternative" lookup method, using the "trusted" stack in the | ||
266 | * xsc as the source for roots. | ||
267 | */ | ||
268 | if (ctx->xsc->trusted != NULL) { | ||
269 | for (i = 0; i < sk_X509_num(ctx->xsc->trusted); i++) { | ||
270 | if (X509_cmp(sk_X509_value(ctx->xsc->trusted, | ||
271 | i), cert) == 0) | ||
272 | return x509_verify_check_chain_end(cert, | ||
273 | full_chain); | ||
274 | } | ||
275 | } | ||
276 | if ((match = x509_vfy_lookup_cert_match(ctx->xsc, | ||
277 | cert)) != NULL) { | ||
278 | X509_free(match); | ||
279 | return x509_verify_check_chain_end(cert, full_chain); | ||
280 | } | ||
281 | } else { | ||
282 | /* Check the provided roots */ | ||
283 | for (i = 0; i < sk_X509_num(ctx->roots); i++) { | ||
284 | if (X509_cmp(sk_X509_value(ctx->roots, i), cert) == 0) | ||
285 | return x509_verify_check_chain_end(cert, | ||
286 | full_chain); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int | ||
294 | x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, | ||
295 | struct x509_verify_chain *chain, int set_error, int is_trusted) | ||
296 | { | ||
297 | size_t num_untrusted; | ||
298 | int i; | ||
299 | |||
300 | if (ctx->xsc == NULL) | ||
301 | return 1; | ||
302 | |||
303 | /* | ||
304 | * XXX num_untrusted is the number of untrusted certs at the | ||
305 | * bottom of the chain. This works now since we stop at the first | ||
306 | * trusted cert. This will need fixing once we allow more than one | ||
307 | * trusted certificate. | ||
308 | */ | ||
309 | num_untrusted = sk_X509_num(chain->certs); | ||
310 | if (is_trusted && num_untrusted > 0) | ||
311 | num_untrusted--; | ||
312 | ctx->xsc->num_untrusted = num_untrusted; | ||
313 | |||
314 | sk_X509_pop_free(ctx->xsc->chain, X509_free); | ||
315 | ctx->xsc->chain = X509_chain_up_ref(chain->certs); | ||
316 | if (ctx->xsc->chain == NULL) | ||
317 | return x509_verify_cert_error(ctx, NULL, 0, | ||
318 | X509_V_ERR_OUT_OF_MEM, 0); | ||
319 | |||
320 | if (set_error) { | ||
321 | ctx->xsc->error = X509_V_OK; | ||
322 | ctx->xsc->error_depth = 0; | ||
323 | for (i = 0; i < sk_X509_num(chain->certs); i++) { | ||
324 | if (chain->cert_errors[i] != X509_V_OK) { | ||
325 | ctx->xsc->error = chain->cert_errors[i]; | ||
326 | ctx->xsc->error_depth = i; | ||
327 | break; | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | |||
332 | return 1; | ||
333 | } | ||
334 | |||
335 | |||
336 | /* | ||
337 | * Save the error state and unvalidated chain off of the xsc for | ||
338 | * later. | ||
339 | */ | ||
340 | static int | ||
341 | x509_verify_ctx_save_xsc_error(struct x509_verify_ctx *ctx) | ||
342 | { | ||
343 | if (ctx->xsc != NULL && ctx->xsc->chain != NULL) { | ||
344 | sk_X509_pop_free(ctx->saved_error_chain, X509_free); | ||
345 | ctx->saved_error_chain = X509_chain_up_ref(ctx->xsc->chain); | ||
346 | if (ctx->saved_error_chain == NULL) | ||
347 | return x509_verify_cert_error(ctx, NULL, 0, | ||
348 | X509_V_ERR_OUT_OF_MEM, 0); | ||
349 | ctx->saved_error = ctx->xsc->error; | ||
350 | ctx->saved_error_depth = ctx->xsc->error_depth; | ||
351 | } | ||
352 | return 1; | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Restore the saved error state and unvalidated chain to the xsc | ||
357 | * if we do not have a validated chain. | ||
358 | */ | ||
359 | static int | ||
360 | x509_verify_ctx_restore_xsc_error(struct x509_verify_ctx *ctx) | ||
361 | { | ||
362 | if (ctx->xsc != NULL && ctx->chains_count == 0 && | ||
363 | ctx->saved_error_chain != NULL) { | ||
364 | sk_X509_pop_free(ctx->xsc->chain, X509_free); | ||
365 | ctx->xsc->chain = X509_chain_up_ref(ctx->saved_error_chain); | ||
366 | if (ctx->xsc->chain == NULL) | ||
367 | return x509_verify_cert_error(ctx, NULL, 0, | ||
368 | X509_V_ERR_OUT_OF_MEM, 0); | ||
369 | ctx->xsc->error = ctx->saved_error; | ||
370 | ctx->xsc->error_depth = ctx->saved_error_depth; | ||
371 | } | ||
372 | return 1; | ||
373 | } | ||
374 | |||
375 | /* Perform legacy style validation of a chain */ | ||
376 | static int | ||
377 | x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx *ctx, | ||
378 | struct x509_verify_chain *chain, size_t depth) | ||
379 | { | ||
380 | int ret = 0, trust; | ||
381 | |||
382 | if (ctx->xsc == NULL) | ||
383 | return 1; | ||
384 | |||
385 | /* | ||
386 | * If we have a legacy xsc, choose a validated chain, and | ||
387 | * apply the extensions, revocation, and policy checks just | ||
388 | * like the legacy code did. We do this here instead of as | ||
389 | * building the chains to more easily support the callback and | ||
390 | * the bewildering array of VERIFY_PARAM knobs that are there | ||
391 | * for the fiddling. | ||
392 | */ | ||
393 | |||
394 | /* These may be set in one of the following calls. */ | ||
395 | ctx->xsc->error = X509_V_OK; | ||
396 | ctx->xsc->error_depth = 0; | ||
397 | |||
398 | if (!x509_verify_ctx_set_xsc_chain(ctx, chain, 0, 1)) | ||
399 | goto err; | ||
400 | |||
401 | /* | ||
402 | * Call the legacy code to walk the chain and check trust | ||
403 | * in the legacy way to handle partial chains and get the | ||
404 | * callback fired correctly. | ||
405 | */ | ||
406 | trust = x509_vfy_check_trust(ctx->xsc); | ||
407 | if (trust == X509_TRUST_REJECTED) | ||
408 | goto err; /* callback was called in x509_vfy_check_trust */ | ||
409 | if (trust != X509_TRUST_TRUSTED) { | ||
410 | /* NOTREACHED */ | ||
411 | goto err; /* should not happen if we get in here - abort? */ | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * XXX currently this duplicates some work done in chain | ||
416 | * build, but we keep it here until we have feature parity | ||
417 | */ | ||
418 | if (!x509_vfy_check_chain_extensions(ctx->xsc)) | ||
419 | goto err; | ||
420 | |||
421 | #ifndef OPENSSL_NO_RFC3779 | ||
422 | if (!X509v3_asid_validate_path(ctx->xsc)) | ||
423 | goto err; | ||
424 | |||
425 | if (!X509v3_addr_validate_path(ctx->xsc)) | ||
426 | goto err; | ||
427 | #endif | ||
428 | |||
429 | if (!x509_vfy_check_security_level(ctx->xsc)) | ||
430 | goto err; | ||
431 | |||
432 | if (!x509_constraints_chain(ctx->xsc->chain, | ||
433 | &ctx->xsc->error, &ctx->xsc->error_depth)) { | ||
434 | X509 *cert = sk_X509_value(ctx->xsc->chain, depth); | ||
435 | if (!x509_verify_cert_error(ctx, cert, | ||
436 | ctx->xsc->error_depth, ctx->xsc->error, 0)) | ||
437 | goto err; | ||
438 | } | ||
439 | |||
440 | if (!x509_vfy_check_revocation(ctx->xsc)) | ||
441 | goto err; | ||
442 | |||
443 | if (!x509_vfy_check_policy(ctx->xsc)) | ||
444 | goto err; | ||
445 | |||
446 | ret = 1; | ||
447 | |||
448 | err: | ||
449 | /* | ||
450 | * The above checks may have set ctx->xsc->error and | ||
451 | * ctx->xsc->error_depth - save these for later on. | ||
452 | */ | ||
453 | if (ctx->xsc->error != X509_V_OK) { | ||
454 | if (ctx->xsc->error_depth < 0 || | ||
455 | ctx->xsc->error_depth >= X509_VERIFY_MAX_CHAIN_CERTS) | ||
456 | return 0; | ||
457 | chain->cert_errors[ctx->xsc->error_depth] = | ||
458 | ctx->xsc->error; | ||
459 | ctx->error_depth = ctx->xsc->error_depth; | ||
460 | } | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | /* Add a validated chain to our list of valid chains */ | ||
466 | static int | ||
467 | x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, | ||
468 | struct x509_verify_chain *chain, char *name) | ||
469 | { | ||
470 | size_t depth; | ||
471 | X509 *last = x509_verify_chain_last(chain); | ||
472 | X509 *leaf = x509_verify_chain_leaf(chain); | ||
473 | |||
474 | depth = sk_X509_num(chain->certs); | ||
475 | if (depth > 0) | ||
476 | depth--; | ||
477 | |||
478 | if (ctx->chains_count >= ctx->max_chains) | ||
479 | return x509_verify_cert_error(ctx, last, depth, | ||
480 | X509_V_ERR_CERT_CHAIN_TOO_LONG, 0); | ||
481 | |||
482 | /* Clear a get issuer failure for a root certificate. */ | ||
483 | if (chain->cert_errors[depth] == | ||
484 | X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) | ||
485 | chain->cert_errors[depth] = X509_V_OK; | ||
486 | |||
487 | if (!x509_verify_ctx_validate_legacy_chain(ctx, chain, depth)) | ||
488 | return 0; | ||
489 | |||
490 | /* Verify the leaf certificate and store any resulting error. */ | ||
491 | if (!x509_verify_cert_valid(ctx, leaf, NULL)) | ||
492 | return 0; | ||
493 | if (!x509_verify_cert_hostname(ctx, leaf, name)) | ||
494 | return 0; | ||
495 | if (ctx->error_depth == 0 && | ||
496 | ctx->error != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) | ||
497 | chain->cert_errors[0] = ctx->error; | ||
498 | |||
499 | /* | ||
500 | * In the non-legacy code, extensions and purpose are dealt | ||
501 | * with as the chain is built. | ||
502 | * | ||
503 | * The non-legacy api returns multiple chains but does not do | ||
504 | * any revocation checking (it must be done by the caller on | ||
505 | * any chain they wish to use) | ||
506 | */ | ||
507 | |||
508 | if ((ctx->chains[ctx->chains_count] = x509_verify_chain_dup(chain)) == | ||
509 | NULL) { | ||
510 | return x509_verify_cert_error(ctx, last, depth, | ||
511 | X509_V_ERR_OUT_OF_MEM, 0); | ||
512 | } | ||
513 | ctx->chains_count++; | ||
514 | |||
515 | ctx->error = X509_V_OK; | ||
516 | ctx->error_depth = depth; | ||
517 | |||
518 | return 1; | ||
519 | } | ||
520 | |||
521 | static int | ||
522 | x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent, | ||
523 | X509 *child) | ||
524 | { | ||
525 | if (!x509_verify_cert_cache_extensions(parent)) | ||
526 | return 0; | ||
527 | if (ctx->xsc != NULL) | ||
528 | return (ctx->xsc->check_issued(ctx->xsc, child, parent)); | ||
529 | |||
530 | /* XXX key usage */ | ||
531 | return X509_check_issued(parent, child) == X509_V_OK; | ||
532 | } | ||
533 | |||
534 | /* Matches x509_crl_verify_parent_signature() */ | ||
535 | static int | ||
536 | x509_verify_parent_signature(X509 *parent, X509 *child, int *error) | ||
537 | { | ||
538 | EVP_PKEY *pkey; | ||
539 | int cached; | ||
540 | int ret = 0; | ||
541 | |||
542 | /* Use cached value if we have it */ | ||
543 | if ((cached = x509_issuer_cache_find(parent->hash, child->hash)) >= 0) { | ||
544 | if (cached == 0) | ||
545 | *error = X509_V_ERR_CERT_SIGNATURE_FAILURE; | ||
546 | return cached; | ||
547 | } | ||
548 | |||
549 | /* Check signature. Did parent sign child? */ | ||
550 | if ((pkey = X509_get0_pubkey(parent)) == NULL) { | ||
551 | *error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; | ||
552 | return 0; | ||
553 | } | ||
554 | if (X509_verify(child, pkey) <= 0) | ||
555 | *error = X509_V_ERR_CERT_SIGNATURE_FAILURE; | ||
556 | else | ||
557 | ret = 1; | ||
558 | |||
559 | /* Add result to cache */ | ||
560 | x509_issuer_cache_add(parent->hash, child->hash, ret); | ||
561 | |||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | static int | ||
566 | x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, | ||
567 | int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain, | ||
568 | int full_chain, char *name) | ||
569 | { | ||
570 | int depth = sk_X509_num(current_chain->certs); | ||
571 | struct x509_verify_chain *new_chain; | ||
572 | int i; | ||
573 | |||
574 | /* Fail if the certificate is already in the chain */ | ||
575 | for (i = 0; i < sk_X509_num(current_chain->certs); i++) { | ||
576 | if (X509_cmp(sk_X509_value(current_chain->certs, i), | ||
577 | candidate) == 0) | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | if (ctx->sig_checks++ > X509_VERIFY_MAX_SIGCHECKS) { | ||
582 | /* don't allow callback to override safety check */ | ||
583 | (void) x509_verify_cert_error(ctx, candidate, depth, | ||
584 | X509_V_ERR_CERT_CHAIN_TOO_LONG, 0); | ||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | if (!x509_verify_parent_signature(candidate, cert, &ctx->error)) { | ||
589 | if (!x509_verify_cert_error(ctx, candidate, depth, | ||
590 | ctx->error, 0)) | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | if (!x509_verify_cert_valid(ctx, candidate, current_chain)) | ||
595 | return 0; | ||
596 | |||
597 | /* candidate is good, add it to a copy of the current chain */ | ||
598 | if ((new_chain = x509_verify_chain_dup(current_chain)) == NULL) { | ||
599 | x509_verify_cert_error(ctx, candidate, depth, | ||
600 | X509_V_ERR_OUT_OF_MEM, 0); | ||
601 | return 0; | ||
602 | } | ||
603 | if (!x509_verify_chain_append(new_chain, candidate, &ctx->error)) { | ||
604 | x509_verify_cert_error(ctx, candidate, depth, ctx->error, 0); | ||
605 | x509_verify_chain_free(new_chain); | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * If candidate is a trusted root, we have a validated chain, | ||
611 | * so we save it. Otherwise, recurse until we find a root or | ||
612 | * give up. | ||
613 | */ | ||
614 | if (is_root_cert) { | ||
615 | if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain, 0, 1)) { | ||
616 | x509_verify_chain_free(new_chain); | ||
617 | return 0; | ||
618 | } | ||
619 | if (!x509_verify_ctx_add_chain(ctx, new_chain, name)) { | ||
620 | x509_verify_chain_free(new_chain); | ||
621 | return 0; | ||
622 | } | ||
623 | goto done; | ||
624 | } | ||
625 | |||
626 | x509_verify_build_chains(ctx, candidate, new_chain, full_chain, name); | ||
627 | |||
628 | done: | ||
629 | x509_verify_chain_free(new_chain); | ||
630 | return 1; | ||
631 | } | ||
632 | |||
633 | static int | ||
634 | x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth, | ||
635 | int error, int ok) | ||
636 | { | ||
637 | ctx->error = error; | ||
638 | ctx->error_depth = depth; | ||
639 | if (ctx->xsc != NULL) { | ||
640 | ctx->xsc->error = error; | ||
641 | ctx->xsc->error_depth = depth; | ||
642 | ctx->xsc->current_cert = cert; | ||
643 | return ctx->xsc->verify_cb(ok, ctx->xsc); | ||
644 | } | ||
645 | return ok; | ||
646 | } | ||
647 | |||
648 | static void | ||
649 | x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | ||
650 | struct x509_verify_chain *current_chain, int full_chain, char *name) | ||
651 | { | ||
652 | X509 *candidate; | ||
653 | int i, depth, count, ret, is_root; | ||
654 | |||
655 | /* | ||
656 | * If we are finding chains with an xsc, just stop after we have | ||
657 | * one chain, there's no point in finding more, it just exercises | ||
658 | * the potentially buggy callback processing in the calling software. | ||
659 | */ | ||
660 | if (ctx->xsc != NULL && ctx->chains_count > 0) | ||
661 | return; | ||
662 | |||
663 | depth = sk_X509_num(current_chain->certs); | ||
664 | if (depth > 0) | ||
665 | depth--; | ||
666 | |||
667 | if (depth >= ctx->max_depth && | ||
668 | !x509_verify_cert_error(ctx, cert, depth, | ||
669 | X509_V_ERR_CERT_CHAIN_TOO_LONG, 0)) | ||
670 | return; | ||
671 | |||
672 | count = ctx->chains_count; | ||
673 | |||
674 | ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; | ||
675 | ctx->error_depth = depth; | ||
676 | |||
677 | if (ctx->saved_error != 0) | ||
678 | ctx->error = ctx->saved_error; | ||
679 | if (ctx->saved_error_depth != 0) | ||
680 | ctx->error_depth = ctx->saved_error_depth; | ||
681 | |||
682 | if (ctx->xsc != NULL) { | ||
683 | /* | ||
684 | * Long ago experiments at Muppet labs resulted in a | ||
685 | * situation where software not only sees these errors | ||
686 | * but forced developers to expect them in certain cases. | ||
687 | * so we must mimic this awfulness for the legacy case. | ||
688 | */ | ||
689 | if (cert->ex_flags & EXFLAG_SS) | ||
690 | ctx->error = (depth == 0) ? | ||
691 | X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: | ||
692 | X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; | ||
693 | } | ||
694 | |||
695 | /* Check for legacy mode roots */ | ||
696 | if (ctx->xsc != NULL) { | ||
697 | if ((ret = ctx->xsc->get_issuer(&candidate, ctx->xsc, cert)) < 0) { | ||
698 | x509_verify_cert_error(ctx, cert, depth, | ||
699 | X509_V_ERR_STORE_LOOKUP, 0); | ||
700 | return; | ||
701 | } | ||
702 | if (ret > 0) { | ||
703 | if (x509_verify_potential_parent(ctx, candidate, cert)) { | ||
704 | is_root = x509_verify_check_chain_end(candidate, | ||
705 | full_chain); | ||
706 | x509_verify_consider_candidate(ctx, cert, | ||
707 | is_root, candidate, current_chain, | ||
708 | full_chain, name); | ||
709 | } | ||
710 | X509_free(candidate); | ||
711 | } | ||
712 | } else { | ||
713 | /* Check to see if we have a trusted root issuer. */ | ||
714 | for (i = 0; i < sk_X509_num(ctx->roots); i++) { | ||
715 | candidate = sk_X509_value(ctx->roots, i); | ||
716 | if (x509_verify_potential_parent(ctx, candidate, cert)) { | ||
717 | is_root = x509_verify_check_chain_end(candidate, | ||
718 | full_chain); | ||
719 | x509_verify_consider_candidate(ctx, cert, | ||
720 | is_root, candidate, current_chain, | ||
721 | full_chain, name); | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | |||
726 | /* Check intermediates after checking roots */ | ||
727 | if (ctx->intermediates != NULL) { | ||
728 | for (i = 0; i < sk_X509_num(ctx->intermediates); i++) { | ||
729 | candidate = sk_X509_value(ctx->intermediates, i); | ||
730 | if (x509_verify_potential_parent(ctx, candidate, cert)) { | ||
731 | x509_verify_consider_candidate(ctx, cert, | ||
732 | 0, candidate, current_chain, | ||
733 | full_chain, name); | ||
734 | } | ||
735 | } | ||
736 | } | ||
737 | |||
738 | if (ctx->chains_count > count) { | ||
739 | if (ctx->xsc != NULL) { | ||
740 | ctx->xsc->error = X509_V_OK; | ||
741 | ctx->xsc->error_depth = depth; | ||
742 | ctx->xsc->current_cert = cert; | ||
743 | } | ||
744 | } else if (ctx->error_depth == depth) { | ||
745 | if (!x509_verify_ctx_set_xsc_chain(ctx, current_chain, 0, 0)) | ||
746 | return; | ||
747 | } | ||
748 | } | ||
749 | |||
750 | static int | ||
751 | x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, char *name) | ||
752 | { | ||
753 | char *candidate; | ||
754 | size_t len; | ||
755 | |||
756 | if (name == NULL) { | ||
757 | if (ctx->xsc != NULL) { | ||
758 | int ret; | ||
759 | |||
760 | if ((ret = x509_vfy_check_id(ctx->xsc)) == 0) | ||
761 | ctx->error = ctx->xsc->error; | ||
762 | return ret; | ||
763 | } | ||
764 | return 1; | ||
765 | } | ||
766 | if ((candidate = strdup(name)) == NULL) { | ||
767 | ctx->error = X509_V_ERR_OUT_OF_MEM; | ||
768 | goto err; | ||
769 | } | ||
770 | if ((len = strlen(candidate)) < 1) { | ||
771 | ctx->error = X509_V_ERR_UNSPECIFIED; /* XXX */ | ||
772 | goto err; | ||
773 | } | ||
774 | |||
775 | /* IP addresses may be written in [ ]. */ | ||
776 | if (candidate[0] == '[' && candidate[len - 1] == ']') { | ||
777 | candidate[len - 1] = '\0'; | ||
778 | if (X509_check_ip_asc(cert, candidate + 1, 0) <= 0) { | ||
779 | ctx->error = X509_V_ERR_IP_ADDRESS_MISMATCH; | ||
780 | goto err; | ||
781 | } | ||
782 | } else { | ||
783 | int flags = 0; | ||
784 | |||
785 | if (ctx->xsc == NULL) | ||
786 | flags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; | ||
787 | |||
788 | if (X509_check_host(cert, candidate, len, flags, NULL) <= 0) { | ||
789 | ctx->error = X509_V_ERR_HOSTNAME_MISMATCH; | ||
790 | goto err; | ||
791 | } | ||
792 | } | ||
793 | free(candidate); | ||
794 | return 1; | ||
795 | err: | ||
796 | free(candidate); | ||
797 | return x509_verify_cert_error(ctx, cert, 0, ctx->error, 0); | ||
798 | } | ||
799 | |||
800 | static int | ||
801 | x509_verify_set_check_time(struct x509_verify_ctx *ctx) | ||
802 | { | ||
803 | if (ctx->xsc != NULL) { | ||
804 | if (ctx->xsc->param->flags & X509_V_FLAG_USE_CHECK_TIME) { | ||
805 | ctx->check_time = &ctx->xsc->param->check_time; | ||
806 | return 1; | ||
807 | } | ||
808 | if (ctx->xsc->param->flags & X509_V_FLAG_NO_CHECK_TIME) | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | ctx->check_time = NULL; | ||
813 | return 1; | ||
814 | } | ||
815 | |||
816 | static int | ||
817 | x509_verify_cert_times(X509 *cert, time_t *cmp_time, int *error) | ||
818 | { | ||
819 | time_t when, not_before, not_after; | ||
820 | |||
821 | if (cmp_time == NULL) | ||
822 | when = time(NULL); | ||
823 | else | ||
824 | when = *cmp_time; | ||
825 | |||
826 | if (!x509_verify_asn1_time_to_time_t(X509_get_notBefore(cert), 0, | ||
827 | ¬_before)) { | ||
828 | *error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; | ||
829 | return 0; | ||
830 | } | ||
831 | if (when < not_before) { | ||
832 | *error = X509_V_ERR_CERT_NOT_YET_VALID; | ||
833 | return 0; | ||
834 | } | ||
835 | if (!x509_verify_asn1_time_to_time_t(X509_get_notAfter(cert), 1, | ||
836 | ¬_after)) { | ||
837 | *error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; | ||
838 | return 0; | ||
839 | } | ||
840 | if (when > not_after) { | ||
841 | *error = X509_V_ERR_CERT_HAS_EXPIRED; | ||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | return 1; | ||
846 | } | ||
847 | |||
848 | static int | ||
849 | x509_verify_validate_constraints(X509 *cert, | ||
850 | struct x509_verify_chain *current_chain, int *error) | ||
851 | { | ||
852 | struct x509_constraints_names *excluded = NULL; | ||
853 | struct x509_constraints_names *permitted = NULL; | ||
854 | int err = X509_V_ERR_UNSPECIFIED; | ||
855 | |||
856 | if (current_chain == NULL) | ||
857 | return 1; | ||
858 | |||
859 | if (cert->nc != NULL) { | ||
860 | if ((permitted = x509_constraints_names_new( | ||
861 | X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) { | ||
862 | err = X509_V_ERR_OUT_OF_MEM; | ||
863 | goto err; | ||
864 | } | ||
865 | if ((excluded = x509_constraints_names_new( | ||
866 | X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) { | ||
867 | err = X509_V_ERR_OUT_OF_MEM; | ||
868 | goto err; | ||
869 | } | ||
870 | if (!x509_constraints_extract_constraints(cert, | ||
871 | permitted, excluded, &err)) | ||
872 | goto err; | ||
873 | if (!x509_constraints_check(current_chain->names, | ||
874 | permitted, excluded, &err)) | ||
875 | goto err; | ||
876 | x509_constraints_names_free(excluded); | ||
877 | x509_constraints_names_free(permitted); | ||
878 | } | ||
879 | |||
880 | return 1; | ||
881 | err: | ||
882 | *error = err; | ||
883 | x509_constraints_names_free(excluded); | ||
884 | x509_constraints_names_free(permitted); | ||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | static int | ||
889 | x509_verify_cert_extensions(struct x509_verify_ctx *ctx, X509 *cert, int need_ca) | ||
890 | { | ||
891 | if (!x509_verify_cert_cache_extensions(cert)) { | ||
892 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
893 | return 0; | ||
894 | } | ||
895 | |||
896 | if (ctx->xsc != NULL) | ||
897 | return 1; /* legacy is checked after chain is built */ | ||
898 | |||
899 | if (cert->ex_flags & EXFLAG_CRITICAL) { | ||
900 | ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; | ||
901 | return 0; | ||
902 | } | ||
903 | /* No we don't care about v1, netscape, and other ancient silliness */ | ||
904 | if (need_ca && (!(cert->ex_flags & EXFLAG_BCONS) && | ||
905 | (cert->ex_flags & EXFLAG_CA))) { | ||
906 | ctx->error = X509_V_ERR_INVALID_CA; | ||
907 | return 0; | ||
908 | } | ||
909 | if (ctx->purpose > 0 && X509_check_purpose(cert, ctx->purpose, need_ca)) { | ||
910 | ctx->error = X509_V_ERR_INVALID_PURPOSE; | ||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | return 1; | ||
915 | } | ||
916 | |||
917 | /* Validate that cert is a possible candidate to append to current_chain */ | ||
918 | static int | ||
919 | x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, | ||
920 | struct x509_verify_chain *current_chain) | ||
921 | { | ||
922 | X509 *issuer_candidate; | ||
923 | int should_be_ca = current_chain != NULL; | ||
924 | size_t depth = 0; | ||
925 | |||
926 | if (current_chain != NULL) | ||
927 | depth = sk_X509_num(current_chain->certs); | ||
928 | |||
929 | if (!x509_verify_cert_extensions(ctx, cert, should_be_ca)) | ||
930 | return 0; | ||
931 | |||
932 | if (should_be_ca) { | ||
933 | issuer_candidate = x509_verify_chain_last(current_chain); | ||
934 | if (issuer_candidate != NULL && | ||
935 | !X509_check_issued(issuer_candidate, cert)) | ||
936 | if (!x509_verify_cert_error(ctx, cert, depth, | ||
937 | X509_V_ERR_SUBJECT_ISSUER_MISMATCH, 0)) | ||
938 | return 0; | ||
939 | } | ||
940 | |||
941 | if (x509_verify_set_check_time(ctx)) { | ||
942 | if (!x509_verify_cert_times(cert, ctx->check_time, | ||
943 | &ctx->error)) { | ||
944 | if (!x509_verify_cert_error(ctx, cert, depth, | ||
945 | ctx->error, 0)) | ||
946 | return 0; | ||
947 | } | ||
948 | } | ||
949 | |||
950 | if (!x509_verify_validate_constraints(cert, current_chain, | ||
951 | &ctx->error) && !x509_verify_cert_error(ctx, cert, depth, | ||
952 | ctx->error, 0)) | ||
953 | return 0; | ||
954 | |||
955 | return 1; | ||
956 | } | ||
957 | |||
958 | struct x509_verify_ctx * | ||
959 | x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc) | ||
960 | { | ||
961 | struct x509_verify_ctx *ctx; | ||
962 | size_t max_depth; | ||
963 | |||
964 | if (xsc == NULL) | ||
965 | return NULL; | ||
966 | |||
967 | if ((ctx = x509_verify_ctx_new(NULL)) == NULL) | ||
968 | return NULL; | ||
969 | |||
970 | ctx->xsc = xsc; | ||
971 | |||
972 | if (xsc->untrusted && | ||
973 | (ctx->intermediates = X509_chain_up_ref(xsc->untrusted)) == NULL) | ||
974 | goto err; | ||
975 | |||
976 | max_depth = X509_VERIFY_MAX_CHAIN_CERTS; | ||
977 | if (xsc->param->depth > 0 && xsc->param->depth < X509_VERIFY_MAX_CHAIN_CERTS) | ||
978 | max_depth = xsc->param->depth; | ||
979 | if (!x509_verify_ctx_set_max_depth(ctx, max_depth)) | ||
980 | goto err; | ||
981 | |||
982 | return ctx; | ||
983 | err: | ||
984 | x509_verify_ctx_free(ctx); | ||
985 | return NULL; | ||
986 | } | ||
987 | |||
988 | /* Public API */ | ||
989 | |||
990 | struct x509_verify_ctx * | ||
991 | x509_verify_ctx_new(STACK_OF(X509) *roots) | ||
992 | { | ||
993 | struct x509_verify_ctx *ctx; | ||
994 | |||
995 | if ((ctx = calloc(1, sizeof(struct x509_verify_ctx))) == NULL) | ||
996 | return NULL; | ||
997 | |||
998 | if (roots != NULL) { | ||
999 | if ((ctx->roots = X509_chain_up_ref(roots)) == NULL) | ||
1000 | goto err; | ||
1001 | } else { | ||
1002 | if ((ctx->roots = sk_X509_new_null()) == NULL) | ||
1003 | goto err; | ||
1004 | } | ||
1005 | |||
1006 | ctx->max_depth = X509_VERIFY_MAX_CHAIN_CERTS; | ||
1007 | ctx->max_chains = X509_VERIFY_MAX_CHAINS; | ||
1008 | ctx->max_sigs = X509_VERIFY_MAX_SIGCHECKS; | ||
1009 | |||
1010 | if ((ctx->chains = calloc(X509_VERIFY_MAX_CHAINS, | ||
1011 | sizeof(*ctx->chains))) == NULL) | ||
1012 | goto err; | ||
1013 | |||
1014 | return ctx; | ||
1015 | err: | ||
1016 | x509_verify_ctx_free(ctx); | ||
1017 | return NULL; | ||
1018 | } | ||
1019 | |||
1020 | void | ||
1021 | x509_verify_ctx_free(struct x509_verify_ctx *ctx) | ||
1022 | { | ||
1023 | if (ctx == NULL) | ||
1024 | return; | ||
1025 | sk_X509_pop_free(ctx->roots, X509_free); | ||
1026 | x509_verify_ctx_clear(ctx); | ||
1027 | free(ctx); | ||
1028 | } | ||
1029 | |||
1030 | int | ||
1031 | x509_verify_ctx_set_max_depth(struct x509_verify_ctx *ctx, size_t max) | ||
1032 | { | ||
1033 | if (max < 1 || max > X509_VERIFY_MAX_CHAIN_CERTS) | ||
1034 | return 0; | ||
1035 | ctx->max_depth = max; | ||
1036 | return 1; | ||
1037 | } | ||
1038 | |||
1039 | int | ||
1040 | x509_verify_ctx_set_max_chains(struct x509_verify_ctx *ctx, size_t max) | ||
1041 | { | ||
1042 | if (max < 1 || max > X509_VERIFY_MAX_CHAINS) | ||
1043 | return 0; | ||
1044 | ctx->max_chains = max; | ||
1045 | return 1; | ||
1046 | } | ||
1047 | |||
1048 | int | ||
1049 | x509_verify_ctx_set_max_signatures(struct x509_verify_ctx *ctx, size_t max) | ||
1050 | { | ||
1051 | if (max < 1 || max > 100000) | ||
1052 | return 0; | ||
1053 | ctx->max_sigs = max; | ||
1054 | return 1; | ||
1055 | } | ||
1056 | |||
1057 | int | ||
1058 | x509_verify_ctx_set_purpose(struct x509_verify_ctx *ctx, int purpose) | ||
1059 | { | ||
1060 | if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX) | ||
1061 | return 0; | ||
1062 | ctx->purpose = purpose; | ||
1063 | return 1; | ||
1064 | } | ||
1065 | |||
1066 | int | ||
1067 | x509_verify_ctx_set_intermediates(struct x509_verify_ctx *ctx, | ||
1068 | STACK_OF(X509) *intermediates) | ||
1069 | { | ||
1070 | if ((ctx->intermediates = X509_chain_up_ref(intermediates)) == NULL) | ||
1071 | return 0; | ||
1072 | return 1; | ||
1073 | } | ||
1074 | |||
1075 | const char * | ||
1076 | x509_verify_ctx_error_string(struct x509_verify_ctx *ctx) | ||
1077 | { | ||
1078 | return X509_verify_cert_error_string(ctx->error); | ||
1079 | } | ||
1080 | |||
1081 | size_t | ||
1082 | x509_verify_ctx_error_depth(struct x509_verify_ctx *ctx) | ||
1083 | { | ||
1084 | return ctx->error_depth; | ||
1085 | } | ||
1086 | |||
1087 | STACK_OF(X509) * | ||
1088 | x509_verify_ctx_chain(struct x509_verify_ctx *ctx, size_t i) | ||
1089 | { | ||
1090 | if (i >= ctx->chains_count) | ||
1091 | return NULL; | ||
1092 | return ctx->chains[i]->certs; | ||
1093 | } | ||
1094 | |||
1095 | size_t | ||
1096 | x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) | ||
1097 | { | ||
1098 | struct x509_verify_chain *current_chain; | ||
1099 | int retry_chain_build, full_chain = 0; | ||
1100 | |||
1101 | if (ctx->roots == NULL || ctx->max_depth == 0) { | ||
1102 | ctx->error = X509_V_ERR_INVALID_CALL; | ||
1103 | goto err; | ||
1104 | } | ||
1105 | |||
1106 | if (ctx->xsc != NULL) { | ||
1107 | if (leaf != NULL || name != NULL) { | ||
1108 | ctx->error = X509_V_ERR_INVALID_CALL; | ||
1109 | goto err; | ||
1110 | } | ||
1111 | leaf = ctx->xsc->cert; | ||
1112 | |||
1113 | /* XXX */ | ||
1114 | full_chain = 1; | ||
1115 | if (ctx->xsc->param->flags & X509_V_FLAG_PARTIAL_CHAIN) | ||
1116 | full_chain = 0; | ||
1117 | /* | ||
1118 | * XXX | ||
1119 | * The legacy code expects the top level cert to be | ||
1120 | * there, even if we didn't find a chain. So put it | ||
1121 | * there, we will clobber it later if we find a valid | ||
1122 | * chain. | ||
1123 | */ | ||
1124 | if ((ctx->xsc->chain = sk_X509_new_null()) == NULL) { | ||
1125 | ctx->error = X509_V_ERR_OUT_OF_MEM; | ||
1126 | goto err; | ||
1127 | } | ||
1128 | if (!X509_up_ref(leaf)) { | ||
1129 | ctx->error = X509_V_ERR_OUT_OF_MEM; | ||
1130 | goto err; | ||
1131 | } | ||
1132 | if (!sk_X509_push(ctx->xsc->chain, leaf)) { | ||
1133 | X509_free(leaf); | ||
1134 | ctx->error = X509_V_ERR_OUT_OF_MEM; | ||
1135 | goto err; | ||
1136 | } | ||
1137 | ctx->xsc->error_depth = 0; | ||
1138 | ctx->xsc->current_cert = leaf; | ||
1139 | } | ||
1140 | |||
1141 | if ((current_chain = x509_verify_chain_new()) == NULL) { | ||
1142 | ctx->error = X509_V_ERR_OUT_OF_MEM; | ||
1143 | goto err; | ||
1144 | } | ||
1145 | |||
1146 | /* | ||
1147 | * Add the leaf to the chain and try to build chains from it. | ||
1148 | * Note that unlike Go's verifier, we have not yet checked | ||
1149 | * anything about the leaf, This is intentional, so that we | ||
1150 | * report failures in chain building before we report problems | ||
1151 | * with the leaf. | ||
1152 | */ | ||
1153 | if (!x509_verify_chain_append(current_chain, leaf, &ctx->error)) { | ||
1154 | x509_verify_chain_free(current_chain); | ||
1155 | goto err; | ||
1156 | } | ||
1157 | do { | ||
1158 | retry_chain_build = 0; | ||
1159 | if (x509_verify_ctx_cert_is_root(ctx, leaf, full_chain)) { | ||
1160 | if (!x509_verify_ctx_add_chain(ctx, current_chain, | ||
1161 | name)) { | ||
1162 | x509_verify_chain_free(current_chain); | ||
1163 | goto err; | ||
1164 | } | ||
1165 | } else { | ||
1166 | x509_verify_build_chains(ctx, leaf, current_chain, | ||
1167 | full_chain, name); | ||
1168 | if (full_chain && ctx->chains_count == 0) { | ||
1169 | /* | ||
1170 | * Save the error state from the xsc | ||
1171 | * at this point to put back on the | ||
1172 | * xsc in case we do not find a chain | ||
1173 | * that is trusted but not a full | ||
1174 | * chain to a self signed root. This | ||
1175 | * is because the unvalidated chain is | ||
1176 | * used by the autochain batshittery | ||
1177 | * on failure and will be needed for | ||
1178 | * that. | ||
1179 | */ | ||
1180 | ctx->xsc->error_depth = ctx->error_depth; | ||
1181 | if (!x509_verify_ctx_save_xsc_error(ctx)) { | ||
1182 | x509_verify_chain_free(current_chain); | ||
1183 | goto err; | ||
1184 | } | ||
1185 | full_chain = 0; | ||
1186 | retry_chain_build = 1; | ||
1187 | } | ||
1188 | } | ||
1189 | } while (retry_chain_build); | ||
1190 | |||
1191 | x509_verify_chain_free(current_chain); | ||
1192 | |||
1193 | /* | ||
1194 | * Do the new verifier style return, where we don't have an xsc | ||
1195 | * that allows a crazy callback to turn invalid things into valid. | ||
1196 | */ | ||
1197 | if (ctx->xsc == NULL) { | ||
1198 | /* | ||
1199 | * Safety net: | ||
1200 | * We could not find a validated chain, and for some reason do not | ||
1201 | * have an error set. | ||
1202 | */ | ||
1203 | if (ctx->chains_count == 0 && ctx->error == X509_V_OK) | ||
1204 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
1205 | |||
1206 | /* | ||
1207 | * If we are not using an xsc, and have no possibility for the | ||
1208 | * crazy OpenSSL callback API changing the results of | ||
1209 | * validation steps (because the callback can make validation | ||
1210 | * proceed in the presence of invalid certs), any chains we | ||
1211 | * have here are correctly built and verified. | ||
1212 | */ | ||
1213 | if (ctx->chains_count > 0) | ||
1214 | ctx->error = X509_V_OK; | ||
1215 | |||
1216 | return ctx->chains_count; | ||
1217 | } | ||
1218 | |||
1219 | /* | ||
1220 | * Otherwise we are doing compatibility with an xsc, which means that we | ||
1221 | * will have one chain, which might actually be a bogus chain because | ||
1222 | * the callback told us to ignore errors and proceed to build an invalid | ||
1223 | * chain. Possible return values from this include returning 1 with an | ||
1224 | * invalid chain and a value of xsc->error != X509_V_OK (It's tradition | ||
1225 | * that makes it ok). | ||
1226 | */ | ||
1227 | |||
1228 | if (ctx->chains_count > 0) { | ||
1229 | /* | ||
1230 | * The chain we have using an xsc might not be a verified chain | ||
1231 | * if the callback perverted things while we built it to ignore | ||
1232 | * failures and proceed with chain building. We put this chain | ||
1233 | * and the error associated with it on the xsc. | ||
1234 | */ | ||
1235 | if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1, 1)) | ||
1236 | goto err; | ||
1237 | |||
1238 | /* | ||
1239 | * Call the callback for completion up our built | ||
1240 | * chain. The callback could still tell us to | ||
1241 | * fail. Since this chain might exist as the result of | ||
1242 | * callback doing perversions, we could still return | ||
1243 | * "success" with something other than X509_V_OK set | ||
1244 | * as the error. | ||
1245 | */ | ||
1246 | if (!x509_vfy_callback_indicate_completion(ctx->xsc)) | ||
1247 | goto err; | ||
1248 | } else { | ||
1249 | /* | ||
1250 | * We did not find a chain. Bring back the failure | ||
1251 | * case we wanted to the xsc if we saved one. If we | ||
1252 | * did not we should have just the leaf on the xsc. | ||
1253 | */ | ||
1254 | if (!x509_verify_ctx_restore_xsc_error(ctx)) | ||
1255 | goto err; | ||
1256 | |||
1257 | /* | ||
1258 | * Safety net, ensure we have an error set in the | ||
1259 | * failing case. | ||
1260 | */ | ||
1261 | if (ctx->xsc->error == X509_V_OK) { | ||
1262 | if (ctx->error == X509_V_OK) | ||
1263 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
1264 | ctx->xsc->error = ctx->error; | ||
1265 | } | ||
1266 | |||
1267 | /* | ||
1268 | * Let the callback override the return value | ||
1269 | * at depth 0 if it chooses to | ||
1270 | */ | ||
1271 | return ctx->xsc->verify_cb(0, ctx->xsc); | ||
1272 | } | ||
1273 | |||
1274 | /* We only ever find one chain in compat mode with an xsc. */ | ||
1275 | return 1; | ||
1276 | |||
1277 | err: | ||
1278 | if (ctx->error == X509_V_OK) | ||
1279 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
1280 | |||
1281 | if (ctx->xsc != NULL) { | ||
1282 | if (ctx->xsc->error == X509_V_OK) | ||
1283 | ctx->xsc->error = X509_V_ERR_UNSPECIFIED; | ||
1284 | ctx->error = ctx->xsc->error; | ||
1285 | } | ||
1286 | |||
1287 | return 0; | ||
1288 | } | ||