Fix warnings about unused variables when EC is disabled.
[openssl.git] / ssl / statem / statem_clnt.c
index c68eecf24fea8d2bfe2fc0e825a4d9b92675df50..7c98228b425abf909a88cb749700b42843cfddb7 100644 (file)
 #endif
 
 static inline int cert_req_allowed(SSL *s);
-static inline int key_exchange_skip_allowed(SSL *s);
+static int key_exchange_expected(SSL *s);
 static int ssl_set_version(SSL *s);
 static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b);
 static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
@@ -182,48 +182,52 @@ static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
 static inline int cert_req_allowed(SSL *s)
 {
     /* TLS does not like anon-DH with client cert */
-    if (s->version > SSL3_VERSION
-            && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
+    if ((s->version > SSL3_VERSION
+                && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
+            || (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK)))
         return 0;
 
     return 1;
 }
 
 /*
- * Are we allowed to skip the ServerKeyExchange message?
+ * Should we expect the ServerKeyExchange message or not?
  *
  *  Return values are:
  *  1: Yes
  *  0: No
+ * -1: Error
  */
-static inline int key_exchange_skip_allowed(SSL *s)
+static int key_exchange_expected(SSL *s)
 {
     long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
     /*
      * Can't skip server key exchange if this is an ephemeral
-     * ciphersuite.
+     * ciphersuite or for SRP
      */
-    if (alg_k & (SSL_kDHE | SSL_kECDHE)) {
-        return 0;
+    if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK
+                 | SSL_kSRP)) {
+        return 1;
     }
 
-    return 1;
+    return 0;
 }
 
 /*
- * client_read_transition() encapsulates the logic for the allowed handshake
- * state transitions when the client is reading messages from the server. The
- * message type that the server has sent is provided in |mt|. The current state
- * is in |s->statem.hand_state|.
+ * ossl_statem_client_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when the client is reading messages from the
+ * server. The message type that the server has sent is provided in |mt|. The
+ * current state is in |s->statem.hand_state|.
  *
  *  Return values are:
  *  1: Success (transition allowed)
  *  0: Error (transition not allowed)
  */
-int client_read_transition(SSL *s, int mt)
+int ossl_statem_client_read_transition(SSL *s, int mt)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
+    int ske_expected;
 
     switch(st->hand_state) {
     case TLS_ST_CW_CLNT_HELLO:
@@ -255,6 +259,19 @@ int client_read_transition(SSL *s, int mt)
             if (SSL_IS_DTLS(s) && mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
                 st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
                 return 1;
+            } else if (s->version >= TLS1_VERSION
+                    && s->tls_session_secret_cb != NULL
+                    && s->session->tlsext_tick != NULL
+                    && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+                /*
+                 * Normally, we can tell if the server is resuming the session
+                 * from the session ID. EAP-FAST (RFC 4851), however, relies on
+                 * the next server message after the ServerHello to determine if
+                 * the server is resuming.
+                 */
+                s->hit = 1;
+                st->hand_state = TLS_ST_CR_CHANGE;
+                return 1;
             } else if (!(s->s3->tmp.new_cipher->algorithm_auth
                         & (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
                 if (mt == SSL3_MT_CERTIFICATE) {
@@ -262,18 +279,24 @@ int client_read_transition(SSL *s, int mt)
                     return 1;
                 }
             } else {
-                if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
-                    st->hand_state = TLS_ST_CR_KEY_EXCH;
-                    return 1;
-                } else if (key_exchange_skip_allowed(s)) {
-                    if (mt == SSL3_MT_CERTIFICATE_REQUEST
+                ske_expected = key_exchange_expected(s);
+                if (ske_expected < 0)
+                    return 0;
+                /* SKE is optional for some PSK ciphersuites */
+                if (ske_expected
+                        || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
+                            && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
+                    if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
+                        st->hand_state = TLS_ST_CR_KEY_EXCH;
+                        return 1;
+                    }
+                } else if (mt == SSL3_MT_CERTIFICATE_REQUEST
                             && cert_req_allowed(s)) {
                         st->hand_state = TLS_ST_CR_CERT_REQ;
                         return 1;
-                    } else if (mt == SSL3_MT_SERVER_DONE) {
+                } else if (mt == SSL3_MT_SERVER_DONE) {
                         st->hand_state = TLS_ST_CR_SRVR_DONE;
                         return 1;
-                    }
                 }
             }
         }
@@ -285,46 +308,35 @@ int client_read_transition(SSL *s, int mt)
                 st->hand_state = TLS_ST_CR_CERT_STATUS;
                 return 1;
             }
-        } else {
+            return 0;
+        }
+        /* Fall through */
+
+    case TLS_ST_CR_CERT_STATUS:
+        ske_expected = key_exchange_expected(s);
+        if (ske_expected < 0)
+            return 0;
+        /* SKE is optional for some PSK ciphersuites */
+        if (ske_expected
+                || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
+                    && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
             if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
                 st->hand_state = TLS_ST_CR_KEY_EXCH;
                 return 1;
-            } else if (key_exchange_skip_allowed(s)) {
-                if (mt == SSL3_MT_CERTIFICATE_REQUEST && cert_req_allowed(s)) {
-                    st->hand_state = TLS_ST_CR_CERT_REQ;
-                    return 1;
-                } else if (mt == SSL3_MT_SERVER_DONE) {
-                    st->hand_state = TLS_ST_CR_SRVR_DONE;
-                    return 1;
-                }
             }
+            return 0;
         }
