Move libssl's internals into the bssl namespace.

This is horrible, but everything else I tried was worse. The goal with
this CL is to take the extern "C" out of ssl/internal.h and move most
symbols to namespace bssl, so we can start using C++ helpers and
destructors without worry.

Complications:

- Public API functions must be extern "C" and match their declaration in
  ssl.h, which is unnamespaced. C++ really does not want you to
  interleave namespaced and unnamespaced things. One can actually write
  a namespaced extern "C" function, but this means, from C++'s
  perspective, the function is namespaced. Trying to namespace the
  public header would worked but ended up too deep a rabbithole.

- Our STACK_OF macros do not work right in namespaces.

- The typedefs for our exposed but opaque types are visible in the
  header files and copied into consuming projects as forward
  declarations. We ultimately want to give SSL a destructor, but
  clobbering an unnamespaced ssl_st::~ssl_st seems bad manners.

- MSVC complains about ambiguous names if one typedefs SSL to bssl::SSL.

This CL opts for:

- ssl/*.cc must begin with #define BORINGSSL_INTERNAL_CXX_TYPES. This
  informs the public headers to create forward declarations which are
  compatible with our namespaces.

- For now, C++-defined type FOO ends up at bssl::FOO with a typedef
  outside. Later I imagine we'll rename many of them.

- Internal functions get namespace bssl, so we stop worrying about
  stomping the tls1_prf symbol. Exported C functions are stuck as they
  are. Rather than try anything weird, bite the bullet and reorder files
  which have a mix of public and private functions. I expect that over
  time, the public functions will become fairly small as we move logic
  to more idiomatic C++.

  Files without any public C functions can just be written normally.

- To avoid MSVC troubles, some bssl types are renamed to CPlusPlusStyle
  in advance of them being made idiomatic C++.

Bug: 132
Change-Id: Ic931895e117c38b14ff8d6e5a273e868796c7581
Reviewed-on: https://boringssl-review.googlesource.com/18124
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 460c1e0..d67e997 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -317,11 +317,8 @@
 typedef struct srtp_protection_profile_st SRTP_PROTECTION_PROFILE;
 typedef struct ssl_cipher_st SSL_CIPHER;
 typedef struct ssl_ctx_st SSL_CTX;
-typedef struct ssl_custom_extension SSL_CUSTOM_EXTENSION;
-typedef struct ssl_method_st SSL_METHOD;
 typedef struct ssl_private_key_method_st SSL_PRIVATE_KEY_METHOD;
 typedef struct ssl_session_st SSL_SESSION;
-typedef struct ssl_st SSL;
 typedef struct ssl_ticket_aead_method_st SSL_TICKET_AEAD_METHOD;
 typedef struct st_ERR_FNS ERR_FNS;
 typedef struct v3_ext_ctx X509V3_CTX;
@@ -338,6 +335,25 @@
 
 typedef void *OPENSSL_BLOCK;
 
+/* The following opaque types are visible in public header files but are defined
+ * internally in C++. For compatibility with projects which copy the historical
+ * typedefs in forward declarations, the typedefs cannot change for external
+ * consumers. The C++ implementation files define |BORINGSSL_INTERNAL_CXX_TYPES|
+ * to namespace the underlying types. */
+#if defined(BORINGSSL_INTERNAL_CXX_TYPES)
+extern "C++" {
+namespace bssl {
+struct SSLConnection;
+struct SSLMethod;
+}
+using SSL = bssl::SSLConnection;
+using SSL_METHOD = bssl::SSLMethod;
+}
+#else
+typedef struct ssl_st SSL;
+typedef struct ssl_method_st SSL_METHOD;
+#endif
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 4a1a726..e60bb88 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3983,8 +3983,26 @@
  * This structures are exposed for historical reasons, but access to them is
  * deprecated. */
 
+/* TODO(davidben): Opaquify most or all of |SSL_CTX| and |SSL_SESSION| so these
+ * forward declarations are not needed. */
+#if defined(BORINGSSL_INTERNAL_CXX_TYPES)
+extern "C++" {
+namespace bssl {
+struct CERT;
+struct SSLProtocolMethod;
+struct SSLX509Method;
+}
+using SSL_CERT_CONFIG = bssl::CERT;
+using SSL_PROTOCOL_METHOD = bssl::SSLProtocolMethod;
+using SSL_X509_METHOD = bssl::SSLX509Method;
+}
+#else
+typedef struct ssl_cert_config_st SSL_CERT_CONFIG;
 typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD;
 typedef struct ssl_x509_method_st SSL_X509_METHOD;
+#endif
+
+DECLARE_STACK_OF(SSL_CUSTOM_EXTENSION)
 
 struct ssl_cipher_st {
   /* name is the OpenSSL name for the cipher. */
@@ -4169,8 +4187,6 @@
   uint8_t *in_group_flags;
 };
 
-DECLARE_STACK_OF(SSL_CUSTOM_EXTENSION)
-
 /* ssl_ctx_st (aka |SSL_CTX|) contains configuration common to several SSL
  * connections. */
 struct ssl_ctx_st {
@@ -4282,7 +4298,7 @@
   uint32_t mode;
   uint32_t max_cert_list;
 
-  struct cert_st /* CERT */ *cert;
+  SSL_CERT_CONFIG *cert;
 
   /* callback that allows applications to peek at protocol messages */
   void (*msg_callback)(int write_p, int version, int content_type,
diff --git a/ssl/custom_extensions.cc b/ssl/custom_extensions.cc
index f438f73..84463fa 100644
--- a/ssl/custom_extensions.cc
+++ b/ssl/custom_extensions.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -25,6 +27,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension) {
   OPENSSL_free(custom_extension);
 }
@@ -246,6 +250,10 @@
   return 1;
 }
 
+}  // namespace bssl
+
+using namespace bssl;
+
 int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned extension_value,
                                   SSL_custom_ext_add_cb add_cb,
                                   SSL_custom_ext_free_cb free_cb, void *add_arg,
diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc
index ee0ec4f..cc1de90 100644
--- a/ssl/d1_both.cc
+++ b/ssl/d1_both.cc
@@ -111,6 +111,8 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -127,6 +129,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 /* TODO(davidben): 28 comes from the size of IP + UDP header. Is this reasonable
  * for these values? Notably, why is kMinMTU a function of the transport
  * protocol's overhead rather than, say, what's needed to hold a minimally-sized
@@ -812,3 +816,5 @@
 unsigned int dtls1_min_mtu(void) {
   return kMinMTU;
 }
+
+}  // namespace bssl
diff --git a/ssl/d1_lib.cc b/ssl/d1_lib.cc
index 0074855..73f9797 100644
--- a/ssl/d1_lib.cc
+++ b/ssl/d1_lib.cc
@@ -54,6 +54,8 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -68,6 +70,7 @@
 #include "internal.h"
 
 
+namespace bssl {
 
 /* DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire
  * before starting to decrease the MTU. */
@@ -113,10 +116,6 @@
   ssl->d1 = NULL;
 }
 
-void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
-  ssl->initial_timeout_duration_ms = duration_ms;
-}
-
 void dtls1_start_timer(SSL *ssl) {
   /* If timer is not set, initialize duration (by default, 1 second) */
   if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
@@ -135,56 +134,6 @@
   }
 }
 
-int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
-  if (!SSL_is_dtls(ssl)) {
-    return 0;
-  }
-
-  /* If no timeout is set, just return NULL */
-  if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
-    return 0;
-  }
-
-  struct OPENSSL_timeval timenow;
-  ssl_get_current_time(ssl, &timenow);
-
-  /* If timer already expired, set remaining time to 0 */
-  if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
-      (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
-       ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
-    OPENSSL_memset(out, 0, sizeof(*out));
-    return 1;
-  }
-
-  /* Calculate time left until timer expires */
-  struct OPENSSL_timeval ret;
-  OPENSSL_memcpy(&ret, &ssl->d1->next_timeout, sizeof(ret));
-  ret.tv_sec -= timenow.tv_sec;
-  if (ret.tv_usec >= timenow.tv_usec) {
-    ret.tv_usec -= timenow.tv_usec;
-  } else {
-    ret.tv_usec = 1000000 + ret.tv_usec - timenow.tv_usec;
-    ret.tv_sec--;
-  }
-
-  /* If remaining time is less than 15 ms, set it to 0 to prevent issues
-   * because of small divergences with socket timeouts. */
-  if (ret.tv_sec == 0 && ret.tv_usec < 15000) {
-    OPENSSL_memset(&ret, 0, sizeof(ret));
-  }
-
-  /* Clamp the result in case of overflow. */
-  if (ret.tv_sec > INT_MAX) {
-    assert(0);
-    out->tv_sec = INT_MAX;
-  } else {
-    out->tv_sec = ret.tv_sec;
-  }
-
-  out->tv_usec = ret.tv_usec;
-  return 1;
-}
-
 int dtls1_is_timer_expired(SSL *ssl) {
   struct timeval timeleft;
 
@@ -241,6 +190,64 @@
   return 0;
 }
 
+}  // namespace bssl
+
+using namespace bssl;
+
+void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
+  ssl->initial_timeout_duration_ms = duration_ms;
+}
+
+int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
+  if (!SSL_is_dtls(ssl)) {
+    return 0;
+  }
+
+  /* If no timeout is set, just return NULL */
+  if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
+    return 0;
+  }
+
+  struct OPENSSL_timeval timenow;
+  ssl_get_current_time(ssl, &timenow);
+
+  /* If timer already expired, set remaining time to 0 */
+  if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
+      (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
+       ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
+    OPENSSL_memset(out, 0, sizeof(*out));
+    return 1;
+  }
+
+  /* Calculate time left until timer expires */
+  struct OPENSSL_timeval ret;
+  OPENSSL_memcpy(&ret, &ssl->d1->next_timeout, sizeof(ret));
+  ret.tv_sec -= timenow.tv_sec;
+  if (ret.tv_usec >= timenow.tv_usec) {
+    ret.tv_usec -= timenow.tv_usec;
+  } else {
+    ret.tv_usec = 1000000 + ret.tv_usec - timenow.tv_usec;
+    ret.tv_sec--;
+  }
+
+  /* If remaining time is less than 15 ms, set it to 0 to prevent issues
+   * because of small divergences with socket timeouts. */
+  if (ret.tv_sec == 0 && ret.tv_usec < 15000) {
+    OPENSSL_memset(&ret, 0, sizeof(ret));
+  }
+
+  /* Clamp the result in case of overflow. */
+  if (ret.tv_sec > INT_MAX) {
+    assert(0);
+    out->tv_sec = INT_MAX;
+  } else {
+    out->tv_sec = ret.tv_sec;
+  }
+
+  out->tv_usec = ret.tv_usec;
+  return 1;
+}
+
 int DTLSv1_handle_timeout(SSL *ssl) {
   ssl_reset_error_state(ssl);
 
diff --git a/ssl/d1_pkt.cc b/ssl/d1_pkt.cc
index 1ae55eb..189c85b 100644
--- a/ssl/d1_pkt.cc
+++ b/ssl/d1_pkt.cc
@@ -109,6 +109,8 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -126,6 +128,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 int dtls1_get_record(SSL *ssl) {
 again:
   switch (ssl->s3->recv_shutdown) {
@@ -415,3 +419,5 @@
 
   return 1;
 }
+
+}  // namespace bssl
diff --git a/ssl/d1_srtp.cc b/ssl/d1_srtp.cc
index 1085377..829e8ba 100644
--- a/ssl/d1_srtp.cc
+++ b/ssl/d1_srtp.cc
@@ -114,6 +114,8 @@
   Copyright (C) 2011, RTFM, Inc.
 */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <string.h>
@@ -124,6 +126,8 @@
 #include "internal.h"
 
 
+using namespace bssl;
+
 static const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
     {
         "SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80,
@@ -143,9 +147,7 @@
 static int find_profile_by_name(const char *profile_name,
                                 const SRTP_PROTECTION_PROFILE **pptr,
                                 size_t len) {
-  const SRTP_PROTECTION_PROFILE *p;
-
-  p = kSRTPProfiles;
+  const SRTP_PROTECTION_PROFILE *p = kSRTPProfiles;
   while (p->name) {
     if (len == strlen(p->name) && !strncmp(p->name, profile_name, len)) {
       *pptr = p;
diff --git a/ssl/dtls_method.cc b/ssl/dtls_method.cc
index dd8d786..426c6a8 100644
--- a/ssl/dtls_method.cc
+++ b/ssl/dtls_method.cc
@@ -54,6 +54,8 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -66,6 +68,8 @@
 #include "internal.h"
 
 
+using namespace bssl;
+
 static int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
   return cipher->algorithm_enc != SSL_eNULL;
 }
diff --git a/ssl/dtls_record.cc b/ssl/dtls_record.cc
index 879706d..5546471 100644
--- a/ssl/dtls_record.cc
+++ b/ssl/dtls_record.cc
@@ -109,6 +109,8 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -121,6 +123,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 /* to_u64_be treats |in| as a 8-byte big-endian integer and returns the value as
  * a |uint64_t|. */
 static uint64_t to_u64_be(const uint8_t in[8]) {
@@ -332,3 +336,5 @@
 
   return 1;
 }
+
+}  // namespace bssl
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index e60b6ae..cd3ee9a 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -147,6 +147,8 @@
  * OTHERWISE.
  */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -168,6 +170,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static int ssl3_send_client_hello(SSL_HANDSHAKE *hs);
 static int dtls1_get_hello_verify_request(SSL_HANDSHAKE *hs);
 static int ssl3_get_server_hello(SSL_HANDSHAKE *hs);
@@ -653,7 +657,7 @@
 
 int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  bssl::ScopedCBB cbb;
+  ScopedCBB cbb;
   CBB body;
   if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO)) {
     return 0;
@@ -1515,7 +1519,7 @@
 
 static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  bssl::ScopedCBB cbb;
+  ScopedCBB cbb;
   CBB body;
   if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_CLIENT_KEY_EXCHANGE)) {
@@ -1696,7 +1700,7 @@
   SSL *const ssl = hs->ssl;
   assert(ssl_has_private_key(ssl));
 
-  bssl::ScopedCBB cbb;
+  ScopedCBB cbb;
   CBB body, child;
   if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_CERTIFICATE_VERIFY)) {
@@ -1894,3 +1898,5 @@
   }
   return -1;
 }
+
+}  // namespace bssl
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc
index 00ac549..85c1c82 100644
--- a/ssl/handshake_server.cc
+++ b/ssl/handshake_server.cc
@@ -146,6 +146,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -170,6 +172,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 static int ssl3_process_client_hello(SSL_HANDSHAKE *hs);
 static int ssl3_select_certificate(SSL_HANDSHAKE *hs);
 static int ssl3_select_parameters(SSL_HANDSHAKE *hs);
@@ -825,12 +829,12 @@
 
   /* Determine whether we are doing session resumption. */
   int tickets_supported = 0, renew_ticket = 0;
-  /* TODO(davidben): Switch |ssl_get_prev_session| to take a |bssl::UniquePtr|
+  /* TODO(davidben): Switch |ssl_get_prev_session| to take a |UniquePtr|
    * output and simplify this. */
   SSL_SESSION *session_raw = nullptr;
   auto session_ret = ssl_get_prev_session(ssl, &session_raw, &tickets_supported,
                                           &renew_ticket, &client_hello);
