Convert SSLv3 code to use the new read side record layer
authorMatt Caswell <matt@openssl.org>
Thu, 28 Apr 2022 15:57:07 +0000 (16:57 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 18 Aug 2022 15:38:12 +0000 (16:38 +0100)
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18132)

ssl/record/methods/tlsrecord.c
ssl/s3_enc.c

index 691dd12ca57d0c38c10dd30c62f7f1a76cc952f9..1646ba5ba1811832f9d4062f666365eb2845fe0f 100644 (file)
@@ -101,6 +101,9 @@ struct ossl_record_layer_st
     /* uncompress */
     COMP_CTX *expand;
 
+    /* Only used by SSLv3 */
+    unsigned char mac_secret[EVP_MAX_MD_SIZE];
+
     /* Function pointers for version specific functions */
     /* Function pointers for version specific functions */
     struct record_functions_st *funcs;
@@ -206,6 +209,69 @@ static int tls_any_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
     return 1;
 }
 
+/* TODO(RECLAYER): Handle OPENSSL_NO_COMP */
+static int ssl3_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+                                 unsigned char *key, size_t keylen,
+                                 unsigned char *iv, size_t ivlen,
+                                 unsigned char *mackey, size_t mackeylen,
+                                 const EVP_CIPHER *ciph,
+                                 size_t taglen,
+                                 /* TODO(RECLAYER): This probably should not be an int */
+                                 int mactype,
+                                 const EVP_MD *md,
+                                 const SSL_COMP *comp,
+                                 /* TODO(RECLAYER): Remove me */
+                                 SSL_CONNECTION *s)
+{
+    EVP_CIPHER_CTX *ciph_ctx;
+
+    if (md == NULL) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    if ((rl->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    ciph_ctx = rl->enc_read_ctx;
+
+    rl->read_hash = EVP_MD_CTX_new();
+    if (rl->read_hash == NULL) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+#ifndef OPENSSL_NO_COMP
+    if (comp != NULL) {
+        rl->expand = COMP_CTX_new(comp->method);
+        if (rl->expand == NULL) {
+            RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR,
+                        SSL_R_COMPRESSION_LIBRARY_ERROR);
+            return 0;
+        }
+    }
+#endif
+
+    if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, iv)) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    if (EVP_CIPHER_get0_provider(ciph) != NULL
+            && !tls_provider_set_tls_parameters(rl, ciph_ctx, ciph, md, s)) {
+        /* RLAYERfatal already called */
+        return 0;
+    }
+
+    if (mackeylen > sizeof(rl->mac_secret)) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+    memcpy(rl->mac_secret, mackey, mackeylen);
+
+    return 1;
+}
+
 /* TODO(RECLAYER): Handle OPENSSL_NO_COMP */
 static int tls1_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
                                  unsigned char *key, size_t keylen,
@@ -337,7 +403,7 @@ static int tls1_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
     }
     if (EVP_CIPHER_get0_provider(ciph) != NULL
             && !tls_provider_set_tls_parameters(rl, ciph_ctx, ciph, md, s)) {
-        /* SSLfatal already called */
+        /* RLAYERfatal already called */
         return 0;
     }
 
@@ -358,6 +424,125 @@ static int tls_any_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_rec
     return 1;
 }
 
