Require intermediate CAs to have basicConstraints CA:true.
[openssl.git] / crypto / x509 / x509_vfy.c
index 73339f3fd45fc1d8de4eb82c7c352fd93eff829c..ffa211badb9804318751b2b262e8d91a4aea9599 100644 (file)
@@ -1,4 +1,3 @@
-/* crypto/x509/x509_vfy.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -193,7 +192,6 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
 
 static int verify_chain(X509_STORE_CTX *ctx)
 {
-    int (*cb) (int xok, X509_STORE_CTX *xctx) = ctx->verify_cb;
     int err;
     int ok;
 
@@ -214,7 +212,7 @@ static int verify_chain(X509_STORE_CTX *ctx)
     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;
     }
 
@@ -320,16 +318,7 @@ static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
         }
     }
 
-    if (ret == X509_V_OK)
-        return 1;
-    /* If we haven't asked for issuer errors don't set ctx */
-    if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
-        return 0;
-
-    ctx->error = ret;
-    ctx->current_cert = x;
-    ctx->current_issuer = issuer;
-    return ctx->verify_cb(0, ctx);
+    return (ret == X509_V_OK);
 }
 
 /* Alternative lookup method: look from a STACK stored in other_ctx */
@@ -344,6 +333,80 @@ 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)
+{
+    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 EE or CA certificate purpose.  For trusted certificates explicit local
+ * auxiliary trust can be used to override EKU-restrictions.
+ */
+static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
+                         int must_be_ca)
+{
+    int tr_ok = X509_TRUST_UNTRUSTED;
+
+    /*
+     * For trusted certificates we want to see whether any auxiliary trust
+     * settings trump the purpose constraints.
+     *
+     * This is complicated by the fact that the trust ordinals in
+     * ctx->param->trust are entirely independent of the purpose ordinals in
+     * ctx->param->purpose!
+     *
+     * What connects them is their mutual initialization via calls from
+     * X509_STORE_CTX_set_default() into X509_VERIFY_PARAM_lookup() which sets
+     * related values of both param->trust and param->purpose.  It is however
+     * typically possible to infer associated trust values from a purpose value
+     * via the X509_PURPOSE API.
+     *
+     * Therefore, we can only check for trust overrides when the purpose we're
+     * checking is the same as ctx->param->purpose and ctx->param->trust is
+     * also set.
+     */
+    if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose)
+        tr_ok = X509_check_trust(x, ctx->param->trust, X509_TRUST_NO_SS_COMPAT);
+
+    switch (tr_ok) {
+    case X509_TRUST_TRUSTED:
+        return 1;
+    case X509_TRUST_REJECTED:
+        break;
+    default:
+        switch (X509_check_purpose(x, purpose, must_be_ca > 0)) {
+        case 1:
+            return 1;
+        case 0:
+            break;
+        default:
+            if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0)
+                return 1;
+        }
+        break;
+    }
+
+    ctx->error = X509_V_ERR_INVALID_PURPOSE;
+    ctx->error_depth = depth;
+    ctx->current_cert = x;
+    return ctx->verify_cb(0, ctx);
+}
+
 /*
  * Check a certificate chains extensions for consistency with the supplied
  * purpose
@@ -351,13 +414,12 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
 
 static int check_chain_extensions(X509_STORE_CTX *ctx)
 {
-    int i, ok = 0, must_be_ca, plen = 0;
+    int i, 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;
+    int num = sk_X509_num(ctx->chain);
 
     /*-
      *  must_be_ca can have 1 of 3 values:
@@ -386,8 +448,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
         purpose = ctx->param->purpose;
     }
 
-    /* Check all untrusted certificates */
-    for (i = 0; i == 0 || i < ctx->num_untrusted; i++) {
+    for (i = 0; i < num; i++) {
         int ret;
         x = sk_X509_value(ctx->chain, i);
         if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
@@ -395,17 +456,15 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
             ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
             ctx->error_depth = i;
             ctx->current_cert = x;
-            ok = cb(0, ctx);
-            if (!ok)
-                goto end;
+            if (!ctx->verify_cb(0, ctx))
+                return 0;
         }
         if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) {
             ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
             ctx->error_depth = i;
             ctx->current_cert = x;
-            ok = cb(0, ctx);
-            if (!ok)
-                goto end;
+            if (!ctx->verify_cb(0, ctx))
+                return 0;
         }
         ret = X509_check_ca(x);
         switch (must_be_ca) {
@@ -425,8 +484,9 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
                 ret = 1;
             break;
         default:
+            /* X509_V_FLAG_X509_STRICT is implicit for intermediate CAs */
             if ((ret == 0)
-                || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+                || ((i + 1 < num || ctx->param->flags & X509_V_FLAG_X509_STRICT)
                     && (ret != 1))) {
                 ret = 0;
                 ctx->error = X509_V_ERR_INVALID_CA;
@@ -437,22 +497,12 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
         if (ret == 0) {
             ctx->error_depth = i;
             ctx->current_cert = x;
-            ok = cb(0, ctx);
-            if (!ok)
-                goto end;
+            if (!ctx->verify_cb(0, ctx))
+                return 0;
         }
-        if (ctx->param->purpose > 0) {
-            ret = X509_check_purpose(x, purpose, must_be_ca > 0);
-            if ((ret == 0)
-                || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
-                    && (ret != 1))) {
-                ctx->error = X509_V_ERR_INVALID_PURPOSE;
-                ctx->error_depth = i;
-                ctx->current_cert = x;
-                ok = cb(0, ctx);
-                if (!ok)
-                    goto end;
-            }
+        if (purpose > 0) {
+            if (!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)
@@ -461,9 +511,8 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
             ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
             ctx->error_depth = i;
             ctx->current_cert = x;
-            ok = cb(0, ctx);
-            if (!ok)
-                goto end;
+            if (!ctx->verify_cb(0, ctx))
+                return 0;
         }
         /* Increment path length if not self issued */
         if (!(x->ex_flags & EXFLAG_SI))
@@ -478,18 +527,15 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
                 ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
                 ctx->error_depth = i;
                 ctx->current_cert = x;
-                ok = cb(0, ctx);
-                if (!ok)
-                    goto end;
+                if (!ctx->verify_cb(0, ctx))
+                    return 0;
             }
             proxy_path_length++;
             must_be_ca = 0;
         } else
             must_be_ca = 1;
     }