-  bssl::UniquePtr<SSL_SESSION> session(session_raw);
+  UniquePtr<SSL_SESSION> session(session_raw);
   switch (session_ret) {
     case ssl_session_success:
       break;
@@ -1001,7 +1005,7 @@
 
 static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  bssl::ScopedCBB cbb;
+  ScopedCBB cbb;
 
   if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
     if (!ssl_has_certificate(ssl)) {
@@ -1722,3 +1726,5 @@
 
   return ssl3_send_finished(hs);
 }
+
+}  // namespace bssl
diff --git a/ssl/internal.h b/ssl/internal.h
index e2a3af4..d7a3af8 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -142,6 +142,10 @@
 #ifndef OPENSSL_HEADER_SSL_INTERNAL_H
 #define OPENSSL_HEADER_SSL_INTERNAL_H
 
+#if !defined(BORINGSSL_INTERNAL_CXX_TYPES)
+#error "Files including this header must define BORINGSSL_INTERNAL_CXX_TYPES before including any headers"
+#endif
+
 #include <openssl/base.h>
 
 #include <openssl/aead.h>
@@ -158,12 +162,10 @@
 #include <sys/time.h>
 #endif
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
 
+namespace bssl {
 
-typedef struct ssl_handshake_st SSL_HANDSHAKE;
+struct SSL_HANDSHAKE;
 
 /* Protocol versions.
  *
@@ -314,7 +316,7 @@
 
 /* SSL_TRANSCRIPT maintains the handshake transcript as a combination of a
  * buffer and running hash. */
-typedef struct ssl_transcript_st {
+struct SSL_TRANSCRIPT {
   /* buffer, if non-NULL, contains the handshake transcript. */
   BUF_MEM *buffer;
   /* hash, if initialized with an |EVP_MD|, maintains the handshake hash. For
@@ -323,7 +325,7 @@
   /* md5, if initialized with an |EVP_MD|, maintains the MD5 half of the
    * handshake hash for TLS 1.1 and below. */
   EVP_MD_CTX md5;
-} SSL_TRANSCRIPT;
+};
 
 /* SSL_TRANSCRIPT_init initializes the handshake transcript. If called on an
  * existing transcript, it resets the transcript and hash. It returns one on
@@ -395,7 +397,7 @@
 
 /* SSL_AEAD_CTX contains information about an AEAD that is being used to encrypt
  * an SSL connection. */
-typedef struct ssl_aead_ctx_st {
+struct SSL_AEAD_CTX {
   const SSL_CIPHER *cipher;
   EVP_AEAD_CTX ctx;
   /* fixed_nonce contains any bytes of the nonce that are fixed for all
@@ -422,7 +424,7 @@
   /* xor_fixed_nonce is non-zero if the fixed nonce should be XOR'd into the
    * variable nonce rather than prepended. */
   unsigned xor_fixed_nonce : 1;
-} SSL_AEAD_CTX;
+};
 
 /* SSL_AEAD_CTX_new creates a newly-allocated |SSL_AEAD_CTX| using the supplied
  * key material. It returns NULL on error. Only one of |SSL_AEAD_CTX_open| or
@@ -502,14 +504,14 @@
 
 /* DTLS1_BITMAP maintains a sliding window of 64 sequence numbers to detect
  * replayed packets. It should be initialized by zeroing every field. */
-typedef struct dtls1_bitmap_st {
+struct DTLS1_BITMAP {
   /* map is a bit mask of the last 64 sequence numbers. Bit
    * |1<<i| corresponds to |max_seq_num - i|. */
   uint64_t map;
   /* max_seq_num is the largest sequence number seen so far as a 64-bit
    * integer. */
   uint64_t max_seq_num;
-} DTLS1_BITMAP;
+};
 
 
 /* Record layer. */
@@ -658,21 +660,26 @@
 
 /* Custom extensions */
 
-/* ssl_custom_extension (a.k.a. SSL_CUSTOM_EXTENSION) is a structure that
- * contains information about custom-extension callbacks. */
-struct ssl_custom_extension {
+}  // namespace bssl
+
+/* |SSL_CUSTOM_EXTENSION| is a structure that contains information about
+ * custom-extension callbacks. It is defined unnamespaced for compatibility with
+ * |STACK_OF(SSL_CUSTOM_EXTENSION)|. */
+typedef struct ssl_custom_extension {
   SSL_custom_ext_add_cb add_callback;
   void *add_arg;
   SSL_custom_ext_free_cb free_callback;
   SSL_custom_ext_parse_cb parse_callback;
   void *parse_arg;
   uint16_t value;
-};
-
-void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension);
+} SSL_CUSTOM_EXTENSION;
 
 DEFINE_STACK_OF(SSL_CUSTOM_EXTENSION)
 
+namespace bssl {
+
+void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension);
+
 int custom_ext_add_clienthello(SSL_HANDSHAKE *hs, CBB *extensions);
 int custom_ext_parse_serverhello(SSL_HANDSHAKE *hs, int *out_alert,
                                  uint16_t value, const CBS *extension);
@@ -683,11 +690,11 @@
 
 /* ECDH groups. */
 
-typedef struct ssl_ecdh_ctx_st SSL_ECDH_CTX;
+struct SSL_ECDH_CTX;
 
 /* An SSL_ECDH_METHOD is an implementation of ECDH-like key exchanges for
  * TLS. */
-typedef struct ssl_ecdh_method_st {
+struct SSL_ECDH_METHOD {
   int nid;
   uint16_t group_id;
   const char name[8];
@@ -718,9 +725,9 @@
   int (*finish)(SSL_ECDH_CTX *ctx, uint8_t **out_secret, size_t *out_secret_len,
                 uint8_t *out_alert, const uint8_t *peer_key,
                 size_t peer_key_len);
-} SSL_ECDH_METHOD;
+};
 
-struct ssl_ecdh_ctx_st {
+struct SSL_ECDH_CTX {
   const SSL_ECDH_METHOD *method;
   void *data;
 };
@@ -785,12 +792,12 @@
  * messages ahead of the current message and zero otherwise. */
 int dtls_has_incoming_messages(const SSL *ssl);
 
-typedef struct dtls_outgoing_message_st {
+struct DTLS_OUTGOING_MESSAGE {
   uint8_t *data;
   uint32_t len;
   uint16_t epoch;
   char is_ccs;
-} DTLS_OUTGOING_MESSAGE;
+};
 
 /* dtls_clear_outgoing_messages releases all buffered outgoing messages. */
 void dtls_clear_outgoing_messages(SSL *ssl);
@@ -1010,7 +1017,7 @@
   ssl_hs_certificate_verify,
 };
 
-struct ssl_handshake_st {
+struct SSL_HANDSHAKE {
   /* ssl is a non-owning pointer to the parent |SSL| object. */
   SSL *ssl;
 
@@ -1237,7 +1244,7 @@
   /* early_data_written is the amount of early data that has been written by the
    * record layer. */
   uint16_t early_data_written;
-} /* SSL_HANDSHAKE */;
+};
 
 SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
 
@@ -1327,11 +1334,11 @@
 int ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                        const SSL_CLIENT_HELLO *client_hello);
 
-typedef struct {
+struct SSL_EXTENSION_TYPE {
   uint16_t type;
   int *out_present;
   CBS *out_data;
-} SSL_EXTENSION_TYPE;
+};
 
 /* ssl_parse_extensions parses a TLS extensions block out of |cbs| and advances
  * it. It writes the parsed extensions to pointers denoted by |ext_types|. On
@@ -1420,7 +1427,7 @@
 /* From RFC4492, used in encoding the curve type in ECParameters */
 #define NAMED_CURVE_TYPE 3
 
-typedef struct cert_st {
+struct CERT {
   EVP_PKEY *privatekey;
 
   /* chain contains the certificate chain, with the leaf at the beginning. The
@@ -1485,11 +1492,11 @@
 
   /* 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
- * methods. */
-struct ssl_method_st {
+/* SSLMethod backs the public |SSL_METHOD| type. It is a compatibility structure
+ * to support the legacy version-locked methods. */
+struct SSLMethod {
   /* version, if non-zero, is the only protocol version acceptable to an
    * SSL_CTX initialized from this method. */
   uint16_t version;
@@ -1501,8 +1508,9 @@
   const SSL_X509_METHOD *x509_method;
 };
 
-/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
-struct ssl_protocol_method_st {
+/* SSLProtocolMethod is use to hold functions for SSLv2 or SSLv3/TLSv1
+ * functions */
+struct SSLProtocolMethod {
   /* is_dtls is one if the protocol is DTLS and zero otherwise. */
   char is_dtls;
   int (*ssl_new)(SSL *ssl);
@@ -1570,7 +1578,7 @@
   int (*set_write_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
 };
 
-struct ssl_x509_method_st {
+struct SSLX509Method {
   /* check_client_CA_list returns one if |names| is a good list of X.509
    * distinguished names and zero otherwise. This is used to ensure that we can
    * reject unparsable values at handshake time when using crypto/x509. */
@@ -1626,20 +1634,20 @@
   void (*ssl_ctx_flush_cached_client_CA)(SSL_CTX *ssl);
 };
 
-/* ssl_crypto_x509_method provides the |ssl_x509_method_st| functions using
+/* ssl_crypto_x509_method provides the |SSL_X509_METHOD| functions using
  * crypto/x509. */
-extern const struct ssl_x509_method_st ssl_crypto_x509_method;
+extern const SSL_X509_METHOD ssl_crypto_x509_method;
 
-typedef struct ssl3_record_st {
+struct SSL3_RECORD {
   /* type is the record type. */
   uint8_t type;
   /* length is the number of unconsumed bytes in the record. */
   uint16_t length;
   /* data is a non-owning pointer to the first unconsumed byte of the record. */
   uint8_t *data;
-} SSL3_RECORD;
+};
 
-typedef struct ssl3_buffer_st {
+struct SSL3_BUFFER {
   /* buf is the memory allocated for this buffer. */
   uint8_t *buf;
   /* offset is the offset into |buf| which the buffer contents start at. */
@@ -1648,7 +1656,7 @@
   uint16_t len;
   /* cap is how much memory beyond |buf| + |offset| is available. */
   uint16_t cap;
-} SSL3_BUFFER;
+};
 
 /* An ssl_shutdown_t describes the shutdown state of one end of the connection,
  * whether it is alive or has been shutdown via close_notify or fatal alert. */
@@ -1658,7 +1666,7 @@
   ssl_shutdown_fatal_alert = 2,
 };
 
-typedef struct ssl3_state_st {
+struct SSL3_STATE {
   uint8_t read_sequence[8];
   uint8_t write_sequence[8];
 
@@ -1825,7 +1833,7 @@
    * ticket age and the server-computed value in TLS 1.3 server connections
    * which resumed a session. */
   int32_t ticket_age_skew;
-} SSL3_STATE;
+};
 
 /* lengths of messages */
 #define DTLS1_COOKIE_LENGTH 256
@@ -1847,7 +1855,7 @@
 };
 
 /* An hm_fragment is an incoming DTLS message, possibly not yet assembled. */
-typedef struct hm_fragment_st {
+struct hm_fragment {
   /* type is the type of the message. */
   uint8_t type;
   /* seq is the sequence number of this message. */
@@ -1860,14 +1868,14 @@
   /* reassembly is a bitmask of |msg_len| bits corresponding to which parts of
    * the message have been received. It is NULL if the message is complete. */
   uint8_t *reassembly;
-} hm_fragment;
+};
 
 struct OPENSSL_timeval {
   uint64_t tv_sec;
   uint32_t tv_usec;
 };
 
-typedef struct dtls1_state_st {
+struct DTLS1_STATE {
   /* send_cookie is true if we are resending the ClientHello
    * with a cookie from a HelloVerifyRequest. */
   unsigned int send_cookie;
@@ -1919,9 +1927,10 @@
 
   /* timeout_duration_ms is the timeout duration in milliseconds. */
   unsigned timeout_duration_ms;
-} DTLS1_STATE;
+};
 
-struct ssl_st {
+/* SSLConnection backs the public |SSL| type. */
+struct SSLConnection {
   /* method is the method table corresponding to the current protocol (DTLS or
    * TLS). */
   const SSL_PROTOCOL_METHOD *method;
@@ -1960,8 +1969,8 @@
   /* init_num is the length of the current handshake message body. */
   uint32_t init_num;
 
-  struct ssl3_state_st *s3;  /* SSLv3 variables */
-  struct dtls1_state_st *d1; /* DTLSv1 variables */
+  SSL3_STATE *s3;  /* SSLv3 variables */
+  DTLS1_STATE *d1; /* DTLSv1 variables */
 
   /* callback that allows applications to peek at protocol messages */
   void (*msg_callback)(int write_p, int version, int content_type,
@@ -1977,7 +1986,7 @@
 
   /* client cert? */
   /* This is used to hold the server certificate used */
-  struct cert_st /* CERT */ *cert;
+  CERT *cert;
 
   /* This holds a variable that indicates what we were doing when a 0 or -1 is
    * returned.  This is needed for non-blocking IO so we know what request
@@ -2390,9 +2399,7 @@
 #define SSL_FALLTHROUGH
 #endif
 
+}  // namespace bssl
 
-#if defined(__cplusplus)
-} /* extern C */
-#endif
 
 #endif /* OPENSSL_HEADER_SSL_INTERNAL_H */
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index 85de99c..785d66a 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -110,6 +110,8 @@
  * ECC cipher suite support in OpenSSL originally developed by
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -130,6 +132,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
   SSL_HANDSHAKE *hs = (SSL_HANDSHAKE *)OPENSSL_malloc(sizeof(SSL_HANDSHAKE));
   if (hs == NULL) {
@@ -861,3 +865,5 @@
 
   return ret;
 }
+
+}  // namespace bssl
diff --git a/ssl/s3_lib.cc b/ssl/s3_lib.cc
index 9548bbd..cd39524 100644
--- a/ssl/s3_lib.cc
+++ b/ssl/s3_lib.cc
@@ -146,6 +146,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -162,6 +164,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 int ssl3_new(SSL *ssl) {
   SSL3_STATE *s3 = (SSL3_STATE *)OPENSSL_malloc(sizeof *s3);
   if (s3 == NULL) {
@@ -215,3 +219,5 @@
 
   return ssl->ctx->cipher_list;
 }
+
+}  // namespace bssl
diff --git a/ssl/s3_pkt.cc b/ssl/s3_pkt.cc
index 4ae2e34..9d4b057 100644
--- a/ssl/s3_pkt.cc
+++ b/ssl/s3_pkt.cc
@@ -106,6 +106,8 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -122,6 +124,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len);
 
 /* ssl3_get_record reads a new input record. On success, it places it in
@@ -590,3 +594,5 @@
 
   return 1;
 }
+
+}  // namespace bssl
diff --git a/ssl/ssl_aead_ctx.cc b/ssl/ssl_aead_ctx.cc
index 5264a65..e7e4cb5 100644
--- a/ssl/ssl_aead_ctx.cc
+++ b/ssl/ssl_aead_ctx.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -25,6 +27,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
                                uint16_t version, int is_dtls,
                                const SSL_CIPHER *cipher, const uint8_t *enc_key,
@@ -363,3 +367,5 @@
   *out_len = prefix_len + in_len + suffix_len;
   return 1;
 }
+
+}  // namespace bssl
diff --git a/ssl/ssl_asn1.cc b/ssl/ssl_asn1.cc
index 1d6140e..d8b1bd6 100644
--- a/ssl/ssl_asn1.cc
+++ b/ssl/ssl_asn1.cc
@@ -87,6 +87,8 @@
 #define __STDC_LIMIT_MACROS
 #endif
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <limits.h>
@@ -102,6 +104,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 /* An SSL_SESSION is serialized as the following ASN.1 structure:
  *
  * SSLSession ::= SEQUENCE {
@@ -422,55 +426,6 @@
   return 0;
 }
 
-int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
-                         size_t *out_len) {
-  if (in->not_resumable) {
-    /* If the caller has an unresumable session, e.g. if |SSL_get_session| were
-     * called on a TLS 1.3 or False Started connection, serialize with a
-     * placeholder value so it is not accidentally deserialized into a resumable
-     * one. */
-    static const char kNotResumableSession[] = "NOT RESUMABLE";
-
-    *out_len = strlen(kNotResumableSession);
-    *out_data = (uint8_t *)BUF_memdup(kNotResumableSession, *out_len);
-    if (*out_data == NULL) {
-      return 0;
-    }
-
-    return 1;
-  }
-
-  return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
-}
-
-int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data,
-                                    size_t *out_len) {
-  return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1);
-}
-
-int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) {
-  uint8_t *out;
-  size_t len;
-
-  if (!SSL_SESSION_to_bytes(in, &out, &len)) {
-    return -1;
-  }
-
-  if (len > INT_MAX) {
-    OPENSSL_free(out);
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return -1;
-  }
-
-  if (pp) {
-    OPENSSL_memcpy(*pp, out, len);
-    *pp += len;
-  }
-  OPENSSL_free(out);
-
-  return len;
-}
-
 /* SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING
  * explicitly tagged with |tag| from |cbs| and saves it in |*out|. On
  * entry, if |*out| is not NULL, it frees the existing contents. If
@@ -805,6 +760,59 @@
   return NULL;
 }
 
+}  // namespace bssl
+
+using namespace bssl;
+
+int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
+                         size_t *out_len) {
+  if (in->not_resumable) {
+    /* If the caller has an unresumable session, e.g. if |SSL_get_session| were
+     * called on a TLS 1.3 or False Started connection, serialize with a
+     * placeholder value so it is not accidentally deserialized into a resumable
+     * one. */
+    static const char kNotResumableSession[] = "NOT RESUMABLE";
+
+    *out_len = strlen(kNotResumableSession);
+    *out_data = (uint8_t *)BUF_memdup(kNotResumableSession, *out_len);
+    if (*out_data == NULL) {
+      return 0;
+    }
+
+    return 1;
+  }
+
+  return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
+}
+
+int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data,
+                                    size_t *out_len) {
+  return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1);
+}
+
+int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) {
+  uint8_t *out;
+  size_t len;
+
+  if (!SSL_SESSION_to_bytes(in, &out, &len)) {
+    return -1;
+  }
+
+  if (len > INT_MAX) {
+    OPENSSL_free(out);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return -1;
+  }
+
+  if (pp) {
+    OPENSSL_memcpy(*pp, out, len);
+    *pp += len;
+  }
+  OPENSSL_free(out);
+
+  return len;
+}
+
 SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len,
                                     const SSL_CTX *ctx) {
   CBS cbs;
diff --git a/ssl/ssl_buffer.cc b/ssl/ssl_buffer.cc
index 579899b..c5b5608 100644
--- a/ssl/ssl_buffer.cc
+++ b/ssl/ssl_buffer.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -27,6 +29,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 /* BIO uses int instead of size_t. No lengths will exceed uint16_t, so this will
  * not overflow. */
 static_assert(0xffff <= INT_MAX, "uint16_t does not fit in int");
@@ -289,3 +293,5 @@
 void ssl_write_buffer_clear(SSL *ssl) {
   clear_buffer(&ssl->s3->write_buffer);
 }
+
+}  // namespace bssl
diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc
index a9f334e..61d35b9 100644
--- a/ssl/ssl_cert.cc
+++ b/ssl/ssl_cert.cc
@@ -112,6 +112,8 @@
  * ECC cipher suite support in OpenSSL originally developed by
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -131,6 +133,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 CERT *ssl_cert_new(const SSL_X509_METHOD *x509_method) {
   CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
   if (ret == NULL) {
@@ -340,20 +344,6 @@
   return 1;
 }
 
-int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs,
-                          size_t num_certs, EVP_PKEY *privkey,
-                          const SSL_PRIVATE_KEY_METHOD *privkey_method) {
-  return cert_set_chain_and_key(ssl->cert, certs, num_certs, privkey,
-                                privkey_method);
-}
-
-int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
-                              size_t num_certs, EVP_PKEY *privkey,
-                              const SSL_PRIVATE_KEY_METHOD *privkey_method) {
-  return cert_set_chain_and_key(ctx->cert, certs, num_certs, privkey,
-                                privkey_method);
-}
-
 int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
   switch (check_leaf_cert_and_privkey(buffer, cert->privatekey)) {
     case leaf_cert_and_privkey_error:
@@ -393,29 +383,6 @@
   return 1;
 }
 
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
-                                 const uint8_t *der) {
-  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
-  if (buffer == NULL) {
-    return 0;
-  }
-
-  const int ok = ssl_set_cert(ctx->cert, buffer);
-  CRYPTO_BUFFER_free(buffer);
-  return ok;
-}
-
-int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
-  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
-  if (buffer == NULL) {
-    return 0;
-  }
-
-  const int ok = ssl_set_cert(ssl->cert, buffer);
-  CRYPTO_BUFFER_free(buffer);
-  return ok;
-}
-
 int ssl_has_certificate(const SSL *ssl) {
   return ssl->cert->chain != NULL &&
          sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0) != NULL &&
