remove ancient SSLeay bug workaround
[openssl.git] / ssl / statem / statem_srvr.c
index 64bbee9392fc01d99dca065c5ccd30f87e655248..6c6e41dcb358c5ae34937fbd364baa3e9f2423ae 100644 (file)
@@ -180,7 +180,7 @@ static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,
  *  1: Success (transition allowed)
  *  0: Error (transition not allowed)
  */
-int server_read_transition(SSL *s, int mt)
+int ossl_statem_server_read_transition(SSL *s, int mt)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -310,12 +310,12 @@ int server_read_transition(SSL *s, int mt)
  *   1: Yes
  *   0: No
  */
-static inline int send_server_key_exchange(SSL *s)
+static int send_server_key_exchange(SSL *s)
 {
     unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
     /*
-     * only send a ServerKeyExchange if DH, fortezza or RSA but we have a
+     * only send a ServerKeyExchange if DH or fortezza but we have a
      * sign only certificate PSK: may send PSK identity hints For
      * ECC ciphersuites, we send a serverKeyExchange message only if
      * the cipher suite is either ECDH-anon or ECDHE. In other cases,
@@ -324,15 +324,6 @@ static inline int send_server_key_exchange(SSL *s)
      */
     if (   (alg_k & SSL_kDHE)
         || (alg_k & SSL_kECDHE)
-        || ((alg_k & SSL_kRSA)
-            && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
-                || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
-                    && EVP_PKEY_size(s->cert->pkeys
-                                     [SSL_PKEY_RSA_ENC].privatekey) *
-                    8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
-                   )
-               )
-           )
         /*
          * PSK: send ServerKeyExchange if PSK identity hint if
          * provided
@@ -362,7 +353,7 @@ static inline int send_server_key_exchange(SSL *s)
  *   1: Yes
  *   0: No
  */
-static inline int send_certificate_request(SSL *s)
+static int send_certificate_request(SSL *s)
 {
     if (
            /* don't request cert unless asked for it: */
@@ -391,7 +382,7 @@ static inline int send_certificate_request(SSL *s)
             * With normal PSK Certificates and Certificate Requests
             * are omitted
             */
-           && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) {
+           && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)) {
         return 1;
     }
 
@@ -402,7 +393,7 @@ static inline int send_certificate_request(SSL *s)
  * server_write_transition() works out what handshake state to move to next
  * when the server is writing messages to be sent to the client.
  */
-WRITE_TRAN server_write_transition(SSL *s)
+WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -520,7 +511,7 @@ WRITE_TRAN server_write_transition(SSL *s)
  * Perform any pre work that needs to be done prior to sending a message from
  * the server to the client.
  */
-WORK_STATE server_pre_work(SSL *s, WORK_STATE wst)
+WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -599,7 +590,7 @@ WORK_STATE server_pre_work(SSL *s, WORK_STATE wst)
  * Perform any work that needs to be done after sending a message from the
  * server to the client.
  */
-WORK_STATE server_post_work(SSL *s, WORK_STATE wst)
+WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -635,8 +626,8 @@ WORK_STATE server_post_work(SSL *s, WORK_STATE wst)
              * Add new shared key for SCTP-Auth, will be ignored if no
              * SCTP used.
              */
