summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortb <>2021-02-24 17:59:05 +0000
committertb <>2021-02-24 17:59:05 +0000
commit3055c9422506884a72601500fcfd923343060dee (patch)
tree6a82977031792901b175e88b3195d0e2b65a9c14 /src/lib
parent6487e268876a41e84c6d6a028a6bf491155f03ba (diff)
downloadopenbsd-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.c23
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
196static int 196static int
197x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, 197x509_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);