+/*-
+ * ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Calls SSLfatal on
+ * internal error, but not otherwise. It is the responsibility of the caller to
+ * report a bad_record_mac
+ *
+ * Returns:
+ *    0: if the record is publicly invalid, or an internal error
+ *    1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
+ */
+static int ssl3_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs,
+                       int sending, SSL_MAC_BUF *mac, size_t macsize,
+                       /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s)
+{
+    SSL3_RECORD *rec;
+    EVP_CIPHER_CTX *ds;
+    size_t l, i;
+    size_t bs;
+    const EVP_CIPHER *enc;
+    int provided;
+
+    rec = inrecs;
+    /*
+     * We shouldn't ever be called with more than one record in the SSLv3 case
+     */
+    if (n_recs != 1)
+        return 0;
+    if (sending) {
+        ds = s->enc_write_ctx;
+        if (s->enc_write_ctx == NULL)
+            enc = NULL;
+        else
+            enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx);
+    } else {
+        ds = rl->enc_read_ctx;
+        if (rl->enc_read_ctx == NULL)
+            enc = NULL;
+        else
+            enc = EVP_CIPHER_CTX_get0_cipher(rl->enc_read_ctx);
+    }
+
+    provided = (EVP_CIPHER_get0_provider(enc) != NULL);
+
+    l = rec->length;
+    bs = EVP_CIPHER_CTX_get_block_size(ds);
+
+    /* COMPRESS */
+
+    if ((bs != 1) && sending && !provided) {
+        /*
+            * We only do this for legacy ciphers. Provided ciphers add the
+            * padding on the provider side.
+            */
+        i = bs - (l % bs);
+
+        /* we need to add 'i-1' padding bytes */
+        l += i;
+        /*
+            * the last of these zero bytes will be overwritten with the
+            * padding length.
+            */
+        memset(&rec->input[rec->length], 0, i);
+        rec->length += i;
+        rec->input[l - 1] = (unsigned char)(i - 1);
+    }
+
+    if (!sending) {
+        if (l == 0 || l % bs != 0) {
+            /* Publicly invalid */
+            return 0;
+        }
+        /* otherwise, rec->length >= bs */
+    }
+
+    if (provided) {
+        int outlen;
+
+        if (!EVP_CipherUpdate(ds, rec->data, &outlen, rec->input,
+                                (unsigned int)l))
+            return 0;
+        rec->length = outlen;
+
+        if (!sending && mac != NULL) {
+            /* Now get a pointer to the MAC */
+            OSSL_PARAM params[2], *p = params;
+
+            /* Get the MAC */
+            mac->alloced = 0;
+
+            *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
+                                                    (void **)&mac->mac,
+                                                    macsize);
+            *p = OSSL_PARAM_construct_end();
+
+            if (!EVP_CIPHER_CTX_get_params(ds, params)) {
+                /* Shouldn't normally happen */
+                RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+                return 0;
+            }
+        }
+    } else {
+        if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) {
+            /* Shouldn't happen */
+            RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
+
+        if (!sending)
+            return ssl3_cbc_remove_padding_and_mac(&rec->length,
+                                        rec->orig_len,
+                                        rec->data,
+                                        (mac != NULL) ? &mac->mac : NULL,
+                                        (mac != NULL) ? &mac->alloced : NULL,
+                                        bs,
+                                        macsize,
+                                        rl->libctx);
+    }
+
+    return 1;
+}
 
 #define MAX_PADDING 256
 /*-
@@ -690,6 +875,125 @@ static int tls1_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs,
     return 1;
 }
 
+static const unsigned char ssl3_pad_1[48] = {
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+};
+
+static const unsigned char ssl3_pad_2[48] = {
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+};
+
+static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
+                    int sending, SSL_CONNECTION *ssl)
+{
+    unsigned char *mac_sec, *seq;
+    const EVP_MD_CTX *hash;
+    unsigned char *p, rec_char;
+    size_t md_size;
+    size_t npad;
+    int t;
+
+    if (sending) {
+        mac_sec = &(ssl->s3.write_mac_secret[0]);
+        seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
+        hash = ssl->write_hash;
+    } else {
+        mac_sec = &(rl->mac_secret[0]);
+        seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
+        hash = rl->read_hash;
+    }
+
+    t = EVP_MD_CTX_get_size(hash);
+    if (t < 0)
+        return 0;
+    md_size = t;
+    npad = (48 / md_size) * md_size;
+
+    if (!sending
+        && EVP_CIPHER_CTX_get_mode(rl->enc_read_ctx) == EVP_CIPH_CBC_MODE
+        && ssl3_cbc_record_digest_supported(hash)) {
+#ifdef OPENSSL_NO_DEPRECATED_3_0
+        return 0;
+#else
+        /*
+         * This is a CBC-encrypted record. We must avoid leaking any
+         * timing-side channel information about how many blocks of data we
+         * are hashing because that gives an attacker a timing-oracle.
+         */
+
+        /*-
+         * npad is, at most, 48 bytes and that's with MD5:
+         *   16 + 48 + 8 (sequence bytes) + 1 + 2 = 75.
+         *
+         * With SHA-1 (the largest hash speced for SSLv3) the hash size
+         * goes up 4, but npad goes down by 8, resulting in a smaller
+         * total size.
+         */
+        unsigned char header[75];
+        size_t j = 0;
+        memcpy(header + j, mac_sec, md_size);
+        j += md_size;
+        memcpy(header + j, ssl3_pad_1, npad);
+        j += npad;
+        memcpy(header + j, seq, 8);
+        j += 8;
+        header[j++] = rec->type;
+        header[j++] = (unsigned char)(rec->length >> 8);
+        header[j++] = (unsigned char)(rec->length & 0xff);
+
+        /* Final param == is SSLv3 */
+        if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash),
+                                   md, &md_size,
+                                   header, rec->input,
+                                   rec->length, rec->orig_len,
+                                   mac_sec, md_size, 1) <= 0)
+            return 0;
+#endif
+    } else {
+        unsigned int md_size_u;
+        /* Chop the digest off the end :-) */
+        EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+
+        if (md_ctx == NULL)
+            return 0;
+
+        rec_char = rec->type;
+        p = md;
+        s2n(rec->length, p);
+        if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
+            || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
+            || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0
+            || EVP_DigestUpdate(md_ctx, seq, 8) <= 0
+            || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0
+            || EVP_DigestUpdate(md_ctx, md, 2) <= 0
+            || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0
+            || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0
+            || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
+            || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
+            || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0
+            || EVP_DigestUpdate(md_ctx, md, md_size) <= 0
+            || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) {
+            EVP_MD_CTX_free(md_ctx);
+            return 0;
+        }
+
+        EVP_MD_CTX_free(md_ctx);
+    }
+
+    ssl3_record_sequence_update(seq);
+    return 1;
+}
+
 static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
                     int sending, SSL_CONNECTION *ssl)
 {
@@ -830,9 +1134,9 @@ struct record_functions_st tls_1_0_funcs = {
 };
 
 struct record_functions_st ssl_3_0_funcs = {
-    tls_fail_set_crypto_state,
-    NULL,
-    NULL
+    ssl3_set_crypto_state,
+    ssl3_cipher,
+    ssl3_mac
 };
 
 static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio);