-            snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
-                     DTLS1_SCTP_AUTH_LABEL);
+            memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+                   sizeof(DTLS1_SCTP_AUTH_LABEL));
 
             if (SSL_export_keying_material(s, sctpauthkey,
                     sizeof(sctpauthkey), labelbuffer,
@@ -707,7 +698,7 @@ WORK_STATE server_post_work(SSL *s, WORK_STATE wst)
  *   1: Success
  *   0: Error
  */
-int server_construct_message(SSL *s)
+int ossl_statem_server_construct_message(SSL *s)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -767,7 +758,7 @@ int server_construct_message(SSL *s)
  * Returns the maximum allowed length for the current message that we are
  * reading. Excludes the message header.
  */
-unsigned long server_max_message_size(SSL *s)
+unsigned long ossl_statem_server_max_message_size(SSL *s)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -806,7 +797,7 @@ unsigned long server_max_message_size(SSL *s)
 /*
  * Process a message that the server has received from the client.
  */
-MSG_PROCESS_RETURN server_process_message(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -846,7 +837,7 @@ MSG_PROCESS_RETURN server_process_message(SSL *s, PACKET *pkt)
  * Perform any further processing required following the receipt of a message
  * from the client
  */
-WORK_STATE server_post_process_message(SSL *s, WORK_STATE wst)
+WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -868,20 +859,14 @@ WORK_STATE server_post_process_message(SSL *s, WORK_STATE wst)
             s->rwstate = SSL_READING;
             BIO_clear_retry_flags(SSL_get_rbio(s));
             BIO_set_retry_read(SSL_get_rbio(s));
-            statem_set_sctp_read_sock(s, 1);
+            ossl_statem_set_sctp_read_sock(s, 1);
             return WORK_MORE_A;
         } else {
-            ossl_ossl_statem_set_sctp_read_sock(s, 0);
+            ossl_statem_set_sctp_read_sock(s, 0);
         }
 #endif
         return WORK_FINISHED_CONTINUE;
 
-
-    case TLS_ST_SR_FINISHED:
-        if (s->hit)
-            return tls_finish_handshake(s, wst);
-        else
-            return WORK_FINISHED_STOP;
     default:
         break;
     }
@@ -1556,7 +1541,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
             s->s3->tmp.new_cipher = s->session->cipher;
         }
 
-        if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) {
+        if (!(s->verify_mode & SSL_VERIFY_PEER)) {
             if (!ssl3_digest_cached_records(s, 0)) {
                 al = SSL_AD_INTERNAL_ERROR;
                 goto f_err;
@@ -1729,18 +1714,10 @@ int tls_construct_server_done(SSL *s)
 
 int tls_construct_server_key_exchange(SSL *s)
 {
-#ifndef OPENSSL_NO_RSA
-    unsigned char *q;
-    int j, num;
-    RSA *rsa;
-    unsigned char md_buf[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH];
-    unsigned int u;
-#endif
 #ifndef OPENSSL_NO_DH
     DH *dh = NULL, *dhp;
 #endif
 #ifndef OPENSSL_NO_EC
-    EC_KEY *ecdh = NULL, *ecdhp;
     unsigned char *encodedPoint = NULL;
     int encodedlen = 0;
     int curve_id = 0;
@@ -1752,16 +1729,18 @@ int tls_construct_server_key_exchange(SSL *s)
     int al, i;
     unsigned long type;
     int n;
-    CERT *cert;
     BIGNUM *r[4];
     int nr[4], kn;
     BUF_MEM *buf;
-    EVP_MD_CTX md_ctx;
+    EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
 
-    EVP_MD_CTX_init(&md_ctx);
+    if (md_ctx == NULL) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+        al = SSL_AD_INTERNAL_ERROR;
+        goto f_err;
+    }
 
     type = s->s3->tmp.new_cipher->algorithm_mkey;
-    cert = s->cert;
 
     buf = s->init_buf;
 
@@ -1780,37 +1759,10 @@ int tls_construct_server_key_exchange(SSL *s)
     if (type & (SSL_kPSK | SSL_kRSAPSK)) {
     } else
 #endif                          /* !OPENSSL_NO_PSK */
-#ifndef OPENSSL_NO_RSA
-    if (type & SSL_kRSA) {
-        rsa = cert->rsa_tmp;
-        if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) {
-            rsa = s->cert->rsa_tmp_cb(s,
-                                      SSL_C_IS_EXPORT(s->s3->
-                                                      tmp.new_cipher),
-                                      SSL_C_EXPORT_PKEYLENGTH(s->s3->
-                                                              tmp.new_cipher));
-            if (rsa == NULL) {
-                al = SSL_AD_HANDSHAKE_FAILURE;
-                SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                       SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
-                goto f_err;
-            }
-            RSA_up_ref(rsa);
-            cert->rsa_tmp = rsa;
-        }
-        if (rsa == NULL) {
-            al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   SSL_R_MISSING_TMP_RSA_KEY);
-            goto f_err;
-        }
-        r[0] = rsa->n;
-        r[1] = rsa->e;
-        s->s3->tmp.use_rsa_tmp = 1;
-    } else
-#endif
 #ifndef OPENSSL_NO_DH
     if (type & (SSL_kDHE | SSL_kDHEPSK)) {
+        CERT *cert = s->cert;
+
         if (s->cert->dh_tmp_auto) {
             dhp = ssl_get_auto_dh(s);
             if (dhp == NULL) {
@@ -1822,11 +1774,7 @@ int tls_construct_server_key_exchange(SSL *s)
         } else
             dhp = cert->dh_tmp;
         if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
-            dhp = s->cert->dh_tmp_cb(s,
-                                     SSL_C_IS_EXPORT(s->s3->
-                                                     tmp.new_cipher),
-                                     SSL_C_EXPORT_PKEYLENGTH(s->s3->
-                                                             tmp.new_cipher));
+            dhp = s->cert->dh_tmp_cb(s, 0, 1024);
         if (dhp == NULL) {
             al = SSL_AD_HANDSHAKE_FAILURE;
             SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
@@ -1877,21 +1825,13 @@ int tls_construct_server_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_EC
     if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
         const EC_GROUP *group;
+        EC_KEY *ecdh = NULL;
 
-        ecdhp = cert->ecdh_tmp;
-        if (s->cert->ecdh_tmp_auto) {
-            /* Get NID of appropriate shared curve */
-            int nid = tls1_shared_curve(s, -2);
-            if (nid != NID_undef)
-                ecdhp = EC_KEY_new_by_curve_name(nid);
-        } else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) {
-            ecdhp = s->cert->ecdh_tmp_cb(s,
-                                         SSL_C_IS_EXPORT(s->s3->
-                                                         tmp.new_cipher),
-                                         SSL_C_EXPORT_PKEYLENGTH(s->
-                                                                 s3->tmp.new_cipher));
-        }
-        if (ecdhp == NULL) {
+        /* Get NID of appropriate shared curve */
+        int nid = tls1_shared_curve(s, -2);
+        if (nid != NID_undef)
+            ecdh = EC_KEY_new_by_curve_name(nid);
+        if (ecdh == NULL) {
             al = SSL_AD_HANDSHAKE_FAILURE;
             SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                    SSL_R_MISSING_TMP_ECDH_KEY);
@@ -1904,18 +1844,6 @@ int tls_construct_server_key_exchange(SSL *s)
             goto err;
         }
 
-        /* Duplicate the ECDH structure. */
-        if (ecdhp == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB);
-            goto err;
-        }
-        if (s->cert->ecdh_tmp_auto)
-            ecdh = ecdhp;
-        else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB);
-            goto err;
-        }
-
         s->s3->tmp.ecdh = ecdh;
         if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
             (EC_KEY_get0_private_key(ecdh) == NULL) ||
