xref: /openbsd/lib/libcrypto/x509/x509_verify.c (revision 41c05129)
1*41c05129Stb /* $OpenBSD: x509_verify.c,v 1.70 2024/06/07 06:21:40 tb Exp $ */
223258cfeSbeck /*
358d6c226Sbeck  * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org>
423258cfeSbeck  *
523258cfeSbeck  * Permission to use, copy, modify, and distribute this software for any
623258cfeSbeck  * purpose with or without fee is hereby granted, provided that the above
723258cfeSbeck  * copyright notice and this permission notice appear in all copies.
823258cfeSbeck  *
923258cfeSbeck  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1023258cfeSbeck  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1123258cfeSbeck  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1223258cfeSbeck  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1323258cfeSbeck  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1423258cfeSbeck  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1523258cfeSbeck  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1623258cfeSbeck  */
1723258cfeSbeck 
18a235c622Sjsing /* x509_verify - inspired by golang's crypto/x509.Verify */
1923258cfeSbeck 
2023258cfeSbeck #include <errno.h>
2123258cfeSbeck #include <stdio.h>
2223258cfeSbeck #include <string.h>
2323258cfeSbeck #include <time.h>
2423258cfeSbeck #include <unistd.h>
2523258cfeSbeck 
2623258cfeSbeck #include <openssl/safestack.h>
2723258cfeSbeck #include <openssl/x509.h>
2823258cfeSbeck #include <openssl/x509v3.h>
2923258cfeSbeck 
3091b40737Stb #include "asn1_local.h"
3123258cfeSbeck #include "x509_internal.h"
3223258cfeSbeck #include "x509_issuer_cache.h"
3323258cfeSbeck 
3423258cfeSbeck static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert,
3523258cfeSbeck     struct x509_verify_chain *current_chain);
36b8644936Sbeck static int x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert,
37b8644936Sbeck     char *name);
3823258cfeSbeck static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
39b8644936Sbeck     struct x509_verify_chain *current_chain, int full_chain, char *name);
4023258cfeSbeck static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert,
4123258cfeSbeck     size_t depth, int error, int ok);
4223258cfeSbeck static void x509_verify_chain_free(struct x509_verify_chain *chain);
4323258cfeSbeck 
4488e5d447Sbeck /*
4588e5d447Sbeck  * Parse an asn1 to a representable time_t as per RFC 5280 rules.
4688e5d447Sbeck  * Returns -1 if that can't be done for any reason.
4788e5d447Sbeck  */
4891b40737Stb int
x509_verify_asn1_time_to_time_t(const ASN1_TIME * atime,int notAfter,time_t * out)4991b40737Stb x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notAfter,
5091b40737Stb     time_t *out)
5188e5d447Sbeck {
5288e5d447Sbeck 	struct tm tm = { 0 };
5388e5d447Sbeck 	int type;
5488e5d447Sbeck 
55cc34b9f0Sbeck 	if (atime == NULL)
56cc34b9f0Sbeck 		return 0;
57cc34b9f0Sbeck 
5888e5d447Sbeck 	type = ASN1_time_parse(atime->data, atime->length, &tm, atime->type);
5988e5d447Sbeck 	if (type == -1)
6091b40737Stb 		return 0;
6188e5d447Sbeck 
6288e5d447Sbeck 	/* RFC 5280 section 4.1.2.5 */
6388e5d447Sbeck 	if (tm.tm_year < 150 && type != V_ASN1_UTCTIME)
6491b40737Stb 		return 0;
6588e5d447Sbeck 	if (tm.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
6691b40737Stb 		return 0;
6788e5d447Sbeck 
6888e5d447Sbeck 	if (notAfter) {
6988e5d447Sbeck 		/*
7088e5d447Sbeck 		 * If we are a completely broken operating system with a
7188e5d447Sbeck 		 * 32 bit time_t, and we have been told this is a notAfter
7288e5d447Sbeck 		 * date, limit the date to a 32 bit representable value.
7388e5d447Sbeck 		 */
7488e5d447Sbeck 		if (!ASN1_time_tm_clamp_notafter(&tm))
7591b40737Stb 			return 0;
7688e5d447Sbeck 	}
7788e5d447Sbeck 
7888e5d447Sbeck 	/*
7988e5d447Sbeck 	 * Defensively fail if the time string is not representable as
8088e5d447Sbeck 	 * a time_t. A time_t must be sane if you care about times after
8188e5d447Sbeck 	 * Jan 19 2038.
8288e5d447Sbeck 	 */
8391b40737Stb 	return asn1_time_tm_to_time_t(&tm, out);
8488e5d447Sbeck }
8588e5d447Sbeck 
8623258cfeSbeck struct x509_verify_chain *
x509_verify_chain_new(void)8723258cfeSbeck x509_verify_chain_new(void)
8823258cfeSbeck {
8923258cfeSbeck 	struct x509_verify_chain *chain;
9023258cfeSbeck 
9123258cfeSbeck 	if ((chain = calloc(1, sizeof(*chain))) == NULL)
9223258cfeSbeck 		goto err;
9323258cfeSbeck 	if ((chain->certs = sk_X509_new_null()) == NULL)
9423258cfeSbeck 		goto err;
95a235c622Sjsing 	if ((chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS,
96a235c622Sjsing 	    sizeof(int))) == NULL)
97a235c622Sjsing 		goto err;
9842f3108aStb 	if ((chain->names =
9942f3108aStb 	    x509_constraints_names_new(X509_VERIFY_MAX_CHAIN_NAMES)) == NULL)
10023258cfeSbeck 		goto err;
10123258cfeSbeck 
10223258cfeSbeck 	return chain;
10323258cfeSbeck  err:
10423258cfeSbeck 	x509_verify_chain_free(chain);
10523258cfeSbeck 	return NULL;
10623258cfeSbeck }
10723258cfeSbeck 
10823258cfeSbeck static void
x509_verify_chain_clear(struct x509_verify_chain * chain)10923258cfeSbeck x509_verify_chain_clear(struct x509_verify_chain *chain)
11023258cfeSbeck {
11123258cfeSbeck 	sk_X509_pop_free(chain->certs, X509_free);
11223258cfeSbeck 	chain->certs = NULL;
113a235c622Sjsing 	free(chain->cert_errors);
114a235c622Sjsing 	chain->cert_errors = NULL;
11523258cfeSbeck 	x509_constraints_names_free(chain->names);
11623258cfeSbeck 	chain->names = NULL;
11723258cfeSbeck }
11823258cfeSbeck 
11923258cfeSbeck static void
x509_verify_chain_free(struct x509_verify_chain * chain)12023258cfeSbeck x509_verify_chain_free(struct x509_verify_chain *chain)
12123258cfeSbeck {
12223258cfeSbeck 	if (chain == NULL)
12323258cfeSbeck 		return;
12423258cfeSbeck 	x509_verify_chain_clear(chain);
12523258cfeSbeck 	free(chain);
12623258cfeSbeck }
12723258cfeSbeck 
12823258cfeSbeck static struct x509_verify_chain *
x509_verify_chain_dup(struct x509_verify_chain * chain)12923258cfeSbeck x509_verify_chain_dup(struct x509_verify_chain *chain)
13023258cfeSbeck {
13123258cfeSbeck 	struct x509_verify_chain *new_chain;
13223258cfeSbeck 
133f83e3c38Stb 	if ((new_chain = calloc(1, sizeof(*chain))) == NULL)
13423258cfeSbeck 		goto err;
13523258cfeSbeck 	if ((new_chain->certs = X509_chain_up_ref(chain->certs)) == NULL)
13623258cfeSbeck 		goto err;
137a235c622Sjsing 	if ((new_chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS,
138a235c622Sjsing 	    sizeof(int))) == NULL)
139a235c622Sjsing 		goto err;
140a235c622Sjsing 	memcpy(new_chain->cert_errors, chain->cert_errors,
141a235c622Sjsing 	    X509_VERIFY_MAX_CHAIN_CERTS * sizeof(int));
14223258cfeSbeck 	if ((new_chain->names =
14323258cfeSbeck 	    x509_constraints_names_dup(chain->names)) == NULL)
14423258cfeSbeck 		goto err;
14523258cfeSbeck 	return(new_chain);
14623258cfeSbeck  err:
14723258cfeSbeck 	x509_verify_chain_free(new_chain);
14823258cfeSbeck 	return NULL;
14923258cfeSbeck }
15023258cfeSbeck 
15123258cfeSbeck static int
x509_verify_chain_append(struct x509_verify_chain * chain,X509 * cert,int * error)15223258cfeSbeck x509_verify_chain_append(struct x509_verify_chain *chain, X509 *cert,
15323258cfeSbeck     int *error)
15423258cfeSbeck {
15523258cfeSbeck 	int verify_err = X509_V_ERR_UNSPECIFIED;
156a235c622Sjsing 	size_t idx;
15723258cfeSbeck 
15823258cfeSbeck 	if (!x509_constraints_extract_names(chain->names, cert,
15923258cfeSbeck 	    sk_X509_num(chain->certs) == 0, &verify_err)) {
16023258cfeSbeck 		*error = verify_err;
16123258cfeSbeck 		return 0;
16223258cfeSbeck 	}
163a235c622Sjsing 
16423258cfeSbeck 	X509_up_ref(cert);
16523258cfeSbeck 	if (!sk_X509_push(chain->certs, cert)) {
16623258cfeSbeck 		X509_free(cert);
1676b178030Sbeck 		*error = X509_V_ERR_OUT_OF_MEM;
16823258cfeSbeck 		return 0;
16923258cfeSbeck 	}
170a235c622Sjsing 
171a235c622Sjsing 	idx = sk_X509_num(chain->certs) - 1;
172a235c622Sjsing 	chain->cert_errors[idx] = *error;
173a235c622Sjsing 
174a235c622Sjsing 	/*
175a235c622Sjsing 	 * We've just added the issuer for the previous certificate,
176a235c622Sjsing 	 * clear its error if appropriate.
177a235c622Sjsing 	 */
17850df4f34Sbeck 	if (idx > 1 && chain->cert_errors[idx - 1] ==
17950df4f34Sbeck 	    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
180a235c622Sjsing 		chain->cert_errors[idx - 1] = X509_V_OK;
181a235c622Sjsing 
18223258cfeSbeck 	return 1;
18323258cfeSbeck }
18423258cfeSbeck 
18523258cfeSbeck static X509 *
x509_verify_chain_last(struct x509_verify_chain * chain)18623258cfeSbeck x509_verify_chain_last(struct x509_verify_chain *chain)
18723258cfeSbeck {
18823258cfeSbeck 	int last;
18923258cfeSbeck 
19023258cfeSbeck 	if (chain->certs == NULL)
19123258cfeSbeck 		return NULL;
19223258cfeSbeck 	if ((last = sk_X509_num(chain->certs) - 1) < 0)
19323258cfeSbeck 		return NULL;
19423258cfeSbeck 	return sk_X509_value(chain->certs, last);
19523258cfeSbeck }
19623258cfeSbeck 
19723258cfeSbeck X509 *
x509_verify_chain_leaf(struct x509_verify_chain * chain)19823258cfeSbeck x509_verify_chain_leaf(struct x509_verify_chain *chain)
19923258cfeSbeck {
20023258cfeSbeck 	if (chain->certs == NULL)
20123258cfeSbeck 		return NULL;
20223258cfeSbeck 	return sk_X509_value(chain->certs, 0);
20323258cfeSbeck }
20423258cfeSbeck 
20523258cfeSbeck static void
x509_verify_ctx_reset(struct x509_verify_ctx * ctx)20623258cfeSbeck x509_verify_ctx_reset(struct x509_verify_ctx *ctx)
20723258cfeSbeck {
20823258cfeSbeck 	size_t i;
20923258cfeSbeck 
21023258cfeSbeck 	for (i = 0; i < ctx->chains_count; i++)
21123258cfeSbeck 		x509_verify_chain_free(ctx->chains[i]);
2129ab39fd2Sbeck 	sk_X509_pop_free(ctx->saved_error_chain, X509_free);
2139ab39fd2Sbeck 	ctx->saved_error = 0;
2149ab39fd2Sbeck 	ctx->saved_error_depth = 0;
21523258cfeSbeck 	ctx->error = 0;
21623258cfeSbeck 	ctx->error_depth = 0;
21723258cfeSbeck 	ctx->chains_count = 0;
21823258cfeSbeck 	ctx->sig_checks = 0;
21923258cfeSbeck 	ctx->check_time = NULL;
22023258cfeSbeck }
22123258cfeSbeck 
22223258cfeSbeck static void
x509_verify_ctx_clear(struct x509_verify_ctx * ctx)22323258cfeSbeck x509_verify_ctx_clear(struct x509_verify_ctx *ctx)
22423258cfeSbeck {
22523258cfeSbeck 	x509_verify_ctx_reset(ctx);
22623258cfeSbeck 	sk_X509_pop_free(ctx->intermediates, X509_free);
22723258cfeSbeck 	free(ctx->chains);
228b8644936Sbeck 
22923258cfeSbeck }
23023258cfeSbeck 
23123258cfeSbeck static int
x509_verify_cert_cache_extensions(X509 * cert)2328d41a2d6Stb x509_verify_cert_cache_extensions(X509 *cert)
2338d41a2d6Stb {
2340051318fSjob 	return x509v3_cache_extensions(cert);
2359ab39fd2Sbeck }
2369ab39fd2Sbeck 
2379ab39fd2Sbeck static int
x509_verify_cert_self_signed(X509 * cert)2389ab39fd2Sbeck x509_verify_cert_self_signed(X509 *cert)
2399ab39fd2Sbeck {
2409ab39fd2Sbeck 	return (cert->ex_flags & EXFLAG_SS) ? 1 : 0;
2419ab39fd2Sbeck }
2429ab39fd2Sbeck 
243d8913d6aSbeck /* XXX beck - clean up this mess of is_root */
244d8913d6aSbeck static int
x509_verify_check_chain_end(X509 * cert,int full_chain)245d8913d6aSbeck x509_verify_check_chain_end(X509 *cert, int full_chain)
246d8913d6aSbeck {
247d8913d6aSbeck 	if (full_chain)
248d8913d6aSbeck 		return x509_verify_cert_self_signed(cert);
249d8913d6aSbeck 	return 1;
250d8913d6aSbeck }
251d8913d6aSbeck 
252d8913d6aSbeck static int
x509_verify_ctx_cert_is_root(struct x509_verify_ctx * ctx,X509 * cert,int full_chain)2539ab39fd2Sbeck x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert,
2549ab39fd2Sbeck     int full_chain)
25523258cfeSbeck {
256ac5ed168Sbeck 	X509 *match = NULL;
25723258cfeSbeck 	int i;
25823258cfeSbeck 
2599ab39fd2Sbeck 	if (!x509_verify_cert_cache_extensions(cert))
2609ab39fd2Sbeck 		return 0;
2619ab39fd2Sbeck 
262ac5ed168Sbeck 	/* Check by lookup if we have a legacy xsc */
263ac5ed168Sbeck 	if (ctx->xsc != NULL) {
2644e6a4da2Sbeck 		/*
2654e6a4da2Sbeck 		 * "alternative" lookup method, using the "trusted" stack in the
2664e6a4da2Sbeck 		 * xsc as the source for roots.
2674e6a4da2Sbeck 		 */
2684e6a4da2Sbeck 		if (ctx->xsc->trusted != NULL) {
2694e6a4da2Sbeck 			for (i = 0; i < sk_X509_num(ctx->xsc->trusted); i++) {
2704e6a4da2Sbeck 				if (X509_cmp(sk_X509_value(ctx->xsc->trusted,
2714e6a4da2Sbeck 				    i), cert) == 0)
2724e6a4da2Sbeck 					return x509_verify_check_chain_end(cert,
2734e6a4da2Sbeck 					    full_chain);
2744e6a4da2Sbeck 			}
2754e6a4da2Sbeck 		}
276ac5ed168Sbeck 		if ((match = x509_vfy_lookup_cert_match(ctx->xsc,
277ac5ed168Sbeck 		    cert)) != NULL) {
278ac5ed168Sbeck 			X509_free(match);
2793c8bff2fSbeck 			return x509_verify_check_chain_end(cert, full_chain);
280ac5ed168Sbeck 		}
28199d404ebSbeck 	} else {
28299d404ebSbeck 		/* Check the provided roots */
28399d404ebSbeck 		for (i = 0; i < sk_X509_num(ctx->roots); i++) {
28499d404ebSbeck 			if (X509_cmp(sk_X509_value(ctx->roots, i), cert) == 0)
285d8913d6aSbeck 				return x509_verify_check_chain_end(cert,
286d8913d6aSbeck 				    full_chain);
28799d404ebSbeck 		}
288ac5ed168Sbeck 	}
289ac5ed168Sbeck 
29023258cfeSbeck 	return 0;
29123258cfeSbeck }
29223258cfeSbeck 
293733666e3Sjsing static int
x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx * ctx,struct x509_verify_chain * chain,int set_error,int is_trusted)294733666e3Sjsing x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx,
295d095297bStb     struct x509_verify_chain *chain, int set_error, int is_trusted)
296733666e3Sjsing {
2975d6c9775Sjsing 	size_t num_untrusted;
298a235c622Sjsing 	int i;
299733666e3Sjsing 
300733666e3Sjsing 	if (ctx->xsc == NULL)
301733666e3Sjsing 		return 1;
302733666e3Sjsing 
303d095297bStb 	/*
304e30c9e23Stb 	 * XXX num_untrusted is the number of untrusted certs at the
305d095297bStb 	 * bottom of the chain. This works now since we stop at the first
306d095297bStb 	 * trusted cert. This will need fixing once we allow more than one
307d095297bStb 	 * trusted certificate.
308d095297bStb 	 */
3095d6c9775Sjsing 	num_untrusted = sk_X509_num(chain->certs);
3105d6c9775Sjsing 	if (is_trusted && num_untrusted > 0)
3115d6c9775Sjsing 		num_untrusted--;
312e30c9e23Stb 	ctx->xsc->num_untrusted = num_untrusted;
313733666e3Sjsing 
314733666e3Sjsing 	sk_X509_pop_free(ctx->xsc->chain, X509_free);
315733666e3Sjsing 	ctx->xsc->chain = X509_chain_up_ref(chain->certs);
316733666e3Sjsing 	if (ctx->xsc->chain == NULL)
317d963395aSjsing 		return x509_verify_cert_error(ctx, NULL, 0,
318733666e3Sjsing 		    X509_V_ERR_OUT_OF_MEM, 0);
319a235c622Sjsing 
320a235c622Sjsing 	if (set_error) {
321a235c622Sjsing 		ctx->xsc->error = X509_V_OK;
322a235c622Sjsing 		ctx->xsc->error_depth = 0;
323a235c622Sjsing 		for (i = 0; i < sk_X509_num(chain->certs); i++) {
324a235c622Sjsing 			if (chain->cert_errors[i] != X509_V_OK) {
325a235c622Sjsing 				ctx->xsc->error = chain->cert_errors[i];
326a235c622Sjsing 				ctx->xsc->error_depth = i;
327a235c622Sjsing 				break;
328a235c622Sjsing 			}
329a235c622Sjsing 		}
330a235c622Sjsing 	}
331a235c622Sjsing 
332733666e3Sjsing 	return 1;
333733666e3Sjsing }
334733666e3Sjsing 
3359ab39fd2Sbeck 
3369ab39fd2Sbeck /*
3379ab39fd2Sbeck  * Save the error state and unvalidated chain off of the xsc for
3389ab39fd2Sbeck  * later.
3399ab39fd2Sbeck  */
3409ab39fd2Sbeck static int
x509_verify_ctx_save_xsc_error(struct x509_verify_ctx * ctx)3419ab39fd2Sbeck x509_verify_ctx_save_xsc_error(struct x509_verify_ctx *ctx)
3429ab39fd2Sbeck {
3439ab39fd2Sbeck 	if (ctx->xsc != NULL && ctx->xsc->chain != NULL) {
3449ab39fd2Sbeck 		sk_X509_pop_free(ctx->saved_error_chain, X509_free);
3459ab39fd2Sbeck 		ctx->saved_error_chain = X509_chain_up_ref(ctx->xsc->chain);
3469ab39fd2Sbeck 		if (ctx->saved_error_chain == NULL)
3479ab39fd2Sbeck 			return x509_verify_cert_error(ctx, NULL, 0,
3489ab39fd2Sbeck 			    X509_V_ERR_OUT_OF_MEM, 0);
3499ab39fd2Sbeck 		ctx->saved_error = ctx->xsc->error;
3509ab39fd2Sbeck 		ctx->saved_error_depth = ctx->xsc->error_depth;
3519ab39fd2Sbeck 	}
3529ab39fd2Sbeck 	return 1;
3539ab39fd2Sbeck }
3549ab39fd2Sbeck 
3559ab39fd2Sbeck /*
3569ab39fd2Sbeck  * Restore the saved error state and unvalidated chain to the xsc
3579ab39fd2Sbeck  * if we do not have a validated chain.
3589ab39fd2Sbeck  */
3599ab39fd2Sbeck static int
x509_verify_ctx_restore_xsc_error(struct x509_verify_ctx * ctx)3609ab39fd2Sbeck x509_verify_ctx_restore_xsc_error(struct x509_verify_ctx *ctx)
3619ab39fd2Sbeck {
3629ab39fd2Sbeck 	if (ctx->xsc != NULL && ctx->chains_count == 0 &&
3639ab39fd2Sbeck 	    ctx->saved_error_chain != NULL) {
3649ab39fd2Sbeck 		sk_X509_pop_free(ctx->xsc->chain, X509_free);
3659ab39fd2Sbeck 		ctx->xsc->chain = X509_chain_up_ref(ctx->saved_error_chain);
3669ab39fd2Sbeck 		if (ctx->xsc->chain == NULL)
3679ab39fd2Sbeck 			return x509_verify_cert_error(ctx, NULL, 0,
3689ab39fd2Sbeck 			    X509_V_ERR_OUT_OF_MEM, 0);
3699ab39fd2Sbeck 		ctx->xsc->error = ctx->saved_error;
3709ab39fd2Sbeck 		ctx->xsc->error_depth = ctx->saved_error_depth;
3719ab39fd2Sbeck 	}
3729ab39fd2Sbeck 	return 1;
3739ab39fd2Sbeck }
3749ab39fd2Sbeck 
375ad8616e3Sbeck /* Perform legacy style validation of a chain */
376ad8616e3Sbeck static int
x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx * ctx,struct x509_verify_chain * chain,size_t depth)377ad8616e3Sbeck x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx *ctx,
378ad8616e3Sbeck     struct x509_verify_chain *chain, size_t depth)
379ad8616e3Sbeck {
3804e67fe4cSbeck 	int ret = 0, trust;
381ad8616e3Sbeck 
382ad8616e3Sbeck 	if (ctx->xsc == NULL)
383ad8616e3Sbeck 		return 1;
384ad8616e3Sbeck 
385ad8616e3Sbeck 	/*
386ad8616e3Sbeck 	 * If we have a legacy xsc, choose a validated chain, and
387ad8616e3Sbeck 	 * apply the extensions, revocation, and policy checks just
388ad8616e3Sbeck 	 * like the legacy code did. We do this here instead of as
389ad8616e3Sbeck 	 * building the chains to more easily support the callback and
390ad8616e3Sbeck 	 * the bewildering array of VERIFY_PARAM knobs that are there
391ad8616e3Sbeck 	 * for the fiddling.
392ad8616e3Sbeck 	 */
393ad8616e3Sbeck 
394ad8616e3Sbeck 	/* These may be set in one of the following calls. */
395ad8616e3Sbeck 	ctx->xsc->error = X509_V_OK;
396ad8616e3Sbeck 	ctx->xsc->error_depth = 0;
397ad8616e3Sbeck 
398ad8616e3Sbeck 	if (!x509_verify_ctx_set_xsc_chain(ctx, chain, 0, 1))
399ad8616e3Sbeck 		goto err;
400ad8616e3Sbeck 
401ad8616e3Sbeck 	/*
402d8913d6aSbeck 	 * Call the legacy code to walk the chain and check trust
403d8913d6aSbeck 	 * in the legacy way to handle partial chains and get the
404d8913d6aSbeck 	 * callback fired correctly.
405d8913d6aSbeck 	 */
406d8913d6aSbeck 	trust = x509_vfy_check_trust(ctx->xsc);
407d8913d6aSbeck 	if (trust == X509_TRUST_REJECTED)
408d8913d6aSbeck 		goto err; /* callback was called in x509_vfy_check_trust */
409d8913d6aSbeck 	if (trust != X509_TRUST_TRUSTED) {
410d8913d6aSbeck 		/* NOTREACHED */
411d8913d6aSbeck 		goto err;  /* should not happen if we get in here - abort? */
412d8913d6aSbeck 	}
413d8913d6aSbeck 
414d8913d6aSbeck 	/*
415ad8616e3Sbeck 	 * XXX currently this duplicates some work done in chain
416ad8616e3Sbeck 	 * build, but we keep it here until we have feature parity
417ad8616e3Sbeck 	 */
418ad8616e3Sbeck 	if (!x509_vfy_check_chain_extensions(ctx->xsc))
419ad8616e3Sbeck 		goto err;
420ad8616e3Sbeck 
42169c7967eSjob #ifndef OPENSSL_NO_RFC3779
42269c7967eSjob 	if (!X509v3_asid_validate_path(ctx->xsc))
42369c7967eSjob 		goto err;
42469c7967eSjob 
42569c7967eSjob 	if (!X509v3_addr_validate_path(ctx->xsc))
42669c7967eSjob 		goto err;
42769c7967eSjob #endif
42869c7967eSjob 
429284c6bbfStb 	if (!x509_vfy_check_security_level(ctx->xsc))
430284c6bbfStb 		goto err;
431284c6bbfStb 
432ad8616e3Sbeck 	if (!x509_constraints_chain(ctx->xsc->chain,
433ad8616e3Sbeck 		&ctx->xsc->error, &ctx->xsc->error_depth)) {
434ad8616e3Sbeck 		X509 *cert = sk_X509_value(ctx->xsc->chain, depth);
435ad8616e3Sbeck 		if (!x509_verify_cert_error(ctx, cert,
436ad8616e3Sbeck 			ctx->xsc->error_depth, ctx->xsc->error, 0))
437ad8616e3Sbeck 			goto err;
438ad8616e3Sbeck 	}
439ad8616e3Sbeck 
440ad8616e3Sbeck 	if (!x509_vfy_check_revocation(ctx->xsc))
441ad8616e3Sbeck 		goto err;
442ad8616e3Sbeck 
4437d883af9Sbeck 	if (!x509_vfy_check_policy(ctx->xsc))
444ad8616e3Sbeck 		goto err;
445ad8616e3Sbeck 
446ad8616e3Sbeck 	ret = 1;
447ad8616e3Sbeck 
448ad8616e3Sbeck  err:
449ad8616e3Sbeck 	/*
450ad8616e3Sbeck 	 * The above checks may have set ctx->xsc->error and
451ad8616e3Sbeck 	 * ctx->xsc->error_depth - save these for later on.
452ad8616e3Sbeck 	 */
453ad8616e3Sbeck 	if (ctx->xsc->error != X509_V_OK) {
454ad8616e3Sbeck 		if (ctx->xsc->error_depth < 0 ||
455ad8616e3Sbeck 		    ctx->xsc->error_depth >= X509_VERIFY_MAX_CHAIN_CERTS)
456ad8616e3Sbeck 			return 0;
457ad8616e3Sbeck 		chain->cert_errors[ctx->xsc->error_depth] =
458ad8616e3Sbeck 		    ctx->xsc->error;
45989ae9cb0Sbeck 		ctx->error_depth = ctx->xsc->error_depth;
460ad8616e3Sbeck 	}
461ad8616e3Sbeck 
462ad8616e3Sbeck 	return ret;
463ad8616e3Sbeck }
464ad8616e3Sbeck 
46523258cfeSbeck /* Add a validated chain to our list of valid chains */
46623258cfeSbeck static int
x509_verify_ctx_add_chain(struct x509_verify_ctx * ctx,struct x509_verify_chain * chain,char * name)46723258cfeSbeck x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
468b8644936Sbeck     struct x509_verify_chain *chain, char *name)
46923258cfeSbeck {
47023258cfeSbeck 	size_t depth;
47123258cfeSbeck 	X509 *last = x509_verify_chain_last(chain);
472b8644936Sbeck 	X509 *leaf = x509_verify_chain_leaf(chain);
47323258cfeSbeck 
47423258cfeSbeck 	depth = sk_X509_num(chain->certs);
47523258cfeSbeck 	if (depth > 0)
47623258cfeSbeck 		depth--;
47723258cfeSbeck 
47823258cfeSbeck 	if (ctx->chains_count >= ctx->max_chains)
47923258cfeSbeck 		return x509_verify_cert_error(ctx, last, depth,
48023258cfeSbeck 		    X509_V_ERR_CERT_CHAIN_TOO_LONG, 0);
48123258cfeSbeck 
482a235c622Sjsing 	/* Clear a get issuer failure for a root certificate. */
483a235c622Sjsing 	if (chain->cert_errors[depth] ==
48450df4f34Sbeck 	    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
485a235c622Sjsing 		chain->cert_errors[depth] = X509_V_OK;
486a235c622Sjsing 
487ad8616e3Sbeck 	if (!x509_verify_ctx_validate_legacy_chain(ctx, chain, depth))
488733666e3Sjsing 		return 0;
48923258cfeSbeck 
4904f94258cSjsing 	/* Verify the leaf certificate and store any resulting error. */
4914f94258cSjsing 	if (!x509_verify_cert_valid(ctx, leaf, NULL))
4924f94258cSjsing 		return 0;
4934f94258cSjsing 	if (!x509_verify_cert_hostname(ctx, leaf, name))
4944f94258cSjsing 		return 0;
4954f94258cSjsing 	if (ctx->error_depth == 0 &&
4964f94258cSjsing 	    ctx->error != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
4974f94258cSjsing 		chain->cert_errors[0] = ctx->error;
4984f94258cSjsing 
49923258cfeSbeck 	/*
500ad8616e3Sbeck 	 * In the non-legacy code, extensions and purpose are dealt
501ad8616e3Sbeck 	 * with as the chain is built.
50223258cfeSbeck 	 *
50323258cfeSbeck 	 * The non-legacy api returns multiple chains but does not do
50423258cfeSbeck 	 * any revocation checking (it must be done by the caller on
50523258cfeSbeck 	 * any chain they wish to use)
50623258cfeSbeck 	 */
50723258cfeSbeck 
50823258cfeSbeck 	if ((ctx->chains[ctx->chains_count] = x509_verify_chain_dup(chain)) ==
50923258cfeSbeck 	    NULL) {
51023258cfeSbeck 		return x509_verify_cert_error(ctx, last, depth,
51123258cfeSbeck 		    X509_V_ERR_OUT_OF_MEM, 0);
51223258cfeSbeck 	}
51323258cfeSbeck 	ctx->chains_count++;
5144f94258cSjsing 
51523258cfeSbeck 	ctx->error = X509_V_OK;
51623258cfeSbeck 	ctx->error_depth = depth;
5174f94258cSjsing 
51823258cfeSbeck 	return 1;
51923258cfeSbeck }
52023258cfeSbeck 
52123258cfeSbeck static int
x509_verify_potential_parent(struct x509_verify_ctx * ctx,X509 * parent,X509 * child)52223258cfeSbeck x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent,
52323258cfeSbeck     X509 *child)
52423258cfeSbeck {
5259ab39fd2Sbeck 	if (!x509_verify_cert_cache_extensions(parent))
5269ab39fd2Sbeck 		return 0;
52723258cfeSbeck 	if (ctx->xsc != NULL)
52823258cfeSbeck 		return (ctx->xsc->check_issued(ctx->xsc, child, parent));
52923258cfeSbeck 
53023258cfeSbeck 	/* XXX key usage */
531*41c05129Stb 	return X509_check_issued(parent, child) == X509_V_OK;
53223258cfeSbeck }
53323258cfeSbeck 
53423258cfeSbeck static int
x509_verify_parent_signature(X509 * parent,X509 * child,int * error)53588e5d447Sbeck x509_verify_parent_signature(X509 *parent, X509 *child, int *error)
53623258cfeSbeck {
53723258cfeSbeck 	EVP_PKEY *pkey;
53823258cfeSbeck 	int cached;
53923258cfeSbeck 	int ret = 0;
54023258cfeSbeck 
54123258cfeSbeck 	/* Use cached value if we have it */
54288e5d447Sbeck 	if ((cached = x509_issuer_cache_find(parent->hash, child->hash)) >= 0)
54323258cfeSbeck 		return cached;
54423258cfeSbeck 
54523258cfeSbeck 	/* Check signature. Did parent sign child? */
54623258cfeSbeck 	if ((pkey = X509_get_pubkey(parent)) == NULL) {
54723258cfeSbeck 		*error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
54823258cfeSbeck 		return 0;
54923258cfeSbeck 	}
55023258cfeSbeck 	if (X509_verify(child, pkey) <= 0)
55123258cfeSbeck 		*error = X509_V_ERR_CERT_SIGNATURE_FAILURE;
55223258cfeSbeck 	else
55323258cfeSbeck 		ret = 1;
55423258cfeSbeck 
55523258cfeSbeck 	/* Add result to cache */
55688e5d447Sbeck 	x509_issuer_cache_add(parent->hash, child->hash, ret);
55723258cfeSbeck 
55823258cfeSbeck 	EVP_PKEY_free(pkey);
55923258cfeSbeck 
56023258cfeSbeck 	return ret;
56123258cfeSbeck }
56223258cfeSbeck 
56323258cfeSbeck static int
x509_verify_consider_candidate(struct x509_verify_ctx * ctx,X509 * cert,int is_root_cert,X509 * candidate,struct x509_verify_chain * current_chain,int full_chain,char * name)56423258cfeSbeck x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
56588e5d447Sbeck     int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain,
566b8644936Sbeck     int full_chain, char *name)
56723258cfeSbeck {
56823258cfeSbeck 	int depth = sk_X509_num(current_chain->certs);
56923258cfeSbeck 	struct x509_verify_chain *new_chain;
57023258cfeSbeck 	int i;
57123258cfeSbeck 
57223258cfeSbeck 	/* Fail if the certificate is already in the chain */
57323258cfeSbeck 	for (i = 0; i < sk_X509_num(current_chain->certs); i++) {
57423258cfeSbeck 		if (X509_cmp(sk_X509_value(current_chain->certs, i),
57576d63a55Sbeck 		    candidate) == 0)
57623258cfeSbeck 			return 0;
57723258cfeSbeck 	}
57823258cfeSbeck 
57923258cfeSbeck 	if (ctx->sig_checks++ > X509_VERIFY_MAX_SIGCHECKS) {
58023258cfeSbeck 		/* don't allow callback to override safety check */
58123258cfeSbeck 		(void) x509_verify_cert_error(ctx, candidate, depth,
58223258cfeSbeck 		    X509_V_ERR_CERT_CHAIN_TOO_LONG, 0);
58323258cfeSbeck 		return 0;
58423258cfeSbeck 	}
58523258cfeSbeck 
58688e5d447Sbeck 	if (!x509_verify_parent_signature(candidate, cert, &ctx->error)) {
58723258cfeSbeck 		if (!x509_verify_cert_error(ctx, candidate, depth,
58823258cfeSbeck 		    ctx->error, 0))
58923258cfeSbeck 			return 0;
59023258cfeSbeck 	}
59123258cfeSbeck 
59223258cfeSbeck 	if (!x509_verify_cert_valid(ctx, candidate, current_chain))
59323258cfeSbeck 		return 0;
59423258cfeSbeck 
59523258cfeSbeck 	/* candidate is good, add it to a copy of the current chain */
59623258cfeSbeck 	if ((new_chain = x509_verify_chain_dup(current_chain)) == NULL) {
59723258cfeSbeck 		x509_verify_cert_error(ctx, candidate, depth,
59823258cfeSbeck 		    X509_V_ERR_OUT_OF_MEM, 0);
59923258cfeSbeck 		return 0;
60023258cfeSbeck 	}
60123258cfeSbeck 	if (!x509_verify_chain_append(new_chain, candidate, &ctx->error)) {
602a235c622Sjsing 		x509_verify_cert_error(ctx, candidate, depth, ctx->error, 0);
60323258cfeSbeck 		x509_verify_chain_free(new_chain);
60423258cfeSbeck 		return 0;
60523258cfeSbeck 	}
60623258cfeSbeck 
60723258cfeSbeck 	/*
60823258cfeSbeck 	 * If candidate is a trusted root, we have a validated chain,
60923258cfeSbeck 	 * so we save it.  Otherwise, recurse until we find a root or
61023258cfeSbeck 	 * give up.
61123258cfeSbeck 	 */
612733666e3Sjsing 	if (is_root_cert) {
613d095297bStb 		if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain, 0, 1)) {
614733666e3Sjsing 			x509_verify_chain_free(new_chain);
615733666e3Sjsing 			return 0;
616733666e3Sjsing 		}
617b8644936Sbeck 		if (!x509_verify_ctx_add_chain(ctx, new_chain, name)) {
61889ae9cb0Sbeck 			x509_verify_chain_free(new_chain);
61989ae9cb0Sbeck 			return 0;
620733666e3Sjsing 		}
62189ae9cb0Sbeck 		goto done;
622733666e3Sjsing 	}
623733666e3Sjsing 
624b8644936Sbeck 	x509_verify_build_chains(ctx, candidate, new_chain, full_chain, name);
62523258cfeSbeck 
626733666e3Sjsing  done:
62723258cfeSbeck 	x509_verify_chain_free(new_chain);
62823258cfeSbeck 	return 1;
62923258cfeSbeck }
63023258cfeSbeck 
63123258cfeSbeck static int
x509_verify_cert_error(struct x509_verify_ctx * ctx,X509 * cert,size_t depth,int error,int ok)63223258cfeSbeck x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth,
63323258cfeSbeck     int error, int ok)
63423258cfeSbeck {
63523258cfeSbeck 	ctx->error = error;
63623258cfeSbeck 	ctx->error_depth = depth;
63723258cfeSbeck 	if (ctx->xsc != NULL) {
63823258cfeSbeck 		ctx->xsc->error = error;
63923258cfeSbeck 		ctx->xsc->error_depth = depth;
64023258cfeSbeck 		ctx->xsc->current_cert = cert;
64123258cfeSbeck 		return ctx->xsc->verify_cb(ok, ctx->xsc);
64223258cfeSbeck 	}
64323258cfeSbeck 	return ok;
64423258cfeSbeck }
64523258cfeSbeck 
64623258cfeSbeck static void
x509_verify_build_chains(struct x509_verify_ctx * ctx,X509 * cert,struct x509_verify_chain * current_chain,int full_chain,char * name)64723258cfeSbeck x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
648b8644936Sbeck     struct x509_verify_chain *current_chain, int full_chain, char *name)
64923258cfeSbeck {
65023258cfeSbeck 	X509 *candidate;
6519ab39fd2Sbeck 	int i, depth, count, ret, is_root;
65223258cfeSbeck 
6534f6c473eSbeck 	/*
6544f6c473eSbeck 	 * If we are finding chains with an xsc, just stop after we have
6554f6c473eSbeck 	 * one chain, there's no point in finding more, it just exercises
6564f6c473eSbeck 	 * the potentially buggy callback processing in the calling software.
6574f6c473eSbeck 	 */
6584f6c473eSbeck 	if (ctx->xsc != NULL && ctx->chains_count > 0)
6594f6c473eSbeck 		return;
6604f6c473eSbeck 
66123258cfeSbeck 	depth = sk_X509_num(current_chain->certs);
66223258cfeSbeck 	if (depth > 0)
66323258cfeSbeck 		depth--;
66423258cfeSbeck 
66523258cfeSbeck 	if (depth >= ctx->max_depth &&
66623258cfeSbeck 	    !x509_verify_cert_error(ctx, cert, depth,
66723258cfeSbeck 		X509_V_ERR_CERT_CHAIN_TOO_LONG, 0))
66823258cfeSbeck 		return;
66923258cfeSbeck 
67023258cfeSbeck 	count = ctx->chains_count;
67189ae9cb0Sbeck 
67250df4f34Sbeck 	ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
67323258cfeSbeck 	ctx->error_depth = depth;
67489ae9cb0Sbeck 
67589ae9cb0Sbeck 	if (ctx->saved_error != 0)
67689ae9cb0Sbeck 		ctx->error = ctx->saved_error;
67789ae9cb0Sbeck 	if (ctx->saved_error_depth != 0)
67889ae9cb0Sbeck 		ctx->error_depth = ctx->saved_error_depth;
67989ae9cb0Sbeck 
680ddb051cdSbeck 	if (ctx->xsc != NULL) {
681ddb051cdSbeck 		/*
682ddb051cdSbeck 		 * Long ago experiments at Muppet labs resulted in a
683ddb051cdSbeck 		 * situation where software not only sees these errors
684ddb051cdSbeck 		 * but forced developers to expect them in certain cases.
685ddb051cdSbeck 		 * so we must mimic this awfulness for the legacy case.
686ddb051cdSbeck 		 */
687ddb051cdSbeck 		if (cert->ex_flags & EXFLAG_SS)
688ddb051cdSbeck 			ctx->error = (depth == 0) ?
689ddb051cdSbeck 			    X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
690ddb051cdSbeck 			    X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
691ddb051cdSbeck 	}
69223258cfeSbeck 
69358d6c226Sbeck 	/* Check for legacy mode roots */
694e096bf87Sjsing 	if (ctx->xsc != NULL) {
695e096bf87Sjsing 		if ((ret = ctx->xsc->get_issuer(&candidate, ctx->xsc, cert)) < 0) {
696e096bf87Sjsing 			x509_verify_cert_error(ctx, cert, depth,
697e096bf87Sjsing 			    X509_V_ERR_STORE_LOOKUP, 0);
698e096bf87Sjsing 			return;
699e096bf87Sjsing 		}
700e096bf87Sjsing 		if (ret > 0) {
701e096bf87Sjsing 			if (x509_verify_potential_parent(ctx, candidate, cert)) {
7023c8bff2fSbeck 				is_root = x509_verify_check_chain_end(candidate,
7033c8bff2fSbeck 				    full_chain);
704e096bf87Sjsing 				x509_verify_consider_candidate(ctx, cert,
70588e5d447Sbeck 				    is_root, candidate, current_chain,
706b8644936Sbeck 				    full_chain, name);
707e096bf87Sjsing 			}
708e096bf87Sjsing 			X509_free(candidate);
709e096bf87Sjsing 		}
71099d404ebSbeck 	} else {
71199d404ebSbeck 		/* Check to see if we have a trusted root issuer. */
71299d404ebSbeck 		for (i = 0; i < sk_X509_num(ctx->roots); i++) {
71399d404ebSbeck 			candidate = sk_X509_value(ctx->roots, i);
71499d404ebSbeck 			if (x509_verify_potential_parent(ctx, candidate, cert)) {
715d8913d6aSbeck 				is_root = x509_verify_check_chain_end(candidate,
716d8913d6aSbeck 				    full_chain);
71799d404ebSbeck 				x509_verify_consider_candidate(ctx, cert,
71888e5d447Sbeck 				    is_root, candidate, current_chain,
719b8644936Sbeck 				    full_chain, name);
72099d404ebSbeck 			}
72199d404ebSbeck 		}
722e096bf87Sjsing 	}
723e096bf87Sjsing 
72458d6c226Sbeck 	/* Check intermediates after checking roots */
72558d6c226Sbeck 	if (ctx->intermediates != NULL) {
72658d6c226Sbeck 		for (i = 0; i < sk_X509_num(ctx->intermediates); i++) {
72758d6c226Sbeck 			candidate = sk_X509_value(ctx->intermediates, i);
72858d6c226Sbeck 			if (x509_verify_potential_parent(ctx, candidate, cert)) {
72958d6c226Sbeck 				x509_verify_consider_candidate(ctx, cert,
73088e5d447Sbeck 				    0, candidate, current_chain,
731b8644936Sbeck 				    full_chain, name);
73258d6c226Sbeck 			}
73358d6c226Sbeck 		}
73458d6c226Sbeck 	}
73558d6c226Sbeck 
73623258cfeSbeck 	if (ctx->chains_count > count) {
73723258cfeSbeck 		if (ctx->xsc != NULL) {
73823258cfeSbeck 			ctx->xsc->error = X509_V_OK;
73923258cfeSbeck 			ctx->xsc->error_depth = depth;
74023258cfeSbeck 			ctx->xsc->current_cert = cert;
74123258cfeSbeck 		}
74276d63a55Sbeck 	} else if (ctx->error_depth == depth) {
743d095297bStb 		if (!x509_verify_ctx_set_xsc_chain(ctx, current_chain, 0, 0))
744532f0381Sjsing 			return;
74523258cfeSbeck 	}
74623258cfeSbeck }
74723258cfeSbeck 
74823258cfeSbeck static int
x509_verify_cert_hostname(struct x509_verify_ctx * ctx,X509 * cert,char * name)74923258cfeSbeck x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, char *name)
75023258cfeSbeck {
75123258cfeSbeck 	char *candidate;
75223258cfeSbeck 	size_t len;
75323258cfeSbeck 
75423258cfeSbeck 	if (name == NULL) {
755f31559c1Stb 		if (ctx->xsc != NULL) {
756f31559c1Stb 			int ret;
757f31559c1Stb 
758f31559c1Stb 			if ((ret = x509_vfy_check_id(ctx->xsc)) == 0)
759f31559c1Stb 				ctx->error = ctx->xsc->error;
760f31559c1Stb 			return ret;
761f31559c1Stb 		}
76223258cfeSbeck 		return 1;
76323258cfeSbeck 	}
76423258cfeSbeck 	if ((candidate = strdup(name)) == NULL) {
76523258cfeSbeck 		ctx->error = X509_V_ERR_OUT_OF_MEM;
76623258cfeSbeck 		goto err;
76723258cfeSbeck 	}
76823258cfeSbeck 	if ((len = strlen(candidate)) < 1) {
76923258cfeSbeck 		ctx->error = X509_V_ERR_UNSPECIFIED; /* XXX */
77023258cfeSbeck 		goto err;
77123258cfeSbeck 	}
77223258cfeSbeck 
77323258cfeSbeck 	/* IP addresses may be written in [ ]. */
77423258cfeSbeck 	if (candidate[0] == '[' && candidate[len - 1] == ']') {
77523258cfeSbeck 		candidate[len - 1] = '\0';
77623258cfeSbeck 		if (X509_check_ip_asc(cert, candidate + 1, 0) <= 0) {
77723258cfeSbeck 			ctx->error = X509_V_ERR_IP_ADDRESS_MISMATCH;
77823258cfeSbeck 			goto err;
77923258cfeSbeck 		}
78023258cfeSbeck 	} else {
78123258cfeSbeck 		int flags = 0;
78223258cfeSbeck 
78323258cfeSbeck 		if (ctx->xsc == NULL)
78423258cfeSbeck 			flags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT;
78523258cfeSbeck 
78623258cfeSbeck 		if (X509_check_host(cert, candidate, len, flags, NULL) <= 0) {
78723258cfeSbeck 			ctx->error = X509_V_ERR_HOSTNAME_MISMATCH;
78823258cfeSbeck 			goto err;
78923258cfeSbeck 		}
79023258cfeSbeck 	}
79123258cfeSbeck 	free(candidate);
79223258cfeSbeck 	return 1;
79323258cfeSbeck  err:
79423258cfeSbeck 	free(candidate);
79523258cfeSbeck 	return x509_verify_cert_error(ctx, cert, 0, ctx->error, 0);
79623258cfeSbeck }
79723258cfeSbeck 
79823258cfeSbeck static int
x509_verify_set_check_time(struct x509_verify_ctx * ctx)799947886bcSjsing x509_verify_set_check_time(struct x509_verify_ctx *ctx)
800947886bcSjsing {
80123258cfeSbeck 	if (ctx->xsc != NULL)  {
80223258cfeSbeck 		if (ctx->xsc->param->flags & X509_V_FLAG_USE_CHECK_TIME) {
80323258cfeSbeck 			ctx->check_time = &ctx->xsc->param->check_time;
80423258cfeSbeck 			return 1;
80523258cfeSbeck 		}
80623258cfeSbeck 		if (ctx->xsc->param->flags & X509_V_FLAG_NO_CHECK_TIME)
80723258cfeSbeck 			return 0;
80823258cfeSbeck 	}
80923258cfeSbeck 
81023258cfeSbeck 	ctx->check_time = NULL;
81123258cfeSbeck 	return 1;
81223258cfeSbeck }
81323258cfeSbeck 
81423258cfeSbeck static int
x509_verify_cert_times(X509 * cert,time_t * cmp_time,int * error)81588e5d447Sbeck x509_verify_cert_times(X509 *cert, time_t *cmp_time, int *error)
81623258cfeSbeck {
817cc34b9f0Sbeck 	time_t when, not_before, not_after;
81823258cfeSbeck 
81923258cfeSbeck 	if (cmp_time == NULL)
82023258cfeSbeck 		when = time(NULL);
82123258cfeSbeck 	else
82223258cfeSbeck 		when = *cmp_time;
82323258cfeSbeck 
824cc34b9f0Sbeck 	if (!x509_verify_asn1_time_to_time_t(X509_get_notBefore(cert), 0,
825cc34b9f0Sbeck 	    &not_before)) {
82688e5d447Sbeck 		*error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
82723258cfeSbeck 		return 0;
82823258cfeSbeck 	}
829cc34b9f0Sbeck 	if (when < not_before) {
83023258cfeSbeck 		*error = X509_V_ERR_CERT_NOT_YET_VALID;
83123258cfeSbeck 		return 0;
83223258cfeSbeck 	}
833cc34b9f0Sbeck 	if (!x509_verify_asn1_time_to_time_t(X509_get_notAfter(cert), 1,
834cc34b9f0Sbeck 	    &not_after)) {
83588e5d447Sbeck 		*error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
83688e5d447Sbeck 		return 0;
83788e5d447Sbeck 	}
838cc34b9f0Sbeck 	if (when > not_after) {
83988e5d447Sbeck 		*error = X509_V_ERR_CERT_HAS_EXPIRED;
84088e5d447Sbeck 		return 0;
84123258cfeSbeck 	}
84223258cfeSbeck 
84323258cfeSbeck 	return 1;
84423258cfeSbeck }
84523258cfeSbeck 
84623258cfeSbeck static int
x509_verify_validate_constraints(X509 * cert,struct x509_verify_chain * current_chain,int * error)84723258cfeSbeck x509_verify_validate_constraints(X509 *cert,
84823258cfeSbeck     struct x509_verify_chain *current_chain, int *error)
84923258cfeSbeck {
85023258cfeSbeck 	struct x509_constraints_names *excluded = NULL;
85123258cfeSbeck 	struct x509_constraints_names *permitted = NULL;
85223258cfeSbeck 	int err = X509_V_ERR_UNSPECIFIED;
85323258cfeSbeck 
85423258cfeSbeck 	if (current_chain == NULL)
85523258cfeSbeck 		return 1;
85623258cfeSbeck 
85723258cfeSbeck 	if (cert->nc != NULL) {
85842f3108aStb 		if ((permitted = x509_constraints_names_new(
85942f3108aStb 		    X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) {
86023258cfeSbeck 			err = X509_V_ERR_OUT_OF_MEM;
86123258cfeSbeck 			goto err;
86223258cfeSbeck 		}
86342f3108aStb 		if ((excluded = x509_constraints_names_new(
86442f3108aStb 		    X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) {
86523258cfeSbeck 			err = X509_V_ERR_OUT_OF_MEM;
86623258cfeSbeck 			goto err;
86723258cfeSbeck 		}
86823258cfeSbeck 		if (!x509_constraints_extract_constraints(cert,
86923258cfeSbeck 		    permitted, excluded, &err))
87023258cfeSbeck 			goto err;
87123258cfeSbeck 		if (!x509_constraints_check(current_chain->names,
87223258cfeSbeck 		    permitted, excluded, &err))
87323258cfeSbeck 			goto err;
87423258cfeSbeck 		x509_constraints_names_free(excluded);
87523258cfeSbeck 		x509_constraints_names_free(permitted);
87623258cfeSbeck 	}
87723258cfeSbeck 
87823258cfeSbeck 	return 1;
87923258cfeSbeck  err:
88023258cfeSbeck 	*error = err;
88123258cfeSbeck 	x509_constraints_names_free(excluded);
88223258cfeSbeck 	x509_constraints_names_free(permitted);
88323258cfeSbeck 	return 0;
88423258cfeSbeck }
88523258cfeSbeck 
88623258cfeSbeck static int
x509_verify_cert_extensions(struct x509_verify_ctx * ctx,X509 * cert,int need_ca)88723258cfeSbeck x509_verify_cert_extensions(struct x509_verify_ctx *ctx, X509 *cert, int need_ca)
88823258cfeSbeck {
889bf735c1eSbeck 	if (!x509_verify_cert_cache_extensions(cert)) {
8903746f1b0Stobhe 		ctx->error = X509_V_ERR_UNSPECIFIED;
8913746f1b0Stobhe 		return 0;
8923746f1b0Stobhe 	}
89323258cfeSbeck 
89423258cfeSbeck 	if (ctx->xsc != NULL)
89523258cfeSbeck 		return 1;	/* legacy is checked after chain is built */
89623258cfeSbeck 
89723258cfeSbeck 	if (cert->ex_flags & EXFLAG_CRITICAL) {
89823258cfeSbeck 		ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
89923258cfeSbeck 		return 0;
90023258cfeSbeck 	}
90123258cfeSbeck 	/* No we don't care about v1, netscape, and other ancient silliness */
90223258cfeSbeck 	if (need_ca && (!(cert->ex_flags & EXFLAG_BCONS) &&
90323258cfeSbeck 	    (cert->ex_flags & EXFLAG_CA))) {
90423258cfeSbeck 		ctx->error = X509_V_ERR_INVALID_CA;
90523258cfeSbeck 		return 0;
90623258cfeSbeck 	}
90723258cfeSbeck 	if (ctx->purpose > 0 && X509_check_purpose(cert, ctx->purpose, need_ca)) {
90823258cfeSbeck 		ctx->error = X509_V_ERR_INVALID_PURPOSE;
90923258cfeSbeck 		return 0;
91023258cfeSbeck 	}
91123258cfeSbeck 
91223258cfeSbeck 	return 1;
91323258cfeSbeck }
91423258cfeSbeck 
91523258cfeSbeck /* Validate that cert is a possible candidate to append to current_chain */
91623258cfeSbeck static int
x509_verify_cert_valid(struct x509_verify_ctx * ctx,X509 * cert,struct x509_verify_chain * current_chain)91723258cfeSbeck x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert,
91823258cfeSbeck     struct x509_verify_chain *current_chain)
91923258cfeSbeck {
92023258cfeSbeck 	X509 *issuer_candidate;
92123258cfeSbeck 	int should_be_ca = current_chain != NULL;
92223258cfeSbeck 	size_t depth = 0;
92323258cfeSbeck 
924ec12bfceSbeck 	if (current_chain != NULL)
92523258cfeSbeck 		depth = sk_X509_num(current_chain->certs);
92623258cfeSbeck 
92723258cfeSbeck 	if (!x509_verify_cert_extensions(ctx, cert, should_be_ca))
92823258cfeSbeck 		return 0;
92923258cfeSbeck 
93023258cfeSbeck 	if (should_be_ca) {
93123258cfeSbeck 		issuer_candidate = x509_verify_chain_last(current_chain);
93223258cfeSbeck 		if (issuer_candidate != NULL &&
93323258cfeSbeck 		    !X509_check_issued(issuer_candidate, cert))
93423258cfeSbeck 			if (!x509_verify_cert_error(ctx, cert, depth,
93523258cfeSbeck 			    X509_V_ERR_SUBJECT_ISSUER_MISMATCH, 0))
93623258cfeSbeck 				return 0;
93723258cfeSbeck 	}
93823258cfeSbeck 
93923258cfeSbeck 	if (x509_verify_set_check_time(ctx)) {
94088e5d447Sbeck 		if (!x509_verify_cert_times(cert, ctx->check_time,
94188e5d447Sbeck 		    &ctx->error)) {
94223258cfeSbeck 			if (!x509_verify_cert_error(ctx, cert, depth,
94323258cfeSbeck 			    ctx->error, 0))
94423258cfeSbeck 				return 0;
94523258cfeSbeck 		}
94623258cfeSbeck 	}
94723258cfeSbeck 
94823258cfeSbeck 	if (!x509_verify_validate_constraints(cert, current_chain,
94923258cfeSbeck 	    &ctx->error) && !x509_verify_cert_error(ctx, cert, depth,
95023258cfeSbeck 	    ctx->error, 0))
95123258cfeSbeck 		return 0;
95223258cfeSbeck 
95323258cfeSbeck 	return 1;
95423258cfeSbeck }
95523258cfeSbeck 
95623258cfeSbeck struct x509_verify_ctx *
x509_verify_ctx_new_from_xsc(X509_STORE_CTX * xsc)95799d404ebSbeck x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc)
95823258cfeSbeck {
95923258cfeSbeck 	struct x509_verify_ctx *ctx;
9602c940cf3Sjsing 	size_t max_depth;
96123258cfeSbeck 
96223258cfeSbeck 	if (xsc == NULL)
96323258cfeSbeck 		return NULL;
96423258cfeSbeck 
96599d404ebSbeck 	if ((ctx = x509_verify_ctx_new(NULL)) == NULL)
96623258cfeSbeck 		return NULL;
96723258cfeSbeck 
96823258cfeSbeck 	ctx->xsc = xsc;
96923258cfeSbeck 
97023258cfeSbeck 	if (xsc->untrusted &&
97123258cfeSbeck 	    (ctx->intermediates = X509_chain_up_ref(xsc->untrusted)) == NULL)
97223258cfeSbeck 		goto err;
97323258cfeSbeck 
9742c940cf3Sjsing 	max_depth = X509_VERIFY_MAX_CHAIN_CERTS;
9752c940cf3Sjsing 	if (xsc->param->depth > 0 && xsc->param->depth < X509_VERIFY_MAX_CHAIN_CERTS)
9762c940cf3Sjsing 		max_depth = xsc->param->depth;
9772c940cf3Sjsing 	if (!x509_verify_ctx_set_max_depth(ctx, max_depth))
97823258cfeSbeck 		goto err;
97923258cfeSbeck 
98023258cfeSbeck 	return ctx;
98123258cfeSbeck  err:
98223258cfeSbeck 	x509_verify_ctx_free(ctx);
98323258cfeSbeck 	return NULL;
98423258cfeSbeck }
98523258cfeSbeck 
98623258cfeSbeck /* Public API */
98723258cfeSbeck 
98823258cfeSbeck struct x509_verify_ctx *
x509_verify_ctx_new(STACK_OF (X509)* roots)98923258cfeSbeck x509_verify_ctx_new(STACK_OF(X509) *roots)
99023258cfeSbeck {
99123258cfeSbeck 	struct x509_verify_ctx *ctx;
99223258cfeSbeck 
99323258cfeSbeck 	if ((ctx = calloc(1, sizeof(struct x509_verify_ctx))) == NULL)
99423258cfeSbeck 		return NULL;
99523258cfeSbeck 
99699d404ebSbeck 	if (roots != NULL) {
99723258cfeSbeck 		if  ((ctx->roots = X509_chain_up_ref(roots)) == NULL)
99823258cfeSbeck 			goto err;
99999d404ebSbeck 	} else {
100099d404ebSbeck 		if ((ctx->roots = sk_X509_new_null()) == NULL)
100199d404ebSbeck 			goto err;
100299d404ebSbeck 	}
100323258cfeSbeck 
100423258cfeSbeck 	ctx->max_depth = X509_VERIFY_MAX_CHAIN_CERTS;
100523258cfeSbeck 	ctx->max_chains = X509_VERIFY_MAX_CHAINS;
100623258cfeSbeck 	ctx->max_sigs = X509_VERIFY_MAX_SIGCHECKS;
100723258cfeSbeck 
100823258cfeSbeck 	if ((ctx->chains = calloc(X509_VERIFY_MAX_CHAINS,
100923258cfeSbeck 	    sizeof(*ctx->chains))) == NULL)
101023258cfeSbeck 		goto err;
101123258cfeSbeck 
101223258cfeSbeck 	return ctx;
101323258cfeSbeck  err:
101423258cfeSbeck 	x509_verify_ctx_free(ctx);
101523258cfeSbeck 	return NULL;
101623258cfeSbeck }
101723258cfeSbeck 
101823258cfeSbeck void
x509_verify_ctx_free(struct x509_verify_ctx * ctx)101923258cfeSbeck x509_verify_ctx_free(struct x509_verify_ctx *ctx)
102023258cfeSbeck {
102123258cfeSbeck 	if (ctx == NULL)
102223258cfeSbeck 		return;
102323258cfeSbeck 	sk_X509_pop_free(ctx->roots, X509_free);
102423258cfeSbeck 	x509_verify_ctx_clear(ctx);
102523258cfeSbeck 	free(ctx);
102623258cfeSbeck }
102723258cfeSbeck 
102823258cfeSbeck int
x509_verify_ctx_set_max_depth(struct x509_verify_ctx * ctx,size_t max)102923258cfeSbeck x509_verify_ctx_set_max_depth(struct x509_verify_ctx *ctx, size_t max)
103023258cfeSbeck {
103123258cfeSbeck 	if (max < 1 || max > X509_VERIFY_MAX_CHAIN_CERTS)
103223258cfeSbeck 		return 0;
103323258cfeSbeck 	ctx->max_depth = max;
103423258cfeSbeck 	return 1;
103523258cfeSbeck }
103623258cfeSbeck 
103723258cfeSbeck int
x509_verify_ctx_set_max_chains(struct x509_verify_ctx * ctx,size_t max)103823258cfeSbeck x509_verify_ctx_set_max_chains(struct x509_verify_ctx *ctx, size_t max)
103923258cfeSbeck {
104023258cfeSbeck 	if (max < 1 || max > X509_VERIFY_MAX_CHAINS)
104123258cfeSbeck 		return 0;
104223258cfeSbeck 	ctx->max_chains = max;
104323258cfeSbeck 	return 1;
104423258cfeSbeck }
104523258cfeSbeck 
104623258cfeSbeck int
x509_verify_ctx_set_max_signatures(struct x509_verify_ctx * ctx,size_t max)104723258cfeSbeck x509_verify_ctx_set_max_signatures(struct x509_verify_ctx *ctx, size_t max)
104823258cfeSbeck {
10499f2be83cSjsing 	if (max < 1 || max > 100000)
105023258cfeSbeck 		return 0;
105123258cfeSbeck 	ctx->max_sigs = max;
105223258cfeSbeck 	return 1;
105323258cfeSbeck }
105423258cfeSbeck 
105523258cfeSbeck int
x509_verify_ctx_set_purpose(struct x509_verify_ctx * ctx,int purpose)105623258cfeSbeck x509_verify_ctx_set_purpose(struct x509_verify_ctx *ctx, int purpose)
105723258cfeSbeck {
105823258cfeSbeck 	if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX)
105923258cfeSbeck 		return 0;
106023258cfeSbeck 	ctx->purpose = purpose;
106123258cfeSbeck 	return 1;
106223258cfeSbeck }
106323258cfeSbeck 
106423258cfeSbeck int
x509_verify_ctx_set_intermediates(struct x509_verify_ctx * ctx,STACK_OF (X509)* intermediates)106523258cfeSbeck x509_verify_ctx_set_intermediates(struct x509_verify_ctx *ctx,
106623258cfeSbeck     STACK_OF(X509) *intermediates)
106723258cfeSbeck {
106823258cfeSbeck 	if ((ctx->intermediates = X509_chain_up_ref(intermediates)) == NULL)
106923258cfeSbeck 		return 0;
107023258cfeSbeck 	return 1;
107123258cfeSbeck }
107223258cfeSbeck 
107323258cfeSbeck const char *
x509_verify_ctx_error_string(struct x509_verify_ctx * ctx)107423258cfeSbeck x509_verify_ctx_error_string(struct x509_verify_ctx *ctx)
107523258cfeSbeck {
107623258cfeSbeck 	return X509_verify_cert_error_string(ctx->error);
107723258cfeSbeck }
107823258cfeSbeck 
107923258cfeSbeck size_t
x509_verify_ctx_error_depth(struct x509_verify_ctx * ctx)108023258cfeSbeck x509_verify_ctx_error_depth(struct x509_verify_ctx *ctx)
108123258cfeSbeck {
108223258cfeSbeck 	return ctx->error_depth;
108323258cfeSbeck }
108423258cfeSbeck 
STACK_OF(X509)108523258cfeSbeck STACK_OF(X509) *
108623258cfeSbeck x509_verify_ctx_chain(struct x509_verify_ctx *ctx, size_t i)
108723258cfeSbeck {
108823258cfeSbeck 	if (i >= ctx->chains_count)
108923258cfeSbeck 		return NULL;
109023258cfeSbeck 	return ctx->chains[i]->certs;
109123258cfeSbeck }
109223258cfeSbeck 
109323258cfeSbeck size_t
x509_verify(struct x509_verify_ctx * ctx,X509 * leaf,char * name)109423258cfeSbeck x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
109523258cfeSbeck {
109623258cfeSbeck 	struct x509_verify_chain *current_chain;
10979ab39fd2Sbeck 	int retry_chain_build, full_chain = 0;
109823258cfeSbeck 
1099e4db083fSbeck 	if (ctx->roots == NULL || ctx->max_depth == 0) {
110023258cfeSbeck 		ctx->error = X509_V_ERR_INVALID_CALL;
1101b77df7f7Stb 		goto err;
110223258cfeSbeck 	}
110323258cfeSbeck 
110423258cfeSbeck 	if (ctx->xsc != NULL) {
110523258cfeSbeck 		if (leaf != NULL || name != NULL) {
110623258cfeSbeck 			ctx->error = X509_V_ERR_INVALID_CALL;
1107b77df7f7Stb 			goto err;
110823258cfeSbeck 		}
110923258cfeSbeck 		leaf = ctx->xsc->cert;
111023258cfeSbeck 
11119ab39fd2Sbeck 		/* XXX */
11129ab39fd2Sbeck 		full_chain = 1;
11139ab39fd2Sbeck 		if (ctx->xsc->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
11149ab39fd2Sbeck 			full_chain = 0;
111523258cfeSbeck 		/*
111623258cfeSbeck 		 * XXX
111723258cfeSbeck 		 * The legacy code expects the top level cert to be
111823258cfeSbeck 		 * there, even if we didn't find a chain. So put it
111923258cfeSbeck 		 * there, we will clobber it later if we find a valid
112023258cfeSbeck 		 * chain.
112123258cfeSbeck 		 */
112223258cfeSbeck 		if ((ctx->xsc->chain = sk_X509_new_null()) == NULL) {
112323258cfeSbeck 			ctx->error = X509_V_ERR_OUT_OF_MEM;
1124b77df7f7Stb 			goto err;
112523258cfeSbeck 		}
112623258cfeSbeck 		if (!X509_up_ref(leaf)) {
112723258cfeSbeck 			ctx->error = X509_V_ERR_OUT_OF_MEM;
1128b77df7f7Stb 			goto err;
112923258cfeSbeck 		}
113023258cfeSbeck 		if (!sk_X509_push(ctx->xsc->chain, leaf)) {
113123258cfeSbeck 			X509_free(leaf);
113223258cfeSbeck 			ctx->error = X509_V_ERR_OUT_OF_MEM;
1133b77df7f7Stb 			goto err;
113423258cfeSbeck 		}
1135d59cc15fSbeck 		ctx->xsc->error_depth = 0;
1136d59cc15fSbeck 		ctx->xsc->current_cert = leaf;
113723258cfeSbeck 	}
113823258cfeSbeck 
113923258cfeSbeck 	if ((current_chain = x509_verify_chain_new()) == NULL) {
114023258cfeSbeck 		ctx->error = X509_V_ERR_OUT_OF_MEM;
1141b77df7f7Stb 		goto err;
114223258cfeSbeck 	}
1143b8644936Sbeck 
1144b8644936Sbeck 	/*
1145b8644936Sbeck 	 * Add the leaf to the chain and try to build chains from it.
1146b8644936Sbeck 	 * Note that unlike Go's verifier, we have not yet checked
1147b8644936Sbeck 	 * anything about the leaf, This is intentional, so that we
1148b8644936Sbeck 	 * report failures in chain building before we report problems
1149b8644936Sbeck 	 * with the leaf.
1150b8644936Sbeck 	 */
115123258cfeSbeck 	if (!x509_verify_chain_append(current_chain, leaf, &ctx->error)) {
115223258cfeSbeck 		x509_verify_chain_free(current_chain);
1153b77df7f7Stb 		goto err;
115423258cfeSbeck 	}
11559ab39fd2Sbeck 	do {
11569ab39fd2Sbeck 		retry_chain_build = 0;
115789ae9cb0Sbeck 		if (x509_verify_ctx_cert_is_root(ctx, leaf, full_chain)) {
1158b8644936Sbeck 			if (!x509_verify_ctx_add_chain(ctx, current_chain,
1159b8644936Sbeck 			    name)) {
116089ae9cb0Sbeck 				x509_verify_chain_free(current_chain);
116189ae9cb0Sbeck 				goto err;
116289ae9cb0Sbeck 			}
116389ae9cb0Sbeck 		} else {
11649ab39fd2Sbeck 			x509_verify_build_chains(ctx, leaf, current_chain,
1165b8644936Sbeck 			    full_chain, name);
11669ab39fd2Sbeck 			if (full_chain && ctx->chains_count == 0) {
11679ab39fd2Sbeck 				/*
11689ab39fd2Sbeck 				 * Save the error state from the xsc
11699ab39fd2Sbeck 				 * at this point to put back on the
11709ab39fd2Sbeck 				 * xsc in case we do not find a chain
11719ab39fd2Sbeck 				 * that is trusted but not a full
11729ab39fd2Sbeck 				 * chain to a self signed root. This
11739ab39fd2Sbeck 				 * is because the unvalidated chain is
11749ab39fd2Sbeck 				 * used by the autochain batshittery
11759ab39fd2Sbeck 				 * on failure and will be needed for
11769ab39fd2Sbeck 				 * that.
11779ab39fd2Sbeck 				 */
1178d8913d6aSbeck 				ctx->xsc->error_depth = ctx->error_depth;
11799ab39fd2Sbeck 				if (!x509_verify_ctx_save_xsc_error(ctx)) {
11809ab39fd2Sbeck 					x509_verify_chain_free(current_chain);
11819ab39fd2Sbeck 					goto err;
11829ab39fd2Sbeck 				}
11839ab39fd2Sbeck 				full_chain = 0;
11849ab39fd2Sbeck 				retry_chain_build = 1;
11859ab39fd2Sbeck 			}
11869ab39fd2Sbeck 		}
11879ab39fd2Sbeck 	} while (retry_chain_build);
118823258cfeSbeck 
118923258cfeSbeck 	x509_verify_chain_free(current_chain);
119023258cfeSbeck 
119123258cfeSbeck 	/*
11923f851282Sbeck 	 * Do the new verifier style return, where we don't have an xsc
11933f851282Sbeck 	 * that allows a crazy callback to turn invalid things into valid.
11949ab39fd2Sbeck 	 */
11953f851282Sbeck 	if (ctx->xsc == NULL) {
11969ab39fd2Sbeck 		/*
119723258cfeSbeck 		 * Safety net:
119823258cfeSbeck 		 * We could not find a validated chain, and for some reason do not
119923258cfeSbeck 		 * have an error set.
120023258cfeSbeck 		 */
12013f851282Sbeck 		if (ctx->chains_count == 0 && ctx->error == X509_V_OK)
120223258cfeSbeck 			ctx->error = X509_V_ERR_UNSPECIFIED;
120323258cfeSbeck 
12043f851282Sbeck 		/*
12053f851282Sbeck 		 * If we are not using an xsc, and have no possibility for the
12063f851282Sbeck 		 * crazy OpenSSL callback API changing the results of
12073f851282Sbeck 		 * validation steps (because the callback can make validation
12083f851282Sbeck 		 * proceed in the presence of invalid certs), any chains we
12093f851282Sbeck 		 * have here are correctly built and verified.
12103f851282Sbeck 		 */
121123258cfeSbeck 		if (ctx->chains_count > 0)
121223258cfeSbeck 			ctx->error = X509_V_OK;
121323258cfeSbeck 
12143f851282Sbeck 		return ctx->chains_count;
12156cf34315Sbeck 	}
12163f851282Sbeck 
12173f851282Sbeck 	/*
12183f851282Sbeck 	 * Otherwise we are doing compatibility with an xsc, which means that we
12193f851282Sbeck 	 * will have one chain, which might actually be a bogus chain because
12203f851282Sbeck 	 * the callback told us to ignore errors and proceed to build an invalid
12213f851282Sbeck 	 * chain. Possible return values from this include returning 1 with an
12223f851282Sbeck 	 * invalid chain and a value of xsc->error != X509_V_OK (It's tradition
12233f851282Sbeck 	 * that makes it ok).
12243f851282Sbeck 	 */
12253f851282Sbeck 
12263f851282Sbeck 	if (ctx->chains_count > 0) {
12273f851282Sbeck 		/*
12283f851282Sbeck 		 * The chain we have using an xsc might not be a verified chain
12293f851282Sbeck 		 * if the callback perverted things while we built it to ignore
12303f851282Sbeck 		 * failures and proceed with chain building. We put this chain
12313f851282Sbeck 		 * and the error associated with it on the xsc.
12323f851282Sbeck 		 */
12333f851282Sbeck 		if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1, 1))
12343f851282Sbeck 			goto err;
12353f851282Sbeck 
12363f851282Sbeck 		/*
12373f851282Sbeck 		 * Call the callback for completion up our built
12383f851282Sbeck 		 * chain. The callback could still tell us to
12393f851282Sbeck 		 * fail. Since this chain might exist as the result of
12403f851282Sbeck 		 * callback doing perversions, we could still return
12413f851282Sbeck 		 * "success" with something other than X509_V_OK set
12423f851282Sbeck 		 * as the error.
12433f851282Sbeck 		 */
12443f851282Sbeck 		if (!x509_vfy_callback_indicate_completion(ctx->xsc))
12453f851282Sbeck 			goto err;
124689ae9cb0Sbeck 	} else {
124789ae9cb0Sbeck 		/*
12483f851282Sbeck 		 * We did not find a chain. Bring back the failure
12493f851282Sbeck 		 * case we wanted to the xsc if we saved one. If we
12503f851282Sbeck 		 * did not we should have just the leaf on the xsc.
125189ae9cb0Sbeck 		 */
12523f851282Sbeck 		if (!x509_verify_ctx_restore_xsc_error(ctx))
12533f851282Sbeck 			goto err;
12543f851282Sbeck 
12553f851282Sbeck 		/*
12563f851282Sbeck 		 * Safety net, ensure we have an error set in the
12573f851282Sbeck 		 * failing case.
12583f851282Sbeck 		 */
12593f851282Sbeck 		if (ctx->xsc->error == X509_V_OK) {
12603f851282Sbeck 			if (ctx->error == X509_V_OK)
12613f851282Sbeck 				ctx->error = X509_V_ERR_UNSPECIFIED;
12623f851282Sbeck 			ctx->xsc->error = ctx->error;
12633f851282Sbeck 		}
12643f851282Sbeck 
12653f851282Sbeck 		/*
12663f851282Sbeck 		 * Let the callback override the return value
12673f851282Sbeck 		 * at depth 0 if it chooses to
12683f851282Sbeck 		 */
12693f851282Sbeck 		return ctx->xsc->verify_cb(0, ctx->xsc);
12703f851282Sbeck 	}
12713f851282Sbeck 
12723f851282Sbeck 	/* We only ever find one chain in compat mode with an xsc. */
127389ae9cb0Sbeck 	return 1;
1274b77df7f7Stb 
1275b77df7f7Stb  err:
12763cb8f152Stb 	if (ctx->error == X509_V_OK)
12773cb8f152Stb 		ctx->error = X509_V_ERR_UNSPECIFIED;
12783f851282Sbeck 
12793f851282Sbeck 	if (ctx->xsc != NULL) {
12803f851282Sbeck 		if (ctx->xsc->error == X509_V_OK)
12813f851282Sbeck 			ctx->xsc->error = X509_V_ERR_UNSPECIFIED;
12823f851282Sbeck 		ctx->error = ctx->xsc->error;
12833f851282Sbeck 	}
12843f851282Sbeck 
1285b77df7f7Stb 	return 0;
128623258cfeSbeck }
1287