index 348b8747801bf762989b01c2051d3cd75c079f3e..8e6db3f0c16c0a1b2ac276d8ce83b0a8fdd895b5 100644 (file)
@@ -90,128 +90,55 @@ static int ssl3_generate_key_block(SSL_CONNECTION *s, unsigned char *km, int num
 int ssl3_change_cipher_state(SSL_CONNECTION *s, int which)
 {
     unsigned char *p, *mac_secret;
-    unsigned char *ms, *key, *iv;
+    size_t md_len;
+    unsigned char *key, *iv;
     EVP_CIPHER_CTX *dd;
-    const EVP_CIPHER *c;
+    const EVP_CIPHER *ciph;
 #ifndef OPENSSL_NO_COMP
-    COMP_METHOD *comp;
+    const SSL_COMP *comp;
 #endif
-    const EVP_MD *m;
+    const EVP_MD *md;
     int mdi;
-    size_t n, i, j, k, cl;
+    size_t n, iv_len, key_len;
     int reuse_dd = 0;
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
 
-    c = s->s3.tmp.new_sym_enc;
-    m = s->s3.tmp.new_hash;
+    ciph = s->s3.tmp.new_sym_enc;
+    md = s->s3.tmp.new_hash;
     /* m == NULL will lead to a crash later */
-    if (!ossl_assert(m != NULL)) {
+    if (!ossl_assert(md != NULL)) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 #ifndef OPENSSL_NO_COMP
-    if (s->s3.tmp.new_compression == NULL)
-        comp = NULL;
-    else
-        comp = s->s3.tmp.new_compression->method;
+    comp = s->s3.tmp.new_compression;
 #endif
 
-    if (which & SSL3_CC_READ) {
-        if (s->enc_read_ctx != NULL) {
-            reuse_dd = 1;
-        } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
-            goto err;
-        } else {
-            /*
-             * make sure it's initialised in case we exit later with an error
-             */
-            EVP_CIPHER_CTX_reset(s->enc_read_ctx);
-        }
-        dd = s->enc_read_ctx;
-
-        if (ssl_replace_hash(&s->read_hash, m) == NULL) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-            goto err;
-        }
-#ifndef OPENSSL_NO_COMP
-        /* COMPRESS */
-        COMP_CTX_free(s->expand);
-        s->expand = NULL;
-        if (comp != NULL) {
-            s->expand = COMP_CTX_new(comp);
-            if (s->expand == NULL) {
-                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                         SSL_R_COMPRESSION_LIBRARY_ERROR);
-                goto err;
-            }
-        }
-#endif
-        RECORD_LAYER_reset_read_sequence(&s->rlayer);
-        mac_secret = &(s->s3.read_mac_secret[0]);
-    } else {
-        s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
-        if (s->enc_write_ctx != NULL) {
-            reuse_dd = 1;
-        } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
-            goto err;
-        } else {
-            /*
-             * make sure it's initialised in case we exit later with an error
-             */
-            EVP_CIPHER_CTX_reset(s->enc_write_ctx);
-        }
-        dd = s->enc_write_ctx;
-        if (ssl_replace_hash(&s->write_hash, m) == NULL) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
-            goto err;
-        }
-#ifndef OPENSSL_NO_COMP
-        /* COMPRESS */
-        COMP_CTX_free(s->compress);
-        s->compress = NULL;
-        if (comp != NULL) {
-            s->compress = COMP_CTX_new(comp);
-            if (s->compress == NULL) {
-                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                         SSL_R_COMPRESSION_LIBRARY_ERROR);
-                goto err;
-            }
-        }
-#endif
-        RECORD_LAYER_reset_write_sequence(&s->rlayer);
-        mac_secret = &(s->s3.write_mac_secret[0]);
-    }
-
-    if (reuse_dd)
-        EVP_CIPHER_CTX_reset(dd);
-
     p = s->s3.tmp.key_block;
