Construct the server side early_data extension

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2737)
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index ccc60b6..f8bd47a 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -138,7 +138,7 @@
     {
         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
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 8994ab9..57f3873 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -170,7 +170,18 @@
         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 @@
     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)
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index 26c9273..9c74a29 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -154,7 +154,7 @@
 /* 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)
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index e70ed10..4f44093 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -714,7 +714,7 @@
              */
             if (!tls13_change_cipher_state(s,
                         SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
-            return WORK_ERROR;
+                return WORK_ERROR;
         }
         break;
 
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index 02c3679..9dc9b1f 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -235,6 +235,8 @@
 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);