Parse the early_data extension
authorMatt Caswell <matt@openssl.org>
Mon, 20 Feb 2017 16:35:03 +0000 (16:35 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 2 Mar 2017 17:44:15 +0000 (17:44 +0000)
We also skip any early_data that subsequently gets sent. Later commits will
process it if we can.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2737)

ssl/record/ssl3_record.c
ssl/ssl_locl.h
ssl/statem/extensions.c
ssl/statem/extensions_srvr.c
ssl/statem/statem.c
ssl/statem/statem.h
ssl/statem/statem_locl.h

index 3868bb5d82ed5e89fc58639ddc57bff72ce9bcae..4a1c0413a145669f0dae1b52f5a166138022d20b 100644 (file)
@@ -424,6 +424,17 @@ int ssl3_get_record(SSL *s)
      *    -1: if the padding is invalid
      */
     if (enc_err == 0) {
      *    -1: if the padding is invalid
      */
     if (enc_err == 0) {
+        if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
+            /*
+             * We assume this is unreadable early_data - we treat it like an
+             * empty record
+             */
+            thisrr = &rr[0];
+            thisrr->length = 0;
+            thisrr->read = 1;
+            RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
+            return 1;
+        }
         al = SSL_AD_DECRYPTION_FAILED;
         SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
         goto f_err;
         al = SSL_AD_DECRYPTION_FAILED;
         SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
         goto f_err;
index a1689726132306804ed544632cc0863e1c2d6585..2aef000a7d8725de39c2b30f596a9a13168815fd 100644 (file)
@@ -1176,6 +1176,9 @@ struct ssl_st {
 
         /* Set to one if we have negotiated ETM */
         int use_etm;
 
         /* Set to one if we have negotiated ETM */
         int use_etm;
+
+        /* Set to 1 if we are expecting to receive early data */
+        int expect_early_data;
     } ext;
 
     /* Parsed form of the ClientHello, kept around across early_cb calls. */
     } ext;
 
     /* Parsed form of the ClientHello, kept around across early_cb calls. */
index a2efd0a73924ce95858a5d8cd3ea21f9b8282cb6..ccc60b6a26c6168694ecc5682b2b07fb7e6d5327 100644 (file)
@@ -138,7 +138,8 @@ static const EXTENSION_DEFINITION ext_defs[] = {
     {
         TLSEXT_TYPE_early_data,
         EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
     {
         TLSEXT_TYPE_early_data,
         EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
-        NULL, NULL, NULL, NULL, tls_construct_ctos_early_data, NULL
+        NULL, tls_parse_ctos_early_data, NULL, NULL,
+        tls_construct_ctos_early_data, NULL
     },
 #ifndef OPENSSL_NO_EC
     {
     },
 #ifndef OPENSSL_NO_EC
     {
index 690cc30cf31d80095a483bbe3f0028f25d19957e..8994ab9cc1b65cbb8037789da5285ec009d5d12d 100644 (file)
@@ -162,6 +162,19 @@ int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 }
 #endif
 
 }
 #endif
 
+int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al)
+{
+    if (PACKET_remaining(pkt) != 0) {
+        *al = SSL_AD_DECODE_ERROR;
+        return 0;
+    }
+
+    s->ext.expect_early_data = 1;
+
+    return 1;
+}
+
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al)
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al)
index 10d794ede7fdb35dce999690e6f597e570cb73a4..9ec8e85426763084dcf8c3234422f3f2237956d3 100644 (file)
@@ -151,6 +151,18 @@ void ossl_statem_set_in_handshake(SSL *s, int inhand)
         s->statem.in_handshake--;
 }
 
         s->statem.in_handshake--;
 }
 
+/* Are we in a sensible state to skip over unreadable early data? */
+int ossl_statem_skip_early_data(SSL *s)
+{
+    if (!s->ext.expect_early_data)
+        return 0;
+
+    if (s->statem.hand_state != TLS_ST_SW_FINISHED)
+        return 0;
+
+    return 1;
+}
+
 void ossl_statem_set_hello_verify_done(SSL *s)
 {
     s->statem.state = MSG_FLOW_UNINITED;
 void ossl_statem_set_hello_verify_done(SSL *s)
 {
     s->statem.state = MSG_FLOW_UNINITED;
index 906f2ec5bc00c7235b87d24e0684fcb27a81671f..5bb74d029f341db9fb3100cfb15fe220e50330a9 100644 (file)
@@ -122,6 +122,7 @@ int ossl_statem_in_error(const SSL *s);
 void ossl_statem_set_in_init(SSL *s, int init);
 int ossl_statem_get_in_handshake(SSL *s);
 void ossl_statem_set_in_handshake(SSL *s, int inhand);
 void ossl_statem_set_in_init(SSL *s, int init);
 int ossl_statem_get_in_handshake(SSL *s);
 void ossl_statem_set_in_handshake(SSL *s, int inhand);
+__owur int ossl_statem_skip_early_data(SSL *s);
 void ossl_statem_set_hello_verify_done(SSL *s);
 __owur int ossl_statem_app_data_allowed(SSL *s);
 #ifndef OPENSSL_NO_SCTP
 void ossl_statem_set_hello_verify_done(SSL *s);
 __owur int ossl_statem_app_data_allowed(SSL *s);
 #ifndef OPENSSL_NO_SCTP
index 99eb8ed319993fa38c838397820e3de5e0b70122..02c367910bc9313657ab92467e8ea99ac559c034 100644 (file)
@@ -191,6 +191,8 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
 int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx, int *al);
 #endif
 int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx, int *al);
 #endif
+int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al);
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al);
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al);