Don't set the handshake header in every message
[openssl.git] / ssl / statem / statem_lib.c
index 258b897a5236550910d8856b89ce6ec21429492a..cac18cc550b47056b25581d532cad55ae7c36d26 100644 (file)
@@ -57,22 +57,38 @@ int ssl3_do_write(SSL *s, int type)
     return (0);
 }
 
-int tls_construct_finished(SSL *s, const char *sender, int slen)
+int tls_close_construct_packet(SSL *s, WPACKET *pkt)
 {
-    unsigned char *p;
-    int i;
-    unsigned long l;
+    size_t msglen;
+
+    if (!WPACKET_close(pkt)
+            || !WPACKET_get_length(pkt, &msglen)
+            || msglen > INT_MAX)
+        return 0;
+    s->init_num = (int)msglen;
+    s->init_off = 0;
 
-    p = ssl_handshake_start(s);
+    return 1;
+}
+
+int tls_construct_finished(SSL *s, WPACKET *pkt, const char *sender, int slen)
+{
+    int i;
 
     i = s->method->ssl3_enc->final_finish_mac(s,
                                               sender, slen,
                                               s->s3->tmp.finish_md);
-    if (i <= 0)
-        return 0;
+    if (i <= 0) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
     s->s3->tmp.finish_md_len = i;
-    memcpy(p, s->s3->tmp.finish_md, i);
-    l = i;
+
+    if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, i)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
 
     /*
      * Copy the finished so we can use it for renegotiation checks
@@ -87,12 +103,10 @@ int tls_construct_finished(SSL *s, const char *sender, int slen)
         s->s3->previous_server_finished_len = i;
     }
 
-    if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
-        return 0;
-    }
-
     return 1;
+ err:
+    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    return 0;
 }
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -138,13 +152,13 @@ MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
      */
     if (SSL_IS_DTLS(s)) {
         if ((s->version == DTLS1_BAD_VER
-                        && remain != DTLS1_CCS_HEADER_LENGTH + 1)
-                    || (s->version != DTLS1_BAD_VER
-                        && remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
-                al = SSL_AD_ILLEGAL_PARAMETER;
-                SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
-                       SSL_R_BAD_CHANGE_CIPHER_SPEC);
-                goto f_err;
+             && remain != DTLS1_CCS_HEADER_LENGTH + 1)
+            || (s->version != DTLS1_BAD_VER
+                && remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
+            al = SSL_AD_ILLEGAL_PARAMETER;
+            SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+                   SSL_R_BAD_CHANGE_CIPHER_SPEC);
+            goto f_err;
         }
     } else {
         if (remain != 0) {
@@ -238,36 +252,29 @@ 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)
 {
-    unsigned char *p;
+    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;
+    }
 
-    p = (unsigned char *)s->init_buf->data;
-    *p = SSL3_MT_CCS;
     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)
 {
-    unsigned char *p;
-    unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
-
-    if (!ssl_add_cert_chain(s, cpk, &l))
-        return 0;
-
-    l -= 3 + SSL_HM_HEADER_LENGTH(s);
-    p = ssl_handshake_start(s);
-    l2n3(l, p);
-    l += 3;
-
-    if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l)) {
+    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);
         return 0;
     }
-    return l + SSL_HM_HEADER_LENGTH(s);
+    return 1;
 }
 
 WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
@@ -331,6 +338,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
             s->d1->handshake_read_seq = 0;
             s->d1->handshake_write_seq = 0;
             s->d1->next_handshake_write_seq = 0;
+            dtls1_clear_received_buffer(s);
         }
     }
 