@@ -1934,13 +1862,6 @@ int tls_construct_server_key_exchange(SSL *s)
             goto err;
         }
 
-        if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
-            (EC_GROUP_get_degree(group) > 163)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
-            goto err;
-        }
-
         /*
          * XXX: For now, we only support ephemeral ECDH keys over named
          * (not generic) curves. For supported named curves, curve_id is
@@ -2108,33 +2029,6 @@ int tls_construct_server_key_exchange(SSL *s)
          * n is the length of the params, they start at &(d[4]) and p
          * points to the space at the end.
          */
-#ifndef OPENSSL_NO_RSA
-        if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) {
-            q = md_buf;
-            j = 0;
-            for (num = 2; num > 0; num--) {
-                EVP_MD_CTX_set_flags(&md_ctx,
-                                     EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
-                EVP_DigestInit_ex(&md_ctx, (num == 2)
-                                  ? s->ctx->md5 : s->ctx->sha1, NULL);
-                EVP_DigestUpdate(&md_ctx, &(s->s3->client_random[0]),
-                                 SSL3_RANDOM_SIZE);
-                EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]),
-                                 SSL3_RANDOM_SIZE);
-                EVP_DigestUpdate(&md_ctx, d, n);
-                EVP_DigestFinal_ex(&md_ctx, q, (unsigned int *)&i);
-                q += i;
-                j += i;
-            }
-            if (RSA_sign(NID_md5_sha1, md_buf, j,
-                         &(p[2]), &u, pkey->pkey.rsa) <= 0) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_LIB_RSA);
-                goto err;
-            }
-            s2n(u, p);
-            n += u + 2;
-        } else
-#endif
         if (md) {
             /* send signature algorithm */
             if (SSL_USE_SIGALGS(s)) {
@@ -2150,16 +2044,17 @@ int tls_construct_server_key_exchange(SSL *s)
 #ifdef SSL_DEBUG
             fprintf(stderr, "Using hash %s\n", EVP_MD_name(md));
 #endif
-            EVP_SignInit_ex(&md_ctx, md, NULL);
-            EVP_SignUpdate(&md_ctx, &(s->s3->client_random[0]),
-                           SSL3_RANDOM_SIZE);
-            EVP_SignUpdate(&md_ctx, &(s->s3->server_random[0]),
-                           SSL3_RANDOM_SIZE);
-            EVP_SignUpdate(&md_ctx, d, n);
-            if (!EVP_SignFinal(&md_ctx, &(p[2]),
-                               (unsigned int *)&i, pkey)) {
+            if (EVP_SignInit_ex(md_ctx, md, NULL) <= 0
+                    || EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]),
+                                      SSL3_RANDOM_SIZE) <= 0
+                    || EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]),
+                                      SSL3_RANDOM_SIZE) <= 0
+                    || EVP_SignUpdate(md_ctx, d, n) <= 0
+                    || EVP_SignFinal(md_ctx, &(p[2]),
+                               (unsigned int *)&i, pkey) <= 0) {
                 SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_LIB_EVP);
