diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/x509/x509_internal.h | 5 | ||||
| -rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 146 |
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 { | |||
| 65 | struct x509_verify_ctx { | 65 | struct 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 @@ | |||
| 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 void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | 35 | static 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); |
| 37 | static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, | 37 | static 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); |
| 39 | static void x509_verify_chain_free(struct x509_verify_chain *chain); | 39 | static 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 | ||
| 185 | static int | 188 | static int |
| 186 | x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert) | 189 | x509_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 | |||
| 200 | static int | ||
| 201 | x509_verify_cert_self_signed(X509 *cert) | ||
| 202 | { | ||
| 203 | return (cert->ex_flags & EXFLAG_SS) ? 1 : 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | static int | ||
| 207 | x509_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 | */ | ||
| 275 | static int | ||
| 276 | x509_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 | */ | ||
| 294 | static int | ||
| 295 | x509_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 */ |
| 240 | static int | 311 | static int |
| 241 | x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, | 312 | x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, |
| @@ -331,6 +402,8 @@ static int | |||
| 331 | x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent, | 402 | x509_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, | |||
| 378 | static int | 451 | static int |
| 379 | x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, | 452 | x509_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 | ||
| 471 | static void | 544 | static void |
| 472 | x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | 545 | x509_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 | |||
| 973 | x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) | 1053 | x509_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. |