-    ok = 1;
- end:
-    return ok;
+    return 1;
 }
 
 static int check_name_constraints(X509_STORE_CTX *ctx)
@@ -575,12 +621,15 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
     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:
@@ -614,12 +663,13 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
         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;
@@ -651,7 +701,7 @@ static int check_trust(X509_STORE_CTX *ctx, int num_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;
@@ -1443,16 +1493,35 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
 static int check_policy(X509_STORE_CTX *ctx)
 {
     int ret;
+
     if (ctx->parent)
         return 1;
+    /*
+     * With DANE, the trust anchor might be a bare public key, not a
+     * certificate!  In that case our chain does not have the trust anchor
+     * certificate as a top-most element.  This comports well with RFC5280
+     * chain verification, since there too, the trust anchor is not part of the
+     * chain to be verified.  In particular, X509_policy_check() does not look
+     * at the TA cert, but assumes that it is present as the top-most chain
+     * element.  We therefore temporarily push a NULL cert onto the chain if it
+     * was verified via a bare public key, and pop it off right after the
+     * X509_policy_check() call.
+     */
+    if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL)) {
+        X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
     ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
                             ctx->param->policies, ctx->param->flags);
-    if (ret == 0) {
+    if (ctx->bare_ta_signed)
+        sk_X509_pop(ctx->chain);
+
+    if (ret == X509_PCY_TREE_INTERNAL) {
         X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     /* Invalid or inconsistent extensions */
-    if (ret == -1) {
+    if (ret == X509_PCY_TREE_INVALID) {
         /*
          * Locate certificates with bad extensions and notify callback.
          */
@@ -1469,11 +1538,15 @@ static int check_policy(X509_STORE_CTX *ctx)
         }
         return 1;
     }
-    if (ret == -2) {
+    if (ret == X509_PCY_TREE_FAILURE) {
         ctx->current_cert = NULL;
         ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
         return ctx->verify_cb(0, ctx);
     }
+    if (ret != X509_PCY_TREE_VALID) {
+        X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
 
     if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
         ctx->current_cert = NULL;
@@ -1543,9 +1616,6 @@ static int internal_verify(X509_STORE_CTX *ctx)
     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;
@@ -1572,7 +1642,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
         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--;
@@ -1593,26 +1663,22 @@ static int internal_verify(X509_STORE_CTX *ctx)
          * 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)
@@ -1621,7 +1687,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
         /* 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;
 
@@ -2003,11 +2069,20 @@ void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
 
 int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
 {
+    /*
+     * XXX: Why isn't this function always used to set the associated trust?
+     * Should there even be a VPM->trust field at all?  Or should the trust
+     * always be inferred from the purpose by X509_STORE_CTX_init().
+     */
     return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
 }
 
 int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
 {
+    /*
+     * XXX: See above, this function would only be needed when the default
+     * trust for the purpose needs an override in a corner case.
+     */
     return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
 }
 
@@ -2041,6 +2116,11 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
         ptmp = X509_PURPOSE_get0(idx);
         if (ptmp->trust == X509_TRUST_DEFAULT) {
             idx = X509_PURPOSE_get_by_id(def_purpose);
+            /*
+             * XXX: In the two callers above def_purpose is always 0, which is
+             * not a known value, so idx will always be -1.  How is the
+             * X509_TRUST_DEFAULT case actually supposed to be handled?
+             */
             if (idx == -1) {
                 X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
                         X509_R_UNKNOWN_PURPOSE_ID);
@@ -2081,8 +2161,9 @@ X509_STORE_CTX *X509_STORE_CTX_new(void)
 
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
 {
-    if (!ctx)
+    if (ctx == NULL)
         return;
+
     X509_STORE_CTX_cleanup(ctx);
     OPENSSL_free(ctx);
 }
@@ -2150,6 +2231,8 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
 
     if (store && store->get_crl)
         ctx->get_crl = store->get_crl;
+    else
+        ctx->get_crl = NULL;
 
     if (store && store->check_crl)
         ctx->check_crl = store->check_crl;
@@ -2196,6 +2279,18 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
         goto err;
     }
 
+    /*
+     * XXX: For now, continue to inherit trust from VPM, but infer from the
+     * purpose if this still yields the default value.
+     */
+    if (ctx->param->trust == X509_TRUST_DEFAULT) {
+        int idx = X509_PURPOSE_get_by_id(ctx->param->purpose);
+        X509_PURPOSE *xp = X509_PURPOSE_get0(idx);
+
+        if (xp != NULL)
+            ctx->param->trust = X509_PURPOSE_get_trust(xp);
+    }
+
     if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
                            &ctx->ex_data))
         return 1;