-    mdi = EVP_MD_get_size(m);
+    mdi = EVP_MD_get_size(md);
     if (mdi < 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
-    i = mdi;
-    cl = EVP_CIPHER_get_key_length(c);
-    j = cl;
-    k = EVP_CIPHER_get_iv_length(c);
+    md_len = (size_t)mdi;
+    key_len = EVP_CIPHER_get_key_length(ciph);
+    iv_len = EVP_CIPHER_get_iv_length(ciph);
     if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
         (which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
-        ms = &(p[0]);
-        n = i + i;
+        mac_secret = &(p[0]);
+        n = md_len + md_len;
         key = &(p[n]);
-        n += j + j;
+        n += key_len + key_len;
         iv = &(p[n]);
-        n += k + k;
+        n += iv_len + iv_len;
     } else {
-        n = i;
-        ms = &(p[n]);
-        n += i + j;
+        n = md_len;
+        mac_secret = &(p[n]);
+        n += md_len + key_len;
         key = &(p[n]);
-        n += j + k;
+        n += key_len + iv_len;
         iv = &(p[n]);
-        n += k;
+        n += iv_len;
     }
 
     if (n > s->s3.tmp.key_block_length) {
@@ -219,15 +146,67 @@ int ssl3_change_cipher_state(SSL_CONNECTION *s, int which)
         goto err;
     }
 
-    memcpy(mac_secret, ms, i);
+    if (which & SSL3_CC_READ) {
+        s->rrlmethod->free(s->rrl);
+        s->rrl = s->rrlmethod->new_record_layer(sctx->libctx,
+                                                sctx->propq,
+                                                SSL3_VERSION, s->server,
+                                                OSSL_RECORD_DIRECTION_READ,
+                                                OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
+                                                key, key_len, iv, iv_len,
+                                                mac_secret, md_len, ciph, 0,
+                                                NID_undef, md, comp, s->rbio,
+                                                NULL, NULL, NULL, NULL, s);
+        if (s->rrl == NULL) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
+
+        s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
+        return 1;
+    }
+
+    s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
+    if (s->enc_write_ctx != NULL) {
+        reuse_dd = 1;
+    } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+        goto err;
+    } else {
+        /*  make sure it's initialised in case we exit later with an error */
+        EVP_CIPHER_CTX_reset(s->enc_write_ctx);
+    }
+    dd = s->enc_write_ctx;
+    if (ssl_replace_hash(&s->write_hash, md) == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+#ifndef OPENSSL_NO_COMP
+    /* COMPRESS */
+    COMP_CTX_free(s->compress);
+    s->compress = NULL;
+    if (comp != NULL) {
+        s->compress = COMP_CTX_new(comp->method);
+        if (s->compress == NULL) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                        SSL_R_COMPRESSION_LIBRARY_ERROR);
+            goto err;
+        }
+    }
+#endif
+    RECORD_LAYER_reset_write_sequence(&s->rlayer);
+    memcpy(&(s->s3.write_mac_secret[0]), mac_secret, md_len);
+
+    if (reuse_dd)
+        EVP_CIPHER_CTX_reset(dd);
 
-    if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
+    if (!EVP_CipherInit_ex(dd, ciph, NULL, key, iv, (which & SSL3_CC_WRITE))) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
-    if (EVP_CIPHER_get0_provider(c) != NULL
-            && !tls_provider_set_tls_params(s, dd, c, m)) {
+    if (EVP_CIPHER_get0_provider(ciph) != NULL
+            && !tls_provider_set_tls_params(s, dd, ciph, md)) {
         /* SSLfatal already called */
         goto err;
     }