-        break;
+        /* Fall through */
 
-    case TLS_ST_CR_CERT_STATUS:
-        if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
-            st->hand_state = TLS_ST_CR_KEY_EXCH;
-            return 1;
-        } else if (key_exchange_skip_allowed(s)) {
-            if (mt == SSL3_MT_CERTIFICATE_REQUEST && cert_req_allowed(s)) {
+    case TLS_ST_CR_KEY_EXCH:
+        if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
+            if (cert_req_allowed(s)) {
                 st->hand_state = TLS_ST_CR_CERT_REQ;
                 return 1;
-            } else if (mt == SSL3_MT_SERVER_DONE) {
-                st->hand_state = TLS_ST_CR_SRVR_DONE;
-                return 1;
             }
+            return 0;
         }
-        break;
-
-    case TLS_ST_CR_KEY_EXCH:
-        if (mt == SSL3_MT_CERTIFICATE_REQUEST && cert_req_allowed(s)) {
-            st->hand_state = TLS_ST_CR_CERT_REQ;
-            return 1;
-        } else if (mt == SSL3_MT_SERVER_DONE) {
-            st->hand_state = TLS_ST_CR_SRVR_DONE;
-            return 1;
-        }
-        break;
+        /* Fall through */
 
     case TLS_ST_CR_CERT_REQ:
         if (mt == SSL3_MT_SERVER_DONE) {
@@ -369,9 +381,9 @@ int client_read_transition(SSL *s, int mt)
  * client_write_transition() works out what handshake state to move to next
  * when the client is writing messages to be sent to the server.
  */
-enum WRITE_TRAN client_write_transition(SSL *s)
+WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     switch(st->hand_state) {
         case TLS_ST_OK:
@@ -447,7 +459,7 @@ enum WRITE_TRAN client_write_transition(SSL *s)
         case TLS_ST_CW_FINISHED:
             if (s->hit) {
                 st->hand_state = TLS_ST_OK;
-                statem_set_in_init(s, 0);
+                ossl_statem_set_in_init(s, 0);
                 return WRITE_TRAN_CONTINUE;
             } else {
                 return WRITE_TRAN_FINISHED;
@@ -459,7 +471,7 @@ enum WRITE_TRAN client_write_transition(SSL *s)
                 return WRITE_TRAN_CONTINUE;
             } else {
                 st->hand_state = TLS_ST_OK;
-                statem_set_in_init(s, 0);
+                ossl_statem_set_in_init(s, 0);
                 return WRITE_TRAN_CONTINUE;
             }
 
@@ -473,9 +485,9 @@ enum WRITE_TRAN client_write_transition(SSL *s)
  * Perform any pre work that needs to be done prior to sending a message from
  * the client to the server.
  */
-enum WORK_STATE client_pre_work(SSL *s, enum WORK_STATE wst)
+WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     switch(st->hand_state) {
     case TLS_ST_CW_CLNT_HELLO:
@@ -520,9 +532,9 @@ enum WORK_STATE client_pre_work(SSL *s, enum WORK_STATE wst)
  * Perform any work that needs to be done after sending a message from the
  * client to the server.
  */
-enum WORK_STATE client_post_work(SSL *s, enum WORK_STATE wst)
+WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     s->init_num = 0;
 
@@ -599,9 +611,6 @@ enum WORK_STATE client_post_work(SSL *s, enum WORK_STATE wst)
 #endif
         if (statem_flush(s) != 1)
             return WORK_MORE_B;
-
-        if (s->hit && tls_finish_handshake(s, WORK_MORE_A) != 1)
-                return WORK_ERROR;
         break;
 
     default:
@@ -619,9 +628,9 @@ enum WORK_STATE client_post_work(SSL *s, enum WORK_STATE wst)
  *   1: Success
  *   0: Error
  */
-int client_construct_message(SSL *s)
+int ossl_statem_client_construct_message(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     switch(st->hand_state) {
     case TLS_ST_CW_CLNT_HELLO:
@@ -665,9 +674,9 @@ int client_construct_message(SSL *s)
  * Returns the maximum allowed length for the current message that we are
  * reading. Excludes the message header.
  */
-unsigned long client_max_message_size(SSL *s)
+unsigned long ossl_statem_client_max_message_size(SSL *s)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     switch(st->hand_state) {
         case TLS_ST_CR_SRVR_HELLO:
@@ -711,9 +720,9 @@ unsigned long client_max_message_size(SSL *s)
 /*
  * Process a message that the client has been received from the server.
  */
-enum MSG_PROCESS_RETURN client_process_message(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     switch(st->hand_state) {
         case TLS_ST_CR_SRVR_HELLO:
@@ -758,9 +767,9 @@ enum MSG_PROCESS_RETURN client_process_message(SSL *s, PACKET *pkt)
  * Perform any further processing required following the receipt of a message
  * from the server
  */
-enum WORK_STATE client_post_process_message(SSL *s, enum WORK_STATE wst)
+WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
 {
-    STATEM *st = &s->statem;
+    OSSL_STATEM *st = &s->statem;
 
     switch(st->hand_state) {
 #ifndef OPENSSL_NO_SCTP
@@ -771,18 +780,13 @@ enum WORK_STATE client_post_process_message(SSL *s, enum 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;
         }
-        statem_set_sctp_read_sock(s, 0);
+        ossl_statem_set_sctp_read_sock(s, 0);
         return WORK_FINISHED_STOP;
 #endif
 
-    case TLS_ST_CR_FINISHED:
-        if (!s->hit)
-            return tls_finish_handshake(s, wst);
-        else
-            return WORK_FINISHED_STOP;
     default:
         break;
     }
@@ -1067,11 +1071,11 @@ int tls_construct_client_hello(SSL *s)
 
     return 1;
  err:
-    statem_set_error(s);
+    ossl_statem_set_error(s);
     return 0;
 }
 
-enum MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
 {
     int al;
     unsigned int cookie_len;
@@ -1101,11 +1105,11 @@ enum MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
     return MSG_PROCESS_FINISHED_READING;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    statem_set_error(s);
+    ossl_statem_set_error(s);
     return MSG_PROCESS_ERROR;
 }
 
-enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
 {
     STACK_OF(SSL_CIPHER) *sk;
     const SSL_CIPHER *c;
@@ -1220,7 +1224,7 @@ enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     /* Get the session-id. */
     if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
         al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
         goto f_err;
     }
     session_id_len = PACKET_remaining(&session_id);
@@ -1232,7 +1236,7 @@ enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     }
 
     if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
-        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
         al = SSL_AD_DECODE_ERROR;
         goto f_err;
     }
@@ -1310,6 +1314,9 @@ enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
         s->s3->tmp.mask_ssl = SSL_TLSV1_2;
     else
         s->s3->tmp.mask_ssl = 0;
+    /* Skip TLS v1.0 ciphersuites if SSLv3 */
+    if ((c->algorithm_ssl & SSL_TLSV1) && s->version == SSL3_VERSION)
+        s->s3->tmp.mask_ssl |= SSL_TLSV1;
     /*
      * If it is a disabled cipher we didn't send it in client hello, so
      * return an error.
@@ -1343,16 +1350,10 @@ enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
         goto f_err;
     }
     s->s3->tmp.new_cipher = c;
-    /*
-     * Don't digest cached records if no sigalgs: we may need them for client
-     * authentication.
-     */
-    if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s, 0))
-        goto f_err;
     /* lets get the compression algorithm */
     /* COMPRESSION */
     if (!PACKET_get_1(pkt, &compression)) {
-        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
         al = SSL_AD_DECODE_ERROR;
         goto f_err;
     }
@@ -1420,9 +1421,8 @@ enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
          * 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),
@@ -1441,11 +1441,11 @@ enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
  err:
-    statem_set_error(s);
+    ossl_statem_set_error(s);
     return MSG_PROCESS_ERROR;
 }
 
-enum MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
 {
     int al, i, ret = MSG_PROCESS_ERROR, exp_idx;
     unsigned long cert_list_len, cert_len;
@@ -1539,7 +1539,10 @@ enum MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     }
 
     exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
-    if (exp_idx >= 0 && i != exp_idx) {
+    if (exp_idx >= 0 && i != exp_idx
+            && (exp_idx != SSL_PKEY_GOST_EC ||
+                (i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256
+                 && i != SSL_PKEY_GOST01))) {
         x = NULL;
         al = SSL_AD_ILLEGAL_PARAMETER;
         SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
@@ -1560,7 +1563,7 @@ enum MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
  err:
-    statem_set_error(s);
+    ossl_statem_set_error(s);
  done:
     EVP_PKEY_free(pkey);
     X509_free(x);
@@ -1568,13 +1571,10 @@ enum MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     return ret;
 }
 
-enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 {
-#ifndef OPENSSL_NO_RSA
-    unsigned char *q, md_buf[EVP_MAX_MD_SIZE * 2];
-#endif
-    EVP_MD_CTX md_ctx;
-    int al, j, verify_ret;
+    EVP_MD_CTX *md_ctx;
+    int al, j;
     long alg_k, alg_a;
     EVP_PKEY *pkey = NULL;
     const EVP_MD *md = NULL;
@@ -1592,16 +1592,17 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 #endif
     PACKET save_param_start, signature;
 
-    EVP_MD_CTX_init(&md_ctx);
+    md_ctx = EVP_MD_CTX_new();
+    if (md_ctx == NULL) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+        goto f_err;
+    }
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
     save_param_start = *pkt;
 
-#ifndef OPENSSL_NO_RSA
-    RSA_free(s->s3->peer_rsa_tmp);
-    s->s3->peer_rsa_tmp = NULL;
-#endif
 #ifndef OPENSSL_NO_DH
     DH_free(s->s3->peer_dh_tmp);
     s->s3->peer_dh_tmp = NULL;
@@ -1620,7 +1621,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
     if (alg_k & SSL_PSK) {
         PACKET psk_identity_hint;
         if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
@@ -1636,7 +1637,10 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             goto f_err;
         }
 
-        if (!PACKET_strndup(&psk_identity_hint,
+        if (PACKET_remaining(&psk_identity_hint) == 0) {
+            OPENSSL_free(s->session->psk_identity_hint);
+            s->session->psk_identity_hint = NULL;
+        } else if (!PACKET_strndup(&psk_identity_hint,
                             &s->session->psk_identity_hint)) {
             al = SSL_AD_INTERNAL_ERROR;
             goto f_err;
@@ -1654,7 +1658,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             || !PACKET_get_length_prefixed_2(pkt, &generator)
             || !PACKET_get_length_prefixed_1(pkt, &salt)
             || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
@@ -1670,7 +1674,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             || (s->srp_ctx.B =
                 BN_bin2bn(PACKET_data(&server_pub),
                           PACKET_remaining(&server_pub), NULL)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
 
@@ -1682,57 +1686,8 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 /* We must check if there is a certificate */
         if (alg_a & (SSL_aRSA|SSL_aDSS))
             pkey = X509_get_pubkey(s->session->peer);
-    } else
-#endif                          /* !OPENSSL_NO_SRP */
-#ifndef OPENSSL_NO_RSA
-    if (alg_k & SSL_kRSA) {
-        PACKET mod, exp;
-        /* Temporary RSA keys only allowed in export ciphersuites */
-        if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) {
-            al = SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
-            goto f_err;
-        }
-
-        if (!PACKET_get_length_prefixed_2(pkt, &mod)
-            || !PACKET_get_length_prefixed_2(pkt, &exp)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
-        }
-
-        if ((rsa = RSA_new()) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-            goto err;
-        }
-
-        if ((rsa->n = BN_bin2bn(PACKET_data(&mod), PACKET_remaining(&mod),
-                                rsa->n)) == NULL
-            || (rsa->e = BN_bin2bn(PACKET_data(&exp), PACKET_remaining(&exp),
-                                   rsa->e)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto err;
-        }
-
-        /* this should be because we are using an export cipher */
-        if (alg_a & SSL_aRSA)
-            pkey = X509_get_pubkey(s->session->peer);
-        else {
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            goto err;
-        }
-
-        if (EVP_PKEY_bits(pkey) <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
-            al = SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
-            goto f_err;
-        }
-
-        s->s3->peer_rsa_tmp = rsa;
-        rsa = NULL;
     }
-#else                           /* OPENSSL_NO_RSA */
-    if (0) ;
-#endif
+#endif                          /* !OPENSSL_NO_SRP */
 #ifndef OPENSSL_NO_DH
     else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
         PACKET prime, generator, pub_key;
@@ -1740,12 +1695,12 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
         if (!PACKET_get_length_prefixed_2(pkt, &prime)
             || !PACKET_get_length_prefixed_2(pkt, &generator)
             || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
         if ((dh = DH_new()) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_DH_LIB);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_DH_LIB);
             goto err;
         }
 
@@ -1756,12 +1711,12 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             || (dh->pub_key =
                 BN_bin2bn(PACKET_data(&pub_key),
                           PACKET_remaining(&pub_key), NULL)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
 
         if (BN_is_zero(dh->p) || BN_is_zero(dh->g) || BN_is_zero(dh->pub_key)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
             goto f_err;
         }
 
@@ -1797,7 +1752,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
          * ECParameters in this case is just three bytes.
          */
         if (!PACKET_get_bytes(pkt, &ecparams, 3)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
         /*
@@ -1805,7 +1760,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
          * invalid curve. ECParameters is 3 bytes.
          */
         if (!tls1_check_curve(s, ecparams, 3)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_WRONG_CURVE);
             goto f_err;
         }
 
@@ -1829,14 +1784,6 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 
         group = EC_KEY_get0_group(ecdh);
 
-        if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
-            (EC_GROUP_get_degree(group) > 163)) {
-            al = SSL_AD_EXPORT_RESTRICTION;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE,
-                   SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
-            goto f_err;
-        }
-
         /* Next, get the encoded ECPoint */
         if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
             ((bn_ctx = BN_CTX_new()) == NULL)) {
@@ -1845,13 +1792,13 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
         }
 
         if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
         if (EC_POINT_oct2point(group, srvr_ecpoint, PACKET_data(&encoded_pt),
                                PACKET_remaining(&encoded_pt), bn_ctx) == 0) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
             goto f_err;
         }
 
@@ -1895,7 +1842,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
                                    PACKET_remaining(&save_param_start) -
                                    PACKET_remaining(pkt))) {
             al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
             goto f_err;
         }
 
@@ -1903,7 +1850,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             unsigned char *sigalgs;
             int rv;
             if (!PACKET_get_bytes(pkt, &sigalgs, 2)) {
-                SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
                 goto f_err;
             }
             rv = tls12_check_peer_sigalg(&md, s, sigalgs, pkey);
@@ -1915,13 +1862,15 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 #ifdef SSL_DEBUG
             fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
+        } else if (pkey->type == EVP_PKEY_RSA) {
+            md = EVP_md5_sha1();
         } else {
             md = EVP_sha1();
         }
 
         if (!PACKET_get_length_prefixed_2(pkt, &signature)
             || PACKET_remaining(pkt) != 0) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
         j = EVP_PKEY_size(pkey);
@@ -1938,58 +1887,23 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_WRONG_SIGNATURE_LENGTH);
             goto f_err;
         }
