xref: /openbsd/lib/libcrypto/x509/x509_verify.c (revision e30c9e23)
1*e30c9e23Stb /* $OpenBSD: x509_verify.c,v 1.52 2021/11/07 15:51:23 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 
3023258cfeSbeck #include "x509_internal.h"
3123258cfeSbeck #include "x509_issuer_cache.h"
3223258cfeSbeck 
3323258cfeSbeck static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert,
3423258cfeSbeck     struct x509_verify_chain *current_chain);
3523258cfeSbeck static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
369ab39fd2Sbeck     struct x509_verify_chain *current_chain, int full_chain);
3723258cfeSbeck static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert,
3823258cfeSbeck     size_t depth, int error, int ok);
3923258cfeSbeck static void x509_verify_chain_free(struct x509_verify_chain *chain);
4023258cfeSbeck 
4188e5d447Sbeck /*
4288e5d447Sbeck  * Parse an asn1 to a representable time_t as per RFC 5280 rules.
4388e5d447Sbeck  * Returns -1 if that can't be done for any reason.
4488e5d447Sbeck  */
4588e5d447Sbeck time_t
4688e5d447Sbeck x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notAfter)
4788e5d447Sbeck {
4888e5d447Sbeck 	struct tm tm = { 0 };
4988e5d447Sbeck 	int type;
5088e5d447Sbeck 
5188e5d447Sbeck 	type = ASN1_time_parse(atime->data, atime->length, &tm, atime->type);
5288e5d447Sbeck 	if (type == -1)
5388e5d447Sbeck 		return -1;
5488e5d447Sbeck 
5588e5d447Sbeck 	/* RFC 5280 section 4.1.2.5 */
5688e5d447Sbeck 	if (tm.tm_year < 150 && type != V_ASN1_UTCTIME)
5788e5d447Sbeck 		return -1;
5888e5d447Sbeck 	if (tm.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
5988e5d447Sbeck 		return -1;
6088e5d447Sbeck 
6188e5d447Sbeck 	if (notAfter) {
6288e5d447Sbeck 		/*
6388e5d447Sbeck 		 * If we are a completely broken operating system with a
6488e5d447Sbeck 		 * 32 bit time_t, and we have been told this is a notAfter
6588e5d447Sbeck 		 * date, limit the date to a 32 bit representable value.
6688e5d447Sbeck 		 */
6788e5d447Sbeck 		if (!ASN1_time_tm_clamp_notafter(&tm))
6888e5d447Sbeck 			return -1;
6988e5d447Sbeck 	}
7088e5d447Sbeck 
7188e5d447Sbeck 	/*
7288e5d447Sbeck 	 * Defensively fail if the time string is not representable as
7388e5d447Sbeck 	 * a time_t. A time_t must be sane if you care about times after
7488e5d447Sbeck 	 * Jan 19 2038.
7588e5d447Sbeck 	 */
7688e5d447Sbeck 	return timegm(&tm);
7788e5d447Sbeck }
7888e5d447Sbeck 
7988e5d447Sbeck /*
8088e5d447Sbeck  * Cache certificate hash, and values parsed out of an X509.
8188e5d447Sbeck  * called from cache_extensions()
8288e5d447Sbeck  */
8388e5d447Sbeck void
8488e5d447Sbeck x509_verify_cert_info_populate(X509 *cert)
8588e5d447Sbeck {
8688e5d447Sbeck 	/*
8788e5d447Sbeck 	 * Parse and save the cert times, or remember that they
8888e5d447Sbeck 	 * are unacceptable/unparsable.
8988e5d447Sbeck 	 */
9088e5d447Sbeck 	cert->not_before = x509_verify_asn1_time_to_time_t(X509_get_notBefore(cert), 0);
9188e5d447Sbeck 	cert->not_after = x509_verify_asn1_time_to_time_t(X509_get_notAfter(cert), 1);
9288e5d447Sbeck }
9323258cfeSbeck 
9423258cfeSbeck struct x509_verify_chain *
9523258cfeSbeck x509_verify_chain_new(void)
9623258cfeSbeck {
9723258cfeSbeck 	struct x509_verify_chain *chain;
9823258cfeSbeck 
9923258cfeSbeck 	if ((chain = calloc(1, sizeof(*chain))) == NULL)
10023258cfeSbeck 		goto err;
10123258cfeSbeck 	if ((chain->certs = sk_X509_new_null()) == NULL)
10223258cfeSbeck 		goto err;
103a235c622Sjsing 	if ((chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS,
104a235c622Sjsing 	    sizeof(int))) == NULL)
105a235c622Sjsing 		goto err;
10642f3108aStb 	if ((chain->names =
10742f3108aStb 	    x509_constraints_names_new(X509_VERIFY_MAX_CHAIN_NAMES)) == NULL)
10823258cfeSbeck 		goto err;
10923258cfeSbeck 
11023258cfeSbeck 	return chain;
11123258cfeSbeck  err:
11223258cfeSbeck 	x509_verify_chain_free(chain);
11323258cfeSbeck 	return NULL;
11423258cfeSbeck }
11523258cfeSbeck 
11623258cfeSbeck static void
11723258cfeSbeck x509_verify_chain_clear(struct x509_verify_chain *chain)
11823258cfeSbeck {
11923258cfeSbeck 	sk_X509_pop_free(chain->certs, X509_free);
12023258cfeSbeck 	chain->certs = NULL;
121a235c622Sjsing 	free(chain->cert_errors);
122a235c622Sjsing 	chain->cert_errors = NULL;
12323258cfeSbeck 	x509_constraints_names_free(chain->names);
12423258cfeSbeck 	chain->names = NULL;
12523258cfeSbeck }
12623258cfeSbeck 
12723258cfeSbeck static void
12823258cfeSbeck x509_verify_chain_free(struct x509_verify_chain *chain)
12923258cfeSbeck {
13023258cfeSbeck 	if (chain == NULL)
13123258cfeSbeck 		return;
13223258cfeSbeck 	x509_verify_chain_clear(chain);
13323258cfeSbeck 	free(chain);
13423258cfeSbeck }
13523258cfeSbeck 
13623258cfeSbeck static struct x509_verify_chain *
13723258cfeSbeck x509_verify_chain_dup(struct x509_verify_chain *chain)
13823258cfeSbeck {
13923258cfeSbeck 	struct x509_verify_chain *new_chain;
14023258cfeSbeck 
141f83e3c38Stb 	if ((new_chain = calloc(1, sizeof(*chain))) == NULL)
14223258cfeSbeck 		goto err;
14323258cfeSbeck 	if ((new_chain->certs = X509_chain_up_ref(chain->certs)) == NULL)
14423258cfeSbeck 		goto err;
145a235c622Sjsing 	if ((new_chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS,
146a235c622Sjsing 	    sizeof(int))) == NULL)
147a235c622Sjsing 		goto err;
148a235c622Sjsing 	memcpy(new_chain->cert_errors, chain->cert_errors,
149a235c622Sjsing 	    X509_VERIFY_MAX_CHAIN_CERTS * sizeof(int));
15023258cfeSbeck 	if ((new_chain->names =
15123258cfeSbeck 	    x509_constraints_names_dup(chain->names)) == NULL)
15223258cfeSbeck 		goto err;
15323258cfeSbeck 	return(new_chain);
15423258cfeSbeck  err:
15523258cfeSbeck 	x509_verify_chain_free(new_chain);
15623258cfeSbeck 	return NULL;
15723258cfeSbeck }
15823258cfeSbeck 
15923258cfeSbeck static int
16023258cfeSbeck x509_verify_chain_append(struct x509_verify_chain *chain, X509 *cert,
16123258cfeSbeck     int *error)
16223258cfeSbeck {
16323258cfeSbeck 	int verify_err = X509_V_ERR_UNSPECIFIED;
164a235c622Sjsing 	size_t idx;
16523258cfeSbeck 
16623258cfeSbeck 	if (!x509_constraints_extract_names(chain->names, cert,
16723258cfeSbeck 	    sk_X509_num(chain->certs) == 0, &verify_err)) {
16823258cfeSbeck 		*error = verify_err;
16923258cfeSbeck 		return 0;
17023258cfeSbeck 	}
171a235c622Sjsing 
17223258cfeSbeck 	X509_up_ref(cert);
17323258cfeSbeck 	if (!sk_X509_push(chain->certs, cert)) {
17423258cfeSbeck 		X509_free(cert);
1756b178030Sbeck 		*error = X509_V_ERR_OUT_OF_MEM;
17623258cfeSbeck 		return 0;
17723258cfeSbeck 	}
178a235c622Sjsing 
179a235c622Sjsing 	idx = sk_X509_num(chain->certs) - 1;
180a235c622Sjsing 	chain->cert_errors[idx] = *error;
181a235c622Sjsing 
182a235c622Sjsing 	/*
183a235c622Sjsing 	 * We've just added the issuer for the previous certificate,
184a235c622Sjsing 	 * clear its error if appropriate.
185a235c622Sjsing 	 */
18650df4f34Sbeck 	if (idx > 1 && chain->cert_errors[idx - 1] ==
18750df4f34Sbeck 	    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
188a235c622Sjsing 		chain->cert_errors[idx - 1] = X509_V_OK;
189a235c622Sjsing 
19023258cfeSbeck 	return 1;
19123258cfeSbeck }
19223258cfeSbeck 
19323258cfeSbeck static X509 *
19423258cfeSbeck x509_verify_chain_last(struct x509_verify_chain *chain)
19523258cfeSbeck {
19623258cfeSbeck 	int last;
19723258cfeSbeck 
19823258cfeSbeck 	if (chain->certs == NULL)
19923258cfeSbeck 		return NULL;
20023258cfeSbeck 	if ((last = sk_X509_num(chain->certs) - 1) < 0)
20123258cfeSbeck 		return NULL;
20223258cfeSbeck 	return sk_X509_value(chain->certs, last);
20323258cfeSbeck }
20423258cfeSbeck 
20523258cfeSbeck X509 *
20623258cfeSbeck x509_verify_chain_leaf(struct x509_verify_chain *chain)
20723258cfeSbeck {
20823258cfeSbeck 	if (chain->certs == NULL)
20923258cfeSbeck 		return NULL;
21023258cfeSbeck 	return sk_X509_value(chain->certs, 0);
21123258cfeSbeck }
21223258cfeSbeck 
21323258cfeSbeck static void
21423258cfeSbeck x509_verify_ctx_reset(struct x509_verify_ctx *ctx)
21523258cfeSbeck {
21623258cfeSbeck 	size_t i;
21723258cfeSbeck 
21823258cfeSbeck 	for (i = 0; i < ctx->chains_count; i++)
21923258cfeSbeck 		x509_verify_chain_free(ctx->chains[i]);
2209ab39fd2Sbeck 	sk_X509_pop_free(ctx->saved_error_chain, X509_free);
2219ab39fd2Sbeck 	ctx->saved_error = 0;
2229ab39fd2Sbeck 	ctx->saved_error_depth = 0;
22323258cfeSbeck 	ctx->error = 0;
22423258cfeSbeck 	ctx->error_depth = 0;
22523258cfeSbeck 	ctx->chains_count = 0;
22623258cfeSbeck 	ctx->sig_checks = 0;
22723258cfeSbeck 	ctx->check_time = NULL;
22823258cfeSbeck }
22923258cfeSbeck 
23023258cfeSbeck static void
23123258cfeSbeck x509_verify_ctx_clear(struct x509_verify_ctx *ctx)
23223258cfeSbeck {
23323258cfeSbeck 	x509_verify_ctx_reset(ctx);
23423258cfeSbeck 	sk_X509_pop_free(ctx->intermediates, X509_free);
23523258cfeSbeck 	free(ctx->chains);
23623258cfeSbeck 	memset(ctx, 0, sizeof(*ctx));
23723258cfeSbeck }
23823258cfeSbeck 
23923258cfeSbeck static int
2409ab39fd2Sbeck x509_verify_cert_cache_extensions(X509 *cert) {
2419ab39fd2Sbeck 	if (!(cert->ex_flags & EXFLAG_SET)) {
2429ab39fd2Sbeck 		CRYPTO_w_lock(CRYPTO_LOCK_X509);
2439ab39fd2Sbeck 		x509v3_cache_extensions(cert);
2449ab39fd2Sbeck 		CRYPTO_w_unlock(CRYPTO_LOCK_X509);
2459ab39fd2Sbeck 	}
2469ab39fd2Sbeck 	if (cert->ex_flags & EXFLAG_INVALID)
2479ab39fd2Sbeck 		return 0;
24888e5d447Sbeck 
2499ab39fd2Sbeck 	return (cert->ex_flags & EXFLAG_SET);
2509ab39fd2Sbeck }
2519ab39fd2Sbeck 
2529ab39fd2Sbeck static int
2539ab39fd2Sbeck x509_verify_cert_self_signed(X509 *cert)
2549ab39fd2Sbeck {
2559ab39fd2Sbeck 	return (cert->ex_flags & EXFLAG_SS) ? 1 : 0;
2569ab39fd2Sbeck }
2579ab39fd2Sbeck 
2589ab39fd2Sbeck static int
2599ab39fd2Sbeck x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert,
2609ab39fd2Sbeck     int full_chain)
26123258cfeSbeck {
262ac5ed168Sbeck 	X509 *match = NULL;
26323258cfeSbeck 	int i;
26423258cfeSbeck 
2659ab39fd2Sbeck 	if (!x509_verify_cert_cache_extensions(cert))
2669ab39fd2Sbeck 		return 0;
2679ab39fd2Sbeck 
268ac5ed168Sbeck 	/* Check by lookup if we have a legacy xsc */
269ac5ed168Sbeck 	if (ctx->xsc != NULL) {
270ac5ed168Sbeck 		if ((match = x509_vfy_lookup_cert_match(ctx->xsc,
271ac5ed168Sbeck 		    cert)) != NULL) {
272ac5ed168Sbeck 			X509_free(match);
273ac5ed168Sbeck 			return !full_chain ||
274ac5ed168Sbeck 			    x509_verify_cert_self_signed(cert);
275ac5ed168Sbeck 		}
27699d404ebSbeck 	} else {
27799d404ebSbeck 		/* Check the provided roots */
27899d404ebSbeck 		for (i = 0; i < sk_X509_num(ctx->roots); i++) {
27999d404ebSbeck 			if (X509_cmp(sk_X509_value(ctx->roots, i), cert) == 0)
28099d404ebSbeck 				return !full_chain ||
28199d404ebSbeck 				    x509_verify_cert_self_signed(cert);
28299d404ebSbeck 		}
283ac5ed168Sbeck 	}
284ac5ed168Sbeck 
28523258cfeSbeck 	return 0;
28623258cfeSbeck }
28723258cfeSbeck 
288733666e3Sjsing static int
289733666e3Sjsing x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx,
290d095297bStb     struct x509_verify_chain *chain, int set_error, int is_trusted)
291733666e3Sjsing {
2925d6c9775Sjsing 	size_t num_untrusted;
293a235c622Sjsing 	int i;
294733666e3Sjsing 
295733666e3Sjsing 	if (ctx->xsc == NULL)
296733666e3Sjsing 		return 1;
297733666e3Sjsing 
298d095297bStb 	/*
299*e30c9e23Stb 	 * XXX num_untrusted is the number of untrusted certs at the
300d095297bStb 	 * bottom of the chain. This works now since we stop at the first
301d095297bStb 	 * trusted cert. This will need fixing once we allow more than one
302d095297bStb 	 * trusted certificate.
303d095297bStb 	 */
3045d6c9775Sjsing 	num_untrusted = sk_X509_num(chain->certs);
3055d6c9775Sjsing 	if (is_trusted && num_untrusted > 0)
3065d6c9775Sjsing 		num_untrusted--;
307*e30c9e23Stb 	ctx->xsc->num_untrusted = num_untrusted;
308733666e3Sjsing 
309733666e3Sjsing 	sk_X509_pop_free(ctx->xsc->chain, X509_free);
310733666e3Sjsing 	ctx->xsc->chain = X509_chain_up_ref(chain->certs);
311733666e3Sjsing 	if (ctx->xsc->chain == NULL)
312d963395aSjsing 		return x509_verify_cert_error(ctx, NULL, 0,
313733666e3Sjsing 		    X509_V_ERR_OUT_OF_MEM, 0);
314a235c622Sjsing 
315a235c622Sjsing 	if (set_error) {
316a235c622Sjsing 		ctx->xsc->error = X509_V_OK;
317a235c622Sjsing 		ctx->xsc->error_depth = 0;
318a235c622Sjsing 		for (i = 0; i < sk_X509_num(chain->certs); i++) {
319a235c622Sjsing 			if (chain->cert_errors[i] != X509_V_OK) {
320a235c622Sjsing 				ctx->xsc->error = chain->cert_errors[i];
321a235c622Sjsing 				ctx->xsc->error_depth = i;
322a235c622Sjsing 				break;
323a235c622Sjsing 			}
324a235c622Sjsing 		}
325a235c622Sjsing 	}
326a235c622Sjsing 
327733666e3Sjsing 	return 1;
328733666e3Sjsing }
329733666e3Sjsing 
3309ab39fd2Sbeck 
3319ab39fd2Sbeck /*
3329ab39fd2Sbeck  * Save the error state and unvalidated chain off of the xsc for
3339ab39fd2Sbeck  * later.
3349ab39fd2Sbeck  */
3359ab39fd2Sbeck static int
3369ab39fd2Sbeck x509_verify_ctx_save_xsc_error(struct x509_verify_ctx *ctx)
3379ab39fd2Sbeck {
3389ab39fd2Sbeck 	if (ctx->xsc != NULL && ctx->xsc->chain != NULL) {
3399ab39fd2Sbeck 		sk_X509_pop_free(ctx->saved_error_chain, X509_free);
3409ab39fd2Sbeck 		ctx->saved_error_chain = X509_chain_up_ref(ctx->xsc->chain);
3419ab39fd2Sbeck 		if (ctx->saved_error_chain == NULL)
3429ab39fd2Sbeck 			return x509_verify_cert_error(ctx, NULL, 0,
3439ab39fd2Sbeck 			    X509_V_ERR_OUT_OF_MEM, 0);
3449ab39fd2Sbeck 		ctx->saved_error = ctx->xsc->error;
3459ab39fd2Sbeck 		ctx->saved_error_depth = ctx->xsc->error_depth;
3469ab39fd2Sbeck 	}
3479ab39fd2Sbeck 	return 1;
3489ab39fd2Sbeck }
3499ab39fd2Sbeck 
3509ab39fd2Sbeck /*
3519ab39fd2Sbeck  * Restore the saved error state and unvalidated chain to the xsc
3529ab39fd2Sbeck  * if we do not have a validated chain.
3539ab39fd2Sbeck  */
3549ab39fd2Sbeck static int
3559ab39fd2Sbeck x509_verify_ctx_restore_xsc_error(struct x509_verify_ctx *ctx)
3569ab39fd2Sbeck {
3579ab39fd2Sbeck 	if (ctx->xsc != NULL && ctx->chains_count == 0 &&
3589ab39fd2Sbeck 	    ctx->saved_error_chain != NULL) {
3599ab39fd2Sbeck 		sk_X509_pop_free(ctx->xsc->chain, X509_free);
3609ab39fd2Sbeck 		ctx->xsc->chain = X509_chain_up_ref(ctx->saved_error_chain);
3619ab39fd2Sbeck 		if (ctx->xsc->chain == NULL)
3629ab39fd2Sbeck 			return x509_verify_cert_error(ctx, NULL, 0,
3639ab39fd2Sbeck 			    X509_V_ERR_OUT_OF_MEM, 0);
3649ab39fd2Sbeck 		ctx->xsc->error = ctx->saved_error;
3659ab39fd2Sbeck 		ctx->xsc->error_depth = ctx->saved_error_depth;
3669ab39fd2Sbeck 	}
3679ab39fd2Sbeck 	return 1;
3689ab39fd2Sbeck }
3699ab39fd2Sbeck 
370ad8616e3Sbeck /* Perform legacy style validation of a chain */
371ad8616e3Sbeck static int
372ad8616e3Sbeck x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx *ctx,
373ad8616e3Sbeck     struct x509_verify_chain *chain, size_t depth)
374ad8616e3Sbeck {
3754e67fe4cSbeck 	int ret = 0, trust;
376ad8616e3Sbeck 
377ad8616e3Sbeck 	if (ctx->xsc == NULL)
378ad8616e3Sbeck 		return 1;
379ad8616e3Sbeck 
380ad8616e3Sbeck 	/*
381ad8616e3Sbeck 	 * If we have a legacy xsc, choose a validated chain, and
382ad8616e3Sbeck 	 * apply the extensions, revocation, and policy checks just
383ad8616e3Sbeck 	 * like the legacy code did. We do this here instead of as
384ad8616e3Sbeck 	 * building the chains to more easily support the callback and
385ad8616e3Sbeck 	 * the bewildering array of VERIFY_PARAM knobs that are there
386ad8616e3Sbeck 	 * for the fiddling.
387ad8616e3Sbeck 	 */
388ad8616e3Sbeck 
389ad8616e3Sbeck 	/* These may be set in one of the following calls. */
390ad8616e3Sbeck 	ctx->xsc->error = X509_V_OK;
391ad8616e3Sbeck 	ctx->xsc->error_depth = 0;
392ad8616e3Sbeck 
3934e67fe4cSbeck 	trust = x509_vfy_check_trust(ctx->xsc);
3944e67fe4cSbeck 	if (trust == X509_TRUST_REJECTED)
3954e67fe4cSbeck 		goto err;
3964e67fe4cSbeck 
397ad8616e3Sbeck 	if (!x509_verify_ctx_set_xsc_chain(ctx, chain, 0, 1))
398ad8616e3Sbeck 		goto err;
399ad8616e3Sbeck 
400ad8616e3Sbeck 	/*
401ad8616e3Sbeck 	 * XXX currently this duplicates some work done in chain
402ad8616e3Sbeck 	 * build, but we keep it here until we have feature parity
403ad8616e3Sbeck 	 */
404ad8616e3Sbeck 	if (!x509_vfy_check_chain_extensions(ctx->xsc))
405ad8616e3Sbeck 		goto err;
406ad8616e3Sbeck 
40769c7967eSjob #ifndef OPENSSL_NO_RFC3779
40869c7967eSjob 	if (!X509v3_asid_validate_path(ctx->xsc))
40969c7967eSjob 		goto err;
41069c7967eSjob 
41169c7967eSjob 	if (!X509v3_addr_validate_path(ctx->xsc))
41269c7967eSjob 		goto err;
41369c7967eSjob #endif
41469c7967eSjob 
415ad8616e3Sbeck 	if (!x509_constraints_chain(ctx->xsc->chain,
416ad8616e3Sbeck 		&ctx->xsc->error, &ctx->xsc->error_depth)) {
417ad8616e3Sbeck 		X509 *cert = sk_X509_value(ctx->xsc->chain, depth);
418ad8616e3Sbeck 		if (!x509_verify_cert_error(ctx, cert,
419ad8616e3Sbeck 			ctx->xsc->error_depth, ctx->xsc->error, 0))
420ad8616e3Sbeck 			goto err;
421ad8616e3Sbeck 	}
422ad8616e3Sbeck 
423ad8616e3Sbeck 	if (!x509_vfy_check_revocation(ctx->xsc))
424ad8616e3Sbeck 		goto err;
425ad8616e3Sbeck 
426ad8616e3Sbeck 	if (!x509_vfy_check_policy(ctx->xsc))
427ad8616e3Sbeck 		goto err;
428ad8616e3Sbeck 
4294e67fe4cSbeck 	if ((!(ctx->xsc->param->flags & X509_V_FLAG_PARTIAL_CHAIN)) &&
4304e67fe4cSbeck 	    trust != X509_TRUST_TRUSTED)
4314e67fe4cSbeck 		goto err;
4324e67fe4cSbeck 
433ad8616e3Sbeck 	ret = 1;
434ad8616e3Sbeck 
435ad8616e3Sbeck  err:
436ad8616e3Sbeck 	/*
437ad8616e3Sbeck 	 * The above checks may have set ctx->xsc->error and
438ad8616e3Sbeck 	 * ctx->xsc->error_depth - save these for later on.
439ad8616e3Sbeck 	 */
440ad8616e3Sbeck 	if (ctx->xsc->error != X509_V_OK) {
441ad8616e3Sbeck 		if (ctx->xsc->error_depth < 0 ||
442ad8616e3Sbeck 		    ctx->xsc->error_depth >= X509_VERIFY_MAX_CHAIN_CERTS)
443ad8616e3Sbeck 			return 0;
444ad8616e3Sbeck 		chain->cert_errors[ctx->xsc->error_depth] =
445ad8616e3Sbeck 		    ctx->xsc->error;
44689ae9cb0Sbeck 		ctx->error_depth = ctx->xsc->error_depth;
447ad8616e3Sbeck 	}
448ad8616e3Sbeck 
449ad8616e3Sbeck 	return ret;
450ad8616e3Sbeck }
451ad8616e3Sbeck 
45223258cfeSbeck /* Add a validated chain to our list of valid chains */
45323258cfeSbeck static int
45423258cfeSbeck x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
45523258cfeSbeck     struct x509_verify_chain *chain)
45623258cfeSbeck {
45723258cfeSbeck 	size_t depth;
45823258cfeSbeck 	X509 *last = x509_verify_chain_last(chain);
45923258cfeSbeck 
46023258cfeSbeck 	depth = sk_X509_num(chain->certs);
46123258cfeSbeck 	if (depth > 0)
46223258cfeSbeck 		depth--;
46323258cfeSbeck 
46423258cfeSbeck 	if (ctx->chains_count >= ctx->max_chains)
46523258cfeSbeck 		return x509_verify_cert_error(ctx, last, depth,
46623258cfeSbeck 		    X509_V_ERR_CERT_CHAIN_TOO_LONG, 0);
46723258cfeSbeck 
468a235c622Sjsing 	/* Clear a get issuer failure for a root certificate. */
469a235c622Sjsing 	if (chain->cert_errors[depth] ==
47050df4f34Sbeck 	    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
471a235c622Sjsing 		chain->cert_errors[depth] = X509_V_OK;
472a235c622Sjsing 
473ad8616e3Sbeck 	if (!x509_verify_ctx_validate_legacy_chain(ctx, chain, depth))
474733666e3Sjsing 		return 0;
47523258cfeSbeck 
47623258cfeSbeck 	/*
477ad8616e3Sbeck 	 * In the non-legacy code, extensions and purpose are dealt
478ad8616e3Sbeck 	 * with as the chain is built.
47923258cfeSbeck 	 *
48023258cfeSbeck 	 * The non-legacy api returns multiple chains but does not do
48123258cfeSbeck 	 * any revocation checking (it must be done by the caller on
48223258cfeSbeck 	 * any chain they wish to use)
48323258cfeSbeck 	 */
48423258cfeSbeck 
48523258cfeSbeck 	if ((ctx->chains[ctx->chains_count] = x509_verify_chain_dup(chain)) ==
48623258cfeSbeck 	    NULL) {
48723258cfeSbeck 		return x509_verify_cert_error(ctx, last, depth,
48823258cfeSbeck 		    X509_V_ERR_OUT_OF_MEM, 0);
48923258cfeSbeck 	}
49023258cfeSbeck 	ctx->chains_count++;
49123258cfeSbeck 	ctx->error = X509_V_OK;
49223258cfeSbeck 	ctx->error_depth = depth;
49323258cfeSbeck 	return 1;
49423258cfeSbeck }
49523258cfeSbeck 
49623258cfeSbeck static int
49723258cfeSbeck x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent,
49823258cfeSbeck     X509 *child)
49923258cfeSbeck {
5009ab39fd2Sbeck 	if (!x509_verify_cert_cache_extensions(parent))
5019ab39fd2Sbeck 		return 0;
50223258cfeSbeck 	if (ctx->xsc != NULL)
50323258cfeSbeck 		return (ctx->xsc->check_issued(ctx->xsc, child, parent));
50423258cfeSbeck 
50523258cfeSbeck 	/* XXX key usage */
50623258cfeSbeck 	return X509_check_issued(child, parent) != X509_V_OK;
50723258cfeSbeck }
50823258cfeSbeck 
50923258cfeSbeck static int
51088e5d447Sbeck x509_verify_parent_signature(X509 *parent, X509 *child, int *error)
51123258cfeSbeck {
51223258cfeSbeck 	EVP_PKEY *pkey;
51323258cfeSbeck 	int cached;
51423258cfeSbeck 	int ret = 0;
51523258cfeSbeck 
51623258cfeSbeck 	/* Use cached value if we have it */
51788e5d447Sbeck 	if ((cached = x509_issuer_cache_find(parent->hash, child->hash)) >= 0)
51823258cfeSbeck 		return cached;
51923258cfeSbeck 
52023258cfeSbeck 	/* Check signature. Did parent sign child? */
52123258cfeSbeck 	if ((pkey = X509_get_pubkey(parent)) == NULL) {
52223258cfeSbeck 		*error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
52323258cfeSbeck 		return 0;
52423258cfeSbeck 	}
52523258cfeSbeck 	if (X509_verify(child, pkey) <= 0)
52623258cfeSbeck 		*error = X509_V_ERR_CERT_SIGNATURE_FAILURE;
52723258cfeSbeck 	else
52823258cfeSbeck 		ret = 1;
52923258cfeSbeck 
53023258cfeSbeck 	/* Add result to cache */
53188e5d447Sbeck 	x509_issuer_cache_add(parent->hash, child->hash, ret);
53223258cfeSbeck 
53323258cfeSbeck 	EVP_PKEY_free(pkey);
53423258cfeSbeck 
53523258cfeSbeck 	return ret;
53623258cfeSbeck }
53723258cfeSbeck 
53823258cfeSbeck static int
53923258cfeSbeck x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
54088e5d447Sbeck     int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain,
54188e5d447Sbeck     int full_chain)
54223258cfeSbeck {
54323258cfeSbeck 	int depth = sk_X509_num(current_chain->certs);
54423258cfeSbeck 	struct x509_verify_chain *new_chain;
54523258cfeSbeck 	int i;
54623258cfeSbeck 
54723258cfeSbeck 	/* Fail if the certificate is already in the chain */
54823258cfeSbeck 	for (i = 0; i < sk_X509_num(current_chain->certs); i++) {
54923258cfeSbeck 		if (X509_cmp(sk_X509_value(current_chain->certs, i),
55076d63a55Sbeck 		    candidate) == 0)
55123258cfeSbeck 			return 0;
55223258cfeSbeck 	}
55323258cfeSbeck 
55423258cfeSbeck 	if (ctx->sig_checks++ > X509_VERIFY_MAX_SIGCHECKS) {
55523258cfeSbeck 		/* don't allow callback to override safety check */
55623258cfeSbeck 		(void) x509_verify_cert_error(ctx, candidate, depth,
55723258cfeSbeck 		    X509_V_ERR_CERT_CHAIN_TOO_LONG, 0);
55823258cfeSbeck 		return 0;
55923258cfeSbeck 	}
56023258cfeSbeck 
56188e5d447Sbeck 	if (!x509_verify_parent_signature(candidate, cert, &ctx->error)) {
56223258cfeSbeck 		if (!x509_verify_cert_error(ctx, candidate, depth,
56323258cfeSbeck 		    ctx->error, 0))
56423258cfeSbeck 			return 0;
56523258cfeSbeck 	}
56623258cfeSbeck 
56723258cfeSbeck 	if (!x509_verify_cert_valid(ctx, candidate, current_chain))
56823258cfeSbeck 		return 0;
56923258cfeSbeck 
57023258cfeSbeck 	/* candidate is good, add it to a copy of the current chain */
57123258cfeSbeck 	if ((new_chain = x509_verify_chain_dup(current_chain)) == NULL) {
57223258cfeSbeck 		x509_verify_cert_error(ctx, candidate, depth,
57323258cfeSbeck 		    X509_V_ERR_OUT_OF_MEM, 0);
57423258cfeSbeck 		return 0;
57523258cfeSbeck 	}
57623258cfeSbeck 	if (!x509_verify_chain_append(new_chain, candidate, &ctx->error)) {
577a235c622Sjsing 		x509_verify_cert_error(ctx, candidate, depth, ctx->error, 0);
57823258cfeSbeck 		x509_verify_chain_free(new_chain);
57923258cfeSbeck 		return 0;
58023258cfeSbeck 	}
58123258cfeSbeck 
58223258cfeSbeck 	/*
58323258cfeSbeck 	 * If candidate is a trusted root, we have a validated chain,
58423258cfeSbeck 	 * so we save it.  Otherwise, recurse until we find a root or
58523258cfeSbeck 	 * give up.
58623258cfeSbeck 	 */
587733666e3Sjsing 	if (is_root_cert) {
588d095297bStb 		if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain, 0, 1)) {
589733666e3Sjsing 			x509_verify_chain_free(new_chain);
590733666e3Sjsing 			return 0;
591733666e3Sjsing 		}
59289ae9cb0Sbeck 		if (!x509_verify_ctx_add_chain(ctx, new_chain)) {
59389ae9cb0Sbeck 			x509_verify_chain_free(new_chain);
59489ae9cb0Sbeck 			return 0;
595733666e3Sjsing 		}
59689ae9cb0Sbeck 		goto done;
597733666e3Sjsing 	}
598733666e3Sjsing 
5999ab39fd2Sbeck 	x509_verify_build_chains(ctx, candidate, new_chain, full_chain);
60023258cfeSbeck 
601733666e3Sjsing  done:
60223258cfeSbeck 	x509_verify_chain_free(new_chain);
60323258cfeSbeck 	return 1;
60423258cfeSbeck }
60523258cfeSbeck 
60623258cfeSbeck static int
60723258cfeSbeck x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth,
60823258cfeSbeck     int error, int ok)
60923258cfeSbeck {
61023258cfeSbeck 	ctx->error = error;
61123258cfeSbeck 	ctx->error_depth = depth;
61223258cfeSbeck 	if (ctx->xsc != NULL) {
61323258cfeSbeck 		ctx->xsc->error = error;
61423258cfeSbeck 		ctx->xsc->error_depth = depth;
61523258cfeSbeck 		ctx->xsc->current_cert = cert;
61623258cfeSbeck 		return ctx->xsc->verify_cb(ok, ctx->xsc);
61723258cfeSbeck 	}
61823258cfeSbeck 	return ok;
61923258cfeSbeck }
62023258cfeSbeck 
62123258cfeSbeck static void
62223258cfeSbeck x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
6239ab39fd2Sbeck     struct x509_verify_chain *current_chain, int full_chain)
62423258cfeSbeck {
62523258cfeSbeck 	X509 *candidate;
6269ab39fd2Sbeck 	int i, depth, count, ret, is_root;
62723258cfeSbeck 
6284f6c473eSbeck 	/*
6294f6c473eSbeck 	 * If we are finding chains with an xsc, just stop after we have
6304f6c473eSbeck 	 * one chain, there's no point in finding more, it just exercises
6314f6c473eSbeck 	 * the potentially buggy callback processing in the calling software.
6324f6c473eSbeck 	 */
6334f6c473eSbeck 	if (ctx->xsc != NULL && ctx->chains_count > 0)
6344f6c473eSbeck 		return;
6354f6c473eSbeck 
63623258cfeSbeck 	depth = sk_X509_num(current_chain->certs);
63723258cfeSbeck 	if (depth > 0)
63823258cfeSbeck 		depth--;
63923258cfeSbeck 
64023258cfeSbeck 	if (depth >= ctx->max_depth &&
64123258cfeSbeck 	    !x509_verify_cert_error(ctx, cert, depth,
64223258cfeSbeck 		X509_V_ERR_CERT_CHAIN_TOO_LONG, 0))
64323258cfeSbeck 		return;
64423258cfeSbeck 
64523258cfeSbeck 	count = ctx->chains_count;
64689ae9cb0Sbeck 
64750df4f34Sbeck 	ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
64823258cfeSbeck 	ctx->error_depth = depth;
64989ae9cb0Sbeck 
65089ae9cb0Sbeck 	if (ctx->saved_error != 0)
65189ae9cb0Sbeck 		ctx->error = ctx->saved_error;
65289ae9cb0Sbeck 	if (ctx->saved_error_depth != 0)
65389ae9cb0Sbeck 		ctx->error_depth = ctx->saved_error_depth;
65489ae9cb0Sbeck 
655ddb051cdSbeck 	if (ctx->xsc != NULL) {
656ddb051cdSbeck 		/*
657ddb051cdSbeck 		 * Long ago experiments at Muppet labs resulted in a
658ddb051cdSbeck 		 * situation where software not only sees these errors
659ddb051cdSbeck 		 * but forced developers to expect them in certain cases.
660ddb051cdSbeck 		 * so we must mimic this awfulness for the legacy case.
661ddb051cdSbeck 		 */
662ddb051cdSbeck 		if (cert->ex_flags & EXFLAG_SS)
663ddb051cdSbeck 			ctx->error = (depth == 0) ?
664ddb051cdSbeck 			    X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
665ddb051cdSbeck 			    X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
666ddb051cdSbeck 	}
66723258cfeSbeck 
66858d6c226Sbeck 	/* Check for legacy mode roots */
669e096bf87Sjsing 	if (ctx->xsc != NULL) {
670e096bf87Sjsing 		if ((ret = ctx->xsc->get_issuer(&candidate, ctx->xsc, cert)) < 0) {
671e096bf87Sjsing 			x509_verify_cert_error(ctx, cert, depth,
672e096bf87Sjsing 			    X509_V_ERR_STORE_LOOKUP, 0);
673e096bf87Sjsing 			return;
674e096bf87Sjsing 		}
675e096bf87Sjsing 		if (ret > 0) {
676e096bf87Sjsing 			if (x509_verify_potential_parent(ctx, candidate, cert)) {
6779ab39fd2Sbeck 				is_root = !full_chain ||
6789ab39fd2Sbeck 				    x509_verify_cert_self_signed(candidate);
679e096bf87Sjsing 				x509_verify_consider_candidate(ctx, cert,
68088e5d447Sbeck 				    is_root, candidate, current_chain,
6819ab39fd2Sbeck 				    full_chain);
682e096bf87Sjsing 			}
683e096bf87Sjsing 			X509_free(candidate);
684e096bf87Sjsing 		}
68599d404ebSbeck 	} else {
68699d404ebSbeck 		/* Check to see if we have a trusted root issuer. */
68799d404ebSbeck 		for (i = 0; i < sk_X509_num(ctx->roots); i++) {
68899d404ebSbeck 			candidate = sk_X509_value(ctx->roots, i);
68999d404ebSbeck 			if (x509_verify_potential_parent(ctx, candidate, cert)) {
69099d404ebSbeck 				is_root = !full_chain ||
69199d404ebSbeck 				    x509_verify_cert_self_signed(candidate);
69299d404ebSbeck 				x509_verify_consider_candidate(ctx, cert,
69388e5d447Sbeck 				    is_root, candidate, current_chain,
69499d404ebSbeck 				    full_chain);
69599d404ebSbeck 			}
69699d404ebSbeck 		}
697e096bf87Sjsing 	}
698e096bf87Sjsing 
69958d6c226Sbeck 	/* Check intermediates after checking roots */
70058d6c226Sbeck 	if (ctx->intermediates != NULL) {
70158d6c226Sbeck 		for (i = 0; i < sk_X509_num(ctx->intermediates); i++) {
70258d6c226Sbeck 			candidate = sk_X509_value(ctx->intermediates, i);
70358d6c226Sbeck 			if (x509_verify_potential_parent(ctx, candidate, cert)) {
70458d6c226Sbeck 				x509_verify_consider_candidate(ctx, cert,
70588e5d447Sbeck 				    0, candidate, current_chain,
7069ab39fd2Sbeck 				    full_chain);
70758d6c226Sbeck 			}
70858d6c226Sbeck 		}
70958d6c226Sbeck 	}
71058d6c226Sbeck 
71123258cfeSbeck 	if (ctx->chains_count > count) {
71223258cfeSbeck 		if (ctx->xsc != NULL) {
71323258cfeSbeck 			ctx->xsc->error = X509_V_OK;
71423258cfeSbeck 			ctx->xsc->error_depth = depth;
71523258cfeSbeck 			ctx->xsc->current_cert = cert;
71623258cfeSbeck 		}
71776d63a55Sbeck 	} else if (ctx->error_depth == depth) {
718d095297bStb 		if (!x509_verify_ctx_set_xsc_chain(ctx, current_chain, 0, 0))
719532f0381Sjsing 			return;
72023258cfeSbeck 	}
72123258cfeSbeck }
72223258cfeSbeck 
72323258cfeSbeck static int
72423258cfeSbeck x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, char *name)
72523258cfeSbeck {
72623258cfeSbeck 	char *candidate;
72723258cfeSbeck 	size_t len;
72823258cfeSbeck 
72923258cfeSbeck 	if (name == NULL) {
730f31559c1Stb 		if (ctx->xsc != NULL) {
731f31559c1Stb 			int ret;
732f31559c1Stb 
733f31559c1Stb 			if ((ret = x509_vfy_check_id(ctx->xsc)) == 0)
734f31559c1Stb 				ctx->error = ctx->xsc->error;
735f31559c1Stb 			return ret;
736f31559c1Stb 		}
73723258cfeSbeck 		return 1;
73823258cfeSbeck 	}
73923258cfeSbeck 	if ((candidate = strdup(name)) == NULL) {
74023258cfeSbeck 		ctx->error = X509_V_ERR_OUT_OF_MEM;
74123258cfeSbeck 		goto err;
74223258cfeSbeck 	}
74323258cfeSbeck 	if ((len = strlen(candidate)) < 1) {
74423258cfeSbeck 		ctx->error = X509_V_ERR_UNSPECIFIED; /* XXX */
74523258cfeSbeck 		goto err;
74623258cfeSbeck 	}
74723258cfeSbeck 
74823258cfeSbeck 	/* IP addresses may be written in [ ]. */
74923258cfeSbeck 	if (candidate[0] == '[' && candidate[len - 1] == ']') {
75023258cfeSbeck 		candidate[len - 1] = '\0';
75123258cfeSbeck 		if (X509_check_ip_asc(cert, candidate + 1, 0) <= 0) {
75223258cfeSbeck 			ctx->error = X509_V_ERR_IP_ADDRESS_MISMATCH;
75323258cfeSbeck 			goto err;
75423258cfeSbeck 		}
75523258cfeSbeck 	} else {
75623258cfeSbeck 		int flags = 0;
75723258cfeSbeck 
75823258cfeSbeck 		if (ctx->xsc == NULL)
75923258cfeSbeck 			flags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT;
76023258cfeSbeck 
76123258cfeSbeck 		if (X509_check_host(cert, candidate, len, flags, NULL) <= 0) {
76223258cfeSbeck 			ctx->error = X509_V_ERR_HOSTNAME_MISMATCH;
76323258cfeSbeck 			goto err;
76423258cfeSbeck 		}
76523258cfeSbeck 	}
76623258cfeSbeck 	free(candidate);
76723258cfeSbeck 	return 1;
76823258cfeSbeck  err:
76923258cfeSbeck 	free(candidate);
77023258cfeSbeck 	return x509_verify_cert_error(ctx, cert, 0, ctx->error, 0);
77123258cfeSbeck }
77223258cfeSbeck 
77323258cfeSbeck static int
77423258cfeSbeck x509_verify_set_check_time(struct x509_verify_ctx *ctx) {
77523258cfeSbeck 	if (ctx->xsc != NULL)  {
77623258cfeSbeck 		if (ctx->xsc->param->flags & X509_V_FLAG_USE_CHECK_TIME) {
77723258cfeSbeck 			ctx->check_time = &ctx->xsc->param->check_time;
77823258cfeSbeck 			return 1;
77923258cfeSbeck 		}
78023258cfeSbeck 		if (ctx->xsc->param->flags & X509_V_FLAG_NO_CHECK_TIME)
78123258cfeSbeck 			return 0;
78223258cfeSbeck 	}
78323258cfeSbeck 
78423258cfeSbeck 	ctx->check_time = NULL;
78523258cfeSbeck 	return 1;
78623258cfeSbeck }
78723258cfeSbeck 
78823258cfeSbeck static int
78988e5d447Sbeck x509_verify_cert_times(X509 *cert, time_t *cmp_time, int *error)
79023258cfeSbeck {
79123258cfeSbeck 	time_t when;
79223258cfeSbeck 
79323258cfeSbeck 	if (cmp_time == NULL)
79423258cfeSbeck 		when = time(NULL);
79523258cfeSbeck 	else
79623258cfeSbeck 		when = *cmp_time;
79723258cfeSbeck 
79888e5d447Sbeck 	if (cert->not_before == -1) {
79988e5d447Sbeck 		*error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
80023258cfeSbeck 		return 0;
80123258cfeSbeck 	}
80288e5d447Sbeck 	if (when < cert->not_before) {
80323258cfeSbeck 		*error = X509_V_ERR_CERT_NOT_YET_VALID;
80423258cfeSbeck 		return 0;
80523258cfeSbeck 	}
80688e5d447Sbeck 	if (cert->not_after == -1) {
80788e5d447Sbeck 		*error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
80888e5d447Sbeck 		return 0;
80988e5d447Sbeck 	}
81088e5d447Sbeck 	if (when > cert->not_after) {
81188e5d447Sbeck 		*error = X509_V_ERR_CERT_HAS_EXPIRED;
81288e5d447Sbeck 		return 0;
81323258cfeSbeck 	}
81423258cfeSbeck 
81523258cfeSbeck 	return 1;
81623258cfeSbeck }
81723258cfeSbeck 
81823258cfeSbeck static int
81923258cfeSbeck x509_verify_validate_constraints(X509 *cert,
82023258cfeSbeck     struct x509_verify_chain *current_chain, int *error)
82123258cfeSbeck {
82223258cfeSbeck 	struct x509_constraints_names *excluded = NULL;
82323258cfeSbeck 	struct x509_constraints_names *permitted = NULL;
82423258cfeSbeck 	int err = X509_V_ERR_UNSPECIFIED;
82523258cfeSbeck 
82623258cfeSbeck 	if (current_chain == NULL)
82723258cfeSbeck 		return 1;
82823258cfeSbeck 
82923258cfeSbeck 	if (cert->nc != NULL) {
83042f3108aStb 		if ((permitted = x509_constraints_names_new(
83142f3108aStb 		    X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) {
83223258cfeSbeck 			err = X509_V_ERR_OUT_OF_MEM;
83323258cfeSbeck 			goto err;
83423258cfeSbeck 		}
83542f3108aStb 		if ((excluded = x509_constraints_names_new(
83642f3108aStb 		    X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) {
83723258cfeSbeck 			err = X509_V_ERR_OUT_OF_MEM;
83823258cfeSbeck 			goto err;
83923258cfeSbeck 		}
84023258cfeSbeck 		if (!x509_constraints_extract_constraints(cert,
84123258cfeSbeck 		    permitted, excluded, &err))
84223258cfeSbeck 			goto err;
84323258cfeSbeck 		if (!x509_constraints_check(current_chain->names,
84423258cfeSbeck 		    permitted, excluded, &err))
84523258cfeSbeck 			goto err;
84623258cfeSbeck 		x509_constraints_names_free(excluded);
84723258cfeSbeck 		x509_constraints_names_free(permitted);
84823258cfeSbeck 	}
84923258cfeSbeck 
85023258cfeSbeck 	return 1;
85123258cfeSbeck  err:
85223258cfeSbeck 	*error = err;
85323258cfeSbeck 	x509_constraints_names_free(excluded);
85423258cfeSbeck 	x509_constraints_names_free(permitted);
85523258cfeSbeck 	return 0;
85623258cfeSbeck }
85723258cfeSbeck 
85823258cfeSbeck static int
85923258cfeSbeck x509_verify_cert_extensions(struct x509_verify_ctx *ctx, X509 *cert, int need_ca)
86023258cfeSbeck {
861bf735c1eSbeck 	if (!x509_verify_cert_cache_extensions(cert)) {
8623746f1b0Stobhe 		ctx->error = X509_V_ERR_UNSPECIFIED;
8633746f1b0Stobhe 		return 0;
8643746f1b0Stobhe 	}
86523258cfeSbeck 
86623258cfeSbeck 	if (ctx->xsc != NULL)
86723258cfeSbeck 		return 1;	/* legacy is checked after chain is built */
86823258cfeSbeck 
86923258cfeSbeck 	if (cert->ex_flags & EXFLAG_CRITICAL) {
87023258cfeSbeck 		ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
87123258cfeSbeck 		return 0;
87223258cfeSbeck 	}
87323258cfeSbeck 	/* No we don't care about v1, netscape, and other ancient silliness */
87423258cfeSbeck 	if (need_ca && (!(cert->ex_flags & EXFLAG_BCONS) &&
87523258cfeSbeck 	    (cert->ex_flags & EXFLAG_CA))) {
87623258cfeSbeck 		ctx->error = X509_V_ERR_INVALID_CA;
87723258cfeSbeck 		return 0;
87823258cfeSbeck 	}
87923258cfeSbeck 	if (ctx->purpose > 0 && X509_check_purpose(cert, ctx->purpose, need_ca)) {
88023258cfeSbeck 		ctx->error = X509_V_ERR_INVALID_PURPOSE;
88123258cfeSbeck 		return 0;
88223258cfeSbeck 	}
88323258cfeSbeck 
88423258cfeSbeck 	/* XXX support proxy certs later in new api */
88523258cfeSbeck 	if (ctx->xsc == NULL && cert->ex_flags & EXFLAG_PROXY) {
88623258cfeSbeck 		ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
88723258cfeSbeck 		return 0;
88823258cfeSbeck 	}
88923258cfeSbeck 
89023258cfeSbeck 	return 1;
89123258cfeSbeck }
89223258cfeSbeck 
89323258cfeSbeck /* Validate that cert is a possible candidate to append to current_chain */
89423258cfeSbeck static int
89523258cfeSbeck x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert,
89623258cfeSbeck     struct x509_verify_chain *current_chain)
89723258cfeSbeck {
89823258cfeSbeck 	X509 *issuer_candidate;
89923258cfeSbeck 	int should_be_ca = current_chain != NULL;
90023258cfeSbeck 	size_t depth = 0;
90123258cfeSbeck 
902ec12bfceSbeck 	if (current_chain != NULL)
90323258cfeSbeck 		depth = sk_X509_num(current_chain->certs);
90423258cfeSbeck 
90523258cfeSbeck 	if (!x509_verify_cert_extensions(ctx, cert, should_be_ca))
90623258cfeSbeck 		return 0;
90723258cfeSbeck 
90823258cfeSbeck 	if (should_be_ca) {
90923258cfeSbeck 		issuer_candidate = x509_verify_chain_last(current_chain);
91023258cfeSbeck 		if (issuer_candidate != NULL &&
91123258cfeSbeck 		    !X509_check_issued(issuer_candidate, cert))
91223258cfeSbeck 			if (!x509_verify_cert_error(ctx, cert, depth,
91323258cfeSbeck 			    X509_V_ERR_SUBJECT_ISSUER_MISMATCH, 0))
91423258cfeSbeck 				return 0;
91523258cfeSbeck 	}
91623258cfeSbeck 
91723258cfeSbeck 	if (x509_verify_set_check_time(ctx)) {
91888e5d447Sbeck 		if (!x509_verify_cert_times(cert, ctx->check_time,
91988e5d447Sbeck 		    &ctx->error)) {
92023258cfeSbeck 			if (!x509_verify_cert_error(ctx, cert, depth,
92123258cfeSbeck 			    ctx->error, 0))
92223258cfeSbeck 				return 0;
92323258cfeSbeck 		}
92423258cfeSbeck 	}
92523258cfeSbeck 
92623258cfeSbeck 	if (!x509_verify_validate_constraints(cert, current_chain,
92723258cfeSbeck 	    &ctx->error) && !x509_verify_cert_error(ctx, cert, depth,
92823258cfeSbeck 	    ctx->error, 0))
92923258cfeSbeck 		return 0;
93023258cfeSbeck 
93123258cfeSbeck 	return 1;
93223258cfeSbeck }
93323258cfeSbeck 
93423258cfeSbeck struct x509_verify_ctx *
93599d404ebSbeck x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc)
93623258cfeSbeck {
93723258cfeSbeck 	struct x509_verify_ctx *ctx;
9382c940cf3Sjsing 	size_t max_depth;
93923258cfeSbeck 
94023258cfeSbeck 	if (xsc == NULL)
94123258cfeSbeck 		return NULL;
94223258cfeSbeck 
94399d404ebSbeck 	if ((ctx = x509_verify_ctx_new(NULL)) == NULL)
94423258cfeSbeck 		return NULL;
94523258cfeSbeck 
94623258cfeSbeck 	ctx->xsc = xsc;
94723258cfeSbeck 
94823258cfeSbeck 	if (xsc->untrusted &&
94923258cfeSbeck 	    (ctx->intermediates = X509_chain_up_ref(xsc->untrusted)) == NULL)
95023258cfeSbeck 		goto err;
95123258cfeSbeck 
9522c940cf3Sjsing 	max_depth = X509_VERIFY_MAX_CHAIN_CERTS;
9532c940cf3Sjsing 	if (xsc->param->depth > 0 && xsc->param->depth < X509_VERIFY_MAX_CHAIN_CERTS)
9542c940cf3Sjsing 		max_depth = xsc->param->depth;
9552c940cf3Sjsing 	if (!x509_verify_ctx_set_max_depth(ctx, max_depth))
95623258cfeSbeck 		goto err;
95723258cfeSbeck 
95823258cfeSbeck 	return ctx;
95923258cfeSbeck  err:
96023258cfeSbeck 	x509_verify_ctx_free(ctx);
96123258cfeSbeck 	return NULL;
96223258cfeSbeck }
96323258cfeSbeck 
96423258cfeSbeck /* Public API */
96523258cfeSbeck 
96623258cfeSbeck struct x509_verify_ctx *
96723258cfeSbeck x509_verify_ctx_new(STACK_OF(X509) *roots)
96823258cfeSbeck {
96923258cfeSbeck 	struct x509_verify_ctx *ctx;
97023258cfeSbeck 
97123258cfeSbeck 	if ((ctx = calloc(1, sizeof(struct x509_verify_ctx))) == NULL)
97223258cfeSbeck 		return NULL;
97323258cfeSbeck 
97499d404ebSbeck 	if (roots != NULL) {
97523258cfeSbeck 		if  ((ctx->roots = X509_chain_up_ref(roots)) == NULL)
97623258cfeSbeck 			goto err;
97799d404ebSbeck 	} else {
97899d404ebSbeck 		if ((ctx->roots = sk_X509_new_null()) == NULL)
97999d404ebSbeck 			goto err;
98099d404ebSbeck 	}
98123258cfeSbeck 
98223258cfeSbeck 	ctx->max_depth = X509_VERIFY_MAX_CHAIN_CERTS;
98323258cfeSbeck 	ctx->max_chains = X509_VERIFY_MAX_CHAINS;
98423258cfeSbeck 	ctx->max_sigs = X509_VERIFY_MAX_SIGCHECKS;
98523258cfeSbeck 
98623258cfeSbeck 	if ((ctx->chains = calloc(X509_VERIFY_MAX_CHAINS,
98723258cfeSbeck 	    sizeof(*ctx->chains))) == NULL)
98823258cfeSbeck 		goto err;
98923258cfeSbeck 
99023258cfeSbeck 	return ctx;
99123258cfeSbeck  err:
99223258cfeSbeck 	x509_verify_ctx_free(ctx);
99323258cfeSbeck 	return NULL;
99423258cfeSbeck }
99523258cfeSbeck 
99623258cfeSbeck void
99723258cfeSbeck x509_verify_ctx_free(struct x509_verify_ctx *ctx)
99823258cfeSbeck {
99923258cfeSbeck 	if (ctx == NULL)
100023258cfeSbeck 		return;
100123258cfeSbeck 	sk_X509_pop_free(ctx->roots, X509_free);
100223258cfeSbeck 	x509_verify_ctx_clear(ctx);
100323258cfeSbeck 	free(ctx);
100423258cfeSbeck }
100523258cfeSbeck 
100623258cfeSbeck int
100723258cfeSbeck x509_verify_ctx_set_max_depth(struct x509_verify_ctx *ctx, size_t max)
100823258cfeSbeck {
100923258cfeSbeck 	if (max < 1 || max > X509_VERIFY_MAX_CHAIN_CERTS)
101023258cfeSbeck 		return 0;
101123258cfeSbeck 	ctx->max_depth = max;
101223258cfeSbeck 	return 1;
101323258cfeSbeck }
101423258cfeSbeck 
101523258cfeSbeck int
101623258cfeSbeck x509_verify_ctx_set_max_chains(struct x509_verify_ctx *ctx, size_t max)
101723258cfeSbeck {
101823258cfeSbeck 	if (max < 1 || max > X509_VERIFY_MAX_CHAINS)
101923258cfeSbeck 		return 0;
102023258cfeSbeck 	ctx->max_chains = max;
102123258cfeSbeck 	return 1;
102223258cfeSbeck }
102323258cfeSbeck 
102423258cfeSbeck int
102523258cfeSbeck x509_verify_ctx_set_max_signatures(struct x509_verify_ctx *ctx, size_t max)
102623258cfeSbeck {
10279f2be83cSjsing 	if (max < 1 || max > 100000)
102823258cfeSbeck 		return 0;
102923258cfeSbeck 	ctx->max_sigs = max;
103023258cfeSbeck 	return 1;
103123258cfeSbeck }
103223258cfeSbeck 
103323258cfeSbeck int
103423258cfeSbeck x509_verify_ctx_set_purpose(struct x509_verify_ctx *ctx, int purpose)
103523258cfeSbeck {
103623258cfeSbeck 	if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX)
103723258cfeSbeck 		return 0;
103823258cfeSbeck 	ctx->purpose = purpose;
103923258cfeSbeck 	return 1;
104023258cfeSbeck }
104123258cfeSbeck 
104223258cfeSbeck int
104323258cfeSbeck x509_verify_ctx_set_intermediates(struct x509_verify_ctx *ctx,
104423258cfeSbeck     STACK_OF(X509) *intermediates)
104523258cfeSbeck {
104623258cfeSbeck 	if ((ctx->intermediates = X509_chain_up_ref(intermediates)) == NULL)
104723258cfeSbeck 		return 0;
104823258cfeSbeck 	return 1;
104923258cfeSbeck }
105023258cfeSbeck 
105123258cfeSbeck const char *
105223258cfeSbeck x509_verify_ctx_error_string(struct x509_verify_ctx *ctx)
105323258cfeSbeck {
105423258cfeSbeck 	return X509_verify_cert_error_string(ctx->error);
105523258cfeSbeck }
105623258cfeSbeck 
105723258cfeSbeck size_t
105823258cfeSbeck x509_verify_ctx_error_depth(struct x509_verify_ctx *ctx)
105923258cfeSbeck {
106023258cfeSbeck 	return ctx->error_depth;
106123258cfeSbeck }
106223258cfeSbeck 
106323258cfeSbeck STACK_OF(X509) *
106423258cfeSbeck x509_verify_ctx_chain(struct x509_verify_ctx *ctx, size_t i)
106523258cfeSbeck {
106623258cfeSbeck 	if (i >= ctx->chains_count)
106723258cfeSbeck 		return NULL;
106823258cfeSbeck 	return ctx->chains[i]->certs;
106923258cfeSbeck }
107023258cfeSbeck 
107123258cfeSbeck size_t
107223258cfeSbeck x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
107323258cfeSbeck {
107423258cfeSbeck 	struct x509_verify_chain *current_chain;
10759ab39fd2Sbeck 	int retry_chain_build, full_chain = 0;
107623258cfeSbeck 
1077e4db083fSbeck 	if (ctx->roots == NULL || ctx->max_depth == 0) {
107823258cfeSbeck 		ctx->error = X509_V_ERR_INVALID_CALL;
1079b77df7f7Stb 		goto err;
108023258cfeSbeck 	}
108123258cfeSbeck 
108223258cfeSbeck 	if (ctx->xsc != NULL) {
108323258cfeSbeck 		if (leaf != NULL || name != NULL) {
108423258cfeSbeck 			ctx->error = X509_V_ERR_INVALID_CALL;
1085b77df7f7Stb 			goto err;
108623258cfeSbeck 		}
108723258cfeSbeck 		leaf = ctx->xsc->cert;
108823258cfeSbeck 
10899ab39fd2Sbeck 		/* XXX */
10909ab39fd2Sbeck 		full_chain = 1;
10919ab39fd2Sbeck 		if (ctx->xsc->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
10929ab39fd2Sbeck 			full_chain = 0;
109323258cfeSbeck 		/*
109423258cfeSbeck 		 * XXX
109523258cfeSbeck 		 * The legacy code expects the top level cert to be
109623258cfeSbeck 		 * there, even if we didn't find a chain. So put it
109723258cfeSbeck 		 * there, we will clobber it later if we find a valid
109823258cfeSbeck 		 * chain.
109923258cfeSbeck 		 */
110023258cfeSbeck 		if ((ctx->xsc->chain = sk_X509_new_null()) == NULL) {
110123258cfeSbeck 			ctx->error = X509_V_ERR_OUT_OF_MEM;
1102b77df7f7Stb 			goto err;
110323258cfeSbeck 		}
110423258cfeSbeck 		if (!X509_up_ref(leaf)) {
110523258cfeSbeck 			ctx->error = X509_V_ERR_OUT_OF_MEM;
1106b77df7f7Stb 			goto err;
110723258cfeSbeck 		}
110823258cfeSbeck 		if (!sk_X509_push(ctx->xsc->chain, leaf)) {
110923258cfeSbeck 			X509_free(leaf);
111023258cfeSbeck 			ctx->error = X509_V_ERR_OUT_OF_MEM;
1111b77df7f7Stb 			goto err;
111223258cfeSbeck 		}
1113d59cc15fSbeck 		ctx->xsc->error_depth = 0;
1114d59cc15fSbeck 		ctx->xsc->current_cert = leaf;
111523258cfeSbeck 	}
111623258cfeSbeck 
111734417d0dSjsing 	if (!x509_verify_cert_valid(ctx, leaf, NULL))
1118b77df7f7Stb 		goto err;
111934417d0dSjsing 
112034417d0dSjsing 	if (!x509_verify_cert_hostname(ctx, leaf, name))
1121b77df7f7Stb 		goto err;
112234417d0dSjsing 
112323258cfeSbeck 	if ((current_chain = x509_verify_chain_new()) == NULL) {
112423258cfeSbeck 		ctx->error = X509_V_ERR_OUT_OF_MEM;
1125b77df7f7Stb 		goto err;
112623258cfeSbeck 	}
112723258cfeSbeck 	if (!x509_verify_chain_append(current_chain, leaf, &ctx->error)) {
112823258cfeSbeck 		x509_verify_chain_free(current_chain);
1129b77df7f7Stb 		goto err;
113023258cfeSbeck 	}
11319ab39fd2Sbeck 	do {
11329ab39fd2Sbeck 		retry_chain_build = 0;
113389ae9cb0Sbeck 		if (x509_verify_ctx_cert_is_root(ctx, leaf, full_chain)) {
113489ae9cb0Sbeck 			if (!x509_verify_ctx_add_chain(ctx, current_chain)) {
113589ae9cb0Sbeck 				x509_verify_chain_free(current_chain);
113689ae9cb0Sbeck 				goto err;
113789ae9cb0Sbeck 			}
113889ae9cb0Sbeck 		} else {
11399ab39fd2Sbeck 			x509_verify_build_chains(ctx, leaf, current_chain,
11409ab39fd2Sbeck 			    full_chain);
11419ab39fd2Sbeck 			if (full_chain && ctx->chains_count == 0) {
11429ab39fd2Sbeck 				/*
11439ab39fd2Sbeck 				 * Save the error state from the xsc
11449ab39fd2Sbeck 				 * at this point to put back on the
11459ab39fd2Sbeck 				 * xsc in case we do not find a chain
11469ab39fd2Sbeck 				 * that is trusted but not a full
11479ab39fd2Sbeck 				 * chain to a self signed root. This
11489ab39fd2Sbeck 				 * is because the unvalidated chain is
11499ab39fd2Sbeck 				 * used by the autochain batshittery
11509ab39fd2Sbeck 				 * on failure and will be needed for
11519ab39fd2Sbeck 				 * that.
11529ab39fd2Sbeck 				 */
11539ab39fd2Sbeck 				if (!x509_verify_ctx_save_xsc_error(ctx)) {
11549ab39fd2Sbeck 					x509_verify_chain_free(current_chain);
11559ab39fd2Sbeck 					goto err;
11569ab39fd2Sbeck 				}
11579ab39fd2Sbeck 				full_chain = 0;
11589ab39fd2Sbeck 				retry_chain_build = 1;
11599ab39fd2Sbeck 			}
11609ab39fd2Sbeck 		}
11619ab39fd2Sbeck 	} while (retry_chain_build);
116223258cfeSbeck 
116323258cfeSbeck 	x509_verify_chain_free(current_chain);
116423258cfeSbeck 
116523258cfeSbeck 	/*
11669ab39fd2Sbeck 	 * Bring back the failure case we wanted to the xsc if
11679ab39fd2Sbeck 	 * we saved one.
11689ab39fd2Sbeck 	 */
11699ab39fd2Sbeck 	if (!x509_verify_ctx_restore_xsc_error(ctx))
11709ab39fd2Sbeck 		goto err;
11719ab39fd2Sbeck 
11729ab39fd2Sbeck 	/*
117323258cfeSbeck 	 * Safety net:
117423258cfeSbeck 	 * We could not find a validated chain, and for some reason do not
117523258cfeSbeck 	 * have an error set.
117623258cfeSbeck 	 */
11771e2ba4e8Sjsing 	if (ctx->chains_count == 0 && ctx->error == X509_V_OK) {
117823258cfeSbeck 		ctx->error = X509_V_ERR_UNSPECIFIED;
11791e2ba4e8Sjsing 		if (ctx->xsc != NULL && ctx->xsc->error != X509_V_OK)
1180a235c622Sjsing 			ctx->error = ctx->xsc->error;
1181a235c622Sjsing 	}
118223258cfeSbeck 
118323258cfeSbeck 	/* Clear whatever errors happened if we have any validated chain */
118423258cfeSbeck 	if (ctx->chains_count > 0)
118523258cfeSbeck 		ctx->error = X509_V_OK;
118623258cfeSbeck 
118723258cfeSbeck 	if (ctx->xsc != NULL) {
11888d234490Sjsing 		ctx->xsc->error = ctx->error;
1189a235c622Sjsing 		if (ctx->chains_count > 0) {
11908d234490Sjsing 			/* Take the first chain we found. */
1191d095297bStb 			if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0],
1192d095297bStb 			    1, 1))
1193a235c622Sjsing 				goto err;
119489ae9cb0Sbeck 			ctx->xsc->error = X509_V_OK;
119589ae9cb0Sbeck 			/*
119689ae9cb0Sbeck 			 * Call the callback indicating success up our already
119789ae9cb0Sbeck 			 * verified chain. The callback could still tell us to
119889ae9cb0Sbeck 			 * fail.
119989ae9cb0Sbeck 			 */
12006cf34315Sbeck 			if(!x509_vfy_callback_indicate_success(ctx->xsc)) {
12016cf34315Sbeck 				/* The callback can change the error code */
12026cf34315Sbeck 				ctx->error = ctx->xsc->error;
120389ae9cb0Sbeck 				goto err;
12046cf34315Sbeck 			}
120589ae9cb0Sbeck 		} else {
120689ae9cb0Sbeck 			/*
120789ae9cb0Sbeck 			 * We had a failure, indicate the failure, but
120889ae9cb0Sbeck 			 * allow the callback to override at depth 0
120989ae9cb0Sbeck 			 */
121089ae9cb0Sbeck 			if (ctx->xsc->verify_cb(0, ctx->xsc)) {
121189ae9cb0Sbeck 				ctx->xsc->error = X509_V_OK;
121289ae9cb0Sbeck 				return 1;
1213a235c622Sjsing 			}
121489ae9cb0Sbeck 		}
121523258cfeSbeck 	}
121623258cfeSbeck 	return (ctx->chains_count);
1217b77df7f7Stb 
1218b77df7f7Stb  err:
12193cb8f152Stb 	if (ctx->error == X509_V_OK)
12203cb8f152Stb 		ctx->error = X509_V_ERR_UNSPECIFIED;
1221b77df7f7Stb 	if (ctx->xsc != NULL)
1222b77df7f7Stb 		ctx->xsc->error = ctx->error;
1223b77df7f7Stb 	return 0;
122423258cfeSbeck }
1225