Move C++ helpers into |bssl| namespace.

We currently have the situation where the |tool| and |bssl_shim| code
includes scoped_types.h from crypto/test and ssl/test. That's weird and
shouldn't happen. Also, our C++ consumers might quite like to have
access to the scoped types.

Thus this change moves some of the template code to base.h and puts it
all in a |bssl| namespace to prepare for scattering these types into
their respective headers. In order that all the existing test code be
able to access these types, it's all moved into the same namespace.

Change-Id: I3207e29474dc5fcc344ace43119df26dae04eabb
Reviewed-on: https://boringssl-review.googlesource.com/8730
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc
index 8b02442..e3e310b 100644
--- a/crypto/asn1/asn1_test.cc
+++ b/crypto/asn1/asn1_test.cc
@@ -21,6 +21,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 // kTag128 is an ASN.1 structure with a universal tag with number 128.
 static const uint8_t kTag128[] = {
     0x1f, 0x81, 0x00, 0x01, 0x00,
@@ -69,10 +71,12 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main() {
   CRYPTO_library_init();
 
-  if (!TestLargeTags()) {
+  if (!bssl::TestLargeTags()) {
     return 1;
   }
 
diff --git a/crypto/bio/bio_test.cc b/crypto/bio/bio_test.cc
index f2eb20b..e7c061e 100644
--- a/crypto/bio/bio_test.cc
+++ b/crypto/bio/bio_test.cc
@@ -43,6 +43,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 #if !defined(OPENSSL_WINDOWS)
 static int closesocket(int sock) {
   return close(sock);
@@ -339,7 +341,7 @@
   if (!ok) {
     out = nullptr;
   }
-  ScopedOpenSSLBytes out_storage(out);
+  ScopedBytes out_storage(out);
 
   if (should_succeed != (ok == 1)) {
     return false;
@@ -369,7 +371,7 @@
   static const size_t kLargePayloadLen = 8000;
   static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
                                          kLargePayloadLen & 0xff};
-  ScopedOpenSSLBytes large(reinterpret_cast<uint8_t *>(
+  ScopedBytes large(reinterpret_cast<uint8_t *>(
       OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
   if (!large) {
     return false;
@@ -410,6 +412,8 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(void) {
   CRYPTO_library_init();
 
@@ -428,10 +432,10 @@
   }
 #endif
 
-  if (!TestSocketConnect() ||
-      !TestPrintf() ||
-      !TestZeroCopyBioPairs() ||
-      !TestASN1()) {
+  if (!bssl::TestSocketConnect() ||
+      !bssl::TestPrintf() ||
+      !bssl::TestZeroCopyBioPairs() ||
+      !bssl::TestASN1()) {
     return 1;
   }
 
diff --git a/crypto/bn/bn_test.cc b/crypto/bn/bn_test.cc
index 3405cbd..3028745 100644
--- a/crypto/bn/bn_test.cc
+++ b/crypto/bn/bn_test.cc
@@ -90,6 +90,8 @@
 #include "../crypto/test/test_util.h"
 
 
+namespace bssl {
+
 static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
   BIGNUM *raw = NULL;
   int ret = BN_hex2bn(&raw, in);
@@ -132,8 +134,8 @@
     return true;
   }
 
-  ScopedOpenSSLString expected_str(BN_bn2hex(expected));
-  ScopedOpenSSLString actual_str(BN_bn2hex(actual));
+  ScopedString expected_str(BN_bn2hex(expected));
+  ScopedString actual_str(BN_bn2hex(actual));
   if (!expected_str || !actual_str) {
     return false;
   }
@@ -997,7 +999,7 @@
       CBB_cleanup(&cbb);
       return false;
     }
-    ScopedOpenSSLBytes delete_der(der);
+    ScopedBytes delete_der(der);
     if (der_len != test.der_len ||
         memcmp(der, reinterpret_cast<const uint8_t*>(test.der), der_len) != 0) {
       fprintf(stderr, "Bad serialization.\n");
@@ -1263,6 +1265,8 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char *argv[]) {
   CRYPTO_library_init();
 
@@ -1271,24 +1275,24 @@
     return 1;
   }
 
-  ScopedBN_CTX ctx(BN_CTX_new());
+  bssl::ScopedBN_CTX ctx(BN_CTX_new());
   if (!ctx) {
     return 1;
   }
 
-  if (!TestBN2BinPadded(ctx.get()) ||
-      !TestDec2BN(ctx.get()) ||
-      !TestHex2BN(ctx.get()) ||
-      !TestASC2BN(ctx.get()) ||
-      !TestMPI() ||
-      !TestRand() ||
-      !TestASN1() ||
-      !TestNegativeZero(ctx.get()) ||
-      !TestBadModulus(ctx.get()) ||
-      !TestExpModZero() ||
-      !TestSmallPrime(ctx.get())) {
+  if (!bssl::TestBN2BinPadded(ctx.get()) ||
+      !bssl::TestDec2BN(ctx.get()) ||
+      !bssl::TestHex2BN(ctx.get()) ||
+      !bssl::TestASC2BN(ctx.get()) ||
+      !bssl::TestMPI() ||
+      !bssl::TestRand() ||
+      !bssl::TestASN1() ||
+      !bssl::TestNegativeZero(ctx.get()) ||
+      !bssl::TestBadModulus(ctx.get()) ||
+      !bssl::TestExpModZero() ||
+      !bssl::TestSmallPrime(ctx.get())) {
     return 1;
   }
 
-  return FileTestMain(RunTest, ctx.get(), argv[1]);
+  return bssl::FileTestMain(bssl::RunTest, ctx.get(), argv[1]);
 }
diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc
index 31ee51c..95d9b85 100644
--- a/crypto/bytestring/bytestring_test.cc
+++ b/crypto/bytestring/bytestring_test.cc
@@ -29,6 +29,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 static bool TestSkip() {
   static const uint8_t kData[] = {1, 2, 3};
   CBS data;
@@ -292,7 +294,7 @@
     return false;
   }
 
-  ScopedOpenSSLBytes scoper(buf);
+  ScopedBytes scoper(buf);
   return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
 }
 
@@ -337,7 +339,7 @@
     CBB_cleanup(&cbb);
     return false;
   }
-  ScopedOpenSSLBytes scoper(out_buf);
+  ScopedBytes scoper(out_buf);
   return out_size == 1 && out_buf[0] == 0;
 }
 
@@ -370,7 +372,7 @@
     return false;
   }
 
-  ScopedOpenSSLBytes scoper(buf);
+  ScopedBytes scoper(buf);
   return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
 }
 
@@ -410,7 +412,7 @@
   if (!CBB_finish(cbb.get(), &buf, &buf_len)) {
     return false;
   }
-  ScopedOpenSSLBytes scoper(buf);
+  ScopedBytes scoper(buf);
 
   static const uint8_t kExpected[] = {
         0xaa,
@@ -456,7 +458,7 @@
     CBB_cleanup(&cbb);
     return false;
   }
-  ScopedOpenSSLBytes scoper(buf);
+  ScopedBytes scoper(buf);
 
   if (buf_len != 3 ||
       memcmp(buf, "\x01\x01\x02", 3) != 0) {
@@ -480,7 +482,7 @@
     CBB_cleanup(&cbb);
     return false;
   }
-  ScopedOpenSSLBytes scoper(buf);
+  ScopedBytes scoper(buf);
 
   if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
     return false;
@@ -555,7 +557,7 @@
     fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
     return false;
   }
-  ScopedOpenSSLBytes scoper(out);
+  ScopedBytes scoper(out);
 
   if (out == NULL) {
     if (ber_len != der_len ||
@@ -668,7 +670,7 @@
     int ok = CBS_get_asn1_implicit_string(&in, &out, &storage,
                                           CBS_ASN1_CONTEXT_SPECIFIC | 0,
                                           CBS_ASN1_OCTETSTRING);
-    ScopedOpenSSLBytes scoper(storage);
+    ScopedBytes scoper(storage);
 
     if (static_cast<bool>(ok) != test.ok) {
       fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n",
@@ -747,7 +749,7 @@
       CBB_cleanup(&cbb);
       return false;
     }
-    ScopedOpenSSLBytes scoper(out);
+    ScopedBytes scoper(out);
     if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
       return false;
     }
@@ -797,27 +799,29 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(void) {
   CRYPTO_library_init();
 
-  if (!TestSkip() ||
-      !TestGetUint() ||
-      !TestGetPrefixed() ||
-      !TestGetPrefixedBad() ||
-      !TestGetASN1() ||
-      !TestCBBBasic() ||
-      !TestCBBFixed() ||
-      !TestCBBFinishChild() ||
-      !TestCBBMisuse() ||
-      !TestCBBPrefixed() ||
-      !TestCBBDiscardChild() ||
-      !TestCBBASN1() ||
-      !TestBerConvert() ||
-      !TestImplicitString() ||
-      !TestASN1Uint64() ||
-      !TestGetOptionalASN1Bool() ||
-      !TestZero() ||
-      !TestCBBReserve()) {
+  if (!bssl::TestSkip() ||
+      !bssl::TestGetUint() ||
+      !bssl::TestGetPrefixed() ||
+      !bssl::TestGetPrefixedBad() ||
+      !bssl::TestGetASN1() ||
+      !bssl::TestCBBBasic() ||
+      !bssl::TestCBBFixed() ||
+      !bssl::TestCBBFinishChild() ||
+      !bssl::TestCBBMisuse() ||
+      !bssl::TestCBBPrefixed() ||
+      !bssl::TestCBBDiscardChild() ||
+      !bssl::TestCBBASN1() ||
+      !bssl::TestBerConvert() ||
+      !bssl::TestImplicitString() ||
+      !bssl::TestASN1Uint64() ||
+      !bssl::TestGetOptionalASN1Bool() ||
+      !bssl::TestZero() ||
+      !bssl::TestCBBReserve()) {
     return 1;
   }
 
diff --git a/crypto/cipher/aead_test.cc b/crypto/cipher/aead_test.cc
index 8bad93f..cf0f24a 100644
--- a/crypto/cipher/aead_test.cc
+++ b/crypto/cipher/aead_test.cc
@@ -25,6 +25,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 // This program tests an AEAD against a series of test vectors from a file,
 // using the FileTest format. As an example, here's a valid test case:
 //
@@ -327,7 +329,7 @@
   { "", NULL, false },
 };
 
-int main(int argc, char **argv) {
+static int Main(int argc, char **argv) {
   CRYPTO_library_init();
 
   if (argc != 3) {
@@ -360,3 +362,9 @@
 
   return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
 }
+
+}  // namespace bssl
+
+int main(int argc, char **argv) {
+  return bssl::Main(argc, argv);
+}
diff --git a/crypto/cipher/cipher_test.cc b/crypto/cipher/cipher_test.cc
index fa384c6..221eb67 100644
--- a/crypto/cipher/cipher_test.cc
+++ b/crypto/cipher/cipher_test.cc
@@ -65,6 +65,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 static const EVP_CIPHER *GetCipher(const std::string &name) {
   if (name == "DES-CBC") {
     return EVP_des_cbc();
@@ -284,6 +286,8 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
   CRYPTO_library_init();
 
@@ -292,5 +296,5 @@
     return 1;
   }
 
-  return FileTestMain(TestCipher, nullptr, argv[1]);
+  return bssl::FileTestMain(bssl::TestCipher, nullptr, argv[1]);
 }
diff --git a/crypto/cmac/cmac_test.cc b/crypto/cmac/cmac_test.cc
index 2496f2a..11b7ad6 100644
--- a/crypto/cmac/cmac_test.cc
+++ b/crypto/cmac/cmac_test.cc
@@ -22,6 +22,8 @@
 #include "../test/test_util.h"
 
 
+namespace bssl {
+
 static void dump(const uint8_t *got, const uint8_t *want, size_t len) {
   hexdump(stderr, "got :", got, len);
   hexdump(stderr, "want:", want, len);
@@ -141,8 +143,10 @@
   return 1;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
-  if (!rfc_4493_test_vectors()) {
+  if (!bssl::rfc_4493_test_vectors()) {
     return 1;
   }
 
diff --git a/crypto/curve25519/ed25519_test.cc b/crypto/curve25519/ed25519_test.cc
index 1b6a0b6..3c08cc9 100644
--- a/crypto/curve25519/ed25519_test.cc
+++ b/crypto/curve25519/ed25519_test.cc
@@ -20,6 +20,8 @@
 #include "../test/file_test.h"
 
 
+namespace bssl {
+
 static bool TestSignature(FileTest *t, void *arg) {
   std::vector<uint8_t> private_key, public_key, message, expected_signature;
   if (!t->GetBytes(&private_key, "PRIV") ||
@@ -53,11 +55,13 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
   if (argc != 2) {
     fprintf(stderr, "%s <test input.txt>\n", argv[0]);
     return 1;
   }
 
-  return FileTestMain(TestSignature, nullptr, argv[1]);
+  return bssl::FileTestMain(bssl::TestSignature, nullptr, argv[1]);
 }
diff --git a/crypto/curve25519/spake25519_test.cc b/crypto/curve25519/spake25519_test.cc
index d97a860..b8742ed 100644
--- a/crypto/curve25519/spake25519_test.cc
+++ b/crypto/curve25519/spake25519_test.cc
@@ -22,6 +22,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 struct SPAKE2Run {
   bool Run() {
     ScopedSPAKE2_CTX alice(SPAKE2_CTX_new(
@@ -154,13 +156,15 @@
   return true;
 }
 
+}  // namespace bssl
+
 /* TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down. */
 
 int main(int argc, char **argv) {
-  if (!TestSPAKE2() ||
-      !TestWrongPassword() ||
-      !TestWrongNames() ||
-      !TestCorruptMessages()) {
+  if (!bssl::TestSPAKE2() ||
+      !bssl::TestWrongPassword() ||
+      !bssl::TestWrongNames() ||
+      !bssl::TestCorruptMessages()) {
     return 1;
   }
 
diff --git a/crypto/dh/dh_test.cc b/crypto/dh/dh_test.cc
index 1c24428..8fe496c 100644
--- a/crypto/dh/dh_test.cc
+++ b/crypto/dh/dh_test.cc
@@ -71,25 +71,7 @@
 #include "../test/scoped_types.h"
 
 
-static bool RunBasicTests();
-static bool RunRFC5114Tests();
-static bool TestBadY();
-static bool TestASN1();
-
-int main(int argc, char *argv[]) {
-  CRYPTO_library_init();
-
-  if (!RunBasicTests() ||
-      !RunRFC5114Tests() ||
-      !TestBadY() ||
-      !TestASN1()) {
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  printf("PASS\n");
-  return 0;
-}
+namespace bssl {
 
 static int GenerateCallback(int p, int n, BN_GENCB *arg) {
   char c = '*';
@@ -575,7 +557,7 @@
       !CBB_finish(cbb.get(), &der, &der_len)) {
     return false;
   }
-  ScopedOpenSSLBytes free_der(der);
+  ScopedBytes free_der(der);
   if (der_len != sizeof(kParams) || memcmp(der, kParams, der_len) != 0) {
     return false;
   }
@@ -617,10 +599,27 @@
       !CBB_finish(cbb.get(), &der, &der_len)) {
     return false;
   }
-  ScopedOpenSSLBytes free_der2(der);
+  ScopedBytes free_der2(der);
   if (der_len != sizeof(kParamsDSA) || memcmp(der, kParamsDSA, der_len) != 0) {
     return false;
   }
 
   return true;
 }
+
+}  // namespace bssl
+
+int main(int argc, char *argv[]) {
+  CRYPTO_library_init();
+
+  if (!bssl::RunBasicTests() ||
+      !bssl::RunRFC5114Tests() ||
+      !bssl::TestBadY() ||
+      !bssl::TestASN1()) {
+    ERR_print_errors_fp(stderr);
+    return 1;
+  }
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/crypto/digest/digest_test.cc b/crypto/digest/digest_test.cc
index 39ceaff..32d12d2 100644
--- a/crypto/digest/digest_test.cc
+++ b/crypto/digest/digest_test.cc
@@ -26,6 +26,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 struct MD {
   // name is the name of the digest.
   const char* name;
@@ -243,7 +245,7 @@
   return true;
 }
 
-int main(void) {
+static int Main() {
   CRYPTO_library_init();
 
   for (size_t i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) {
@@ -260,3 +262,9 @@
   printf("PASS\n");
   return 0;
 }
+
+}  // namespace bssl
+
+int main() {
+  return bssl::Main();
+}
diff --git a/crypto/ec/ec_test.cc b/crypto/ec/ec_test.cc
index 23befeb..864cd49 100644
--- a/crypto/ec/ec_test.cc
+++ b/crypto/ec/ec_test.cc
@@ -26,6 +26,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
 // omitted.
 static const uint8_t kECKeyWithoutPublic[] = {
@@ -161,8 +163,8 @@
     fprintf(stderr, "Failed to get public key in affine coordinates.\n");
     return false;
   }
-  ScopedOpenSSLString x_hex(BN_bn2hex(x.get()));
-  ScopedOpenSSLString y_hex(BN_bn2hex(y.get()));
+  ScopedString x_hex(BN_bn2hex(x.get()));
+  ScopedString y_hex(BN_bn2hex(y.get()));
   if (!x_hex || !y_hex) {
     return false;
   }
@@ -471,15 +473,17 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(void) {
   CRYPTO_library_init();
 
-  if (!Testd2i_ECPrivateKey() ||
-      !TestZeroPadding() ||
-      !TestSpecifiedCurve() ||
-      !ForEachCurve(TestSetAffine) ||
-      !ForEachCurve(TestAddingEqualPoints) ||
-      !TestArbitraryCurve()) {
+  if (!bssl::Testd2i_ECPrivateKey() ||
+      !bssl::TestZeroPadding() ||
+      !bssl::TestSpecifiedCurve() ||
+      !bssl::ForEachCurve(bssl::TestSetAffine) ||
+      !bssl::ForEachCurve(bssl::TestAddingEqualPoints) ||
+      !bssl::TestArbitraryCurve()) {
     fprintf(stderr, "failed\n");
     return 1;
   }
diff --git a/crypto/ecdsa/ecdsa_test.cc b/crypto/ecdsa/ecdsa_test.cc
index 8d7827d..ad2325b 100644
--- a/crypto/ecdsa/ecdsa_test.cc
+++ b/crypto/ecdsa/ecdsa_test.cc
@@ -64,6 +64,9 @@
 
 #include "../test/scoped_types.h"
 
+
+namespace bssl {
+
 enum Api {
   kEncodedApi,
   kRawApi,
@@ -82,7 +85,7 @@
       if (!ECDSA_SIG_to_bytes(&der, &der_len, ecdsa_sig)) {
         return false;
       }
-      ScopedOpenSSLBytes delete_der(der);
+      ScopedBytes delete_der(der);
       actual_result = ECDSA_verify(0, digest, digest_len, der, der_len, eckey);
       break;
     }
@@ -328,7 +331,7 @@
   if (!ECDSA_SIG_to_bytes(&der, &der_len, sig.get())) {
     return false;
   }
-  ScopedOpenSSLBytes delete_der(der);
+  ScopedBytes delete_der(der);
 
   size_t max_len = ECDSA_SIG_max_len(order_len);
   if (max_len != der_len) {
@@ -340,6 +343,8 @@
   return true;
 }
 
+}  // namespace bssl
+
 static size_t BitsToBytes(size_t bits) {
   return (bits / 8) + (7 + (bits % 8)) / 8;
 }
@@ -347,12 +352,12 @@
 int main(void) {
   CRYPTO_library_init();
 
-  if (!TestBuiltin(stdout) ||
-      !TestECDSA_SIG_max_len(BitsToBytes(224)) ||
-      !TestECDSA_SIG_max_len(BitsToBytes(256)) ||
-      !TestECDSA_SIG_max_len(BitsToBytes(384)) ||
-      !TestECDSA_SIG_max_len(BitsToBytes(521)) ||
-      !TestECDSA_SIG_max_len(BitsToBytes(10000))) {
+  if (!bssl::TestBuiltin(stdout) ||
+      !bssl::TestECDSA_SIG_max_len(BitsToBytes(224)) ||
+      !bssl::TestECDSA_SIG_max_len(BitsToBytes(256)) ||
+      !bssl::TestECDSA_SIG_max_len(BitsToBytes(384)) ||
+      !bssl::TestECDSA_SIG_max_len(BitsToBytes(521)) ||
+      !bssl::TestECDSA_SIG_max_len(BitsToBytes(10000))) {
     printf("\nECDSA test failed\n");
     ERR_print_errors_fp(stdout);
     return 1;
diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc
index 9bc36ad..2253c56 100644
--- a/crypto/evp/evp_extra_test.cc
+++ b/crypto/evp/evp_extra_test.cc
@@ -30,6 +30,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 // kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
 // should never use this key anywhere but in an example.
 static const uint8_t kExampleRSAKeyDER[] = {
@@ -671,7 +673,7 @@
   return true;
 }
 
-int main(void) {
+static int Main() {
   CRYPTO_library_init();
 
   if (!TestEVP_DigestSignInit()) {
@@ -719,3 +721,9 @@
   printf("PASS\n");
   return 0;
 }
+
+}  // namespace bssl
+
+int main() {
+  return bssl::Main();
+}
diff --git a/crypto/evp/evp_test.cc b/crypto/evp/evp_test.cc
index b01d1e4..9b8a683 100644
--- a/crypto/evp/evp_test.cc
+++ b/crypto/evp/evp_test.cc
@@ -77,6 +77,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 // evp_test dispatches between multiple test types. PrivateKey tests take a key
 // name parameter and single block, decode it as a PEM private key, and save it
 // under that key name. Decrypt, Sign, and Verify tests take a previously
@@ -149,7 +151,7 @@
       !CBB_finish(cbb.get(), &der, &der_len)) {
     return false;
   }
-  ScopedOpenSSLBytes free_der(der);
+  ScopedBytes free_der(der);
 
   std::vector<uint8_t> output = input;
   if (t->HasAttribute("Output") &&
@@ -253,6 +255,8 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
   CRYPTO_library_init();
   if (argc != 2) {
@@ -260,6 +264,6 @@
     return 1;
   }
 
-  KeyMap map;
-  return FileTestMain(TestEVP, &map, argv[1]);
+  bssl::KeyMap map;
+  return bssl::FileTestMain(bssl::TestEVP, &map, argv[1]);
 }
diff --git a/crypto/hmac/hmac_test.cc b/crypto/hmac/hmac_test.cc
index da390ef..ba84cc2 100644
--- a/crypto/hmac/hmac_test.cc
+++ b/crypto/hmac/hmac_test.cc
@@ -68,6 +68,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 static const EVP_MD *GetDigest(const std::string &name) {
   if (name == "MD5") {
     return EVP_md5();
@@ -152,6 +154,8 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char *argv[]) {
   CRYPTO_library_init();
 
@@ -160,5 +164,5 @@
     return 1;
   }
 
-  return FileTestMain(TestHMAC, nullptr, argv[1]);
+  return bssl::FileTestMain(bssl::TestHMAC, nullptr, argv[1]);
 }
diff --git a/crypto/newhope/newhope_statistical_test.cc b/crypto/newhope/newhope_statistical_test.cc
index 44fac48..d3a5443 100644
--- a/crypto/newhope/newhope_statistical_test.cc
+++ b/crypto/newhope/newhope_statistical_test.cc
@@ -25,6 +25,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static const unsigned kNumTests = 1000;
 
 static bool TestNoise(void) {
@@ -146,9 +148,11 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(void) {
-  if (!TestKeys() ||
-      !TestNoise()) {
+  if (!bssl::TestKeys() ||
+      !bssl::TestNoise()) {
     return 1;
   }
   printf("PASS\n");
diff --git a/crypto/newhope/newhope_test.cc b/crypto/newhope/newhope_test.cc
index 6637393..d94eee8 100644
--- a/crypto/newhope/newhope_test.cc
+++ b/crypto/newhope/newhope_test.cc
@@ -23,6 +23,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 // Set to 10 for quick execution.  Tested up to 1,000,000.
 static const int kNumTests = 10;
 
@@ -128,11 +130,13 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(void) {
-  for (int i = 0; i < kNumTests; i++) {
-    if (!TestKeys() ||
-        !TestInvalidSK() ||
-        !TestInvalidAcceptMsg()) {
+  for (int i = 0; i < bssl::kNumTests; i++) {
+    if (!bssl::TestKeys() ||
+        !bssl::TestInvalidSK() ||
+        !bssl::TestInvalidAcceptMsg()) {
       return 1;
     }
   }
diff --git a/crypto/newhope/newhope_vectors_test.cc b/crypto/newhope/newhope_vectors_test.cc
index fe84cd4..691d693 100644
--- a/crypto/newhope/newhope_vectors_test.cc
+++ b/crypto/newhope/newhope_vectors_test.cc
@@ -24,6 +24,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static bool TestNewhope(FileTest *t, void *arg) {
   ScopedNEWHOPE_POLY a(NEWHOPE_POLY_new());
   ScopedNEWHOPE_POLY s(NEWHOPE_POLY_new()), sp(NEWHOPE_POLY_new());
@@ -110,6 +112,8 @@
   }
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
   CRYPTO_library_init();
 
@@ -118,5 +122,5 @@
     return 1;
   }
 
-  return FileTestMain(TestNewhope, nullptr, argv[1]);
+  return bssl::FileTestMain(bssl::TestNewhope, nullptr, argv[1]);
 }
diff --git a/crypto/pkcs8/pkcs12_test.cc b/crypto/pkcs8/pkcs12_test.cc
index 17bcd27..1069444 100644
--- a/crypto/pkcs8/pkcs12_test.cc
+++ b/crypto/pkcs8/pkcs12_test.cc
@@ -681,6 +681,8 @@
     0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
 };
 
+namespace bssl {
+
 static const char kPassword[] = "foo";
 
 static bool Test(const char *name, const uint8_t *der, size_t der_len) {
@@ -755,13 +757,15 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
   CRYPTO_library_init();
 
-  if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
-      !Test("NSS", kNSS, sizeof(kNSS)) ||
-      !Test("Windows", kWindows, sizeof(kWindows)) ||
-      !TestCompat(kWindows, sizeof(kWindows))) {
+  if (!bssl::Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
+      !bssl::Test("NSS", kNSS, sizeof(kNSS)) ||
+      !bssl::Test("Windows", kWindows, sizeof(kWindows)) ||
+      !bssl::TestCompat(kWindows, sizeof(kWindows))) {
     return 1;
   }
 
diff --git a/crypto/pkcs8/pkcs8_test.cc b/crypto/pkcs8/pkcs8_test.cc
index 7a88ddf..e54a699 100644
--- a/crypto/pkcs8/pkcs8_test.cc
+++ b/crypto/pkcs8/pkcs8_test.cc
@@ -62,7 +62,9 @@
   0xd6, 0x2d,
 };
 
-static bool test(const uint8_t *der, size_t der_len) {
+namespace bssl {
+
+static bool Test(const uint8_t *der, size_t der_len) {
   const uint8_t *data = der;
   ScopedX509_SIG sig(d2i_X509_SIG(NULL, &data, der_len));
   if (sig.get() == NULL || data != der + der_len) {
@@ -81,8 +83,10 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
-  if (!test(kDER, sizeof(kDER))) {
+  if (!bssl::Test(kDER, sizeof(kDER))) {
     return 1;
   }
 
diff --git a/crypto/poly1305/poly1305_test.cc b/crypto/poly1305/poly1305_test.cc
index 2c25e93..a327225 100644
--- a/crypto/poly1305/poly1305_test.cc
+++ b/crypto/poly1305/poly1305_test.cc
@@ -24,6 +24,8 @@
 #include "../test/file_test.h"
 
 
+namespace bssl {
+
 static bool TestSIMD(FileTest *t, unsigned excess,
                      const std::vector<uint8_t> &key,
                      const std::vector<uint8_t> &in,
@@ -119,6 +121,8 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
   CRYPTO_library_init();
 
@@ -127,5 +131,5 @@
     return 1;
   }
 
-  return FileTestMain(TestPoly1305, nullptr, argv[1]);
+  return bssl::FileTestMain(bssl::TestPoly1305, nullptr, argv[1]);
 }
diff --git a/crypto/rsa/rsa_test.cc b/crypto/rsa/rsa_test.cc
index 62177a4..5307f2c 100644
--- a/crypto/rsa/rsa_test.cc
+++ b/crypto/rsa/rsa_test.cc
@@ -523,6 +523,8 @@
     0xdd, 0x02, 0x01, 0x01,
 };
 
+namespace bssl {
+
 static bool TestRSA(const uint8_t *der, size_t der_len,
                     const uint8_t *oaep_ciphertext,
                     size_t oaep_ciphertext_len) {
@@ -855,7 +857,7 @@
   if (!RSA_private_key_to_bytes(&der, &der_len, rsa.get())) {
     return false;
   }
-  ScopedOpenSSLBytes delete_der(der);
+  ScopedBytes delete_der(der);
   if (der_len != sizeof(kKey1) - 1 || memcmp(der, kKey1, der_len) != 0) {
     return false;
   }
@@ -878,7 +880,7 @@
   if (!RSA_public_key_to_bytes(&der2, &der2_len, rsa.get())) {
     return false;
   }
-  ScopedOpenSSLBytes delete_der2(der2);
+  ScopedBytes delete_der2(der2);
   if (der_len != der2_len || memcmp(der, der2, der_len) != 0) {
     return false;
   }
@@ -922,30 +924,32 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char *argv[]) {
   CRYPTO_library_init();
 
-  if (!TestRSA(kKey1, sizeof(kKey1) - 1, kOAEPCiphertext1,
-               sizeof(kOAEPCiphertext1) - 1) ||
-      !TestRSA(kKey2, sizeof(kKey2) - 1, kOAEPCiphertext2,
-               sizeof(kOAEPCiphertext2) - 1) ||
-      !TestRSA(kKey3, sizeof(kKey3) - 1, kOAEPCiphertext3,
-               sizeof(kOAEPCiphertext3) - 1) ||
-      !TestOnlyDGiven() ||
-      !TestRecoverCRTParams() ||
-      !TestBadKey() ||
-      !TestMultiPrimeKey(2, kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1,
-                            kTwoPrimeEncryptedMessage,
-                            sizeof(kTwoPrimeEncryptedMessage)) ||
-      !TestMultiPrimeKey(3, kThreePrimeKey, sizeof(kThreePrimeKey) - 1,
-                            kThreePrimeEncryptedMessage,
-                            sizeof(kThreePrimeEncryptedMessage)) ||
-      !TestMultiPrimeKey(6, kSixPrimeKey, sizeof(kSixPrimeKey) - 1,
-                            kSixPrimeEncryptedMessage,
-                            sizeof(kSixPrimeEncryptedMessage)) ||
-      !TestMultiPrimeKeygen() ||
-      !TestASN1() ||
-      !TestBadExponent()) {
+  if (!bssl::TestRSA(kKey1, sizeof(kKey1) - 1, kOAEPCiphertext1,
+                     sizeof(kOAEPCiphertext1) - 1) ||
+      !bssl::TestRSA(kKey2, sizeof(kKey2) - 1, kOAEPCiphertext2,
+                     sizeof(kOAEPCiphertext2) - 1) ||
+      !bssl::TestRSA(kKey3, sizeof(kKey3) - 1, kOAEPCiphertext3,
+                     sizeof(kOAEPCiphertext3) - 1) ||
+      !bssl::TestOnlyDGiven() ||
+      !bssl::TestRecoverCRTParams() ||
+      !bssl::TestBadKey() ||
+      !bssl::TestMultiPrimeKey(2, kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1,
+                               kTwoPrimeEncryptedMessage,
+                               sizeof(kTwoPrimeEncryptedMessage)) ||
+      !bssl::TestMultiPrimeKey(3, kThreePrimeKey, sizeof(kThreePrimeKey) - 1,
+                               kThreePrimeEncryptedMessage,
+                               sizeof(kThreePrimeEncryptedMessage)) ||
+      !bssl::TestMultiPrimeKey(6, kSixPrimeKey, sizeof(kSixPrimeKey) - 1,
+                               kSixPrimeEncryptedMessage,
+                               sizeof(kSixPrimeEncryptedMessage)) ||
+      !bssl::TestMultiPrimeKeygen() ||
+      !bssl::TestASN1() ||
+      !bssl::TestBadExponent()) {
     return 1;
   }
 
diff --git a/crypto/test/file_test.cc b/crypto/test/file_test.cc
index d684aa0..7e99316 100644
--- a/crypto/test/file_test.cc
+++ b/crypto/test/file_test.cc
@@ -25,6 +25,8 @@
 #include <openssl/err.h>
 
 
+namespace bssl {
+
 FileTest::FileTest(const char *path) {
   file_ = fopen(path, "r");
   if (file_ == nullptr) {
@@ -300,3 +302,5 @@
   printf("PASS\n");
   return 0;
 }
+
+}  // namespace bssl
diff --git a/crypto/test/file_test.h b/crypto/test/file_test.h
index a859127..447b1ee 100644
--- a/crypto/test/file_test.h
+++ b/crypto/test/file_test.h
@@ -30,6 +30,9 @@
 
 OPENSSL_MSVC_PRAGMA(warning(pop))
 
+
+namespace bssl {
+
 // File-based test framework.
 //
 // This module provides a file-based test framework. The file format is based on
@@ -153,5 +156,7 @@
 int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg,
                  const char *path);
 
+}  // namespace bssl
+
 
 #endif /* OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H */
diff --git a/crypto/test/scoped_types.h b/crypto/test/scoped_types.h
index 2a2c371..7e4a48e 100644
--- a/crypto/test/scoped_types.h
+++ b/crypto/test/scoped_types.h
@@ -15,6 +15,8 @@
 #ifndef OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
 #define OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
 
+#include <openssl/base.h>
+
 #include <stdint.h>
 #include <stdio.h>
 
@@ -40,28 +42,7 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
-
-template<typename T, void (*func)(T*)>
-struct OpenSSLDeleter {
-  void operator()(T *obj) {
-    func(obj);
-  }
-};
-
-template<typename StackType, typename T, void (*func)(T*)>
-struct OpenSSLStackDeleter {
-  void operator()(StackType *obj) {
-    sk_pop_free(reinterpret_cast<_STACK*>(obj),
-                reinterpret_cast<void (*)(void *)>(func));
-  }
-};
-
-template<typename T>
-struct OpenSSLFree {
-  void operator()(T *buf) {
-    OPENSSL_free(buf);
-  }
-};
+namespace bssl {
 
 struct FileCloser {
   void operator()(FILE *file) {
@@ -69,77 +50,48 @@
   }
 };
 
-template<typename T, void (*func)(T*)>
-using ScopedOpenSSLType = std::unique_ptr<T, OpenSSLDeleter<T, func>>;
+using ScopedASN1_TYPE = ScopedType<ASN1_TYPE, ASN1_TYPE_free>;
+using ScopedBIO = ScopedType<BIO, BIO_vfree>;
+using ScopedBIGNUM = ScopedType<BIGNUM, BN_free>;
+using ScopedBN_CTX = ScopedType<BN_CTX, BN_CTX_free>;
+using ScopedBN_MONT_CTX = ScopedType<BN_MONT_CTX, BN_MONT_CTX_free>;
+using ScopedCMAC_CTX = ScopedType<CMAC_CTX, CMAC_CTX_free>;
+using ScopedDH = ScopedType<DH, DH_free>;
+using ScopedECDSA_SIG = ScopedType<ECDSA_SIG, ECDSA_SIG_free>;
+using ScopedEC_GROUP = ScopedType<EC_GROUP, EC_GROUP_free>;
+using ScopedEC_KEY = ScopedType<EC_KEY, EC_KEY_free>;
+using ScopedEC_POINT = ScopedType<EC_POINT, EC_POINT_free>;
+using ScopedEVP_PKEY = ScopedType<EVP_PKEY, EVP_PKEY_free>;
+using ScopedEVP_PKEY_CTX = ScopedType<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
+using ScopedNEWHOPE_POLY = ScopedType<NEWHOPE_POLY, NEWHOPE_POLY_free>;
+using ScopedPKCS8_PRIV_KEY_INFO =
+    ScopedType<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
+using ScopedPKCS12 = ScopedType<PKCS12, PKCS12_free>;
+using ScopedSPAKE2_CTX = ScopedType<SPAKE2_CTX, SPAKE2_CTX_free>;
+using ScopedRSA = ScopedType<RSA, RSA_free>;
+using ScopedX509 = ScopedType<X509, X509_free>;
+using ScopedX509_ALGOR = ScopedType<X509_ALGOR, X509_ALGOR_free>;
+using ScopedX509_SIG = ScopedType<X509_SIG, X509_SIG_free>;
+using ScopedX509_STORE_CTX = ScopedType<X509_STORE_CTX, X509_STORE_CTX_free>;
 
-template<typename StackType, typename T, void (*func)(T*)>
-using ScopedOpenSSLStack =
-    std::unique_ptr<StackType, OpenSSLStackDeleter<StackType, T, func>>;
+using ScopedX509Stack = ScopedStack<STACK_OF(X509), X509, X509_free>;
 
-template<typename T, typename CleanupRet, void (*init_func)(T*),
-         CleanupRet (*cleanup_func)(T*)>
-class ScopedOpenSSLContext {
- public:
-  ScopedOpenSSLContext() {
-    init_func(&ctx_);
-  }
-  ~ScopedOpenSSLContext() {
-    cleanup_func(&ctx_);
-  }
+using ScopedCBB = ScopedContext<CBB, void, CBB_zero, CBB_cleanup>;
+using ScopedEVP_AEAD_CTX =
+    ScopedContext<EVP_AEAD_CTX, void, EVP_AEAD_CTX_zero, EVP_AEAD_CTX_cleanup>;
+using ScopedEVP_CIPHER_CTX =
+    ScopedContext<EVP_CIPHER_CTX, int, EVP_CIPHER_CTX_init,
+                  EVP_CIPHER_CTX_cleanup>;
+using ScopedEVP_MD_CTX =
+    ScopedContext<EVP_MD_CTX, int, EVP_MD_CTX_init, EVP_MD_CTX_cleanup>;
+using ScopedHMAC_CTX =
+    ScopedContext<HMAC_CTX, void, HMAC_CTX_init, HMAC_CTX_cleanup>;
 
-  T *get() { return &ctx_; }
-  const T *get() const { return &ctx_; }
-
-  void Reset() {
-    cleanup_func(&ctx_);
-    init_func(&ctx_);
-  }
-
- private:
-  T ctx_;
-};
-
-using ScopedASN1_TYPE = ScopedOpenSSLType<ASN1_TYPE, ASN1_TYPE_free>;
-using ScopedBIO = ScopedOpenSSLType<BIO, BIO_vfree>;
-using ScopedBIGNUM = ScopedOpenSSLType<BIGNUM, BN_free>;
-using ScopedBN_CTX = ScopedOpenSSLType<BN_CTX, BN_CTX_free>;
-using ScopedBN_MONT_CTX = ScopedOpenSSLType<BN_MONT_CTX, BN_MONT_CTX_free>;
-using ScopedCMAC_CTX = ScopedOpenSSLType<CMAC_CTX, CMAC_CTX_free>;
-using ScopedDH = ScopedOpenSSLType<DH, DH_free>;
-using ScopedECDSA_SIG = ScopedOpenSSLType<ECDSA_SIG, ECDSA_SIG_free>;
-using ScopedEC_GROUP = ScopedOpenSSLType<EC_GROUP, EC_GROUP_free>;
-using ScopedEC_KEY = ScopedOpenSSLType<EC_KEY, EC_KEY_free>;
-using ScopedEC_POINT = ScopedOpenSSLType<EC_POINT, EC_POINT_free>;
-using ScopedEVP_PKEY = ScopedOpenSSLType<EVP_PKEY, EVP_PKEY_free>;
-using ScopedEVP_PKEY_CTX = ScopedOpenSSLType<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
-using ScopedNEWHOPE_POLY = ScopedOpenSSLType<NEWHOPE_POLY, NEWHOPE_POLY_free>;
-using ScopedPKCS8_PRIV_KEY_INFO = ScopedOpenSSLType<PKCS8_PRIV_KEY_INFO,
-                                                    PKCS8_PRIV_KEY_INFO_free>;
-using ScopedPKCS12 = ScopedOpenSSLType<PKCS12, PKCS12_free>;
-using ScopedSPAKE2_CTX = ScopedOpenSSLType<SPAKE2_CTX, SPAKE2_CTX_free>;
-using ScopedRSA = ScopedOpenSSLType<RSA, RSA_free>;
-using ScopedX509 = ScopedOpenSSLType<X509, X509_free>;
-using ScopedX509_ALGOR = ScopedOpenSSLType<X509_ALGOR, X509_ALGOR_free>;
-using ScopedX509_SIG = ScopedOpenSSLType<X509_SIG, X509_SIG_free>;
-using ScopedX509_STORE_CTX = ScopedOpenSSLType<X509_STORE_CTX, X509_STORE_CTX_free>;
-
-using ScopedX509Stack = ScopedOpenSSLStack<STACK_OF(X509), X509, X509_free>;
-
-using ScopedCBB = ScopedOpenSSLContext<CBB, void, CBB_zero, CBB_cleanup>;
-using ScopedEVP_AEAD_CTX = ScopedOpenSSLContext<EVP_AEAD_CTX, void,
-                                                EVP_AEAD_CTX_zero,
-                                                EVP_AEAD_CTX_cleanup>;
-using ScopedEVP_CIPHER_CTX = ScopedOpenSSLContext<EVP_CIPHER_CTX, int,
-                                                  EVP_CIPHER_CTX_init,
-                                                  EVP_CIPHER_CTX_cleanup>;
-using ScopedEVP_MD_CTX = ScopedOpenSSLContext<EVP_MD_CTX, int, EVP_MD_CTX_init,
-                                              EVP_MD_CTX_cleanup>;
-using ScopedHMAC_CTX = ScopedOpenSSLContext<HMAC_CTX, void, HMAC_CTX_init,
-                                            HMAC_CTX_cleanup>;
-
-using ScopedOpenSSLBytes = std::unique_ptr<uint8_t, OpenSSLFree<uint8_t>>;
-using ScopedOpenSSLString = std::unique_ptr<char, OpenSSLFree<char>>;
+using ScopedBytes = std::unique_ptr<uint8_t, Free<uint8_t>>;
+using ScopedString = std::unique_ptr<char, Free<char>>;
 
 using ScopedFILE = std::unique_ptr<FILE, FileCloser>;
 
+}  // namespace bssl
+
 #endif  // OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index 650163a..cb28df7 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -27,6 +27,8 @@
 #include "../test/scoped_types.h"
 
 
+namespace bssl {
+
 static const char kCrossSigningRootPEM[] =
 "-----BEGIN CERTIFICATE-----\n"
 "MIICcTCCAdqgAwIBAgIIagJHiPvE0MowDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n"
@@ -457,13 +459,15 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main(int argc, char **argv) {
   CRYPTO_library_init();
 
-  if (!TestVerify() ||
-      !TestPSS() ||
-      !TestBadPSSParameters() ||
-      !TestSignCtx()) {
+  if (!bssl::TestVerify() ||
+      !bssl::TestPSS() ||
+      !bssl::TestBadPSSParameters() ||
+      !bssl::TestSignCtx()) {
     return 1;
   }
 
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 7a3adfb..68df107 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -67,6 +67,8 @@
 #endif
 
 #if defined(__cplusplus)
+#include <memory>
+
 extern "C" {
 #endif
 
@@ -290,6 +292,44 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+namespace bssl {
+
+template<typename T, void (*func)(T*)>
+struct Deleter {
+  void operator()(T *obj) {
+    func(obj);
+  }
+};
+
+template<typename T, void (*func)(T*)>
+using ScopedType = std::unique_ptr<T, Deleter<T, func>>;
+
+template<typename T, typename CleanupRet, void (*init_func)(T*),
+         CleanupRet (*cleanup_func)(T*)>
+class ScopedContext {
+ public:
+  ScopedContext() {
+    init_func(&ctx_);
+  }
+  ~ScopedContext() {
+    cleanup_func(&ctx_);
+  }
+
+  T *get() { return &ctx_; }
+  const T *get() const { return &ctx_; }
+
+  void Reset() {
+    cleanup_func(&ctx_);
+    init_func(&ctx_);
+  }
+
+ private:
+  T ctx_;
+};
+
+}  // namespace bssl
+
 #endif
 
 #endif  /* OPENSSL_HEADER_BASE_H */
diff --git a/include/openssl/mem.h b/include/openssl/mem.h
index 31756f0..d773752 100644
--- a/include/openssl/mem.h
+++ b/include/openssl/mem.h
@@ -133,6 +133,18 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+namespace bssl {
+
+template<typename T>
+struct Free {
+  void operator()(T *buf) {
+    OPENSSL_free(buf);
+  }
+};
+
+}  // namespace bssl
+
 #endif
 
 #endif  /* OPENSSL_HEADER_MEM_H */
diff --git a/include/openssl/stack.h b/include/openssl/stack.h
index 16b9f4f..913db50 100644
--- a/include/openssl/stack.h
+++ b/include/openssl/stack.h
@@ -290,6 +290,22 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+namespace bssl {
+
+template<typename StackType, typename T, void (*func)(T*)>
+struct StackDeleter {
+  void operator()(StackType *obj) {
+    sk_pop_free(reinterpret_cast<_STACK*>(obj),
+                reinterpret_cast<void (*)(void *)>(func));
+  }
+};
+
+template <typename StackType, typename T, void (*func)(T *)>
+using ScopedStack =
+    std::unique_ptr<StackType, StackDeleter<StackType, T, func>>;
+
+}  // namespace bssl
 #endif
 
 #endif  /* OPENSSL_HEADER_STACK_H */
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index be3b8b7..92fad05 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -33,6 +33,190 @@
 #include "../crypto/test/test_util.h"
 
 
+// kOpenSSLSession is a serialized SSL_SESSION generated from openssl
+// s_client -sess_out.
+static const char kOpenSSLSession[] =
+    "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"
+    "i4gv7Y5oliyn";
+
+// kCustomSession is a custom serialized SSL_SESSION generated by
+// filling in missing fields from |kOpenSSLSession|. This includes
+// providing |peer_sha256|, so |peer| is not serialized.
+static const char kCustomSession[] =
+    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
+    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
+    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
+    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
+    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
+    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
+    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
+
+// kBoringSSLSession is a serialized SSL_SESSION generated from bssl client.
+static const char kBoringSSLSession[] =
+    "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"
+    "lQI5kQsO/jgu0R0FmvZNPm8PBx2vLB6PYDni+jZTEznUXiYr2z2oFL0y6xgDKFIE"
+    "ceWrMz3hOLsHNoRinHnqFjD0X8Ar6HFr5PkCAwEAAaOB8DCB7TAfBgNVHSMEGDAW"
+    "gBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHQ4EFgQUwHqYaI2J+6sFZAwRfap9"
+    "ZbjKzE4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMw"
+    "MTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5j"
+    "cmwwTgYDVR0gBEcwRTBDBgRVHSAAMDswOQYIKwYBBQUHAgEWLWh0dHBzOi8vd3d3"
+    "Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeTANBgkqhkiG9w0BAQUF"
+    "AAOBgQB24RJuTksWEoYwBrKBCM/wCMfHcX5m7sLt1Dsf//DwyE7WQziwuTB9GNBV"
+    "g6JqyzYRnOhIZqNtf7gT1Ef+i1pcc/yu2RsyGTirlzQUqpbS66McFAhJtrvlke+D"
+    "NusdVm/K2rxzY5Dkf3s+Iss9B+1fOHSc4wNQTqGvmO5h8oQ/Eg==";
+
+// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing
+// the final (optional) element of |kCustomSession| with tag number 30.
+static const char kBadSessionExtraField[] =
+    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
+    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
+    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
+    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
+    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
+    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
+    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF";
+
+// kBadSessionVersion is a custom serialized SSL_SESSION generated by replacing
+// the version of |kCustomSession| with 2.
+static const char kBadSessionVersion[] =
+    "MIIBdgIBAgICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
+    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
+    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
+    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
+    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
+    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
+    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
+
+// kBadSessionTrailingData is a custom serialized SSL_SESSION with trailing data
+// appended.
+static const char kBadSessionTrailingData[] =
+    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
+    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
+    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
+    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
+    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
+    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
+    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEFAAAA";
+
+namespace bssl {
+
 struct ExpectedCipher {
   unsigned long id;
   int in_group_flag;
@@ -401,188 +585,6 @@
   return true;
 }
 
-// kOpenSSLSession is a serialized SSL_SESSION generated from openssl
-// s_client -sess_out.
-static const char kOpenSSLSession[] =
-    "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"
-    "i4gv7Y5oliyn";
-
-// kCustomSession is a custom serialized SSL_SESSION generated by
-// filling in missing fields from |kOpenSSLSession|. This includes
-// providing |peer_sha256|, so |peer| is not serialized.
-static const char kCustomSession[] =
-    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
-    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
-    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
-    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
-    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
-    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
-    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
-    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
-
-// kBoringSSLSession is a serialized SSL_SESSION generated from bssl client.
-static const char kBoringSSLSession[] =
-    "MIIRwQIBAQICAwMEAsAvBCDdoGxGK26mR+8lM0uq6+k9xYuxPnwAjpcF9n0Yli9R"
-    "kQQwbyshfWhdi5XQ1++7n2L1qqrcVlmHBPpr6yknT/u4pUrpQB5FZ7vqvNn8MdHf"
-    "9rWgoQYCBFXgs7uiBAICHCCjggR6MIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJ"
-    "KoZIhvcNAQELBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
-    "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEy"
-    "MTQ1MzE1WhcNMTUxMTEwMDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
-    "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
-    "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
-    "AQUAA4IBDwAwggEKAoIBAQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpo"
-    "PLuBinvhkXZo3DC133NpCBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU"
-    "792c7hFyNXSUCG7At8Ifi3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mce"
-    "Tv9iGKqSkSTlp8puy/9SZ/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/"
-    "RCh8/UKc8PaL+cxlt531qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eL"
-    "EucWQ72YZU8mUzXBoXGn0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAd"
-    "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
-    "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
-    "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
-    "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjG"
-    "GjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
-    "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
-    "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAb"
-    "qdWPZEHk0X7iKPCTHL6S3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovE"
-    "kQZSHwT+pyOPWQhsSjO+1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXd"
-    "X+s0WdbOpn6MStKAiBVloPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+"
-    "n0OTucD9sHV7EVj9XUxi51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779a"
-    "f07vR03r349Iz/KTzk95rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1y"
-    "TTlM80jBMOwyjZXmjRAhpAIEAKUDAgEUqQUCAwGJwKqBpwSBpOgebbmn9NRUtMWH"
-    "+eJpqA5JLMFSMCChOsvKey3toBaCNGU7HfAEiiXNuuAdCBoK262BjQc2YYfqFzqH"
-    "zuppopXCvhohx7j/tnCNZIMgLYt/O9SXK2RYI5z8FhCCHvB4CbD5G0LGl5EFP27s"
-    "Jb6S3aTTYPkQe8yZSlxevg6NDwmTogLO9F7UUkaYmVcMQhzssEE2ZRYNwSOU6KjE"
-    "0Yj+8fAiBtbQriIEIN2L8ZlpaVrdN5KFNdvcmOxJu81P8q53X55xQyGTnGWwsgMC"
-    "ARezggvvMIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJKoZIhvcNAQELBQAwSTEL"
-    "MAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2ds"
-    "ZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEyMTQ1MzE1WhcNMTUxMTEw"
-    "MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG"
-    "A1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UE"
-    "AwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB"
-    "AQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpoPLuBinvhkXZo3DC133Np"
-    "CBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU792c7hFyNXSUCG7At8If"
-    "i3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mceTv9iGKqSkSTlp8puy/9S"
-    "Z/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/RCh8/UKc8PaL+cxlt531"
-    "qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eLEucWQ72YZU8mUzXBoXGn"
-    "0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEF"
-    "BQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYB"
-    "BQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB"
-    "RzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9v"
-    "Y3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjGGjAMBgNVHRMBAf8EAjAA"
-    "MB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYK"
-    "KwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5j"
-    "b20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAbqdWPZEHk0X7iKPCTHL6S"
-    "3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovEkQZSHwT+pyOPWQhsSjO+"
-    "1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXdX+s0WdbOpn6MStKAiBVl"
-    "oPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+n0OTucD9sHV7EVj9XUxi"
-    "51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779af07vR03r349Iz/KTzk95"
-    "rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1yTTlM80jBMOwyjZXmjRAh"
-    "MIID8DCCAtigAwIBAgIDAjqDMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT"
-    "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i"
-    "YWwgQ0EwHhcNMTMwNDA1MTUxNTU2WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG"
-    "EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy"
-    "bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB"
-    "AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP"
-    "VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv"
-    "h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE"
-    "ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ"
-    "EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC"
-    "DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7"
-    "qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wDgYD"
-    "VR0PAQH/BAQDAgEGMC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDov"
-    "L2cuc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYBAf8CAQAwNQYDVR0fBC4wLDAqoCig"
-    "JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMBcGA1UdIAQQ"
-    "MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQsFAAOCAQEAqvqpIM1qZ4PtXtR+"
-    "3h3Ef+AlBgDFJPupyC1tft6dgmUsgWM0Zj7pUsIItMsv91+ZOmqcUHqFBYx90SpI"
-    "hNMJbHzCzTWf84LuUt5oX+QAihcglvcpjZpNy6jehsgNb1aHA30DP9z6eX0hGfnI"
-    "Oi9RdozHQZJxjyXON/hKTAAj78Q1EK7gI4BzfE00LshukNYQHpmEcxpw8u1VDu4X"
-    "Bupn7jLrLN1nBz/2i8Jw3lsA5rsb0zYaImxssDVCbJAJPZPpZAkiDoUGn8JzIdPm"
-    "X4DkjYUiOnMDsWCOrmji9D6X52ASCWg23jrW4kOVWzeBkoEfu43XrVJkFleW2V40"
-    "fsg12DCCA30wggLmoAMCAQICAxK75jANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQG"
-    "EwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUg"
-    "Q2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTAyMDUyMTA0MDAwMFoXDTE4MDgyMTA0"
-    "MDAwMFowQjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xGzAZ"
-    "BgNVBAMTEkdlb1RydXN0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP"
-    "ADCCAQoCggEBANrMGGMw/fQXIxpWflvfPGw45HG3eJHUvKHYTPioQ7YD6U0hBwiI"
-    "2lgvZjkpvQV4i5046AW3an5xpObEYKaw74DkiSgPniXW7YPzraaRx5jJQhg1FJ2t"
-    "mEaSLk/K8YdDwRaVVy1Q74ktgHpXrfLuX2vSAI25FPgUFTXZwEaje3LIkb/JVSvN"
-    "0Jc+nCZkzN/Ogxlxyk7m1NV7qRnNVd7I7NJeOFPlXE+MLf5QIzb8ZubLjqQ5GQC3"
-    "lQI5kQsO/jgu0R0FmvZNPm8PBx2vLB6PYDni+jZTEznUXiYr2z2oFL0y6xgDKFIE"
-    "ceWrMz3hOLsHNoRinHnqFjD0X8Ar6HFr5PkCAwEAAaOB8DCB7TAfBgNVHSMEGDAW"
-    "gBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHQ4EFgQUwHqYaI2J+6sFZAwRfap9"
-    "ZbjKzE4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMw"
-    "MTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5j"
-    "cmwwTgYDVR0gBEcwRTBDBgRVHSAAMDswOQYIKwYBBQUHAgEWLWh0dHBzOi8vd3d3"
-    "Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeTANBgkqhkiG9w0BAQUF"
-    "AAOBgQB24RJuTksWEoYwBrKBCM/wCMfHcX5m7sLt1Dsf//DwyE7WQziwuTB9GNBV"
-    "g6JqyzYRnOhIZqNtf7gT1Ef+i1pcc/yu2RsyGTirlzQUqpbS66McFAhJtrvlke+D"
-    "NusdVm/K2rxzY5Dkf3s+Iss9B+1fOHSc4wNQTqGvmO5h8oQ/Eg==";
-
-// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing
-// the final (optional) element of |kCustomSession| with tag number 30.
-static const char kBadSessionExtraField[] =
-    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
-    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
-    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
-    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
-    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
-    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
-    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
-    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF";
-
-// kBadSessionVersion is a custom serialized SSL_SESSION generated by replacing
-// the version of |kCustomSession| with 2.
-static const char kBadSessionVersion[] =
-    "MIIBdgIBAgICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
-    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
-    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
-    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
-    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
-    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
-    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
-    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
-
-// kBadSessionTrailingData is a custom serialized SSL_SESSION with trailing data
-// appended.
-static const char kBadSessionTrailingData[] =
-    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
-    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
-    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
-    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
-    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
-    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
-    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
-    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEFAAAA";
-
 static bool DecodeBase64(std::vector<uint8_t> *out, const char *in) {
   size_t len;
   if (!EVP_DecodedLength(&len, strlen(in))) {
@@ -619,7 +621,7 @@
 
   // Verify the SSL_SESSION encoding round-trips.
   size_t encoded_len;
-  ScopedOpenSSLBytes encoded;
+  ScopedBytes encoded;
   uint8_t *encoded_raw;
   if (!SSL_SESSION_to_bytes(session.get(), &encoded_raw, &encoded_len)) {
     fprintf(stderr, "SSL_SESSION_to_bytes failed\n");
@@ -708,7 +710,7 @@
   if (cipher == NULL) {
     return false;
   }
-  ScopedOpenSSLString rfc_name(SSL_CIPHER_get_rfc_name(cipher));
+  ScopedString rfc_name(SSL_CIPHER_get_rfc_name(cipher));
   if (!rfc_name) {
     return false;
   }
@@ -1353,33 +1355,39 @@
   return true;
 }
 
+}  // namespace bssl
+
 int main() {
   CRYPTO_library_init();
 
-  if (!TestCipherRules() ||
-      !TestSSL_SESSIONEncoding(kOpenSSLSession) ||
-      !TestSSL_SESSIONEncoding(kCustomSession) ||
-      !TestSSL_SESSIONEncoding(kBoringSSLSession) ||
-      !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
-      !TestBadSSL_SESSIONEncoding(kBadSessionVersion) ||
-      !TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) ||
+  if (!bssl::TestCipherRules() ||
+      !bssl::TestSSL_SESSIONEncoding(kOpenSSLSession) ||
+      !bssl::TestSSL_SESSIONEncoding(kCustomSession) ||
+      !bssl::TestSSL_SESSIONEncoding(kBoringSSLSession) ||
+      !bssl::TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
+      !bssl::TestBadSSL_SESSIONEncoding(kBadSessionVersion) ||
+      !bssl::TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) ||
       // TODO(svaldez): Update this when TLS 1.3 is enabled by default.
-      !TestDefaultVersion(SSL3_VERSION, TLS1_2_VERSION, &TLS_method) ||
-      !TestDefaultVersion(SSL3_VERSION, SSL3_VERSION, &SSLv3_method) ||
-      !TestDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method) ||
-      !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &TLSv1_1_method) ||
-      !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &TLSv1_2_method) ||
-      !TestDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method) ||
-      !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &DTLSv1_method) ||
-      !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method) ||
-      !TestCipherGetRFCName() ||
-      !TestPaddingExtension() ||
-      !TestClientCAList() ||
-      !TestInternalSessionCache() ||
-      !TestSequenceNumber(false /* TLS */) ||
-      !TestSequenceNumber(true /* DTLS */) ||
-      !TestOneSidedShutdown() ||
-      !TestSetFD()) {
+      !bssl::TestDefaultVersion(SSL3_VERSION, TLS1_2_VERSION, &TLS_method) ||
+      !bssl::TestDefaultVersion(SSL3_VERSION, SSL3_VERSION, &SSLv3_method) ||
+      !bssl::TestDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method) ||
+      !bssl::TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION,
+                                &TLSv1_1_method) ||
+      !bssl::TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION,
+                                &TLSv1_2_method) ||
+      !bssl::TestDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method) ||
+      !bssl::TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION,
+                                &DTLSv1_method) ||
+      !bssl::TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION,
+                                &DTLSv1_2_method) ||
+      !bssl::TestCipherGetRFCName() ||
+      !bssl::TestPaddingExtension() ||
+      !bssl::TestClientCAList() ||
+      !bssl::TestInternalSessionCache() ||
+      !bssl::TestSequenceNumber(false /* TLS */) ||
+      !bssl::TestSequenceNumber(true /* DTLS */) ||
+      !bssl::TestOneSidedShutdown() ||
+      !bssl::TestSetFD()) {
     ERR_print_errors_fp(stderr);
     return 1;
   }
diff --git a/ssl/test/async_bio.cc b/ssl/test/async_bio.cc
index 7a5737b..b758219 100644
--- a/ssl/test/async_bio.cc
+++ b/ssl/test/async_bio.cc
@@ -20,6 +20,8 @@
 #include <openssl/mem.h>
 
 
+namespace bssl {
+
 namespace {
 
 extern const BIO_METHOD g_async_bio_method;
@@ -186,3 +188,5 @@
   }
   a->enforce_write_quota = enforce;
 }
+
+}  // namespace bssl
diff --git a/ssl/test/async_bio.h b/ssl/test/async_bio.h
index fbc4016..1799347 100644
--- a/ssl/test/async_bio.h
+++ b/ssl/test/async_bio.h
@@ -20,6 +20,8 @@
 #include "../../crypto/test/scoped_types.h"
 
 
+namespace bssl {
+
 // AsyncBioCreate creates a filter BIO for testing asynchronous state
 // machines which consume a stream socket. Reads and writes will fail
 // and return EAGAIN unless explicitly allowed. Each async BIO has a
@@ -41,5 +43,7 @@
 // AsyncBioEnforceWriteQuota configures where |bio| enforces its write quota.
 void AsyncBioEnforceWriteQuota(BIO *bio, bool enforce);
 
+}  // namespace bssl
+
 
 #endif  // HEADER_ASYNC_BIO
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 54157ee..9ce8b5f 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -62,6 +62,8 @@
 #include "test_config.h"
 
 
+namespace bssl {
+
 #if !defined(OPENSSL_WINDOWS)
 static int closesocket(int sock) {
   return close(sock);
@@ -284,7 +286,7 @@
 };
 
 template<typename T>
-struct Free {
+struct SystemFree {
   void operator()(T *buf) {
     free(buf);
   }
@@ -295,7 +297,7 @@
   const TestConfig *config = GetTestConfig(ssl);
 
   if (!config->digest_prefs.empty()) {
-    std::unique_ptr<char, Free<char>> digest_prefs(
+    std::unique_ptr<char, SystemFree<char>> digest_prefs(
         strdup(config->digest_prefs.c_str()));
     std::vector<int> digest_list;
 
@@ -1555,7 +1557,7 @@
   ~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); }
 };
 
-int main(int argc, char **argv) {
+static int Main(int argc, char **argv) {
   // To distinguish ASan's output from ours, add a trailing message to stderr.
   // Anything following this line will be considered an error.
   StderrDelimiter delimiter;
@@ -1611,3 +1613,9 @@
 
   return 0;
 }
+
+}  // namespace bssl
+
+int main(int argc, char **argv) {
+  return bssl::Main(argc, argv);
+}
diff --git a/ssl/test/packeted_bio.cc b/ssl/test/packeted_bio.cc
index b0982b0..131cd92 100644
--- a/ssl/test/packeted_bio.cc
+++ b/ssl/test/packeted_bio.cc
@@ -22,6 +22,8 @@
 #include <openssl/mem.h>
 
 
+namespace bssl {
+
 namespace {
 
 extern const BIO_METHOD g_packeted_bio_method;
@@ -302,3 +304,5 @@
   memset(&data->timeout, 0, sizeof(data->timeout));
   return true;
 }
+
+}  // namespace bssl
diff --git a/ssl/test/packeted_bio.h b/ssl/test/packeted_bio.h
index 9bab635..e6dcfe4 100644
--- a/ssl/test/packeted_bio.h
+++ b/ssl/test/packeted_bio.h
@@ -29,6 +29,8 @@
 #endif
 
 
+namespace bssl {
+
 // PacketedBioCreate creates a filter BIO which implements a reliable in-order
 // blocking datagram socket. It internally maintains a clock and honors
 // |BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT| based on it.
@@ -47,5 +49,7 @@
 // there is a pending timeout. Otherwise, it returns false.
 bool PacketedBioAdvanceClock(BIO *bio);
 
+}  // namespace bssl
+
 
 #endif  // HEADER_PACKETED_BIO
diff --git a/ssl/test/scoped_types.h b/ssl/test/scoped_types.h
index 7e92cee..0b3b562 100644
--- a/ssl/test/scoped_types.h
+++ b/ssl/test/scoped_types.h
@@ -20,9 +20,13 @@
 #include "../../crypto/test/scoped_types.h"
 
 
-using ScopedSSL = ScopedOpenSSLType<SSL, SSL_free>;
-using ScopedSSL_CTX = ScopedOpenSSLType<SSL_CTX, SSL_CTX_free>;
-using ScopedSSL_SESSION = ScopedOpenSSLType<SSL_SESSION, SSL_SESSION_free>;
+namespace bssl {
+
+using ScopedSSL = ScopedType<SSL, SSL_free>;
+using ScopedSSL_CTX = ScopedType<SSL_CTX, SSL_CTX_free>;
+using ScopedSSL_SESSION = ScopedType<SSL_SESSION, SSL_SESSION_free>;
+
+}  // namespace bssl
 
 
 #endif  // OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 32b91e9..3fe25be 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -22,6 +22,8 @@
 
 #include <openssl/base64.h>
 
+namespace bssl {
+
 namespace {
 
 template <typename T>
@@ -213,3 +215,5 @@
 
   return true;
 }
+
+}  // namespace bssl
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index a3e9ad1..bf2e815 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -18,6 +18,8 @@
 #include <string>
 
 
+namespace bssl {
+
 struct TestConfig {
   int port = 0;
   bool is_server = false;
@@ -111,5 +113,7 @@
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config);
 
+}  // namespace bssl
+
 
 #endif  // HEADER_TEST_CONFIG
diff --git a/tool/args.cc b/tool/args.cc
index 9ec18a3..952584d 100644
--- a/tool/args.cc
+++ b/tool/args.cc
@@ -23,6 +23,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 bool ParseKeyValueArguments(std::map<std::string, std::string> *out_args,
                             const std::vector<std::string> &args,
                             const struct argument *templates) {
@@ -102,3 +104,5 @@
   *out = num;
   return true;
 }
+
+}  // namespace bssl
diff --git a/tool/ciphers.cc b/tool/ciphers.cc
index d7cc36b..fa060ab 100644
--- a/tool/ciphers.cc
+++ b/tool/ciphers.cc
@@ -25,6 +25,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 bool Ciphers(const std::vector<std::string> &args) {
   if (args.size() != 1) {
     fprintf(stderr, "Usage: bssl ciphers <cipher suite string>\n");
@@ -64,3 +66,5 @@
 
   return true;
 }
+
+}  // namespace bssl
diff --git a/tool/client.cc b/tool/client.cc
index 7310ebf..593e3c6 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -26,6 +26,8 @@
 #include "transport_common.h"
 
 
+namespace bssl {
+
 static const struct argument kArguments[] = {
     {
      "-connect", kRequiredArgument,
@@ -326,3 +328,5 @@
 
   return ok;
 }
+
+}  // namespace bssl
diff --git a/tool/const.cc b/tool/const.cc
index 7b7001e..553e2d9 100644
--- a/tool/const.cc
+++ b/tool/const.cc
@@ -18,6 +18,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 const uint8_t kDERRSAPrivate2048[] = {
     0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
     0xd0, 0x02, 0xde, 0x5d, 0x19, 0x33, 0x48, 0x15, 0xc7, 0x86, 0xde, 0xa3,
@@ -432,3 +434,5 @@
 };
 
 const size_t kDERRSAPrivate3Prime2048Len = sizeof(kDERRSAPrivate3Prime2048);
+
+}  // namespace bssl
diff --git a/tool/digest.cc b/tool/digest.cc
index 2e3e608..e6a97bb 100644
--- a/tool/digest.cc
+++ b/tool/digest.cc
@@ -44,6 +44,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 struct close_delete {
   void operator()(int *fd) {
     BORINGSSL_CLOSE(*fd);
@@ -476,3 +478,5 @@
 bool SHA512Sum(const std::vector<std::string> &args) {
   return DigestSum(EVP_sha512(), args);
 }
+
+}  // namespace bssl
diff --git a/tool/generate_ed25519.cc b/tool/generate_ed25519.cc
index 15d3692..9672b78 100644
--- a/tool/generate_ed25519.cc
+++ b/tool/generate_ed25519.cc
@@ -22,6 +22,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static const struct argument kArguments[] = {
     {
         "-out-public", kRequiredArgument, "The file to write the public key to",
@@ -65,3 +67,5 @@
          WriteToFile(args_map["-out-private"], private_key,
                      sizeof(private_key));
 }
+
+}  // namespace bssl
diff --git a/tool/genrsa.cc b/tool/genrsa.cc
index 4b39401..576bd7c 100644
--- a/tool/genrsa.cc
+++ b/tool/genrsa.cc
@@ -22,6 +22,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static const struct argument kArguments[] = {
     {
      "-nprimes", kOptionalArgument,
@@ -67,3 +69,5 @@
 
   return true;
 }
+
+}  // namespace bssl
diff --git a/tool/internal.h b/tool/internal.h
index fd66e00..769bcab 100644
--- a/tool/internal.h
+++ b/tool/internal.h
@@ -44,6 +44,8 @@
   #define BORINGSSL_WRITE write
 #endif
 
+namespace bssl {
+
 enum ArgumentType {
   kRequiredArgument,
   kOptionalArgument,
@@ -88,5 +90,7 @@
 extern const uint8_t kDERRSAPrivate3Prime2048[];
 extern const size_t kDERRSAPrivate3Prime2048Len;
 
+}  // namespace bssl
+
 
 #endif /* !OPENSSL_HEADER_TOOL_INTERNAL_H */
diff --git a/tool/pkcs12.cc b/tool/pkcs12.cc
index 15e32d3..2423f19 100644
--- a/tool/pkcs12.cc
+++ b/tool/pkcs12.cc
@@ -39,6 +39,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 #if defined(OPENSSL_WINDOWS)
 typedef int read_result_t;
 #else
@@ -140,3 +142,5 @@
 
   return true;
 }
+
+}  // namespace bssl
diff --git a/tool/rand.cc b/tool/rand.cc
index 3701748..a76dc84 100644
--- a/tool/rand.cc
+++ b/tool/rand.cc
@@ -23,6 +23,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 static const struct argument kArguments[] = {
     {
      "-hex", kBooleanArgument,
@@ -93,3 +95,5 @@
 
   return true;
 }
+
+}  // namespace bssl
diff --git a/tool/server.cc b/tool/server.cc
index 14f37a4..04bb7ef 100644
--- a/tool/server.cc
+++ b/tool/server.cc
@@ -21,6 +21,8 @@
 #include "transport_common.h"
 
 
+namespace bssl {
+
 static const struct argument kArguments[] = {
     {
      "-accept", kRequiredArgument,
@@ -150,3 +152,5 @@
   SSL_CTX_free(ctx);
   return ok;
 }
+
+}  // namespace bssl
diff --git a/tool/speed.cc b/tool/speed.cc
index a8eb8bf..8efd1f4 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -41,6 +41,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 // TimeResults represents the results of benchmarking a function.
 struct TimeResults {
   // num_calls is the number of function calls done in the time period.
@@ -630,3 +632,5 @@
 
   return true;
 }
+
+}  // namespace bssl
diff --git a/tool/tool.cc b/tool/tool.cc
index 34851b4..8519108 100644
--- a/tool/tool.cc
+++ b/tool/tool.cc
@@ -29,6 +29,8 @@
 #include "internal.h"
 
 
+namespace bssl {
+
 typedef bool (*tool_func_t)(const std::vector<std::string> &args);
 
 struct Tool {
@@ -79,7 +81,8 @@
   }
 }
 
-int main(int argc, char **argv) {
+
+static int Main(int argc, char **argv) {
 #if defined(OPENSSL_WINDOWS)
   // Read and write in binary mode. This makes bssl on Windows consistent with
   // bssl on other platforms, and also makes it consistent with MSYS's commands
@@ -124,3 +127,9 @@
 
   return !tool(args);
 }
+
+}  // namespace bssl
+
+int main(int argc, char **argv) {
+  return bssl::Main(argc, argv);
+}
diff --git a/tool/transport_common.cc b/tool/transport_common.cc
index 01bba00..7ccda21 100644
--- a/tool/transport_common.cc
+++ b/tool/transport_common.cc
@@ -51,6 +51,8 @@
 #include "transport_common.h"
 
 
+namespace bssl {
+
 #if !defined(OPENSSL_WINDOWS)
 static int closesocket(int sock) {
   return close(sock);
@@ -537,3 +539,5 @@
 
   return true;
 }
+
+}  // namespace bssl
diff --git a/tool/transport_common.h b/tool/transport_common.h
index a57a916..8618129 100644
--- a/tool/transport_common.h
+++ b/tool/transport_common.h
@@ -18,6 +18,9 @@
 #include <openssl/ssl.h>
 #include <string.h>
 
+
+namespace bssl {
+
 // InitSocketLibrary calls the Windows socket init functions, if needed.
 bool InitSocketLibrary();
 
@@ -43,4 +46,7 @@
 // returns true on success and false otherwise.
 bool DoSMTPStartTLS(int sock);
 
+}  // namespace bssl
+
+
 #endif  /* !OPENSSL_HEADER_TOOL_TRANSPORT_COMMON_H */
diff --git a/util/doc.go b/util/doc.go
index 681b834..c03f742 100644
--- a/util/doc.go
+++ b/util/doc.go
@@ -72,6 +72,7 @@
 
 const (
 	cppGuard     = "#if defined(__cplusplus)"
+	endif        = "#endif"
 	commentStart = "/* "
 	commentEnd   = " */"
 )
@@ -292,8 +293,14 @@
 	if len(lines) == 0 || lines[0] != "extern \"C\" {" {
 		return nil, errors.New("no extern \"C\" found after C++ guard")
 	}
-	lineNo += 2
-	lines = lines[2:]
+
+	for i, line := range lines {
+		if line == endif {
+			lines = lines[i+1:]
+			lineNo += i + 1
+			break
+		}
+	}
 
 	header := &HeaderFile{
 		Name:     filepath.Base(path),