-#ifndef OPENSSL_NO_RSA
-        if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) {
-            int num;
-            unsigned int size;
-
-            j = 0;
-            q = md_buf;
-            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, PACKET_data(&params),
-                                 PACKET_remaining(&params));
-                EVP_DigestFinal_ex(&md_ctx, q, &size);
-                q += size;
-                j += size;
-            }
-            verify_ret =
-                RSA_verify(NID_md5_sha1, md_buf, j, PACKET_data(&signature),
-                           PACKET_remaining(&signature), pkey->pkey.rsa);
-            if (verify_ret < 0) {
-                al = SSL_AD_DECRYPT_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_RSA_DECRYPT);
-                goto f_err;
-            }
-            if (verify_ret == 0) {
-                /* bad signature */
-                al = SSL_AD_DECRYPT_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
-                goto f_err;
-            }
-        } else
-#endif
-        {
-            EVP_VerifyInit_ex(&md_ctx, md, NULL);
-            EVP_VerifyUpdate(&md_ctx, &(s->s3->client_random[0]),
-                             SSL3_RANDOM_SIZE);
-            EVP_VerifyUpdate(&md_ctx, &(s->s3->server_random[0]),
-                             SSL3_RANDOM_SIZE);
-            EVP_VerifyUpdate(&md_ctx, PACKET_data(&params),
-                             PACKET_remaining(&params));
-            if (EVP_VerifyFinal(&md_ctx, PACKET_data(&signature),
-                                PACKET_remaining(&signature), pkey) <= 0) {
-                /* bad signature */
-                al = SSL_AD_DECRYPT_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
-                goto f_err;
-            }
+        if (EVP_VerifyInit_ex(md_ctx, md, NULL) <= 0
+                || EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]),
+                                    SSL3_RANDOM_SIZE) <= 0
+                || EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]),
+                                    SSL3_RANDOM_SIZE) <= 0
+                || EVP_VerifyUpdate(md_ctx, PACKET_data(&params),
+                                    PACKET_remaining(&params)) <= 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+            goto f_err;
+        }
+        if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature),
+                            PACKET_remaining(&signature), pkey) <= 0) {
+            /* bad signature */
+            al = SSL_AD_DECRYPT_ERROR;
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
+            goto f_err;
         }
     } else {
         /* aNULL, aSRP or PSK do not need public keys */
@@ -2007,7 +1921,7 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
         }
     }
     EVP_PKEY_free(pkey);
