[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Mon Oct 3 15:28:17 UTC 2016


The branch master has been updated
       via  b90506e995d44dee0ef4dd0324b56b59154256c2 (commit)
       via  a15c953f77b6df4044d495252c33e42bc3c960b8 (commit)
       via  6392fb8e2aa810d6c0e13e00a1c848ceacee33e1 (commit)
       via  229185e668514e17bce9b22c38303e3cc3c9eb7a (commit)
       via  4a01c59f3689db930d056c84f548d525f651cc6b (commit)
       via  5923ad4bbe5d13c2fcc11f7849594db838ea57bd (commit)
       via  7cea05dcc7f6f74a18d48102008d53ea9a42c297 (commit)
      from  b7c9aa645e4eddf5d198d2b20f1c6a74ab96f98e (commit)


- Log -----------------------------------------------------------------
commit b90506e995d44dee0ef4dd0324b56b59154256c2
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Oct 3 15:37:47 2016 +0100

    Fix linebreaks in the tls_construct_client_certificate function
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit a15c953f77b6df4044d495252c33e42bc3c960b8
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Oct 3 15:35:17 2016 +0100

    Add a typedef for the construction function
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 6392fb8e2aa810d6c0e13e00a1c848ceacee33e1
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Sep 30 11:17:57 2016 +0100

    Move setting of the handshake header up one more level
    
    We now set the handshake header, and close the packet directly in the
    write_state_machine. This is now possible because it is common for all
    messages.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 229185e668514e17bce9b22c38303e3cc3c9eb7a
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Sep 30 10:50:57 2016 +0100

    Remove the special case processing for finished construction
    
    tls_construct_finished() used to have different arguments to all of the
    other construction functions. It doesn't anymore, so there is no neeed to
    treat it as a special case.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 4a01c59f3689db930d056c84f548d525f651cc6b
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Sep 30 10:38:32 2016 +0100

    Harmonise setting the header and closing construction
    
    Ensure all message types work the same way including CCS so that the state
    machine doesn't need to know about special cases. Put all the special logic
    into ssl_set_handshake_header() and ssl_close_construct_packet().
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 5923ad4bbe5d13c2fcc11f7849594db838ea57bd
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Sep 30 00:27:40 2016 +0100

    Don't set the handshake header in every message
    
    Move setting the handshake header up a level into the state machine code
    in order to reduce boilerplate.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 7cea05dcc7f6f74a18d48102008d53ea9a42c297
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Sep 29 23:28:29 2016 +0100

    Move init of the WPACKET into write_state_machine()
    
    Instead of initialising, finishing and cleaning up the WPACKET in every
    message construction function, we should do it once in
    write_state_machine().
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 include/openssl/ssl.h    |   2 +
 ssl/s3_lib.c             |   4 +
 ssl/ssl_err.c            |   4 +
 ssl/ssl_locl.h           |  13 ++-
 ssl/statem/statem.c      |  21 +++-
 ssl/statem/statem_clnt.c | 226 +++++++++++++-----------------------
 ssl/statem/statem_dtls.c |  89 ++++++---------
 ssl/statem/statem_lib.c  |  72 ++++--------
 ssl/statem/statem_locl.h |  41 +++----
 ssl/statem/statem_srvr.c | 291 +++++++++++++++++------------------------------
 10 files changed, 298 insertions(+), 465 deletions(-)

diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 517716f..e0d82f2 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2078,7 +2078,9 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE               370
 # define SSL_F_DTLS_PROCESS_HELLO_VERIFY                  386
 # define SSL_F_OPENSSL_INIT_SSL                           342
+# define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE       430
 # define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION         417
+# define SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE       431
 # define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION         418
 # define SSL_F_READ_STATE_MACHINE                         352
 # define SSL_F_SSL3_CHANGE_CIPHER_STATE                   129
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 630c94d..d19b97a 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -2779,6 +2779,10 @@ const SSL_CIPHER *ssl3_get_cipher(unsigned int u)
 
 int ssl3_set_handshake_header(SSL *s, WPACKET *pkt, int htype)
 {
+    /* No header in the event of a CCS */
+    if (htype == SSL3_MT_CHANGE_CIPHER_SPEC)
+        return 1;
+
     /* Set the content type and 3 bytes for the message len */
     if (!WPACKET_put_bytes_u8(pkt, htype)
             || !WPACKET_start_sub_packet_u24(pkt))
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 9539e67..c1a886a 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -49,8 +49,12 @@ static ERR_STRING_DATA SSL_str_functs[] = {
      "dtls_get_reassembled_message"},
     {ERR_FUNC(SSL_F_DTLS_PROCESS_HELLO_VERIFY), "dtls_process_hello_verify"},
     {ERR_FUNC(SSL_F_OPENSSL_INIT_SSL), "OPENSSL_init_ssl"},
+    {ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE),
+     "ossl_statem_client_construct_message"},
     {ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION),
      "ossl_statem_client_read_transition"},
+    {ERR_FUNC(SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE),
+     "ossl_statem_server_construct_message"},
     {ERR_FUNC(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION),
      "ossl_statem_server_read_transition"},
     {ERR_FUNC(SSL_F_READ_STATE_MACHINE), "read_state_machine"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index eb29740..8a7e1a9 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1586,7 +1586,7 @@ typedef struct ssl3_enc_method {
     /* Set the handshake header */
     int (*set_handshake_header) (SSL *s, WPACKET *pkt, int type);
     /* Close construction of the handshake message */
-    int (*close_construct_packet) (SSL *s, WPACKET *pkt);
+    int (*close_construct_packet) (SSL *s, WPACKET *pkt, int htype);
     /* Write out handshake message */
     int (*do_write) (SSL *s);
 } SSL3_ENC_METHOD;
@@ -1596,8 +1596,8 @@ typedef struct ssl3_enc_method {
         (((unsigned char *)s->init_buf->data) + s->method->ssl3_enc->hhlen)
 # define ssl_set_handshake_header(s, pkt, htype) \
         s->method->ssl3_enc->set_handshake_header((s), (pkt), (htype))
-# define ssl_close_construct_packet(s, pkt) \
-        s->method->ssl3_enc->close_construct_packet((s), (pkt))
+# define ssl_close_construct_packet(s, pkt, htype) \
+        s->method->ssl3_enc->close_construct_packet((s), (pkt), (htype))
 # define ssl_do_write(s)  s->method->ssl3_enc->do_write(s)
 
 /* Values for enc_flags */
@@ -1879,7 +1879,8 @@ __owur int ssl3_final_finish_mac(SSL *s, const char *sender, int slen,
                                  unsigned char *p);
 __owur int ssl3_finish_mac(SSL *s, const unsigned char *buf, int len);
 void ssl3_free_digest_list(SSL *s);
-__owur unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk);
+__owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
+                                            CERT_PKEY *cpk);
 __owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
                                             STACK_OF(SSL_CIPHER) *clnt,
                                             STACK_OF(SSL_CIPHER) *srvr);
