Only support >= 256-bit elliptic curves with ecdh_auto (server) or by default (client).
[openssl.git] / ssl / t1_lib.c
index 31ebfdde45f58f90da76966acf83cce69f618b14..7053c4a714ca438979cb79e5c9b60c874626f13b 100644 (file)
@@ -268,37 +268,65 @@ static const unsigned char ecformats_default[] = {
     TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
 };
 
-static const unsigned char eccurves_default[] = {
-    0, 14,                      /* sect571r1 (14) */
-    0, 13,                      /* sect571k1 (13) */
+/* The client's default curves / the server's 'auto' curves. */
+static const unsigned char eccurves_auto[] = {
+    /* Prefer P-256 which has the fastest and most secure implementations. */
+    0, 23,                      /* secp256r1 (23) */
+    /* Other >= 256-bit prime curves. */
     0, 25,                      /* secp521r1 (25) */
     0, 28,                      /* brainpool512r1 (28) */
-    0, 11,                      /* sect409k1 (11) */
-    0, 12,                      /* sect409r1 (12) */
     0, 27,                      /* brainpoolP384r1 (27) */
     0, 24,                      /* secp384r1 (24) */
+    0, 26,                      /* brainpoolP256r1 (26) */
+    0, 22,                      /* secp256k1 (22) */
+    /* >= 256-bit binary curves. */
+    0, 14,                      /* sect571r1 (14) */
+    0, 13,                      /* sect571k1 (13) */
+    0, 11,                      /* sect409k1 (11) */
+    0, 12,                      /* sect409r1 (12) */
     0, 9,                       /* sect283k1 (9) */
     0, 10,                      /* sect283r1 (10) */
+};
+
+static const unsigned char eccurves_all[] = {
+    /* Prefer P-256 which has the fastest and most secure implementations. */
+    0, 23,                      /* secp256r1 (23) */
+    /* Other >= 256-bit prime curves. */
+    0, 25,                      /* secp521r1 (25) */
+    0, 28,                      /* brainpool512r1 (28) */
+    0, 27,                      /* brainpoolP384r1 (27) */
+    0, 24,                      /* secp384r1 (24) */
     0, 26,                      /* brainpoolP256r1 (26) */
     0, 22,                      /* secp256k1 (22) */
-    0, 23,                      /* secp256r1 (23) */
+    /* >= 256-bit binary curves. */
+    0, 14,                      /* sect571r1 (14) */
+    0, 13,                      /* sect571k1 (13) */
+    0, 11,                      /* sect409k1 (11) */
+    0, 12,                      /* sect409r1 (12) */
+    0, 9,                       /* sect283k1 (9) */
+    0, 10,                      /* sect283r1 (10) */
+    /*
+     * Remaining curves disabled by default but still permitted if set
+     * via an explicit callback or parameters.
+     */
+    0, 20,                      /* secp224k1 (20) */
+    0, 21,                      /* secp224r1 (21) */
+    0, 18,                      /* secp192k1 (18) */
+    0, 19,                      /* secp192r1 (19) */
+    0, 15,                      /* secp160k1 (15) */
+    0, 16,                      /* secp160r1 (16) */
+    0, 17,                      /* secp160r2 (17) */
     0, 8,                       /* sect239k1 (8) */
     0, 6,                       /* sect233k1 (6) */
     0, 7,                       /* sect233r1 (7) */
-    0, 20,                      /* secp224k1 (20) */
-    0, 21,                      /* secp224r1 (21) */
     0, 4,                       /* sect193r1 (4) */
     0, 5,                       /* sect193r2 (5) */
-    0, 18,                      /* secp192k1 (18) */
-    0, 19,                      /* secp192r1 (19) */
     0, 1,                       /* sect163k1 (1) */
     0, 2,                       /* sect163r1 (2) */
     0, 3,                       /* sect163r2 (3) */
-    0, 15,                      /* secp160k1 (15) */
-    0, 16,                      /* secp160r1 (16) */
-    0, 17,                      /* secp160r2 (17) */
 };
 
+
 static const unsigned char suiteb_curves[] = {
     0, TLSEXT_curve_P_256,
     0, TLSEXT_curve_P_384
@@ -307,8 +335,7 @@ static const unsigned char suiteb_curves[] = {
 int tls1_ec_curve_id2nid(int curve_id)
 {
     /* ECC curves from RFC 4492 and RFC 7027 */
-    if ((curve_id < 1) || ((unsigned int)curve_id >
-                           sizeof(nid_list) / sizeof(nid_list[0])))
+    if ((curve_id < 1) || ((unsigned int)curve_id > OSSL_NELEM(nid_list)))
         return 0;
     return nid_list[curve_id - 1].nid;
 }
@@ -420,8 +447,13 @@ static int tls1_get_curvelist(SSL *s, int sess,
             pcurveslen = s->tlsext_ellipticcurvelist_length;
         }
         if (!*pcurves) {
-            *pcurves = eccurves_default;
-            pcurveslen = sizeof(eccurves_default);
+            if (!s->server || (s->cert && s->cert->ecdh_tmp_auto)) {
+                *pcurves = eccurves_auto;
+                pcurveslen = sizeof(eccurves_auto);
+            } else {
+                *pcurves = eccurves_all;
+                pcurveslen = sizeof(eccurves_all);
+            }
         }
     }
 
@@ -442,8 +474,7 @@ static int tls_curve_allowed(SSL *s, const unsigned char *curve, int op)
     const tls_curve_info *cinfo;
     if (curve[0])
         return 1;
-    if ((curve[1] < 1) || ((size_t)curve[1] >
-                           sizeof(nid_list) / sizeof(nid_list[0])))
+    if ((curve[1] < 1) || ((size_t)curve[1] > OSSL_NELEM(nid_list)))
         return 0;
     cinfo = &nid_list[curve[1] - 1];
 # ifdef OPENSSL_NO_EC2M
@@ -797,9 +828,9 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
             return 0;
         if (set_ee_md == 2) {
             if (check_md == NID_ecdsa_with_SHA256)
-                c->pkeys[SSL_PKEY_ECC].digest = EVP_sha256();
+                s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha256();
             else
-                c->pkeys[SSL_PKEY_ECC].digest = EVP_sha384();
+                s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha384();
         }
     }
     return rv;
@@ -1038,8 +1069,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
     /*
      * Store the digest used so applications can retrieve it if they wish.
      */
-    if (s->session && s->session->sess_cert)
-        s->session->sess_cert->peer_key->digest = *pmd;
+    s->s3->tmp.peer_md = *pmd;
     return 1;
 }
 