-    EVP_MD_CTX_cleanup(&md_ctx);
+    EVP_MD_CTX_free(md_ctx);
     return MSG_PROCESS_CONTINUE_READING;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
@@ -2024,12 +1938,12 @@ enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
     EC_POINT_free(srvr_ecpoint);
     EC_KEY_free(ecdh);
 #endif
-    EVP_MD_CTX_cleanup(&md_ctx);
-    statem_set_error(s);
+    EVP_MD_CTX_free(md_ctx);
+    ossl_statem_set_error(s);
     return MSG_PROCESS_ERROR;
 }
 
-enum MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
 {
     int ret = MSG_PROCESS_ERROR;
     unsigned int list_len, ctype_num, i, name_len;
@@ -2091,6 +2005,8 @@ enum MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
             SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
             goto err;
         }
+    } else {
+        ssl_set_default_md(s);
     }
 
     /* get the CA RDNs */
@@ -2141,7 +2057,7 @@ enum MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
     ret = MSG_PROCESS_CONTINUE_READING;
     goto done;
  err:
-    statem_set_error(s);
+    ossl_statem_set_error(s);
  done:
     sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
     return ret;
@@ -2152,7 +2068,7 @@ static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
     return (X509_NAME_cmp(*a, *b));
 }
 
-enum MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
 {
     int al;
     unsigned int ticklen;
@@ -2162,13 +2078,13 @@ enum MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
             || !PACKET_get_net_2(pkt, &ticklen)
             || PACKET_remaining(pkt) != ticklen) {
         al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+        SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
         goto f_err;
     }
 
     /* Server is allowed to change its mind and send an empty ticket. */
     if (ticklen == 0)