@@ -1900,9 +1901,9 @@ __owur int ssl3_do_change_cipher_spec(SSL *ssl);
 __owur long ssl3_default_timeout(void);
 
 __owur int ssl3_set_handshake_header(SSL *s, WPACKET *pkt, int htype);
-__owur int tls_close_construct_packet(SSL *s, WPACKET *pkt);
+__owur int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype);
 __owur int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype);
-__owur int dtls1_close_construct_packet(SSL *s, WPACKET *pkt);
+__owur int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype);
 __owur int ssl3_handshake_write(SSL *s);
 
 __owur int ssl_allow_compression(SSL *s);
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index f004808..786eb24 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -708,8 +708,13 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
     WRITE_TRAN(*transition) (SSL *s);
     WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst);
     WORK_STATE(*post_work) (SSL *s, WORK_STATE wst);
-    int (*construct_message) (SSL *s);
+    int (*get_construct_message_f) (SSL *s, WPACKET *pkt,
+                                    int (**confunc) (SSL *s, WPACKET *pkt),
+                                    int *mt);
     void (*cb) (const SSL *ssl, int type, int val) = NULL;
+    int (*confunc) (SSL *s, WPACKET *pkt);
+    int mt;
+    WPACKET pkt;
 
     cb = get_callback(s);
 
@@ -717,12 +722,12 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
         transition = ossl_statem_server_write_transition;
         pre_work = ossl_statem_server_pre_work;
         post_work = ossl_statem_server_post_work;
-        construct_message = ossl_statem_server_construct_message;
+        get_construct_message_f = ossl_statem_server_construct_message;
     } else {
         transition = ossl_statem_client_write_transition;
         pre_work = ossl_statem_client_pre_work;
         post_work = ossl_statem_client_post_work;
-        construct_message = ossl_statem_client_construct_message;
+        get_construct_message_f = ossl_statem_client_construct_message;
     }
 
     while (1) {
@@ -764,8 +769,16 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
             case WORK_FINISHED_STOP:
                 return SUB_STATE_END_HANDSHAKE;
             }
-            if (construct_message(s) == 0)
+            if (!WPACKET_init(&pkt, s->init_buf)
+                    || !get_construct_message_f(s, &pkt, &confunc, &mt)
+                    || !ssl_set_handshake_header(s, &pkt, mt)
+                    || (confunc != NULL && !confunc(s, &pkt))
+                    || !ssl_close_construct_packet(s, &pkt, mt)
+                    || !WPACKET_finish(&pkt)) {
+                WPACKET_cleanup(&pkt);
+                ossl_statem_set_error(s);
                 return SUB_STATE_ERROR;
+            }
 
             /* Fall through */
 
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 02d1b7a..51513d5 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -504,13 +504,15 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
 }
 
 /*
- * Construct a message to be sent from the client to the server.
+ * Get the message construction function and message type for sending from the
+ * client
  *
  * Valid return values are:
  *   1: Success
  *   0: Error
  */
-int ossl_statem_client_construct_message(SSL *s)
+int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
+                                         confunc_f *confunc, int *mt)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -519,35 +521,47 @@ int ossl_statem_client_construct_message(SSL *s)
         /* Shouldn't happen */
         return 0;
 
+    case TLS_ST_CW_CHANGE:
+        if (SSL_IS_DTLS(s))
+            *confunc = dtls_construct_change_cipher_spec;
+        else
+            *confunc = tls_construct_change_cipher_spec;
+        *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
+        break;
+
     case TLS_ST_CW_CLNT_HELLO:
-        return tls_construct_client_hello(s);
+        *confunc = tls_construct_client_hello;
+        *mt = SSL3_MT_CLIENT_HELLO;
+        break;
 
     case TLS_ST_CW_CERT:
-        return tls_construct_client_certificate(s);
+        *confunc = tls_construct_client_certificate;
+        *mt = SSL3_MT_CERTIFICATE;
+        break;
 
     case TLS_ST_CW_KEY_EXCH:
-        return tls_construct_client_key_exchange(s);
+        *confunc = tls_construct_client_key_exchange;
+        *mt = SSL3_MT_CLIENT_KEY_EXCHANGE;
+        break;
 
     case TLS_ST_CW_CERT_VRFY:
-        return tls_construct_client_verify(s);
-
-    case TLS_ST_CW_CHANGE:
-        if (SSL_IS_DTLS(s))
-            return dtls_construct_change_cipher_spec(s);
-        else
-            return tls_construct_change_cipher_spec(s);
+        *confunc = tls_construct_client_verify;
+        *mt = SSL3_MT_CERTIFICATE_VERIFY;
+        break;
 
 #if !defined(OPENSSL_NO_NEXTPROTONEG)
     case TLS_ST_CW_NEXT_PROTO:
-        return tls_construct_next_proto(s);
+        *confunc = tls_construct_next_proto;
+        *mt = SSL3_MT_NEXT_PROTO;
+        break;
 #endif
     case TLS_ST_CW_FINISHED:
-        return tls_construct_finished(s,
-                                      s->method->
-                                      ssl3_enc->client_finished_label,
-                                      s->method->
-                                      ssl3_enc->client_finished_label_len);
+        *confunc = tls_construct_finished;
+        *mt = SSL3_MT_FINISHED;
+        break;
     }
+
+    return 1;
 }
 
 /*
@@ -679,7 +693,7 @@ WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
     }
 }
 
-int tls_construct_client_hello(SSL *s)
+int tls_construct_client_hello(SSL *s, WPACKET *pkt)
 {
     unsigned char *p;
     int i;
@@ -689,20 +703,18 @@ int tls_construct_client_hello(SSL *s)
     SSL_COMP *comp;
 #endif
     SSL_SESSION *sess = s->session;
-    WPACKET pkt;
 
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !WPACKET_set_max_size(&pkt, SSL3_RT_MAX_PLAIN_LENGTH)) {
+    if (!WPACKET_set_max_size(pkt, SSL3_RT_MAX_PLAIN_LENGTH)) {
         /* Should not happen */
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
 
     /* Work out what SSL/TLS/DTLS version to use */
     protverr = ssl_set_client_hello_version(s);
     if (protverr != 0) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, protverr);
-        goto err;
+        return 0;
     }
 
     if ((sess == NULL) || !ssl_version_supported(s, sess->ssl_version) ||
@@ -713,7 +725,7 @@ int tls_construct_client_hello(SSL *s)
         (!sess->session_id_length && !sess->tlsext_tick) ||
         (sess->not_resumable)) {
         if (!ssl_get_new_session(s, 0))
-            goto err;
+            return 0;
     }
     /* else use the pre-loaded session */
 
@@ -736,13 +748,7 @@ int tls_construct_client_hello(SSL *s)
         i = 1;
 
     if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random)) <= 0)
