Delay flush until after CCS with early_data
authorMatt Caswell <matt@openssl.org>
Thu, 30 Nov 2017 11:28:26 +0000 (11:28 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 14 Dec 2017 15:06:38 +0000 (15:06 +0000)
Normally we flush immediately after writing the ClientHello. However if
we are going to write a CCS immediately because we've got early_data to
come, then we should move the flush until after the CCS.

Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/4701)

ssl/statem/extensions_clnt.c
ssl/statem/statem_clnt.c

index f357396..2b39459 100644 (file)
@@ -1664,9 +1664,9 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
          * TLSv1.3, therefore we shouldn't be getting an HRR for anything else.
          */
         if (version != TLS1_3_VERSION) {
-            *al = SSL_AD_PROTOCOL_VERSION;
-            SSLerr(SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
-                   SSL_R_BAD_HRR_VERSION);
+            SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+                     SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
+                     SSL_R_BAD_HRR_VERSION);
             return 0;
         }
         return 1;
index 80148fa..6313b31 100644 (file)
@@ -679,27 +679,30 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
         break;
 
     case TLS_ST_CW_CLNT_HELLO:
-        if (wst == WORK_MORE_A && statem_flush(s) != 1)
-            return WORK_MORE_A;
-
-        if (SSL_IS_DTLS(s)) {
-            /* Treat the next message as the first packet */
-            s->first_packet = 1;
-        }
-
         if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
-                && s->max_early_data > 0
-                && (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) {
+                && s->max_early_data > 0) {
             /*
              * We haven't selected TLSv1.3 yet so we don't call the change
              * cipher state function associated with the SSL_METHOD. Instead
              * we call tls13_change_cipher_state() directly.
              */
-            if (!tls13_change_cipher_state(s,
-                        SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
-                /* SSLfatal() already called */
-                return WORK_ERROR;
+            if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) {
+                if (!statem_flush(s))
+                    return WORK_MORE_A;
+                if (!tls13_change_cipher_state(s,
+                            SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+                    /* SSLfatal() already called */
+                    return WORK_ERROR;
+                }
             }
+            /* else we're in compat mode so we delay flushing until after CCS */
+        } else if (!statem_flush(s)) {
+            return WORK_MORE_A;
+        }
+
+        if (SSL_IS_DTLS(s)) {
+            /* Treat the next message as the first packet */
+            s->first_packet = 1;
         }
         break;
 
@@ -724,6 +727,8 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
             break;
         if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
                     && s->max_early_data > 0) {
+            if (statem_flush(s) != 1)
+                return WORK_MORE_A;
             /*
              * We haven't selected TLSv1.3 yet so we don't call the change
              * cipher state function associated with the SSL_METHOD. Instead