@@ -349,16 +357,18 @@ int tls_get_message_header(SSL *s, int *mt)
     do {
         while (s->init_num < SSL3_HM_HEADER_LENGTH) {
             i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
-                &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0);
+                                          &p[s->init_num],
+                                          SSL3_HM_HEADER_LENGTH - s->init_num,
+                                          0);
             if (i <= 0) {
                 s->rwstate = SSL_READING;
                 return 0;
             }
             if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
                 /*
-                * A ChangeCipherSpec must be a single byte and may not occur
-                * in the middle of a handshake message.
-                */
+                 * A ChangeCipherSpec must be a single byte and may not occur
+                 * in the middle of a handshake message.
+                 */
                 if (s->init_num != 0 || i != 1 || p[0] != SSL3_MT_CCS) {
                     al = SSL_AD_UNEXPECTED_MESSAGE;
                     SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER,
@@ -401,21 +411,16 @@ int tls_get_message_header(SSL *s, int *mt)
     *mt = *p;
     s->s3->tmp.message_type = *(p++);
 
-    if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
+    if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
         /*
          * Only happens with SSLv3+ in an SSLv2 backward compatible
          * ClientHello
+         *
+         * Total message size is the remaining record bytes to read
+         * plus the SSL3_HM_HEADER_LENGTH bytes that we already read
          */
-         /*
-          * Total message size is the remaining record bytes to read
-          * plus the SSL3_HM_HEADER_LENGTH bytes that we already read
-          */
         l = RECORD_LAYER_get_rrec_length(&s->rlayer)
             + SSL3_HM_HEADER_LENGTH;
-        if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) {
-            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB);
-            goto err;
-        }
         s->s3->tmp.message_size = l;
 
         s->init_msg = s->init_buf->data;
@@ -428,11 +433,6 @@ int tls_get_message_header(SSL *s, int *mt)
             SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
             goto f_err;
         }
-        if (l && !BUF_MEM_grow_clean(s->init_buf,
-                                    (int)l + SSL3_HM_HEADER_LENGTH)) {
-            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB);
-            goto err;
-        }
         s->s3->tmp.message_size = l;
 
         s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
@@ -442,7 +442,6 @@ int tls_get_message_header(SSL *s, int *mt)
     return 1;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
- err:
     return 0;
 }
 
@@ -482,7 +481,7 @@ int tls_get_message_body(SSL *s, unsigned long *len)
 #endif
 
     /* Feed this message into MAC computation. */
-    if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
+    if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
         if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
                              s->init_num)) {
             SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
@@ -491,11 +490,11 @@ int tls_get_message_body(SSL *s, unsigned long *len)
             return 0;
         }
         if (s->msg_callback)
-            s->msg_callback(0, SSL2_VERSION, 0,  s->init_buf->data,
+            s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data,
                             (size_t)s->init_num, s, s->msg_callback_arg);
     } else {
         if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
-            s->init_num + SSL3_HM_HEADER_LENGTH)) {
+                             s->init_num + SSL3_HM_HEADER_LENGTH)) {
             SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
             *len = 0;
@@ -521,10 +520,9 @@ int tls_get_message_body(SSL *s, unsigned long *len)
     return 1;
 }
 
