Construct the server side early_data extension
authorMatt Caswell <matt@openssl.org>
Wed, 22 Feb 2017 13:01:48 +0000 (13:01 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 2 Mar 2017 17:44:15 +0000 (17:44 +0000)
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2737)

include/openssl/ssl.h
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/statem/extensions.c
ssl/statem/extensions_srvr.c
ssl/statem/statem.c
ssl/statem/statem_clnt.c
ssl/statem/statem_locl.h
util/libssl.num

index 597f77380da11c60fd1f87dc38804ca44c1a83c6..d2f9fc6daa600f3739cce1fa0f297f446e0dc102 100644 (file)
@@ -1629,6 +1629,12 @@ long SSL_callback_ctrl(SSL *, int, void (*)(void));
 long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
 long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
 
+# define SSL_EARLY_DATA_NOT_SENT    0
+# define SSL_EARLY_DATA_REJECTED    1
+# define SSL_EARLY_DATA_ACCEPTED    2
+
+__owur int SSL_get_early_data_status(SSL *s);
+
 __owur int SSL_get_error(const SSL *s, int ret_code);
 __owur const char *SSL_get_version(const SSL *s);
 
@@ -2374,6 +2380,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE             374
 # define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG           452
 # define SSL_F_TLS_CONSTRUCT_STOC_DONE                    375
+# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA              531
 # define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO         525
 # define SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS           453
 # define SSL_F_TLS_CONSTRUCT_STOC_EMS                     454
index 0620966172ad409b2f7cc0cbe506b5c98f036e36..d896ff9e58a6bdc5d7e605317919e8c146505f14 100644 (file)
@@ -362,6 +362,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG),
      "tls_construct_stoc_cryptopro_bug"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_DONE), "TLS_CONSTRUCT_STOC_DONE"},
+    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA),
+     "tls_construct_stoc_early_data"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO),
      "tls_construct_stoc_early_data_info"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS),
index e3e7853d602997103ff1365d4ee8b8c38ef406f9..a774452a6112dac35d3729043504e41910b52719 100644 (file)
@@ -1663,6 +1663,11 @@ int ssl_end_of_early_data_seen(SSL *s)
     return 0;
 }
 
+int SSL_get_early_data_status(SSL *s)
+{
+    return s->ext.early_data;
+}
+
 static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
 {
     if (s->handshake_func == NULL) {
index db1d7cfad3e8b8a027779a8941110f1f0ebe422a..3175009d80bf3191b89c1ad0a53e85e023717f16 100644 (file)
@@ -1182,8 +1182,8 @@ struct ssl_st {
         /* 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;
+        /* Are we expecting to receive early data? */
+        int early_data;
     } ext;
 
     /* Parsed form of the ClientHello, kept around across early_cb calls. */
index ccc60b6a26c6168694ecc5682b2b07fb7e6d5327..f8bd47a1e09344231c94e356acd9e4e64f41e1c3 100644 (file)
@@ -138,7 +138,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
     {
         TLSEXT_TYPE_early_data,
         EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
-        NULL, tls_parse_ctos_early_data, NULL, NULL,
+        NULL, tls_parse_ctos_early_data, NULL, tls_construct_stoc_early_data,
         tls_construct_ctos_early_data, NULL
     },
 #ifndef OPENSSL_NO_EC
index 8994ab9cc1b65cbb8037789da5285ec009d5d12d..57f38738d8737aab1f721f0edf6d1bf9d9124f4f 100644 (file)
@@ -170,7 +170,18 @@ int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
         return 0;
     }
 
-    s->ext.expect_early_data = 1;
+    if (s->max_early_data == 0 || !s->hit || s->session->ext.tick_identity != 0
+            || s->early_data_state != SSL_EARLY_DATA_ACCEPTING) {
+        s->ext.early_data = SSL_EARLY_DATA_REJECTED;
+    } else {
+        s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
+
+        if (!tls13_change_cipher_state(s,
+                    SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+            *al = SSL_AD_INTERNAL_ERROR;
+            return 0;
+        }
+    }
 
     return 1;
 }
@@ -832,6 +843,22 @@ int tls_construct_stoc_early_data_info(SSL *s, WPACKET *pkt,
     return 1;
 }
 
+int tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, unsigned int context,
+                                  X509 *x, size_t chainidx, int *al)
+{
+    if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
 #ifndef OPENSSL_NO_EC
 int tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, unsigned int context,
                                      X509 *x, size_t chainidx, int *al)
index 26c927321060de1113eb6da61b618feefabff931..9c74a2932e5d32c4f4371aa250d3900ac977d15a 100644 (file)
@@ -154,7 +154,7 @@ void ossl_statem_set_in_handshake(SSL *s, int inhand)
 /* 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)
+    if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
         return 0;
 
     if (s->statem.hand_state != TLS_ST_SW_FINISHED)
index e70ed10932b28f7c163e737fd9acad04ff37e44b..4f4409300e879713db280ec887f93d733131bf92 100644 (file)
@@ -714,7 +714,7 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
              */
             if (!tls13_change_cipher_state(s,
                         SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
-            return WORK_ERROR;
+                return WORK_ERROR;
         }
         break;
 
index 02c367910bc9313657ab92467e8ea99ac559c034..9dc9b1f515711efa094e499de6c61e35c38dd514 100644 (file)
@@ -235,6 +235,8 @@ int tls_construct_stoc_server_name(SSL *s, WPACKET *pkt, unsigned int context,
 int tls_construct_stoc_early_data_info(SSL *s, WPACKET *pkt,
                                        unsigned int context, X509 *x,
                                        size_t chainidx, int *al);
+int tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, unsigned int context,
+                                  X509 *x, size_t chainidx, int *al);
 #ifndef OPENSSL_NO_EC
 int tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, unsigned int context,
                                      X509 *x, size_t chainidx, int *al);
index 8d1f0b88b77995456039aee28012e9742661cc26..1d59a60dd0bce7ffb22f6d0eac458f6c34d583e2 100644 (file)
@@ -431,3 +431,4 @@ SSL_CTX_get_max_early_data              431 1_1_1   EXIST::FUNCTION:
 SSL_write_early                         432    1_1_1   EXIST::FUNCTION:
 SSL_write_early_finish                  433    1_1_1   EXIST::FUNCTION:
 SSL_read_early                          434    1_1_1   EXIST::FUNCTION:
+SSL_get_early_data_status               435    1_1_1   EXIST::FUNCTION: