summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorbeck <>2021-07-10 15:52:59 +0000
committerbeck <>2021-07-10 15:52:59 +0000
commitc1da4349c38325cc82b5304667bba610e823b4d3 (patch)
tree7c835a85f59541049cb874aacfb00d3ffb5c4e9b /src/lib
parenta2b25cbc6c1634311f248dc10449fb6fbf5c6598 (diff)
downloadopenbsd-c1da4349c38325cc82b5304667bba610e823b4d3.tar.gz
openbsd-c1da4349c38325cc82b5304667bba610e823b4d3.tar.bz2
openbsd-c1da4349c38325cc82b5304667bba610e823b4d3.zip
Add a bunch of workarond in the verifier to support partial chains and
the saving of the first error case so that the "autochain" craziness from openssl will work with the new verifier. This should allow the new verification code to work with a bunch of the autochain using cases in some software. (and should allow us to stop using the legacy verifier with autochain) ok tb@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/x509/x509_internal.h5
-rw-r--r--src/lib/libcrypto/x509/x509_verify.c146
2 files changed, 135 insertions, 16 deletions
diff --git a/src/lib/libcrypto/x509/x509_internal.h b/src/lib/libcrypto/x509/x509_internal.h
index fe40351228..7160053a8a 100644
--- a/src/lib/libcrypto/x509/x509_internal.h
+++ b/src/lib/libcrypto/x509/x509_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_internal.h,v 1.7 2021/03/12 15:53:38 tb Exp $ */ 1/* $OpenBSD: x509_internal.h,v 1.8 2021/07/10 15:52:59 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -65,6 +65,9 @@ struct x509_verify_chain {
65struct x509_verify_ctx { 65struct x509_verify_ctx {
66 X509_STORE_CTX *xsc; 66 X509_STORE_CTX *xsc;
67 struct x509_verify_chain **chains; /* Validated chains */ 67 struct x509_verify_chain **chains; /* Validated chains */
68 STACK_OF(X509) *saved_error_chain;
69 int saved_error;
70 int saved_error_depth;
68 size_t chains_count; 71 size_t chains_count;
69 int dump_chain; /* Dump current chain without erroring */ 72 int dump_chain; /* Dump current chain without erroring */
70 STACK_OF(X509) *roots; /* Trusted roots for this validation */ 73 STACK_OF(X509) *roots; /* Trusted roots for this validation */
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c
index 57c52aa240..21b391c76c 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.37 2021/04/28 17:53:34 tb Exp $ */ 1/* $OpenBSD: x509_verify.c,v 1.38 2021/07/10 15:52:59 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 *
@@ -33,7 +33,7 @@
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 void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, 35static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
36 struct x509_verify_chain *current_chain); 36 struct x509_verify_chain *current_chain, int full_chain);
37static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, 37static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert,
38 size_t depth, int error, int ok); 38 size_t depth, int error, int ok);
39static void x509_verify_chain_free(struct x509_verify_chain *chain); 39static void x509_verify_chain_free(struct x509_verify_chain *chain);
@@ -166,6 +166,9 @@ x509_verify_ctx_reset(struct x509_verify_ctx *ctx)
166 166
167 for (i = 0; i < ctx->chains_count; i++) 167 for (i = 0; i < ctx->chains_count; i++)
168 x509_verify_chain_free(ctx->chains[i]); 168 x509_verify_chain_free(ctx->chains[i]);
169 sk_X509_pop_free(ctx->saved_error_chain, X509_free);
170 ctx->saved_error = 0;
171 ctx->saved_error_depth = 0;
169 ctx->error = 0; 172 ctx->error = 0;
170 ctx->error_depth = 0; 173 ctx->error_depth = 0;
171 ctx->chains_count = 0; 174 ctx->chains_count = 0;
@@ -183,14 +186,42 @@ x509_verify_ctx_clear(struct x509_verify_ctx *ctx)
183} 186}
184 187
185static int 188static int
186x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert) 189x509_verify_cert_cache_extensions(X509 *cert) {
190 if (!(cert->ex_flags & EXFLAG_SET)) {
191 CRYPTO_w_lock(CRYPTO_LOCK_X509);
192 x509v3_cache_extensions(cert);
193 CRYPTO_w_unlock(CRYPTO_LOCK_X509);
194 }
195 if (cert->ex_flags & EXFLAG_INVALID)
196 return 0;
197 return (cert->ex_flags & EXFLAG_SET);
198}
199
200static int
201x509_verify_cert_self_signed(X509 *cert)
202{
203 return (cert->ex_flags & EXFLAG_SS) ? 1 : 0;
204}
205
206static int
207x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert,
208 int full_chain)
187{ 209{
188 int i; 210 int i;
189 211
212 if (!x509_verify_cert_cache_extensions(cert))
213 return 0;
214
190 for (i = 0; i < sk_X509_num(ctx->roots); i++) { 215 for (i = 0; i < sk_X509_num(ctx->roots); i++) {
191 if (X509_cmp(sk_X509_value(ctx->roots, i), cert) == 0) 216 if (X509_cmp(sk_X509_value(ctx->roots, i), cert) == 0)
192 return 1; 217 return !full_chain ||
218 x509_verify_cert_self_signed(cert);
193 } 219 }
220 /*
221 * XXX what if this is a by_dir thing? this currently isn't
222 * handled so this case is a bit messed up for loonix with
223 * by directory trust bundles...
224 */
194 return 0; 225 return 0;
195} 226}
196 227
@@ -236,6 +267,46 @@ x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx,
236 return 1; 267 return 1;
237} 268}
238 269
270
271/*
272 * Save the error state and unvalidated chain off of the xsc for
273 * later.
274 */
275static int
276x509_verify_ctx_save_xsc_error(struct x509_verify_ctx *ctx)
277{
278 if (ctx->xsc != NULL && ctx->xsc->chain != NULL) {
279 sk_X509_pop_free(ctx->saved_error_chain, X509_free);
280 ctx->saved_error_chain = X509_chain_up_ref(ctx->xsc->chain);
281 if (ctx->saved_error_chain == NULL)
282 return x509_verify_cert_error(ctx, NULL, 0,
283 X509_V_ERR_OUT_OF_MEM, 0);
284 ctx->saved_error = ctx->xsc->error;
285 ctx->saved_error_depth = ctx->xsc->error_depth;
286 }
287 return 1;
288}
289
290/*
291 * Restore the saved error state and unvalidated chain to the xsc
292 * if we do not have a validated chain.
293 */
294static int
295x509_verify_ctx_restore_xsc_error(struct x509_verify_ctx *ctx)
296{
297 if (ctx->xsc != NULL && ctx->chains_count == 0 &&
298 ctx->saved_error_chain != NULL) {
299 sk_X509_pop_free(ctx->xsc->chain, X509_free);
300 ctx->xsc->chain = X509_chain_up_ref(ctx->saved_error_chain);
301 if (ctx->xsc->chain == NULL)
302 return x509_verify_cert_error(ctx, NULL, 0,
303 X509_V_ERR_OUT_OF_MEM, 0);
304 ctx->xsc->error = ctx->saved_error;
305 ctx->xsc->error_depth = ctx->saved_error_depth;
306 }
307 return 1;
308}
309
239/* Add a validated chain to our list of valid chains */ 310/* Add a validated chain to our list of valid chains */
240static int 311static int
241x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, 312x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
@@ -331,6 +402,8 @@ static int
331x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent, 402x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent,
332 X509 *child) 403 X509 *child)
333{ 404{
405 if (!x509_verify_cert_cache_extensions(parent))
406 return 0;
334 if (ctx->xsc != NULL) 407 if (ctx->xsc != NULL)
335 return (ctx->xsc->check_issued(ctx->xsc, child, parent)); 408 return (ctx->xsc->check_issued(ctx->xsc, child, parent));
336 409
@@ -378,7 +451,7 @@ x509_verify_parent_signature(X509 *parent, X509 *child,
378static int 451static int
379x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, 452x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
380 unsigned char *cert_md, int is_root_cert, X509 *candidate, 453 unsigned char *cert_md, int is_root_cert, X509 *candidate,
381 struct x509_verify_chain *current_chain) 454 struct x509_verify_chain *current_chain, int full_chain)
382{ 455{
383 int depth = sk_X509_num(current_chain->certs); 456 int depth = sk_X509_num(current_chain->certs);
384 struct x509_verify_chain *new_chain; 457 struct x509_verify_chain *new_chain;
@@ -446,7 +519,7 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
446 } 519 }
447 } 520 }
448 521
449 x509_verify_build_chains(ctx, candidate, new_chain); 522 x509_verify_build_chains(ctx, candidate, new_chain, full_chain);
450 523
451 done: 524 done:
452 x509_verify_chain_free(new_chain); 525 x509_verify_chain_free(new_chain);
@@ -470,11 +543,11 @@ x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth,
470 543
471static void 544static void
472x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, 545x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
473 struct x509_verify_chain *current_chain) 546 struct x509_verify_chain *current_chain, int full_chain)
474{ 547{
475 unsigned char cert_md[EVP_MAX_MD_SIZE] = { 0 }; 548 unsigned char cert_md[EVP_MAX_MD_SIZE] = { 0 };
476 X509 *candidate; 549 X509 *candidate;
477 int i, depth, count, ret; 550 int i, depth, count, ret, is_root;
478 551
479 /* 552 /*
480 * If we are finding chains with an xsc, just stop after we have 553 * If we are finding chains with an xsc, just stop after we have
@@ -519,8 +592,11 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
519 for (i = 0; i < sk_X509_num(ctx->roots); i++) { 592 for (i = 0; i < sk_X509_num(ctx->roots); i++) {
520 candidate = sk_X509_value(ctx->roots, i); 593 candidate = sk_X509_value(ctx->roots, i);
521 if (x509_verify_potential_parent(ctx, candidate, cert)) { 594 if (x509_verify_potential_parent(ctx, candidate, cert)) {
595 is_root = !full_chain ||
596 x509_verify_cert_self_signed(candidate);
522 x509_verify_consider_candidate(ctx, cert, 597 x509_verify_consider_candidate(ctx, cert,
523 cert_md, 1, candidate, current_chain); 598 cert_md, is_root, candidate, current_chain,
599 full_chain);
524 } 600 }
525 } 601 }
526 /* Check for legacy mode roots */ 602 /* Check for legacy mode roots */
@@ -532,8 +608,11 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
532 } 608 }
533 if (ret > 0) { 609 if (ret > 0) {
534 if (x509_verify_potential_parent(ctx, candidate, cert)) { 610 if (x509_verify_potential_parent(ctx, candidate, cert)) {
611 is_root = !full_chain ||
612 x509_verify_cert_self_signed(candidate);
535 x509_verify_consider_candidate(ctx, cert, 613 x509_verify_consider_candidate(ctx, cert,
536 cert_md, 1, candidate, current_chain); 614 cert_md, is_root, candidate, current_chain,
615 full_chain);
537 } 616 }
538 X509_free(candidate); 617 X509_free(candidate);
539 } 618 }
@@ -545,7 +624,8 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
545 candidate = sk_X509_value(ctx->intermediates, i); 624 candidate = sk_X509_value(ctx->intermediates, i);
546 if (x509_verify_potential_parent(ctx, candidate, cert)) { 625 if (x509_verify_potential_parent(ctx, candidate, cert)) {
547 x509_verify_consider_candidate(ctx, cert, 626 x509_verify_consider_candidate(ctx, cert,
548 cert_md, 0, candidate, current_chain); 627 cert_md, 0, candidate, current_chain,
628 full_chain);
549 } 629 }
550 } 630 }
551 } 631 }
@@ -973,6 +1053,7 @@ size_t
973x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) 1053x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
974{ 1054{
975 struct x509_verify_chain *current_chain; 1055 struct x509_verify_chain *current_chain;
1056 int retry_chain_build, full_chain = 0;
976 1057
977 if (ctx->roots == NULL || ctx->max_depth == 0) { 1058 if (ctx->roots == NULL || ctx->max_depth == 0) {
978 ctx->error = X509_V_ERR_INVALID_CALL; 1059 ctx->error = X509_V_ERR_INVALID_CALL;
@@ -986,6 +1067,10 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
986 } 1067 }
987 leaf = ctx->xsc->cert; 1068 leaf = ctx->xsc->cert;
988 1069
1070 /* XXX */
1071 full_chain = 1;
1072 if (ctx->xsc->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
1073 full_chain = 0;
989 /* 1074 /*
990 * XXX 1075 * XXX
991 * The legacy code expects the top level cert to be 1076 * The legacy code expects the top level cert to be
@@ -1024,14 +1109,45 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
1024 x509_verify_chain_free(current_chain); 1109 x509_verify_chain_free(current_chain);
1025 goto err; 1110 goto err;
1026 } 1111 }
1027 if (x509_verify_ctx_cert_is_root(ctx, leaf)) 1112 do {
1028 x509_verify_ctx_add_chain(ctx, current_chain); 1113 retry_chain_build = 0;
1029 else 1114 if (x509_verify_ctx_cert_is_root(ctx, leaf, full_chain))
1030 x509_verify_build_chains(ctx, leaf, current_chain); 1115 x509_verify_ctx_add_chain(ctx, current_chain);
1116 else {
1117 x509_verify_build_chains(ctx, leaf, current_chain,
1118 full_chain);
1119 if (full_chain && ctx->chains_count == 0) {
1120 /*
1121 * Save the error state from the xsc
1122 * at this point to put back on the
1123 * xsc in case we do not find a chain
1124 * that is trusted but not a full
1125 * chain to a self signed root. This
1126 * is because the unvalidated chain is
1127 * used by the autochain batshittery
1128 * on failure and will be needed for
1129 * that.
1130 */
1131 if (!x509_verify_ctx_save_xsc_error(ctx)) {
1132 x509_verify_chain_free(current_chain);
1133 goto err;
1134 }
1135 full_chain = 0;
1136 retry_chain_build = 1;
1137 }
1138 }
1139 } while (retry_chain_build);
1031 1140
1032 x509_verify_chain_free(current_chain); 1141 x509_verify_chain_free(current_chain);
1033 1142
1034 /* 1143 /*
1144 * Bring back the failure case we wanted to the xsc if
1145 * we saved one.
1146 */
1147 if (!x509_verify_ctx_restore_xsc_error(ctx))
1148 goto err;
1149
1150 /*
1035 * Safety net: 1151 * Safety net:
1036 * We could not find a validated chain, and for some reason do not 1152 * We could not find a validated chain, and for some reason do not
1037 * have an error set. 1153 * have an error set.