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