@@ -1051,52 +1081,44 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
  */
 void ssl_set_client_disabled(SSL *s)
 {
-    CERT *c = s->cert;
-    c->mask_a = 0;
-    c->mask_k = 0;
+    s->s3->tmp.mask_a = 0;
+    s->s3->tmp.mask_k = 0;
     /* Don't allow TLS 1.2 only ciphers if we don't suppport them */
     if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s))
-        c->mask_ssl = SSL_TLSV1_2;
+        s->s3->tmp.mask_ssl = SSL_TLSV1_2;
     else
-        c->mask_ssl = 0;
-    ssl_set_sig_mask(&c->mask_a, s, SSL_SECOP_SIGALG_MASK);
+        s->s3->tmp.mask_ssl = 0;
+    ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
     /*
      * Disable static DH if we don't include any appropriate signature
      * algorithms.
      */
-    if (c->mask_a & SSL_aRSA)
-        c->mask_k |= SSL_kDHr | SSL_kECDHr;
-    if (c->mask_a & SSL_aDSS)
-        c->mask_k |= SSL_kDHd;
-    if (c->mask_a & SSL_aECDSA)
-        c->mask_k |= SSL_kECDHe;
-# ifndef OPENSSL_NO_KRB5
-    if (!kssl_tgt_is_available(s->kssl_ctx)) {
-        c->mask_a |= SSL_aKRB5;
-        c->mask_k |= SSL_kKRB5;
-    }
-# endif
+    if (s->s3->tmp.mask_a & SSL_aRSA)
+        s->s3->tmp.mask_k |= SSL_kDHr | SSL_kECDHr;
+    if (s->s3->tmp.mask_a & SSL_aDSS)
+        s->s3->tmp.mask_k |= SSL_kDHd;
+    if (s->s3->tmp.mask_a & SSL_aECDSA)
+        s->s3->tmp.mask_k |= SSL_kECDHe;
 # ifndef OPENSSL_NO_PSK
     /* with PSK there must be client callback set */
     if (!s->psk_client_callback) {
-        c->mask_a |= SSL_aPSK;
-        c->mask_k |= SSL_kPSK;
+        s->s3->tmp.mask_a |= SSL_aPSK;
+        s->s3->tmp.mask_k |= SSL_kPSK;
     }
 # endif                         /* OPENSSL_NO_PSK */
 # ifndef OPENSSL_NO_SRP
     if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) {
-        c->mask_a |= SSL_aSRP;
-        c->mask_k |= SSL_kSRP;
+        s->s3->tmp.mask_a |= SSL_aSRP;
+        s->s3->tmp.mask_k |= SSL_kSRP;
     }
 # endif