-        goto err;
-
-    if (!ssl_set_handshake_header(s, &pkt, SSL3_MT_CLIENT_HELLO)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
+        return 0;
 
     /*-
      * version indicates the negotiated version: for example from
@@ -774,10 +780,10 @@ int tls_construct_client_hello(SSL *s)
      * client_version in client hello and not resetting it to
      * the negotiated version.
      */
-    if (!WPACKET_put_bytes_u16(&pkt, s->client_version)
-            || !WPACKET_memcpy(&pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
+    if (!WPACKET_put_bytes_u16(pkt, s->client_version)
+            || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
 
     /* Session ID */
@@ -786,88 +792,78 @@ int tls_construct_client_hello(SSL *s)
     else
         i = s->session->session_id_length;
     if (i > (int)sizeof(s->session->session_id)
-            || !WPACKET_start_sub_packet_u8(&pkt)
-            || (i != 0 && !WPACKET_memcpy(&pkt, s->session->session_id, i))
-            || !WPACKET_close(&pkt)) {
+            || !WPACKET_start_sub_packet_u8(pkt)
+            || (i != 0 && !WPACKET_memcpy(pkt, s->session->session_id, i))
+            || !WPACKET_close(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
 
     /* cookie stuff for DTLS */
     if (SSL_IS_DTLS(s)) {
         if (s->d1->cookie_len > sizeof(s->d1->cookie)
-                || !WPACKET_sub_memcpy_u8(&pkt, s->d1->cookie,
+                || !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
                                           s->d1->cookie_len)) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-            goto err;
+            return 0;
         }
     }
 
     /* Ciphers supported */
-    if (!WPACKET_start_sub_packet_u16(&pkt)) {
+    if (!WPACKET_start_sub_packet_u16(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
     /* ssl_cipher_list_to_bytes() raises SSLerr if appropriate */
-    if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &pkt))
-        goto err;
-    if (!WPACKET_close(&pkt)) {
+    if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt))
+        return 0;
+    if (!WPACKET_close(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
 
     /* COMPRESSION */
-    if (!WPACKET_start_sub_packet_u8(&pkt)) {
+    if (!WPACKET_start_sub_packet_u8(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
 #ifndef OPENSSL_NO_COMP
     if (ssl_allow_compression(s) && s->ctx->comp_methods) {
         int compnum = sk_SSL_COMP_num(s->ctx->comp_methods);
         for (i = 0; i < compnum; i++) {
             comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
-            if (!WPACKET_put_bytes_u8(&pkt, comp->id)) {
+            if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
                 SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-                goto err;
+                return 0;
             }
         }
     }
 #endif
     /* Add the NULL method */
-    if (!WPACKET_put_bytes_u8(&pkt, 0) || !WPACKET_close(&pkt)) {
+    if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
 
     /* TLS extensions */
     if (ssl_prepare_clienthello_tlsext(s) <= 0) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
-        goto err;
+        return 0;
     }
-    if (!WPACKET_start_sub_packet_u16(&pkt)
+    if (!WPACKET_start_sub_packet_u16(pkt)
                /*
                 * If extensions are of zero length then we don't even add the
                 * extensions length bytes
                 */
-            || !WPACKET_set_flags(&pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)
-            || !ssl_add_clienthello_tlsext(s, &pkt, &al)
-            || !WPACKET_close(&pkt)) {
+            || !WPACKET_set_flags(pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)
+            || !ssl_add_clienthello_tlsext(s, pkt, &al)
+            || !WPACKET_close(pkt)) {
         ssl3_send_alert(s, SSL3_AL_FATAL, al);
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    if (!ssl_close_construct_packet(s, &pkt)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
 
     return 1;
- err:
-    ossl_statem_set_error(s);
-    WPACKET_cleanup(&pkt);
-    return 0;
 }
 
 MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
@@ -2457,44 +2453,31 @@ static int tls_construct_cke_srp(SSL *s, WPACKET *pkt, int *al)
 #endif
 }
 
-int tls_construct_client_key_exchange(SSL *s)
+int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
 {
     unsigned long alg_k;
     int al = -1;
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)) {
-        /* Should not happen */
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    if (!ssl_set_handshake_header(s, &pkt, SSL3_MT_CLIENT_KEY_EXCHANGE)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
     if ((alg_k & SSL_PSK)
-        && !tls_construct_cke_psk_preamble(s, &pkt, &al))
+        && !tls_construct_cke_psk_preamble(s, pkt, &al))
         goto err;
 
     if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
-        if (!tls_construct_cke_rsa(s, &pkt, &al))
+        if (!tls_construct_cke_rsa(s, pkt, &al))
             goto err;
     } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
-        if (!tls_construct_cke_dhe(s, &pkt, &al))
+        if (!tls_construct_cke_dhe(s, pkt, &al))
             goto err;
     } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
-        if (!tls_construct_cke_ecdhe(s, &pkt, &al))
+        if (!tls_construct_cke_ecdhe(s, pkt, &al))
             goto err;
     } else if (alg_k & SSL_kGOST) {
-        if (!tls_construct_cke_gost(s, &pkt, &al))
+        if (!tls_construct_cke_gost(s, pkt, &al))
             goto err;
     } else if (alg_k & SSL_kSRP) {
-        if (!tls_construct_cke_srp(s, &pkt, &al))
+        if (!tls_construct_cke_srp(s, pkt, &al))
             goto err;
     } else if (!(alg_k & SSL_kPSK)) {
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -2502,12 +2485,6 @@ int tls_construct_client_key_exchange(SSL *s)
         goto err;
     }
 
-    if (!ssl_close_construct_packet(s, &pkt)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
     return 1;
  err:
     if (al != -1)
@@ -2518,8 +2495,6 @@ int tls_construct_client_key_exchange(SSL *s)
     OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
     s->s3->tmp.psk = NULL;
 #endif
-    WPACKET_cleanup(&pkt);
-    ossl_statem_set_error(s);
     return 0;
 }
 
@@ -2588,7 +2563,7 @@ int tls_client_key_exchange_post_work(SSL *s)
     return 0;
 }
 
-int tls_construct_client_verify(SSL *s)
+int tls_construct_client_verify(SSL *s, WPACKET *pkt)
 {
     EVP_PKEY *pkey;
     const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
@@ -2597,18 +2572,6 @@ int tls_construct_client_verify(SSL *s)
     long hdatalen = 0;
     void *hdata;
     unsigned char *sig = NULL;
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)) {
-        /* Should not happen */
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    if (!ssl_set_handshake_header(s, &pkt, SSL3_MT_CERTIFICATE_VERIFY)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
 
     mctx = EVP_MD_CTX_new();
     if (mctx == NULL) {
@@ -2622,7 +2585,7 @@ int tls_construct_client_verify(SSL *s)
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
         goto err;
     }
-    if (SSL_USE_SIGALGS(s)&& !tls12_get_sigandhash(&pkt, pkey, md)) {
+    if (SSL_USE_SIGALGS(s)&& !tls12_get_sigandhash(pkt, pkey, md)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -2654,7 +2617,7 @@ int tls_construct_client_verify(SSL *s)
     }
 #endif
 
-    if (!WPACKET_sub_memcpy_u16(&pkt, sig, u)) {
+    if (!WPACKET_sub_memcpy_u16(pkt, sig, u)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -2663,16 +2626,10 @@ int tls_construct_client_verify(SSL *s)
     if (!ssl3_digest_cached_records(s, 0))
         goto err;
 
-    if (!ssl_close_construct_packet(s, &pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
     OPENSSL_free(sig);
     EVP_MD_CTX_free(mctx);
     return 1;
  err:
-    WPACKET_cleanup(&pkt);
     OPENSSL_free(sig);
     EVP_MD_CTX_free(mctx);
     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
@@ -2776,14 +2733,13 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
     return WORK_ERROR;
 }
 
-int tls_construct_client_certificate(SSL *s)
+int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
 {
-    if (!ssl3_output_cert_chain(s,
-                                (s->s3->tmp.cert_req ==
-                                 2) ? NULL : s->cert->key)) {
+    if (!ssl3_output_cert_chain(s, pkt,
+                               (s->s3->tmp.cert_req == 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);
-        ossl_statem_set_error(s);
         return 0;
     }
 
@@ -2866,42 +2822,24 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 }
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
-int tls_construct_next_proto(SSL *s)
+int tls_construct_next_proto(SSL *s, WPACKET *pkt)
 {
     size_t len, padding_len;
     unsigned char *padding = NULL;
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)) {
-        /* Should not happen */
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEXT_PROTO, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    if (!ssl_set_handshake_header(s, &pkt, SSL3_MT_NEXT_PROTO)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEXT_PROTO, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
 
     len = s->next_proto_negotiated_len;
     padding_len = 32 - ((len + 2) % 32);
 
-    if (!WPACKET_sub_memcpy_u8(&pkt, s->next_proto_negotiated, len)
-            || !WPACKET_sub_allocate_bytes_u8(&pkt, padding_len, &padding)) {
+    if (!WPACKET_sub_memcpy_u8(pkt, s->next_proto_negotiated, len)
+            || !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_NEXT_PROTO, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     memset(padding, 0, padding_len);
 
-    if (!ssl_close_construct_packet(s, &pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEXT_PROTO, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
     return 1;
  err:
-    WPACKET_cleanup(&pkt);
     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return 0;
 }
diff --git a/ssl/statem/statem_dtls.c b/ssl/statem/statem_dtls.c
index 0328ab7..5b90c56 100644
--- a/ssl/statem/statem_dtls.c
+++ b/ssl/statem/statem_dtls.c
@@ -872,53 +872,18 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
  * ssl->session->read_compression       assign
  * ssl->session->read_hash              assign
  */
-int dtls_construct_change_cipher_spec(SSL *s)
+int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
 {
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !WPACKET_put_bytes_u8(&pkt, SSL3_MT_CCS)) {
-        SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
-    s->init_num = DTLS1_CCS_HEADER_LENGTH;
-
     if (s->version == DTLS1_BAD_VER) {
         s->d1->next_handshake_write_seq++;
 
-        if (!WPACKET_put_bytes_u16(&pkt, s->d1->handshake_write_seq)) {
+        if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) {
             SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-            goto err;
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
         }
-
-        s->init_num += 2;
-    }
-
-    if (!WPACKET_finish(&pkt)) {
-        SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    s->init_off = 0;
-
-    dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
-                                 s->d1->handshake_write_seq, 0, 0);
-
-    /* buffer the message to handle re-xmits */
-    if (!dtls1_buffer_message(s, 1)) {
-        SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-        goto err    ;
     }
 
     return 1;
- err:
-    WPACKET_cleanup(&pkt);
-    ossl_statem_set_error(s);
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-
-    return 0;
 }
 
 #ifndef OPENSSL_NO_SCTP
@@ -1216,36 +1181,48 @@ int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype)
 {
     unsigned char *header;
 
-    dtls1_set_message_header(s, htype, 0, 0, 0);
-
-    /*
-     * We allocate space at the start for the message header. This gets filled
-     * in later
-     */
-    if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header)
-            || !WPACKET_start_sub_packet(pkt))
-        return 0;
+    if (htype == SSL3_MT_CHANGE_CIPHER_SPEC) {
+        s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+        dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
+                                     s->d1->handshake_write_seq, 0, 0);
+        if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS))
+            return 0;
+    } else {
+        dtls1_set_message_header(s, htype, 0, 0, 0);
+        /*
+         * We allocate space at the start for the message header. This gets
+         * filled in later
+         */
+        if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header)
+                || !WPACKET_start_sub_packet(pkt))
+            return 0;
+    }
 
     return 1;
 }
 
-int dtls1_close_construct_packet(SSL *s, WPACKET *pkt)
+int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
 {
     size_t msglen;
 
-    if (!WPACKET_close(pkt)
+    if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
             || !WPACKET_get_length(pkt, &msglen)
-            || msglen > INT_MAX
-            || !WPACKET_finish(pkt))
+            || msglen > INT_MAX)
         return 0;
-    s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH;
-    s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH;
+
+    if (htype != SSL3_MT_CHANGE_CIPHER_SPEC) {
+        s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH;
+        s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH;
+    }
     s->init_num = (int)msglen;
     s->init_off = 0;
 
-    /* Buffer the message to handle re-xmits */
-    if (!dtls1_buffer_message(s, 0))
-        return 0;
+    if (htype != DTLS1_MT_HELLO_VERIFY_REQUEST) {
+        /* Buffer the message to handle re-xmits */
+        if (!dtls1_buffer_message(s, htype == SSL3_MT_CHANGE_CIPHER_SPEC
+                                     ? 1 : 0))
+            return 0;
+    }
 
     return 1;
 }
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index da26ef8..c185d7c 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -57,14 +57,13 @@ int ssl3_do_write(SSL *s, int type)
     return (0);
 }
 
-int tls_close_construct_packet(SSL *s, WPACKET *pkt)
+int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
 {
     size_t msglen;
 
-    if (!WPACKET_close(pkt)
+    if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
             || !WPACKET_get_length(pkt, &msglen)
-            || msglen > INT_MAX
-            || !WPACKET_finish(pkt))
+            || msglen > INT_MAX)
         return 0;
     s->init_num = (int)msglen;
     s->init_off = 0;
@@ -72,15 +71,18 @@ int tls_close_construct_packet(SSL *s, WPACKET *pkt)
     return 1;
 }
 
-int tls_construct_finished(SSL *s, const char *sender, int slen)
+int tls_construct_finished(SSL *s, WPACKET *pkt)
 {
     int i;
-    WPACKET pkt;
+    const char *sender;
+    int slen;
 
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt, SSL3_MT_FINISHED)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
-        goto err;
+    if (s->server) {
+        sender = s->method->ssl3_enc->server_finished_label;
+        slen = s->method->ssl3_enc->server_finished_label_len;
+    } else {
+        sender = s->method->ssl3_enc->client_finished_label;
+        slen = s->method->ssl3_enc->client_finished_label_len;
     }
 
     i = s->method->ssl3_enc->final_finish_mac(s,
@@ -93,7 +95,7 @@ int tls_construct_finished(SSL *s, const char *sender, int slen)
 
     s->s3->tmp.finish_md_len = i;
 
-    if (!WPACKET_memcpy(&pkt, s->s3->tmp.finish_md, i)) {
+    if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, i)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -111,15 +113,8 @@ int tls_construct_finished(SSL *s, const char *sender, int slen)
         s->s3->previous_server_finished_len = i;
     }
 
-    if (!ssl_close_construct_packet(s, &pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
     return 1;
  err:
-    ossl_statem_set_error(s);
-    WPACKET_cleanup(&pkt);
     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return 0;
 }
@@ -267,53 +262,26 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
     return MSG_PROCESS_ERROR;
 }
 
-int tls_construct_change_cipher_spec(SSL *s)
+int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
 {
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !WPACKET_put_bytes_u8(&pkt, SSL3_MT_CCS)
-            || !WPACKET_finish(&pkt)) {
-        WPACKET_cleanup(&pkt);
-        ossl_statem_set_error(s);
+    if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
         return 0;
     }
 
-    s->init_num = 1;
-    s->init_off = 0;
-
     return 1;
 }
 
-unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
+unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
 {
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)) {
-        /* Should not happen */
-        SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    if (!ssl_set_handshake_header(s, &pkt, SSL3_MT_CERTIFICATE)
-            || !WPACKET_start_sub_packet_u24(&pkt)) {
-        SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    if (!ssl_add_cert_chain(s, &pkt, cpk))
-        goto err;
-
-    if (!WPACKET_close(&pkt) || !ssl_close_construct_packet(s, &pkt)) {
+    if (!WPACKET_start_sub_packet_u24(pkt)
+            || !ssl_add_cert_chain(s, pkt, cpk)
+            || !WPACKET_close(pkt)) {
         SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_INTERNAL_ERROR);
-        goto err;
+        return 0;
     }
     return 1;
- err:
-    WPACKET_cleanup(&pkt);
-    return 0;
 }
 
 WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index a46e6c7..6b57b25 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -43,6 +43,8 @@ typedef enum {
 /* Flush the write BIO */
 int statem_flush(SSL *s);
 
+typedef int (*confunc_f) (SSL *s, WPACKET *pkt);
+
 /*
  * TLS/DTLS client state machine functions
  */
@@ -50,7 +52,8 @@ int ossl_statem_client_read_transition(SSL *s, int mt);
 WRITE_TRAN ossl_statem_client_write_transition(SSL *s);
 WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst);
 WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst);
-int ossl_statem_client_construct_message(SSL *s);
+int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
+                                         confunc_f *confunc, int *mt);
 unsigned long ossl_statem_client_max_message_size(SSL *s);
 MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt);
 WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst);
@@ -62,7 +65,8 @@ int ossl_statem_server_read_transition(SSL *s, int mt);
 WRITE_TRAN ossl_statem_server_write_transition(SSL *s);
 WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst);
 WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst);