@@ -781,31 +748,6 @@
   return CBB_flush(cbb);
 }
 
-void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
-                         void *arg) {
-  ssl_cert_set_cert_cb(ctx->cert, cb, arg);
-}
-
-void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
-  ssl_cert_set_cert_cb(ssl->cert, cb, arg);
-}
-
-STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) {
-  SSL_SESSION *session = SSL_get_session(ssl);
-  if (session == NULL) {
-    return NULL;
-  }
-
-  return session->certs;
-}
-
-STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs(const SSL *ssl) {
-  if (ssl->s3->hs == NULL) {
-    return NULL;
-  }
-  return ssl->s3->hs->ca_names;
-}
-
 int ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey,
                                const CRYPTO_BUFFER *leaf) {
   SSL *const ssl = hs->ssl;
@@ -866,6 +808,72 @@
   return hs->local_pubkey != NULL;
 }
 
+}  // namespace bssl
+
+using namespace bssl;
+
+int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs,
+                          size_t num_certs, EVP_PKEY *privkey,
+                          const SSL_PRIVATE_KEY_METHOD *privkey_method) {
+  return cert_set_chain_and_key(ssl->cert, certs, num_certs, privkey,
+                                privkey_method);
+}
+
+int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
+                              size_t num_certs, EVP_PKEY *privkey,
+                              const SSL_PRIVATE_KEY_METHOD *privkey_method) {
+  return cert_set_chain_and_key(ctx->cert, certs, num_certs, privkey,
+                                privkey_method);
+}
+
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
+                                 const uint8_t *der) {
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  const int ok = ssl_set_cert(ctx->cert, buffer);
+  CRYPTO_BUFFER_free(buffer);
+  return ok;
+}
+
+int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  const int ok = ssl_set_cert(ssl->cert, buffer);
+  CRYPTO_BUFFER_free(buffer);
+  return ok;
+}
+
+void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
+                         void *arg) {
+  ssl_cert_set_cert_cb(ctx->cert, cb, arg);
+}
+
+void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
+  ssl_cert_set_cert_cb(ssl->cert, cb, arg);
+}
+
+STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) {
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return NULL;
+  }
+
+  return session->certs;
+}
+
+STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs(const SSL *ssl) {
+  if (ssl->s3->hs == NULL) {
+    return NULL;
+  }
+  return ssl->s3->hs->ca_names;
+}
+
 static int set_signed_cert_timestamp_list(CERT *cert, const uint8_t *list,
                                            size_t list_len) {
   CBS sct_list;
diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc
index c0f4122..ecf87e8 100644
--- a/ssl/ssl_cipher.cc
+++ b/ssl/ssl_cipher.cc
@@ -138,6 +138,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -154,6 +156,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 /* kCiphers is an array of all supported ciphers, sorted by id. */
 static const SSL_CIPHER kCiphers[] = {
     /* The RSA ciphers */
@@ -643,14 +647,6 @@
   }
 }
 
-const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) {
-  SSL_CIPHER c;
-
-  c.id = 0x03000000L | value;
-  return reinterpret_cast<const SSL_CIPHER *>(bsearch(
-      &c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER), ssl_cipher_id_cmp));
-}
-
 int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
                             size_t *out_mac_secret_len,
                             size_t *out_fixed_iv_len,
@@ -1371,8 +1367,6 @@
   return 0;
 }
 
-uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
-
 uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher) {
   uint32_t id = cipher->id;
   /* All ciphers are SSLv3. */
@@ -1380,6 +1374,68 @@
   return id & 0xffff;
 }
 
+uint32_t ssl_cipher_auth_mask_for_key(const EVP_PKEY *key) {
+  switch (EVP_PKEY_id(key)) {
+    case EVP_PKEY_RSA:
+      return SSL_aRSA;
+    case EVP_PKEY_EC:
+    case EVP_PKEY_ED25519:
+      /* Ed25519 keys in TLS 1.2 repurpose the ECDSA ciphers. */
+      return SSL_aECDSA;
+    default:
+      return 0;
+  }
+}
+
+int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) {
+  return (cipher->algorithm_auth & SSL_aCERT) != 0;
+}
+
+int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
+  /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
+  if (cipher->algorithm_mkey & SSL_kECDHE) {
+    return 1;
+  }
+
+  /* It is optional in all others. */
+  return 0;
+}
+
+size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher) {
+  size_t block_size;
+  switch (cipher->algorithm_enc) {
+    case SSL_3DES:
+      block_size = 8;
+      break;
+    case SSL_AES128:
+    case SSL_AES256:
+      block_size = 16;
+      break;
+    default:
+      return 0;
+  }
+
+  /* All supported TLS 1.0 ciphers use SHA-1. */
+  assert(cipher->algorithm_mac == SSL_SHA1);
+  size_t ret = 1 + SHA_DIGEST_LENGTH;
+  ret += block_size - (ret % block_size);
+  return ret;
+}
+
+}  // namespace bssl
+
+using namespace bssl;
+
+const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) {
+  SSL_CIPHER c;
+
+  c.id = 0x03000000L | value;
+  return reinterpret_cast<const SSL_CIPHER *>(bsearch(
+      &c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER), ssl_cipher_id_cmp));
+}
+
+uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
+
 int SSL_CIPHER_is_AES(const SSL_CIPHER *cipher) {
   return (cipher->algorithm_enc & SSL_AES) != 0;
 }
@@ -1697,51 +1753,3 @@
 const char *SSL_COMP_get_name(const COMP_METHOD *comp) { return NULL; }
 
 void SSL_COMP_free_compression_methods(void) {}
-
-uint32_t ssl_cipher_auth_mask_for_key(const EVP_PKEY *key) {
-  switch (EVP_PKEY_id(key)) {
-    case EVP_PKEY_RSA:
-      return SSL_aRSA;
-    case EVP_PKEY_EC:
-    case EVP_PKEY_ED25519:
-      /* Ed25519 keys in TLS 1.2 repurpose the ECDSA ciphers. */
-      return SSL_aECDSA;
-    default:
-      return 0;
-  }
-}
-
-int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) {
-  return (cipher->algorithm_auth & SSL_aCERT) != 0;
-}
-
-int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
-  /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
-  if (cipher->algorithm_mkey & SSL_kECDHE) {
-    return 1;
-  }
-
-  /* It is optional in all others. */
-  return 0;
-}
-
-size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher) {
-  size_t block_size;
-  switch (cipher->algorithm_enc) {
-    case SSL_3DES:
-      block_size = 8;
-      break;
-    case SSL_AES128:
-    case SSL_AES256:
-      block_size = 16;
-      break;
-    default:
-      return 0;
-  }
-
-  /* All supported TLS 1.0 ciphers use SHA-1. */
-  assert(cipher->algorithm_mac == SSL_SHA1);
-  size_t ret = 1 + SHA_DIGEST_LENGTH;
-  ret += block_size - (ret % block_size);
-  return ret;
-}
diff --git a/ssl/ssl_ecdh.cc b/ssl/ssl_ecdh.cc
index fa1cbe9..137f30a 100644
--- a/ssl/ssl_ecdh.cc
+++ b/ssl/ssl_ecdh.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -29,6 +31,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 /* |EC_POINT| implementation. */
 
 static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) {
@@ -38,15 +42,15 @@
 
 static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
   /* Set up a shared |BN_CTX| for all operations. */
-  bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
+  UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
   if (!bn_ctx) {
     return 0;
   }
-  bssl::BN_CTXScope scope(bn_ctx.get());
+  BN_CTXScope scope(bn_ctx.get());
 
   /* Generate a private key. */
-  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
-  bssl::UniquePtr<BIGNUM> private_key(BN_new());
+  UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
+  UniquePtr<BIGNUM> private_key(BN_new());
   if (!group || !private_key ||
       !BN_rand_range_ex(private_key.get(), 1,
                         EC_GROUP_get0_order(group.get()))) {
@@ -54,7 +58,7 @@
   }
 
   /* Compute the corresponding public key and serialize it. */
-  bssl::UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get()));
+  UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get()));
   if (!public_key ||
       !EC_POINT_mul(group.get(), public_key.get(), private_key.get(), NULL,
                     NULL, bn_ctx.get()) ||
@@ -76,19 +80,19 @@
   *out_alert = SSL_AD_INTERNAL_ERROR;
 
   /* Set up a shared |BN_CTX| for all operations. */
-  bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
+  UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
   if (!bn_ctx) {
     return 0;
   }
-  bssl::BN_CTXScope scope(bn_ctx.get());
+  BN_CTXScope scope(bn_ctx.get());
 
-  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
+  UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
   if (!group) {
     return 0;
   }
 
-  bssl::UniquePtr<EC_POINT> peer_point(EC_POINT_new(group.get()));
-  bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
+  UniquePtr<EC_POINT> peer_point(EC_POINT_new(group.get()));
+  UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
   BIGNUM *x = BN_CTX_get(bn_ctx.get());
   if (!peer_point || !result || !x) {
     return 0;
@@ -110,7 +114,7 @@
 
   /* Encode the x-coordinate left-padded with zeros. */
   size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8;
-  bssl::UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
+  UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
   if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) {
     return 0;
   }
@@ -271,14 +275,6 @@
   return NULL;
 }
 
-const char* SSL_get_curve_name(uint16_t group_id) {
-  const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
-  if (method == NULL) {
-    return NULL;
-  }
-  return method->name;
-}
-
 int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
   const SSL_ECDH_METHOD *method = method_from_nid(nid);
   if (method == NULL) {
@@ -340,3 +336,15 @@
   return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert,
                              peer_key, peer_key_len);
 }