-    c->valid = 1;
 }
 
 int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op)
 {
-    CERT *ct = s->cert;
-    if (c->algorithm_ssl & ct->mask_ssl || c->algorithm_mkey & ct->mask_k
-        || c->algorithm_auth & ct->mask_a)
+    if (c->algorithm_ssl & s->s3->tmp.mask_ssl
+        || c->algorithm_mkey & s->s3->tmp.mask_k
+        || c->algorithm_auth & s->s3->tmp.mask_a)
         return 1;
     return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
 }
@@ -1466,13 +1488,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
      */
     if (s->options & SSL_OP_TLSEXT_PADDING) {
         int hlen = ret - (unsigned char *)s->init_buf->data;
-        /*
-         * The code in s23_clnt.c to build ClientHello messages includes the
-         * 5-byte record header in the buffer, while the code in s3_clnt.c
-         * does not.
-         */
-        if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
-            hlen -= 5;
+
         if (hlen > 0xff && hlen < 0x200) {
             hlen = 0x200 - hlen;
             if (hlen >= 4)
@@ -1903,8 +1919,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
 # endif                         /* !OPENSSL_NO_EC */
 
     /* Clear any signature algorithms extension received */
-    OPENSSL_free(s->cert->peer_sigalgs);
-    s->cert->peer_sigalgs = NULL;
+    OPENSSL_free(s->s3->tmp.peer_sigalgs);
+    s->s3->tmp.peer_sigalgs = NULL;
 # ifdef TLSEXT_TYPE_encrypt_then_mac
     s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
 # endif
@@ -2121,7 +2137,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
             }
         } else if (type == TLSEXT_TYPE_signature_algorithms) {
             int dsize;
-            if (s->cert->peer_sigalgs || size < 2) {
+            if (s->s3->tmp.peer_sigalgs || size < 2) {
                 *al = SSL_AD_DECODE_ERROR;
                 return 0;
             }
@@ -2682,6 +2698,21 @@ static int ssl_check_clienthello_tlsext_early(SSL *s)
         return 1;
     }
 }
+/* Initialise digests to default values */
+static void ssl_set_default_md(SSL *s)
+{
+    const EVP_MD **pmd = s->s3->tmp.md;
+#ifndef OPENSSL_NO_DSA
+    pmd[SSL_PKEY_DSA_SIGN] = EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_RSA
+    pmd[SSL_PKEY_RSA_SIGN] = EVP_sha1();
+    pmd[SSL_PKEY_RSA_ENC] = EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_EC
+    pmd[SSL_PKEY_ECC] = EVP_sha1();
+#endif
+}
 
 int tls1_set_server_sigalgs(SSL *s)
 {
@@ -2693,12 +2724,12 @@ int tls1_set_server_sigalgs(SSL *s)
     s->cert->shared_sigalgslen = 0;
     /* Clear certificate digests and validity flags */
     for (i = 0; i < SSL_PKEY_NUM; i++) {
-        s->cert->pkeys[i].digest = NULL;
-        s->cert->pkeys[i].valid_flags = 0;
+        s->s3->tmp.md[i] = NULL;
+        s->s3->tmp.valid_flags[i] = 0;
     }
 
     /* If sigalgs received process it. */
-    if (s->cert->peer_sigalgs) {
+    if (s->s3->tmp.peer_sigalgs) {
         if (!tls1_process_sigalgs(s)) {
             SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE);
             al = SSL_AD_INTERNAL_ERROR;
@@ -2711,8 +2742,9 @@ int tls1_set_server_sigalgs(SSL *s)
             al = SSL_AD_ILLEGAL_PARAMETER;
             goto err;
         }
-    } else
-        ssl_cert_set_default_md(s->cert);
+    } else {
+        ssl_set_default_md(s);
+    }
     return 1;
  err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