-                goto err;
+                al = SSL_AD_INTERNAL_ERROR;
+                goto f_err;
             }
             s2n(i, p);
             n += i + 2;
@@ -2180,7 +2075,7 @@ int tls_construct_server_key_exchange(SSL *s)
         goto f_err;
     }
 
-    EVP_MD_CTX_cleanup(&md_ctx);
+    EVP_MD_CTX_free(md_ctx);
     return 1;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
@@ -2189,7 +2084,7 @@ int tls_construct_server_key_exchange(SSL *s)
     OPENSSL_free(encodedPoint);
     BN_CTX_free(bn_ctx);
 #endif
-    EVP_MD_CTX_cleanup(&md_ctx);
+    EVP_MD_CTX_free(md_ctx);
     ossl_statem_set_error(s);
     return 0;
 }
@@ -2373,30 +2268,15 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
         size_t j;
 
         /* FIX THIS UP EAY EAY EAY EAY */
-        if (s->s3->tmp.use_rsa_tmp) {
-            if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL))
-                rsa = s->cert->rsa_tmp;
-            /*
-             * Don't do a callback because rsa_tmp should be sent already
-             */
-            if (rsa == NULL) {
-                al = SSL_AD_HANDSHAKE_FAILURE;
-                SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
-                       SSL_R_MISSING_TMP_RSA_PKEY);
-                goto f_err;
-
-            }
-        } else {
-            pkey = s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
-            if ((pkey == NULL) ||
-                (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) {
-                al = SSL_AD_HANDSHAKE_FAILURE;
-                SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
-                       SSL_R_MISSING_RSA_CERTIFICATE);
-                goto f_err;
-            }
-            rsa = pkey->pkey.rsa;
+        pkey = s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
+        if ((pkey == NULL) ||
+            (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) {
+            al = SSL_AD_HANDSHAKE_FAILURE;
+            SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+                   SSL_R_MISSING_RSA_CERTIFICATE);
+            goto f_err;
         }
+        rsa = pkey->pkey.rsa;
 
         /* SSLv3 and pre-standard DTLS omit the length bytes. */
         if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) {
@@ -2541,14 +2421,9 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
             i = 0;
         }
         if (PACKET_remaining(pkt) != i) {
-            if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) {
-                SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
-                       SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
-                goto err;
-            } else {
-                *pkt = bookmark;
-                i = PACKET_remaining(pkt);
-            }
+            SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+                   SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
+            goto err;
         }
         if (alg_k & SSL_kDHr)
             idx = SSL_PKEY_DH_RSA;
@@ -2797,6 +2672,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
         }
     } else
 #endif                          /* OPENSSL_NO_SRP */