-int ossl_statem_server_construct_message(SSL *s);
+int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
+                                         confunc_f *confunc,int *mt);
 unsigned long ossl_statem_server_max_message_size(SSL *s);
 MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt);
 WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
@@ -75,45 +79,44 @@ __owur int dtls_get_message(SSL *s, int *mt, unsigned long *len);
 /* Message construction and processing functions */
 __owur MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt);
-__owur int tls_construct_change_cipher_spec(SSL *s);
-__owur int dtls_construct_change_cipher_spec(SSL *s);
+__owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
+__owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
 
-__owur int tls_construct_finished(SSL *s, const char *sender, int slen);
+__owur int tls_construct_finished(SSL *s, WPACKET *pkt);
 __owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst);
 __owur WORK_STATE dtls_wait_for_dry(SSL *s);
 
 /* some client-only functions */
-__owur int tls_construct_client_hello(SSL *s);
+__owur int tls_construct_client_hello(SSL *s, WPACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt);
-__owur int tls_construct_client_verify(SSL *s);
+__owur int tls_construct_client_verify(SSL *s, WPACKET *pkt);
 __owur WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst);
-__owur int tls_construct_client_certificate(SSL *s);
+__owur int tls_construct_client_certificate(SSL *s, WPACKET *pkt);
 __owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
