static int verify_chain(X509_STORE_CTX *ctx)
{
- int (*cb) (int xok, X509_STORE_CTX *xctx) = ctx->verify_cb;
int err;
int ok;
if (err != X509_V_OK) {
ctx->error = err;
ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
- if ((ok = cb(0, ctx)) == 0)
+ if ((ok = ctx->verify_cb(0, ctx)) == 0)
return ok;
}
return 0;
}
+static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, 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) {
+ if (sk == NULL)
+ sk = sk_X509_new_null();
+ if (sk == NULL || sk_X509_push(sk, x) == 0) {
+ sk_X509_pop_free(sk, X509_free);
+ return NULL;
+ }
+ X509_up_ref(x);
+ }
+ }
+ return sk;
+}
+
/*
* Check a certificate chains extensions for consistency with the supplied
* purpose
{
int i, ok = 0, must_be_ca, plen = 0;
X509 *x;
- int (*cb) (int xok, X509_STORE_CTX *xctx);
int proxy_path_length = 0;
int purpose;
int allow_proxy_certs;
- cb = ctx->verify_cb;
/*-
* must_be_ca can have 1 of 3 values:
ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
ctx->error_depth = i;
ctx->current_cert = x;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
}
ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
ctx->error_depth = i;
ctx->current_cert = x;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
}
if (ret == 0) {
ctx->error_depth = i;
ctx->current_cert = x;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
}
ctx->error = X509_V_ERR_INVALID_PURPOSE;
ctx->error_depth = i;
ctx->current_cert = x;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
}
ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
ctx->error_depth = i;
ctx->current_cert = x;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
}
ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
ctx->error_depth = i;
ctx->current_cert = x;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
}
int i, ok = 0;
X509 *x = NULL;
X509 *mx;
- int (*cb) (int xok, X509_STORE_CTX *xctx) = ctx->verify_cb;
struct dane_st *dane = (struct dane_st *)ctx->dane;
int num = sk_X509_num(ctx->chain);
int trust;
- if (DANETLS_HAS_TA(dane) && num_untrusted > 0) {
+ /*
+ * Check for a DANE issuer at depth 1 or greater, if it is a DANE-TA(2)
+ * match, we're done, otherwise we'll merely record the match depth.
+ */
+ if (DANETLS_HAS_TA(dane) && num_untrusted > 0 && num_untrusted < num) {
switch (trust = check_dane_issuer(ctx, num_untrusted)) {
case X509_TRUST_TRUSTED:
case X509_TRUST_REJECTED:
return X509_TRUST_UNTRUSTED;
}
- if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
+ if (num_untrusted == num && ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
/*
* Last-resort call with no new trusted certificates, check the leaf
* for a direct trust store match.
*/
- x = sk_X509_value(ctx->chain, 0);
+ i = 0;
+ x = sk_X509_value(ctx->chain, i);
mx = lookup_cert_match(ctx, x);
if (!mx)
return X509_TRUST_UNTRUSTED;
ctx->error_depth = i;
ctx->current_cert = x;
ctx->error = X509_V_ERR_CERT_REJECTED;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
return X509_TRUST_REJECTED;
return X509_TRUST_UNTRUSTED;
int ok = 0, n;
X509 *xs, *xi;
EVP_PKEY *pkey = NULL;
- int (*cb) (int xok, X509_STORE_CTX *xctx);
-
- cb = ctx->verify_cb;
n = sk_X509_num(ctx->chain) - 1;
ctx->error_depth = n;
if (n <= 0) {
ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
ctx->current_cert = xi;
- ok = cb(0, ctx);
+ ok = ctx->verify_cb(0, ctx);
goto end;
} else {
n--;
* explicitly asked for. It doesn't add any security and just wastes
* time.
*/
- if (!xs->valid
- && (xs != xi
- || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE))) {
+ if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) {
if ((pkey = X509_get0_pubkey(xi)) == NULL) {
ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
ctx->current_cert = xi;
- ok = (*cb) (0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
} else if (X509_verify(xs, pkey) <= 0) {
ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE;
ctx->current_cert = xs;
- ok = (*cb) (0, ctx);
+ ok = ctx->verify_cb(0, ctx);
if (!ok)
goto end;
}
}
- xs->valid = 1;
-
check_cert:
ok = x509_check_cert_time(ctx, xs, 0);
if (!ok)
/* The last error (if any) is still in the error value */
ctx->current_issuer = xi;
ctx->current_cert = xs;
- ok = (*cb) (1, ctx);
+ ok = ctx->verify_cb(1, ctx);
if (!ok)
goto end;
{
ctx->other_ctx = sk;
ctx->get_issuer = get_issuer_sk;
+ ctx->lookup_certs = lookup_certs_sk;
}
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
dane->pdpth = -1;
}
+static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert)
+{
+ int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags);
+
+ if (err == X509_V_OK)
+ return 1;
+ ctx->current_cert = cert;
+ ctx->error_depth = 0;
+ ctx->error = err;
+ return ctx->verify_cb(0, ctx);
+}
+
static int dane_verify(X509_STORE_CTX *ctx)
{
X509 *cert = ctx->cert;
- int (*cb)(int xok, X509_STORE_CTX *xctx) = ctx->verify_cb;
struct dane_st *dane = (struct dane_st *)ctx->dane;
int matched;
int done;
X509_get_pubkey_parameters(NULL, ctx->chain);
if (matched > 0) {
+ if (!check_leaf_suiteb(ctx, cert))
+ return 0;
ctx->error_depth = 0;
ctx->current_cert = cert;
- return cb(1, ctx);
+ return ctx->verify_cb(1, ctx);
}
if (matched < 0) {
if (done) {
/* Fail early, TA-based success is not possible */
+ if (!check_leaf_suiteb(ctx, cert))
+ return 0;
ctx->current_cert = cert;
ctx->error_depth = 0;
ctx->error = X509_V_ERR_CERT_UNTRUSTED;
- return cb(0, ctx);
+ return ctx->verify_cb(0, ctx);
}
/*
static int build_chain(X509_STORE_CTX *ctx)
{
struct dane_st *dane = (struct dane_st *)ctx->dane;
- int (*cb) (int, X509_STORE_CTX *) = ctx->verify_cb;
int num = sk_X509_num(ctx->chain);
X509 *cert = sk_X509_value(ctx->chain, num - 1);
int ss = cert_self_signed(cert);
* Last chance to make a trusted chain, either bare DANE-TA public-key
* signers, or else direct leaf PKIX trust.
*/
- if (sk_X509_num(ctx->chain) <= depth) {
+ num = sk_X509_num(ctx->chain);
+ if (num <= depth) {
if (trust == X509_TRUST_UNTRUSTED && DANETLS_HAS_DANE_TA(dane))
trust = check_dane_pkeys(ctx);
- if (trust == X509_TRUST_UNTRUSTED &&
- sk_X509_num(ctx->chain) == ctx->num_untrusted)
- trust = check_trust(ctx, 1);
+ if (trust == X509_TRUST_UNTRUSTED && num == ctx->num_untrusted)
+ trust = check_trust(ctx, num);
}
switch (trust) {
ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
if (DANETLS_ENABLED(dane))
dane_reset(dane);
- return cb(0, ctx);
+ return ctx->verify_cb(0, ctx);
}
}