-        return 1;
+        return MSG_PROCESS_CONTINUE_READING;
 
     if (s->session->session_id_length > 0) {
         int i = s->session_ctx->session_cache_mode;
@@ -2205,7 +2121,7 @@ enum MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
     s->session->tlsext_ticklen = 0;
 
     s->session->tlsext_tick = OPENSSL_malloc(ticklen);
-    if (!s->session->tlsext_tick) {
+    if (s->session->tlsext_tick == NULL) {
         SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
         goto err;
     }
@@ -2235,11 +2151,11 @@ enum MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
  err:
-    statem_set_error(s);
+    ossl_statem_set_error(s);
     return MSG_PROCESS_ERROR;
 }
 
-enum MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
 {
     int al;
     unsigned long resplen;
@@ -2259,7 +2175,7 @@ enum MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
     }
     OPENSSL_free(s->tlsext_ocsp_resp);
     s->tlsext_ocsp_resp = OPENSSL_malloc(resplen);
-    if (!s->tlsext_ocsp_resp) {
+    if (s->tlsext_ocsp_resp == NULL) {
         al = SSL_AD_INTERNAL_ERROR;
         SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, ERR_R_MALLOC_FAILURE);
         goto f_err;
@@ -2287,17 +2203,17 @@ enum MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
     return MSG_PROCESS_CONTINUE_READING;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    statem_set_error(s);
+    ossl_statem_set_error(s);
     return MSG_PROCESS_ERROR;
 }
 
-enum MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
+MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
 {
     if (PACKET_remaining(pkt) > 0) {
         /* should contain no data */
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
         SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_LENGTH_MISMATCH);
-        statem_set_error(s);
+        ossl_statem_set_error(s);
         return MSG_PROCESS_ERROR;
     }
 
@@ -2306,12 +2222,22 @@ enum MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
         if (SRP_Calc_A_param(s) <= 0) {
             SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_SRP_A_CALC);
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-            statem_set_error(s);
+            ossl_statem_set_error(s);
             return MSG_PROCESS_ERROR;
         }
     }
 #endif
 
+    /*
+     * at this point we check that we have the required stuff from
+     * the server
+     */
+    if (!ssl3_check_cert_and_algorithm(s)) {
+        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+        ossl_statem_set_error(s);
+        return MSG_PROCESS_ERROR;
+    }
+
 #ifndef OPENSSL_NO_SCTP
     /* Only applies to renegotiation */
     if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))
