Support enabling early data on SSL

This moves the early data switch to CERT to make this
|SSL_set_SSL_CTX|-proof.

Change-Id: Icca96e76636d87578deb24b2d507cabee7e46a4a
Reviewed-on: https://boringssl-review.googlesource.com/14545
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index b476592..75862fc 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3095,6 +3095,11 @@
  * fully implemented. */
 OPENSSL_EXPORT void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled);
 
+/* SSL_set_early_data_enabled sets whether early data is allowed to be used
+ * with resumptions using |ssl|. See |SSL_CTX_set_early_data_enabled| for more
+ * information. */
+OPENSSL_EXPORT void SSL_set_early_data_enabled(SSL *ssl, int enabled);
+
 /* SSL_early_data_accepted returns whether early data was accepted on the
  * handshake performed by |ssl|. */
 OPENSSL_EXPORT int SSL_early_data_accepted(const SSL *ssl);
@@ -4254,10 +4259,6 @@
    * shutdown. */
   unsigned quiet_shutdown:1;
 
-  /* If enable_early_data is non-zero, early data can be sent and accepted over
-   * new connections. */
-  unsigned enable_early_data:1;
-
   /* ocsp_stapling_enabled is only used by client connections and indicates
    * whether OCSP stapling will be requested. */
   unsigned ocsp_stapling_enabled:1;
diff --git a/ssl/custom_extensions.c b/ssl/custom_extensions.c
index ea57c20..ac18517 100644
--- a/ssl/custom_extensions.c
+++ b/ssl/custom_extensions.c
@@ -69,7 +69,7 @@
     return 1;
   }
 
-  if (ssl->ctx->enable_early_data) {
+  if (ssl->cert->enable_early_data) {
     /* TODO(svaldez): Support Custom Extensions with 0-RTT. For now the caller
      * is expected not to configure both together.
      * https://crbug.com/boringssl/173. */
diff --git a/ssl/internal.h b/ssl/internal.h
index ded5ba8..2504ca0 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1371,6 +1371,9 @@
    * ticket key. Only sessions with a matching value will be accepted. */
   uint8_t sid_ctx_length;
   uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+  /* If enable_early_data is non-zero, early data can be sent and accepted. */
+  unsigned enable_early_data:1;
 } CERT;
 
 /* SSL_METHOD is a compatibility structure to support the legacy version-locked
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 5013b20..4722a66 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -204,6 +204,8 @@
   ret->sid_ctx_length = cert->sid_ctx_length;
   OPENSSL_memcpy(ret->sid_ctx, cert->sid_ctx, sizeof(ret->sid_ctx));
 
+  ret->enable_early_data = cert->enable_early_data;
+
   return ret;
 
 err:
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index d01f6a2..17e6521 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -832,7 +832,11 @@
 }
 
 void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) {
-  ctx->enable_early_data = !!enabled;
+  ctx->cert->enable_early_data = !!enabled;
+}
+
+void SSL_set_early_data_enabled(SSL *ssl, int enabled) {
+  ssl->cert->enable_early_data = !!enabled;
 }
 
 int SSL_early_data_accepted(const SSL *ssl) {
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 014432e..45a04c1 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -2095,7 +2095,7 @@
       session_version < TLS1_3_VERSION ||
       ssl->session->ticket_max_early_data == 0 ||
       hs->received_hello_retry_request ||
-      !ssl->ctx->enable_early_data) {
+      !ssl->cert->enable_early_data) {
     return 1;
   }
 
diff --git a/ssl/tls13_client.c b/ssl/tls13_client.c
index 0d60661..4c711e6 100644
--- a/ssl/tls13_client.c
+++ b/ssl/tls13_client.c
@@ -704,7 +704,7 @@
     goto err;
   }
 
-  if (have_early_data_info && ssl->ctx->enable_early_data) {
+  if (have_early_data_info && ssl->cert->enable_early_data) {
     if (!CBS_get_u32(&early_data_info, &session->ticket_max_early_data) ||
         CBS_len(&early_data_info) != 0) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index 35ee4f7..500cb9d 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -167,7 +167,7 @@
       goto err;
     }
 
-    if (ssl->ctx->enable_early_data) {
+    if (ssl->cert->enable_early_data) {
       session->ticket_max_early_data = kMaxEarlyDataAccepted;
 
       CBB early_data_info;
@@ -355,7 +355,7 @@
       hs->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
 
       if (/* Early data must be acceptable for this ticket. */
-          ssl->ctx->enable_early_data &&
+          ssl->cert->enable_early_data &&
           session->ticket_max_early_data != 0 &&
           /* The client must have offered early data. */
           hs->early_data_offered &&