Fix travis mixed declarations and code error
[openssl.git] / ssl / statem / extensions_srvr.c
index 38a6bef8627dd1097840263dba43e5b02a0cd24a..370d0b9b02800b44fb2f74d99c7e85d15c3c44cf 100644 (file)
@@ -14,7 +14,7 @@
 /*
  * Parse the client's renegotiation binding and abort if it's not right
  */
-int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_renegotiate(SSL *s, PACKET *pkt, int *al)
 {
     unsigned int ilen;
     const unsigned char *data;
@@ -22,7 +22,7 @@ int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al)
     /* Parse the length byte */
     if (!PACKET_get_1(pkt, &ilen)
         || !PACKET_get_bytes(pkt, &data, ilen)) {
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_RENEGOTIATE,
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_RENEGOTIATE,
                SSL_R_RENEGOTIATION_ENCODING_ERR);
         *al = SSL_AD_ILLEGAL_PARAMETER;
         return 0;
@@ -30,7 +30,7 @@ int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al)
 
     /* Check that the extension matches */
     if (ilen != s->s3->previous_client_finished_len) {
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_RENEGOTIATE,
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_RENEGOTIATE,
                SSL_R_RENEGOTIATION_MISMATCH);
         *al = SSL_AD_HANDSHAKE_FAILURE;
         return 0;
@@ -38,7 +38,7 @@ int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al)
 
     if (memcmp(data, s->s3->previous_client_finished,
                s->s3->previous_client_finished_len)) {
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_RENEGOTIATE,
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_RENEGOTIATE,
                SSL_R_RENEGOTIATION_MISMATCH);
         *al = SSL_AD_HANDSHAKE_FAILURE;
         return 0;
@@ -49,7 +49,7 @@ int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al)
     return 1;
 }
 