+
+}  // namespace bssl
+
+using namespace bssl;
+
+const char* SSL_get_curve_name(uint16_t group_id) {
+  const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
+  if (method == NULL) {
+    return NULL;
+  }
+  return method->name;
+}
diff --git a/ssl/ssl_file.cc b/ssl/ssl_file.cc
index 59351a3..05643ed 100644
--- a/ssl/ssl_file.cc
+++ b/ssl/ssl_file.cc
@@ -108,6 +108,8 @@
  *
  */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <errno.h>
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index b2d5f02..1808fb2 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -138,6 +138,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -162,6 +164,8 @@
 #endif
 
 
+namespace bssl {
+
 /* |SSL_R_UNKNOWN_PROTOCOL| is no longer emitted, but continue to define it
  * to avoid downstream churn. */
 OPENSSL_DECLARE_ERROR_REASON(SSL, UNKNOWN_PROTOCOL)
@@ -185,6 +189,225 @@
 static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx =
     CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
 
+void ssl_reset_error_state(SSL *ssl) {
+  /* Functions which use |SSL_get_error| must reset I/O and error state on
+   * entry. */
+  ssl->rwstate = SSL_NOTHING;
+  ERR_clear_error();
+  ERR_clear_system_error();
+}
+
+int ssl_can_write(const SSL *ssl) {
+  return !SSL_in_init(ssl) || ssl->s3->hs->can_early_write;
+}
+
+int ssl_can_read(const SSL *ssl) {
+  return !SSL_in_init(ssl) || ssl->s3->hs->can_early_read;
+}
+
+void ssl_cipher_preference_list_free(
+    struct ssl_cipher_preference_list_st *cipher_list) {
+  if (cipher_list == NULL) {
+    return;
+  }
+  sk_SSL_CIPHER_free(cipher_list->ciphers);
+  OPENSSL_free(cipher_list->in_group_flags);
+  OPENSSL_free(cipher_list);
+}
+
+void ssl_update_cache(SSL_HANDSHAKE *hs, int mode) {
+  SSL *const ssl = hs->ssl;
+  SSL_CTX *ctx = ssl->session_ctx;
+  /* Never cache sessions with empty session IDs. */
+  if (ssl->s3->established_session->session_id_length == 0 ||
+      (ctx->session_cache_mode & mode) != mode) {
+    return;
+  }
+
+  /* Clients never use the internal session cache. */
+  int use_internal_cache = ssl->server && !(ctx->session_cache_mode &
+                                            SSL_SESS_CACHE_NO_INTERNAL_STORE);
+
+  /* A client may see new sessions on abbreviated handshakes if the server
+   * decides to renew the ticket. Once the handshake is completed, it should be
+   * inserted into the cache. */
+  if (ssl->s3->established_session != ssl->session ||
+      (!ssl->server && hs->ticket_expected)) {
+    if (use_internal_cache) {
+      SSL_CTX_add_session(ctx, ssl->s3->established_session);
+    }
+    if (ctx->new_session_cb != NULL) {
+      SSL_SESSION_up_ref(ssl->s3->established_session);
+      if (!ctx->new_session_cb(ssl, ssl->s3->established_session)) {
+        /* |new_session_cb|'s return value signals whether it took ownership. */
+        SSL_SESSION_free(ssl->s3->established_session);
+      }
+    }
+  }
+
+  if (use_internal_cache &&
+      !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR)) {
+    /* Automatically flush the internal session cache every 255 connections. */
+    int flush_cache = 0;
+    CRYPTO_MUTEX_lock_write(&ctx->lock);
+    ctx->handshakes_since_cache_flush++;
+    if (ctx->handshakes_since_cache_flush >= 255) {
+      flush_cache = 1;
+      ctx->handshakes_since_cache_flush = 0;
+    }
+    CRYPTO_MUTEX_unlock_write(&ctx->lock);
+
+    if (flush_cache) {
+      struct OPENSSL_timeval now;
+      ssl_get_current_time(ssl, &now);
+      SSL_CTX_flush_sessions(ctx, now.tv_sec);
+    }
+  }
+}
+
+static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
+  static const char hextable[] = "0123456789abcdef";
+  uint8_t *out;
+
+  if (!CBB_add_space(cbb, &out, in_len * 2)) {
+    return 0;
+  }
+
+  for (size_t i = 0; i < in_len; i++) {
+    *(out++) = (uint8_t)hextable[in[i] >> 4];
+    *(out++) = (uint8_t)hextable[in[i] & 0xf];
+  }
+
+  return 1;
+}
+
+int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
+                   size_t secret_len) {
+  if (ssl->ctx->keylog_callback == NULL) {
+    return 1;
+  }
+
+  CBB cbb;
+  uint8_t *out;
+  size_t out_len;
+  if (!CBB_init(&cbb, strlen(label) + 1 + SSL3_RANDOM_SIZE * 2 + 1 +
+                          secret_len * 2 + 1) ||
+      !CBB_add_bytes(&cbb, (const uint8_t *)label, strlen(label)) ||
+      !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
+      !cbb_add_hex(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+      !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
+      !cbb_add_hex(&cbb, secret, secret_len) ||
+      !CBB_add_u8(&cbb, 0 /* NUL */) ||
+      !CBB_finish(&cbb, &out, &out_len)) {
+    CBB_cleanup(&cbb);
+    return 0;
+  }
+
+  ssl->ctx->keylog_callback(ssl, (const char *)out);
+  OPENSSL_free(out);
+  return 1;
+}
+
+int ssl3_can_false_start(const SSL *ssl) {
+  const SSL_CIPHER *const cipher = SSL_get_current_cipher(ssl);
+
+  /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */
+  return !SSL_is_dtls(ssl) &&
+      SSL_version(ssl) == TLS1_2_VERSION &&
+      (ssl->s3->alpn_selected != NULL ||
+       ssl->s3->next_proto_negotiated != NULL) &&
+      cipher != NULL &&
+      cipher->algorithm_mkey == SSL_kECDHE &&
+      cipher->algorithm_mac == SSL_AEAD;
+}
+
+void ssl_do_info_callback(const SSL *ssl, int type, int value) {
+  void (*cb)(const SSL *ssl, int type, int value) = NULL;
+  if (ssl->info_callback != NULL) {
+    cb = ssl->info_callback;
+  } else if (ssl->ctx->info_callback != NULL) {
+    cb = ssl->ctx->info_callback;
+  }
+
+  if (cb != NULL) {
+    cb(ssl, type, value);
+  }
+}
+
+void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+                         const void *buf, size_t len) {
+  if (ssl->msg_callback == NULL) {
+    return;
+  }
+
+  /* |version| is zero when calling for |SSL3_RT_HEADER| and |SSL2_VERSION| for
+   * a V2ClientHello. */
+  int version;
+  switch (content_type) {
+    case 0:
+      /* V2ClientHello */
+      version = SSL2_VERSION;
+      break;
+    case SSL3_RT_HEADER:
+      version = 0;
+      break;
+    default:
+      version = SSL_version(ssl);
+  }
+
+  ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
+                    ssl->msg_callback_arg);
+}
+
+void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock) {
+  if (ssl->ctx->current_time_cb != NULL) {
+    /* TODO(davidben): Update current_time_cb to use OPENSSL_timeval. See
+     * https://crbug.com/boringssl/155. */
+    struct timeval clock;
+    ssl->ctx->current_time_cb(ssl, &clock);
+    if (clock.tv_sec < 0) {
+      assert(0);
+      out_clock->tv_sec = 0;
+      out_clock->tv_usec = 0;
+    } else {
+      out_clock->tv_sec = (uint64_t)clock.tv_sec;
+      out_clock->tv_usec = (uint32_t)clock.tv_usec;
+    }
+    return;
+  }
+
+#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+  out_clock->tv_sec = 1234;
+  out_clock->tv_usec = 1234;
+#elif defined(OPENSSL_WINDOWS)
+  struct _timeb time;
+  _ftime(&time);
+  if (time.time < 0) {
+    assert(0);
+    out_clock->tv_sec = 0;
+    out_clock->tv_usec = 0;
+  } else {
+    out_clock->tv_sec = time.time;
+    out_clock->tv_usec = time.millitm * 1000;
+  }
+#else
+  struct timeval clock;
+  gettimeofday(&clock, NULL);
+  if (clock.tv_sec < 0) {
+    assert(0);
+    out_clock->tv_sec = 0;
+    out_clock->tv_usec = 0;
+  } else {
+    out_clock->tv_sec = (uint64_t)clock.tv_sec;
+    out_clock->tv_usec = (uint32_t)clock.tv_usec;
+  }
+#endif
+}
+
+}  // namespace bssl
+
+using namespace bssl;
+
 int SSL_library_init(void) {
   CRYPTO_library_init();
   return 1;
@@ -562,14 +785,6 @@
 
 BIO *SSL_get_wbio(const SSL *ssl) { return ssl->wbio; }
 
-void ssl_reset_error_state(SSL *ssl) {
-  /* Functions which use |SSL_get_error| must reset I/O and error state on
-   * entry. */
-  ssl->rwstate = SSL_NOTHING;
-  ERR_clear_error();
-  ERR_clear_system_error();
-}
-
 int SSL_do_handshake(SSL *ssl) {
   ssl_reset_error_state(ssl);
 
@@ -621,14 +836,6 @@
   return SSL_do_handshake(ssl);
 }
 
-int ssl_can_write(const SSL *ssl) {
-  return !SSL_in_init(ssl) || ssl->s3->hs->can_early_write;
-}
-
-int ssl_can_read(const SSL *ssl) {
-  return !SSL_in_init(ssl) || ssl->s3->hs->can_early_read;
-}
-
 static int ssl_do_renegotiate(SSL *ssl) {
   /* We do not accept renegotiations as a server or SSL 3.0. SSL 3.0 will be
    * removed entirely in the future and requires retaining more data for
@@ -1108,16 +1315,6 @@
   return ssl->cert->sid_ctx;
 }
 
-void ssl_cipher_preference_list_free(
-    struct ssl_cipher_preference_list_st *cipher_list) {
-  if (cipher_list == NULL) {
-    return;
-  }
-  sk_SSL_CIPHER_free(cipher_list->ciphers);
-  OPENSSL_free(cipher_list->in_group_flags);
-  OPENSSL_free(cipher_list);
-}
-
 void SSL_certs_clear(SSL *ssl) { ssl_cert_clear_certs(ssl->cert); }
 
 int SSL_get_fd(const SSL *ssl) { return SSL_get_rfd(ssl); }
@@ -1820,56 +2017,6 @@
   return ssl->s3->hs->num_certificate_types;
 }
 
-void ssl_update_cache(SSL_HANDSHAKE *hs, int mode) {
-  SSL *const ssl = hs->ssl;
-  SSL_CTX *ctx = ssl->session_ctx;
-  /* Never cache sessions with empty session IDs. */
-  if (ssl->s3->established_session->session_id_length == 0 ||
-      (ctx->session_cache_mode & mode) != mode) {
-    return;
-  }
-
-  /* Clients never use the internal session cache. */
-  int use_internal_cache = ssl->server && !(ctx->session_cache_mode &
-                                            SSL_SESS_CACHE_NO_INTERNAL_STORE);
-
-  /* A client may see new sessions on abbreviated handshakes if the server
-   * decides to renew the ticket. Once the handshake is completed, it should be
-   * inserted into the cache. */
-  if (ssl->s3->established_session != ssl->session ||
-      (!ssl->server && hs->ticket_expected)) {
-    if (use_internal_cache) {
-      SSL_CTX_add_session(ctx, ssl->s3->established_session);
-    }
-    if (ctx->new_session_cb != NULL) {
-      SSL_SESSION_up_ref(ssl->s3->established_session);
-      if (!ctx->new_session_cb(ssl, ssl->s3->established_session)) {
-        /* |new_session_cb|'s return value signals whether it took ownership. */
-        SSL_SESSION_free(ssl->s3->established_session);
-      }
-    }
-  }
-
-  if (use_internal_cache &&
-      !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR)) {
-    /* Automatically flush the internal session cache every 255 connections. */
-    int flush_cache = 0;
-    CRYPTO_MUTEX_lock_write(&ctx->lock);
-    ctx->handshakes_since_cache_flush++;
-    if (ctx->handshakes_since_cache_flush >= 255) {
-      flush_cache = 1;
-      ctx->handshakes_since_cache_flush = 0;
-    }
-    CRYPTO_MUTEX_unlock_write(&ctx->lock);
-
-    if (flush_cache) {
-      struct OPENSSL_timeval now;
-      ssl_get_current_time(ssl, &now);
-      SSL_CTX_flush_sessions(ctx, now.tv_sec);
-    }
-  }
-}
-
 EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
   if (ssl->cert != NULL) {
     return ssl->cert->privatekey;
@@ -2169,49 +2316,6 @@
   ctx->current_time_cb = cb;
 }
 
-static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
-  static const char hextable[] = "0123456789abcdef";
-  uint8_t *out;
-
-  if (!CBB_add_space(cbb, &out, in_len * 2)) {
-    return 0;
-  }
-
-  for (size_t i = 0; i < in_len; i++) {
-    *(out++) = (uint8_t)hextable[in[i] >> 4];
-    *(out++) = (uint8_t)hextable[in[i] & 0xf];
-  }
-
-  return 1;
-}
-
-int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
-                   size_t secret_len) {
-  if (ssl->ctx->keylog_callback == NULL) {
-    return 1;
-  }
-
-  CBB cbb;
-  uint8_t *out;
-  size_t out_len;
-  if (!CBB_init(&cbb, strlen(label) + 1 + SSL3_RANDOM_SIZE * 2 + 1 +
-                          secret_len * 2 + 1) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)label, strlen(label)) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
-      !cbb_add_hex(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
-      !cbb_add_hex(&cbb, secret, secret_len) ||
-      !CBB_add_u8(&cbb, 0 /* NUL */) ||
-      !CBB_finish(&cbb, &out, &out_len)) {
-    CBB_cleanup(&cbb);
-    return 0;
-  }
-
-  ssl->ctx->keylog_callback(ssl, (const char *)out);
-  OPENSSL_free(out);
-  return 1;
-}
-
 int SSL_is_init_finished(const SSL *ssl) {
   return !SSL_in_init(ssl);
 }
@@ -2239,19 +2343,6 @@
   *ssl_session_size = sizeof(SSL_SESSION);
 }
 
-int ssl3_can_false_start(const SSL *ssl) {
-  const SSL_CIPHER *const cipher = SSL_get_current_cipher(ssl);
-
-  /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */
-  return !SSL_is_dtls(ssl) &&
-      SSL_version(ssl) == TLS1_2_VERSION &&
-      (ssl->s3->alpn_selected != NULL ||
-       ssl->s3->next_proto_negotiated != NULL) &&
-      cipher != NULL &&
-      cipher->algorithm_mkey == SSL_kECDHE &&
-      cipher->algorithm_mac == SSL_AEAD;
-}
-
 int SSL_is_server(const SSL *ssl) { return ssl->server; }
 
 int SSL_is_dtls(const SSL *ssl) { return ssl->method->is_dtls; }
@@ -2422,44 +2513,6 @@
   return 1;
 }
 