-__owur int tls_construct_client_key_exchange(SSL *s);
+__owur int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt);
 __owur int tls_client_key_exchange_post_work(SSL *s);
-__owur int tls_construct_cert_status(SSL *s);
+__owur int tls_construct_cert_status(SSL *s, WPACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt);
 __owur int ssl3_check_cert_and_algorithm(SSL *s);
 #ifndef OPENSSL_NO_NEXTPROTONEG
-__owur int tls_construct_next_proto(SSL *s);
+__owur int tls_construct_next_proto(SSL *s, WPACKET *pkt);
 #endif
 __owur MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt);
 
 /* some server-only functions */
 __owur MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt);
 __owur WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst);
-__owur int tls_construct_server_hello(SSL *s);
-__owur int tls_construct_hello_request(SSL *s);
-__owur int dtls_construct_hello_verify_request(SSL *s);
-__owur int tls_construct_server_certificate(SSL *s);
-__owur int tls_construct_server_key_exchange(SSL *s);
-__owur int tls_construct_certificate_request(SSL *s);
-__owur int tls_construct_server_done(SSL *s);
+__owur int tls_construct_server_hello(SSL *s, WPACKET *pkt);
+__owur int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt);
+__owur int tls_construct_server_certificate(SSL *s, WPACKET *pkt);
+__owur int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt);
+__owur int tls_construct_certificate_request(SSL *s, WPACKET *pkt);
+__owur int tls_construct_server_done(SSL *s, WPACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt);
 __owur WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst);
@@ -121,4 +124,4 @@ __owur MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt);
 #ifndef OPENSSL_NO_NEXTPROTONEG
 __owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
 #endif
-__owur int tls_construct_new_session_ticket(SSL *s);
+__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index cc737ba..009d06c 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -613,13 +613,15 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
 }
 
 /*
- * Construct a message to be sent from the server to the client.
+ * Get the message construction function and message type for sending from the
+ * server
  *
  * Valid return values are:
  *   1: Success
  *   0: Error
  */
