/*
- * Copyright 1995-2018 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
#include <errno.h>
#include <limits.h>
-#include "internal/ctype.h"
+#include "crypto/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include "internal/dane.h"
-#include "internal/x509_int.h"
-#include "x509_lcl.h"
+#include "crypto/x509.h"
+#include "x509_local.h"
/* CRL score values */
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
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);
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;
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 */
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;
/* 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;
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);
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,
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;
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 ASN.1 allows much more slack in the time format than RFC5280.
* In RFC5280, the representation is fixed:
* Digit and date ranges will be verified in the conversion methods.
*/
for (i = 0; i < ctm->length - 1; i++) {
- if (!ossl_isdigit(ctm->data[i]))
+ if (!ascii_isdigit(ctm->data[i]))
return 0;
}
- if (ctm->data[ctm->length - 1] != 'Z')
+ if (ctm->data[ctm->length - 1] != upper_z)
return 0;
/*
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;
+ return 0;
+}
+
ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
{
return X509_time_adj(s, adj, NULL);
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;
}
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;
}
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;
}
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;
}
{
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) {
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);
}
{
int ret = 1;
- ctx->ctx = store;
+ ctx->store = store;
ctx->cert = x509;
ctx->untrusted = chain;
ctx->crls = NULL;
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;
}
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;
}
ctx->verify = verify;
}
-X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx)
+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;
}
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;
}
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 */
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;
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 */
#define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */
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
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.
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;