summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2020-09-23 18:20:16 +0000
committerjsing <>2020-09-23 18:20:16 +0000
commit8fb9c3782c59e736c9e09323162af3af8028e693 (patch)
tree78a2602d8623dcfea6a3202e7fe669645f1f46d6
parent55b453e738ce161fd2fc7e9c03c42366d9f70723 (diff)
downloadopenbsd-8fb9c3782c59e736c9e09323162af3af8028e693.tar.gz
openbsd-8fb9c3782c59e736c9e09323162af3af8028e693.tar.bz2
openbsd-8fb9c3782c59e736c9e09323162af3af8028e693.zip
Ensure chain is set on the X509_STORE_CTX before triggering callback.
Various software expects the previous behaviour where the certificate chain is available on the X509_STORE_CTX when the verify callback is triggered. Issue hit by bket@ with lastpass-cli which has built in certificate pinning that is checked via the verify callback. Fix confirmed by bket@. ok beck@
-rw-r--r--src/lib/libcrypto/x509/x509_verify.c51
1 files changed, 39 insertions, 12 deletions
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c
index 5ab3eaeda1..53a06b193b 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.11 2020/09/19 14:15:38 beck Exp $ */ 1/* $OpenBSD: x509_verify.c,v 1.12 2020/09/23 18:20:16 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -169,6 +169,29 @@ x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert)
169 return 0; 169 return 0;
170} 170}
171 171
172static int
173x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx,
174 struct x509_verify_chain *chain)
175{
176 size_t depth;
177 X509 *last = x509_verify_chain_last(chain);
178
179 if (ctx->xsc == NULL)
180 return 1;
181
182 depth = sk_X509_num(chain->certs);
183 if (depth > 0)
184 depth--;
185
186 ctx->xsc->last_untrusted = depth ? depth - 1 : 0;
187 sk_X509_pop_free(ctx->xsc->chain, X509_free);
188 ctx->xsc->chain = X509_chain_up_ref(chain->certs);
189 if (ctx->xsc->chain == NULL)
190 return x509_verify_cert_error(ctx, last, depth,
191 X509_V_ERR_OUT_OF_MEM, 0);
192 return 1;
193}
194
172/* Add a validated chain to our list of valid chains */ 195/* Add a validated chain to our list of valid chains */
173static int 196static int
174x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, 197x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
@@ -194,12 +217,8 @@ x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
194 * knobs that are there for the fiddling. 217 * knobs that are there for the fiddling.
195 */ 218 */
196 if (ctx->xsc != NULL) { 219 if (ctx->xsc != NULL) {
197 ctx->xsc->last_untrusted = depth ? depth - 1 : 0; 220 if (!x509_verify_ctx_set_xsc_chain(ctx, chain))
198 sk_X509_pop_free(ctx->xsc->chain, X509_free); 221 return 0;
199 ctx->xsc->chain = X509_chain_up_ref(chain->certs);
200 if (ctx->xsc->chain == NULL)
201 return x509_verify_cert_error(ctx, last, depth,
202 X509_V_ERR_OUT_OF_MEM, 0);
203 222
204 /* 223 /*
205 * XXX currently this duplicates some work done 224 * XXX currently this duplicates some work done
@@ -343,12 +362,20 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
343 * so we save it. Otherwise, recurse until we find a root or 362 * so we save it. Otherwise, recurse until we find a root or
344 * give up. 363 * give up.
345 */ 364 */
346 if (is_root_cert && 365 if (is_root_cert) {
347 x509_verify_cert_error(ctx, candidate, depth, X509_V_OK, 1)) 366 if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain)) {
348 (void) x509_verify_ctx_add_chain(ctx, new_chain); 367 x509_verify_chain_free(new_chain);
349 else 368 return 0;
350 x509_verify_build_chains(ctx, candidate, new_chain); 369 }
370 if (x509_verify_cert_error(ctx, candidate, depth, X509_V_OK, 1)) {
371 (void) x509_verify_ctx_add_chain(ctx, new_chain);
372 goto done;
373 }
374 }
375
376 x509_verify_build_chains(ctx, candidate, new_chain);
351 377
378 done:
352 x509_verify_chain_free(new_chain); 379 x509_verify_chain_free(new_chain);
353 return 1; 380 return 1;
354} 381}