@@ -2219,6 +2314,7 @@ void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 {
     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)
@@ -2371,7 +2467,7 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
 
     /*
      * If we've previously matched a PKIX-?? record, no need to test any
-     * furher PKIX-?? records,  it remains to just build the PKIX chain.
+     * further PKIX-?? records,  it remains to just build the PKIX chain.
      * Had the match been a DANE-?? record, we'd be done already.
      */
     if (dane->mdpth >= 0)
@@ -2402,7 +2498,7 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
      *
      * As soon as we find a match at any given depth, we stop, because either
      * we've matched a DANE-?? record and the peer is authenticated, or, after
-     * exhausing all DANE-?? records, we've matched a PKIX-?? record, which is
+     * exhausting all DANE-?? records, we've matched a PKIX-?? record, which is
      * sufficient for DANE, and what remains to do is ordinary PKIX validation.
      */
     recnum = (dane->umask & mask) ? sk_danetls_record_num(dane->trecs) : 0;
@@ -2496,7 +2592,7 @@ static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
         return  X509_TRUST_UNTRUSTED;
 
     /*
-     * Record any DANE trust anchor matches, for the first depth to test, if
+     * Record any DANE trust-anchor matches, for the first depth to test, if
      * there's one at that depth. (This'll be false for length 1 chains looking
      * for an exact match for the leaf certificate).
      */
@@ -2528,7 +2624,7 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx)
             X509_verify(cert, t->spki) <= 0)
             continue;
 
-        /* Clear PKIX-?? matches that failed to panned out to a full chain */
+        /* Clear any PKIX-?? matches that failed to extend to a full chain */
         X509_free(dane->mcert);
         dane->mcert = NULL;
 
@@ -2560,16 +2656,39 @@ static void dane_reset(struct dane_st *dane)
     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;
 
     dane_reset(dane);
 
+    /*-
+     * When testing the leaf certificate, if we match a DANE-EE(3) record,
+     * dane_match() returns 1 and we're done.  If however we match a PKIX-EE(1)
+     * record, the match depth and matching TLSA record are recorded, but the
+     * return value is 0, because we still need to find a PKIX trust-anchor.
+     * Therefore, when DANE authentication is enabled (required), we're done
+     * if:
+     *   + matched < 0, internal error.
+     *   + matched == 1, we matched a DANE-EE(3) record
+     *   + matched == 0, mdepth < 0 (no PKIX-EE match) and there are no
+     *     DANE-TA(2) or PKIX-TA(0) to test.
+     */
     matched = dane_match(ctx, ctx->cert, 0);
     done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0);
 
@@ -2577,9 +2696,11 @@ static int dane_verify(X509_STORE_CTX *ctx)
         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) {
@@ -2591,10 +2712,12 @@ static int dane_verify(X509_STORE_CTX *ctx)
 
     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);
+        ctx->error = X509_V_ERR_DANE_NO_MATCH;
+        return ctx->verify_cb(0, ctx);
     }
 
     /*
@@ -2607,7 +2730,6 @@ static int dane_verify(X509_STORE_CTX *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);
@@ -2887,12 +3009,12 @@ static int build_chain(X509_STORE_CTX *ctx)
      * 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) {
@@ -2909,7 +3031,7 @@ static int build_chain(X509_STORE_CTX *ctx)
             ctx->error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
         else if (DANETLS_ENABLED(dane) &&
                  (!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0))
-            ctx->error = X509_V_ERR_CERT_UNTRUSTED;
+            ctx->error = X509_V_ERR_DANE_NO_MATCH;
         else if (ss && sk_X509_num(ctx->chain) == 1)
             ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
         else if (ss)
@@ -2918,8 +3040,6 @@ static int build_chain(X509_STORE_CTX *ctx)
             ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
         else
             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);
     }
 }