-void ssl_do_info_callback(const SSL *ssl, int type, int value) {
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
-  if (cb != NULL) {
-    cb(ssl, type, value);
-  }
-}
-
-void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
-                         const void *buf, size_t len) {
-  if (ssl->msg_callback == NULL) {
-    return;
-  }
-
-  /* |version| is zero when calling for |SSL3_RT_HEADER| and |SSL2_VERSION| for
-   * a V2ClientHello. */
-  int version;
-  switch (content_type) {
-    case 0:
-      /* V2ClientHello */
-      version = SSL2_VERSION;
-      break;
-    case SSL3_RT_HEADER:
-      version = 0;
-      break;
-    default:
-      version = SSL_version(ssl);
-  }
-
-  ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
-                    ssl->msg_callback_arg);
-}
-
 int SSL_CTX_sess_connect(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_connect_good(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx) { return 0; }
@@ -2502,51 +2555,6 @@
   return SSL_set1_curves(ssl, &nid, 1);
 }
 
-void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock) {
-  if (ssl->ctx->current_time_cb != NULL) {
-    /* TODO(davidben): Update current_time_cb to use OPENSSL_timeval. See
-     * https://crbug.com/boringssl/155. */
-    struct timeval clock;
-    ssl->ctx->current_time_cb(ssl, &clock);
-    if (clock.tv_sec < 0) {
-      assert(0);
-      out_clock->tv_sec = 0;
-      out_clock->tv_usec = 0;
-    } else {
-      out_clock->tv_sec = (uint64_t)clock.tv_sec;
-      out_clock->tv_usec = (uint32_t)clock.tv_usec;
-    }
-    return;
-  }
-
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
-  out_clock->tv_sec = 1234;
-  out_clock->tv_usec = 1234;
-#elif defined(OPENSSL_WINDOWS)
-  struct _timeb time;
-  _ftime(&time);
-  if (time.time < 0) {
-    assert(0);
-    out_clock->tv_sec = 0;
-    out_clock->tv_usec = 0;
-  } else {
-    out_clock->tv_sec = time.time;
-    out_clock->tv_usec = time.millitm * 1000;
-  }
-#else
-  struct timeval clock;
-  gettimeofday(&clock, NULL);
-  if (clock.tv_sec < 0) {
-    assert(0);
-    out_clock->tv_sec = 0;
-    out_clock->tv_usec = 0;
-  } else {
-    out_clock->tv_sec = (uint64_t)clock.tv_sec;
-    out_clock->tv_usec = (uint32_t)clock.tv_usec;
-  }
-#endif
-}
-
 void SSL_CTX_set_ticket_aead_method(SSL_CTX *ctx,
                                     const SSL_TICKET_AEAD_METHOD *aead_method) {
   ctx->ticket_aead_method = aead_method;
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index 5b620f8..73808eb 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -54,6 +54,8 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -69,6 +71,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 int ssl_is_key_type_supported(int key_type) {
   return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC ||
          key_type == EVP_PKEY_ED25519;
@@ -94,227 +98,6 @@
   return 1;
 }
 
-int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
-  EVP_PKEY *pkey;
-  int ret;
-
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  pkey = EVP_PKEY_new();
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
-    return 0;
-  }
-
-  RSA_up_ref(rsa);
-  EVP_PKEY_assign_RSA(pkey, rsa);
-
-  ret = ssl_set_pkey(ssl->cert, pkey);
-  EVP_PKEY_free(pkey);
-
-  return ret;
-}
-
-int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
-  bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
-  if (!rsa) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    return 0;
-  }
-
-  return SSL_use_RSAPrivateKey(ssl, rsa.get());
-}
-
-int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  return ssl_set_pkey(ssl->cert, pkey);
-}
-
-int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
-                            size_t der_len) {
-  if (der_len > LONG_MAX) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return 0;
-  }
-
-  const uint8_t *p = der;
-  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
-  if (pkey == NULL || p != der + der_len) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    EVP_PKEY_free(pkey);
-    return 0;
-  }
-
-  int ret = SSL_use_PrivateKey(ssl, pkey);
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
-  int ret;
-  EVP_PKEY *pkey;
-
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  pkey = EVP_PKEY_new();
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
-    return 0;
-  }
-
-  RSA_up_ref(rsa);
-  EVP_PKEY_assign_RSA(pkey, rsa);
-
-  ret = ssl_set_pkey(ctx->cert, pkey);
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
-                                   size_t der_len) {
-  RSA *rsa = RSA_private_key_from_bytes(der, der_len);
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    return 0;
-  }
-
-  int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
-  RSA_free(rsa);
-  return ret;
-}
-
-int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  return ssl_set_pkey(ctx->cert, pkey);
-}
-
-int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
-                                size_t der_len) {
-  if (der_len > LONG_MAX) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return 0;
-  }
-
-  const uint8_t *p = der;
-  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
-  if (pkey == NULL || p != der + der_len) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    EVP_PKEY_free(pkey);
-    return 0;
-  }
-
-  int ret = SSL_CTX_use_PrivateKey(ctx, pkey);
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-void SSL_set_private_key_method(SSL *ssl,
-                                const SSL_PRIVATE_KEY_METHOD *key_method) {
-  ssl->cert->key_method = key_method;
-}
-
-void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
-                                    const SSL_PRIVATE_KEY_METHOD *key_method) {
-  ctx->cert->key_method = key_method;
-}
-
-static int set_algorithm_prefs(uint16_t **out_prefs, size_t *out_num_prefs,
-                               const uint16_t *prefs, size_t num_prefs) {
-  OPENSSL_free(*out_prefs);
-
-  *out_num_prefs = 0;
-  *out_prefs = (uint16_t *)BUF_memdup(prefs, num_prefs * sizeof(prefs[0]));
-  if (*out_prefs == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-  *out_num_prefs = num_prefs;
-
-  return 1;
-}
-
-int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
-                                        size_t num_prefs) {
-  return set_algorithm_prefs(&ctx->cert->sigalgs, &ctx->cert->num_sigalgs,
-                             prefs, num_prefs);
-}
-
-
-int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs,
-                                    size_t num_prefs) {
-  return set_algorithm_prefs(&ssl->cert->sigalgs, &ssl->cert->num_sigalgs,
-                             prefs, num_prefs);
-}
-
-int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
-                                       size_t num_prefs) {
-  return set_algorithm_prefs(&ctx->verify_sigalgs, &ctx->num_verify_sigalgs,
-                             prefs, num_prefs);
-}
-
-int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
-                                     size_t num_digests) {
-  OPENSSL_free(ssl->cert->sigalgs);
-
-  static_assert(sizeof(int) >= 2 * sizeof(uint16_t),
-                "sigalgs allocation may overflow");
-
-  ssl->cert->num_sigalgs = 0;
-  ssl->cert->sigalgs =
-      (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests);
-  if (ssl->cert->sigalgs == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-
-  /* Convert the digest list to a signature algorithms list.
-   *
-   * TODO(davidben): Replace this API with one that can express RSA-PSS, etc. */
-  for (size_t i = 0; i < num_digests; i++) {
-    switch (digest_nids[i]) {
-      case NID_sha1:
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA1;
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = SSL_SIGN_ECDSA_SHA1;
-        ssl->cert->num_sigalgs += 2;
-        break;
-      case NID_sha256:
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA256;
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
-            SSL_SIGN_ECDSA_SECP256R1_SHA256;
-        ssl->cert->num_sigalgs += 2;
-        break;
-      case NID_sha384:
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA384;
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
-            SSL_SIGN_ECDSA_SECP384R1_SHA384;
-        ssl->cert->num_sigalgs += 2;
-        break;
-      case NID_sha512:
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA512;
-        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
-            SSL_SIGN_ECDSA_SECP521R1_SHA512;
-        ssl->cert->num_sigalgs += 2;
-        break;
-    }
-  }
-
-  return 1;
-}
-
 typedef struct {
   uint16_t sigalg;
   int pkey_type;
@@ -537,3 +320,228 @@
 
   return 1;
 }
+
+}  // namespace bssl
+
+using namespace bssl;
+
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
+  EVP_PKEY *pkey;
+  int ret;
+
+  if (rsa == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  pkey = EVP_PKEY_new();
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
+    return 0;
+  }
+
+  RSA_up_ref(rsa);
+  EVP_PKEY_assign_RSA(pkey, rsa);
+
+  ret = ssl_set_pkey(ssl->cert, pkey);
+  EVP_PKEY_free(pkey);
+
+  return ret;
+}
+
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
+  UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
+  if (!rsa) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    return 0;
+  }
+
+  return SSL_use_RSAPrivateKey(ssl, rsa.get());
+}
+
+int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  return ssl_set_pkey(ssl->cert, pkey);
+}
+
+int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
+                            size_t der_len) {
+  if (der_len > LONG_MAX) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  const uint8_t *p = der;
+  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
+  if (pkey == NULL || p != der + der_len) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    EVP_PKEY_free(pkey);
+    return 0;
+  }
+
+  int ret = SSL_use_PrivateKey(ssl, pkey);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
+  int ret;
+  EVP_PKEY *pkey;
+
+  if (rsa == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  pkey = EVP_PKEY_new();
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
+    return 0;
+  }
+
+  RSA_up_ref(rsa);
+  EVP_PKEY_assign_RSA(pkey, rsa);
+
+  ret = ssl_set_pkey(ctx->cert, pkey);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
+                                   size_t der_len) {
+  RSA *rsa = RSA_private_key_from_bytes(der, der_len);
+  if (rsa == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    return 0;
+  }
+
+  int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+  RSA_free(rsa);
+  return ret;
+}
+
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  return ssl_set_pkey(ctx->cert, pkey);
+}
+
+int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
+                                size_t der_len) {
+  if (der_len > LONG_MAX) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  const uint8_t *p = der;
+  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
+  if (pkey == NULL || p != der + der_len) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    EVP_PKEY_free(pkey);
+    return 0;
+  }
+
+  int ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+void SSL_set_private_key_method(SSL *ssl,
+                                const SSL_PRIVATE_KEY_METHOD *key_method) {
+  ssl->cert->key_method = key_method;
+}
+
+void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
+                                    const SSL_PRIVATE_KEY_METHOD *key_method) {
+  ctx->cert->key_method = key_method;
+}
+
+static int set_algorithm_prefs(uint16_t **out_prefs, size_t *out_num_prefs,
+                               const uint16_t *prefs, size_t num_prefs) {
+  OPENSSL_free(*out_prefs);
+
+  *out_num_prefs = 0;
+  *out_prefs = (uint16_t *)BUF_memdup(prefs, num_prefs * sizeof(prefs[0]));
+  if (*out_prefs == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+  *out_num_prefs = num_prefs;
+
+  return 1;
+}
+
+int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
+                                        size_t num_prefs) {
+  return set_algorithm_prefs(&ctx->cert->sigalgs, &ctx->cert->num_sigalgs,
+                             prefs, num_prefs);
+}
+
+
+int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs,
+                                    size_t num_prefs) {
+  return set_algorithm_prefs(&ssl->cert->sigalgs, &ssl->cert->num_sigalgs,
+                             prefs, num_prefs);
+}
+
+int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
+                                       size_t num_prefs) {
+  return set_algorithm_prefs(&ctx->verify_sigalgs, &ctx->num_verify_sigalgs,
+                             prefs, num_prefs);
+}
+
+int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
+                                     size_t num_digests) {
+  OPENSSL_free(ssl->cert->sigalgs);
+
+  static_assert(sizeof(int) >= 2 * sizeof(uint16_t),
+                "sigalgs allocation may overflow");
+
+  ssl->cert->num_sigalgs = 0;
+  ssl->cert->sigalgs =
+      (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests);
+  if (ssl->cert->sigalgs == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+
+  /* Convert the digest list to a signature algorithms list.
+   *
+   * TODO(davidben): Replace this API with one that can express RSA-PSS, etc. */
+  for (size_t i = 0; i < num_digests; i++) {
+    switch (digest_nids[i]) {
+      case NID_sha1:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA1;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = SSL_SIGN_ECDSA_SHA1;
+        ssl->cert->num_sigalgs += 2;
+        break;
+      case NID_sha256:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA256;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
+            SSL_SIGN_ECDSA_SECP256R1_SHA256;
+        ssl->cert->num_sigalgs += 2;
+        break;
+      case NID_sha384:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA384;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
+            SSL_SIGN_ECDSA_SECP384R1_SHA384;
+        ssl->cert->num_sigalgs += 2;
+        break;
+      case NID_sha512:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA512;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
+            SSL_SIGN_ECDSA_SECP521R1_SHA512;
+        ssl->cert->num_sigalgs += 2;
+        break;
+    }
+  }
+
+  return 1;
+}
diff --git a/ssl/ssl_session.cc b/ssl/ssl_session.cc
index 9cb78cc..33d61b7 100644
--- a/ssl/ssl_session.cc
+++ b/ssl/ssl_session.cc
@@ -133,6 +133,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -148,6 +150,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 /* The address of this is a magic value, a pointer to which is returned by
  * SSL_magic_pending_session_ptr(). It allows a session callback to indicate
  * that it needs to asynchronously fetch session information. */
@@ -178,10 +182,6 @@
   return session;
 }
 
-SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
-  return ssl_session_new(ctx->x509_method);
-}
-
 SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
   SSL_SESSION *new_session = ssl_session_new(session->x509_method);
   if (new_session == NULL) {
@@ -359,152 +359,6 @@
   }
 }
 