-int ossl_statem_server_construct_message(SSL *s)
+int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
+                                         confunc_f *confunc, int *mt)
 {
     OSSL_STATEM *st = &s->statem;
 
@@ -628,46 +630,67 @@ int ossl_statem_server_construct_message(SSL *s)
         /* Shouldn't happen */
         return 0;
 
+    case TLS_ST_SW_CHANGE:
+        if (SSL_IS_DTLS(s))
+            *confunc = dtls_construct_change_cipher_spec;
+        else
+            *confunc = tls_construct_change_cipher_spec;
+        *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
+        break;
+
     case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
-        return dtls_construct_hello_verify_request(s);
+        *confunc = dtls_construct_hello_verify_request;
+        *mt = DTLS1_MT_HELLO_VERIFY_REQUEST;
+        break;
 
     case TLS_ST_SW_HELLO_REQ:
-        return tls_construct_hello_request(s);
+        /* No construction function needed */
+        *confunc = NULL;
+        *mt = SSL3_MT_HELLO_REQUEST;
+        break;
 
     case TLS_ST_SW_SRVR_HELLO:
-        return tls_construct_server_hello(s);
+        *confunc = tls_construct_server_hello;
+        *mt = SSL3_MT_SERVER_HELLO;
+        break;
 
     case TLS_ST_SW_CERT:
-        return tls_construct_server_certificate(s);
+        *confunc = tls_construct_server_certificate;
+        *mt = SSL3_MT_CERTIFICATE;
+        break;
 
     case TLS_ST_SW_KEY_EXCH:
-        return tls_construct_server_key_exchange(s);
+        *confunc = tls_construct_server_key_exchange;
+        *mt = SSL3_MT_SERVER_KEY_EXCHANGE;
+        break;
 
     case TLS_ST_SW_CERT_REQ:
-        return tls_construct_certificate_request(s);
+        *confunc = tls_construct_certificate_request;
+        *mt = SSL3_MT_CERTIFICATE_REQUEST;
+        break;
 
     case TLS_ST_SW_SRVR_DONE:
-        return tls_construct_server_done(s);
+        *confunc = tls_construct_server_done;
+        *mt = SSL3_MT_SERVER_DONE;
+        break;
 
     case TLS_ST_SW_SESSION_TICKET:
-        return tls_construct_new_session_ticket(s);
+        *confunc = tls_construct_new_session_ticket;
+        *mt = SSL3_MT_NEWSESSION_TICKET;
+        break;
 
     case TLS_ST_SW_CERT_STATUS:
-        return tls_construct_cert_status(s);
-
-    case TLS_ST_SW_CHANGE:
-        if (SSL_IS_DTLS(s))
-            return dtls_construct_change_cipher_spec(s);
-        else
-            return tls_construct_change_cipher_spec(s);
+        *confunc = tls_construct_cert_status;
+        *mt = SSL3_MT_CERTIFICATE_STATUS;
+        break;
 
     case TLS_ST_SW_FINISHED:
-        return tls_construct_finished(s,
-                                      s->method->
-                                      ssl3_enc->server_finished_label,
-                                      s->method->
-                                      ssl3_enc->server_finished_label_len);
+        *confunc = tls_construct_finished;
+        *mt = SSL3_MT_FINISHED;
+        break;
     }
+
+    return 1;
 }
 
 /*
@@ -829,22 +852,6 @@ static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
 }
 #endif
 
-int tls_construct_hello_request(SSL *s)
-{
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt, SSL3_MT_HELLO_REQUEST)
-            || !ssl_close_construct_packet(s, &pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_HELLO_REQUEST, ERR_R_INTERNAL_ERROR);
-        ossl_statem_set_error(s);
-        WPACKET_cleanup(&pkt);
-        return 0;
-    }
-
-    return 1;
-}
-
 int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
                                   unsigned char cookie_len)
 {
@@ -856,45 +863,23 @@ int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
     return 1;
 }
 
-int dtls_construct_hello_verify_request(SSL *s)
+int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
 {
-    size_t msglen;
-    WPACKET pkt;
-
     if (s->ctx->app_gen_cookie_cb == NULL ||
         s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
                                   &(s->d1->cookie_len)) == 0 ||
         s->d1->cookie_len > 255) {
         SSLerr(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
                SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
-        ossl_statem_set_error(s);
         return 0;
     }
 
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt,
-                                         DTLS1_MT_HELLO_VERIFY_REQUEST)
-            || !dtls_raw_hello_verify_request(&pkt, s->d1->cookie,
-                                              s->d1->cookie_len)
-               /*
-                * We don't call close_construct_packet() because we don't want
-                * to buffer this message
-                */
-            || !WPACKET_close(&pkt)
-            || !WPACKET_get_length(&pkt, &msglen)
-            || !WPACKET_finish(&pkt)) {
+    if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
+                                              s->d1->cookie_len)) {
         SSLerr(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST, ERR_R_INTERNAL_ERROR);
-        WPACKET_cleanup(&pkt);
-        ossl_statem_set_error(s);
         return 0;
     }
 
-    /* number of bytes to write */
-    s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH;
-    s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH;
-    s->init_num = (int)msglen;
-    s->init_off = 0;
-
     return 1;
 }
 
@@ -1497,20 +1482,17 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
     return WORK_ERROR;
 }
 
