Add SSL_SESSION_copy_without_early_data.

While we could store an extra boolean along with each session in the
session cache and then disable early data on a per-socket level, that
causes SSL_early_data_reason to report confusing values. Clearing it
at the session seems simpler. Since sessions are intended to be
mutable, do this as a copy operation.

Bug: chromium:1066623
Change-Id: I599b1559b696805e330ab5c2d61e4158440daef8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40464
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/ssl_session.cc b/ssl/ssl_session.cc
index 8819239..0d372cb 100644
--- a/ssl/ssl_session.cc
+++ b/ssl/ssl_session.cc
@@ -1060,6 +1060,24 @@
          session->ticket_max_early_data != 0;
 }
 
+SSL_SESSION *SSL_SESSION_copy_without_early_data(SSL_SESSION *session) {
+  if (!SSL_SESSION_early_data_capable(session)) {
+    return UpRef(session).release();
+  }
+
+  bssl::UniquePtr<SSL_SESSION> copy =
+      SSL_SESSION_dup(session, SSL_SESSION_DUP_ALL);
+  if (!copy) {
+    return nullptr;
+  }
+
+  copy->ticket_max_early_data = 0;
+  // Copied sessions are non-resumable until they're completely filled in.
+  copy->not_resumable = session->not_resumable;
+  assert(!SSL_SESSION_early_data_capable(copy.get()));
+  return copy.release();
+}
+
 SSL_SESSION *SSL_magic_pending_session_ptr(void) {
   return (SSL_SESSION *)&g_pending_session_magic;
 }