X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fx509%2Fx509_vfy.c;h=c3eb261b94a1e83de4aa9a66246a84f824a05ce4;hp=abe9caae13caa27b28720367990887f0e6a5a592;hb=0820217441b68724d91b7644f3560e15149a1848;hpb=fc9d1ef39c97c06f83fd40a6f94c0af4da3887ea diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index abe9caae13..c3eb261b94 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -12,18 +12,18 @@ #include #include +#include "crypto/ctype.h" #include "internal/cryptlib.h" #include -#include #include #include #include #include #include #include -#include -#include -#include "x509_lcl.h" +#include "internal/dane.h" +#include "crypto/x509.h" +#include "x509_local.h" /* CRL score values */ @@ -104,15 +104,12 @@ static int null_callback(int ok, X509_STORE_CTX *e) return ok; } -/* Return 1 is a certificate is self signed */ -static int cert_self_signed(X509 *x) +/* Return 1 is a certificate is self signed, 0 if not, or -1 on error */ +static int cert_self_signed(X509_STORE_CTX *ctx, X509 *x) { - /* - * FIXME: x509v3_cache_extensions() needs to detect more failures and not - * set EXFLAG_SET when that happens. Especially, if the failures are - * parse errors, rather than memory pressure! - */ - X509_check_purpose(x, -1, 0); + if (!X509v3_cache_extensions(x, ctx->libctx, ctx->propq)) + return -1; + if (x->ex_flags & EXFLAG_SS) return 1; else @@ -216,7 +213,6 @@ static int verify_chain(X509_STORE_CTX *ctx) if ((ok = build_chain(ctx)) == 0 || (ok = check_chain_extensions(ctx)) == 0 || (ok = check_auth_level(ctx)) == 0 || - (ok = check_name_constraints(ctx)) == 0 || (ok = check_id(ctx)) == 0 || 1) X509_get_pubkey_parameters(NULL, ctx->chain); if (ok == 0 || (ok = ctx->check_revocation(ctx)) == 0) @@ -234,6 +230,9 @@ static int verify_chain(X509_STORE_CTX *ctx) if (!ok) return ok; + if ((ok = check_name_constraints(ctx)) == 0) + return ok; + #ifndef OPENSSL_NO_RFC3779 /* RFC 3779 path validation, now that CRL check has been done */ if ((ok = X509v3_asid_validate_path(ctx)) == 0) @@ -308,16 +307,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) { int i; + X509 *issuer, *rv = NULL; for (i = 0; i < sk_X509_num(sk); i++) { - X509 *issuer = sk_X509_value(sk, i); - - if (!ctx->check_issued(ctx, x, issuer)) - continue; - if (x509_check_cert_time(ctx, issuer, -1)) - return issuer; + issuer = sk_X509_value(sk, i); + if (ctx->check_issued(ctx, x, issuer)) { + rv = issuer; + if (x509_check_cert_time(ctx, rv, -1)) + break; + } } - return NULL; + return rv; } /* Given a possible certificate and issuer check them */ @@ -325,14 +325,26 @@ static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) { int ret; - if (x == issuer) - return cert_self_signed(x); + int ss; + + if (x == issuer) { + ss = cert_self_signed(ctx, x); + if (ss < 0) + return 0; + return ss; + } + ret = X509_check_issued(issuer, x); if (ret == X509_V_OK) { int i; X509 *ch; + + ss = cert_self_signed(ctx, x); + if (ss < 0) + return 0; + /* Special case: single self signed certificate */ - if (cert_self_signed(x) && sk_X509_num(ctx->chain) == 1) + if (ss > 0 && sk_X509_num(ctx->chain) == 1) return 1; for (i = 0; i < sk_X509_num(ctx->chain); i++) { ch = sk_X509_value(ctx->chain, i); @@ -358,11 +370,13 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) return 0; } -static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm) +static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, + const X509_NAME *nm) { STACK_OF(X509) *sk = NULL; X509 *x; int i; + for (i = 0; i < sk_X509_num(ctx->other_ctx); i++) { x = sk_X509_value(ctx->other_ctx, i); if (X509_NAME_cmp(nm, X509_get_subject_name(x)) == 0) { @@ -370,6 +384,8 @@ static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm) sk = sk_X509_new_null(); if (sk == NULL || sk_X509_push(sk, x) == 0) { sk_X509_pop_free(sk, X509_free); + X509err(X509_F_LOOKUP_CERTS_SK, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; return NULL; } X509_up_ref(x); @@ -506,20 +522,25 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ret = 1; break; } + if ((x->ex_flags & EXFLAG_CA) == 0 + && x->ex_pathlen != -1 + && (ctx->param->flags & X509_V_FLAG_X509_STRICT)) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + ret = 0; + } if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK)) return 0; /* check_purpose() makes the callback as needed */ if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca)) return 0; - /* Check pathlen if not self issued */ - if ((i > 1) && !(x->ex_flags & EXFLAG_SI) - && (x->ex_pathlen != -1) - && (plen > (x->ex_pathlen + proxy_path_length + 1))) { + /* Check pathlen */ + if ((i > 1) && (x->ex_pathlen != -1) + && (plen > (x->ex_pathlen + proxy_path_length))) { if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED)) return 0; } - /* Increment path length if not self issued */ - if (!(x->ex_flags & EXFLAG_SI)) + /* Increment path length if not a self issued intermediate CA */ + if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0) plen++; /* * If this certificate is a proxy certificate, the next certificate @@ -554,6 +575,27 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) return 1; } +static int has_san_id(X509 *x, int gtype) +{ + int i; + int ret = 0; + GENERAL_NAMES *gs = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + + if (gs == NULL) + return 0; + + for (i = 0; i < sk_GENERAL_NAME_num(gs); i++) { + GENERAL_NAME *g = sk_GENERAL_NAME_value(gs, i); + + if (g->type == gtype) { + ret = 1; + break; + } + } + GENERAL_NAMES_free(gs); + return ret; +} + static int check_name_constraints(X509_STORE_CTX *ctx) { int i; @@ -652,7 +694,12 @@ static int check_name_constraints(X509_STORE_CTX *ctx) int rv = NAME_CONSTRAINTS_check(x, nc); /* If EE certificate check commonName too */ - if (rv == X509_V_OK && i == 0) + if (rv == X509_V_OK && i == 0 + && (ctx->param->hostflags + & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) == 0 + && ((ctx->param->hostflags + & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) != 0 + || !has_san_id(x, GEN_DNS))) rv = NAME_CONSTRAINTS_check_CN(x, nc); switch (rv) { @@ -844,6 +891,9 @@ static int check_cert(X509_STORE_CTX *ctx) ctx->current_crl_score = 0; ctx->current_reasons = 0; + if (x->ex_flags & EXFLAG_PROXY) + return 1; + while (ctx->current_reasons != CRLDP_ALL_REASONS) { unsigned int last_reasons = ctx->current_reasons; @@ -886,7 +936,7 @@ static int check_cert(X509_STORE_CTX *ctx) crl = NULL; dcrl = NULL; /* - * If reasons not updated we wont get anywhere by another iteration, + * If reasons not updated we won't get anywhere by another iteration, * so exit loop. */ if (last_reasons == ctx->current_reasons) { @@ -918,7 +968,7 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) else ptime = NULL; - i = X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime); + i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime); if (i == 0) { if (!notify) return 0; @@ -933,8 +983,8 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) return 0; } - if (X509_CRL_get_nextUpdate(crl)) { - i = X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime); + if (X509_CRL_get0_nextUpdate(crl)) { + i = X509_cmp_time(X509_CRL_get0_nextUpdate(crl), ptime); if (i == 0) { if (!notify) @@ -971,15 +1021,19 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, crl = sk_X509_CRL_value(crls, i); reasons = *preasons; crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x); - if (crl_score < best_score) + if (crl_score < best_score || crl_score == 0) continue; /* If current CRL is equivalent use it if it is newer */ - if (crl_score == best_score) { + if (crl_score == best_score && best_crl != NULL) { int day, sec; - if (ASN1_TIME_diff(&day, &sec, X509_CRL_get_lastUpdate(best_crl), - X509_CRL_get_lastUpdate(crl)) == 0) + if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl), + X509_CRL_get0_lastUpdate(crl)) == 0) continue; - if (day < 0 || sec <= 0) + /* + * ASN1_TIME_diff never returns inconsistent signs for |day| + * and |sec|. + */ + if (day <= 0 && sec <= 0) continue; } best_crl = crl; @@ -1174,7 +1228,7 @@ static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, int *pcrl_score) { X509 *crl_issuer = NULL; - X509_NAME *cnm = X509_CRL_get_issuer(crl); + const X509_NAME *cnm = X509_CRL_get_issuer(crl); int cidx = ctx->error_depth; int i; @@ -1238,7 +1292,7 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) /* Don't allow recursive CRL path validation */ if (ctx->parent) return 0; - if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted)) + if (!X509_STORE_CTX_init(&crl_ctx, ctx->store, x, ctx->untrusted)) return -1; crl_ctx.crls = ctx->crls; @@ -1350,7 +1404,7 @@ static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) { int i; - X509_NAME *nm = X509_CRL_get_issuer(crl); + const X509_NAME *nm = X509_CRL_get_issuer(crl); /* If no CRLissuer return is successful iff don't need a match */ if (!dp->CRLissuer) return ! !(crl_score & CRL_SCORE_ISSUER_NAME); @@ -1409,7 +1463,7 @@ static int get_crl_delta(X509_STORE_CTX *ctx, unsigned int reasons; X509_CRL *crl = NULL, *dcrl = NULL; STACK_OF(X509_CRL) *skcrl; - X509_NAME *nm = X509_get_issuer_name(x); + const X509_NAME *nm = X509_get_issuer_name(x); reasons = ctx->current_reasons; ok = get_crl_sk(ctx, &crl, &dcrl, @@ -1639,7 +1693,7 @@ int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) else ptime = NULL; - i = X509_cmp_time(X509_get_notBefore(x), ptime); + i = X509_cmp_time(X509_get0_notBefore(x), ptime); if (i >= 0 && depth < 0) return 0; if (i == 0 && !verify_cb_cert(ctx, x, depth, @@ -1648,7 +1702,7 @@ int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) if (i > 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_NOT_YET_VALID)) return 0; - i = X509_cmp_time(X509_get_notAfter(x), ptime); + i = X509_cmp_time(X509_get0_notAfter(x), ptime); if (i <= 0 && depth < 0) return 0; if (i == 0 && !verify_cb_cert(ctx, x, depth, @@ -1709,7 +1763,7 @@ static int internal_verify(X509_STORE_CTX *ctx) if (!verify_cb_cert(ctx, xi, xi != xs ? n+1 : n, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)) return 0; - } else if (X509_verify(xs, pkey) <= 0) { + } else if (X509_verify_ex(xs, pkey, ctx->libctx, ctx->propq) <= 0) { if (!verify_cb_cert(ctx, xs, n, X509_V_ERR_CERT_SIGNATURE_FAILURE)) return 0; @@ -1746,119 +1800,96 @@ int X509_cmp_current_time(const ASN1_TIME *ctm) int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) { - char *str; - ASN1_TIME atm; - long offset; - char buff1[24], buff2[24], *p; - int i, j, remaining; - - p = buff1; - remaining = ctm->length; - str = (char *)ctm->data; + static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1; + static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1; + ASN1_TIME *asn1_cmp_time = NULL; + int i, day, sec, ret = 0; +#ifdef CHARSET_EBCDIC + const char upper_z = 0x5A; +#else + const char upper_z = 'Z'; +#endif /* - * Note that the following (historical) code allows much more slack in the - * time format than RFC5280. In RFC5280, the representation is fixed: + * Note that ASN.1 allows much more slack in the time format than RFC5280. + * In RFC5280, the representation is fixed: * UTCTime: YYMMDDHHMMSSZ * GeneralizedTime: YYYYMMDDHHMMSSZ + * + * We do NOT currently enforce the following RFC 5280 requirement: + * "CAs conforming to this profile MUST always encode certificate + * validity dates through the year 2049 as UTCTime; certificate validity + * dates in 2050 or later MUST be encoded as GeneralizedTime." */ - if (ctm->type == V_ASN1_UTCTIME) { - /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */ - int min_length = sizeof("YYMMDDHHMMZ") - 1; - int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1; - if (remaining < min_length || remaining > max_length) + switch (ctm->type) { + case V_ASN1_UTCTIME: + if (ctm->length != (int)(utctime_length)) return 0; - memcpy(p, str, 10); - p += 10; - str += 10; - remaining -= 10; - } else { - /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */ - int min_length = sizeof("YYYYMMDDHHMMZ") - 1; - int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1; - if (remaining < min_length || remaining > max_length) + break; + case V_ASN1_GENERALIZEDTIME: + if (ctm->length != (int)(generalizedtime_length)) return 0; - memcpy(p, str, 12); - p += 12; - str += 12; - remaining -= 12; + break; + default: + return 0; } - if ((*str == 'Z') || (*str == '-') || (*str == '+')) { - *(p++) = '0'; - *(p++) = '0'; - } else { - /* SS (seconds) */ - if (remaining < 2) + /** + * Verify the format: the ASN.1 functions we use below allow a more + * flexible format than what's mandated by RFC 5280. + * Digit and date ranges will be verified in the conversion methods. + */ + for (i = 0; i < ctm->length - 1; i++) { + if (!ascii_isdigit(ctm->data[i])) return 0; - *(p++) = *(str++); - *(p++) = *(str++); - remaining -= 2; - /* - * Skip any (up to three) fractional seconds... - * TODO(emilia): in RFC5280, fractional seconds are forbidden. - * Can we just kill them altogether? - */ - if (remaining && *str == '.') { - str++; - remaining--; - for (i = 0; i < 3 && remaining; i++, str++, remaining--) { - if (*str < '0' || *str > '9') - break; - } - } - } - *(p++) = 'Z'; - *(p++) = '\0'; - - /* We now need either a terminating 'Z' or an offset. */ - if (!remaining) + if (ctm->data[ctm->length - 1] != upper_z) return 0; - if (*str == 'Z') { - if (remaining != 1) - return 0; - offset = 0; - } else { - /* (+-)HHMM */ - if ((*str != '+') && (*str != '-')) - return 0; - /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */ - if (remaining != 5) - return 0; - if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' || - str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9') - return 0; - offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; - offset += (str[3] - '0') * 10 + (str[4] - '0'); - if (*str == '-') - offset = -offset; - } - atm.type = ctm->type; - atm.flags = 0; - atm.length = sizeof(buff2); - atm.data = (unsigned char *)buff2; - if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) - return 0; + /* + * There is ASN1_UTCTIME_cmp_time_t but no + * ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t, + * so we go through ASN.1 + */ + asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time); + if (asn1_cmp_time == NULL) + goto err; + if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time)) + goto err; - if (ctm->type == V_ASN1_UTCTIME) { - i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); - if (i < 50) - i += 100; /* cf. RFC 2459 */ - j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); - if (j < 50) - j += 100; - - if (i < j) - return -1; - if (i > j) - return 1; - } - i = strcmp(buff1, buff2); - if (i == 0) /* wait a second then return younger :-) */ + /* + * X509_cmp_time comparison is <=. + * The return value 0 is reserved for errors. + */ + ret = (day >= 0 && sec >= 0) ? -1 : 1; + + err: + ASN1_TIME_free(asn1_cmp_time); + return ret; +} + +/* + * Return 0 if time should not be checked or reference time is in range, + * or else 1 if it is past the end, or -1 if it is before the start + */ +int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm, + const ASN1_TIME *start, const ASN1_TIME *end) +{ + time_t ref_time; + time_t *time = NULL; + unsigned long flags = vpm == NULL ? 0 : X509_VERIFY_PARAM_get_flags(vpm); + + if ((flags & X509_V_FLAG_USE_CHECK_TIME) != 0) { + ref_time = X509_VERIFY_PARAM_get_time(vpm); + time = &ref_time; + } else if ((flags & X509_V_FLAG_NO_CHECK_TIME) != 0) { + return 0; /* this means ok */ + } /* else reference time is the current time */ + + if (end != NULL && X509_cmp_time(end, time) < 0) + return 1; + if (start != NULL && X509_cmp_time(start, time) > 0) return -1; - else - return i; + return 0; } ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) @@ -1976,9 +2007,9 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) goto memerr; - if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer))) + if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer))) goto memerr; - if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer))) + if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer))) goto memerr; /* Set base CRL number: must be critical */ @@ -2037,12 +2068,12 @@ int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); } -void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) +void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx) { return CRYPTO_get_ex_data(&ctx->ex_data, idx); } -int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx) { return ctx->error; } @@ -2052,7 +2083,7 @@ void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) ctx->error = err; } -int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx) { return ctx->error_depth; } @@ -2062,7 +2093,7 @@ void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth) ctx->error_depth = depth; } -X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) +X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx) { return ctx->current_cert; } @@ -2072,29 +2103,29 @@ void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x) ctx->current_cert = x; } -STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx) +STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx) { return ctx->chain; } -STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) +STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx) { if (!ctx->chain) return NULL; return X509_chain_up_ref(ctx->chain); } -X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) +X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx) { return ctx->current_issuer; } -X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) +X509_CRL *X509_STORE_CTX_get0_current_crl(const X509_STORE_CTX *ctx) { return ctx->current_crl; } -X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(const X509_STORE_CTX *ctx) { return ctx->parent; } @@ -2144,10 +2175,10 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, { int idx; /* If purpose not set use default */ - if (!purpose) + if (purpose == 0) purpose = def_purpose; /* If we have a purpose then check it is valid */ - if (purpose) { + if (purpose != 0) { X509_PURPOSE *ptmp; idx = X509_PURPOSE_get_by_id(purpose); if (idx == -1) { @@ -2190,23 +2221,45 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, return 1; } -X509_STORE_CTX *X509_STORE_CTX_new(void) +X509_STORE_CTX *X509_STORE_CTX_new_with_libctx(OPENSSL_CTX *libctx, + const char *propq) { X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); if (ctx == NULL) { - X509err(X509_F_X509_STORE_CTX_NEW, ERR_R_MALLOC_FAILURE); + X509err(0, ERR_R_MALLOC_FAILURE); return NULL; } + + ctx->libctx = libctx; + if (propq != NULL) { + ctx->propq = OPENSSL_strdup(propq); + if (ctx->propq == NULL) { + OPENSSL_free(ctx); + X509err(0, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + return ctx; } +X509_STORE_CTX *X509_STORE_CTX_new(void) +{ + return X509_STORE_CTX_new_with_libctx(NULL, NULL); +} + + void X509_STORE_CTX_free(X509_STORE_CTX *ctx) { if (ctx == NULL) return; X509_STORE_CTX_cleanup(ctx); + + /* libctx and propq survive X509_STORE_CTX_cleanup() */ + OPENSSL_free(ctx->propq); + OPENSSL_free(ctx); } @@ -2215,7 +2268,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, { int ret = 1; - ctx->ctx = store; + ctx->store = store; ctx->cert = x509; ctx->untrusted = chain; ctx->crls = NULL; @@ -2401,12 +2454,12 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, X509_VERIFY_PARAM_set_time(ctx->param, t); } -X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) +X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx) { return ctx->cert; } -STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) +STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) { return ctx->untrusted; } @@ -2428,77 +2481,88 @@ void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, ctx->verify_cb = verify_cb; } -X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx) +X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(const X509_STORE_CTX *ctx) { return ctx->verify_cb; } -X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx) +void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_fn verify) +{ + ctx->verify = verify; +} + +X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx) { return ctx->verify; } -X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx) +X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(const X509_STORE_CTX *ctx) { return ctx->get_issuer; } -X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_issued_fn + X509_STORE_CTX_get_check_issued(const X509_STORE_CTX *ctx) { return ctx->check_issued; } -X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_revocation_fn + X509_STORE_CTX_get_check_revocation(const X509_STORE_CTX *ctx) { return ctx->check_revocation; } -X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx) +X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(const X509_STORE_CTX *ctx) { return ctx->get_crl; } -X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(const X509_STORE_CTX *ctx) { return ctx->check_crl; } -X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx) +X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(const X509_STORE_CTX *ctx) { return ctx->cert_crl; } -X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_policy_fn + X509_STORE_CTX_get_check_policy(const X509_STORE_CTX *ctx) { return ctx->check_policy; } -X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx) +X509_STORE_CTX_lookup_certs_fn + X509_STORE_CTX_get_lookup_certs(const X509_STORE_CTX *ctx) { return ctx->lookup_certs; } -X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx) +X509_STORE_CTX_lookup_crls_fn + X509_STORE_CTX_get_lookup_crls(const X509_STORE_CTX *ctx) { return ctx->lookup_crls; } -X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx) +X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(const X509_STORE_CTX *ctx) { return ctx->cleanup; } -X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(const X509_STORE_CTX *ctx) { return ctx->tree; } -int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_explicit_policy(const X509_STORE_CTX *ctx) { return ctx->explicit_policy; } -int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx) { return ctx->num_untrusted; } @@ -2506,13 +2570,14 @@ int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) { const X509_VERIFY_PARAM *param; + param = X509_VERIFY_PARAM_lookup(name); - if (!param) + if (param == NULL) return 0; return X509_VERIFY_PARAM_inherit(ctx->param, param); } -X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx) { return ctx->param; } @@ -2744,7 +2809,7 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx) if (t->usage != DANETLS_USAGE_DANE_TA || t->selector != DANETLS_SELECTOR_SPKI || t->mtype != DANETLS_MATCHING_FULL || - X509_verify(cert, t->spki) <= 0) + X509_verify_ex(cert, t->spki, ctx->libctx, ctx->propq) <= 0) continue; /* Clear any PKIX-?? matches that failed to extend to a full chain */ @@ -2868,7 +2933,7 @@ static int build_chain(X509_STORE_CTX *ctx) SSL_DANE *dane = ctx->dane; int num = sk_X509_num(ctx->chain); X509 *cert = sk_X509_value(ctx->chain, num - 1); - int ss = cert_self_signed(cert); + int ss; STACK_OF(X509) *sktmp = NULL; unsigned int search; int may_trusted = 0; @@ -2880,7 +2945,18 @@ static int build_chain(X509_STORE_CTX *ctx) int i; /* Our chain starts with a single untrusted element. */ - OPENSSL_assert(num == 1 && ctx->num_untrusted == num); + if (!ossl_assert(num == 1 && ctx->num_untrusted == num)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + + ss = cert_self_signed(ctx, cert); + if (ss < 0) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } #define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */ #define S_DOTRUSTED (1 << 1) /* Search trusted store */ @@ -3017,7 +3093,14 @@ static int build_chain(X509_STORE_CTX *ctx) * certificate among the ones from the trust store. */ if ((search & S_DOALTERNATE) != 0) { - OPENSSL_assert(num > i && i > 0 && ss == 0); + if (!ossl_assert(num > i && i > 0 && ss == 0)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + X509_free(xtmp); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } search &= ~S_DOALTERNATE; for (; num > i; --num) X509_free(sk_X509_pop(ctx->chain)); @@ -3047,7 +3130,12 @@ static int build_chain(X509_STORE_CTX *ctx) search = 0; continue; } - ss = cert_self_signed(x); + ss = cert_self_signed(ctx, x); + if (ss < 0) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } } else if (num == ctx->num_untrusted) { /* * We have a self-signed certificate that has the same @@ -3080,7 +3168,13 @@ static int build_chain(X509_STORE_CTX *ctx) * certificate with ctx->num_untrusted <= num. */ if (ok) { - OPENSSL_assert(ctx->num_untrusted <= num); + if (!ossl_assert(ctx->num_untrusted <= num)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } search &= ~S_DOUNTRUSTED; switch (trust = check_trust(ctx, num)) { case X509_TRUST_TRUSTED: @@ -3119,7 +3213,13 @@ static int build_chain(X509_STORE_CTX *ctx) */ if ((search & S_DOUNTRUSTED) != 0) { num = sk_X509_num(ctx->chain); - OPENSSL_assert(num == ctx->num_untrusted); + if (!ossl_assert(num == ctx->num_untrusted)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } x = sk_X509_value(ctx->chain, num-1); /* @@ -3147,7 +3247,12 @@ static int build_chain(X509_STORE_CTX *ctx) X509_up_ref(x = xtmp); ++ctx->num_untrusted; - ss = cert_self_signed(xtmp); + ss = cert_self_signed(ctx, xtmp); + if (ss < 0) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } /* * Check for DANE-TA trust of the topmost untrusted certificate. @@ -3217,12 +3322,19 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) EVP_PKEY *pkey = X509_get0_pubkey(cert); int level = ctx->param->auth_level; + /* + * At security level zero, return without checking for a supported public + * key type. Some engines support key types not understood outside the + * engine, and we only need to understand the key when enforcing a security + * floor. + */ + if (level <= 0) + return 1; + /* Unsupported or malformed keys are not secure */ if (pkey == NULL) return 0; - if (level <= 0) - return 1; if (level > NUM_AUTH_LEVELS) level = NUM_AUTH_LEVELS; @@ -3238,8 +3350,6 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) */ static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert) { - int nid = X509_get_signature_nid(cert); - int mdnid = NID_undef; int secbits = -1; int level = ctx->param->auth_level; @@ -3248,14 +3358,8 @@ static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert) if (level > NUM_AUTH_LEVELS) level = NUM_AUTH_LEVELS; - /* Lookup signature algorithm digest */ - if (nid && OBJ_find_sigid_algs(nid, &mdnid, NULL)) { - const EVP_MD *md; - - /* Assume 4 bits of collision resistance for each hash octet */ - if (mdnid != NID_undef && (md = EVP_get_digestbynid(mdnid)) != NULL) - secbits = EVP_MD_size(md) * 4; - } + if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL)) + return 0; return secbits >= minbits_table[level - 1]; }