-int tls_construct_server_hello(SSL *s)
+int tls_construct_server_hello(SSL *s, WPACKET *pkt)
 {
     int sl, compm, al = SSL_AD_INTERNAL_ERROR;
     size_t len;
-    WPACKET pkt;
 
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt, SSL3_MT_SERVER_HELLO)
-            || !WPACKET_put_bytes_u16(&pkt, s->version)
+    if (!WPACKET_put_bytes_u16(pkt, s->version)
                /*
                 * Random stuff. Filling of the server_random takes place in
                 * tls_process_client_hello()
                 */
-            || !WPACKET_memcpy(&pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+            || !WPACKET_memcpy(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -1552,49 +1534,33 @@ int tls_construct_server_hello(SSL *s)
         compm = s->s3->tmp.new_compression->id;
 #endif
 
-    if (!WPACKET_sub_memcpy_u8(&pkt, s->session->session_id, sl)
-            || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &pkt, &len)
-            || !WPACKET_put_bytes_u8(&pkt, compm)
+    if (!WPACKET_sub_memcpy_u8(pkt, s->session->session_id, sl)
+            || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
+            || !WPACKET_put_bytes_u8(pkt, compm)
             || !ssl_prepare_serverhello_tlsext(s)
-            || !ssl_add_serverhello_tlsext(s, &pkt, &al)
-            || !ssl_close_construct_packet(s, &pkt)) {
+            || !ssl_add_serverhello_tlsext(s, pkt, &al)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     return 1;
  err:
-    WPACKET_cleanup(&pkt);
     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    ossl_statem_set_error(s);
     return 0;
 }
 
-int tls_construct_server_done(SSL *s)
+int tls_construct_server_done(SSL *s, WPACKET *pkt)
 {
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt, SSL3_MT_SERVER_DONE)
-            || !ssl_close_construct_packet(s, &pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_DONE, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
     if (!s->s3->tmp.cert_request) {
-        if (!ssl3_digest_cached_records(s, 0))
-            goto err;
+        if (!ssl3_digest_cached_records(s, 0)) {
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            return 0;
+        }
     }
     return 1;
-
- err:
-    WPACKET_cleanup(&pkt);
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    ossl_statem_set_error(s);
-    return 0;
 }
 
-int tls_construct_server_key_exchange(SSL *s)
+int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_DH
     EVP_PKEY *pkdh = NULL;
@@ -1610,13 +1576,9 @@ int tls_construct_server_key_exchange(SSL *s)
     unsigned long type;
     const BIGNUM *r[4];
     EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
-    WPACKET pkt;
     size_t paramlen, paramoffset;
 
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt,
-                                         SSL3_MT_SERVER_KEY_EXCHANGE)
-            || !WPACKET_get_total_written(&pkt, &paramoffset)) {
+    if (!WPACKET_get_total_written(pkt, &paramoffset)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
         goto f_err;
     }
@@ -1786,7 +1748,7 @@ int tls_construct_server_key_exchange(SSL *s)
          * checked this when we set the identity hint - but just in case
          */
         if (len > PSK_MAX_IDENTITY_LEN
-                || !WPACKET_sub_memcpy_u16(&pkt, s->cert->psk_identity_hint,
+                || !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
                                            len)) {
             SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
@@ -1801,10 +1763,10 @@ int tls_construct_server_key_exchange(SSL *s)
 
 #ifndef OPENSSL_NO_SRP
         if ((i == 2) && (type & SSL_kSRP)) {
-            res = WPACKET_start_sub_packet_u8(&pkt);
+            res = WPACKET_start_sub_packet_u8(pkt);
         } else
 #endif
-            res = WPACKET_start_sub_packet_u16(&pkt);
+            res = WPACKET_start_sub_packet_u16(pkt);
 
         if (!res) {
             SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
@@ -1822,7 +1784,7 @@ int tls_construct_server_key_exchange(SSL *s)
             size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]);
 
             if (len > 0) {
-                if (!WPACKET_allocate_bytes(&pkt, len, &binval)) {
+                if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
                     SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                            ERR_R_INTERNAL_ERROR);
                     goto f_err;
@@ -1831,8 +1793,8 @@ int tls_construct_server_key_exchange(SSL *s)
             }
         }
 #endif
-        if (!WPACKET_allocate_bytes(&pkt, BN_num_bytes(r[i]), &binval)
-                || !WPACKET_close(&pkt)) {
+        if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
+                || !WPACKET_close(pkt)) {
             SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
             goto f_err;
@@ -1849,10 +1811,10 @@ int tls_construct_server_key_exchange(SSL *s)
          * [1 byte length of encoded point], followed by the actual encoded
          * point itself
          */
-        if (!WPACKET_put_bytes_u8(&pkt, NAMED_CURVE_TYPE)
-                || !WPACKET_put_bytes_u8(&pkt, 0)
-                || !WPACKET_put_bytes_u8(&pkt, curve_id)
-                || !WPACKET_sub_memcpy_u8(&pkt, encodedPoint, encodedlen)) {
+        if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE)
+                || !WPACKET_put_bytes_u8(pkt, 0)
+                || !WPACKET_put_bytes_u8(pkt, curve_id)
+                || !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
             SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                    ERR_R_INTERNAL_ERROR);
             goto f_err;
@@ -1873,14 +1835,14 @@ int tls_construct_server_key_exchange(SSL *s)
             unsigned int siglen;
 
             /* Get length of the parameters we have written above */
-            if (!WPACKET_get_length(&pkt, &paramlen)) {
+            if (!WPACKET_get_length(pkt, &paramlen)) {
                 SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                        ERR_R_INTERNAL_ERROR);
                 goto f_err;
             }
             /* send signature algorithm */
             if (SSL_USE_SIGALGS(s)) {
-                if (!tls12_get_sigandhash(&pkt, pkey, md)) {
+                if (!tls12_get_sigandhash(pkt, pkey, md)) {
                     /* Should never happen */
                     SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                            ERR_R_INTERNAL_ERROR);
@@ -1896,7 +1858,7 @@ int tls_construct_server_key_exchange(SSL *s)
              * up front, and then properly allocate them in the WPACKET
              * afterwards.
              */
-            if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_size(pkey),
+            if (!WPACKET_sub_reserve_bytes_u16(pkt, EVP_PKEY_size(pkey),
                                                &sigbytes1)
                     || EVP_SignInit_ex(md_ctx, md, NULL) <= 0
                     || EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]),
@@ -1906,7 +1868,7 @@ int tls_construct_server_key_exchange(SSL *s)
                     || EVP_SignUpdate(md_ctx, s->init_buf->data + paramoffset,
                                       paramlen) <= 0
                     || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0
-                    || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2)
+                    || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
                     || sigbytes1 != sigbytes2) {
                 SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                        ERR_R_INTERNAL_ERROR);
@@ -1921,11 +1883,6 @@ int tls_construct_server_key_exchange(SSL *s)
         }
     }
 
-    if (!ssl_close_construct_packet(s, &pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-        goto f_err;
-    }
-
     EVP_MD_CTX_free(md_ctx);
     return 1;
  f_err:
@@ -1938,29 +1895,18 @@ int tls_construct_server_key_exchange(SSL *s)
     OPENSSL_free(encodedPoint);
 #endif
     EVP_MD_CTX_free(md_ctx);
-    ossl_statem_set_error(s);
-    WPACKET_cleanup(&pkt);
     return 0;
 }
 
-int tls_construct_certificate_request(SSL *s)
+int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
 {
     int i, nl;
     STACK_OF(X509_NAME) *sk = NULL;
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt,
-                                         SSL3_MT_CERTIFICATE_REQUEST)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
 
     /* get the list of acceptable cert types */