+#ifndef OPENSSL_NO_GOST
     if (alg_k & SSL_kGOST) {
         EVP_PKEY_CTX *pkey_ctx;
         EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
@@ -2809,11 +2685,32 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
 
         /* Get our certificate private key */
         alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-        if (alg_a & SSL_aGOST01)
+        if (alg_a & SSL_aGOST12) {
+            /*
+             * New GOST ciphersuites have SSL_aGOST01 bit too
+             */
+            pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey;
+            if (pk == NULL) {
+                pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
+            }
+            if (pk == NULL) {
+                pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
+            }
+        } else if (alg_a & SSL_aGOST01) {
             pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
+        }
 
         pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
-        EVP_PKEY_decrypt_init(pkey_ctx);
+        if (pkey_ctx == NULL) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+        if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            goto f_err;
+        }
         /*
          * If client certificate is present and is of the same type, maybe
          * use it for key exchange.  Don't mind errors from
@@ -2830,12 +2727,13 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
         if (!PACKET_get_bytes(pkt, &data, sess_key_len)) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            goto gerr;
         }
         if (ASN1_get_object ((const unsigned char **)&data, &Tlen, &Ttag,
                              &Tclass, sess_key_len) != V_ASN1_CONSTRUCTED
             || Ttag != V_ASN1_SEQUENCE
             || Tclass != V_ASN1_UNIVERSAL) {
+            al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
                    SSL_R_DECRYPTION_FAILED);
             goto gerr;
@@ -2844,6 +2742,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
         inlen = Tlen;
         if (EVP_PKEY_decrypt
             (pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
+            al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
                    SSL_R_DECRYPTION_FAILED);
             goto gerr;
@@ -2853,7 +2752,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
                                         sizeof(premaster_secret), 0)) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            goto gerr;
         }
         /* Check if pubkey from client certificate was used */
         if (EVP_PKEY_CTX_ctrl
@@ -2866,8 +2765,10 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
  gerr:
         EVP_PKEY_free(client_pub_pkey);
         EVP_PKEY_CTX_free(pkey_ctx);
-        goto err;
-    } else {
+        goto f_err;
+    } else
+#endif
+    {
         al = SSL_AD_HANDSHAKE_FAILURE;
         SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, SSL_R_UNKNOWN_CIPHER_TYPE);
         goto f_err;
@@ -2905,8 +2806,8 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
              * Add new shared key for SCTP-Auth, will be ignored if no SCTP
              * used.
              */
