/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
#include "crypto/x509.h"
#include "x509_local.h"
+DEFINE_STACK_OF(X509)
+DEFINE_STACK_OF(X509_REVOKED)
+DEFINE_STACK_OF(GENERAL_NAME)
+DEFINE_STACK_OF(X509_CRL)
+DEFINE_STACK_OF(DIST_POINT)
+DEFINE_STACK_OF_STRING()
+
/* CRL score values */
/* No unhandled critical extensions */
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
xtmp = sk_X509_value(certs, i);
if (!X509_cmp(xtmp, x))
break;
+ xtmp = NULL;
}
- if (i < sk_X509_num(certs))
- X509_up_ref(xtmp);
- else
+ if (xtmp != NULL && !X509_up_ref(xtmp))
xtmp = NULL;
sk_X509_pop_free(certs, X509_free);
return xtmp;
return -1;
}
+ if (!X509_up_ref(ctx->cert)) {
+ X509err(X509_F_X509_VERIFY_CERT, ERR_R_INTERNAL_ERROR);
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return -1;
+ }
+
/*
* first we make sure the chain we are going to build is present and that
* the first entry is in place
*/
- if (((ctx->chain = sk_X509_new_null()) == NULL) ||
- (!sk_X509_push(ctx->chain, ctx->cert))) {
+ if ((ctx->chain = sk_X509_new_null()) == NULL
+ || !sk_X509_push(ctx->chain, ctx->cert)) {
+ X509_free(ctx->cert);
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
- X509_up_ref(ctx->cert);
+
ctx->num_untrusted = 1;
/* If the peer's public key is too weak, we can stop early. */
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
{
int ret;
- if (x == issuer)
- return cert_self_signed(x);
- ret = X509_check_issued(issuer, x);
+ int ss;
+
+ if (x == issuer) {
+ ss = cert_self_signed(ctx, x);
+ if (ss < 0)
+ return 0;
+ return ss;
+ }
+
+ ret = x509_check_issued_int(issuer, x, ctx->libctx, ctx->propq);
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);
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
*issuer = find_issuer(ctx, ctx->other_ctx, x);
- if (*issuer) {
- X509_up_ref(*issuer);
- return 1;
- } else
- return 0;
+
+ if (*issuer == NULL || !X509_up_ref(*issuer))
+ goto err;
+
+ return 1;
+
+ err:
+ *issuer = NULL;
+ 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;
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) {
+ if (!X509_up_ref(x)) {
+ X509err(X509_F_LOOKUP_CERTS_SK, ERR_R_INTERNAL_ERROR);
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return NULL;
+ }
if (sk == NULL)
sk = sk_X509_new_null();
- if (sk == NULL || sk_X509_push(sk, x) == 0) {
+ if (sk == NULL || !sk_X509_push(sk, x)) {
+ X509_free(x);
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);
}
}
return sk;
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;
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;
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;
}
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);
}
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;
}
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
/* Drop this issuer from future consideration */
(void) sk_X509_delete_ptr(sktmp, xtmp);
+ if (!X509_up_ref(xtmp)) {
+ X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
+ trust = X509_TRUST_REJECTED;
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ search = 0;
+ continue;
+ }
+
if (!sk_X509_push(ctx->chain, xtmp)) {
+ X509_free(xtmp);
X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_OUT_OF_MEM;
continue;
}
- X509_up_ref(x = xtmp);
+ 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;
+ sk_X509_free(sktmp);
+ return 0;
+ }
/*
* Check for DANE-TA trust of the topmost untrusted certificate.