-int tls_parse_clienthello_server_name(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_server_name(SSL *s, PACKET *pkt, int *al)
 {
     unsigned int servname_type;
     PACKET sni, hostname;
@@ -135,7 +135,7 @@ int tls_parse_clienthello_server_name(SSL *s, PACKET *pkt, int *al)
 }
 
 #ifndef OPENSSL_NO_SRP
-int tls_parse_clienthello_srp(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_srp(SSL *s, PACKET *pkt, int *al)
 {
     PACKET srp_I;
 
@@ -159,7 +159,7 @@ int tls_parse_clienthello_srp(SSL *s, PACKET *pkt, int *al)
 #endif
 
 #ifndef OPENSSL_NO_EC
-int tls_parse_clienthello_ec_pt_formats(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_ec_pt_formats(SSL *s, PACKET *pkt, int *al)
 {
     PACKET ec_point_format_list;
 
@@ -182,7 +182,7 @@ int tls_parse_clienthello_ec_pt_formats(SSL *s, PACKET *pkt, int *al)
 }
 #endif                          /* OPENSSL_NO_EC */
 
-int tls_parse_clienthello_session_ticket(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_session_ticket(SSL *s, PACKET *pkt, int *al)
 {
     if (s->tls_session_ticket_ext_cb &&
             !s->tls_session_ticket_ext_cb(s, PACKET_data(pkt),
@@ -195,7 +195,7 @@ int tls_parse_clienthello_session_ticket(SSL *s, PACKET *pkt, int *al)
     return 1;
 }
 
-int tls_parse_clienthello_sig_algs(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_sig_algs(SSL *s, PACKET *pkt, int *al)
 {
     PACKET supported_sig_algs;
 
@@ -215,13 +215,14 @@ int tls_parse_clienthello_sig_algs(SSL *s, PACKET *pkt, int *al)
     return 1;
 }
 
-int tls_parse_clienthello_status_request(SSL *s, PACKET *pkt, int *al)
+#ifndef OPENSSL_NO_OCSP
+int tls_parse_client_status_request(SSL *s, PACKET *pkt, int *al)
 {
     if (!PACKET_get_1(pkt, (unsigned int *)&s->tlsext_status_type)) {
         *al = SSL_AD_DECODE_ERROR;
         return 0;
     }
-#ifndef OPENSSL_NO_OCSP
+
     if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
         const unsigned char *ext_data;
         PACKET responder_id_list, exts;
@@ -297,9 +298,7 @@ int tls_parse_clienthello_status_request(SSL *s, PACKET *pkt, int *al)
                 return 0;
             }
         }
-    } else
-#endif
-    {
+    } else {
         /*
          * We don't know what to do with any other type so ignore it.
          */
@@ -308,9 +307,10 @@ int tls_parse_clienthello_status_request(SSL *s, PACKET *pkt, int *al)
 
     return 1;
 }
+#endif
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
-int tls_parse_clienthello_npn(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_npn(SSL *s, PACKET *pkt, int *al)
 {
     if (s->s3->tmp.finish_md_len == 0) {
         /*-
@@ -343,7 +343,7 @@ int tls_parse_clienthello_npn(SSL *s, PACKET *pkt, int *al)
  * al: a pointer to the  alert value to send in the event of a failure.
  * returns: 1 on success, 0 on error.
  */
-int tls_parse_clienthello_alpn(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_alpn(SSL *s, PACKET *pkt, int *al)
 {
     PACKET protocol_list, save_protocol_list, protocol;
 
@@ -376,7 +376,7 @@ int tls_parse_clienthello_alpn(SSL *s, PACKET *pkt, int *al)
 }
 
 #ifndef OPENSSL_NO_SRTP
-int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_use_srtp(SSL *s, PACKET *pkt, int *al)
 {
     SRTP_PROTECTION_PROFILE *sprof;
     STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
@@ -391,7 +391,7 @@ int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al)
     /* Pull off the length of the cipher suite list  and check it is even */
     if (!PACKET_get_net_2(pkt, &ct)
         || (ct & 1) != 0 || !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP,
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_USE_SRTP,
                SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
         *al = SSL_AD_DECODE_ERROR;
         return 0;
@@ -404,7 +404,7 @@ int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al)
 
     while (PACKET_remaining(&subpkt)) {
         if (!PACKET_get_net_2(&subpkt, &id)) {
-            SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP,
+            SSLerr(SSL_F_TLS_PARSE_CLIENT_USE_SRTP,
                    SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
             *al = SSL_AD_DECODE_ERROR;
             return 0;
@@ -430,7 +430,7 @@ int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al)
      * Now extract the MKI value as a sanity check, but discard it for now
      */
     if (!PACKET_get_1(pkt, &mki_len)) {
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP,
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_USE_SRTP,
                SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
         *al = SSL_AD_DECODE_ERROR;
         return 0;
@@ -438,7 +438,7 @@ int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al)
 
     if (!PACKET_forward(pkt, mki_len)
         || PACKET_remaining(pkt)) {
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP, SSL_R_BAD_SRTP_MKI_VALUE);
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_USE_SRTP, SSL_R_BAD_SRTP_MKI_VALUE);
         *al = SSL_AD_DECODE_ERROR;
         return 0;
     }
@@ -447,7 +447,7 @@ int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al)
 }
 #endif
 
-int tls_parse_clienthello_etm(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_etm(SSL *s, PACKET *pkt, int *al)
 {
     if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
         s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
@@ -489,7 +489,7 @@ static int check_in_list(SSL *s, unsigned int group_id,
  * the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
  * If a failure occurs then |*al| is set to an appropriate alert value.
  */
-int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_key_share(SSL *s, PACKET *pkt, int *al)
 {
     unsigned int group_id;
     PACKET key_share_list, encoded_pt;
@@ -504,27 +504,31 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
     /* Sanity check */
     if (s->s3->peer_tmp != NULL) {
         *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
         *al = SSL_AD_HANDSHAKE_FAILURE;
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, SSL_R_LENGTH_MISMATCH);
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
     /* Get our list of supported curves */
     if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) {
         *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
-    /* Get the clients list of supported curves */
+    /*
+     * Get the clients list of supported curves.
+     * TODO(TLS1.3): We should validate that we actually received
+     * supported_groups!
+     */
     if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) {
         *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -533,7 +537,7 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
                 || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt)
                 || PACKET_remaining(&encoded_pt) == 0) {
             *al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE,
+            SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE,
                    SSL_R_LENGTH_MISMATCH);
             return 0;
         }
@@ -548,7 +552,7 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
         /* Check if this share is in supported_groups sent from client */
         if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) {
             *al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+            SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
             return 0;
         }
 
@@ -562,7 +566,7 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
 
         if (group_nid == 0) {
             *al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE,
+            SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE,
                    SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
             return 0;
         }
@@ -573,7 +577,7 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
 
             if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) {
                 *al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, ERR_R_EVP_LIB);
+                SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, ERR_R_EVP_LIB);
                 EVP_PKEY_free(key);
                 return 0;
             }
@@ -587,7 +591,7 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
                                                               group_nid) <= 0
                     || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
                 *al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, ERR_R_EVP_LIB);
+                SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, ERR_R_EVP_LIB);
                 EVP_PKEY_CTX_free(pctx);
                 return 0;
             }
@@ -600,7 +604,7 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
                 PACKET_data(&encoded_pt),
                 PACKET_remaining(&encoded_pt))) {
             *al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, SSL_R_BAD_ECPOINT);
+            SSLerr(SSL_F_TLS_PARSE_CLIENT_KEY_SHARE, SSL_R_BAD_ECPOINT);
             return 0;
         }
 
@@ -611,7 +615,7 @@ int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al)
 }
 
 #ifndef OPENSSL_NO_EC
-int tls_parse_clienthello_supported_groups(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_supported_groups(SSL *s, PACKET *pkt, int *al)
 {
     PACKET supported_groups_list;
 
@@ -635,7 +639,7 @@ int tls_parse_clienthello_supported_groups(SSL *s, PACKET *pkt, int *al)
 }
 #endif
 
-int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al)
+int tls_parse_client_ems(SSL *s, PACKET *pkt, int *al)
 {
     /* The extension must always be empty */
     if (PACKET_remaining(pkt) != 0) {
@@ -647,3 +651,286 @@ int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al)
 
     return 1;
 }