@@ -2722,7 +2754,7 @@ int tls1_set_server_sigalgs(SSL *s)
 int ssl_check_clienthello_tlsext_late(SSL *s)
 {
     int ret = SSL_TLSEXT_ERR_OK;
-    int al;
+    int al = SSL_AD_INTERNAL_ERROR;
 
     /*
      * If status request then ask callback what to do. Note: this must be
@@ -3172,8 +3204,7 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
     int sig_id, md_id;
     if (!md)
         return 0;
-    md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
-                          sizeof(tls12_md) / sizeof(tls12_lookup));
+    md_id = tls12_find_id(EVP_MD_type(md), tls12_md, OSSL_NELEM(tls12_md));
     if (md_id == -1)
         return 0;
     sig_id = tls12_get_sigid(pk);
@@ -3186,8 +3217,7 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
 
 int tls12_get_sigid(const EVP_PKEY *pk)
 {
-    return tls12_find_id(pk->type, tls12_sig,
-                         sizeof(tls12_sig) / sizeof(tls12_lookup));
+    return tls12_find_id(pk->type, tls12_sig, OSSL_NELEM(tls12_sig));
 }
 
 typedef struct {
@@ -3213,7 +3243,7 @@ static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg)
 {
     if (hash_alg == 0)
         return NULL;
-    if (hash_alg > sizeof(tls12_md_info) / sizeof(tls12_md_info[0]))
+    if (hash_alg > OSSL_NELEM(tls12_md_info))
         return NULL;
     return tls12_md_info + hash_alg - 1;
 }
@@ -3256,14 +3286,12 @@ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
     if (!phash_nid && !psign_nid && !psignhash_nid)
         return;
     if (phash_nid || psignhash_nid) {
-        hash_nid = tls12_find_nid(data[0], tls12_md,
-                                  sizeof(tls12_md) / sizeof(tls12_lookup));
+        hash_nid = tls12_find_nid(data[0], tls12_md, OSSL_NELEM(tls12_md));
         if (phash_nid)
             *phash_nid = hash_nid;
     }
     if (psign_nid || psignhash_nid) {
-        sign_nid = tls12_find_nid(data[1], tls12_sig,
-                                  sizeof(tls12_sig) / sizeof(tls12_lookup));
+        sign_nid = tls12_find_nid(data[1], tls12_sig, OSSL_NELEM(tls12_sig));
         if (psign_nid)
             *psign_nid = sign_nid;
     }
@@ -3404,13 +3432,13 @@ static int tls1_set_shared_sigalgs(SSL *s)
     if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) {
         pref = conf;
         preflen = conflen;
-        allow = c->peer_sigalgs;
-        allowlen = c->peer_sigalgslen;
+        allow = s->s3->tmp.peer_sigalgs;
+        allowlen = s->s3->tmp.peer_sigalgslen;
     } else {
         allow = conf;
         allowlen = conflen;
-        pref = c->peer_sigalgs;
-        preflen = c->peer_sigalgslen;
+        pref = s->s3->tmp.peer_sigalgs;
+        preflen = s->s3->tmp.peer_sigalgslen;
     }
     nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
     if (nmatch) {
@@ -3438,12 +3466,12 @@ int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize)
     if (!c)
         return 0;
 
-    OPENSSL_free(c->peer_sigalgs);
-    c->peer_sigalgs = OPENSSL_malloc(dsize);
-    if (!c->peer_sigalgs)
+    OPENSSL_free(s->s3->tmp.peer_sigalgs);
+    s->s3->tmp.peer_sigalgs = OPENSSL_malloc(dsize);
+    if (s->s3->tmp.peer_sigalgs == NULL)
         return 0;
-    c->peer_sigalgslen = dsize;
-    memcpy(c->peer_sigalgs, data, dsize);
+    s->s3->tmp.peer_sigalgslen = dsize;
+    memcpy(s->s3->tmp.peer_sigalgs, data, dsize);
     return 1;
 }
 
@@ -3452,6 +3480,8 @@ int tls1_process_sigalgs(SSL *s)
     int idx;
     size_t i;
     const EVP_MD *md;
+    const EVP_MD **pmd = s->s3->tmp.md;
+    int *pvalid = s->s3->tmp.valid_flags;
     CERT *c = s->cert;
     TLS_SIGALGS *sigptr;
     if (!tls1_set_shared_sigalgs(s))
@@ -3471,12 +3501,11 @@ int tls1_process_sigalgs(SSL *s)
         if (sigs) {
             idx = tls12_get_pkey_idx(sigs[1]);
             md = tls12_get_hash(sigs[0]);
-            c->pkeys[idx].digest = md;
-            c->pkeys[idx].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+            pmd[idx] = md;
+            pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN;
             if (idx == SSL_PKEY_RSA_SIGN) {
-                c->pkeys[SSL_PKEY_RSA_ENC].valid_flags =
-                    CERT_PKEY_EXPLICIT_SIGN;
-                c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+                pvalid[SSL_PKEY_RSA_ENC] = CERT_PKEY_EXPLICIT_SIGN;
+                pmd[SSL_PKEY_RSA_ENC] = md;
             }
         }
     }
@@ -3485,14 +3514,13 @@ int tls1_process_sigalgs(SSL *s)
     for (i = 0, sigptr = c->shared_sigalgs;
          i < c->shared_sigalgslen; i++, sigptr++) {
         idx = tls12_get_pkey_idx(sigptr->rsign);
-        if (idx > 0 && c->pkeys[idx].digest == NULL) {
+        if (idx > 0 && pmd[idx] == NULL) {
             md = tls12_get_hash(sigptr->rhash);
-            c->pkeys[idx].digest = md;
-            c->pkeys[idx].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+            pmd[idx] = md;
+            pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN;
             if (idx == SSL_PKEY_RSA_SIGN) {
-                c->pkeys[SSL_PKEY_RSA_ENC].valid_flags =
-                    CERT_PKEY_EXPLICIT_SIGN;
-                c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+                pvalid[SSL_PKEY_RSA_ENC] = CERT_PKEY_EXPLICIT_SIGN;
+                pmd[SSL_PKEY_RSA_ENC] = md;
             }
         }
 
@@ -3507,18 +3535,18 @@ int tls1_process_sigalgs(SSL *s)
          * supported it stays as NULL.
          */
 # ifndef OPENSSL_NO_DSA
-        if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
-            c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
+        if (pmd[SSL_PKEY_DSA_SIGN] == NULL)
+            pmd[SSL_PKEY_DSA_SIGN] = EVP_sha1();
 # endif
 # ifndef OPENSSL_NO_RSA
-        if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest) {
-            c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
-            c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+        if (pmd[SSL_PKEY_RSA_SIGN] == NULL) {
+            pmd[SSL_PKEY_RSA_SIGN] = EVP_sha1();
+            pmd[SSL_PKEY_RSA_ENC] = EVP_sha1();
         }
 # endif
 # ifndef OPENSSL_NO_EC
-        if (!c->pkeys[SSL_PKEY_ECC].digest)
-            c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
+        if (pmd[SSL_PKEY_ECC] == NULL)
+            pmd[SSL_PKEY_ECC] = EVP_sha1();
 # endif
     }
     return 1;