-int SSL_SESSION_up_ref(SSL_SESSION *session) {
-  CRYPTO_refcount_inc(&session->references);
-  return 1;
-}
-
-void SSL_SESSION_free(SSL_SESSION *session) {
-  if (session == NULL ||
-      !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
-    return;
-  }
-
-  CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
-
-  OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
-  OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
-  sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
-  session->x509_method->session_clear(session);
-  OPENSSL_free(session->tlsext_hostname);
-  OPENSSL_free(session->tlsext_tick);
-  OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
-  OPENSSL_free(session->ocsp_response);
-  OPENSSL_free(session->psk_identity);
-  OPENSSL_free(session->early_alpn);
-  OPENSSL_cleanse(session, sizeof(*session));
-  OPENSSL_free(session);
-}
-
-const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
-                                  unsigned *out_len) {
-  if (out_len != NULL) {
-    *out_len = session->session_id_length;
-  }
-  return session->session_id;
-}
-
-uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
-  return session->timeout;
-}
-
-uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
-  if (session == NULL) {
-    /* NULL should crash, but silently accept it here for compatibility. */
-    return 0;
-  }
-  return session->time;
-}
-
-X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
-  return session->x509_peer;
-}
-
-size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
-                                  size_t max_out) {
-  /* TODO(davidben): Fix master_key_length's type and remove these casts. */
-  if (max_out == 0) {
-    return (size_t)session->master_key_length;
-  }
-  if (max_out > (size_t)session->master_key_length) {
-    max_out = (size_t)session->master_key_length;
-  }
-  OPENSSL_memcpy(out, session->master_key, max_out);
-  return max_out;
-}
-
-uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
-  if (session == NULL) {
-    return 0;
-  }
-
-  session->time = time;
-  return time;
-}
-
-uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
-  if (session == NULL) {
-    return 0;
-  }
-
-  session->timeout = timeout;
-  session->auth_timeout = timeout;
-  return 1;
-}
-
-int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
-                                size_t sid_ctx_len) {
-  if (sid_ctx_len > sizeof(session->sid_ctx)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
-    return 0;
-  }
-
-  assert(sizeof(session->sid_ctx) < 256);
-  session->sid_ctx_length = (uint8_t)sid_ctx_len;
-  OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
-
-  return 1;
-}
-
-SSL_SESSION *SSL_magic_pending_session_ptr(void) {
-  return (SSL_SESSION *)&g_pending_session_magic;
-}
-
-SSL_SESSION *SSL_get_session(const SSL *ssl) {
-  /* Once the handshake completes we return the established session. Otherwise
-   * we return the intermediate session, either |session| (for resumption) or
-   * |new_session| if doing a full handshake. */
-  if (!SSL_in_init(ssl)) {
-    return ssl->s3->established_session;
-  }
-  SSL_HANDSHAKE *hs = ssl->s3->hs;
-  if (hs->early_session != NULL) {
-    return hs->early_session;
-  }
-  if (hs->new_session != NULL) {
-    return hs->new_session;
-  }
-  return ssl->session;
-}
-
-SSL_SESSION *SSL_get1_session(SSL *ssl) {
-  SSL_SESSION *ret = SSL_get_session(ssl);
-  if (ret != NULL) {
-    SSL_SESSION_up_ref(ret);
-  }
-  return ret;
-}
-
-int SSL_SESSION_get_ex_new_index(long argl, void *argp,
-                                 CRYPTO_EX_unused *unused,
-                                 CRYPTO_EX_dup *dup_unused,
-                                 CRYPTO_EX_free *free_func) {
-  int index;
-  if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
-                               free_func)) {
-    return -1;
-  }
-  return index;
-}
-
-int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) {
-  return CRYPTO_set_ex_data(&session->ex_data, idx, arg);
-}
-
-void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
-  return CRYPTO_get_ex_data(&session->ex_data, idx);
-}
-
 uint16_t SSL_SESSION_protocol_version(const SSL_SESSION *session) {
   uint16_t ret;
   if (!ssl_protocol_version_from_wire(&ret, session->ssl_version)) {
@@ -595,8 +449,8 @@
 static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
                                               const uint8_t *session_buf,
                                               size_t session_len) {
-  bssl::ScopedEVP_CIPHER_CTX ctx;
-  bssl::ScopedHMAC_CTX hctx;
+  ScopedEVP_CIPHER_CTX ctx;
+  ScopedHMAC_CTX hctx;
 
   /* If the session is too long, emit a dummy value rather than abort the
    * connection. */
@@ -881,6 +735,249 @@
   return ssl_session_success;
 }
 
+static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
+  int ret = 0;
+
+  if (session != NULL && session->session_id_length != 0) {
+    if (lock) {
+      CRYPTO_MUTEX_lock_write(&ctx->lock);
+    }
+    SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
+                                                         session);
+    if (found_session == session) {
+      ret = 1;
+      found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
+      SSL_SESSION_list_remove(ctx, session);
+    }
+
+    if (lock) {
+      CRYPTO_MUTEX_unlock_write(&ctx->lock);
+    }
+
+    if (ret) {
+      if (ctx->remove_session_cb != NULL) {
+        ctx->remove_session_cb(ctx, found_session);
+      }
+      SSL_SESSION_free(found_session);
+    }
+  }
+
+  return ret;
+}
+
+void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
+  if (ssl->session == session) {
+    return;
+  }
+
+  SSL_SESSION_free(ssl->session);
+  ssl->session = session;
+  if (session != NULL) {
+    SSL_SESSION_up_ref(session);
+  }
+}
+
+/* locked by SSL_CTX in the calling function */
+static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
+  if (session->next == NULL || session->prev == NULL) {
+    return;
+  }
+
+  if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
+    /* last element in list */
+    if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
+      /* only one element in list */
+      ctx->session_cache_head = NULL;
+      ctx->session_cache_tail = NULL;
+    } else {
+      ctx->session_cache_tail = session->prev;
+      session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
+    }
+  } else {
+    if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
+      /* first element in list */
+      ctx->session_cache_head = session->next;
+      session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+    } else { /* middle of list */
+      session->next->prev = session->prev;
+      session->prev->next = session->next;
+    }
+  }
+  session->prev = session->next = NULL;
+}
+
+static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
+  if (session->next != NULL && session->prev != NULL) {
+    SSL_SESSION_list_remove(ctx, session);
+  }
+
+  if (ctx->session_cache_head == NULL) {
+    ctx->session_cache_head = session;
+    ctx->session_cache_tail = session;
+    session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+    session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
+  } else {
+    session->next = ctx->session_cache_head;
+    session->next->prev = session;
+    session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+    ctx->session_cache_head = session;
+  }
+}
+
+}  // namespace bssl
+
+using namespace bssl;
+
+SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
+  return ssl_session_new(ctx->x509_method);
+}
+
+int SSL_SESSION_up_ref(SSL_SESSION *session) {
+  CRYPTO_refcount_inc(&session->references);
+  return 1;
+}
+
+void SSL_SESSION_free(SSL_SESSION *session) {
+  if (session == NULL ||
+      !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
+    return;
+  }
+
+  CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
+
+  OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
+  OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
+  sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
+  session->x509_method->session_clear(session);
+  OPENSSL_free(session->tlsext_hostname);
+  OPENSSL_free(session->tlsext_tick);
+  OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
+  OPENSSL_free(session->ocsp_response);
+  OPENSSL_free(session->psk_identity);
+  OPENSSL_free(session->early_alpn);
+  OPENSSL_cleanse(session, sizeof(*session));
+  OPENSSL_free(session);
+}
+
+const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
+                                  unsigned *out_len) {
+  if (out_len != NULL) {
+    *out_len = session->session_id_length;
+  }
+  return session->session_id;
+}
+
+uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
+  return session->timeout;
+}
+
+uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
+  if (session == NULL) {
+    /* NULL should crash, but silently accept it here for compatibility. */
+    return 0;
+  }
+  return session->time;
+}
+
+X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
+  return session->x509_peer;
+}
+
+size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
+                                  size_t max_out) {
+  /* TODO(davidben): Fix master_key_length's type and remove these casts. */
+  if (max_out == 0) {
+    return (size_t)session->master_key_length;
+  }
+  if (max_out > (size_t)session->master_key_length) {
+    max_out = (size_t)session->master_key_length;
+  }
+  OPENSSL_memcpy(out, session->master_key, max_out);
+  return max_out;
+}
+
+uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
+  if (session == NULL) {
+    return 0;
+  }
+
+  session->time = time;
+  return time;
+}
+
+uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
+  if (session == NULL) {
+    return 0;
+  }
+
+  session->timeout = timeout;
+  session->auth_timeout = timeout;
+  return 1;
+}
+
+int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
+                                size_t sid_ctx_len) {
+  if (sid_ctx_len > sizeof(session->sid_ctx)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+    return 0;
+  }
+
+  assert(sizeof(session->sid_ctx) < 256);
+  session->sid_ctx_length = (uint8_t)sid_ctx_len;
+  OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
+
+  return 1;
+}
+
+SSL_SESSION *SSL_magic_pending_session_ptr(void) {
+  return (SSL_SESSION *)&g_pending_session_magic;
+}
+
+SSL_SESSION *SSL_get_session(const SSL *ssl) {
+  /* Once the handshake completes we return the established session. Otherwise
+   * we return the intermediate session, either |session| (for resumption) or
+   * |new_session| if doing a full handshake. */
+  if (!SSL_in_init(ssl)) {
+    return ssl->s3->established_session;
+  }
+  SSL_HANDSHAKE *hs = ssl->s3->hs;
+  if (hs->early_session != NULL) {
+    return hs->early_session;
+  }
+  if (hs->new_session != NULL) {
+    return hs->new_session;
+  }
+  return ssl->session;
+}
+
+SSL_SESSION *SSL_get1_session(SSL *ssl) {
+  SSL_SESSION *ret = SSL_get_session(ssl);
+  if (ret != NULL) {
+    SSL_SESSION_up_ref(ret);
+  }
+  return ret;
+}
+
+int SSL_SESSION_get_ex_new_index(long argl, void *argp,
+                                 CRYPTO_EX_unused *unused,
+                                 CRYPTO_EX_dup *dup_unused,
+                                 CRYPTO_EX_free *free_func) {
+  int index;
+  if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+                               free_func)) {
+    return -1;
+  }
+  return index;
+}
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) {
+  return CRYPTO_set_ex_data(&session->ex_data, idx, arg);
+}
+
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
+  return CRYPTO_get_ex_data(&session->ex_data, idx);
+}
+
 int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
   /* Although |session| is inserted into two structures (a doubly-linked list
    * and the hash table), |ctx| only takes one reference. */
@@ -927,36 +1024,6 @@
   return remove_session_lock(ctx, session, 1);
 }
 
-static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
-  int ret = 0;
-
-  if (session != NULL && session->session_id_length != 0) {
-    if (lock) {
-      CRYPTO_MUTEX_lock_write(&ctx->lock);
-    }
-    SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
-                                                         session);
-    if (found_session == session) {
-      ret = 1;
-      found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
-      SSL_SESSION_list_remove(ctx, session);
-    }
-
-    if (lock) {
-      CRYPTO_MUTEX_unlock_write(&ctx->lock);
-    }
-
-    if (ret) {
-      if (ctx->remove_session_cb != NULL) {
-        ctx->remove_session_cb(ctx, found_session);
-      }
-      SSL_SESSION_free(found_session);
-    }
-  }
-
-  return ret;
-}
-
 int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
   /* SSL_set_session may only be called before the handshake has started. */
   if (ssl->s3->initial_handshake_complete ||
@@ -969,18 +1036,6 @@
   return 1;
 }
 
-void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
-  if (ssl->session == session) {
-    return;
-  }
-
-  SSL_SESSION_free(ssl->session);
-  ssl->session = session;
-  if (session != NULL) {
-    SSL_SESSION_up_ref(session);
-  }
-}
-
 uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout) {
   if (ctx == NULL) {
     return 0;
@@ -1046,53 +1101,6 @@
   CRYPTO_MUTEX_unlock_write(&ctx->lock);
 }
 
-/* locked by SSL_CTX in the calling function */
-static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
-  if (session->next == NULL || session->prev == NULL) {
-    return;
-  }
-
-  if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
-    /* last element in list */
-    if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
-      /* only one element in list */
-      ctx->session_cache_head = NULL;
-      ctx->session_cache_tail = NULL;
-    } else {
-      ctx->session_cache_tail = session->prev;
-      session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
-    }
-  } else {
-    if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
-      /* first element in list */
-      ctx->session_cache_head = session->next;
-      session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
-    } else { /* middle of list */
-      session->next->prev = session->prev;
-      session->prev->next = session->next;
-    }
-  }
-  session->prev = session->next = NULL;
-}
-
-static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
-  if (session->next != NULL && session->prev != NULL) {
-    SSL_SESSION_list_remove(ctx, session);
-  }
-
-  if (ctx->session_cache_head == NULL) {
-    ctx->session_cache_head = session;
-    ctx->session_cache_tail = session;
-    session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
-    session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
-  } else {
-    session->next = ctx->session_cache_head;
-    session->next->prev = session;
-    session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
-    ctx->session_cache_head = session;
-  }
-}
-
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
                              int (*cb)(SSL *ssl, SSL_SESSION *session)) {
   ctx->new_session_cb = cb;
diff --git a/ssl/ssl_stat.cc b/ssl/ssl_stat.cc
index 22149e2..a02e395 100644
--- a/ssl/ssl_stat.cc
+++ b/ssl/ssl_stat.cc
@@ -81,6 +81,8 @@
  * OTHERWISE.
  */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index bf546da..38cac4b 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
@@ -1527,7 +1529,7 @@
 
   SSL_SESSION *session0 = SSL_get_session(client.get());
   bssl::UniquePtr<SSL_SESSION> session1(
-      SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL));
+      bssl::SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL));
   ASSERT_TRUE(session1);
 
   session1->not_resumable = 0;
diff --git a/ssl/ssl_transcript.cc b/ssl/ssl_transcript.cc
index 9cc3777..7436027 100644
--- a/ssl/ssl_transcript.cc
+++ b/ssl/ssl_transcript.cc
@@ -133,6 +133,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -150,6 +152,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript) {
   SSL_TRANSCRIPT_cleanup(transcript);
   transcript->buffer = BUF_MEM_new();
@@ -403,3 +407,5 @@
   *out_len = kFinishedLen;
   return 1;
 }
+
+}  // namespace bssl
diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc
index 6fd19c6..f7184b0 100644
--- a/ssl/ssl_versions.cc
+++ b/ssl/ssl_versions.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -23,6 +25,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
   switch (version) {
     case SSL3_VERSION:
@@ -141,22 +145,6 @@
   return set_version_bound(method, out, version);
 }
 
-int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version) {
-  return set_min_version(ctx->method, &ctx->conf_min_version, version);
-}
-
-int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) {
-  return set_max_version(ctx->method, &ctx->conf_max_version, version);
-}
-
-int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
-  return set_min_version(ssl->method, &ssl->conf_min_version, version);
-}
-
-int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
-  return set_max_version(ssl->method, &ssl->conf_max_version, version);
-}
-
 const struct {
   uint16_t version;
   uint32_t flag;
@@ -238,17 +226,7 @@
   return ssl->version;
 }
 
-int SSL_version(const SSL *ssl) {
-  uint16_t ret = ssl_version(ssl);
-  /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
-  if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION ||
-      ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
-    return TLS1_3_VERSION;
-  }
-  return ret;
-}
-
-static const char *ssl_get_version(int version) {
+static const char *ssl_version_to_string(uint16_t version) {
   switch (version) {
     /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
     case TLS1_3_DRAFT_VERSION:
@@ -279,14 +257,6 @@
   }
 }
 
-const char *SSL_get_version(const SSL *ssl) {
-  return ssl_get_version(ssl_version(ssl));
-}
-
-const char *SSL_SESSION_get_version(const SSL_SESSION *session) {
-  return ssl_get_version(session->ssl_version);
-}
-
 uint16_t ssl3_protocol_version(const SSL *ssl) {
   assert(ssl->s3->have_version);
   uint16_t version;
@@ -372,3 +342,41 @@
   *out_alert = SSL_AD_PROTOCOL_VERSION;
   return 0;
 }
+
+}  // namespace bssl
+
+using namespace bssl;
+
+int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version) {
+  return set_min_version(ctx->method, &ctx->conf_min_version, version);
+}
+
+int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) {
+  return set_max_version(ctx->method, &ctx->conf_max_version, version);
+}
+
+int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
+  return set_min_version(ssl->method, &ssl->conf_min_version, version);
+}
+
+int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
+  return set_max_version(ssl->method, &ssl->conf_max_version, version);
+}
+
+int SSL_version(const SSL *ssl) {
+  uint16_t ret = ssl_version(ssl);
+  /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
+  if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION ||
+      ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
+    return TLS1_3_VERSION;
+  }
+  return ret;
+}
+
+const char *SSL_get_version(const SSL *ssl) {
+  return ssl_version_to_string(ssl_version(ssl));
+}
+
+const char *SSL_SESSION_get_version(const SSL_SESSION *session) {
+  return ssl_version_to_string(session->ssl_version);
+}
diff --git a/ssl/ssl_x509.cc b/ssl/ssl_x509.cc
index 125e105..95c8ac0 100644
--- a/ssl/ssl_x509.cc
+++ b/ssl/ssl_x509.cc
@@ -138,6 +138,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -155,6 +157,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 /* check_ssl_x509_method asserts that |ssl| has the X509-based method
  * installed. Calling an X509-based method on an |ssl| with a different method
  * will likely misbehave and possibly crash or leak memory. */