+
+/* Add the server's renegotiation binding */
+int tls_construct_server_renegotiate(SSL *s, WPACKET *pkt, int *al)
+{
+    if (!s->s3->send_connection_binding)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_start_sub_packet_u8(pkt)
+            || !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
+                               s->s3->previous_client_finished_len)
+            || !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
+                               s->s3->previous_server_finished_len)
+            || !WPACKET_close(pkt)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_RENEGOTIATE, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
+int tls_construct_server_server_name(SSL *s, WPACKET *pkt, int *al)
+{
+    if (s->hit || s->servername_done != 1
+            || s->session->tlsext_hostname == NULL)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
+            || !WPACKET_put_bytes_u16(pkt, 0)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_SERVER_NAME, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+int tls_construct_server_ec_pt_formats(SSL *s, WPACKET *pkt, int *al)
+{
+    unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+    unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+    int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))
+                    && (s->session->tlsext_ecpointformatlist != NULL);
+    const unsigned char *plist;
+    size_t plistlen;
+
+    if (!using_ecc)
+        return 1;
+
+    tls1_get_formatlist(s, &plist, &plistlen);
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+#endif
+
+int tls_construct_server_session_ticket(SSL *s, WPACKET *pkt, int *al)
+{
+    if (!s->tlsext_ticket_expected || !tls_use_ticket(s)) {
+        s->tlsext_ticket_expected = 0;
+        return 1;
+    }
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
+            || !WPACKET_put_bytes_u16(pkt, 0)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
+#ifndef OPENSSL_NO_OCSP
+int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al)
+{
+    if (!s->tlsext_status_expected)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
+            || !WPACKET_put_bytes_u16(pkt, 0)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+#endif
+
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+int tls_construct_server_next_proto_neg(SSL *s, WPACKET *pkt, int *al)
+{
+    const unsigned char *npa;
+    unsigned int npalen;
+    int ret;
+    int next_proto_neg_seen = s->s3->next_proto_neg_seen;
+
+    s->s3->next_proto_neg_seen = 0;
+    if (!next_proto_neg_seen || s->ctx->next_protos_advertised_cb == NULL)
+        return 1;
+
+    ret = s->ctx->next_protos_advertised_cb(s, &npa, &npalen,
+                                      s->ctx->next_protos_advertised_cb_arg);
+    if (ret == SSL_TLSEXT_ERR_OK) {
+        if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
+                || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
+            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_NEXT_PROTO_NEG,
+                   ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
+        s->s3->next_proto_neg_seen = 1;
+    }
+
+    return 1;
+}
+#endif
+
+int tls_construct_server_alpn(SSL *s, WPACKET *pkt, int *al)
+{
+    if (s->s3->alpn_selected == NULL)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt,
+                TLSEXT_TYPE_application_layer_protocol_negotiation)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
+                                      s->s3->alpn_selected_len)
+            || !WPACKET_close(pkt)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_ALPN, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
+#ifndef OPENSSL_NO_SRTP
+int tls_construct_server_use_srtp(SSL *s, WPACKET *pkt, int *al)
+{
+    if (s->srtp_profile == NULL)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_put_bytes_u16(pkt, 2)
+            || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
+            || !WPACKET_put_bytes_u8(pkt, 0)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+#endif
+
+int tls_construct_server_etm(SSL *s, WPACKET *pkt, int *al)
+{
+    if ((s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) == 0)
+        return 1;
+
+    /*
+     * Don't use encrypt_then_mac if AEAD or RC4 might want to disable
+     * for other cases too.
+     */
+    if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
+        || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
+        || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
+        || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
+        s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
+        return 1;
+    }
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
+            || !WPACKET_put_bytes_u16(pkt, 0)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_ETM, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
+int tls_construct_server_ems(SSL *s, WPACKET *pkt, int *al)
+{
+    if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
+            || !WPACKET_put_bytes_u16(pkt, 0)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_EMS, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
+int tls_construct_server_key_share(SSL *s, WPACKET *pkt, int *al)
+{
+    unsigned char *encodedPoint;
+    size_t encoded_pt_len = 0;
+    EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
+
+    if (s->hit)
+        return 1;
+
+    if (ckey == NULL) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    skey = ssl_generate_pkey(ckey);
+    if (skey == NULL) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    /* Generate encoding of server key */
+    encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
+    if (encoded_pt_len == 0) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_EC_LIB);
+        EVP_PKEY_free(skey);
+        return 0;
+    }
+
+    if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        EVP_PKEY_free(skey);
+        OPENSSL_free(encodedPoint);
+        return 0;
+    }
+    OPENSSL_free(encodedPoint);
+
+    /* This causes the crypto state to be updated based on the derived keys */
+    s->s3->tmp.pkey = skey;
+    if (ssl_derive(s, skey, ckey, 1) == 0) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
+int tls_construct_server_cryptopro_bug(SSL *s, WPACKET *pkt, int *al)
+{
+    const unsigned char cryptopro_ext[36] = {
+        0xfd, 0xe8,         /* 65000 */
+        0x00, 0x20,         /* 32 bytes length */
+        0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
+        0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
+        0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
+        0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
+    };
+
+    if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
+         && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
+            || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
+        return 1;
+
+    if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}