@@ -2433,7 +2359,7 @@ psk_err:
         RSA *rsa;
         pmslen = SSL_MAX_MASTER_KEY_LENGTH;
         pms = OPENSSL_malloc(pmslen);
-        if (!pms)
+        if (pms == NULL)
             goto memerr;
 
         if (s->session->peer == NULL) {
@@ -2445,20 +2371,16 @@ psk_err:
             goto err;
         }
 
-        if (s->s3->peer_rsa_tmp != NULL)
-            rsa = s->s3->peer_rsa_tmp;
-        else {
-            pkey = X509_get_pubkey(s->session->peer);
-            if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA)
-                || (pkey->pkey.rsa == NULL)) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
-                       ERR_R_INTERNAL_ERROR);
-                EVP_PKEY_free(pkey);
-                goto err;
-            }
-            rsa = pkey->pkey.rsa;
+        pkey = X509_get_pubkey(s->session->peer);
+        if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA)
+            || (pkey->pkey.rsa == NULL)) {
+            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
+                   ERR_R_INTERNAL_ERROR);
             EVP_PKEY_free(pkey);
+            goto err;
         }
+        rsa = pkey->pkey.rsa;
+        EVP_PKEY_free(pkey);
 
         pms[0] = s->client_version >> 8;
         pms[1] = s->client_version & 0xff;
@@ -2535,7 +2457,7 @@ psk_err:
 
         pmslen = DH_size(dh_clnt);
         pms = OPENSSL_malloc(pmslen);
-        if (!pms)
+        if (pms == NULL)
             goto memerr;
 
         /*
@@ -2675,7 +2597,7 @@ psk_err:
         }
         pmslen = (field_size + 7) / 8;
         pms = OPENSSL_malloc(pmslen);
-        if (!pms)
+        if (pms == NULL)
             goto memerr;
         n = ECDH_compute_key(pms, pmslen, srvr_ecpoint, clnt_ecdh, NULL);
         if (n <= 0 || pmslen != (size_t)n) {
@@ -2728,6 +2650,7 @@ psk_err:
         EVP_PKEY_free(srvr_pub_pkey);
     }
 #endif                          /* !OPENSSL_NO_EC */
+#ifndef OPENSSL_NO_GOST
     else if (alg_k & SSL_kGOST) {
         /* GOST key exchange message creation */
         EVP_PKEY_CTX *pkey_ctx;
@@ -2737,10 +2660,14 @@ psk_err:
         unsigned char shared_ukm[32], tmp[256];
         EVP_MD_CTX *ukm_hash;
         EVP_PKEY *pub_key;
+        int dgst_nid = NID_id_GostR3411_94;
+        if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
+            dgst_nid = NID_id_GostR3411_2012_256;
+
 
         pmslen = 32;
         pms = OPENSSL_malloc(pmslen);
-        if (!pms)
+        if (pms == NULL)
             goto memerr;
 
         /*
@@ -2755,18 +2682,23 @@ psk_err:
 
         pkey_ctx = EVP_PKEY_CTX_new(pub_key =
                                     X509_get_pubkey(peer_cert), NULL);
+        if (pkey_ctx == NULL) {
+            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
+                   ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
         /*
          * If we have send a certificate, and certificate key
-         *
-         * * parameters match those of server certificate, use
+         * parameters match those of server certificate, use
          * certificate key for key exchange
          */
 
         /* Otherwise, generate ephemeral key pair */
 
-        EVP_PKEY_encrypt_init(pkey_ctx);
-        /* Generate session key */
-        if (RAND_bytes(pms, pmslen) <= 0) {
+        if (pkey_ctx == NULL
+                || EVP_PKEY_encrypt_init(pkey_ctx) <= 0
+                /* Generate session key */
+                || RAND_bytes(pms, pmslen) <= 0) {
             EVP_PKEY_CTX_free(pkey_ctx);
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
@@ -2789,15 +2721,20 @@ psk_err:
          * Compute shared IV and store it in algorithm-specific context
          * data
          */
-        ukm_hash = EVP_MD_CTX_create();
-        EVP_DigestInit(ukm_hash,
-                       EVP_get_digestbynid(NID_id_GostR3411_94));
-        EVP_DigestUpdate(ukm_hash, s->s3->client_random,
-                         SSL3_RANDOM_SIZE);
-        EVP_DigestUpdate(ukm_hash, s->s3->server_random,
-                         SSL3_RANDOM_SIZE);
-        EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
-        EVP_MD_CTX_destroy(ukm_hash);
+        ukm_hash = EVP_MD_CTX_new();
+        if (EVP_DigestInit(ukm_hash,
+                           EVP_get_digestbynid(dgst_nid)) <= 0
+                || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
+                                    SSL3_RANDOM_SIZE) <= 0
+                || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
+                                    SSL3_RANDOM_SIZE) <= 0
+                || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
+            EVP_MD_CTX_free(ukm_hash);
+            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
+                   ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
+        EVP_MD_CTX_free(ukm_hash);
         if (EVP_PKEY_CTX_ctrl
             (pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8,
              shared_ukm) < 0) {
@@ -2811,7 +2748,7 @@ psk_err:
          */
         *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
         msglen = 255;
-        if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) < 0) {
+        if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
                    SSL_R_LIBRARY_BUG);
             goto err;
@@ -2835,6 +2772,7 @@ psk_err:
         EVP_PKEY_free(pub_key);
 
     }
