diff options
author | tb <> | 2021-02-24 17:59:05 +0000 |
---|---|---|
committer | tb <> | 2021-02-24 17:59:05 +0000 |
commit | 3055c9422506884a72601500fcfd923343060dee (patch) | |
tree | 6a82977031792901b175e88b3195d0e2b65a9c14 /src/lib | |
parent | 6487e268876a41e84c6d6a028a6bf491155f03ba (diff) | |
download | openbsd-3055c9422506884a72601500fcfd923343060dee.tar.gz openbsd-3055c9422506884a72601500fcfd923343060dee.tar.bz2 openbsd-3055c9422506884a72601500fcfd923343060dee.zip |
Make the new validator check for EXFLAG_CRITICAL
As should be obvious from the name and the comment in x509_vfy.h
int last_untrusted; /* index of last untrusted cert */
last_untrusted actually counts the number of untrusted certs at the
bottom of the chain.
Unfortunately, an earlier fix introducing x509_verify_set_xsc_chain()
assumed that last_untrusted actually meant the index of the last
untrusted cert in the chain, resulting in an off-by-one, which in turn
led to x509_vfy_check_chain_extension() skipping the check for the
EXFLAG_CRITICAL flag.
A second bug in x509_verify_set_xsc_chain() assumed that it is always
called with a trusted root, which is not necessarily the case anymore.
Address this with a temporary fix which will have to be revisited once
we will allow chains with more than one trusted cert.
Reported with a test case by tobhe.
ok jsing tobhe
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c index cf0d7fb559..598e268d37 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.30 2021/01/09 03:51:42 jsing Exp $ */ | 1 | /* $OpenBSD: x509_verify.c,v 1.31 2021/02/24 17:59:05 tb 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 | * |
@@ -195,7 +195,7 @@ x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert) | |||
195 | 195 | ||
196 | static int | 196 | static int |
197 | x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, | 197 | x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, |
198 | struct x509_verify_chain *chain, int set_error) | 198 | struct x509_verify_chain *chain, int set_error, int is_trusted) |
199 | { | 199 | { |
200 | X509 *last = x509_verify_chain_last(chain); | 200 | X509 *last = x509_verify_chain_last(chain); |
201 | size_t depth; | 201 | size_t depth; |
@@ -205,10 +205,16 @@ x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, | |||
205 | return 1; | 205 | return 1; |
206 | 206 | ||
207 | depth = sk_X509_num(chain->certs); | 207 | depth = sk_X509_num(chain->certs); |
208 | if (depth > 0) | 208 | if (is_trusted && depth > 0) |
209 | depth--; | 209 | depth--; |
210 | /* | ||
211 | * XXX last_untrusted is actually the number of untrusted certs at the | ||
212 | * bottom of the chain. This works now since we stop at the first | ||
213 | * trusted cert. This will need fixing once we allow more than one | ||
214 | * trusted certificate. | ||
215 | */ | ||
216 | ctx->xsc->last_untrusted = depth; | ||
210 | 217 | ||
211 | ctx->xsc->last_untrusted = depth ? depth - 1 : 0; | ||
212 | sk_X509_pop_free(ctx->xsc->chain, X509_free); | 218 | sk_X509_pop_free(ctx->xsc->chain, X509_free); |
213 | ctx->xsc->chain = X509_chain_up_ref(chain->certs); | 219 | ctx->xsc->chain = X509_chain_up_ref(chain->certs); |
214 | if (ctx->xsc->chain == NULL) | 220 | if (ctx->xsc->chain == NULL) |
@@ -264,7 +270,7 @@ x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, | |||
264 | ctx->xsc->error = X509_V_OK; | 270 | ctx->xsc->error = X509_V_OK; |
265 | ctx->xsc->error_depth = 0; | 271 | ctx->xsc->error_depth = 0; |
266 | 272 | ||
267 | if (!x509_verify_ctx_set_xsc_chain(ctx, chain, 0)) | 273 | if (!x509_verify_ctx_set_xsc_chain(ctx, chain, 0, 0)) |
268 | return 0; | 274 | return 0; |
269 | 275 | ||
270 | /* | 276 | /* |
@@ -430,7 +436,7 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, | |||
430 | * give up. | 436 | * give up. |
431 | */ | 437 | */ |
432 | if (is_root_cert) { | 438 | if (is_root_cert) { |
433 | if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain, 0)) { | 439 | if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain, 0, 1)) { |
434 | x509_verify_chain_free(new_chain); | 440 | x509_verify_chain_free(new_chain); |
435 | return 0; | 441 | return 0; |
436 | } | 442 | } |
@@ -555,7 +561,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
555 | if (depth == 0 && | 561 | if (depth == 0 && |
556 | ctx->error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) | 562 | ctx->error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) |
557 | ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; | 563 | ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; |
558 | if (!x509_verify_ctx_set_xsc_chain(ctx, current_chain, 0)) | 564 | if (!x509_verify_ctx_set_xsc_chain(ctx, current_chain, 0, 0)) |
559 | return; | 565 | return; |
560 | (void) x509_verify_cert_error(ctx, cert, depth, | 566 | (void) x509_verify_cert_error(ctx, cert, depth, |
561 | ctx->error, 0); | 567 | ctx->error, 0); |
@@ -1041,7 +1047,8 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) | |||
1041 | ctx->xsc->error = ctx->error; | 1047 | ctx->xsc->error = ctx->error; |
1042 | if (ctx->chains_count > 0) { | 1048 | if (ctx->chains_count > 0) { |
1043 | /* Take the first chain we found. */ | 1049 | /* Take the first chain we found. */ |
1044 | if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1)) | 1050 | if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], |
1051 | 1, 1)) | ||
1045 | goto err; | 1052 | goto err; |
1046 | } | 1053 | } |
1047 | return ctx->xsc->verify_cb(ctx->chains_count > 0, ctx->xsc); | 1054 | return ctx->xsc->verify_cb(ctx->chains_count > 0, ctx->xsc); |