-int ssl_cert_type(X509 *x, EVP_PKEY *pk)
+int ssl_cert_type(const X509 *x, const EVP_PKEY *pk)
 {
-    if (pk == NULL &&
-        (pk = X509_get0_pubkey(x)) == NULL)
+    if (pk == NULL && (pk = X509_get0_pubkey(x)) == NULL)
         return -1;
 
     switch (EVP_PKEY_id(pk)) {
@@ -638,8 +636,8 @@ static int version_cmp(const SSL *s, int a, int b)
 
 typedef struct {
     int version;
-    const SSL_METHOD *(*cmeth)(void);
-    const SSL_METHOD *(*smeth)(void);
+    const SSL_METHOD *(*cmeth) (void);
+    const SSL_METHOD *(*smeth) (void);
 } version_info;
 
 #if TLS_MAX_VERSION != TLS1_2_VERSION
@@ -648,26 +646,26 @@ typedef struct {
 
 static const version_info tls_version_table[] = {
 #ifndef OPENSSL_NO_TLS1_2
-    { TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method },
+    {TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method},
 #else
-    { TLS1_2_VERSION, NULL, NULL },
+    {TLS1_2_VERSION, NULL, NULL},
 #endif
 #ifndef OPENSSL_NO_TLS1_1
-    { TLS1_1_VERSION, tlsv1_1_client_method, tlsv1_1_server_method },
+    {TLS1_1_VERSION, tlsv1_1_client_method, tlsv1_1_server_method},
 #else
-    { TLS1_1_VERSION, NULL, NULL },
+    {TLS1_1_VERSION, NULL, NULL},
 #endif
 #ifndef OPENSSL_NO_TLS1
-    { TLS1_VERSION, tlsv1_client_method, tlsv1_server_method },
+    {TLS1_VERSION, tlsv1_client_method, tlsv1_server_method},
 #else
-    { TLS1_VERSION, NULL, NULL },
+    {TLS1_VERSION, NULL, NULL},
 #endif
 #ifndef OPENSSL_NO_SSL3
-    { SSL3_VERSION, sslv3_client_method, sslv3_server_method },
+    {SSL3_VERSION, sslv3_client_method, sslv3_server_method},
 #else
-    { SSL3_VERSION, NULL, NULL },
+    {SSL3_VERSION, NULL, NULL},
 #endif
-    { 0, NULL, NULL },
+    {0, NULL, NULL},
 };
 
 #if DTLS_MAX_VERSION != DTLS1_2_VERSION
@@ -676,16 +674,18 @@ static const version_info tls_version_table[] = {
 
 static const version_info dtls_version_table[] = {
 #ifndef OPENSSL_NO_DTLS1_2
-    { DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method },
+    {DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method},
 #else
-    { DTLS1_2_VERSION, NULL, NULL },
+    {DTLS1_2_VERSION, NULL, NULL},
 #endif
 #ifndef OPENSSL_NO_DTLS1
-    { DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method },
+    {DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method},
+    {DTLS1_BAD_VER, dtls_bad_ver_client_method, NULL},
 #else
-    { DTLS1_VERSION, NULL, NULL },
+    {DTLS1_VERSION, NULL, NULL},
+    {DTLS1_BAD_VER, NULL, NULL},
 #endif
-    { 0, NULL, NULL },
+    {0, NULL, NULL},
 };
 
 /*
@@ -706,7 +706,7 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
         return SSL_R_VERSION_TOO_LOW;
 
     if (s->max_proto_version != 0 &&
-             version_cmp(s, version, s->max_proto_version) > 0)
+        version_cmp(s, version, s->max_proto_version) > 0)
         return SSL_R_VERSION_TOO_HIGH;
 
     if ((s->options & method->mask) != 0)
@@ -793,8 +793,7 @@ int ssl_check_version_downgrade(SSL *s)
     }
 
     for (vent = table; vent->version != 0; ++vent) {
-        if (vent->smeth != NULL &&
-            ssl_method_error(s, vent->smeth()) == 0)
+        if (vent->smeth != NULL && ssl_method_error(s, vent->smeth()) == 0)
             return s->version == vent->version;
     }
     return 0;
@@ -848,7 +847,7 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
 
     case DTLS_ANY_VERSION:
         if (DTLS_VERSION_GT(version, DTLS_MAX_VERSION) ||
-            DTLS_VERSION_LT(version, DTLS1_VERSION))
+            DTLS_VERSION_LT(version, DTLS1_BAD_VER))
             return 0;
         break;
     }
@@ -994,7 +993,8 @@ int ssl_choose_client_version(SSL *s, int version)
  * Returns 0 on success or an SSL error reason number on failure.  On failure
  * min_version and max_version will also be set to 0.
  */
-int ssl_get_client_min_max_version(const SSL *s, int *min_version, int *max_version)
+int ssl_get_client_min_max_version(const SSL *s, int *min_version,
+                                   int *max_version)
 {
     int version;
     int hole;