+#endif
 #ifndef OPENSSL_NO_SRP
     else if (alg_k & SSL_kSRP) {
         if (s->srp_ctx.A != NULL) {
@@ -2893,7 +2831,7 @@ psk_err:
     OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
     s->s3->tmp.psk = NULL;
 #endif
-    statem_set_error(s);
+    ossl_statem_set_error(s);
     return 0;
 }
 
@@ -2936,8 +2874,8 @@ int tls_client_key_exchange_post_work(SSL *s)
          * 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,
@@ -2959,129 +2897,71 @@ int tls_client_key_exchange_post_work(SSL *s)
 int tls_construct_client_verify(SSL *s)
 {
     unsigned char *p;
-    unsigned char data[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH];
     EVP_PKEY *pkey;
-    EVP_PKEY_CTX *pctx = NULL;
-    EVP_MD_CTX mctx;
+    const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
+    EVP_MD_CTX *mctx;
     unsigned u = 0;
-    unsigned long n;
-    int j;
+    unsigned long n = 0;
+    long hdatalen = 0;
+    void *hdata;
 
-    EVP_MD_CTX_init(&mctx);
+    mctx = EVP_MD_CTX_new();
+    if (mctx == NULL) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
 
     p = ssl_handshake_start(s);
     pkey = s->cert->key->privatekey;
-/* Create context from key and test if sha1 is allowed as digest */
-    pctx = EVP_PKEY_CTX_new(pkey, NULL);
-    EVP_PKEY_sign_init(pctx);
-    if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1()) > 0) {
-        if (!SSL_USE_SIGALGS(s))
-            s->method->ssl3_enc->cert_verify_mac(s,
-                                                 NID_sha1,
-                                                 &(data
-                                                   [MD5_DIGEST_LENGTH]));
-    } else {
-        ERR_clear_error();
+
+    hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+    if (hdatalen <= 0) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+        goto err;
     }
-    /*
-     * For TLS v1.2 send signature algorithm and signature using agreed
-     * digest and cached handshake records.
-     */
     if (SSL_USE_SIGALGS(s)) {
-        long hdatalen = 0;
-        void *hdata;
-        const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
-        hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
-        if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md)) {
+        if (!tls12_get_sigandhash(p, pkey, md)) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
             goto err;
         }
         p += 2;
+        n = 2;
+    }
 #ifdef SSL_DEBUG
-        fprintf(stderr, "Using TLS 1.2 with client alg %s\n",
-                EVP_MD_name(md));
-#endif
-        if (!EVP_SignInit_ex(&mctx, md, NULL)
-            || !EVP_SignUpdate(&mctx, hdata, hdatalen)
-            || !EVP_SignFinal(&mctx, p + 2, &u, pkey)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_EVP_LIB);
-            goto err;
-        }
-        s2n(u, p);
-        n = u + 4;
-        /* Digest cached records and discard handshake buffer */
-        if (!ssl3_digest_cached_records(s, 0))
-            goto err;
-    } else
-#ifndef OPENSSL_NO_RSA
-    if (pkey->type == EVP_PKEY_RSA) {
-        s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(data[0]));
-        if (RSA_sign(NID_md5_sha1, data,
-                     MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
-                     &(p[2]), &u, pkey->pkey.rsa) <= 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_RSA_LIB);
-            goto err;
-        }
-        s2n(u, p);
-        n = u + 2;
-    } else
-#endif
-#ifndef OPENSSL_NO_DSA
-    if (pkey->type == EVP_PKEY_DSA) {
-        if (!DSA_sign(pkey->save_type,
-                      &(data[MD5_DIGEST_LENGTH]),
-                      SHA_DIGEST_LENGTH, &(p[2]),
-                      (unsigned int *)&j, pkey->pkey.dsa)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_DSA_LIB);
-            goto err;
-        }
-        s2n(j, p);
-        n = j + 2;
-    } else
-#endif
-#ifndef OPENSSL_NO_EC
-    if (pkey->type == EVP_PKEY_EC) {
-        if (!ECDSA_sign(pkey->save_type,
-                        &(data[MD5_DIGEST_LENGTH]),
-                        SHA_DIGEST_LENGTH, &(p[2]),
-                        (unsigned int *)&j, pkey->pkey.ec)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_ECDSA_LIB);
-            goto err;
-        }
-        s2n(j, p);
-        n = j + 2;
-    } else
-#endif
-    if (pkey->type == NID_id_GostR3410_2001) {
-        unsigned char signbuf[64];
-        int i;
-        size_t sigsize = 64;
-        s->method->ssl3_enc->cert_verify_mac(s,
-                                             NID_id_GostR3411_94, data);
-        if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
-            goto err;
-        }
-        for (i = 63, j = 0; i >= 0; j++, i--) {
-            p[2 + j] = signbuf[i];
-        }
-        s2n(j, p);
-        n = j + 2;
-    } else {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+    fprintf(stderr, "Using client alg %s\n", EVP_MD_name(md));
+#endif
+    if (!EVP_SignInit_ex(mctx, md, NULL)
+        || !EVP_SignUpdate(mctx, hdata, hdatalen)
+        || (s->version == SSL3_VERSION
+            && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+                                s->session->master_key_length,
+                                s->session->master_key))
+        || !EVP_SignFinal(mctx, p + 2, &u, pkey)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_EVP_LIB);
         goto err;
     }
+#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(p + 2, NULL, u);
+    }
+#endif
+
+    s2n(u, p);
+    n += u + 2;
+    /* Digest cached records and discard handshake buffer */
+    if (!ssl3_digest_cached_records(s, 0))
+        goto err;
     if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
