summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorbeck <>2022-06-25 20:01:43 +0000
committerbeck <>2022-06-25 20:01:43 +0000
commit8f49e18d8b58138d52d4c7d55385ef2f47508529 (patch)
treea057ee19ce4f7b27f7b8864ab578d7746ac590e9 /src/lib
parent45d168a6140632da2ca76c8437622ccf56118001 (diff)
downloadopenbsd-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.c51
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
33static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, 33static 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);
35static int x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert,
36 char *name);
35static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, 37static 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);
37static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, 39static 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);
39static void x509_verify_chain_free(struct x509_verify_chain *chain); 41static 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
239static int 241static 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 */
454static int 456static int
455x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, 457x509_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)
539static int 549static int
540x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, 550x509_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
622static void 632static void
623x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, 633x509_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