-    if (!WPACKET_start_sub_packet_u8(&pkt)
-            || !ssl3_get_req_cert_type(s, &pkt)
-            || !WPACKET_close(&pkt)) {
+    if (!WPACKET_start_sub_packet_u8(pkt)
+            || !ssl3_get_req_cert_type(s, pkt)
+            || !WPACKET_close(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -1968,9 +1914,9 @@ int tls_construct_certificate_request(SSL *s)
     if (SSL_USE_SIGALGS(s)) {
         const unsigned char *psigs;
         nl = tls12_get_psigalgs(s, &psigs);
-        if (!WPACKET_start_sub_packet_u16(&pkt)
-                || !tls12_copy_sigalgs(s, &pkt, psigs, nl)
-                || !WPACKET_close(&pkt)) {
+        if (!WPACKET_start_sub_packet_u16(pkt)
+                || !tls12_copy_sigalgs(s, pkt, psigs, nl)
+                || !WPACKET_close(pkt)) {
             SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
                    ERR_R_INTERNAL_ERROR);
             goto err;
@@ -1978,7 +1924,7 @@ int tls_construct_certificate_request(SSL *s)
     }
 
     /* Start sub-packet for client CA list */
-    if (!WPACKET_start_sub_packet_u16(&pkt)) {
+    if (!WPACKET_start_sub_packet_u16(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -1992,7 +1938,7 @@ int tls_construct_certificate_request(SSL *s)
 
             if (name == NULL
                     || (namelen = i2d_X509_NAME(name, NULL)) < 0
-                    || !WPACKET_sub_allocate_bytes_u16(&pkt, namelen,
+                    || !WPACKET_sub_allocate_bytes_u16(pkt, namelen,
                                                        &namebytes)
                     || i2d_X509_NAME(name, &namebytes) != namelen) {
                 SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
@@ -2003,8 +1949,7 @@ int tls_construct_certificate_request(SSL *s)
     }
     /* else no CA names */
 
-    if (!WPACKET_close(&pkt)
-            || !ssl_close_construct_packet(s, &pkt)) {
+    if (!WPACKET_close(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -2013,9 +1958,7 @@ int tls_construct_certificate_request(SSL *s)
 
     return 1;
  err:
-    WPACKET_cleanup(&pkt);
     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    ossl_statem_set_error(s);
     return 0;
 }
 
@@ -2931,27 +2874,25 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
     return ret;
 }
 
-int tls_construct_server_certificate(SSL *s)
+int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
 {
     CERT_PKEY *cpk;
 
     cpk = ssl_get_server_send_pkey(s);
     if (cpk == NULL) {
         SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        ossl_statem_set_error(s);
         return 0;
     }
 
-    if (!ssl3_output_cert_chain(s, cpk)) {
+    if (!ssl3_output_cert_chain(s, pkt, cpk)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        ossl_statem_set_error(s);
         return 0;
     }
 
     return 1;
 }
 
-int tls_construct_new_session_ticket(SSL *s)
+int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
 {
     unsigned char *senc = NULL;
     EVP_CIPHER_CTX *ctx = NULL;
@@ -2966,7 +2907,6 @@ int tls_construct_new_session_ticket(SSL *s)
     unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
     int iv_len;
     size_t macoffset, macendoffset;
-    WPACKET pkt;
 
     /* get session encoding length */
     slen_full = i2d_SSL_SESSION(s->session, NULL);
@@ -2984,12 +2924,6 @@ int tls_construct_new_session_ticket(SSL *s)
         return 0;
     }
 
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt, SSL3_MT_NEWSESSION_TICKET)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
     ctx = EVP_CIPHER_CTX_new();
     hctx = HMAC_CTX_new();
     if (ctx == NULL || hctx == NULL) {
@@ -3034,9 +2968,8 @@ int tls_construct_new_session_ticket(SSL *s)
         if (ret == 0) {
 
             /* Put timeout and length */
-            if (!WPACKET_put_bytes_u32(&pkt, 0)
-                    || !WPACKET_put_bytes_u16(&pkt, 0)
-                    || !ssl_close_construct_packet(s, &pkt)) {
+            if (!WPACKET_put_bytes_u32(pkt, 0)
+                    || !WPACKET_put_bytes_u16(pkt, 0)) {
                 SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
                        ERR_R_INTERNAL_ERROR);
                 goto err;
@@ -3071,35 +3004,34 @@ int tls_construct_new_session_ticket(SSL *s)
      * for resumed session (for simplicity), and guess that tickets for
      * new sessions will live as long as their sessions.
      */
-    if (!WPACKET_put_bytes_u32(&pkt, s->hit ? 0 : s->session->timeout)
+    if (!WPACKET_put_bytes_u32(pkt, s->hit ? 0 : s->session->timeout)
                /* Now the actual ticket data */
-            || !WPACKET_start_sub_packet_u16(&pkt)
-            || !WPACKET_get_total_written(&pkt, &macoffset)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_get_total_written(pkt, &macoffset)
                /* Output key name */
-            || !WPACKET_memcpy(&pkt, key_name, sizeof(key_name))
+            || !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
                /* output IV */
-            || !WPACKET_memcpy(&pkt, iv, iv_len)
-            || !WPACKET_reserve_bytes(&pkt, slen + EVP_MAX_BLOCK_LENGTH,
+            || !WPACKET_memcpy(pkt, iv, iv_len)
+            || !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
                                       &encdata1)
                /* Encrypt session data */
             || !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
-            || !WPACKET_allocate_bytes(&pkt, len, &encdata2)
+            || !WPACKET_allocate_bytes(pkt, len, &encdata2)
             || encdata1 != encdata2
             || !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
-            || !WPACKET_allocate_bytes(&pkt, lenfinal, &encdata2)
+            || !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
             || encdata1 + len != encdata2
             || len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
-            || !WPACKET_get_total_written(&pkt, &macendoffset)
+            || !WPACKET_get_total_written(pkt, &macendoffset)
             || !HMAC_Update(hctx,
                             (unsigned char *)s->init_buf->data + macoffset,
                             macendoffset - macoffset)
-            || !WPACKET_reserve_bytes(&pkt, EVP_MAX_MD_SIZE, &macdata1)
+            || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
             || !HMAC_Final(hctx, macdata1, &hlen)
             || hlen > EVP_MAX_MD_SIZE
-            || !WPACKET_allocate_bytes(&pkt, hlen, &macdata2)
+            || !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
             || macdata1 != macdata2
-            || !WPACKET_close(&pkt)
-            || !ssl_close_construct_packet(s, &pkt)) {
+            || !WPACKET_close(pkt)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -3113,25 +3045,16 @@ int tls_construct_new_session_ticket(SSL *s)
     EVP_CIPHER_CTX_free(ctx);
     HMAC_CTX_free(hctx);
     ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    ossl_statem_set_error(s);
-    WPACKET_cleanup(&pkt);
     return 0;
 }
 
-int tls_construct_cert_status(SSL *s)
+int tls_construct_cert_status(SSL *s, WPACKET *pkt)
 {
-    WPACKET pkt;
-
-    if (!WPACKET_init(&pkt, s->init_buf)
-            || !ssl_set_handshake_header(s, &pkt, SSL3_MT_CERTIFICATE_STATUS)
-            || !WPACKET_put_bytes_u8(&pkt, s->tlsext_status_type)
-            || !WPACKET_sub_memcpy_u24(&pkt, s->tlsext_ocsp_resp,
-                                       s->tlsext_ocsp_resplen)
-            || !ssl_close_construct_packet(s, &pkt)) {
+    if (!WPACKET_put_bytes_u8(pkt, s->tlsext_status_type)
+            || !WPACKET_sub_memcpy_u24(pkt, s->tlsext_ocsp_resp,
+                                       s->tlsext_ocsp_resplen)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CERT_STATUS, ERR_R_INTERNAL_ERROR);
         ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        ossl_statem_set_error(s);
-        WPACKET_cleanup(&pkt);
         return 0;
     }
 


More information about the openssl-commits mailing list