-            snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
-                     DTLS1_SCTP_AUTH_LABEL);
+            memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+                   sizeof(DTLS1_SCTP_AUTH_LABEL));
 
             if (SSL_export_keying_material(s, sctpauthkey,
                                        sizeof(sctpauthkey), labelbuffer,
@@ -2933,7 +2834,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
         s->rwstate = SSL_READING;
         BIO_clear_retry_flags(SSL_get_rbio(s));
         BIO_set_retry_read(SSL_get_rbio(s));
-        statem_set_sctp_read_sock(s, 1);
+        ossl_statem_set_sctp_read_sock(s, 1);
         return WORK_MORE_B;
     } else {
         ossl_statem_set_sctp_read_sock(s, 0);
@@ -2943,8 +2844,9 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
     if (s->statem.no_cert_verify) {
         /* No certificate verify so we no longer need the handshake_buffer */
         BIO_free(s->s3->handshake_buffer);
+        s->s3->handshake_buffer = NULL;
         return WORK_FINISHED_CONTINUE;
-    } else if (SSL_USE_SIGALGS(s)) {
+    } else {
         if (!s->session->peer) {
             /* No peer certificate so we no longer need the handshake_buffer */
             BIO_free(s->s3->handshake_buffer);
@@ -2964,41 +2866,6 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
             ossl_statem_set_error(s);
             return WORK_ERROR;
         }
-    } else {
-        int offset = 0;
-        int dgst_num;
-
-        /*
-         * We need to get hashes here so if there is a client cert,
-         * it can be verified FIXME - digest processing for
-         * CertificateVerify should be generalized. But it is next
-         * step
-         */
-        if (!ssl3_digest_cached_records(s, 0)) {
-            ossl_statem_set_error(s);
-            return WORK_ERROR;
-        }
-        for (dgst_num = 0; dgst_num < SSL_MAX_DIGEST; dgst_num++) {
-            if (s->s3->handshake_dgst[dgst_num]) {
-                int dgst_size;
-
-                s->method->ssl3_enc->cert_verify_mac(s,
-                                                     EVP_MD_CTX_type
-                                                     (s->
-                                                      s3->handshake_dgst
-                                                      [dgst_num]),
-                                                     &(s->s3->
-                                                       tmp.cert_verify_md
-                                                       [offset]));
-                dgst_size =
-                    EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
-                if (dgst_size < 0) {
-                    ossl_statem_set_error(s);
-                return WORK_ERROR;
-                }
-                offset += dgst_size;
-            }
-        }
     }
 
     return WORK_FINISHED_CONTINUE;
@@ -3009,12 +2876,20 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
     EVP_PKEY *pkey = NULL;
     unsigned char *sig, *data;
     int al, ret = MSG_PROCESS_ERROR;
-    int type = 0, i, j;
+    int type = 0, j;
     unsigned int len;
     X509 *peer;
     const EVP_MD *md = NULL;
-    EVP_MD_CTX mctx;
-    EVP_MD_CTX_init(&mctx);
+    long hdatalen = 0;
+    void *hdata;
+
+    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+
+    if (mctx == NULL) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+        al = SSL_AD_INTERNAL_ERROR;
+        goto f_err;
+    }
 
     peer = s->session->peer;
     pkey = X509_get_pubkey(peer);
@@ -3030,11 +2905,14 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
     /* Check for broken implementations of GOST ciphersuites */
     /*
      * If key is GOST and n is exactly 64, it is bare signature without
-     * length field
+     * length field (CryptoPro implementations at least till CSP 4.0)
      */
+#ifndef OPENSSL_NO_GOST
     if (PACKET_remaining(pkt) == 64 && pkey->type == NID_id_GostR3410_2001) {
         len = 64;
-    } else {
+    } else
+#endif
+    {
         if (SSL_USE_SIGALGS(s)) {
             int rv;
 
@@ -3053,7 +2931,17 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
 #ifdef SSL_DEBUG
             fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
+        } else {
+            /* Use default digest for this key type */
+            int idx = ssl_cert_type(NULL, pkey);
+            if (idx >= 0)
+                md = s->s3->tmp.md[idx];
+            if (md == NULL) {
+                al = SSL_AD_INTERNAL_ERROR;
+                goto f_err;
+            }
         }
+
         if (!PACKET_get_net_2(pkt, &len)) {
             SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
             al = SSL_AD_DECODE_ERROR;
@@ -3073,97 +2961,42 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
         goto f_err;
     }
 
-    if (SSL_USE_SIGALGS(s)) {
-        long hdatalen = 0;
-        void *hdata;
-        hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
-        if (hdatalen <= 0) {
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
-            al = SSL_AD_INTERNAL_ERROR;
-            goto f_err;
-        }
+    hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+    if (hdatalen <= 0) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        al = SSL_AD_INTERNAL_ERROR;
+        goto f_err;
+    }
 #ifdef SSL_DEBUG
-        fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
-                EVP_MD_name(md));
+    fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
 #endif
-        if (!EVP_VerifyInit_ex(&mctx, md, NULL)
-            || !EVP_VerifyUpdate(&mctx, hdata, hdatalen)) {
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
-            al = SSL_AD_INTERNAL_ERROR;
-            goto f_err;
-        }
+    if (!EVP_VerifyInit_ex(mctx, md, NULL)
+        || !EVP_VerifyUpdate(mctx, hdata, hdatalen)) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+        al = SSL_AD_INTERNAL_ERROR;
+        goto f_err;
+    }
 
-        if (EVP_VerifyFinal(&mctx, data, len, pkey) <= 0) {
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
-            goto f_err;
-        }
-    } else
-#ifndef OPENSSL_NO_RSA
-    if (pkey->type == EVP_PKEY_RSA) {
-        i = RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
-                       MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, data, len,
-                       pkey->pkey.rsa);
-        if (i < 0) {
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_RSA_DECRYPT);
-            goto f_err;
-        }
-        if (i == 0) {
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_RSA_SIGNATURE);
-            goto f_err;
-        }
-    } else
-#endif
-#ifndef OPENSSL_NO_DSA
-    if (pkey->type == EVP_PKEY_DSA) {
-        j = DSA_verify(pkey->save_type,
-                       &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
-                       SHA_DIGEST_LENGTH, data, len, pkey->pkey.dsa);
-        if (j <= 0) {
-            /* bad signature */
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_DSA_SIGNATURE);
-            goto f_err;
-        }
-    } else
-#endif
-#ifndef OPENSSL_NO_EC
-    if (pkey->type == EVP_PKEY_EC) {
-        j = ECDSA_verify(pkey->save_type,
-                         &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
-                         SHA_DIGEST_LENGTH, data, len, pkey->pkey.ec);
-        if (j <= 0) {
-            /* bad signature */
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_ECDSA_SIGNATURE);
-            goto f_err;
-        }
-    } else
+#ifndef OPENSSL_NO_GOST
+    if (pkey->type == NID_id_GostR3410_2001
+            || pkey->type == NID_id_GostR3410_2012_256
+            || pkey->type == NID_id_GostR3410_2012_512) {
+        BUF_reverse(data, NULL, len);
+    }
 #endif
