diff options
author | beck <> | 2022-06-25 20:01:43 +0000 |
---|---|---|
committer | beck <> | 2022-06-25 20:01:43 +0000 |
commit | 8f49e18d8b58138d52d4c7d55385ef2f47508529 (patch) | |
tree | a057ee19ce4f7b27f7b8864ab578d7746ac590e9 /src/lib | |
parent | 45d168a6140632da2ca76c8437622ccf56118001 (diff) | |
download | openbsd-8f49e18d8b58138d52d4c7d55385ef2f47508529.tar.gz openbsd-8f49e18d8b58138d52d4c7d55385ef2f47508529.tar.bz2 openbsd-8f49e18d8b58138d52d4c7d55385ef2f47508529.zip |
Move leaf certificate checks to the last thing after chain validation.
While seemingly illogical and not what is done in Go's validator, this
mimics OpenSSL's behavior so that callback overrides for the expiry of
a certificate will not "sticky" override a failure to build a chain.
ok jsing@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c index 630c9f9b5a..f6959d1f3a 100644 --- a/src/lib/libcrypto/x509/x509_verify.c +++ b/src/lib/libcrypto/x509/x509_verify.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_verify.c,v 1.55 2022/04/12 10:42:35 tb Exp $ */ | 1 | /* $OpenBSD: x509_verify.c,v 1.56 2022/06/25 20:01:43 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org> |
4 | * | 4 | * |
@@ -32,8 +32,10 @@ | |||
32 | 32 | ||
33 | static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, | 33 | static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, |
34 | struct x509_verify_chain *current_chain); | 34 | struct x509_verify_chain *current_chain); |
35 | static int x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, | ||
36 | char *name); | ||
35 | static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | 37 | static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, |
36 | struct x509_verify_chain *current_chain, int full_chain); | 38 | struct x509_verify_chain *current_chain, int full_chain, char *name); |
37 | static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, | 39 | static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, |
38 | size_t depth, int error, int ok); | 40 | size_t depth, int error, int ok); |
39 | static void x509_verify_chain_free(struct x509_verify_chain *chain); | 41 | static void x509_verify_chain_free(struct x509_verify_chain *chain); |
@@ -233,7 +235,7 @@ x509_verify_ctx_clear(struct x509_verify_ctx *ctx) | |||
233 | x509_verify_ctx_reset(ctx); | 235 | x509_verify_ctx_reset(ctx); |
234 | sk_X509_pop_free(ctx->intermediates, X509_free); | 236 | sk_X509_pop_free(ctx->intermediates, X509_free); |
235 | free(ctx->chains); | 237 | free(ctx->chains); |
236 | memset(ctx, 0, sizeof(*ctx)); | 238 | |
237 | } | 239 | } |
238 | 240 | ||
239 | static int | 241 | static int |
@@ -453,10 +455,11 @@ x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx *ctx, | |||
453 | /* Add a validated chain to our list of valid chains */ | 455 | /* Add a validated chain to our list of valid chains */ |
454 | static int | 456 | static int |
455 | x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, | 457 | x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, |
456 | struct x509_verify_chain *chain) | 458 | struct x509_verify_chain *chain, char *name) |
457 | { | 459 | { |
458 | size_t depth; | 460 | size_t depth; |
459 | X509 *last = x509_verify_chain_last(chain); | 461 | X509 *last = x509_verify_chain_last(chain); |
462 | X509 *leaf = x509_verify_chain_leaf(chain); | ||
460 | 463 | ||
461 | depth = sk_X509_num(chain->certs); | 464 | depth = sk_X509_num(chain->certs); |
462 | if (depth > 0) | 465 | if (depth > 0) |
@@ -488,6 +491,13 @@ x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, | |||
488 | return x509_verify_cert_error(ctx, last, depth, | 491 | return x509_verify_cert_error(ctx, last, depth, |
489 | X509_V_ERR_OUT_OF_MEM, 0); | 492 | X509_V_ERR_OUT_OF_MEM, 0); |
490 | } | 493 | } |
494 | |||
495 | if (!x509_verify_cert_valid(ctx, leaf, NULL)) | ||
496 | return 0; | ||
497 | |||
498 | if (!x509_verify_cert_hostname(ctx, leaf, name)) | ||
499 | return 0; | ||
500 | |||
491 | ctx->chains_count++; | 501 | ctx->chains_count++; |
492 | ctx->error = X509_V_OK; | 502 | ctx->error = X509_V_OK; |
493 | ctx->error_depth = depth; | 503 | ctx->error_depth = depth; |
@@ -539,7 +549,7 @@ x509_verify_parent_signature(X509 *parent, X509 *child, int *error) | |||
539 | static int | 549 | static int |
540 | x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, | 550 | x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, |
541 | int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain, | 551 | int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain, |
542 | int full_chain) | 552 | int full_chain, char *name) |
543 | { | 553 | { |
544 | int depth = sk_X509_num(current_chain->certs); | 554 | int depth = sk_X509_num(current_chain->certs); |
545 | struct x509_verify_chain *new_chain; | 555 | struct x509_verify_chain *new_chain; |
@@ -590,14 +600,14 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, | |||
590 | x509_verify_chain_free(new_chain); | 600 | x509_verify_chain_free(new_chain); |
591 | return 0; | 601 | return 0; |
592 | } | 602 | } |
593 | if (!x509_verify_ctx_add_chain(ctx, new_chain)) { | 603 | if (!x509_verify_ctx_add_chain(ctx, new_chain, name)) { |
594 | x509_verify_chain_free(new_chain); | 604 | x509_verify_chain_free(new_chain); |
595 | return 0; | 605 | return 0; |
596 | } | 606 | } |
597 | goto done; | 607 | goto done; |
598 | } | 608 | } |
599 | 609 | ||
600 | x509_verify_build_chains(ctx, candidate, new_chain, full_chain); | 610 | x509_verify_build_chains(ctx, candidate, new_chain, full_chain, name); |
601 | 611 | ||
602 | done: | 612 | done: |
603 | x509_verify_chain_free(new_chain); | 613 | x509_verify_chain_free(new_chain); |
@@ -621,7 +631,7 @@ x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth, | |||
621 | 631 | ||
622 | static void | 632 | static void |
623 | x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | 633 | x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, |
624 | struct x509_verify_chain *current_chain, int full_chain) | 634 | struct x509_verify_chain *current_chain, int full_chain, char *name) |
625 | { | 635 | { |
626 | X509 *candidate; | 636 | X509 *candidate; |
627 | int i, depth, count, ret, is_root; | 637 | int i, depth, count, ret, is_root; |
@@ -679,7 +689,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
679 | x509_verify_cert_self_signed(candidate); | 689 | x509_verify_cert_self_signed(candidate); |
680 | x509_verify_consider_candidate(ctx, cert, | 690 | x509_verify_consider_candidate(ctx, cert, |
681 | is_root, candidate, current_chain, | 691 | is_root, candidate, current_chain, |
682 | full_chain); | 692 | full_chain, name); |
683 | } | 693 | } |
684 | X509_free(candidate); | 694 | X509_free(candidate); |
685 | } | 695 | } |
@@ -692,7 +702,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
692 | x509_verify_cert_self_signed(candidate); | 702 | x509_verify_cert_self_signed(candidate); |
693 | x509_verify_consider_candidate(ctx, cert, | 703 | x509_verify_consider_candidate(ctx, cert, |
694 | is_root, candidate, current_chain, | 704 | is_root, candidate, current_chain, |
695 | full_chain); | 705 | full_chain, name); |
696 | } | 706 | } |
697 | } | 707 | } |
698 | } | 708 | } |
@@ -704,7 +714,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
704 | if (x509_verify_potential_parent(ctx, candidate, cert)) { | 714 | if (x509_verify_potential_parent(ctx, candidate, cert)) { |
705 | x509_verify_consider_candidate(ctx, cert, | 715 | x509_verify_consider_candidate(ctx, cert, |
706 | 0, candidate, current_chain, | 716 | 0, candidate, current_chain, |
707 | full_chain); | 717 | full_chain, name); |
708 | } | 718 | } |
709 | } | 719 | } |
710 | } | 720 | } |
@@ -1116,16 +1126,18 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) | |||
1116 | ctx->xsc->current_cert = leaf; | 1126 | ctx->xsc->current_cert = leaf; |
1117 | } | 1127 | } |
1118 | 1128 | ||
1119 | if (!x509_verify_cert_valid(ctx, leaf, NULL)) | ||
1120 | goto err; | ||
1121 | |||
1122 | if (!x509_verify_cert_hostname(ctx, leaf, name)) | ||
1123 | goto err; | ||
1124 | |||
1125 | if ((current_chain = x509_verify_chain_new()) == NULL) { | 1129 | if ((current_chain = x509_verify_chain_new()) == NULL) { |
1126 | ctx->error = X509_V_ERR_OUT_OF_MEM; | 1130 | ctx->error = X509_V_ERR_OUT_OF_MEM; |
1127 | goto err; | 1131 | goto err; |
1128 | } | 1132 | } |
1133 | |||
1134 | /* | ||
1135 | * Add the leaf to the chain and try to build chains from it. | ||
1136 | * Note that unlike Go's verifier, we have not yet checked | ||
1137 | * anything about the leaf, This is intentional, so that we | ||
1138 | * report failures in chain building before we report problems | ||
1139 | * with the leaf. | ||
1140 | */ | ||
1129 | if (!x509_verify_chain_append(current_chain, leaf, &ctx->error)) { | 1141 | if (!x509_verify_chain_append(current_chain, leaf, &ctx->error)) { |
1130 | x509_verify_chain_free(current_chain); | 1142 | x509_verify_chain_free(current_chain); |
1131 | goto err; | 1143 | goto err; |
@@ -1133,13 +1145,14 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) | |||
1133 | do { | 1145 | do { |
1134 | retry_chain_build = 0; | 1146 | retry_chain_build = 0; |
1135 | if (x509_verify_ctx_cert_is_root(ctx, leaf, full_chain)) { | 1147 | if (x509_verify_ctx_cert_is_root(ctx, leaf, full_chain)) { |
1136 | if (!x509_verify_ctx_add_chain(ctx, current_chain)) { | 1148 | if (!x509_verify_ctx_add_chain(ctx, current_chain, |
1149 | name)) { | ||
1137 | x509_verify_chain_free(current_chain); | 1150 | x509_verify_chain_free(current_chain); |
1138 | goto err; | 1151 | goto err; |
1139 | } | 1152 | } |
1140 | } else { | 1153 | } else { |
1141 | x509_verify_build_chains(ctx, leaf, current_chain, | 1154 | x509_verify_build_chains(ctx, leaf, current_chain, |
1142 | full_chain); | 1155 | full_chain, name); |
1143 | if (full_chain && ctx->chains_count == 0) { | 1156 | if (full_chain && ctx->chains_count == 0) { |
1144 | /* | 1157 | /* |
1145 | * Save the error state from the xsc | 1158 | * Save the error state from the xsc |