-    EVP_MD_CTX_cleanup(&mctx);
-    EVP_PKEY_CTX_free(pctx);
+    EVP_MD_CTX_free(mctx);
     return 1;
  err:
-    EVP_MD_CTX_cleanup(&mctx);
-    EVP_PKEY_CTX_free(pctx);
+    EVP_MD_CTX_free(mctx);
     return 0;
 }
 
@@ -3128,7 +3008,7 @@ static int ssl3_check_client_certificate(SSL *s)
     return 1;
 }
 
-enum WORK_STATE tls_prepare_client_certificate(SSL *s, enum WORK_STATE wst)
+WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
 {
     X509 *x509 = NULL;
     EVP_PKEY *pkey = NULL;
@@ -3144,7 +3024,7 @@ enum WORK_STATE tls_prepare_client_certificate(SSL *s, enum WORK_STATE wst)
             }
             if (i == 0) {
                 ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-                statem_set_error(s);
+                ossl_statem_set_error(s);
                 return 0;
             }
             s->rwstate = SSL_NOTHING;
@@ -3190,7 +3070,7 @@ enum WORK_STATE tls_prepare_client_certificate(SSL *s, enum WORK_STATE wst)
                 s->s3->tmp.cert_req = 2;
                 if (!ssl3_digest_cached_records(s, 0)) {
                     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-                    statem_set_error(s);
+                    ossl_statem_set_error(s);
                     return 0;
                 }
             }
@@ -3210,7 +3090,7 @@ int tls_construct_client_certificate(SSL *s)
                                  2) ? NULL : s->cert->key)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        statem_set_error(s);
+        ossl_statem_set_error(s);
         return 0;
     }
 
@@ -3221,13 +3101,12 @@ int tls_construct_client_certificate(SSL *s)
 
 int ssl3_check_cert_and_algorithm(SSL *s)
 {
-    int i, idx;
+    int i;
+#ifndef OPENSSL_NO_EC
+    int idx;
+#endif
     long alg_k, alg_a;
     EVP_PKEY *pkey = NULL;
-    int pkey_bits;
-#ifndef OPENSSL_NO_RSA
-    RSA *rsa;
-#endif
 #ifndef OPENSSL_NO_DH
     DH *dh;
 #endif
@@ -3239,17 +3118,14 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     /* we don't have a certificate */
     if ((alg_a & SSL_aNULL) || (alg_k & SSL_kPSK))
         return (1);
-#ifndef OPENSSL_NO_RSA
-    rsa = s->s3->peer_rsa_tmp;
-#endif
 #ifndef OPENSSL_NO_DH
     dh = s->s3->peer_dh_tmp;
 #endif
 
     /* This is the passed certificate */
 
-    idx = s->session->peer_type;
 #ifndef OPENSSL_NO_EC
+    idx = s->session->peer_type;
     if (idx == SSL_PKEY_ECC) {
         if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s) == 0) {
             /* check failed */
@@ -3268,7 +3144,6 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     }
 #endif
     pkey = X509_get_pubkey(s->session->peer);
-    pkey_bits = EVP_PKEY_bits(pkey);
     i = X509_certificate_type(s->session->peer, pkey);
     EVP_PKEY_free(pkey);
 
@@ -3286,27 +3161,11 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     }
 #endif
 #ifndef OPENSSL_NO_RSA
-    if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
-        if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
-            !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
-            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-                   SSL_R_MISSING_RSA_ENCRYPTING_CERT);
-            goto f_err;
-        } else if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) {
-            if (pkey_bits <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
-                if (!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
-                    SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-                           SSL_R_MISSING_RSA_ENCRYPTING_CERT);
-                    goto f_err;
-                }
-                if (rsa != NULL) {
-                    /* server key exchange is not allowed. */
-                    al = SSL_AD_INTERNAL_ERROR;
-                    SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
-                    goto f_err;
-                }
-            }
-        }
+    if (alg_k & (SSL_kRSA | SSL_kRSAPSK) &&
+        !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+               SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+        goto f_err;
     }
 #endif
 #ifndef OPENSSL_NO_DH
@@ -3330,48 +3189,6 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 # endif
 #endif
 
-    if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
-        pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
-#ifndef OPENSSL_NO_RSA
-        if (alg_k & SSL_kRSA) {
-            if (rsa == NULL) {
-                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-                       SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
-                goto f_err;
-            } else if (RSA_bits(rsa) >
-                SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
-                /* We have a temporary RSA key but it's too large. */
-                al = SSL_AD_EXPORT_RESTRICTION;
-                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-                       SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
-                goto f_err;
-            }
-        } else
-#endif
-#ifndef OPENSSL_NO_DH
-        if (alg_k & SSL_kDHE) {
-            if (DH_bits(dh) >
-                SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
-                /* We have a temporary DH key but it's too large. */
-                al = SSL_AD_EXPORT_RESTRICTION;
-                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-                       SSL_R_MISSING_EXPORT_TMP_DH_KEY);
-                goto f_err;
-            }
-        } else if (alg_k & (SSL_kDHr | SSL_kDHd)) {
-            /* The cert should have had an export DH key. */
-            al = SSL_AD_EXPORT_RESTRICTION;
-            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-                   SSL_R_MISSING_EXPORT_TMP_DH_KEY);
-                goto f_err;
-        } else
-#endif
-        {
-            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-                   SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
-            goto f_err;
-        }
-    }
     return (1);
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);