-    if (pkey->type == NID_id_GostR3410_2001) {
-        unsigned char signature[64];
-        int idx;
-        EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
-        EVP_PKEY_verify_init(pctx);
-        if (len != 64) {
-            fprintf(stderr, "GOST signature length is %d", len);
-        }
-        for (idx = 0; idx < 64; idx++) {
-            signature[63 - idx] = data[idx];
-        }
-        j = EVP_PKEY_verify(pctx, signature, 64, s->s3->tmp.cert_verify_md,
-                            32);
-        EVP_PKEY_CTX_free(pctx);
-        if (j <= 0) {
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_ECDSA_SIGNATURE);
-            goto f_err;
-        }
-    } else {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
-        al = SSL_AD_UNSUPPORTED_CERTIFICATE;
+
+    if (s->version == SSL3_VERSION
+        && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+                            s->session->master_key_length,
+                            s->session->master_key)) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+        al = SSL_AD_INTERNAL_ERROR;
+        goto f_err;
+    }
+
+    if (EVP_VerifyFinal(mctx, data, len, pkey) <= 0) {
+        al = SSL_AD_DECRYPT_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
         goto f_err;
     }
 
@@ -3175,7 +3008,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
     }
     BIO_free(s->s3->handshake_buffer);
     s->s3->handshake_buffer = NULL;
-    EVP_MD_CTX_cleanup(&mctx);
+    EVP_MD_CTX_free(mctx);
     EVP_PKEY_free(pkey);
     return ret;
 }
@@ -3322,7 +3155,7 @@ int tls_construct_new_session_ticket(SSL *s)
 {
     unsigned char *senc = NULL;
     EVP_CIPHER_CTX ctx;
-    HMAC_CTX hctx;
+    HMAC_CTX *hctx = NULL;
     unsigned char *p, *macstart;
     const unsigned char *const_p;
     int len, slen_full, slen;
@@ -3343,13 +3176,13 @@ int tls_construct_new_session_ticket(SSL *s)
         return 0;
     }
     senc = OPENSSL_malloc(slen_full);
-    if (!senc) {
+    if (senc == NULL) {
         ossl_statem_set_error(s);
         return 0;
     }
 
     EVP_CIPHER_CTX_init(&ctx);
-    HMAC_CTX_init(&hctx);
+    hctx = HMAC_CTX_new();
 
     p = senc;
     if (!i2d_SSL_SESSION(s->session, &p))
@@ -3395,8 +3228,7 @@ int tls_construct_new_session_ticket(SSL *s)
      * all the work otherwise use generated values from parent ctx.
      */
     if (tctx->tlsext_ticket_key_cb) {
-        if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
-                                       &hctx, 1) < 0)
+        if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, hctx, 1) < 0)
             goto err;
     } else {
         if (RAND_bytes(iv, 16) <= 0)
@@ -3404,7 +3236,7 @@ int tls_construct_new_session_ticket(SSL *s)
         if (!EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
                                 tctx->tlsext_tick_aes_key, iv))
             goto err;
-        if (!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+        if (!HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, 16,
                           EVP_sha256(), NULL))
             goto err;
         memcpy(key_name, tctx->tlsext_tick_key_name, 16);
@@ -3434,13 +3266,13 @@ int tls_construct_new_session_ticket(SSL *s)
         goto err;
     p += len;
 
-    if (!HMAC_Update(&hctx, macstart, p - macstart))
+    if (!HMAC_Update(hctx, macstart, p - macstart))
         goto err;
-    if (!HMAC_Final(&hctx, p, &hlen))
+    if (!HMAC_Final(hctx, p, &hlen))
         goto err;
 
     EVP_CIPHER_CTX_cleanup(&ctx);
-    HMAC_CTX_cleanup(&hctx);
+    HMAC_CTX_free(hctx);
 
     p += hlen;
     /* Now write out lengths: p points to end of data written */
@@ -3457,7 +3289,7 @@ int tls_construct_new_session_ticket(SSL *s)
  err:
     OPENSSL_free(senc);
     EVP_CIPHER_CTX_cleanup(&ctx);
-    HMAC_CTX_cleanup(&hctx);
+    HMAC_CTX_free(hctx);
     ossl_statem_set_error(s);
     return 0;
 }