@@ -168,205 +172,6 @@
   assert(ctx == NULL || ctx->x509_method == &ssl_crypto_x509_method);
 }
 
-X509 *SSL_get_peer_certificate(const SSL *ssl) {
-  check_ssl_x509_method(ssl);
-  if (ssl == NULL) {
-    return NULL;
-  }
-  SSL_SESSION *session = SSL_get_session(ssl);
-  if (session == NULL || session->x509_peer == NULL) {
-    return NULL;
-  }
-  X509_up_ref(session->x509_peer);
-  return session->x509_peer;
-}
-
-STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl) {
-  check_ssl_x509_method(ssl);
-  if (ssl == NULL) {
-    return NULL;
-  }
-  SSL_SESSION *session = SSL_get_session(ssl);
-  if (session == NULL ||
-      session->x509_chain == NULL) {
-    return NULL;
-  }
-
-  if (!ssl->server) {
-    return session->x509_chain;
-  }
-
-  /* OpenSSL historically didn't include the leaf certificate in the returned
-   * certificate chain, but only for servers. */
-  if (session->x509_chain_without_leaf == NULL) {
-    session->x509_chain_without_leaf = sk_X509_new_null();
-    if (session->x509_chain_without_leaf == NULL) {
-      return NULL;
-    }
-
-    for (size_t i = 1; i < sk_X509_num(session->x509_chain); i++) {
-      X509 *cert = sk_X509_value(session->x509_chain, i);
-      if (!sk_X509_push(session->x509_chain_without_leaf, cert)) {
-        sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
-        session->x509_chain_without_leaf = NULL;
-        return NULL;
-      }
-      X509_up_ref(cert);
-    }
-  }
-
-  return session->x509_chain_without_leaf;
-}
-
-STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl) {
-  check_ssl_x509_method(ssl);
-  SSL_SESSION *session = SSL_get_session(ssl);
-  if (session == NULL) {
-    return NULL;
-  }
-
-  return session->x509_chain;
-}
-
-int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose) {
-  check_ssl_ctx_x509_method(ctx);
-  return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
-}
-
-int SSL_set_purpose(SSL *ssl, int purpose) {
-  check_ssl_x509_method(ssl);
-  return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose);
-}
-
-int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) {
-  check_ssl_ctx_x509_method(ctx);
-  return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
-}
-
-int SSL_set_trust(SSL *ssl, int trust) {
-  check_ssl_x509_method(ssl);
-  return X509_VERIFY_PARAM_set_trust(ssl->param, trust);
-}
-
-int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) {
-  check_ssl_ctx_x509_method(ctx);
-  return X509_VERIFY_PARAM_set1(ctx->param, param);
-}
-
-int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) {
-  check_ssl_x509_method(ssl);
-  return X509_VERIFY_PARAM_set1(ssl->param, param);
-}
-
-X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) {
-  check_ssl_ctx_x509_method(ctx);
-  return ctx->param;
-}
-
-X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) {
-  check_ssl_x509_method(ssl);
-  return ssl->param;
-}
-
-int SSL_get_verify_depth(const SSL *ssl) {
-  check_ssl_x509_method(ssl);
-  return X509_VERIFY_PARAM_get_depth(ssl->param);
-}
-
-int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {
-  check_ssl_x509_method(ssl);
-  return ssl->verify_callback;
-}
-
-int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) {
-  check_ssl_ctx_x509_method(ctx);
-  return ctx->verify_mode;
-}
-
-int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) {
-  check_ssl_ctx_x509_method(ctx);
-  return X509_VERIFY_PARAM_get_depth(ctx->param);
-}
-
-int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
-    int ok, X509_STORE_CTX *store_ctx) {
-  check_ssl_ctx_x509_method(ctx);
-  return ctx->default_verify_callback;
-}
-
-void SSL_set_verify(SSL *ssl, int mode,
-                    int (*callback)(int ok, X509_STORE_CTX *store_ctx)) {
-  check_ssl_x509_method(ssl);
-  ssl->verify_mode = mode;
-  if (callback != NULL) {
-    ssl->verify_callback = callback;
-  }
-}
-
-void SSL_set_verify_depth(SSL *ssl, int depth) {
-  check_ssl_x509_method(ssl);
-  X509_VERIFY_PARAM_set_depth(ssl->param, depth);
-}
-
-void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
-                                      int (*cb)(X509_STORE_CTX *store_ctx,
-                                                void *arg),
-                                      void *arg) {
-  check_ssl_ctx_x509_method(ctx);
-  ctx->app_verify_callback = cb;
-  ctx->app_verify_arg = arg;
-}
-
-void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
-                        int (*cb)(int, X509_STORE_CTX *)) {
-  check_ssl_ctx_x509_method(ctx);
-  ctx->verify_mode = mode;
-  ctx->default_verify_callback = cb;
-}
-
-void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
-  check_ssl_ctx_x509_method(ctx);
-  X509_VERIFY_PARAM_set_depth(ctx->param, depth);
-}
-
-int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
-  check_ssl_ctx_x509_method(ctx);
-  return X509_STORE_set_default_paths(ctx->cert_store);
-}
-
-int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file,
-                                  const char *ca_dir) {
-  check_ssl_ctx_x509_method(ctx);
-  return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir);
-}
-
-void SSL_set_verify_result(SSL *ssl, long result) {
-  check_ssl_x509_method(ssl);
-  if (result != X509_V_OK) {
-    abort();
-  }
-}
-
-long SSL_get_verify_result(const SSL *ssl) {
-  check_ssl_x509_method(ssl);
-  SSL_SESSION *session = SSL_get_session(ssl);
-  if (session == NULL) {
-    return X509_V_ERR_INVALID_CALL;
-  }
-  return session->verify_result;
-}
-
-X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) {
-  check_ssl_ctx_x509_method(ctx);
-  return ctx->cert_store;
-}
-
-void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
-  check_ssl_ctx_x509_method(ctx);
-  X509_STORE_free(ctx->cert_store);
-  ctx->cert_store = store;
-}
-
 /* x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised
  * contents of |x509|. */
 static CRYPTO_BUFFER *x509_to_buffer(X509 *x509) {
@@ -785,6 +590,209 @@
   ssl_crypto_x509_ssl_ctx_flush_cached_client_CA,
 };
 
+}  // namespace bssl
+
+using namespace bssl;
+
+X509 *SSL_get_peer_certificate(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  if (ssl == NULL) {
+    return NULL;
+  }
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL || session->x509_peer == NULL) {
+    return NULL;
+  }
+  X509_up_ref(session->x509_peer);
+  return session->x509_peer;
+}
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  if (ssl == NULL) {
+    return NULL;
+  }
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL ||
+      session->x509_chain == NULL) {
+    return NULL;
+  }
+
+  if (!ssl->server) {
+    return session->x509_chain;
+  }
+
+  /* OpenSSL historically didn't include the leaf certificate in the returned
+   * certificate chain, but only for servers. */
+  if (session->x509_chain_without_leaf == NULL) {
+    session->x509_chain_without_leaf = sk_X509_new_null();
+    if (session->x509_chain_without_leaf == NULL) {
+      return NULL;
+    }
+
+    for (size_t i = 1; i < sk_X509_num(session->x509_chain); i++) {
+      X509 *cert = sk_X509_value(session->x509_chain, i);
+      if (!sk_X509_push(session->x509_chain_without_leaf, cert)) {
+        sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
+        session->x509_chain_without_leaf = NULL;
+        return NULL;
+      }
+      X509_up_ref(cert);
+    }
+  }
+
+  return session->x509_chain_without_leaf;
+}
+
+STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return NULL;
+  }
+
+  return session->x509_chain;
+}
+
+int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
+}
+
+int SSL_set_purpose(SSL *ssl, int purpose) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose);
+}
+
+int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
+}
+
+int SSL_set_trust(SSL *ssl, int trust) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_set_trust(ssl->param, trust);
+}
+
+int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_set1(ctx->param, param);
+}
+
+int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_set1(ssl->param, param);
+}
+
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->param;
+}
+
+X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  return ssl->param;
+}
+
+int SSL_get_verify_depth(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_get_depth(ssl->param);
+}
+
+int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {
+  check_ssl_x509_method(ssl);
+  return ssl->verify_callback;
+}
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->verify_mode;
+}
+
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_get_depth(ctx->param);
+}
+
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
+    int ok, X509_STORE_CTX *store_ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->default_verify_callback;
+}
+
+void SSL_set_verify(SSL *ssl, int mode,
+                    int (*callback)(int ok, X509_STORE_CTX *store_ctx)) {
+  check_ssl_x509_method(ssl);
+  ssl->verify_mode = mode;
+  if (callback != NULL) {
+    ssl->verify_callback = callback;
+  }
+}
+
+void SSL_set_verify_depth(SSL *ssl, int depth) {
+  check_ssl_x509_method(ssl);
+  X509_VERIFY_PARAM_set_depth(ssl->param, depth);
+}
+
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
+                                      int (*cb)(X509_STORE_CTX *store_ctx,
+                                                void *arg),
+                                      void *arg) {
+  check_ssl_ctx_x509_method(ctx);
+  ctx->app_verify_callback = cb;
+  ctx->app_verify_arg = arg;
+}
+
+void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
+                        int (*cb)(int, X509_STORE_CTX *)) {
+  check_ssl_ctx_x509_method(ctx);
+  ctx->verify_mode = mode;
+  ctx->default_verify_callback = cb;
+}
+
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
+  check_ssl_ctx_x509_method(ctx);
+  X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+}
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_STORE_set_default_paths(ctx->cert_store);
+}
+
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file,
+                                  const char *ca_dir) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir);
+}
+
+void SSL_set_verify_result(SSL *ssl, long result) {
+  check_ssl_x509_method(ssl);
+  if (result != X509_V_OK) {
+    abort();
+  }
+}
+
+long SSL_get_verify_result(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return X509_V_ERR_INVALID_CALL;
+  }
+  return session->verify_result;
+}
+
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->cert_store;
+}
+
+void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+  check_ssl_ctx_x509_method(ctx);
+  X509_STORE_free(ctx->cert_store);
+  ctx->cert_store = store;
+}
+
 static int ssl_use_certificate(CERT *cert, X509 *x) {
   if (x == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
diff --git a/ssl/t1_enc.cc b/ssl/t1_enc.cc
index c224240..1efd834 100644
--- a/ssl/t1_enc.cc
+++ b/ssl/t1_enc.cc
@@ -133,6 +133,8 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -150,6 +152,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 /* tls1_P_hash computes the TLS P_<hash> function as described in RFC 5246,
  * section 5. It XORs |out_len| bytes to |out|, using |md| as the hash and
  * |secret| as the secret. |seed1| through |seed3| are concatenated to form the
@@ -442,34 +446,6 @@
   return ssl->method->set_write_state(ssl, aead_ctx);
 }
 
-size_t SSL_get_key_block_len(const SSL *ssl) {
-  return 2 * ((size_t)ssl->s3->tmp.new_mac_secret_len +
-              (size_t)ssl->s3->tmp.new_key_len +
-              (size_t)ssl->s3->tmp.new_fixed_iv_len);
-}
-
-int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
-  if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
-    return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
-                    SSL_get_session(ssl)->master_key_length,
-                    TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
-                    ssl->s3->server_random, SSL3_RANDOM_SIZE,
-                    ssl->s3->client_random, SSL3_RANDOM_SIZE);
-  }
-
-  const EVP_MD *digest = ssl_get_handshake_digest(
-      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
-  if (digest == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-  return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
-                  SSL_get_session(ssl)->master_key_length,
-                  TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
-                  ssl->s3->server_random, SSL3_RANDOM_SIZE,
-                  ssl->s3->client_random, SSL3_RANDOM_SIZE);
-}
-
 int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
                                 const uint8_t *premaster,
                                 size_t premaster_len) {
@@ -507,6 +483,38 @@
   return SSL3_MASTER_SECRET_SIZE;
 }
 
+}  // namespace bssl
+
+using namespace bssl;
+
+size_t SSL_get_key_block_len(const SSL *ssl) {
+  return 2 * ((size_t)ssl->s3->tmp.new_mac_secret_len +
+              (size_t)ssl->s3->tmp.new_key_len +
+              (size_t)ssl->s3->tmp.new_fixed_iv_len);
+}
+
+int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
+  if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+    return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
+                    SSL_get_session(ssl)->master_key_length,
+                    TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+                    ssl->s3->server_random, SSL3_RANDOM_SIZE,
+                    ssl->s3->client_random, SSL3_RANDOM_SIZE);
+  }
+
+  const EVP_MD *digest = ssl_get_handshake_digest(
+      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+  if (digest == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
+                  SSL_get_session(ssl)->master_key_length,
+                  TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+                  ssl->s3->server_random, SSL3_RANDOM_SIZE,
+                  ssl->s3->client_random, SSL3_RANDOM_SIZE);
+}
+
 int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
                                const char *label, size_t label_len,
                                const uint8_t *context, size_t context_len,
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 76469eb..228c1c5 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -106,6 +106,8 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -126,6 +128,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
 
 static int compare_uint16_t(const void *p1, const void *p2) {
@@ -289,20 +293,6 @@
   return 0;
 }
 
-int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
-                                         uint16_t extension_type,
-                                         const uint8_t **out_data,
-                                         size_t *out_len) {
-  CBS cbs;
-  if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
-    return 0;
-  }
-
-  *out_data = CBS_data(&cbs);
-  *out_len = CBS_len(&cbs);
-  return 1;
-}
-
 static const uint16_t kDefaultGroups[] = {
     SSL_CURVE_X25519,
     SSL_CURVE_SECP256R1,
@@ -508,10 +498,6 @@
     SSL_SIGN_RSA_PKCS1_SHA1,
 };
 
-void SSL_CTX_set_ed25519_enabled(SSL_CTX *ctx, int enabled) {
-  ctx->ed25519_enabled = !!enabled;
-}
-
 int tls12_add_verify_sigalgs(const SSL *ssl, CBB *out) {
   const uint16_t *sigalgs = kVerifySignatureAlgorithms;
   size_t num_sigalgs = OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms);
@@ -2658,12 +2644,6 @@
   return NULL;
 }
 
-int SSL_extension_supported(unsigned extension_value) {
-  uint32_t index;
-  return extension_value == TLSEXT_TYPE_padding ||
-         tls_extension_find(&index, extension_value) != NULL;
-}
-
 int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) {
   SSL *const ssl = hs->ssl;
   /* Don't add extensions for SSLv3 unless doing secure renegotiation. */
@@ -3044,8 +3024,8 @@
                                    size_t ticket_len) {
   const SSL_CTX *const ssl_ctx = ssl->session_ctx;
 
-  bssl::ScopedHMAC_CTX hmac_ctx;
-  bssl::ScopedEVP_CIPHER_CTX cipher_ctx;
+  ScopedHMAC_CTX hmac_ctx;
+  ScopedEVP_CIPHER_CTX cipher_ctx;
 
   /* Ensure there is room for the key name and the largest IV
    * |tlsext_ticket_key_cb| may try to consume. The real limit may be lower, but
@@ -3105,7 +3085,7 @@
   const uint8_t *ciphertext = ticket + SSL_TICKET_KEY_NAME_LEN + iv_len;
   size_t ciphertext_len = ticket_len - SSL_TICKET_KEY_NAME_LEN - iv_len -
                           mac_len;
-  bssl::UniquePtr<uint8_t> plaintext((uint8_t *)OPENSSL_malloc(ciphertext_len));
+  UniquePtr<uint8_t> plaintext((uint8_t *)OPENSSL_malloc(ciphertext_len));
   if (!plaintext) {
     return ssl_ticket_aead_error;
   }
@@ -3328,15 +3308,14 @@
     return 0;
   }
 
-  bssl::UniquePtr<EC_GROUP> p256(
-      EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+  UniquePtr<EC_GROUP> p256(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
   if (!p256) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
     return 0;
   }
 
-  bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
-  bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
+  UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
+  UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
   if (!sig || !x || !y) {
     return 0;
   }
@@ -3349,8 +3328,8 @@
     return 0;
   }
 
-  bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
-  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
+  UniquePtr<EC_KEY> key(EC_KEY_new());
+  UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
   if (!key || !point ||
       !EC_POINT_set_affine_coordinates_GFp(p256.get(), point.get(), x.get(),
                                            y.get(), nullptr) ||
@@ -3543,3 +3522,31 @@
 
   return 1;
 }
+
+}  // namespace bssl
+
+using namespace bssl;
+
+int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
+                                         uint16_t extension_type,
+                                         const uint8_t **out_data,
+                                         size_t *out_len) {
+  CBS cbs;
+  if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
+    return 0;
+  }
+
+  *out_data = CBS_data(&cbs);
+  *out_len = CBS_len(&cbs);
+  return 1;
+}
+
+void SSL_CTX_set_ed25519_enabled(SSL_CTX *ctx, int enabled) {
+  ctx->ed25519_enabled = !!enabled;
+}
+
+int SSL_extension_supported(unsigned extension_value) {
+  uint32_t index;
+  return extension_value == TLSEXT_TYPE_padding ||
+         tls_extension_find(&index, extension_value) != NULL;
+}
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 2e98780..038f23a 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -16,6 +16,8 @@
 #define __STDC_FORMAT_MACROS
 #endif
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/base.h>
 
 #if !defined(OPENSSL_WINDOWS)
@@ -1077,12 +1079,12 @@
 };
 
 static void ssl_ctx_add_session(SSL_SESSION *session, void *void_param) {
-  SSL_SESSION *new_session = SSL_SESSION_dup(
-      session, SSL_SESSION_INCLUDE_NONAUTH | SSL_SESSION_INCLUDE_TICKET);
+  SSL_CTX *ctx = reinterpret_cast<SSL_CTX *>(void_param);
+  bssl::UniquePtr<SSL_SESSION> new_session(bssl::SSL_SESSION_dup(
+      session, SSL_SESSION_INCLUDE_NONAUTH | SSL_SESSION_INCLUDE_TICKET));
   if (new_session != nullptr) {
-    SSL_CTX_add_session((SSL_CTX *)void_param, new_session);
+    SSL_CTX_add_session(ctx, new_session.get());
   }
-  SSL_SESSION_free(new_session);
 }
 
 static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx,
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index 6a6c3c6..91b7f2b 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -28,6 +30,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 /* kMaxKeyUpdates is the number of consecutive KeyUpdates that will be
  * processed. Without this limit an attacker could force unbounded processing
  * without being able to return application data. */
@@ -403,7 +407,7 @@
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return 0;
   }
-  bssl::UniquePtr<uint8_t> free_msg(msg);
+  UniquePtr<uint8_t> free_msg(msg);
 
   int sig_ok =
       ssl_public_key_verify(ssl, CBS_data(&signature), CBS_len(&signature),
@@ -455,7 +459,7 @@
 
 int tls13_add_certificate(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  bssl::ScopedCBB cbb;
+  ScopedCBB cbb;
   CBB body, certificate_list;
   if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE) ||
       /* The request context is always empty in the handshake. */
@@ -532,7 +536,7 @@
     return ssl_private_key_failure;
   }
 
-  bssl::ScopedCBB cbb;
+  ScopedCBB cbb;
   CBB body;
   if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_CERTIFICATE_VERIFY) ||