@@ -3528,12 +3556,12 @@ int SSL_get_sigalgs(SSL *s, int idx,
                     int *psign, int *phash, int *psignhash,
                     unsigned char *rsig, unsigned char *rhash)
 {
-    const unsigned char *psig = s->cert->peer_sigalgs;
+    const unsigned char *psig = s->s3->tmp.peer_sigalgs;
     if (psig == NULL)
         return 0;
     if (idx >= 0) {
         idx <<= 1;
-        if (idx >= (int)s->cert->peer_sigalgslen)
+        if (idx >= (int)s->s3->tmp.peer_sigalgslen)
             return 0;
         psig += idx;
         if (rhash)
@@ -3542,7 +3570,7 @@ int SSL_get_sigalgs(SSL *s, int idx,
             *rsig = psig[1];
         tls1_lookup_sigalg(phash, psign, psignhash, psig);
     }
-    return s->cert->peer_sigalgslen / 2;
+    return s->s3->tmp.peer_sigalgslen / 2;
 }
 
 int SSL_get_shared_sigalgs(SSL *s, int idx,
@@ -3755,11 +3783,11 @@ static int sig_cb(const char *elem, int len, void *arg)
     if (!*p)
         return 0;
 
-    if (!strcmp(etmp, "RSA"))
+    if (strcmp(etmp, "RSA") == 0)
         sig_alg = EVP_PKEY_RSA;
-    else if (!strcmp(etmp, "DSA"))
+    else if (strcmp(etmp, "DSA") == 0)
         sig_alg = EVP_PKEY_DSA;
-    else if (!strcmp(etmp, "ECDSA"))
+    else if (strcmp(etmp, "ECDSA") == 0)
         sig_alg = EVP_PKEY_EC;
     else
         return 0;
@@ -3806,10 +3834,8 @@ int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen,
     if (sigalgs == NULL)
         return 0;
     for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
-        rhash = tls12_find_id(*psig_nids++, tls12_md,
-                              sizeof(tls12_md) / sizeof(tls12_lookup));
-        rsign = tls12_find_id(*psig_nids++, tls12_sig,
-                              sizeof(tls12_sig) / sizeof(tls12_lookup));
+        rhash = tls12_find_id(*psig_nids++, tls12_md, OSSL_NELEM(tls12_md));
+        rsign = tls12_find_id(*psig_nids++, tls12_sig, OSSL_NELEM(tls12_sig));
 
         if (rhash == -1 || rsign == -1)
             goto err;
@@ -3886,6 +3912,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
     int check_flags = 0, strict_mode;
     CERT_PKEY *cpk = NULL;
     CERT *c = s->cert;
+    int *pvalid;
     unsigned int suiteb_flags = tls1_suiteb(s);
     /* idx == -1 means checking server chains */
     if (idx != -1) {
@@ -3895,6 +3922,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
             idx = cpk - c->pkeys;
         } else
             cpk = c->pkeys + idx;
+        pvalid = s->s3->tmp.valid_flags + idx;
         x = cpk->x509;
         pk = cpk->privatekey;
         chain = cpk->chain;
@@ -3907,7 +3935,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
         if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) {
             rv = CERT_PKEY_STRICT_FLAGS | CERT_PKEY_EXPLICIT_SIGN |
                 CERT_PKEY_VALID | CERT_PKEY_SIGN;
-            cpk->valid_flags = rv;
+            *pvalid = rv;
             return rv;
         }
 # endif
@@ -3918,6 +3946,8 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
         if (idx == -1)
             return 0;
         cpk = c->pkeys + idx;
+        pvalid = s->s3->tmp.valid_flags + idx;
+
         if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
             check_flags = CERT_PKEY_STRICT_FLAGS;
         else
@@ -3943,7 +3973,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
     if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
         int default_nid;
         unsigned char rsign = 0;
-        if (c->peer_sigalgs)
+        if (s->s3->tmp.peer_sigalgs)
             default_nid = 0;
         /* If no sigalgs extension use defaults from RFC5246 */
         else {
@@ -4104,9 +4134,9 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
  end:
 
     if (TLS1_get_version(s) >= TLS1_2_VERSION) {
-        if (cpk->valid_flags & CERT_PKEY_EXPLICIT_SIGN)
+        if (*pvalid & CERT_PKEY_EXPLICIT_SIGN)
             rv |= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
-        else if (cpk->digest)
+        else if (s->s3->tmp.md[idx] != NULL)
             rv |= CERT_PKEY_SIGN;
     } else
         rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN;
@@ -4117,10 +4147,10 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
      */
     if (!check_flags) {
         if (rv & CERT_PKEY_VALID)
-            cpk->valid_flags = rv;
+            *pvalid = rv;
         else {
             /* Preserve explicit sign flag, clear rest */
-            cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN;
+            *pvalid &= CERT_PKEY_EXPLICIT_SIGN;
             return 0;
         }
     }