diff options
author | jsing <> | 2020-09-23 18:20:16 +0000 |
---|---|---|
committer | jsing <> | 2020-09-23 18:20:16 +0000 |
commit | 8fb9c3782c59e736c9e09323162af3af8028e693 (patch) | |
tree | 78a2602d8623dcfea6a3202e7fe669645f1f46d6 | |
parent | 55b453e738ce161fd2fc7e9c03c42366d9f70723 (diff) | |
download | openbsd-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.c | 51 |
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 | ||
172 | static int | ||
173 | x509_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 */ |
173 | static int | 196 | static int |
174 | x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, | 197 | x509_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 | } |