@@ -560,7 +564,7 @@
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return ssl_private_key_failure;
   }
-  bssl::UniquePtr<uint8_t> free_msg(msg);
+  UniquePtr<uint8_t> free_msg(msg);
 
   enum ssl_private_key_result_t sign_result = ssl_private_key_sign(
       hs, sig, &sig_len, max_sig_len, signature_algorithm, msg, msg_len);
@@ -660,3 +664,5 @@
   OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
   return 0;
 }
+
+}  // namespace bssl
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index 9153dd7..95ef653 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -28,6 +30,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 enum client_hs_state_t {
   state_process_hello_retry_request = 0,
   state_send_second_client_hello,
@@ -714,8 +718,8 @@
 }
 
 int tls13_process_new_session_ticket(SSL *ssl) {
-  bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_dup(
-      ssl->s3->established_session, SSL_SESSION_INCLUDE_NONAUTH));
+  UniquePtr<SSL_SESSION> session(SSL_SESSION_dup(ssl->s3->established_session,
+                                                 SSL_SESSION_INCLUDE_NONAUTH));
   if (!session) {
     return 0;
   }
@@ -786,3 +790,5 @@
   hs->key_share_bytes = NULL;
   hs->key_share_bytes_len = 0;
 }
+
+}  // namespace bssl
diff --git a/ssl/tls13_enc.cc b/ssl/tls13_enc.cc
index 97f0ed9..e7d5448 100644
--- a/ssl/tls13_enc.cc
+++ b/ssl/tls13_enc.cc
@@ -12,6 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -28,6 +30,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static int init_key_schedule(SSL_HANDSHAKE *hs, uint16_t version,
                               int algorithm_prf) {
   if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, version, algorithm_prf)) {
@@ -452,3 +456,5 @@
 
   return 1;
 }
+
+}  // namespace bssl
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index dd7e86d..a110b3a 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -19,6 +19,8 @@
 #define __STDC_LIMIT_MACROS
 #endif
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -36,6 +38,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 enum server_hs_state_t {
   state_select_parameters = 0,
   state_select_session,
@@ -910,3 +914,5 @@
 
   return ssl_hs_ok;
 }
+
+}  // namespace bssl
diff --git a/ssl/tls_method.cc b/ssl/tls_method.cc
index 0bcdf92..ba299ed 100644
--- a/ssl/tls_method.cc
+++ b/ssl/tls_method.cc
@@ -54,6 +54,8 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -65,6 +67,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static int ssl3_supports_cipher(const SSL_CIPHER *cipher) { return 1; }
 
 static void ssl3_expect_flight(SSL *ssl) {}
@@ -120,6 +124,64 @@
     ssl3_set_write_state,
 };
 
+static int ssl_noop_x509_check_client_CA_names(
+    STACK_OF(CRYPTO_BUFFER) *names) {
+  return 1;
+}
+
+static void ssl_noop_x509_clear(CERT *cert) {}
+static void ssl_noop_x509_free(CERT *cert) {}
+static void ssl_noop_x509_dup(CERT *new_cert, const CERT *cert) {}
+static void ssl_noop_x509_flush_cached_leaf(CERT *cert) {}
+static void ssl_noop_x509_flush_cached_chain(CERT *cert) {}
+static int ssl_noop_x509_session_cache_objects(SSL_SESSION *sess) {
+  return 1;
+}
+static int ssl_noop_x509_session_dup(SSL_SESSION *new_session,
+                                       const SSL_SESSION *session) {
+  return 1;
+}
+static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
+static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
+                                                   SSL *ssl,
+                                                   uint8_t *out_alert) {
+  return 0;
+}
+
+static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}
+static int ssl_noop_x509_ssl_new(SSL *ctx) { return 1; }
+static void ssl_noop_x509_ssl_free(SSL *ctx) { }
+static void ssl_noop_x509_ssl_flush_cached_client_CA(SSL *ssl) {}
+static int ssl_noop_x509_ssl_auto_chain_if_needed(SSL *ssl) { return 1; }
+static int ssl_noop_x509_ssl_ctx_new(SSL_CTX *ctx) { return 1; }
+static void ssl_noop_x509_ssl_ctx_free(SSL_CTX *ctx) { }
+static void ssl_noop_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {}
+
+static const SSL_X509_METHOD ssl_noop_x509_method = {
+  ssl_noop_x509_check_client_CA_names,
+  ssl_noop_x509_clear,
+  ssl_noop_x509_free,
+  ssl_noop_x509_dup,
+  ssl_noop_x509_flush_cached_chain,
+  ssl_noop_x509_flush_cached_leaf,
+  ssl_noop_x509_session_cache_objects,
+  ssl_noop_x509_session_dup,
+  ssl_noop_x509_session_clear,
+  ssl_noop_x509_session_verify_cert_chain,
+  ssl_noop_x509_hs_flush_cached_ca_names,
+  ssl_noop_x509_ssl_new,
+  ssl_noop_x509_ssl_free,
+  ssl_noop_x509_ssl_flush_cached_client_CA,
+  ssl_noop_x509_ssl_auto_chain_if_needed,
+  ssl_noop_x509_ssl_ctx_new,
+  ssl_noop_x509_ssl_ctx_free,
+  ssl_noop_x509_ssl_ctx_flush_cached_client_CA,
+};
+
+}  // namespace bssl
+
+using namespace bssl;
+
 const SSL_METHOD *TLS_method(void) {
   static const SSL_METHOD kMethod = {
       0,
@@ -133,6 +195,15 @@
   return TLS_method();
 }
 
+const SSL_METHOD *TLS_with_buffers_method(void) {
+  static const SSL_METHOD kMethod = {
+      0,
+      &kTLSProtocolMethod,
+      &ssl_noop_x509_method,
+  };
+  return &kMethod;
+}
+
 /* Legacy version-locked methods. */
 
 const SSL_METHOD *TLSv1_2_method(void) {
@@ -220,66 +291,3 @@
 const SSL_METHOD *TLS_client_method(void) {
   return TLS_method();
 }
-
-static int ssl_noop_x509_check_client_CA_names(
-    STACK_OF(CRYPTO_BUFFER) *names) {
-  return 1;
-}
-
-static void ssl_noop_x509_clear(CERT *cert) {}
-static void ssl_noop_x509_free(CERT *cert) {}
-static void ssl_noop_x509_dup(CERT *new_cert, const CERT *cert) {}
-static void ssl_noop_x509_flush_cached_leaf(CERT *cert) {}
-static void ssl_noop_x509_flush_cached_chain(CERT *cert) {}
-static int ssl_noop_x509_session_cache_objects(SSL_SESSION *sess) {
-  return 1;
-}
-static int ssl_noop_x509_session_dup(SSL_SESSION *new_session,
-                                       const SSL_SESSION *session) {
-  return 1;
-}
-static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
-static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
-                                                   SSL *ssl,
-                                                   uint8_t *out_alert) {
-  return 0;
-}
-
-static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}
-static int ssl_noop_x509_ssl_new(SSL *ctx) { return 1; }
-static void ssl_noop_x509_ssl_free(SSL *ctx) { }
-static void ssl_noop_x509_ssl_flush_cached_client_CA(SSL *ssl) {}
-static int ssl_noop_x509_ssl_auto_chain_if_needed(SSL *ssl) { return 1; }
-static int ssl_noop_x509_ssl_ctx_new(SSL_CTX *ctx) { return 1; }
-static void ssl_noop_x509_ssl_ctx_free(SSL_CTX *ctx) { }
-static void ssl_noop_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {}
-
-static const SSL_X509_METHOD ssl_noop_x509_method = {
-  ssl_noop_x509_check_client_CA_names,
-  ssl_noop_x509_clear,
-  ssl_noop_x509_free,
-  ssl_noop_x509_dup,
-  ssl_noop_x509_flush_cached_chain,
-  ssl_noop_x509_flush_cached_leaf,
-  ssl_noop_x509_session_cache_objects,
-  ssl_noop_x509_session_dup,
-  ssl_noop_x509_session_clear,
-  ssl_noop_x509_session_verify_cert_chain,
-  ssl_noop_x509_hs_flush_cached_ca_names,
-  ssl_noop_x509_ssl_new,
-  ssl_noop_x509_ssl_free,
-  ssl_noop_x509_ssl_flush_cached_client_CA,
-  ssl_noop_x509_ssl_auto_chain_if_needed,
-  ssl_noop_x509_ssl_ctx_new,
-  ssl_noop_x509_ssl_ctx_free,
-  ssl_noop_x509_ssl_ctx_flush_cached_client_CA,
-};
-
-const SSL_METHOD *TLS_with_buffers_method(void) {
-  static const SSL_METHOD kMethod = {
-      0,
-      &kTLSProtocolMethod,
-      &ssl_noop_x509_method,
-  };
-  return &kMethod;
-}
diff --git a/ssl/tls_record.cc b/ssl/tls_record.cc
index 4708296..b7ac0a9 100644
--- a/ssl/tls_record.cc
+++ b/ssl/tls_record.cc
@@ -106,6 +106,8 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
+#define BORINGSSL_INTERNAL_CXX_TYPES
+
 #include <openssl/ssl.h>
 
 #include <assert.h>
@@ -119,6 +121,8 @@
 #include "../crypto/internal.h"
 
 
+namespace bssl {
+
 /* kMaxEmptyRecords is the number of consecutive, empty records that will be
  * processed. Without this limit an attacker could send empty records at a
  * faster rate than we can process and cause record processing to loop
@@ -186,24 +190,6 @@
   return ret;
 }
 
-size_t SSL_max_seal_overhead(const SSL *ssl) {
-  if (SSL_is_dtls(ssl)) {
-    return dtls_max_seal_overhead(ssl, dtls1_use_current_epoch);
-  }
-
-  size_t ret = SSL3_RT_HEADER_LENGTH;
-  ret += SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
-  /* TLS 1.3 needs an extra byte for the encrypted record type. */
-  if (ssl->s3->aead_write_ctx != NULL &&
-      ssl->s3->aead_write_ctx->version >= TLS1_3_VERSION) {
-    ret += 1;
-  }
-  if (ssl_needs_record_splitting(ssl)) {
-    ret *= 2;
-  }
-  return ret;
-}
-
 enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
                                        size_t *out_consumed, uint8_t *out_alert,
                                        uint8_t *in, size_t in_len) {
@@ -586,3 +572,25 @@
   OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
   return ssl_open_record_error;
 }
+
+}  // namespace bssl
+
+using namespace bssl;
+
+size_t SSL_max_seal_overhead(const SSL *ssl) {
+  if (SSL_is_dtls(ssl)) {
+    return dtls_max_seal_overhead(ssl, dtls1_use_current_epoch);
+  }
+
+  size_t ret = SSL3_RT_HEADER_LENGTH;
+  ret += SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
+  /* TLS 1.3 needs an extra byte for the encrypted record type. */
+  if (ssl->s3->aead_write_ctx != NULL &&
+      ssl->s3->aead_write_ctx->version >= TLS1_3_VERSION) {
+    ret += 1;
+  }
+  if (ssl_needs_record_splitting(ssl)) {
+    ret *= 2;
+  }
+  return ret;
+}