diff --git a/build.json b/build.json
index f88ee2b..b64bc2d 100644
--- a/build.json
+++ b/build.json
@@ -105,63 +105,175 @@
             "third_party/fiat/asm/fiat_p256_adx_sqr.S"
         ],
         "perlasm_aarch64": [
-            {"src": "crypto/fipsmodule/aes/asm/aesv8-armx.pl", "dst": "aesv8-armv8"},
-            {"src": "crypto/fipsmodule/aes/asm/aesv8-gcm-armv8.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/armv8-mont.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/bn-armv8.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghash-neon-armv8.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghashv8-armx.pl", "dst": "ghashv8-armv8"},
-            {"src": "crypto/fipsmodule/ec/asm/p256_beeu-armv8-asm.pl"},
-            {"src": "crypto/fipsmodule/ec/asm/p256-armv8-asm.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha1-armv8.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha512-armv8.pl", "args": ["sha256"], "dst": "sha256-armv8"},
-            {"src": "crypto/fipsmodule/sha/asm/sha512-armv8.pl", "args": ["sha512"]},
-            {"src": "crypto/fipsmodule/aes/asm/vpaes-armv8.pl"}
+            {
+                "src": "crypto/fipsmodule/aes/asm/aesv8-armx.pl",
+                "dst": "aesv8-armv8"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/aesv8-gcm-armv8.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/armv8-mont.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/bn-armv8.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghash-neon-armv8.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghashv8-armx.pl",
+                "dst": "ghashv8-armv8"
+            },
+            {
+                "src": "crypto/fipsmodule/ec/asm/p256_beeu-armv8-asm.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/ec/asm/p256-armv8-asm.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha1-armv8.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha512-armv8.pl",
+                "args": [
+                    "sha256"
+                ],
+                "dst": "sha256-armv8"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha512-armv8.pl",
+                "args": [
+                    "sha512"
+                ]
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/vpaes-armv8.pl"
+            }
         ],
         "perlasm_arm": [
-            {"src": "crypto/fipsmodule/aes/asm/aesv8-armx.pl", "dst": "aesv8-armv7"},
-            {"src": "crypto/fipsmodule/bn/asm/armv4-mont.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/bsaes-armv7.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghash-armv4.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghashv8-armx.pl", "dst": "ghashv8-armv7"},
-            {"src": "crypto/fipsmodule/sha/asm/sha1-armv4-large.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha256-armv4.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha512-armv4.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/vpaes-armv7.pl"}
+            {
+                "src": "crypto/fipsmodule/aes/asm/aesv8-armx.pl",
+                "dst": "aesv8-armv7"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/armv4-mont.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/bsaes-armv7.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghash-armv4.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghashv8-armx.pl",
+                "dst": "ghashv8-armv7"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha1-armv4-large.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha256-armv4.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha512-armv4.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/vpaes-armv7.pl"
+            }
         ],
         "perlasm_x86": [
-            {"src": "crypto/fipsmodule/aes/asm/aesni-x86.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/bn-586.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/co-586.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghash-ssse3-x86.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghash-x86.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha1-586.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha256-586.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha512-586.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/vpaes-x86.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/x86-mont.pl"}
+            {
+                "src": "crypto/fipsmodule/aes/asm/aesni-x86.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/bn-586.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/co-586.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghash-ssse3-x86.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghash-x86.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha1-586.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha256-586.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha512-586.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/vpaes-x86.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/x86-mont.pl"
+            }
         ],
         "perlasm_x86_64": [
-            {"src": "crypto/fipsmodule/aes/asm/aesni-gcm-x86_64.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/aes-gcm-avx512-x86_64.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/aesni-x86_64.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghash-ssse3-x86_64.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/ghash-x86_64.pl"},
-            {"src": "crypto/fipsmodule/ec/asm/p256_beeu-x86_64-asm.pl"},
-            {"src": "crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl"},
-            {"src": "crypto/fipsmodule/rand/asm/rdrand-x86_64.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/rsaz-avx2.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha1-x86_64.pl"},
-            {"src": "crypto/fipsmodule/sha/asm/sha512-x86_64.pl", "args": ["sha256"], "dst": "sha256-x86_64"},
-            {"src": "crypto/fipsmodule/sha/asm/sha512-x86_64.pl", "args": ["sha512"]},
-            {"src": "crypto/fipsmodule/aes/asm/vpaes-x86_64.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/x86_64-mont.pl"},
-            {"src": "crypto/fipsmodule/bn/asm/x86_64-mont5.pl"}
+            {
+                "src": "crypto/fipsmodule/aes/asm/aesni-gcm-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/aes-gcm-avx512-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/aesni-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghash-ssse3-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/ghash-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/ec/asm/p256_beeu-x86_64-asm.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/rand/asm/rdrand-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/rsaz-avx2.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha1-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha512-x86_64.pl",
+                "args": [
+                    "sha256"
+                ],
+                "dst": "sha256-x86_64"
+            },
+            {
+                "src": "crypto/fipsmodule/sha/asm/sha512-x86_64.pl",
+                "args": [
+                    "sha512"
+                ]
+            },
+            {
+                "src": "crypto/fipsmodule/aes/asm/vpaes-x86_64.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/x86_64-mont.pl"
+            },
+            {
+                "src": "crypto/fipsmodule/bn/asm/x86_64-mont5.pl"
+            }
         ]
     },
     "crypto": {
-      "srcs": [
+        "srcs": [
             "crypto/aes/aes.cc",
             "crypto/asn1/a_bitstr.cc",
             "crypto/asn1/a_bool.cc",
@@ -588,21 +700,39 @@
             "third_party/fiat/asm/fiat_curve25519_adx_square.S"
         ],
         "perlasm_aarch64": [
-            {"src": "crypto/chacha/asm/chacha-armv8.pl"},
-            {"src": "crypto/cipher/asm/chacha20_poly1305_armv8.pl"}
+            {
+                "src": "crypto/chacha/asm/chacha-armv8.pl"
+            },
+            {
+                "src": "crypto/cipher/asm/chacha20_poly1305_armv8.pl"
+            }
         ],
         "perlasm_arm": [
-            {"src": "crypto/chacha/asm/chacha-armv4.pl"}
+            {
+                "src": "crypto/chacha/asm/chacha-armv4.pl"
+            }
         ],
         "perlasm_x86": [
-            {"src": "crypto/chacha/asm/chacha-x86.pl"},
-            {"src": "crypto/md5/asm/md5-586.pl"}
+            {
+                "src": "crypto/chacha/asm/chacha-x86.pl"
+            },
+            {
+                "src": "crypto/md5/asm/md5-586.pl"
+            }
         ],
         "perlasm_x86_64": [
-            {"src": "crypto/chacha/asm/chacha-x86_64.pl"},
-            {"src": "crypto/cipher/asm/aes128gcmsiv-x86_64.pl"},
-            {"src": "crypto/cipher/asm/chacha20_poly1305_x86_64.pl"},
-            {"src": "crypto/md5/asm/md5-x86_64.pl"}
+            {
+                "src": "crypto/chacha/asm/chacha-x86_64.pl"
+            },
+            {
+                "src": "crypto/cipher/asm/aes128gcmsiv-x86_64.pl"
+            },
+            {
+                "src": "crypto/cipher/asm/chacha20_poly1305_x86_64.pl"
+            },
+            {
+                "src": "crypto/md5/asm/md5-x86_64.pl"
+            }
         ]
     },
     "pki": {
@@ -742,6 +872,7 @@
             "include/openssl/dtls1.h",
             "include/openssl/srtp.h",
             "include/openssl/ssl.h",
+            "include/openssl/ssl_deprecated.h",
             "include/openssl/ssl3.h",
             "include/openssl/tls1.h"
         ],
@@ -808,16 +939,24 @@
             "ssl/test/test_state.h"
         ],
         "perlasm_aarch64": [
-            {"src": "crypto/test/asm/trampoline-armv8.pl"}
+            {
+                "src": "crypto/test/asm/trampoline-armv8.pl"
+            }
         ],
         "perlasm_arm": [
-            {"src": "crypto/test/asm/trampoline-armv4.pl"}
+            {
+                "src": "crypto/test/asm/trampoline-armv4.pl"
+            }
         ],
         "perlasm_x86": [
-            {"src": "crypto/test/asm/trampoline-x86.pl"}
+            {
+                "src": "crypto/test/asm/trampoline-x86.pl"
+            }
         ],
         "perlasm_x86_64": [
-            {"src": "crypto/test/asm/trampoline-x86_64.pl"}
+            {
+                "src": "crypto/test/asm/trampoline-x86_64.pl"
+            }
         ]
     },
     "crypto_test": {
@@ -1159,4 +1298,4 @@
             "util/fipstools/acvp/modulewrapper/modulewrapper.h"
         ]
     }
-}
+}
\ No newline at end of file
diff --git a/crypto/evp/evp_kem.cc b/crypto/evp/evp_kem.cc
index e07ea3e..e718caf 100644
--- a/crypto/evp/evp_kem.cc
+++ b/crypto/evp/evp_kem.cc
@@ -36,7 +36,8 @@
     OPENSSL_PUT_ERROR(EVP, ERR_R_PASSED_NULL_PARAMETER);
     return false;
   }
-  if (kem->pkey_id != EVP_PKEY_id(pkey_impl)) {
+  if (kem->pkey_id != EVP_PKEY_id(pkey_impl) ||
+      (kem->check_key != nullptr && !kem->check_key(kem, pkey_impl))) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
     return false;
   }
@@ -68,7 +69,7 @@
   if (!check_kem_invocation(kem, &ciphertext_len, secret_len, pkey_impl)) {
     return 0;
   }
-  return kem->encap(Span(out_ciphertext, ciphertext_len),
+  return kem->encap(kem, Span(out_ciphertext, ciphertext_len),
                     Span(out_secret, secret_len), pkey_impl);
 }
 
@@ -84,7 +85,7 @@
     OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_ENTROPY_LENGTH);
     return 0;
   }
-  return kem->encap_external_entropy(Span(out_ciphertext, ciphertext_len),
+  return kem->encap_external_entropy(kem, Span(out_ciphertext, ciphertext_len),
                                      Span(out_secret, secret_len), pkey_impl,
                                      Span(entropy, entropy_len));
 }
@@ -96,6 +97,6 @@
   if (!check_kem_invocation(kem, nullptr, secret_len, pkey_impl)) {
     return 0;
   }
-  return kem->decap(Span(out_secret, secret_len),
+  return kem->decap(kem, Span(out_secret, secret_len),
                     Span(ciphertext, ciphertext_len), pkey_impl);
 }
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
index 2c83190..d4e57dc 100644
--- a/crypto/evp/internal.h
+++ b/crypto/evp/internal.h
@@ -317,13 +317,18 @@
   // Fixed length of external entropy for testing.
   size_t entropy_len;
 
-  int (*encap)(bssl::Span<uint8_t> out_ciphertext,
+  // check_key, if non-null, returns whether `key`, whose type matches
+  // `pkey_id`, is usable with this KEM.
+  bool (*check_key)(const EVP_KEM *kem, const EVP_PKEY *key);
+
+  int (*encap)(const EVP_KEM *kem, bssl::Span<uint8_t> out_ciphertext,
                bssl::Span<uint8_t> out_secret, const EVP_PKEY *peer_key);
-  int (*encap_external_entropy)(bssl::Span<uint8_t> out_ciphertext,
+  int (*encap_external_entropy)(const EVP_KEM *kem,
+                                bssl::Span<uint8_t> out_ciphertext,
                                 bssl::Span<uint8_t> out_secret,
                                 const EVP_PKEY *peer_key,
                                 bssl::Span<const uint8_t> entropy);
-  int (*decap)(bssl::Span<uint8_t> out_secret,
+  int (*decap)(const EVP_KEM *kem, bssl::Span<uint8_t> out_secret,
                bssl::Span<const uint8_t> ciphertext, const EVP_PKEY *key);
 } /* EVP_KEM */;
 
@@ -353,7 +358,7 @@
       OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
       return 0;
     }
-    if (KEM.encap(Span(out_ciphertext, KEM.ciphertext_len),
+    if (KEM.encap(&KEM, Span(out_ciphertext, KEM.ciphertext_len),
                   Span(out_secret, KEM.secret_len), ctx->pkey.get())) {
       *out_ciphertext_len = KEM.ciphertext_len;
       *out_secret_len = KEM.secret_len;
@@ -373,7 +378,7 @@
       OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
       return 0;
     }
-    if (KEM.decap(Span(out_secret, KEM.secret_len),
+    if (KEM.decap(&KEM, Span(out_secret, KEM.secret_len),
                   Span(ciphertext, ciphertext_len), ctx->pkey.get())) {
       *out_secret_len = KEM.secret_len;
       return 1;
diff --git a/crypto/evp/p_dh.cc b/crypto/evp/p_dh.cc
index c3d8f7f..7fcd9f1 100644
--- a/crypto/evp/p_dh.cc
+++ b/crypto/evp/p_dh.cc
@@ -34,25 +34,25 @@
 
 extern const EVP_PKEY_CTX_METHOD dh_pkey_meth;
 
-static void dh_free(EvpPkey *pkey) {
+void dh_free(EvpPkey *pkey) {
   DH_free(reinterpret_cast<DH *>(pkey->pkey));
   pkey->pkey = nullptr;
 }
 
-static int dh_size(const EvpPkey *pkey) {
+int dh_size(const EvpPkey *pkey) {
   return DH_size(reinterpret_cast<const DH *>(pkey->pkey));
 }
 
-static int dh_bits(const EvpPkey *pkey) {
+int dh_bits(const EvpPkey *pkey) {
   return DH_bits(reinterpret_cast<const DH *>(pkey->pkey));
 }
 
-static int dh_param_missing(const EvpPkey *pkey) {
+int dh_param_missing(const EvpPkey *pkey) {
   const DH *dh = reinterpret_cast<const DH *>(pkey->pkey);
   return dh == nullptr || DH_get0_p(dh) == nullptr || DH_get0_g(dh) == nullptr;
 }
 
-static int dh_param_copy(EvpPkey *to, const EvpPkey *from) {
+int dh_param_copy(EvpPkey *to, const EvpPkey *from) {
   if (dh_param_missing(from)) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
     return 0;
@@ -81,7 +81,7 @@
   return 1;
 }
 
-static bool dh_param_equal(const EvpPkey *a, const EvpPkey *b) {
+bool dh_param_equal(const EvpPkey *a, const EvpPkey *b) {
   if (dh_param_missing(a) || dh_param_missing(b)) {
     return false;
   }
@@ -94,7 +94,7 @@
          BN_cmp(DH_get0_g(a_dh), DH_get0_g(b_dh)) == 0;
 }
 
-static bool dh_pub_equal(const EvpPkey *a, const EvpPkey *b) {
+bool dh_pub_equal(const EvpPkey *a, const EvpPkey *b) {
   if (!dh_param_equal(a, b)) {
     return false;
   }
@@ -104,12 +104,12 @@
   return BN_cmp(DH_get0_pub_key(a_dh), DH_get0_pub_key(b_dh)) == 0;
 }
 
-static bool dh_has_pub(const EvpPkey *pk) {
+bool dh_has_pub(const EvpPkey *pk) {
   const DH *pk_dh = reinterpret_cast<const DH *>(pk->pkey);
   return DH_get0_pub_key(pk_dh) != nullptr;
 }
 
-static bool dh_pub_copy(EvpPkey *out, const EvpPkey *pk) {
+bool dh_pub_copy(EvpPkey *out, const EvpPkey *pk) {
   const DH *pk_dh = reinterpret_cast<const DH *>(pk->pkey);
   const BIGNUM *public_key = DH_get0_pub_key(pk_dh);
   if (public_key == nullptr) {
@@ -128,12 +128,12 @@
   return true;
 }
 
-static bool dh_has_priv(const EvpPkey *pk) {
+bool dh_has_priv(const EvpPkey *pk) {
   const DH *pk_dh = reinterpret_cast<const DH *>(pk->pkey);
   return DH_get0_priv_key(pk_dh) != nullptr;
 }
 
-static const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
+const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
     /*pkey_id=*/EVP_PKEY_DH,
     /*oid=*/{0},
     /*oid_len=*/0,
@@ -167,7 +167,7 @@
   bool pad = false;
 };
 
-static int pkey_dh_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *) {
+int pkey_dh_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *) {
   DH_PKEY_CTX *dctx = New<DH_PKEY_CTX>();
   if (dctx == nullptr) {
     return 0;
@@ -177,7 +177,7 @@
   return 1;
 }
 
-static int pkey_dh_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
+int pkey_dh_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
   if (!pkey_dh_init(dst, nullptr)) {
     return 0;
   }
@@ -188,11 +188,11 @@
   return 1;
 }
 
-static void pkey_dh_cleanup(EvpPkeyCtx *ctx) {
+void pkey_dh_cleanup(EvpPkeyCtx *ctx) {
   Delete(reinterpret_cast<DH_PKEY_CTX *>(ctx->data));
 }
 
-static int pkey_dh_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
+int pkey_dh_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
   DH *dh = DH_new();
   if (dh == nullptr || !EVP_PKEY_assign_DH(pkey, dh)) {
     DH_free(dh);
@@ -207,7 +207,7 @@
   return DH_generate_key(dh);
 }
 
-static int pkey_dh_derive(EvpPkeyCtx *ctx, uint8_t *out, size_t *out_len) {
+int pkey_dh_derive(EvpPkeyCtx *ctx, uint8_t *out, size_t *out_len) {
   DH_PKEY_CTX *dctx = reinterpret_cast<DH_PKEY_CTX *>(ctx->data);
   if (ctx->pkey == nullptr || ctx->peerkey == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_KEYS_NOT_SET);
@@ -248,7 +248,7 @@
   return 1;
 }
 
-static int pkey_dh_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
+int pkey_dh_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
   DH_PKEY_CTX *dctx = reinterpret_cast<DH_PKEY_CTX *>(ctx->data);
   switch (type) {
     case EVP_PKEY_CTRL_PEER_KEY:
diff --git a/crypto/evp/p_dsa.cc b/crypto/evp/p_dsa.cc
index df02f1f..786d6be 100644
--- a/crypto/evp/p_dsa.cc
+++ b/crypto/evp/p_dsa.cc
@@ -31,9 +31,9 @@
 
 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth;
 
-static bssl::evp_decode_result_t dsa_pub_decode(const EVP_PKEY_ALG *alg,
-                                                EvpPkey *out, CBS *params,
-                                                CBS *key) {
+bssl::evp_decode_result_t dsa_pub_decode(const EVP_PKEY_ALG *alg,
+                                         EvpPkey *out, CBS *params,
+                                         CBS *key) {
   // See RFC 3279, section 2.3.2.
 
   // Decode parameters. RFC 3279 permits DSA parameters to be omitted, in which
@@ -59,7 +59,7 @@
   return evp_decode_ok;
 }
 
-static int dsa_pub_encode(CBB *out, const EvpPkey *key) {
+int dsa_pub_encode(CBB *out, const EvpPkey *key) {
   const DSAImpl *dsa = reinterpret_cast<const DSAImpl *>(key->pkey);
   const int has_params =
       dsa->p != nullptr && dsa->q != nullptr && dsa->g != nullptr;
@@ -81,9 +81,9 @@
   return 1;
 }
 
-static bssl::evp_decode_result_t dsa_priv_decode(const EVP_PKEY_ALG *alg,
-                                                 EvpPkey *out, CBS *params,
-                                                 CBS *key) {
+bssl::evp_decode_result_t dsa_priv_decode(const EVP_PKEY_ALG *alg,
+                                          EvpPkey *out, CBS *params,
+                                          CBS *key) {
   // See PKCS#11, v2.40, section 2.5.
 
   // Decode parameters.
@@ -124,7 +124,7 @@
   return evp_decode_ok;
 }
 
-static int dsa_priv_encode(CBB *out, const EvpPkey *key) {
+int dsa_priv_encode(CBB *out, const EvpPkey *key) {
   const DSAImpl *dsa = reinterpret_cast<const DSAImpl *>(key->pkey);
   if (dsa == nullptr || dsa->priv_key == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
@@ -148,17 +148,17 @@
   return 1;
 }
 
-static int int_dsa_size(const EvpPkey *pkey) {
+int int_dsa_size(const EvpPkey *pkey) {
   const DSAImpl *dsa = reinterpret_cast<const DSAImpl *>(pkey->pkey);
   return DSA_size(dsa);
 }
 
-static int dsa_bits(const EvpPkey *pkey) {
+int dsa_bits(const EvpPkey *pkey) {
   const DSAImpl *dsa = reinterpret_cast<const DSAImpl *>(pkey->pkey);
   return BN_num_bits(DSA_get0_p(dsa));
 }
 
-static int dsa_missing_parameters(const EvpPkey *pkey) {
+int dsa_missing_parameters(const EvpPkey *pkey) {
   const DSAImpl *dsa = reinterpret_cast<const DSAImpl *>(pkey->pkey);
   if (DSA_get0_p(dsa) == nullptr || DSA_get0_q(dsa) == nullptr ||
       DSA_get0_g(dsa) == nullptr) {
@@ -167,7 +167,7 @@
   return 0;
 }
 
-static int dup_bn_into(UniquePtr<BIGNUM> *out, const BIGNUM *src) {
+int dup_bn_into(UniquePtr<BIGNUM> *out, const BIGNUM *src) {
   UniquePtr<BIGNUM> copy(BN_dup(src));
   if (copy == nullptr) {
     return 0;
@@ -176,7 +176,7 @@
   return 1;
 }
 
-static int dsa_copy_parameters(EvpPkey *to, const EvpPkey *from) {
+int dsa_copy_parameters(EvpPkey *to, const EvpPkey *from) {
   if (to->pkey == nullptr) {
     to->pkey = DSA_new();
     if (to->pkey == nullptr) {
@@ -194,7 +194,7 @@
   return 1;
 }
 
-static bool dsa_equal_parameters(const EvpPkey *a, const EvpPkey *b) {
+bool dsa_equal_parameters(const EvpPkey *a, const EvpPkey *b) {
   const DSAImpl *a_dsa = reinterpret_cast<const DSAImpl *>(a->pkey);
   const DSAImpl *b_dsa = reinterpret_cast<const DSAImpl *>(b->pkey);
   return BN_cmp(DSA_get0_p(a_dsa), DSA_get0_p(b_dsa)) == 0 &&
@@ -202,18 +202,18 @@
          BN_cmp(DSA_get0_g(a_dsa), DSA_get0_g(b_dsa)) == 0;
 }
 
-static bool dsa_pub_equal(const EvpPkey *a, const EvpPkey *b) {
+bool dsa_pub_equal(const EvpPkey *a, const EvpPkey *b) {
   const DSAImpl *a_dsa = reinterpret_cast<const DSAImpl *>(a->pkey);
   const DSAImpl *b_dsa = reinterpret_cast<const DSAImpl *>(b->pkey);
   return BN_cmp(DSA_get0_pub_key(b_dsa), DSA_get0_pub_key(a_dsa)) == 0;
 }
 
-static bool dsa_pub_present(const EvpPkey *pk) {
+bool dsa_pub_present(const EvpPkey *pk) {
   const DSA *pk_dsa = reinterpret_cast<const DSA *>(pk->pkey);
   return DSA_get0_pub_key(pk_dsa) != nullptr;
 }
 
-static bool dsa_pub_copy(EvpPkey *out, const EvpPkey *pk) {
+bool dsa_pub_copy(EvpPkey *out, const EvpPkey *pk) {
   const DSA *pk_dsa = reinterpret_cast<const DSA *>(pk->pkey);
   const BIGNUM *public_key = DSA_get0_pub_key(pk_dsa);
   if (public_key == nullptr) {
@@ -232,12 +232,12 @@
   return true;
 }
 
-static bool dsa_priv_present(const EvpPkey *pk) {
+bool dsa_priv_present(const EvpPkey *pk) {
   const DSA *pk_dsa = reinterpret_cast<const DSA *>(pk->pkey);
   return DSA_get0_priv_key(pk_dsa) != nullptr;
 }
 
-static void int_dsa_free(EvpPkey *pkey) {
+void int_dsa_free(EvpPkey *pkey) {
   DSA_free(reinterpret_cast<DSAImpl *>(pkey->pkey));
   pkey->pkey = nullptr;
 }
diff --git a/crypto/evp/p_ec.cc b/crypto/evp/p_ec.cc
index 3e72432..3f35e5a 100644
--- a/crypto/evp/p_ec.cc
+++ b/crypto/evp/p_ec.cc
@@ -47,7 +47,7 @@
 extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth;
 extern const EVP_PKEY_CTX_METHOD ec_pkey_meth;
 
-static int eckey_pub_encode(CBB *out, const EvpPkey *key) {
+int eckey_pub_encode(CBB *out, const EvpPkey *key) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(key->pkey);
   const EC_GROUP *group = EC_KEY_get0_group(ec_key);
   const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
@@ -71,9 +71,9 @@
   return 1;
 }
 
-static bssl::evp_decode_result_t eckey_pub_decode(const EVP_PKEY_ALG *alg,
-                                                  EvpPkey *out, CBS *params,
-                                                  CBS *key) {
+bssl::evp_decode_result_t eckey_pub_decode(const EVP_PKEY_ALG *alg,
+                                           EvpPkey *out, CBS *params,
+                                           CBS *key) {
   const auto *ec_alg = static_cast<const EVP_PKEY_ALG_EC *>(alg);
   if (ec_alg->ec_group == nullptr) {
     return evp_decode_unsupported;
@@ -107,7 +107,7 @@
   return evp_decode_ok;
 }
 
-static bool eckey_pub_equal(const EvpPkey *a, const EvpPkey *b) {
+bool eckey_pub_equal(const EvpPkey *a, const EvpPkey *b) {
   const EC_KEY *a_ec = reinterpret_cast<const EC_KEY *>(a->pkey);
   const EC_KEY *b_ec = reinterpret_cast<const EC_KEY *>(b->pkey);
   const EC_GROUP *group = EC_KEY_get0_group(b_ec);
@@ -116,9 +116,9 @@
   return EC_POINT_cmp(group, pa, pb, nullptr) == 0;
 }
 
-static bssl::evp_decode_result_t eckey_priv_decode(const EVP_PKEY_ALG *alg,
-                                                   EvpPkey *out, CBS *params,
-                                                   CBS *key) {
+bssl::evp_decode_result_t eckey_priv_decode(const EVP_PKEY_ALG *alg,
+                                            EvpPkey *out, CBS *params,
+                                            CBS *key) {
   const auto *ec_alg = static_cast<const EVP_PKEY_ALG_EC *>(alg);
   if (ec_alg->ec_group == nullptr) {
     return evp_decode_unsupported;
@@ -149,7 +149,7 @@
   return evp_decode_ok;
 }
 
-static int eckey_priv_encode(CBB *out, const EvpPkey *key) {
+int eckey_priv_encode(CBB *out, const EvpPkey *key) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(key->pkey);
 
   // Omit the redundant copy of the curve name. This contradicts RFC 5915 but
@@ -176,8 +176,8 @@
   return 1;
 }
 
-static int eckey_set1_tls_encodedpoint(EvpPkey *pkey, const uint8_t *in,
-                                       size_t len) {
+int eckey_set1_tls_encodedpoint(EvpPkey *pkey, const uint8_t *in,
+                                size_t len) {
   EC_KEY *ec_key = reinterpret_cast<EC_KEY *>(pkey->pkey);
   if (ec_key == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
@@ -187,8 +187,8 @@
   return EC_KEY_oct2key(ec_key, in, len, nullptr);
 }
 
-static size_t eckey_get1_tls_encodedpoint(const EvpPkey *pkey,
-                                          uint8_t **out_ptr) {
+size_t eckey_get1_tls_encodedpoint(const EvpPkey *pkey,
+                                   uint8_t **out_ptr) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   if (ec_key == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
@@ -199,12 +199,12 @@
                         nullptr);
 }
 
-static int int_ec_size(const EvpPkey *pkey) {
+int int_ec_size(const EvpPkey *pkey) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   return ECDSA_size(ec_key);
 }
 
-static int ec_bits(const EvpPkey *pkey) {
+int ec_bits(const EvpPkey *pkey) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   const EC_GROUP *group = EC_KEY_get0_group(ec_key);
   if (group == nullptr) {
@@ -214,12 +214,12 @@
   return EC_GROUP_order_bits(group);
 }
 
-static int ec_missing_parameters(const EvpPkey *pkey) {
+int ec_missing_parameters(const EvpPkey *pkey) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   return ec_key == nullptr || EC_KEY_get0_group(ec_key) == nullptr;
 }
 
-static int ec_copy_parameters(EvpPkey *to, const EvpPkey *from) {
+int ec_copy_parameters(EvpPkey *to, const EvpPkey *from) {
   const EC_KEY *from_key = reinterpret_cast<const EC_KEY *>(from->pkey);
   if (from_key == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
@@ -239,7 +239,7 @@
   return EC_KEY_set_group(reinterpret_cast<EC_KEY *>(to->pkey), group);
 }
 
-static bool ec_equal_parameters(const EvpPkey *a, const EvpPkey *b) {
+bool ec_equal_parameters(const EvpPkey *a, const EvpPkey *b) {
   const EC_KEY *a_ec = reinterpret_cast<const EC_KEY *>(a->pkey);
   const EC_KEY *b_ec = reinterpret_cast<const EC_KEY *>(b->pkey);
   if (a_ec == nullptr || b_ec == nullptr) {
@@ -254,22 +254,22 @@
   return EC_GROUP_cmp(group_a, group_b, nullptr) == 0;
 }
 
-static void int_ec_free(EvpPkey *pkey) {
+void int_ec_free(EvpPkey *pkey) {
   EC_KEY_free(reinterpret_cast<EC_KEY *>(pkey->pkey));
   pkey->pkey = nullptr;
 }
 
-static int eckey_opaque(const EvpPkey *pkey) {
+int eckey_opaque(const EvpPkey *pkey) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   return EC_KEY_is_opaque(ec_key);
 }
 
-static bool eckey_pub_present(const EvpPkey *pkey) {
+bool eckey_pub_present(const EvpPkey *pkey) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   return EC_KEY_get0_public_key(ec_key) != nullptr;
 }
 
-static bool eckey_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
+bool eckey_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
   if (public_key == nullptr) {
@@ -287,7 +287,7 @@
   return true;
 }
 
-static bool eckey_priv_present(const EvpPkey *pkey) {
+bool eckey_priv_present(const EvpPkey *pkey) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(pkey->pkey);
   return EC_KEY_get0_private_key(ec_key) != nullptr;
 }
@@ -337,7 +337,7 @@
   const EC_GROUP *gen_group = nullptr;
 };
 
-static int pkey_ec_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *alg) {
+int pkey_ec_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *alg) {
   EC_PKEY_CTX *dctx = New<EC_PKEY_CTX>();
   if (!dctx) {
     return 0;
@@ -352,7 +352,7 @@
   return 1;
 }
 
-static int pkey_ec_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
+int pkey_ec_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
   if (!pkey_ec_init(dst, nullptr)) {
     return 0;
   }
@@ -364,12 +364,12 @@
   return 1;
 }
 
-static void pkey_ec_cleanup(EvpPkeyCtx *ctx) {
+void pkey_ec_cleanup(EvpPkeyCtx *ctx) {
   Delete(reinterpret_cast<EC_PKEY_CTX *>(ctx->data));
 }
 
-static int pkey_ec_sign(EvpPkeyCtx *ctx, uint8_t *sig, size_t *siglen,
-                        const uint8_t *tbs, size_t tbslen) {
+int pkey_ec_sign(EvpPkeyCtx *ctx, uint8_t *sig, size_t *siglen,
+                 const uint8_t *tbs, size_t tbslen) {
   const EC_KEY *ec = reinterpret_cast<EC_KEY *>(ctx->pkey->pkey);
   if (!sig) {
     *siglen = ECDSA_size(ec);
@@ -387,13 +387,13 @@
   return 1;
 }
 
-static int pkey_ec_verify(EvpPkeyCtx *ctx, const uint8_t *sig, size_t siglen,
-                          const uint8_t *tbs, size_t tbslen) {
+int pkey_ec_verify(EvpPkeyCtx *ctx, const uint8_t *sig, size_t siglen,
+                   const uint8_t *tbs, size_t tbslen) {
   const EC_KEY *ec_key = reinterpret_cast<EC_KEY *>(ctx->pkey->pkey);
   return ECDSA_verify(0, tbs, tbslen, sig, siglen, ec_key);
 }
 
-static int pkey_ec_derive(EvpPkeyCtx *ctx, uint8_t *key, size_t *keylen) {
+int pkey_ec_derive(EvpPkeyCtx *ctx, uint8_t *key, size_t *keylen) {
   if (!ctx->pkey || !ctx->peerkey) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_KEYS_NOT_SET);
     return 0;
@@ -421,7 +421,7 @@
   return 1;
 }
 
-static int pkey_ec_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
+int pkey_ec_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
   EC_PKEY_CTX *dctx = reinterpret_cast<EC_PKEY_CTX *>(ctx->data);
 
   switch (type) {
@@ -457,7 +457,7 @@
   }
 }
 
-static int pkey_ec_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
+int pkey_ec_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
   EC_PKEY_CTX *dctx = reinterpret_cast<EC_PKEY_CTX *>(ctx->data);
   const EC_GROUP *group = dctx->gen_group;
   if (group == nullptr) {
@@ -477,7 +477,7 @@
   return 1;
 }
 
-static int pkey_ec_paramgen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
+int pkey_ec_paramgen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
   EC_PKEY_CTX *dctx = reinterpret_cast<EC_PKEY_CTX *>(ctx->data);
   if (dctx->gen_group == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
diff --git a/crypto/evp/p_ed25519.cc b/crypto/evp/p_ed25519.cc
index 868c9f0..3cdbc1d 100644
--- a/crypto/evp/p_ed25519.cc
+++ b/crypto/evp/p_ed25519.cc
@@ -41,13 +41,13 @@
 
 #define ED25519_PUBLIC_KEY_OFFSET 32
 
-static void ed25519_free(EvpPkey *pkey) {
+void ed25519_free(EvpPkey *pkey) {
   ED25519_KEY *key = reinterpret_cast<ED25519_KEY *>(pkey->pkey);
   Delete(key);
   pkey->pkey = nullptr;
 }
 
-static int ed25519_set_priv_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
+int ed25519_set_priv_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
   if (len != 32) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     return 0;
@@ -67,7 +67,7 @@
   return 1;
 }
 
-static int ed25519_set_pub_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
+int ed25519_set_pub_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
   if (len != 32) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     return 0;
@@ -84,8 +84,8 @@
   return 1;
 }
 
-static int ed25519_get_priv_raw(const EvpPkey *pkey, uint8_t *out,
-                                size_t *out_len) {
+int ed25519_get_priv_raw(const EvpPkey *pkey, uint8_t *out,
+                         size_t *out_len) {
   const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
   if (!key->has_private) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
@@ -108,8 +108,8 @@
   return 1;
 }
 
-static int ed25519_get_pub_raw(const EvpPkey *pkey, uint8_t *out,
-                               size_t *out_len) {
+int ed25519_get_pub_raw(const EvpPkey *pkey, uint8_t *out,
+                        size_t *out_len) {
   const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
   if (out == nullptr) {
     *out_len = 32;
@@ -126,9 +126,9 @@
   return 1;
 }
 
-static bssl::evp_decode_result_t ed25519_pub_decode(const EVP_PKEY_ALG *alg,
-                                                    EvpPkey *out, CBS *params,
-                                                    CBS *key) {
+bssl::evp_decode_result_t ed25519_pub_decode(const EVP_PKEY_ALG *alg,
+                                             EvpPkey *out, CBS *params,
+                                             CBS *key) {
   // See RFC 8410, section 4.
 
   // The parameters must be omitted. Public keys have length 32.
@@ -142,7 +142,7 @@
              : evp_decode_error;
 }
 
-static int ed25519_pub_encode(CBB *out, const EvpPkey *pkey) {
+int ed25519_pub_encode(CBB *out, const EvpPkey *pkey) {
   const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
 
   // See RFC 8410, section 4.
@@ -163,16 +163,16 @@
   return 1;
 }
 
-static bool ed25519_pub_equal(const EvpPkey *a, const EvpPkey *b) {
+bool ed25519_pub_equal(const EvpPkey *a, const EvpPkey *b) {
   const ED25519_KEY *a_key = reinterpret_cast<const ED25519_KEY *>(a->pkey);
   const ED25519_KEY *b_key = reinterpret_cast<const ED25519_KEY *>(b->pkey);
   return OPENSSL_memcmp(a_key->key + ED25519_PUBLIC_KEY_OFFSET,
                         b_key->key + ED25519_PUBLIC_KEY_OFFSET, 32) == 0;
 }
 
-static bssl::evp_decode_result_t ed25519_priv_decode(const EVP_PKEY_ALG *alg,
-                                                     EvpPkey *out, CBS *params,
-                                                     CBS *key) {
+bssl::evp_decode_result_t ed25519_priv_decode(const EVP_PKEY_ALG *alg,
+                                              EvpPkey *out, CBS *params,
+                                              CBS *key) {
   // See RFC 8410, section 7.
 
   // Parameters must be empty. The key is a 32-byte value wrapped in an extra
@@ -189,7 +189,7 @@
              : evp_decode_error;
 }
 
-static int ed25519_priv_encode(CBB *out, const EvpPkey *pkey) {
+int ed25519_priv_encode(CBB *out, const EvpPkey *pkey) {
   const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
   if (!key->has_private) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
@@ -216,9 +216,9 @@
   return 1;
 }
 
-static bool ed25519_pub_present(const EvpPkey *) { return true; }
+bool ed25519_pub_present(const EvpPkey *) { return true; }
 
-static bool ed25519_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
+bool ed25519_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
   const ED25519_KEY *pkey_ed25519 =
       reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
   ED25519_KEY *public_copy = New<ED25519_KEY>();
@@ -233,14 +233,14 @@
   return true;
 }
 
-static bool ed25519_priv_present(const EvpPkey *pkey) {
+bool ed25519_priv_present(const EvpPkey *pkey) {
   const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
   return key->has_private;
 }
 
-static int ed25519_size(const EvpPkey *pkey) { return 64; }
+int ed25519_size(const EvpPkey *pkey) { return 64; }
 
-static int ed25519_bits(const EvpPkey *pkey) { return 253; }
+int ed25519_bits(const EvpPkey *pkey) { return 253; }
 
 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
     EVP_PKEY_ED25519,
@@ -273,9 +273,9 @@
 };
 
 // Ed25519 has no parameters to copy.
-static int pkey_ed25519_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
+int pkey_ed25519_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
 
-static int pkey_ed25519_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
+int pkey_ed25519_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
   ED25519_KEY *key = New<ED25519_KEY>();
   if (key == nullptr) {
     return 0;
@@ -289,9 +289,9 @@
   return 1;
 }
 
-static int pkey_ed25519_sign_message(EvpPkeyCtx *ctx, uint8_t *sig,
-                                     size_t *siglen, const uint8_t *tbs,
-                                     size_t tbslen) {
+int pkey_ed25519_sign_message(EvpPkeyCtx *ctx, uint8_t *sig,
+                              size_t *siglen, const uint8_t *tbs,
+                              size_t tbslen) {
   const ED25519_KEY *key =
       reinterpret_cast<const ED25519_KEY *>(ctx->pkey->pkey);
   if (!key->has_private) {
@@ -317,9 +317,9 @@
   return 1;
 }
 
-static int pkey_ed25519_verify_message(EvpPkeyCtx *ctx, const uint8_t *sig,
-                                       size_t siglen, const uint8_t *tbs,
-                                       size_t tbslen) {
+int pkey_ed25519_verify_message(EvpPkeyCtx *ctx, const uint8_t *sig,
+                                size_t siglen, const uint8_t *tbs,
+                                size_t tbslen) {
   const ED25519_KEY *key =
       reinterpret_cast<const ED25519_KEY *>(ctx->pkey->pkey);
   if (siglen != 64 ||
diff --git a/crypto/evp/p_hkdf.cc b/crypto/evp/p_hkdf.cc
index a45bd6c..3494d5e 100644
--- a/crypto/evp/p_hkdf.cc
+++ b/crypto/evp/p_hkdf.cc
@@ -37,12 +37,12 @@
   Vector<uint8_t> info;
 };
 
-static int pkey_hkdf_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *) {
+int pkey_hkdf_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *) {
   ctx->data = New<HKDF_PKEY_CTX>();
   return 1;
 }
 
-static int pkey_hkdf_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
+int pkey_hkdf_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
   if (!pkey_hkdf_init(dst, nullptr)) {
     return 0;
   }
@@ -62,11 +62,11 @@
   return 1;
 }
 
-static void pkey_hkdf_cleanup(EvpPkeyCtx *ctx) {
+void pkey_hkdf_cleanup(EvpPkeyCtx *ctx) {
   Delete(reinterpret_cast<HKDF_PKEY_CTX *>(ctx->data));
 }
 
-static int pkey_hkdf_derive(EvpPkeyCtx *ctx, uint8_t *out, size_t *out_len) {
+int pkey_hkdf_derive(EvpPkeyCtx *ctx, uint8_t *out, size_t *out_len) {
   HKDF_PKEY_CTX *hctx = reinterpret_cast<HKDF_PKEY_CTX *>(ctx->data);
   if (hctx->md == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
@@ -110,7 +110,7 @@
   return 0;
 }
 
-static int pkey_hkdf_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
+int pkey_hkdf_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
   HKDF_PKEY_CTX *hctx = reinterpret_cast<HKDF_PKEY_CTX *>(ctx->data);
   switch (type) {
     case EVP_PKEY_CTRL_HKDF_MODE:
diff --git a/crypto/evp/p_mlkem.cc b/crypto/evp/p_mlkem.cc
index c62c35e..dd8710c 100644
--- a/crypto/evp/p_mlkem.cc
+++ b/crypto/evp/p_mlkem.cc
@@ -356,8 +356,8 @@
     return 1;
   }
 
-  static int KemEncap(Span<uint8_t> out_ciphertext, Span<uint8_t> out_secret,
-                      const EVP_PKEY *peer_key) {
+  static int KemEncap(const EVP_KEM *kem, Span<uint8_t> out_ciphertext,
+                      Span<uint8_t> out_secret, const EVP_PKEY *peer_key) {
     const auto *peer_pubkey = GetKeyData(FromOpaque(peer_key))->GetPublicKey();
     if (out_ciphertext.size() != Traits::kCiphertextBytes) {
       OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_CIPHERTEXT_LENGTH);
@@ -371,7 +371,8 @@
     return 1;
   }
 
-  static int KemEncapExternalEntropy(Span<uint8_t> out_ciphertext,
+  static int KemEncapExternalEntropy(const EVP_KEM *kem,
+                                     Span<uint8_t> out_ciphertext,
                                      Span<uint8_t> out_secret,
                                      const EVP_PKEY *peer_key,
                                      Span<const uint8_t> entropy) {
@@ -393,8 +394,8 @@
     return 1;
   }
 
-  static int KemDecap(Span<uint8_t> out_secret, Span<const uint8_t> ciphertext,
-                      const EVP_PKEY *key) {
+  static int KemDecap(const EVP_KEM *kem, Span<uint8_t> out_secret,
+                      Span<const uint8_t> ciphertext, const EVP_PKEY *key) {
     const auto *priv = GetKeyData(FromOpaque(key))->AsPrivateKeyData();
     if (priv == nullptr) {
       OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
@@ -413,6 +414,7 @@
       /*ciphertext_len=*/Traits::kCiphertextBytes,
       /*secret_len=*/MLKEM_SHARED_SECRET_BYTES,
       /*entropy_len=*/BCM_MLKEM_ENCAP_ENTROPY,
+      /*check_key=*/nullptr,
       &KemEncap,
       &KemEncapExternalEntropy,
       &KemDecap,
diff --git a/crypto/evp/p_rsa.cc b/crypto/evp/p_rsa.cc
index 41470be..3d9f1a9 100644
--- a/crypto/evp/p_rsa.cc
+++ b/crypto/evp/p_rsa.cc
@@ -46,7 +46,7 @@
 extern const EVP_PKEY_CTX_METHOD rsa_pkey_meth;
 extern const EVP_PKEY_CTX_METHOD rsa_pss_pkey_meth;
 
-static int rsa_pub_encode(CBB *out, const EvpPkey *key) {
+int rsa_pub_encode(CBB *out, const EvpPkey *key) {
   // See RFC 3279, section 2.3.1.
   const RSA *rsa = reinterpret_cast<const RSA *>(key->pkey);
   CBB spki, algorithm, null, key_bitstring;
@@ -66,9 +66,9 @@
   return 1;
 }
 
-static bssl::evp_decode_result_t rsa_pub_decode(const EVP_PKEY_ALG *alg,
-                                                EvpPkey *out, CBS *params,
-                                                CBS *key) {
+bssl::evp_decode_result_t rsa_pub_decode(const EVP_PKEY_ALG *alg,
+                                         EvpPkey *out, CBS *params,
+                                         CBS *key) {
   // See RFC 3279, section 2.3.1.
 
   // The parameters must be NULL.
@@ -89,7 +89,7 @@
   return evp_decode_ok;
 }
 
-static bool rsa_pub_equal(const EvpPkey *a, const EvpPkey *b) {
+bool rsa_pub_equal(const EvpPkey *a, const EvpPkey *b) {
   // We currently assume that all `EVP_PKEY_RSA_PSS` keys have the same
   // parameters, so this vacuously compares parameters. If we ever support
   // multiple PSS parameter sets, we probably should compare them too. Note,
@@ -100,7 +100,7 @@
          BN_cmp(RSA_get0_e(b_rsa), RSA_get0_e(a_rsa)) == 0;
 }
 
-static bool rsa_pub_present(const EvpPkey *pk) {
+bool rsa_pub_present(const EvpPkey *pk) {
   const RSA *pk_rsa = reinterpret_cast<const RSA *>(pk->pkey);
   // An RSA public key should always have n and e. It's possible for a (private)
   // key to have n and d, but not e, so we must explicitly check for the
@@ -108,7 +108,7 @@
   return RSA_get0_n(pk_rsa) != nullptr && RSA_get0_e(pk_rsa) != nullptr;
 }
 
-static bool rsa_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
+bool rsa_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
   const RSAImpl *pk_rsa = reinterpret_cast<const RSAImpl *>(pkey->pkey);
   const BIGNUM *pk_n = RSA_get0_n(pk_rsa);
   const BIGNUM *pk_e = RSA_get0_e(pk_rsa);
@@ -126,7 +126,7 @@
   return true;
 }
 
-static int rsa_priv_encode(CBB *out, const EvpPkey *key) {
+int rsa_priv_encode(CBB *out, const EvpPkey *key) {
   const RSA *rsa = reinterpret_cast<const RSA *>(key->pkey);
   CBB pkcs8, algorithm, null, private_key;
   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
@@ -145,9 +145,9 @@
   return 1;
 }
 
-static bssl::evp_decode_result_t rsa_priv_decode(const EVP_PKEY_ALG *alg,
-                                                 EvpPkey *out, CBS *params,
-                                                 CBS *key) {
+bssl::evp_decode_result_t rsa_priv_decode(const EVP_PKEY_ALG *alg,
+                                          EvpPkey *out, CBS *params,
+                                          CBS *key) {
   // Per RFC 8017, A.1, the parameters have type NULL.
   CBS null;
   if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || CBS_len(&null) != 0 ||
@@ -166,12 +166,12 @@
   return evp_decode_ok;
 }
 
-static bool rsa_priv_present(const EvpPkey *pk) {
+bool rsa_priv_present(const EvpPkey *pk) {
   const RSA *pk_rsa = reinterpret_cast<const RSA *>(pk->pkey);
   return RSA_get0_n(pk_rsa) != nullptr && RSA_get0_d(pk_rsa) != nullptr;
 }
 
-static bssl::evp_decode_result_t rsa_decode_pss_params(
+bssl::evp_decode_result_t rsa_decode_pss_params(
     rsa_pss_params_t expected, CBS *params) {
   if (CBS_len(params) == 0) {
     return evp_decode_unsupported;
@@ -186,7 +186,7 @@
   return pss_params == expected ? evp_decode_ok : evp_decode_unsupported;
 }
 
-static int rsa_pub_encode_pss(CBB *out, const EvpPkey *key) {
+int rsa_pub_encode_pss(CBB *out, const EvpPkey *key) {
   const RSAImpl *rsa = reinterpret_cast<const RSAImpl *>(key->pkey);
   CBB spki, algorithm, key_bitstring;
   if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
@@ -205,17 +205,17 @@
   return 1;
 }
 
-static void evp_pkey_set0_pss(EvpPkey *out, const EVP_PKEY_ALG *alg,
-                              UniquePtr<RSA> rsa) {
+void evp_pkey_set0_pss(EvpPkey *out, const EVP_PKEY_ALG *alg,
+                       UniquePtr<RSA> rsa) {
   BSSL_CHECK(alg->pkey_method->pkey_id == EVP_PKEY_RSA_PSS);
   const auto *alg_pss = static_cast<const EVP_PKEY_ALG_RSA_PSS *>(alg);
   FromOpaque(rsa.get())->pss_params = alg_pss->pss_params;
   evp_pkey_set0(out, alg->method, rsa.release());
 }
 
-static bssl::evp_decode_result_t rsa_pub_decode_pss(const EVP_PKEY_ALG *alg,
-                                                    EvpPkey *out, CBS *params,
-                                                    CBS *key) {
+bssl::evp_decode_result_t rsa_pub_decode_pss(const EVP_PKEY_ALG *alg,
+                                             EvpPkey *out, CBS *params,
+                                             CBS *key) {
   const auto *alg_pss = static_cast<const EVP_PKEY_ALG_RSA_PSS *>(alg);
   evp_decode_result_t ret = rsa_decode_pss_params(alg_pss->pss_params, params);
   if (ret != evp_decode_ok) {
@@ -232,7 +232,7 @@
   return evp_decode_ok;
 }
 
-static int rsa_priv_encode_pss(CBB *out, const EvpPkey *key) {
+int rsa_priv_encode_pss(CBB *out, const EvpPkey *key) {
   const RSAImpl *rsa = reinterpret_cast<const RSAImpl *>(key->pkey);
   CBB pkcs8, algorithm, private_key;
   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
@@ -251,9 +251,9 @@
   return 1;
 }
 
-static bssl::evp_decode_result_t rsa_priv_decode_pss(const EVP_PKEY_ALG *alg,
-                                                     EvpPkey *out, CBS *params,
-                                                     CBS *key) {
+bssl::evp_decode_result_t rsa_priv_decode_pss(const EVP_PKEY_ALG *alg,
+                                              EvpPkey *out, CBS *params,
+                                              CBS *key) {
   const auto *alg_pss = static_cast<const EVP_PKEY_ALG_RSA_PSS *>(alg);
   evp_decode_result_t ret = rsa_decode_pss_params(alg_pss->pss_params, params);
   if (ret != evp_decode_ok) {
@@ -270,32 +270,32 @@
   return evp_decode_ok;
 }
 
-static int rsa_opaque(const EvpPkey *pkey) {
+int rsa_opaque(const EvpPkey *pkey) {
   const RSA *rsa = reinterpret_cast<const RSA *>(pkey->pkey);
   return RSA_is_opaque(rsa);
 }
 
-static int int_rsa_size(const EvpPkey *pkey) {
+int int_rsa_size(const EvpPkey *pkey) {
   const RSA *rsa = reinterpret_cast<const RSA *>(pkey->pkey);
   return RSA_size(rsa);
 }
 
-static int rsa_bits(const EvpPkey *pkey) {
+int rsa_bits(const EvpPkey *pkey) {
   const RSA *rsa = reinterpret_cast<const RSA *>(pkey->pkey);
   return RSA_bits(rsa);
 }
 
-static void int_rsa_free(EvpPkey *pkey) {
+void int_rsa_free(EvpPkey *pkey) {
   RSA_free(reinterpret_cast<RSA *>(pkey->pkey));
   pkey->pkey = nullptr;
 }
 
-static int rsa_pss_params_missing(const EvpPkey *pkey) {
+int rsa_pss_params_missing(const EvpPkey *pkey) {
   const RSA *rsa = reinterpret_cast<const RSA *>(pkey->pkey);
   return rsa == nullptr || FromOpaque(rsa)->pss_params == rsa_pss_none;
 }
 
-static int rsa_pss_params_copy(EvpPkey *to, const EvpPkey *from) {
+int rsa_pss_params_copy(EvpPkey *to, const EvpPkey *from) {
   const RSA *from_key = reinterpret_cast<const RSA *>(from->pkey);
   if (from_key == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
@@ -316,7 +316,7 @@
   return 1;
 }
 
-static bool rsa_pss_params_equal(const EvpPkey *a, const EvpPkey *b) {
+bool rsa_pss_params_equal(const EvpPkey *a, const EvpPkey *b) {
   const RSA *a_rsa = reinterpret_cast<const RSA *>(a->pkey);
   const RSA *b_rsa = reinterpret_cast<const RSA *>(b->pkey);
   if (a_rsa == nullptr || b_rsa == nullptr) {
@@ -428,11 +428,11 @@
   Array<uint8_t> oaep_label;
 };
 
-static bool is_pss_only(const EvpPkeyCtx *ctx) {
+bool is_pss_only(const EvpPkeyCtx *ctx) {
   return ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS;
 }
 
-static int pkey_rsa_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *alg) {
+int pkey_rsa_init(EvpPkeyCtx *ctx, const EVP_PKEY_ALG *alg) {
   RSA_PKEY_CTX *rctx = New<RSA_PKEY_CTX>();
   if (!rctx) {
     return 0;
@@ -462,7 +462,7 @@
   return 1;
 }
 
-static int pkey_rsa_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
+int pkey_rsa_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) {
   RSA_PKEY_CTX *dctx, *sctx;
   if (!pkey_rsa_init(dst, nullptr)) {
     return 0;
@@ -489,12 +489,12 @@
   return 1;
 }
 
-static void pkey_rsa_cleanup(EvpPkeyCtx *ctx) {
+void pkey_rsa_cleanup(EvpPkeyCtx *ctx) {
   Delete(reinterpret_cast<RSA_PKEY_CTX *>(ctx->data));
 }
 
-static int pkey_rsa_sign(EvpPkeyCtx *ctx, uint8_t *sig, size_t *siglen,
-                         const uint8_t *tbs, size_t tbslen) {
+int pkey_rsa_sign(EvpPkeyCtx *ctx, uint8_t *sig, size_t *siglen,
+                  const uint8_t *tbs, size_t tbslen) {
   RSA_PKEY_CTX *rctx = reinterpret_cast<RSA_PKEY_CTX *>(ctx->data);
   RSA *rsa = reinterpret_cast<RSA *>(ctx->pkey->pkey);
   const size_t key_len = EVP_PKEY_size(ctx->pkey.get());
@@ -531,8 +531,8 @@
   return RSA_sign_raw(rsa, siglen, sig, *siglen, tbs, tbslen, rctx->pad_mode);
 }
 
-static int pkey_rsa_verify(EvpPkeyCtx *ctx, const uint8_t *sig, size_t siglen,
-                           const uint8_t *tbs, size_t tbslen) {
+int pkey_rsa_verify(EvpPkeyCtx *ctx, const uint8_t *sig, size_t siglen,
+                    const uint8_t *tbs, size_t tbslen) {
   RSA_PKEY_CTX *rctx = reinterpret_cast<RSA_PKEY_CTX *>(ctx->data);
   RSA *rsa = reinterpret_cast<RSA *>(ctx->pkey->pkey);
 
@@ -566,9 +566,9 @@
   return 1;
 }
 
-static int pkey_rsa_verify_recover(EvpPkeyCtx *ctx, uint8_t *out,
-                                   size_t *out_len, const uint8_t *sig,
-                                   size_t sig_len) {
+int pkey_rsa_verify_recover(EvpPkeyCtx *ctx, uint8_t *out,
+                            size_t *out_len, const uint8_t *sig,
+                            size_t sig_len) {
   RSA_PKEY_CTX *rctx = reinterpret_cast<RSA_PKEY_CTX *>(ctx->data);
   RSA *rsa = reinterpret_cast<RSA *>(ctx->pkey->pkey);
   const size_t key_len = EVP_PKEY_size(ctx->pkey.get());
@@ -626,8 +626,8 @@
   return 1;
 }
 
-static int pkey_rsa_encrypt(EvpPkeyCtx *ctx, uint8_t *out, size_t *outlen,
-                            const uint8_t *in, size_t inlen) {
+int pkey_rsa_encrypt(EvpPkeyCtx *ctx, uint8_t *out, size_t *outlen,
+                     const uint8_t *in, size_t inlen) {
   RSA_PKEY_CTX *rctx = reinterpret_cast<RSA_PKEY_CTX *>(ctx->data);
   RSA *rsa = reinterpret_cast<RSA *>(ctx->pkey->pkey);
   const size_t key_len = EVP_PKEY_size(ctx->pkey.get());
@@ -658,8 +658,8 @@
   return RSA_encrypt(rsa, outlen, out, *outlen, in, inlen, rctx->pad_mode);
 }
 
-static int pkey_rsa_decrypt(EvpPkeyCtx *ctx, uint8_t *out, size_t *outlen,
-                            const uint8_t *in, size_t inlen) {
+int pkey_rsa_decrypt(EvpPkeyCtx *ctx, uint8_t *out, size_t *outlen,
+                     const uint8_t *in, size_t inlen) {
   RSA_PKEY_CTX *rctx = reinterpret_cast<RSA_PKEY_CTX *>(ctx->data);
   RSA *rsa = reinterpret_cast<RSA *>(ctx->pkey->pkey);
   const size_t key_len = EVP_PKEY_size(ctx->pkey.get());
@@ -692,7 +692,7 @@
   return RSA_decrypt(rsa, outlen, out, key_len, in, inlen, rctx->pad_mode);
 }
 
-static int check_padding_md(const EVP_MD *md, int padding) {
+int check_padding_md(const EVP_MD *md, int padding) {
   if (!md) {
     return 1;
   }
@@ -705,7 +705,7 @@
   return 1;
 }
 
-static int is_known_padding(int padding_mode) {
+int is_known_padding(int padding_mode) {
   switch (padding_mode) {
     case RSA_PKCS1_PADDING:
     case RSA_NO_PADDING:
@@ -717,7 +717,7 @@
   }
 }
 
-static int pkey_rsa_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
+int pkey_rsa_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
   RSA_PKEY_CTX *rctx = reinterpret_cast<RSA_PKEY_CTX *>(ctx->data);
   switch (type) {
     case EVP_PKEY_CTRL_RSA_PADDING:
@@ -870,7 +870,7 @@
   }
 }
 
-static int pkey_rsa_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
+int pkey_rsa_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
   RSA_PKEY_CTX *rctx = reinterpret_cast<RSA_PKEY_CTX *>(ctx->data);
   if (!rctx->pub_exp) {
     rctx->pub_exp.reset(BN_new());
diff --git a/crypto/evp/p_x25519.cc b/crypto/evp/p_x25519.cc
index 91df6f4..2c53608 100644
--- a/crypto/evp/p_x25519.cc
+++ b/crypto/evp/p_x25519.cc
@@ -37,13 +37,13 @@
 extern const EVP_PKEY_ASN1_METHOD x25519_asn1_meth;
 extern const EVP_PKEY_CTX_METHOD x25519_pkey_meth;
 
-static void x25519_free(EvpPkey *pkey) {
+void x25519_free(EvpPkey *pkey) {
   X25519_KEY *key = reinterpret_cast<X25519_KEY *>(pkey->pkey);
   OPENSSL_free(key);
   pkey->pkey = nullptr;
 }
 
-static int x25519_set_priv_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
+int x25519_set_priv_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
   if (len != 32) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     return 0;
@@ -62,7 +62,7 @@
   return 1;
 }
 
-static int x25519_set_pub_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
+int x25519_set_pub_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
   if (len != 32) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     return 0;
@@ -80,8 +80,7 @@
   return 1;
 }
 
-static int x25519_get_priv_raw(const EvpPkey *pkey, uint8_t *out,
-                               size_t *out_len) {
+int x25519_get_priv_raw(const EvpPkey *pkey, uint8_t *out, size_t *out_len) {
   const X25519_KEY *key = reinterpret_cast<X25519_KEY *>(pkey->pkey);
   if (!key->has_private) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
@@ -103,8 +102,7 @@
   return 1;
 }
 
-static int x25519_get_pub_raw(const EvpPkey *pkey, uint8_t *out,
-                              size_t *out_len) {
+int x25519_get_pub_raw(const EvpPkey *pkey, uint8_t *out, size_t *out_len) {
   const X25519_KEY *key = reinterpret_cast<X25519_KEY *>(pkey->pkey);
   if (out == nullptr) {
     *out_len = 32;
@@ -121,13 +119,11 @@
   return 1;
 }
 
-static int x25519_set1_tls_encodedpoint(EvpPkey *pkey, const uint8_t *in,
-                                        size_t len) {
+int x25519_set1_tls_encodedpoint(EvpPkey *pkey, const uint8_t *in, size_t len) {
   return x25519_set_pub_raw(pkey, in, len);
 }
 
-static size_t x25519_get1_tls_encodedpoint(const EvpPkey *pkey,
-                                           uint8_t **out_ptr) {
+size_t x25519_get1_tls_encodedpoint(const EvpPkey *pkey, uint8_t **out_ptr) {
   const X25519_KEY *key = reinterpret_cast<X25519_KEY *>(pkey->pkey);
   if (key == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
@@ -138,9 +134,9 @@
   return *out_ptr == nullptr ? 0 : 32;
 }
 
-static bssl::evp_decode_result_t x25519_pub_decode(const EVP_PKEY_ALG *alg,
-                                                   EvpPkey *out, CBS *params,
-                                                   CBS *key) {
+bssl::evp_decode_result_t x25519_pub_decode(const EVP_PKEY_ALG *alg,
+                                            EvpPkey *out, CBS *params,
+                                            CBS *key) {
   // See RFC 8410, section 4.
 
   // The parameters must be omitted. Public keys have length 32.
@@ -154,7 +150,7 @@
              : evp_decode_error;
 }
 
-static int x25519_pub_encode(CBB *out, const EvpPkey *pkey) {
+int x25519_pub_encode(CBB *out, const EvpPkey *pkey) {
   const X25519_KEY *key = reinterpret_cast<X25519_KEY *>(pkey->pkey);
 
   // See RFC 8410, section 4.
@@ -174,15 +170,15 @@
   return 1;
 }
 
-static bool x25519_pub_equal(const EvpPkey *a, const EvpPkey *b) {
+bool x25519_pub_equal(const EvpPkey *a, const EvpPkey *b) {
   const X25519_KEY *a_key = reinterpret_cast<const X25519_KEY *>(a->pkey);
   const X25519_KEY *b_key = reinterpret_cast<const X25519_KEY *>(b->pkey);
   return OPENSSL_memcmp(a_key->pub, b_key->pub, 32) == 0;
 }
 
-static bssl::evp_decode_result_t x25519_priv_decode(const EVP_PKEY_ALG *alg,
-                                                    EvpPkey *out, CBS *params,
-                                                    CBS *key) {
+bssl::evp_decode_result_t x25519_priv_decode(const EVP_PKEY_ALG *alg,
+                                             EvpPkey *out, CBS *params,
+                                             CBS *key) {
   // See RFC 8410, section 7.
 
   // Parameters must be empty. The key is a 32-byte value wrapped in an extra
@@ -199,7 +195,7 @@
              : evp_decode_error;
 }
 
-static int x25519_priv_encode(CBB *out, const EvpPkey *pkey) {
+int x25519_priv_encode(CBB *out, const EvpPkey *pkey) {
   const X25519_KEY *key = reinterpret_cast<const X25519_KEY *>(pkey->pkey);
   if (!key->has_private) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
@@ -226,9 +222,9 @@
   return 1;
 }
 
-static bool x25519_pub_present(const EvpPkey *) { return true; }
+bool x25519_pub_present(const EvpPkey *) { return true; }
 
-static bool x25519_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
+bool x25519_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
   const X25519_KEY *pkey_x25519 =
       reinterpret_cast<const X25519_KEY *>(pkey->pkey);
   X25519_KEY *public_copy = New<X25519_KEY>();
@@ -241,14 +237,14 @@
   return true;
 }
 
-static bool x25519_priv_present(const EvpPkey *pk) {
+bool x25519_priv_present(const EvpPkey *pk) {
   const X25519_KEY *key = reinterpret_cast<const X25519_KEY *>(pk->pkey);
   return key->has_private;
 }
 
-static int x25519_size(const EvpPkey *pkey) { return 32; }
+int x25519_size(const EvpPkey *pkey) { return 32; }
 
-static int x25519_bits(const EvpPkey *pkey) { return 253; }
+int x25519_bits(const EvpPkey *pkey) { return 253; }
 
 const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = {
     EVP_PKEY_X25519,
@@ -281,9 +277,9 @@
 };
 
 // X25519 has no parameters to copy.
-static int pkey_x25519_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
+int pkey_x25519_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
 
-static int pkey_x25519_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
+int pkey_x25519_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
   X25519_KEY *key = New<X25519_KEY>();
   if (key == nullptr) {
     return 0;
@@ -295,7 +291,7 @@
   return 1;
 }
 
-static int pkey_x25519_derive(EvpPkeyCtx *ctx, uint8_t *out, size_t *out_len) {
+int pkey_x25519_derive(EvpPkeyCtx *ctx, uint8_t *out, size_t *out_len) {
   if (ctx->pkey == nullptr || ctx->peerkey == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_KEYS_NOT_SET);
     return 0;
@@ -330,7 +326,7 @@
   return 1;
 }
 
-static int pkey_x25519_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
+int pkey_x25519_ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) {
   switch (type) {
     case EVP_PKEY_CTRL_PEER_KEY:
       // `EVP_PKEY_derive_set_peer` requires the key implement this command,
diff --git a/crypto/evp/p_xwing.cc b/crypto/evp/p_xwing.cc
index 8479bf6..7d9362c 100644
--- a/crypto/evp/p_xwing.cc
+++ b/crypto/evp/p_xwing.cc
@@ -42,19 +42,19 @@
 // This is the length of `eseed` in draft-connolly-cfrg-xwing-kem-06.
 constexpr size_t kXwingEncapEntropyBytes = 64;
 
-static void xwing_free(EvpPkey *pkey) {
+void xwing_free(EvpPkey *pkey) {
   Delete(reinterpret_cast<XWING_KEY *>(pkey->pkey));
 }
 
-static bool xwing_pub_equal(const EvpPkey *a, const EvpPkey *b) {
+bool xwing_pub_equal(const EvpPkey *a, const EvpPkey *b) {
   const XWING_KEY *a_key = reinterpret_cast<const XWING_KEY *>(a->pkey);
   const XWING_KEY *b_key = reinterpret_cast<const XWING_KEY *>(b->pkey);
   return OPENSSL_memcmp(a_key->pub, b_key->pub, XWING_PUBLIC_KEY_BYTES) == 0;
 }
 
-static bool xwing_pub_present(const EvpPkey *) { return true; }
+bool xwing_pub_present(const EvpPkey *) { return true; }
 
-static bool xwing_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
+bool xwing_pub_copy(EvpPkey *out, const EvpPkey *pkey) {
   const XWING_KEY *pkey_xwing = reinterpret_cast<const XWING_KEY *>(pkey->pkey);
   auto public_copy = MakeUnique<XWING_KEY>();
   if (public_copy == nullptr) {
@@ -66,12 +66,12 @@
   return true;
 }
 
-static bool xwing_priv_present(const EvpPkey *pk) {
+bool xwing_priv_present(const EvpPkey *pk) {
   const XWING_KEY *key = reinterpret_cast<const XWING_KEY *>(pk->pkey);
   return key->has_private;
 }
 
-static int xwing_set_priv_seed(EvpPkey *pkey, const uint8_t *in, size_t len) {
+int xwing_set_priv_seed(EvpPkey *pkey, const uint8_t *in, size_t len) {
   auto key = MakeUnique<XWING_KEY>();
   if (key == nullptr) {
     return 0;
@@ -88,8 +88,7 @@
   return 1;
 }
 
-static int xwing_get_priv_seed(const EvpPkey *pkey, uint8_t *out,
-                               size_t *out_len) {
+int xwing_get_priv_seed(const EvpPkey *pkey, uint8_t *out, size_t *out_len) {
   const XWING_KEY *key = reinterpret_cast<const XWING_KEY *>(pkey->pkey);
   if (key == nullptr || !key->has_private) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
@@ -113,7 +112,7 @@
   return 1;
 }
 
-static int xwing_set_pub_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
+int xwing_set_pub_raw(EvpPkey *pkey, const uint8_t *in, size_t len) {
   if (len != XWING_PUBLIC_KEY_BYTES) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     return 0;
@@ -128,8 +127,7 @@
   return 1;
 }
 
-static int xwing_get_pub_raw(const EvpPkey *pkey, uint8_t *out,
-                             size_t *out_len) {
+int xwing_get_pub_raw(const EvpPkey *pkey, uint8_t *out, size_t *out_len) {
   if (out == nullptr) {
     *out_len = XWING_PUBLIC_KEY_BYTES;
     return 1;
@@ -144,16 +142,14 @@
   return 1;
 }
 
-static int xwing_size(const EvpPkey *pkey) { return XWING_CIPHERTEXT_BYTES; }
+int xwing_size(const EvpPkey *pkey) { return XWING_CIPHERTEXT_BYTES; }
 
-static int xwing_bits(const EvpPkey *pkey) {
-  return XWING_PUBLIC_KEY_BYTES * 8;
-}
+int xwing_bits(const EvpPkey *pkey) { return XWING_PUBLIC_KEY_BYTES * 8; }
 
 // X-Wing has no parameters to copy.
-static int pkey_xwing_copy_ctx(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
+int pkey_xwing_copy_ctx(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
 
-static int pkey_xwing_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
+int pkey_xwing_keygen(EvpPkeyCtx *ctx, EvpPkey *pkey) {
   auto key = MakeUnique<XWING_KEY>();
   if (key == nullptr || !XWING_generate_key(key->pub, &key->priv)) {
     OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
@@ -164,8 +160,8 @@
   return 1;
 }
 
-static int xwing_kem_encap(Span<uint8_t> out_ciphertext,
-                           Span<uint8_t> out_secret, const EVP_PKEY *peer_key) {
+int xwing_kem_encap(const EVP_KEM *kem, Span<uint8_t> out_ciphertext,
+                    Span<uint8_t> out_secret, const EVP_PKEY *peer_key) {
   if (out_ciphertext.size() != XWING_CIPHERTEXT_BYTES) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_CIPHERTEXT_LENGTH);
     return 0;
@@ -180,10 +176,11 @@
                      peer_pubkey->pub);
 }
 
-static int xwing_kem_encap_external_entropy(Span<uint8_t> out_ciphertext,
-                                            Span<uint8_t> out_secret,
-                                            const EVP_PKEY *peer_key,
-                                            Span<const uint8_t> entropy) {
+int xwing_kem_encap_external_entropy(const EVP_KEM *kem,
+                                     Span<uint8_t> out_ciphertext,
+                                     Span<uint8_t> out_secret,
+                                     const EVP_PKEY *peer_key,
+                                     Span<const uint8_t> entropy) {
   if (out_ciphertext.size() != XWING_CIPHERTEXT_BYTES) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_CIPHERTEXT_LENGTH);
     return 0;
@@ -202,9 +199,8 @@
                                       peer_pubkey->pub, entropy.data());
 }
 
-static int xwing_kem_decap(Span<uint8_t> out_secret,
-                           Span<const uint8_t> ciphertext,
-                           const EVP_PKEY *key) {
+int xwing_kem_decap(const EVP_KEM *kem, Span<uint8_t> out_secret,
+                    Span<const uint8_t> ciphertext, const EVP_PKEY *key) {
   const XWING_KEY *priv = reinterpret_cast<XWING_KEY *>(FromOpaque(key)->pkey);
   if (priv == nullptr || !priv->has_private) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
@@ -223,11 +219,12 @@
   return XWING_decap(out_secret.data(), ciphertext.data(), &priv->priv);
 }
 
-static const EVP_KEM xwing_evp_kem = {
+const EVP_KEM xwing_evp_kem = {
     EVP_PKEY_XWING,                     //
     XWING_CIPHERTEXT_BYTES,             //
     XWING_SHARED_SECRET_BYTES,          //
     kXwingEncapEntropyBytes,            //
+    /*check_key=*/nullptr,              //
     &xwing_kem_encap,                   //
     &xwing_kem_encap_external_entropy,  //
     &xwing_kem_decap,                   //
diff --git a/crypto/fipsmodule/bn/exponentiation.cc.inc b/crypto/fipsmodule/bn/exponentiation.cc.inc
index dfdb907..81b6385 100644
--- a/crypto/fipsmodule/bn/exponentiation.cc.inc
+++ b/crypto/fipsmodule/bn/exponentiation.cc.inc
@@ -376,29 +376,6 @@
   (void)ret;
 }
 
-static int copy_from_prebuf(BIGNUM *b, int top, const BN_ULONG *table, int idx,
-                            int window) {
-  if (!bn_wexpand(b, top)) {
-    return 0;
-  }
-
-  OPENSSL_memset(b->d, 0, sizeof(BN_ULONG) * top);
-  const int width = 1 << window;
-  for (int i = 0; i < width; i++, table += top) {
-    // Use a value barrier to prevent Clang from adding a branch when `i != idx`
-    // and making this copy not constant time. Clang is still allowed to learn
-    // that `mask` is constant across the inner loop, so this won't inhibit any
-    // vectorization it might do.
-    BN_ULONG mask = value_barrier_w(constant_time_eq_int(i, idx));
-    for (int j = 0; j < top; j++) {
-      b->d[j] |= table[j] & mask;
-    }
-  }
-
-  b->width = top;
-  return 1;
-}
-
 // Window sizes optimized for fixed window size modular exponentiation
 // algorithm (BN_mod_exp_mont_consttime).
 //
@@ -409,6 +386,57 @@
   ((b) > 937 ? 6 : (b) > 306 ? 5 : (b) > 89 ? 4 : (b) > 22 ? 3 : 1)
 #define BN_MAX_MOD_EXP_CTIME_WINDOW (6)
 
+static int copy_from_prebuf(BIGNUM *b, int top, const BN_ULONG *table, int idx,
+                            int window) {
+  if (!bn_wexpand(b, top)) {
+    return 0;
+  }
+
+  assert(window > 0 && window <= BN_MAX_MOD_EXP_CTIME_WINDOW);
+
+  // Compute the selection masks up front. The value barrier prevents Clang
+  // from adding a branch when `i != idx` and making this copy not constant
+  // time.
+  const int width = 1 << window;
+  BN_ULONG masks[1 << BN_MAX_MOD_EXP_CTIME_WINDOW];
+  for (int i = 0; i < width; i++) {
+    masks[i] = value_barrier_w(constant_time_eq_int(i, idx));
+  }
+
+  // Every table entry is read for every limb, independent of `idx`. The output
+  // is accumulated a few limbs at a time in registers. Updating `b->d` once per
+  // table entry instead adds a store-to-load dependency to every iteration,
+  // which the compiler cannot remove because `b->d` may alias `table`.
+  BN_ULONG *const d = b->d;
+  int j = 0;
+  for (; j + 4 <= top; j += 4) {
+    BN_ULONG a0 = 0, a1 = 0, a2 = 0, a3 = 0;
+    const BN_ULONG *t = table + j;
+    for (int i = 0; i < width; i++, t += top) {
+      BN_ULONG m = masks[i];
+      a0 |= t[0] & m;
+      a1 |= t[1] & m;
+      a2 |= t[2] & m;
+      a3 |= t[3] & m;
+    }
+    d[j] = a0;
+    d[j + 1] = a1;
+    d[j + 2] = a2;
+    d[j + 3] = a3;
+  }
+  for (; j < top; j++) {
+    BN_ULONG a = 0;
+    const BN_ULONG *t = table + j;
+    for (int i = 0; i < width; i++, t += top) {
+      a |= *t & masks[i];
+    }
+    d[j] = a;
+  }
+
+  b->width = top;
+  return 1;
+}
+
 // This variant of `BN_mod_exp_mont` uses fixed windows and fixed memory access
 // patterns to protect secret exponents (cf. the hyper-threading timing attacks
 // pointed out by Colin Percival,
diff --git a/crypto/hpke/hpke.cc b/crypto/hpke/hpke.cc
index 30d12df..ceeb2e6 100644
--- a/crypto/hpke/hpke.cc
+++ b/crypto/hpke/hpke.cc
@@ -49,18 +49,63 @@
 #define MAX_SEED_LEN XWING_SEED_LEN
 #define MAX_SHARED_SECRET_LEN SHA256_DIGEST_LENGTH
 
+namespace {
+
+// HpkeKeyMethod implements the key-type-specific operations that HPKE performs
+// on keys of a particular `EVP_PKEY_ALG` type.
+struct HpkeKeyMethod {
+  // hpke_kem_id is the ID of the KEM in RFC 9180.
+  uint16_t hpke_kem_id;
+
+  // public_key_len corresponds to Npk in RFC 9180.
+  size_t public_key_len;
+  // private_key_len corresponds to Nsk in RFC 9180.
+  size_t private_key_len;
+
+  const EVP_PKEY_ALG *(*alg_func)();
+
+  // deserialize_private_key and serialize_private_key implement the
+  // DeserializePrivateKey and SerializePrivateKey operations for the key type
+  // from section 4 of RFC 9180, using the same format accepted by
+  // `EVP_HPKE_KEY_init`.
+  EVP_PKEY *(*deserialize_private_key)(const EVP_PKEY_ALG *alg,
+                                       const uint8_t *in, size_t len);
+  int (*serialize_private_key)(const EVP_PKEY *pkey, uint8_t *out,
+                               size_t *out_len);
+
+  // deserialize_public_key and serialize_public_key implement the
+  // DeserializePublicKey and SerializePublicKey operations from section 4 of
+  // RFC 9180.
+  EVP_PKEY *(*deserialize_public_key)(const EVP_PKEY_ALG *alg,
+                                      const uint8_t *in, size_t len);
+  int (*serialize_public_key)(const EVP_PKEY *pkey, uint8_t *out,
+                              size_t *out_len);
+
+  // derive_key_pair implements the DeriveKeyPair operation from section 4 of
+  // RFC 9180.
+  EVP_PKEY *(*derive_key_pair)(const EVP_PKEY_ALG *alg, uint16_t kem_suite_id,
+                               Span<const uint8_t> ikm);
+};
+
+}  // namespace
+
 struct evp_hpke_kem_st {
   uint16_t id;
 
-  // evp_pkey_alg_func and evp_kem_func, if non-null, provide the EVP_PKEY_CTX
-  // and EVP_KEM functionality backing this EVP_HPKE_KEM. If these are non-null,
-  // then `init_key`, `generate_key`, `derive_key`, `encap_with_seed`, and
-  // `decap` are null and 'seed_len` and `enc_len` are zero (until fully
-  // migrated), and the `evp_*` function pointers are non-null.
+  // evp_kem_func and key_method, if non-null, provide the EVP_PKEY_CTX and
+  // EVP_KEM functionality backing this EVP_HPKE_KEM. If these are non-null,
+  // then (until fully migrated):
+  //  * `init_key`, `generate_key`, and `derive_key` are null (these operations
+  //    are supplied by `key_method`),
+  //  * `encap_with_seed`, and `decap` are null (these operations are supplied
+  //    by the `EVP_KEM`),
+  //  * `public_key_len` and `private_key_len` are zero (they are supplied by
+  //    `key_method`), and
+  //  * `seed_len` and `enc_len` are zero (they are supplied by the `EVP_KEM`).
   // TODO(crbug.com/535883377): Unify EVP_HPKE_KEM and EVP_KEM for all supported
   // HPKE KEMs.
-  const EVP_PKEY_ALG *(*evp_pkey_alg_func)();
   const EVP_KEM *(*evp_kem_func)();
+  const HpkeKeyMethod *key_method;
 
   size_t public_key_len;
   size_t private_key_len;
@@ -90,21 +135,6 @@
                     size_t *out_shared_secret_len, const uint8_t *enc,
                     size_t enc_len, const uint8_t *peer_public_key,
                     size_t peer_public_key_len);
-
-  // Hooks used for operations with `evp_pkey_alg_func` and `evp_kem_func`, when
-  // they are non-null.
-  // TODO(crbug.com/535883377): Unify EVP_HPKE_KEM and EVP_KEM for all supported
-  // HPKE KEMs.
-  EVP_PKEY *(*evp_deserialize_private_key)(const EVP_PKEY_ALG *alg,
-                                           const uint8_t *in, size_t len);
-  int (*evp_serialize_private_key)(const EVP_PKEY *pkey, uint8_t *out,
-                                   size_t *out_len);
-  EVP_PKEY *(*evp_deserialize_public_key)(const EVP_PKEY_ALG *alg,
-                                          const uint8_t *in, size_t len);
-  int (*evp_serialize_public_key)(const EVP_PKEY *pkey, uint8_t *out,
-                                  size_t *out_len);
-  EVP_PKEY *(*evp_derive_key_pair)(const EVP_PKEY_ALG *alg,
-                                   Span<const uint8_t> ikm);
 };
 
 struct evp_hpke_kdf_st {
@@ -389,8 +419,8 @@
   static const EVP_HPKE_KEM kKEM = {
       /*id=*/EVP_HPKE_DHKEM_X25519_HKDF_SHA256,
       // TODO(crbug.com/503758094): Expose this as an EVP_KEM.
-      /*evp_pkey_alg_func=*/nullptr,
       /*evp_kem_func=*/nullptr,
+      /*key_method=*/nullptr,
       /*public_key_len=*/X25519_PUBLIC_VALUE_LEN,
       /*private_key_len=*/X25519_PRIVATE_KEY_LEN,
       /*seed_len=*/X25519_PRIVATE_KEY_LEN,
@@ -402,12 +432,6 @@
       x25519_decap,
       x25519_auth_encap_with_seed,
       x25519_auth_decap,
-      // TODO(crbug.com/503758094): Implement this in terms of an EVP_KEM.
-      /*evp_deserialize_private_key=*/nullptr,
-      /*evp_serialize_private_key=*/nullptr,
-      /*evp_deserialize_public_key=*/nullptr,
-      /*evp_serialize_public_key=*/nullptr,
-      /*evp_derive_key_pair=*/nullptr,
   };
   return &kKEM;
 }
@@ -689,8 +713,8 @@
   static const EVP_HPKE_KEM kKEM = {
       /*id=*/EVP_HPKE_DHKEM_P256_HKDF_SHA256,
       // TODO(crbug.com/503758094): Expose this as an EVP_KEM.
-      /*evp_pkey_alg_func=*/nullptr,
       /*evp_kem_func=*/nullptr,
+      /*key_method=*/nullptr,
       /*public_key_len=*/P256_PUBLIC_KEY_LEN,
       /*private_key_len=*/P256_PRIVATE_KEY_LEN,
       /*seed_len=*/P256_SEED_LEN,
@@ -702,12 +726,6 @@
       p256_decap,
       p256_auth_encap_with_seed,
       p256_auth_decap,
-      // TODO(crbug.com/503758094): Implement this in terms of an EVP_KEM.
-      /*evp_deserialize_private_key=*/nullptr,
-      /*evp_serialize_private_key=*/nullptr,
-      /*evp_deserialize_public_key=*/nullptr,
-      /*evp_serialize_public_key=*/nullptr,
-      /*evp_derive_key_pair=*/nullptr,
   };
   return &kKEM;
 }
@@ -718,22 +736,35 @@
 #define XWING_SEED_LEN 64
 #define XWING_SHARED_KEY_LEN XWING_SHARED_SECRET_BYTES
 
-static EVP_PKEY *xwing_derive_key_pair(const EVP_PKEY_ALG *alg,
-                                       Span<const uint8_t> ikm) {
-  uint8_t seed[XWING_PRIVATE_KEY_BYTES];
-  hpke_shake256_labeled_derive(seed, ikm, hpke_kem_suite_id(EVP_HPKE_XWING),
+template <size_t SEED_BYTES>
+static EVP_PKEY *shake256_derive_key_pair_from_private_seed(
+    const EVP_PKEY_ALG *alg, uint16_t kem_suite_id, Span<const uint8_t> ikm) {
+  uint8_t seed[SEED_BYTES];
+  hpke_shake256_labeled_derive(seed, ikm, hpke_kem_suite_id(kem_suite_id),
                                "DeriveKeyPair", /*context=*/{});
   return EVP_PKEY_from_private_seed(alg, seed, sizeof(seed));
 }
 
+static constexpr HpkeKeyMethod kXwingKeyMethod = {
+    /*hpke_kem_id=*/EVP_HPKE_XWING,
+    /*public_key_len=*/XWING_PUBLIC_KEY_LEN,
+    /*private_key_len=*/XWING_PRIVATE_KEY_LEN,
+    /*alg_func=*/&EVP_pkey_xwing,
+    /*deserialize_private_key=*/&EVP_PKEY_from_private_seed,
+    /*serialize_private_key=*/&EVP_PKEY_get_private_seed,
+    /*deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
+    /*serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
+    /*derive_key_pair=*/
+    shake256_derive_key_pair_from_private_seed<XWING_PRIVATE_KEY_LEN>,
+};
 
 const EVP_HPKE_KEM *EVP_hpke_xwing() {
   static const EVP_HPKE_KEM kKEM = {
       /*id=*/EVP_HPKE_XWING,
-      /*evp_pkey_alg_func=*/&EVP_pkey_xwing,
       /*evp_kem_func=*/&EVP_kem_xwing,
-      /*public_key_len=*/XWING_PUBLIC_KEY_LEN,
-      /*private_key_len=*/XWING_PRIVATE_KEY_LEN,
+      /*key_method=*/&kXwingKeyMethod,
+      /*public_key_len=*/0,
+      /*private_key_len=*/0,
       /*seed_len=*/0,
       /*enc_len=*/0,
       /*init_key=*/nullptr,
@@ -743,32 +774,32 @@
       /*decap=*/nullptr,
       // X-Wing doesn't support authenticated encapsulation/decapsulation:
       // https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-08#name-use-in-hpke
-      /* auth_encap_with_seed= */ nullptr,
-      /* auth_decap= */ nullptr,
-      /*evp_deserialize_private_key=*/&EVP_PKEY_from_private_seed,
-      /*evp_serialize_private_key=*/&EVP_PKEY_get_private_seed,
-      /*evp_deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
-      /*evp_serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
-      /*evp_derive_key_pair=*/xwing_derive_key_pair,
+      /*auth_encap_with_seed=*/nullptr,
+      /*auth_decap=*/nullptr,
   };
   return &kKEM;
 }
 
-static EVP_PKEY *mlkem768_derive_key_pair(const EVP_PKEY_ALG *alg,
-                                          Span<const uint8_t> ikm) {
-  uint8_t seed[MLKEM_SEED_BYTES];
-  hpke_shake256_labeled_derive(seed, ikm, hpke_kem_suite_id(EVP_HPKE_MLKEM768),
-                               "DeriveKeyPair", /*context=*/{});
-  return EVP_PKEY_from_private_seed(alg, seed, sizeof(seed));
-}
+static constexpr HpkeKeyMethod kMlkem768KeyMethod = {
+    /*hpke_kem_id=*/EVP_HPKE_MLKEM768,
+    /*public_key_len=*/MLKEM768_PUBLIC_KEY_BYTES,
+    /*private_key_len=*/MLKEM_SEED_BYTES,
+    /*alg_func=*/&EVP_pkey_ml_kem_768,
+    /*deserialize_private_key=*/&EVP_PKEY_from_private_seed,
+    /*serialize_private_key=*/&EVP_PKEY_get_private_seed,
+    /*deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
+    /*serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
+    /*derive_key_pair=*/
+    shake256_derive_key_pair_from_private_seed<MLKEM_SEED_BYTES>,
+};
 
 const EVP_HPKE_KEM *EVP_hpke_mlkem768() {
   static const EVP_HPKE_KEM kKEM = {
       /*id=*/EVP_HPKE_MLKEM768,
-      /*evp_pkey_alg_func=*/&EVP_pkey_ml_kem_768,
       /*evp_kem_func=*/&EVP_kem_ml_kem_768,
-      /*public_key_len=*/MLKEM768_PUBLIC_KEY_BYTES,
-      /*private_key_len=*/MLKEM_SEED_BYTES,
+      /*key_method=*/&kMlkem768KeyMethod,
+      /*public_key_len=*/0,
+      /*private_key_len=*/0,
       /*seed_len=*/0,
       /*enc_len=*/0,
       /*init_key=*/nullptr,
@@ -780,30 +811,30 @@
       // https://datatracker.ietf.org/doc/draft-ietf-hpke-pq/01/
       /*auth_encap_with_seed=*/nullptr,
       /*auth_decap=*/nullptr,
-      /*evp_deserialize_private_key=*/&EVP_PKEY_from_private_seed,
-      /*evp_serialize_private_key=*/&EVP_PKEY_get_private_seed,
-      /*evp_deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
-      /*evp_serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
-      /*evp_derive_key_pair=*/mlkem768_derive_key_pair,
   };
   return &kKEM;
 }
 
-static EVP_PKEY *mlkem1024_derive_key_pair(const EVP_PKEY_ALG *alg,
-                                           Span<const uint8_t> ikm) {
-  uint8_t seed[MLKEM_SEED_BYTES];
-  hpke_shake256_labeled_derive(seed, ikm, hpke_kem_suite_id(EVP_HPKE_MLKEM1024),
-                               "DeriveKeyPair", /*context=*/{});
-  return EVP_PKEY_from_private_seed(alg, seed, sizeof(seed));
-}
+static constexpr HpkeKeyMethod kMlkem1024KeyMethod = {
+    /*hpke_kem_id=*/EVP_HPKE_MLKEM1024,
+    /*public_key_len=*/MLKEM1024_PUBLIC_KEY_BYTES,
+    /*private_key_len=*/MLKEM_SEED_BYTES,
+    /*alg_func=*/&EVP_pkey_ml_kem_1024,
+    /*deserialize_private_key=*/&EVP_PKEY_from_private_seed,
+    /*serialize_private_key=*/&EVP_PKEY_get_private_seed,
+    /*deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
+    /*serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
+    /*derive_key_pair=*/
+    shake256_derive_key_pair_from_private_seed<MLKEM_SEED_BYTES>,
+};
 
 const EVP_HPKE_KEM *EVP_hpke_mlkem1024() {
   static const EVP_HPKE_KEM kKEM = {
       /*id=*/EVP_HPKE_MLKEM1024,
-      /*evp_pkey_alg_func=*/&EVP_pkey_ml_kem_1024,
       /*evp_kem_func=*/&EVP_kem_ml_kem_1024,
-      /*public_key_len=*/MLKEM1024_PUBLIC_KEY_BYTES,
-      /*private_key_len=*/MLKEM_SEED_BYTES,
+      /*key_method=*/&kMlkem1024KeyMethod,
+      /*public_key_len=*/0,
+      /*private_key_len=*/0,
       /*seed_len=*/0,
       /*enc_len=*/0,
       /*init_key=*/nullptr,
@@ -815,11 +846,6 @@
       // https://datatracker.ietf.org/doc/draft-ietf-hpke-pq/01/
       /*auth_encap_with_seed=*/nullptr,
       /*auth_decap=*/nullptr,
-      /*evp_deserialize_private_key=*/&EVP_PKEY_from_private_seed,
-      /*evp_serialize_private_key=*/&EVP_PKEY_get_private_seed,
-      /*evp_deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
-      /*evp_serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
-      /*evp_derive_key_pair=*/mlkem1024_derive_key_pair,
   };
   return &kKEM;
 }
@@ -832,7 +858,7 @@
 // HPKE KEMs.
 
 bool uses_evp(const EVP_HPKE_KEM *kem) {
-  return kem->evp_pkey_alg_func != nullptr && kem->evp_kem_func != nullptr;
+  return kem->evp_kem_func != nullptr && kem->key_method != nullptr;
 }
 
 }  // namespace
@@ -840,10 +866,16 @@
 uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem) { return kem->id; }
 
 size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem) {
+  if (uses_evp(kem)) {
+    return kem->key_method->public_key_len;
+  }
   return kem->public_key_len;
 }
 
 size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem) {
+  if (uses_evp(kem)) {
+    return kem->key_method->private_key_len;
+  }
   return kem->private_key_len;
 }
 
@@ -923,8 +955,8 @@
   // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
   // HPKE KEMs.
   if (uses_evp(kem)) {
-    UniquePtr<EVP_PKEY> pkey(kem->evp_deserialize_private_key(
-        kem->evp_pkey_alg_func(), priv_key, priv_key_len));
+    UniquePtr<EVP_PKEY> pkey(kem->key_method->deserialize_private_key(
+        kem->key_method->alg_func(), priv_key, priv_key_len));
     if (pkey == nullptr) {
       key->kem = nullptr;
       return 0;
@@ -946,7 +978,7 @@
   // HPKE KEMs.
   if (uses_evp(kem)) {
     UniquePtr<EVP_PKEY> pkey(
-        EVP_PKEY_generate_from_alg(kem->evp_pkey_alg_func()));
+        EVP_PKEY_generate_from_alg(kem->key_method->alg_func()));
     if (pkey == nullptr) {
       key->kem = nullptr;
       return 0;
@@ -968,8 +1000,8 @@
   // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
   // HPKE KEMs.
   if (uses_evp(kem)) {
-    UniquePtr<EVP_PKEY> pkey(
-        kem->evp_derive_key_pair(kem->evp_pkey_alg_func(), Span(ikm, ikm_len)));
+    UniquePtr<EVP_PKEY> pkey(kem->key_method->derive_key_pair(
+        kem->key_method->alg_func(), kem->id, Span(ikm, ikm_len)));
     if (pkey == nullptr) {
       key->kem = nullptr;
       return 0;
@@ -990,7 +1022,7 @@
 
 int EVP_HPKE_KEY_public_key(const EVP_HPKE_KEY *key, uint8_t *out,
                             size_t *out_len, size_t max_out) {
-  if (max_out < key->kem->public_key_len) {
+  if (max_out < EVP_HPKE_KEM_public_key_len(key->kem)) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
     return 0;
   }
@@ -998,7 +1030,7 @@
   // HPKE KEMs.
   if (uses_evp(key->kem)) {
     *out_len = max_out;
-    return key->kem->evp_serialize_public_key(key->pkey, out, out_len);
+    return key->kem->key_method->serialize_public_key(key->pkey, out, out_len);
   }
   OPENSSL_memcpy(out, key->public_key, key->kem->public_key_len);
   *out_len = key->kem->public_key_len;
@@ -1007,7 +1039,7 @@
 
 int EVP_HPKE_KEY_private_key(const EVP_HPKE_KEY *key, uint8_t *out,
                              size_t *out_len, size_t max_out) {
-  if (max_out < key->kem->private_key_len) {
+  if (max_out < EVP_HPKE_KEM_private_key_len(key->kem)) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
     return 0;
   }
@@ -1015,7 +1047,7 @@
   // HPKE KEMs.
   if (uses_evp(key->kem)) {
     *out_len = max_out;
-    return key->kem->evp_serialize_private_key(key->pkey, out, out_len);
+    return key->kem->key_method->serialize_private_key(key->pkey, out, out_len);
   }
   OPENSSL_memcpy(out, key->private_key, key->kem->private_key_len);
   *out_len = key->kem->private_key_len;
@@ -1215,8 +1247,8 @@
     shared_secret_len = EVP_KEM_secret_len(evp_kem);
     assert(size_t{MAX_SHARED_SECRET_LEN} >= shared_secret_len);
 
-    UniquePtr<EVP_PKEY> peer_pubkey(kem->evp_deserialize_public_key(
-        kem->evp_pkey_alg_func(), peer_public_key, peer_public_key_len));
+    UniquePtr<EVP_PKEY> peer_pubkey(kem->key_method->deserialize_public_key(
+        kem->key_method->alg_func(), peer_public_key, peer_public_key_len));
     if (peer_pubkey == nullptr ||
         !EVP_KEM_encap(evp_kem, out_enc, *out_enc_len, shared_secret,
                        shared_secret_len, peer_pubkey.get()) ||
@@ -1261,8 +1293,8 @@
     shared_secret_len = EVP_KEM_secret_len(evp_kem);
     assert(size_t{MAX_SHARED_SECRET_LEN} >= shared_secret_len);
 
-    UniquePtr<EVP_PKEY> peer_pubkey(kem->evp_deserialize_public_key(
-        kem->evp_pkey_alg_func(), peer_public_key, peer_public_key_len));
+    UniquePtr<EVP_PKEY> peer_pubkey(kem->key_method->deserialize_public_key(
+        kem->key_method->alg_func(), peer_public_key, peer_public_key_len));
     if (peer_pubkey == nullptr ||
         !EVP_KEM_encap_external_entropy_for_testing(
             evp_kem, out_enc, *out_enc_len, shared_secret, shared_secret_len,
@@ -1331,8 +1363,8 @@
     decap_ok = EVP_KEM_decap(evp_kem, shared_secret, shared_secret_len, enc,
                              enc_len, decap_key);
   } else {
-    decap_ok = key->kem->decap(key, shared_secret, &shared_secret_len, enc,
-                               enc_len);
+    decap_ok =
+        key->kem->decap(key, shared_secret, &shared_secret_len, enc, enc_len);
   }
 
   return decap_ok && EVP_HPKE_CTX_setup_recipient_with_shared_secret(
diff --git a/gen/sources.bzl b/gen/sources.bzl
index 70b57a7..e8139a7 100644
--- a/gen/sources.bzl
+++ b/gen/sources.bzl
@@ -3008,6 +3008,7 @@
     "include/openssl/srtp.h",
     "include/openssl/ssl.h",
     "include/openssl/ssl3.h",
+    "include/openssl/ssl_deprecated.h",
     "include/openssl/tls1.h",
 ]
 
diff --git a/gen/sources.cmake b/gen/sources.cmake
index 7eec173..a860125 100644
--- a/gen/sources.cmake
+++ b/gen/sources.cmake
@@ -3080,6 +3080,7 @@
   include/openssl/srtp.h
   include/openssl/ssl.h
   include/openssl/ssl3.h
+  include/openssl/ssl_deprecated.h
   include/openssl/tls1.h
 )
 
diff --git a/gen/sources.gni b/gen/sources.gni
index 9e3095b..4116102 100644
--- a/gen/sources.gni
+++ b/gen/sources.gni
@@ -3008,6 +3008,7 @@
   "include/openssl/srtp.h",
   "include/openssl/ssl.h",
   "include/openssl/ssl3.h",
+  "include/openssl/ssl_deprecated.h",
   "include/openssl/tls1.h",
 ]
 
diff --git a/gen/sources.json b/gen/sources.json
index ddbbd39..8c909de 100644
--- a/gen/sources.json
+++ b/gen/sources.json
@@ -2993,6 +2993,7 @@
       "include/openssl/srtp.h",
       "include/openssl/ssl.h",
       "include/openssl/ssl3.h",
+      "include/openssl/ssl_deprecated.h",
       "include/openssl/tls1.h"
     ],
     "internal_hdrs": [
diff --git a/gen/sources.mk b/gen/sources.mk
index b87e605..742a62b 100644
--- a/gen/sources.mk
+++ b/gen/sources.mk
@@ -2973,6 +2973,7 @@
   include/openssl/srtp.h \
   include/openssl/ssl.h \
   include/openssl/ssl3.h \
+  include/openssl/ssl_deprecated.h \
   include/openssl/tls1.h
 
 boringssl_ssl_internal_headers := \
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 9bf83f7..cc6c861 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -5716,747 +5716,6 @@
 OPENSSL_EXPORT int SSL_parse_client_hello(const SSL *ssl, SSL_CLIENT_HELLO *out,
                                           const uint8_t *in, size_t len);
 
-
-// Deprecated functions.
-
-// SSL_library_init returns one.
-OPENSSL_EXPORT int SSL_library_init(void);
-
-// SSL_CIPHER_description writes a description of `cipher` into `buf` and
-// returns `buf`. If `buf` is NULL, it returns a newly allocated string, to be
-// freed with `OPENSSL_free`, or NULL on error.
-//
-// The description includes a trailing newline and has the form:
-// AES128-SHA              Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA1
-//
-// Consider `SSL_CIPHER_standard_name` or `SSL_CIPHER_get_name` instead.
-OPENSSL_EXPORT const char *SSL_CIPHER_description(const SSL_CIPHER *cipher,
-                                                  char *buf, int len);
-
-// SSL_CIPHER_get_version returns the string "TLSv1/SSLv3".
-OPENSSL_EXPORT const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher);
-
-// SSL_CIPHER_get_id returns `cipher`'s IANA-assigned number, OR-d with
-// 0x03000000. This is part of OpenSSL's SSL 2.0 legacy. SSL 2.0 has long since
-// been removed from BoringSSL. Use `SSL_CIPHER_get_protocol_id` instead.
-OPENSSL_EXPORT uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher);
-
-// SSL_CIPHER_get_name returns the OpenSSL name of `cipher`. For example,
-// "ECDHE-RSA-AES128-GCM-SHA256". Callers are recommended to use
-// `SSL_CIPHER_standard_name` instead.
-OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher);
-
-typedef void COMP_METHOD;
-typedef struct ssl_comp_st SSL_COMP;
-
-// SSL_COMP_get_compression_methods returns NULL.
-OPENSSL_EXPORT STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
-
-// SSL_COMP_add_compression_method returns one.
-OPENSSL_EXPORT int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);
-
-// SSL_COMP_get_name returns NULL.
-OPENSSL_EXPORT const char *SSL_COMP_get_name(const COMP_METHOD *comp);
-
-// SSL_COMP_get0_name returns the `name` member of `comp`.
-OPENSSL_EXPORT const char *SSL_COMP_get0_name(const SSL_COMP *comp);
-
-// SSL_COMP_get_id returns the `id` member of `comp`.
-OPENSSL_EXPORT int SSL_COMP_get_id(const SSL_COMP *comp);
-
-// SSL_COMP_free_compression_methods does nothing.
-OPENSSL_EXPORT void SSL_COMP_free_compression_methods(void);
-
-// SSLv23_method calls `TLS_method`.
-OPENSSL_EXPORT const SSL_METHOD *SSLv23_method(void);
-
-// These version-specific methods behave exactly like `TLS_method` and
-// `DTLS_method` except they also call `SSL_CTX_set_min_proto_version` and
-// `SSL_CTX_set_max_proto_version` to lock connections to that protocol
-// version.
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLSv1_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_method(void);
-
-// These client- and server-specific methods call their corresponding generic
-// methods.
-OPENSSL_EXPORT const SSL_METHOD *TLS_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLS_client_method(void);
-OPENSSL_EXPORT const SSL_METHOD *SSLv23_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *SSLv23_client_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_client_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_client_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_client_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLS_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLS_client_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLSv1_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLSv1_client_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_server_method(void);
-OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_client_method(void);
-
-// SSL_clear resets `ssl` to allow another connection and returns one on success
-// or zero on failure. It returns most configuration state but releases memory
-// associated with the current connection.
-//
-// Free `ssl` and create a new one instead.
-OPENSSL_EXPORT int SSL_clear(SSL *ssl);
-
-// SSL_CTX_set_tmp_rsa_callback does nothing.
-OPENSSL_EXPORT void SSL_CTX_set_tmp_rsa_callback(
-    SSL_CTX *ctx, RSA *(*cb)(SSL *ssl, int is_export, int keylength));
-
-// SSL_set_tmp_rsa_callback does nothing.
-OPENSSL_EXPORT void SSL_set_tmp_rsa_callback(SSL *ssl,
-                                             RSA *(*cb)(SSL *ssl, int is_export,
-                                                        int keylength));
-
-// SSL_CTX_sess_connect returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_connect(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_connect_good returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_connect_good(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_connect_renegotiate returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_accept returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_accept(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_accept_renegotiate returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_accept_renegotiate(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_accept_good returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_accept_good(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_hits returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_hits(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_cb_hits returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_cb_hits(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_misses returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_misses(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_timeouts returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_timeouts(const SSL_CTX *ctx);
-
-// SSL_CTX_sess_cache_full returns zero.
-OPENSSL_EXPORT int SSL_CTX_sess_cache_full(const SSL_CTX *ctx);
-
-// SSL_cutthrough_complete calls `SSL_in_false_start`.
-OPENSSL_EXPORT int SSL_cutthrough_complete(const SSL *ssl);
-
-// SSL_num_renegotiations calls `SSL_total_renegotiations`.
-OPENSSL_EXPORT int SSL_num_renegotiations(const SSL *ssl);
-
-// SSL_CTX_need_tmp_RSA returns zero.
-OPENSSL_EXPORT int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx);
-
-// SSL_need_tmp_RSA returns zero.
-OPENSSL_EXPORT int SSL_need_tmp_RSA(const SSL *ssl);
-
-// SSL_CTX_set_tmp_rsa returns one.
-OPENSSL_EXPORT int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa);
-
-// SSL_set_tmp_rsa returns one.
-OPENSSL_EXPORT int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa);
-
-// SSL_CTX_get_read_ahead returns zero.
-OPENSSL_EXPORT int SSL_CTX_get_read_ahead(const SSL_CTX *ctx);
-
-// SSL_CTX_set_read_ahead returns one.
-OPENSSL_EXPORT int SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes);
-
-// SSL_get_read_ahead returns zero.
-OPENSSL_EXPORT int SSL_get_read_ahead(const SSL *ssl);
-
-// SSL_set_read_ahead returns one.
-OPENSSL_EXPORT int SSL_set_read_ahead(SSL *ssl, int yes);
-
-// SSL_set_state does nothing.
-OPENSSL_EXPORT void SSL_set_state(SSL *ssl, int state);
-
-// SSL_get_shared_ciphers writes an empty string to `buf` and returns a
-// pointer to `buf`, or NULL if `len` is less than or equal to zero.
-OPENSSL_EXPORT char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len);
-
-// SSL_get_shared_sigalgs returns zero.
-OPENSSL_EXPORT int SSL_get_shared_sigalgs(SSL *ssl, int idx, int *psign,
-                                          int *phash, int *psignandhash,
-                                          uint8_t *rsig, uint8_t *rhash);
-
-// SSL_MODE_HANDSHAKE_CUTTHROUGH is the same as SSL_MODE_ENABLE_FALSE_START.
-#define SSL_MODE_HANDSHAKE_CUTTHROUGH SSL_MODE_ENABLE_FALSE_START
-
-// i2d_SSL_SESSION serializes `in`, as described in `i2d_SAMPLE`.
-//
-// Use `SSL_SESSION_to_bytes` instead.
-OPENSSL_EXPORT int i2d_SSL_SESSION(const SSL_SESSION *in, uint8_t **pp);
-
-// d2i_SSL_SESSION parses a serialized session from the `len` bytes pointed to
-// by `*inp`, as described in `d2i_SAMPLE`.
-//
-// Use `SSL_SESSION_from_bytes` instead.
-OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **out,
-                                            const uint8_t **inp, long len);
-
-// i2d_SSL_SESSION_bio serializes `session` and writes the result to `bio`. It
-// returns the number of bytes written on success and <= 0 on error.
-OPENSSL_EXPORT int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session);
-
-// d2i_SSL_SESSION_bio reads a serialized `SSL_SESSION` from `bio` and returns a
-// newly-allocated `SSL_SESSION` or NULL on error. If `out` is not NULL, it also
-// frees `*out` and sets `*out` to the new `SSL_SESSION`.
-OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out);
-
-// ERR_load_SSL_strings does nothing.
-OPENSSL_EXPORT void ERR_load_SSL_strings(void);
-
-// SSL_load_error_strings does nothing.
-OPENSSL_EXPORT void SSL_load_error_strings(void);
-
-// SSL_CTX_set_tlsext_use_srtp calls `SSL_CTX_set_srtp_profiles`. It returns
-// zero on success and one on failure.
-//
-// WARNING: this function is dangerous because it breaks the usual return value
-// convention. Use `SSL_CTX_set_srtp_profiles` instead.
-OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,
-                                               const char *profiles);
-
-// SSL_set_tlsext_use_srtp calls `SSL_set_srtp_profiles`. It returns zero on
-// success and one on failure.
-//
-// WARNING: this function is dangerous because it breaks the usual return value
-// convention. Use `SSL_set_srtp_profiles` instead.
-OPENSSL_EXPORT int SSL_set_tlsext_use_srtp(SSL *ssl, const char *profiles);
-
-// SSL_get_current_compression returns NULL.
-OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_compression(SSL *ssl);
-
-// SSL_get_current_expansion returns NULL.
-OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_expansion(SSL *ssl);
-
-// SSL_get_server_tmp_key returns zero.
-OPENSSL_EXPORT int SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key);
-
-// SSL_get_peer_tmp_key returns zero.
-OPENSSL_EXPORT int SSL_get_peer_tmp_key(SSL *ssl, EVP_PKEY **out_key);
-
-// SSL_CTX_set_tmp_dh returns 1.
-OPENSSL_EXPORT int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh);
-
-// SSL_set_tmp_dh returns 1.
-OPENSSL_EXPORT int SSL_set_tmp_dh(SSL *ssl, const DH *dh);
-
-// SSL_CTX_set_tmp_dh_callback does nothing.
-OPENSSL_EXPORT void SSL_CTX_set_tmp_dh_callback(
-    SSL_CTX *ctx, DH *(*cb)(SSL *ssl, int is_export, int keylength));
-
-// SSL_set_tmp_dh_callback does nothing.
-OPENSSL_EXPORT void SSL_set_tmp_dh_callback(SSL *ssl,
-                                            DH *(*cb)(SSL *ssl, int is_export,
-                                                      int keylength));
-
-// SSL_CTX_set1_sigalgs takes `num_values` ints and interprets them as pairs
-// where the first is the nid of a hash function and the second is an
-// `EVP_PKEY_*` value. It configures the signature algorithm preferences for
-// `ctx` based on them and returns one on success or zero on error.
-//
-// This API is compatible with OpenSSL. However, BoringSSL-specific code should
-// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
-// more convenient to codesearch for specific algorithm values.
-OPENSSL_EXPORT int SSL_CTX_set1_sigalgs(SSL_CTX *ctx, const int *values,
-                                        size_t num_values);
-
-// SSL_set1_sigalgs takes `num_values` ints and interprets them as pairs where
-// the first is the nid of a hash function and the second is an `EVP_PKEY_*`
-// value. It configures the signature algorithm preferences for `ssl` based on
-// them and returns one on success or zero on error.
-//
-// This API is compatible with OpenSSL. However, BoringSSL-specific code should
-// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
-// more convenient to codesearch for specific algorithm values.
-OPENSSL_EXPORT int SSL_set1_sigalgs(SSL *ssl, const int *values,
-                                    size_t num_values);
-
-// SSL_CTX_set1_sigalgs_list takes a textual specification of a set of signature
-// algorithms and configures them on `ctx`. It returns one on success and zero
-// on error. See
-// https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set1_sigalgs_list.html for
-// a description of the text format. Also note that TLS 1.3 names (e.g.
-// "rsa_pkcs1_md5_sha1") can also be used (as in OpenSSL, although OpenSSL
-// doesn't document that).
-//
-// This API is compatible with OpenSSL. However, BoringSSL-specific code should
-// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
-// more convenient to codesearch for specific algorithm values.
-OPENSSL_EXPORT int SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str);
-
-// SSL_set1_sigalgs_list takes a textual specification of a set of signature
-// algorithms and configures them on `ssl`. It returns one on success and zero
-// on error. See
-// https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set1_sigalgs_list.html for
-// a description of the text format. Also note that TLS 1.3 names (e.g.
-// "rsa_pkcs1_md5_sha1") can also be used (as in OpenSSL, although OpenSSL
-// doesn't document that).
-//
-// This API is compatible with OpenSSL. However, BoringSSL-specific code should
-// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
-// more convenient to codesearch for specific algorithm values.
-OPENSSL_EXPORT int SSL_set1_sigalgs_list(SSL *ssl, const char *str);
-
-#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg)))
-#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
-#define SSL_SESSION_set_app_data(s, a) \
-  (SSL_SESSION_set_ex_data(s, 0, (char *)(a)))
-#define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s, 0))
-#define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx, 0))
-#define SSL_CTX_set_app_data(ctx, arg) \
-  (SSL_CTX_set_ex_data(ctx, 0, (char *)(arg)))
-
-#define OpenSSL_add_ssl_algorithms() SSL_library_init()
-#define SSLeay_add_ssl_algorithms() SSL_library_init()
-
-#define SSL_get_cipher(ssl) SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))
-#define SSL_get_cipher_bits(ssl, out_alg_bits) \
-  SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), out_alg_bits)
-#define SSL_get_cipher_version(ssl) \
-  SSL_CIPHER_get_version(SSL_get_current_cipher(ssl))
-#define SSL_get_cipher_name(ssl) \
-  SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))
-#define SSL_get_time(session) SSL_SESSION_get_time(session)
-#define SSL_set_time(session, time) SSL_SESSION_set_time((session), (time))
-#define SSL_get_timeout(session) SSL_SESSION_get_timeout(session)
-#define SSL_set_timeout(session, timeout) \
-  SSL_SESSION_set_timeout((session), (timeout))
-
-struct ssl_comp_st {
-  int id;
-  const char *name;
-  char *method;
-};
-
-DEFINE_STACK_OF(SSL_COMP)
-
-// The following flags do nothing and are included only to make it easier to
-// compile code with BoringSSL.
-#define SSL_MODE_AUTO_RETRY 0
-#define SSL_MODE_RELEASE_BUFFERS 0
-#define SSL_MODE_SEND_CLIENTHELLO_TIME 0
-#define SSL_MODE_SEND_SERVERHELLO_TIME 0
-#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0
-#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0
-#define SSL_OP_EPHEMERAL_RSA 0
-#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0
-#define SSL_OP_MICROSOFT_SESS_ID_BUG 0
-#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0
-#define SSL_OP_NETSCAPE_CA_DN_BUG 0
-#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0
-#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0
-#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0
-#define SSL_OP_NO_COMPRESSION 0
-#define SSL_OP_NO_RENEGOTIATION 0  // ssl_renegotiate_never is the default
-#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
-#define SSL_OP_NO_SSLv2 0
-#define SSL_OP_NO_SSLv3 0
-#define SSL_OP_PKCS1_CHECK_1 0
-#define SSL_OP_PKCS1_CHECK_2 0
-#define SSL_OP_SINGLE_DH_USE 0
-#define SSL_OP_SINGLE_ECDH_USE 0
-#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0
-#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0
-#define SSL_OP_TLS_BLOCK_PADDING_BUG 0
-#define SSL_OP_TLS_D5_BUG 0
-#define SSL_OP_TLS_ROLLBACK_BUG 0
-#define SSL_VERIFY_CLIENT_ONCE 0
-
-// SSL_cache_hit calls `SSL_session_reused`.
-OPENSSL_EXPORT int SSL_cache_hit(SSL *ssl);
-
-// SSL_get_default_timeout returns `SSL_DEFAULT_SESSION_TIMEOUT`.
-OPENSSL_EXPORT long SSL_get_default_timeout(const SSL *ssl);
-
-// SSL_get_version returns a string describing the TLS version used by `ssl`.
-// For example, "TLSv1.2" or "DTLSv1".
-OPENSSL_EXPORT const char *SSL_get_version(const SSL *ssl);
-
-// SSL_get_all_version_names outputs a list of possible strings
-// `SSL_get_version` may return in this version of BoringSSL. It writes at most
-// `max_out` entries to `out` and returns the total number it would have
-// written, if `max_out` had been large enough. `max_out` may be initially set
-// to zero to size the output.
-//
-// This function is only intended to help initialize tables in callers that want
-// possible strings pre-declared. This list would not be suitable to set a list
-// of supported features. It is in no particular order, and may contain
-// placeholder, experimental, or deprecated values that do not apply to every
-// caller. Future versions of BoringSSL may also return strings not in this
-// list, so this does not apply if, say, sending strings across services.
-OPENSSL_EXPORT size_t SSL_get_all_version_names(const char **out,
-                                                size_t max_out);
-
-// SSL_get_cipher_list returns the name of the `n`th cipher in the output of
-// `SSL_get_ciphers` or NULL if out of range. Use `SSL_get_ciphers` instead.
-OPENSSL_EXPORT const char *SSL_get_cipher_list(const SSL *ssl, int n);
-
-// SSL_CTX_set_client_cert_cb sets a callback which is called on the client if
-// the server requests a client certificate and none is configured. On success,
-// the callback should return one and set `*out_x509` to `*out_pkey` to a leaf
-// certificate and private key, respectively, passing ownership. It should
-// return zero to send no certificate and -1 to fail or pause the handshake. If
-// the handshake is paused, `SSL_get_error` will return
-// `SSL_ERROR_WANT_X509_LOOKUP`.
-//
-// The callback may call `SSL_get0_certificate_types` and
-// `SSL_get_client_CA_list` for information on the server's certificate request.
-//
-// Use `SSL_CTX_set_cert_cb` instead. Configuring intermediate certificates with
-// this function is confusing. This callback may not be registered concurrently
-// with `SSL_CTX_set_cert_cb` or `SSL_set_cert_cb`.
-OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
-    SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey));
-
-#define SSL_NOTHING SSL_ERROR_NONE
-#define SSL_WRITING SSL_ERROR_WANT_WRITE
-#define SSL_READING SSL_ERROR_WANT_READ
-
-// SSL_want returns one of the above values to determine what the most recent
-// operation on `ssl` was blocked on. Use `SSL_get_error` instead.
-OPENSSL_EXPORT int SSL_want(const SSL *ssl);
-
-#define SSL_want_read(ssl) (SSL_want(ssl) == SSL_READING)
-#define SSL_want_write(ssl) (SSL_want(ssl) == SSL_WRITING)
-
-// SSL_get_finished writes up to `count` bytes of the Finished message sent by
-// `ssl` to `buf`. It returns the total untruncated length or zero if none has
-// been sent yet. At TLS 1.3 and later, it returns zero.
-//
-// Use `SSL_get_tls_unique` instead.
-OPENSSL_EXPORT size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count);
-
-// SSL_get_peer_finished writes up to `count` bytes of the Finished message
-// received from `ssl`'s peer to `buf`. It returns the total untruncated length
-// or zero if none has been received yet. At TLS 1.3 and later, it returns
-// zero.
-//
-// Use `SSL_get_tls_unique` instead.
-OPENSSL_EXPORT size_t SSL_get_peer_finished(const SSL *ssl, void *buf,
-                                            size_t count);
-
-// SSL_alert_type_string returns "!". Use `SSL_alert_type_string_long`
-// instead.
-OPENSSL_EXPORT const char *SSL_alert_type_string(int value);
-
-// SSL_alert_desc_string returns "!!". Use `SSL_alert_desc_string_long`
-// instead.
-OPENSSL_EXPORT const char *SSL_alert_desc_string(int value);
-
-// SSL_state_string returns "!!!!!!". Use `SSL_state_string_long` for a more
-// intelligible string.
-OPENSSL_EXPORT const char *SSL_state_string(const SSL *ssl);
-
-// SSL_TXT_* expand to strings.
-#define SSL_TXT_MEDIUM "MEDIUM"
-#define SSL_TXT_HIGH "HIGH"
-#define SSL_TXT_FIPS "FIPS"
-#define SSL_TXT_kRSA "kRSA"
-#define SSL_TXT_kDHE "kDHE"
-#define SSL_TXT_kEDH "kEDH"
-#define SSL_TXT_kECDHE "kECDHE"
-#define SSL_TXT_kEECDH "kEECDH"
-#define SSL_TXT_kPSK "kPSK"
-#define SSL_TXT_aRSA "aRSA"
-#define SSL_TXT_aECDSA "aECDSA"
-#define SSL_TXT_aPSK "aPSK"
-#define SSL_TXT_DH "DH"
-#define SSL_TXT_DHE "DHE"
-#define SSL_TXT_EDH "EDH"
-#define SSL_TXT_RSA "RSA"
-#define SSL_TXT_ECDH "ECDH"
-#define SSL_TXT_ECDHE "ECDHE"
-#define SSL_TXT_EECDH "EECDH"
-#define SSL_TXT_ECDSA "ECDSA"
-#define SSL_TXT_PSK "PSK"
-#define SSL_TXT_3DES "3DES"
-#define SSL_TXT_RC4 "RC4"
-#define SSL_TXT_AES128 "AES128"
-#define SSL_TXT_AES256 "AES256"
-#define SSL_TXT_AES "AES"
-#define SSL_TXT_AES_GCM "AESGCM"
-#define SSL_TXT_CHACHA20 "CHACHA20"
-#define SSL_TXT_MD5 "MD5"
-#define SSL_TXT_SHA1 "SHA1"
-#define SSL_TXT_SHA "SHA"
-#define SSL_TXT_SHA256 "SHA256"
-#define SSL_TXT_SHA384 "SHA384"
-#define SSL_TXT_SSLV3 "SSLv3"
-#define SSL_TXT_TLSV1 "TLSv1"
-#define SSL_TXT_TLSV1_1 "TLSv1.1"
-#define SSL_TXT_TLSV1_2 "TLSv1.2"
-#define SSL_TXT_TLSV1_3 "TLSv1.3"
-#define SSL_TXT_ALL "ALL"
-#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
-
-typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
-
-// SSL_state returns `SSL_ST_INIT` if a handshake is in progress and `SSL_ST_OK`
-// otherwise.
-//
-// Use `SSL_is_init` instead.
-OPENSSL_EXPORT int SSL_state(const SSL *ssl);
-
-#define SSL_get_state(ssl) SSL_state(ssl)
-
-// SSL_set_shutdown causes `ssl` to behave as if the shutdown bitmask (see
-// `SSL_get_shutdown`) were `mode`. This may be used to skip sending or
-// receiving close_notify in `SSL_shutdown` by causing the implementation to
-// believe the events already happened.
-//
-// It is an error to use `SSL_set_shutdown` to unset a bit that has already been
-// set. Doing so will trigger an `assert` in debug builds and otherwise be
-// ignored.
-//
-// Use `SSL_CTX_set_quiet_shutdown` instead.
-OPENSSL_EXPORT void SSL_set_shutdown(SSL *ssl, int mode);
-
-// SSL_CTX_set_tmp_ecdh calls `SSL_CTX_set1_groups` with a one-element list
-// containing `ec_key`'s curve. The remainder of `ec_key` is ignored.
-OPENSSL_EXPORT int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key);
-
-// SSL_set_tmp_ecdh calls `SSL_set1_groups` with a one-element list containing
-// `ec_key`'s curve. The remainder of `ec_key` is ignored.
-OPENSSL_EXPORT int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key);
-
-#if !defined(OPENSSL_NO_FILESYSTEM)
-// SSL_add_dir_cert_subjects_to_stack lists files in directory `dir`. It calls
-// `SSL_add_file_cert_subjects_to_stack` on each file and returns one on success
-// or zero on error. This function is only available from the libdecrepit
-// library.
-OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
-                                                      const char *dir);
-#endif
-
-// SSL_CTX_enable_tls_channel_id calls `SSL_CTX_set_tls_channel_id_enabled`.
-OPENSSL_EXPORT int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx);
-
-// SSL_enable_tls_channel_id calls `SSL_set_tls_channel_id_enabled`.
-OPENSSL_EXPORT int SSL_enable_tls_channel_id(SSL *ssl);
-
-// BIO_f_ssl returns a `BIO_METHOD` that can wrap an `SSL*` in a `BIO*`. Note
-// that this has quite different behaviour from the version in OpenSSL (notably
-// that it doesn't try to auto renegotiate).
-//
-// IMPORTANT: if you are not curl, don't use this.
-OPENSSL_EXPORT const BIO_METHOD *BIO_f_ssl(void);
-
-// BIO_set_ssl sets `ssl` as the underlying connection for `bio`, which must
-// have been created using `BIO_f_ssl`. If `take_owership` is true, `bio` will
-// call `SSL_free` on `ssl` when closed. It returns one on success or something
-// other than one on error.
-OPENSSL_EXPORT long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership);
-
-// SSL_CTX_set_ecdh_auto returns one.
-#define SSL_CTX_set_ecdh_auto(ctx, onoff) 1
-
-// SSL_set_ecdh_auto returns one.
-#define SSL_set_ecdh_auto(ssl, onoff) 1
-
-// SSL_get_session returns a non-owning pointer to `ssl`'s session. For
-// historical reasons, which session it returns depends on `ssl`'s state.
-//
-// Prior to the start of the initial handshake, it returns the session the
-// caller set with `SSL_set_session`. After the initial handshake has finished
-// and if no additional handshakes are in progress, it returns the currently
-// active session. Its behavior is undefined while a handshake is in progress.
-//
-// If trying to add new sessions to an external session cache, use
-// `SSL_CTX_sess_set_new_cb` instead. In particular, using the callback is
-// required as of TLS 1.3. For compatibility, this function will return an
-// unresumable session which may be cached, but will never be resumed.
-//
-// If querying properties of the connection, use APIs on the `SSL` object.
-OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl);
-
-// SSL_get0_session is an alias for `SSL_get_session`.
-#define SSL_get0_session SSL_get_session
-
-// SSL_get1_session acts like `SSL_get_session` but returns a new reference to
-// the session.
-OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
-
-#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0
-#define OPENSSL_INIT_LOAD_SSL_STRINGS 0
-#define OPENSSL_INIT_SSL_DEFAULT 0
-
-// OPENSSL_init_ssl returns one.
-OPENSSL_EXPORT int OPENSSL_init_ssl(uint64_t opts,
-                                    const OPENSSL_INIT_SETTINGS *settings);
-
-// The following constants are legacy aliases for RSA-PSS with rsaEncryption
-// keys. Use the new names instead.
-#define SSL_SIGN_RSA_PSS_SHA256 SSL_SIGN_RSA_PSS_RSAE_SHA256
-#define SSL_SIGN_RSA_PSS_SHA384 SSL_SIGN_RSA_PSS_RSAE_SHA384
-#define SSL_SIGN_RSA_PSS_SHA512 SSL_SIGN_RSA_PSS_RSAE_SHA512
-
-// SSL_set_tlsext_status_type configures a client to request OCSP stapling if
-// `type` is `TLSEXT_STATUSTYPE_ocsp` and disables it otherwise. It returns one
-// on success and zero if handshake configuration has already been shed.
-//
-// Use `SSL_enable_ocsp_stapling` instead.
-OPENSSL_EXPORT int SSL_set_tlsext_status_type(SSL *ssl, int type);
-
-// SSL_get_tlsext_status_type returns `TLSEXT_STATUSTYPE_ocsp` if the client
-// requested OCSP stapling and `TLSEXT_STATUSTYPE_nothing` otherwise. On the
-// client, this reflects whether OCSP stapling was enabled via, e.g.,
-// `SSL_set_tlsext_status_type`. On the server, this is determined during the
-// handshake. It may be queried in callbacks set by `SSL_CTX_set_cert_cb`. The
-// result is undefined after the handshake completes.
-OPENSSL_EXPORT int SSL_get_tlsext_status_type(const SSL *ssl);
-
-// SSL_set_tlsext_status_ocsp_resp sets the OCSP response. It returns one on
-// success and zero on error. On success, `ssl` takes ownership of `resp`, which
-// must have been allocated by `OPENSSL_malloc`.
-//
-// Use `SSL_set_ocsp_response` instead.
-OPENSSL_EXPORT int SSL_set_tlsext_status_ocsp_resp(SSL *ssl, uint8_t *resp,
-                                                   size_t resp_len);
-
-// SSL_get_tlsext_status_ocsp_resp sets `*out` to point to the OCSP response
-// from the server. It returns the length of the response. If there was no
-// response, it sets `*out` to NULL and returns zero.
-//
-// Use `SSL_get0_ocsp_response` instead.
-//
-// WARNING: the returned data is not guaranteed to be well formed.
-OPENSSL_EXPORT size_t SSL_get_tlsext_status_ocsp_resp(const SSL *ssl,
-                                                      const uint8_t **out);
-
-// SSL_CTX_set_tlsext_status_cb configures the legacy OpenSSL OCSP callback and
-// returns one. Though the type signature is the same, this callback has
-// different behavior for client and server connections:
-//
-// For clients, the callback is called after certificate verification. It should
-// return one for success, zero for a bad OCSP response, and a negative number
-// for internal error. Instead, handle this as part of certificate verification.
-// (Historically, OpenSSL verified certificates just before parsing stapled OCSP
-// responses, but BoringSSL fixes this ordering. All server credentials are
-// available during verification.)
-//
-// Do not use this callback as a server. It is provided for compatibility
-// purposes only. For servers, it is called to configure server credentials. It
-// should return `SSL_TLSEXT_ERR_OK` on success, `SSL_TLSEXT_ERR_NOACK` to
-// ignore OCSP requests, or `SSL_TLSEXT_ERR_ALERT_FATAL` on error. It is usually
-// used to fetch OCSP responses on demand, which is not ideal. Instead, treat
-// OCSP responses like other server credentials, such as certificates or SCT
-// lists. Configure, store, and refresh them eagerly. This avoids downtime if
-// the CA's OCSP responder is briefly offline.
-OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
-                                                int (*callback)(SSL *ssl,
-                                                                void *arg));
-
-// SSL_CTX_set_tlsext_status_arg sets additional data for
-// `SSL_CTX_set_tlsext_status_cb`'s callback and returns one.
-OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
-
-// The following symbols are compatibility aliases for reason codes used when
-// receiving an alert from the peer. Use the other names instead, which fit the
-// naming convention.
-//
-// TODO(davidben): Fix references to `SSL_R_TLSV1_CERTIFICATE_REQUIRED` and
-// remove the compatibility value. The others come from OpenSSL.
-#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION \
-  SSL_R_TLSV1_ALERT_UNSUPPORTED_EXTENSION
-#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE \
-  SSL_R_TLSV1_ALERT_CERTIFICATE_UNOBTAINABLE
-#define SSL_R_TLSV1_UNRECOGNIZED_NAME SSL_R_TLSV1_ALERT_UNRECOGNIZED_NAME
-#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE \
-  SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE
-#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE \
-  SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_HASH_VALUE
-#define SSL_R_TLSV1_CERTIFICATE_REQUIRED SSL_R_TLSV1_ALERT_CERTIFICATE_REQUIRED
-
-// The following symbols are compatibility aliases for `SSL_GROUP_*`.
-#define SSL_CURVE_SECP256R1 SSL_GROUP_SECP256R1
-#define SSL_CURVE_SECP384R1 SSL_GROUP_SECP384R1
-#define SSL_CURVE_SECP521R1 SSL_GROUP_SECP521R1
-#define SSL_CURVE_X25519 SSL_GROUP_X25519
-
-// SSL_get_curve_id calls `SSL_get_group_id`.
-OPENSSL_EXPORT uint16_t SSL_get_curve_id(const SSL *ssl);
-
-// SSL_get_curve_name calls `SSL_get_group_name`.
-OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t curve_id);
-
-// SSL_get_all_curve_names calls `SSL_get_all_group_names`.
-OPENSSL_EXPORT size_t SSL_get_all_curve_names(const char **out, size_t max_out);
-
-// SSL_CTX_set1_curves calls `SSL_CTX_set1_groups`.
-OPENSSL_EXPORT int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves,
-                                       size_t num_curves);
-
-// SSL_set1_curves calls `SSL_set1_groups`.
-OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves,
-                                   size_t num_curves);
-
-// SSL_CTX_set1_curves_list calls `SSL_CTX_set1_groups_list`.
-OPENSSL_EXPORT int SSL_CTX_set1_curves_list(SSL_CTX *ctx, const char *curves);
-
-// SSL_set1_curves_list calls `SSL_set1_groups_list`.
-OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
-
-// TLSEXT_nid_unknown is a constant used in OpenSSL for
-// `SSL_get_negotiated_group` to return an unrecognized group. BoringSSL never
-// returns this value, but we define this constant for compatibility.
-#define TLSEXT_nid_unknown 0x1000000
-
-// SSL_CTX_check_private_key returns one if `ctx` has both a certificate and
-// private key, and zero otherwise.
-//
-// This function does not check consistency because the library checks when the
-// certificate and key are individually configured. However, if the private key
-// is configured before the certificate, inconsistent private keys are silently
-// dropped. Some callers are inadvertently relying on this function to detect
-// when this happens.
-//
-// Instead, callers should configure the certificate first, then the private
-// key, checking for errors in each. This function is then unnecessary.
-OPENSSL_EXPORT int SSL_CTX_check_private_key(const SSL_CTX *ctx);
-
-// SSL_check_private_key returns one if `ssl` has both a certificate and private
-// key, and zero otherwise.
-//
-// See discussion in `SSL_CTX_check_private_key`.
-OPENSSL_EXPORT int SSL_check_private_key(const SSL *ssl);
-
-// SSL_CTX_get_security_level returns zero.
-//
-// This function is not meaningful in BoringSSL. OpenSSL has an arbitrary
-// mapping from algorithms to "security levels" and offers an API to filter TLS
-// configuration by those levels. In OpenSSL, this function does not return how
-// secure `ctx` is, just what security level the caller previously configured.
-// As BoringSSL does not implement this API, we return zero to report that the
-// security levels mechanism is not used.
-OPENSSL_EXPORT int SSL_CTX_get_security_level(const SSL_CTX *ctx);
-
-// SSL_CTX_set0_buffer_pool calls `SSL_CTX_set1_buffer_pool`. Use
-// `SSL_CTX_set1_buffer_pool` instead.
-//
-// WARNING: Despite being named set0, this function does not adopt the caller's
-// reference to `pool` and instead increments its own reference like a set1
-// function. Historically, `CRYPTO_BUFFER_POOL` was not reference-counted and
-// this function saved a non-owning pointer, expecting the caller to maintain a
-// lifetime relationship between the two objects. Now that pools are
-// reference-counted, the compatible behavior is to treat it as set0 rather than
-// ownership-transfering.
-OPENSSL_EXPORT void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx,
-                                             CRYPTO_BUFFER_POOL *pool);
-
-
 // Compliance policy configurations
 //
 // A TLS connection has a large number of different parameters. Some are well
@@ -6578,15 +5837,6 @@
     const SSL *ssl);
 
 
-// Nodejs compatibility section (hidden).
-//
-// These defines exist for node.js, with the hope that we can eliminate the
-// need for them over time.
-
-#define SSLerr(function, reason) \
-  ERR_put_error(ERR_LIB_SSL, 0, reason, __FILE__, __LINE__)
-
-
 // Server Padding
 //
 // The Server Padding extension allows clients to request that servers add
@@ -6899,6 +6149,11 @@
 
 #if defined(__cplusplus)
 }  // extern C
+#endif
+
+#include <openssl/ssl_deprecated.h>  // IWYU pragma: export
+
+#if defined(__cplusplus)
 
 #if !defined(BORINGSSL_NO_CXX)
 
diff --git a/include/openssl/ssl_deprecated.h b/include/openssl/ssl_deprecated.h
new file mode 100644
index 0000000..de1a747
--- /dev/null
+++ b/include/openssl/ssl_deprecated.h
@@ -0,0 +1,790 @@
+// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+// Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+// Copyright 2005 Nokia. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// IWYU pragma: private
+
+
+#ifndef OPENSSL_HEADER_SSL_DEPRECATED_H
+#define OPENSSL_HEADER_SSL_DEPRECATED_H
+
+#include <openssl/base.h>  // IWYU pragma: export
+#include <openssl/stack.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+// Deprecated SSL functions.
+//
+// This header contains functions that are part of <openssl/ssl.h>, but
+// deprecated. They are placed in a separate file to make it clearer that they
+// are deprecated, but there is no need to include this header directly.
+// Including <openssl/ssl.h> will always include this header.
+
+
+// SSL_library_init returns one.
+OPENSSL_EXPORT int SSL_library_init(void);
+
+// SSL_CIPHER_description writes a description of `cipher` into `buf` and
+// returns `buf`. If `buf` is NULL, it returns a newly allocated string, to be
+// freed with `OPENSSL_free`, or NULL on error.
+//
+// The description includes a trailing newline and has the form:
+// AES128-SHA              Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA1
+//
+// Consider `SSL_CIPHER_standard_name` or `SSL_CIPHER_get_name` instead.
+OPENSSL_EXPORT const char *SSL_CIPHER_description(const SSL_CIPHER *cipher,
+                                                  char *buf, int len);
+
+// SSL_CIPHER_get_version returns the string "TLSv1/SSLv3".
+OPENSSL_EXPORT const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher);
+
+// SSL_CIPHER_get_id returns `cipher`'s IANA-assigned number, OR-d with
+// 0x03000000. This is part of OpenSSL's SSL 2.0 legacy. SSL 2.0 has long since
+// been removed from BoringSSL. Use `SSL_CIPHER_get_protocol_id` instead.
+OPENSSL_EXPORT uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher);
+
+// SSL_CIPHER_get_name returns the OpenSSL name of `cipher`. For example,
+// "ECDHE-RSA-AES128-GCM-SHA256". Callers are recommended to use
+// `SSL_CIPHER_standard_name` instead.
+OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher);
+
+typedef void COMP_METHOD;
+typedef struct ssl_comp_st SSL_COMP;
+
+// SSL_COMP_get_compression_methods returns NULL.
+OPENSSL_EXPORT STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+
+// SSL_COMP_add_compression_method returns one.
+OPENSSL_EXPORT int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);
+
+// SSL_COMP_get_name returns NULL.
+OPENSSL_EXPORT const char *SSL_COMP_get_name(const COMP_METHOD *comp);
+
+// SSL_COMP_get0_name returns the `name` member of `comp`.
+OPENSSL_EXPORT const char *SSL_COMP_get0_name(const SSL_COMP *comp);
+
+// SSL_COMP_get_id returns the `id` member of `comp`.
+OPENSSL_EXPORT int SSL_COMP_get_id(const SSL_COMP *comp);
+
+// SSL_COMP_free_compression_methods does nothing.
+OPENSSL_EXPORT void SSL_COMP_free_compression_methods(void);
+
+// SSLv23_method calls `TLS_method`.
+OPENSSL_EXPORT const SSL_METHOD *SSLv23_method(void);
+
+// These version-specific methods behave exactly like `TLS_method` and
+// `DTLS_method` except they also call `SSL_CTX_set_min_proto_version` and
+// `SSL_CTX_set_max_proto_version` to lock connections to that protocol
+// version.
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_method(void);
+
+// These client- and server-specific methods call their corresponding generic
+// methods.
+OPENSSL_EXPORT const SSL_METHOD *TLS_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLS_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *SSLv23_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *SSLv23_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLS_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLS_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_client_method(void);
+
+// SSL_clear resets `ssl` to allow another connection and returns one on success
+// or zero on failure. It returns most configuration state but releases memory
+// associated with the current connection.
+//
+// Free `ssl` and create a new one instead.
+OPENSSL_EXPORT int SSL_clear(SSL *ssl);
+
+// SSL_CTX_set_tmp_rsa_callback does nothing.
+OPENSSL_EXPORT void SSL_CTX_set_tmp_rsa_callback(
+    SSL_CTX *ctx, RSA *(*cb)(SSL *ssl, int is_export, int keylength));
+
+// SSL_set_tmp_rsa_callback does nothing.
+OPENSSL_EXPORT void SSL_set_tmp_rsa_callback(SSL *ssl,
+                                             RSA *(*cb)(SSL *ssl, int is_export,
+                                                        int keylength));
+
+// SSL_CTX_sess_connect returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_connect(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_connect_good returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_connect_good(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_connect_renegotiate returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_accept returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_accept(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_accept_renegotiate returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_accept_renegotiate(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_accept_good returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_accept_good(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_hits returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_hits(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_cb_hits returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_cb_hits(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_misses returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_misses(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_timeouts returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_timeouts(const SSL_CTX *ctx);
+
+// SSL_CTX_sess_cache_full returns zero.
+OPENSSL_EXPORT int SSL_CTX_sess_cache_full(const SSL_CTX *ctx);
+
+// SSL_cutthrough_complete calls `SSL_in_false_start`.
+OPENSSL_EXPORT int SSL_cutthrough_complete(const SSL *ssl);
+
+// SSL_num_renegotiations calls `SSL_total_renegotiations`.
+OPENSSL_EXPORT int SSL_num_renegotiations(const SSL *ssl);
+
+// SSL_CTX_need_tmp_RSA returns zero.
+OPENSSL_EXPORT int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx);
+
+// SSL_need_tmp_RSA returns zero.
+OPENSSL_EXPORT int SSL_need_tmp_RSA(const SSL *ssl);
+
+// SSL_CTX_set_tmp_rsa returns one.
+OPENSSL_EXPORT int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa);
+
+// SSL_set_tmp_rsa returns one.
+OPENSSL_EXPORT int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa);
+
+// SSL_CTX_get_read_ahead returns zero.
+OPENSSL_EXPORT int SSL_CTX_get_read_ahead(const SSL_CTX *ctx);
+
+// SSL_CTX_set_read_ahead returns one.
+OPENSSL_EXPORT int SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes);
+
+// SSL_get_read_ahead returns zero.
+OPENSSL_EXPORT int SSL_get_read_ahead(const SSL *ssl);
+
+// SSL_set_read_ahead returns one.
+OPENSSL_EXPORT int SSL_set_read_ahead(SSL *ssl, int yes);
+
+// SSL_set_state does nothing.
+OPENSSL_EXPORT void SSL_set_state(SSL *ssl, int state);
+
+// SSL_get_shared_ciphers writes an empty string to `buf` and returns a
+// pointer to `buf`, or NULL if `len` is less than or equal to zero.
+OPENSSL_EXPORT char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len);
+
+// SSL_get_shared_sigalgs returns zero.
+OPENSSL_EXPORT int SSL_get_shared_sigalgs(SSL *ssl, int idx, int *psign,
+                                          int *phash, int *psignandhash,
+                                          uint8_t *rsig, uint8_t *rhash);
+
+// SSL_MODE_HANDSHAKE_CUTTHROUGH is the same as SSL_MODE_ENABLE_FALSE_START.
+#define SSL_MODE_HANDSHAKE_CUTTHROUGH SSL_MODE_ENABLE_FALSE_START
+
+// i2d_SSL_SESSION serializes `in`, as described in `i2d_SAMPLE`.
+//
+// Use `SSL_SESSION_to_bytes` instead.
+OPENSSL_EXPORT int i2d_SSL_SESSION(const SSL_SESSION *in, uint8_t **pp);
+
+// d2i_SSL_SESSION parses a serialized session from the `len` bytes pointed to
+// by `*inp`, as described in `d2i_SAMPLE`.
+//
+// Use `SSL_SESSION_from_bytes` instead.
+OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **out,
+                                            const uint8_t **inp, long len);
+
+// i2d_SSL_SESSION_bio serializes `session` and writes the result to `bio`. It
+// returns the number of bytes written on success and <= 0 on error.
+OPENSSL_EXPORT int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session);
+
+// d2i_SSL_SESSION_bio reads a serialized `SSL_SESSION` from `bio` and returns a
+// newly-allocated `SSL_SESSION` or NULL on error. If `out` is not NULL, it also
+// frees `*out` and sets `*out` to the new `SSL_SESSION`.
+OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out);
+
+// ERR_load_SSL_strings does nothing.
+OPENSSL_EXPORT void ERR_load_SSL_strings(void);
+
+// SSL_load_error_strings does nothing.
+OPENSSL_EXPORT void SSL_load_error_strings(void);
+
+// SSL_CTX_set_tlsext_use_srtp calls `SSL_CTX_set_srtp_profiles`. It returns
+// zero on success and one on failure.
+//
+// WARNING: this function is dangerous because it breaks the usual return value
+// convention. Use `SSL_CTX_set_srtp_profiles` instead.
+OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,
+                                               const char *profiles);
+
+// SSL_set_tlsext_use_srtp calls `SSL_set_srtp_profiles`. It returns zero on
+// success and one on failure.
+//
+// WARNING: this function is dangerous because it breaks the usual return value
+// convention. Use `SSL_set_srtp_profiles` instead.
+OPENSSL_EXPORT int SSL_set_tlsext_use_srtp(SSL *ssl, const char *profiles);
+
+// SSL_get_current_compression returns NULL.
+OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_compression(SSL *ssl);
+
+// SSL_get_current_expansion returns NULL.
+OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_expansion(SSL *ssl);
+
+// SSL_get_server_tmp_key returns zero.
+OPENSSL_EXPORT int SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key);
+
+// SSL_get_peer_tmp_key returns zero.
+OPENSSL_EXPORT int SSL_get_peer_tmp_key(SSL *ssl, EVP_PKEY **out_key);
+
+// SSL_CTX_set_tmp_dh returns 1.
+OPENSSL_EXPORT int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh);
+
+// SSL_set_tmp_dh returns 1.
+OPENSSL_EXPORT int SSL_set_tmp_dh(SSL *ssl, const DH *dh);
+
+// SSL_CTX_set_tmp_dh_callback does nothing.
+OPENSSL_EXPORT void SSL_CTX_set_tmp_dh_callback(
+    SSL_CTX *ctx, DH *(*cb)(SSL *ssl, int is_export, int keylength));
+
+// SSL_set_tmp_dh_callback does nothing.
+OPENSSL_EXPORT void SSL_set_tmp_dh_callback(SSL *ssl,
+                                            DH *(*cb)(SSL *ssl, int is_export,
+                                                      int keylength));
+
+// SSL_CTX_set1_sigalgs takes `num_values` ints and interprets them as pairs
+// where the first is the nid of a hash function and the second is an
+// `EVP_PKEY_*` value. It configures the signature algorithm preferences for
+// `ctx` based on them and returns one on success or zero on error.
+//
+// This API is compatible with OpenSSL. However, BoringSSL-specific code should
+// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
+// more convenient to codesearch for specific algorithm values.
+OPENSSL_EXPORT int SSL_CTX_set1_sigalgs(SSL_CTX *ctx, const int *values,
+                                        size_t num_values);
+
+// SSL_set1_sigalgs takes `num_values` ints and interprets them as pairs where
+// the first is the nid of a hash function and the second is an `EVP_PKEY_*`
+// value. It configures the signature algorithm preferences for `ssl` based on
+// them and returns one on success or zero on error.
+//
+// This API is compatible with OpenSSL. However, BoringSSL-specific code should
+// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
+// more convenient to codesearch for specific algorithm values.
+OPENSSL_EXPORT int SSL_set1_sigalgs(SSL *ssl, const int *values,
+                                    size_t num_values);
+
+// SSL_CTX_set1_sigalgs_list takes a textual specification of a set of signature
+// algorithms and configures them on `ctx`. It returns one on success and zero
+// on error. See
+// https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set1_sigalgs_list.html for
+// a description of the text format. Also note that TLS 1.3 names (e.g.
+// "rsa_pkcs1_md5_sha1") can also be used (as in OpenSSL, although OpenSSL
+// doesn't document that).
+//
+// This API is compatible with OpenSSL. However, BoringSSL-specific code should
+// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
+// more convenient to codesearch for specific algorithm values.
+OPENSSL_EXPORT int SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str);
+
+// SSL_set1_sigalgs_list takes a textual specification of a set of signature
+// algorithms and configures them on `ssl`. It returns one on success and zero
+// on error. See
+// https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set1_sigalgs_list.html for
+// a description of the text format. Also note that TLS 1.3 names (e.g.
+// "rsa_pkcs1_md5_sha1") can also be used (as in OpenSSL, although OpenSSL
+// doesn't document that).
+//
+// This API is compatible with OpenSSL. However, BoringSSL-specific code should
+// prefer `SSL_CTX_set_signing_algorithm_prefs` because it's clearer and it's
+// more convenient to codesearch for specific algorithm values.
+OPENSSL_EXPORT int SSL_set1_sigalgs_list(SSL *ssl, const char *str);
+
+#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg)))
+#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
+#define SSL_SESSION_set_app_data(s, a) \
+  (SSL_SESSION_set_ex_data(s, 0, (char *)(a)))
+#define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s, 0))
+#define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx, 0))
+#define SSL_CTX_set_app_data(ctx, arg) \
+  (SSL_CTX_set_ex_data(ctx, 0, (char *)(arg)))
+
+#define OpenSSL_add_ssl_algorithms() SSL_library_init()
+#define SSLeay_add_ssl_algorithms() SSL_library_init()
+
+#define SSL_get_cipher(ssl) SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))
+#define SSL_get_cipher_bits(ssl, out_alg_bits) \
+  SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), out_alg_bits)
+#define SSL_get_cipher_version(ssl) \
+  SSL_CIPHER_get_version(SSL_get_current_cipher(ssl))
+#define SSL_get_cipher_name(ssl) \
+  SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))
+#define SSL_get_time(session) SSL_SESSION_get_time(session)
+#define SSL_set_time(session, time) SSL_SESSION_set_time((session), (time))
+#define SSL_get_timeout(session) SSL_SESSION_get_timeout(session)
+#define SSL_set_timeout(session, timeout) \
+  SSL_SESSION_set_timeout((session), (timeout))
+
+struct ssl_comp_st {
+  int id;
+  const char *name;
+  char *method;
+};
+
+DEFINE_STACK_OF(SSL_COMP)
+
+// The following flags do nothing and are included only to make it easier to
+// compile code with BoringSSL.
+#define SSL_MODE_AUTO_RETRY 0
+#define SSL_MODE_RELEASE_BUFFERS 0
+#define SSL_MODE_SEND_CLIENTHELLO_TIME 0
+#define SSL_MODE_SEND_SERVERHELLO_TIME 0
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0
+#define SSL_OP_EPHEMERAL_RSA 0
+#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0
+#define SSL_OP_MICROSOFT_SESS_ID_BUG 0
+#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0
+#define SSL_OP_NETSCAPE_CA_DN_BUG 0
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0
+#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0
+#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0
+#define SSL_OP_NO_COMPRESSION 0
+#define SSL_OP_NO_RENEGOTIATION 0  // ssl_renegotiate_never is the default
+#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
+#define SSL_OP_NO_SSLv2 0
+#define SSL_OP_NO_SSLv3 0
+#define SSL_OP_PKCS1_CHECK_1 0
+#define SSL_OP_PKCS1_CHECK_2 0
+#define SSL_OP_SINGLE_DH_USE 0
+#define SSL_OP_SINGLE_ECDH_USE 0
+#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0
+#define SSL_OP_TLS_BLOCK_PADDING_BUG 0
+#define SSL_OP_TLS_D5_BUG 0
+#define SSL_OP_TLS_ROLLBACK_BUG 0
+#define SSL_VERIFY_CLIENT_ONCE 0
+
+// SSL_cache_hit calls `SSL_session_reused`.
+OPENSSL_EXPORT int SSL_cache_hit(SSL *ssl);
+
+// SSL_get_default_timeout returns `SSL_DEFAULT_SESSION_TIMEOUT`.
+OPENSSL_EXPORT long SSL_get_default_timeout(const SSL *ssl);
+
+// SSL_get_version returns a string describing the TLS version used by `ssl`.
+// For example, "TLSv1.2" or "DTLSv1".
+OPENSSL_EXPORT const char *SSL_get_version(const SSL *ssl);
+
+// SSL_get_all_version_names outputs a list of possible strings
+// `SSL_get_version` may return in this version of BoringSSL. It writes at most
+// `max_out` entries to `out` and returns the total number it would have
+// written, if `max_out` had been large enough. `max_out` may be initially set
+// to zero to size the output.
+//
+// This function is only intended to help initialize tables in callers that want
+// possible strings pre-declared. This list would not be suitable to set a list
+// of supported features. It is in no particular order, and may contain
+// placeholder, experimental, or deprecated values that do not apply to every
+// caller. Future versions of BoringSSL may also return strings not in this
+// list, so this does not apply if, say, sending strings across services.
+OPENSSL_EXPORT size_t SSL_get_all_version_names(const char **out,
+                                                size_t max_out);
+
+// SSL_get_cipher_list returns the name of the `n`th cipher in the output of
+// `SSL_get_ciphers` or NULL if out of range. Use `SSL_get_ciphers` instead.
+OPENSSL_EXPORT const char *SSL_get_cipher_list(const SSL *ssl, int n);
+
+// SSL_CTX_set_client_cert_cb sets a callback which is called on the client if
+// the server requests a client certificate and none is configured. On success,
+// the callback should return one and set `*out_x509` to `*out_pkey` to a leaf
+// certificate and private key, respectively, passing ownership. It should
+// return zero to send no certificate and -1 to fail or pause the handshake. If
+// the handshake is paused, `SSL_get_error` will return
+// `SSL_ERROR_WANT_X509_LOOKUP`.
+//
+// The callback may call `SSL_get0_certificate_types` and
+// `SSL_get_client_CA_list` for information on the server's certificate request.
+//
+// Use `SSL_CTX_set_cert_cb` instead. Configuring intermediate certificates with
+// this function is confusing. This callback may not be registered concurrently
+// with `SSL_CTX_set_cert_cb` or `SSL_set_cert_cb`.
+OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
+    SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey));
+
+#define SSL_NOTHING SSL_ERROR_NONE
+#define SSL_WRITING SSL_ERROR_WANT_WRITE
+#define SSL_READING SSL_ERROR_WANT_READ
+
+// SSL_want returns one of the above values to determine what the most recent
+// operation on `ssl` was blocked on. Use `SSL_get_error` instead.
+OPENSSL_EXPORT int SSL_want(const SSL *ssl);
+
+#define SSL_want_read(ssl) (SSL_want(ssl) == SSL_READING)
+#define SSL_want_write(ssl) (SSL_want(ssl) == SSL_WRITING)
+
+// SSL_get_finished writes up to `count` bytes of the Finished message sent by
+// `ssl` to `buf`. It returns the total untruncated length or zero if none has
+// been sent yet. At TLS 1.3 and later, it returns zero.
+//
+// Use `SSL_get_tls_unique` instead.
+OPENSSL_EXPORT size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count);
+
+// SSL_get_peer_finished writes up to `count` bytes of the Finished message
+// received from `ssl`'s peer to `buf`. It returns the total untruncated length
+// or zero if none has been received yet. At TLS 1.3 and later, it returns
+// zero.
+//
+// Use `SSL_get_tls_unique` instead.
+OPENSSL_EXPORT size_t SSL_get_peer_finished(const SSL *ssl, void *buf,
+                                            size_t count);
+
+// SSL_alert_type_string returns "!". Use `SSL_alert_type_string_long`
+// instead.
+OPENSSL_EXPORT const char *SSL_alert_type_string(int value);
+
+// SSL_alert_desc_string returns "!!". Use `SSL_alert_desc_string_long`
+// instead.
+OPENSSL_EXPORT const char *SSL_alert_desc_string(int value);
+
+// SSL_state_string returns "!!!!!!". Use `SSL_state_string_long` for a more
+// intelligible string.
+OPENSSL_EXPORT const char *SSL_state_string(const SSL *ssl);
+
+// SSL_TXT_* expand to strings.
+#define SSL_TXT_MEDIUM "MEDIUM"
+#define SSL_TXT_HIGH "HIGH"
+#define SSL_TXT_FIPS "FIPS"
+#define SSL_TXT_kRSA "kRSA"
+#define SSL_TXT_kDHE "kDHE"
+#define SSL_TXT_kEDH "kEDH"
+#define SSL_TXT_kECDHE "kECDHE"
+#define SSL_TXT_kEECDH "kEECDH"
+#define SSL_TXT_kPSK "kPSK"
+#define SSL_TXT_aRSA "aRSA"
+#define SSL_TXT_aECDSA "aECDSA"
+#define SSL_TXT_aPSK "aPSK"
+#define SSL_TXT_DH "DH"
+#define SSL_TXT_DHE "DHE"
+#define SSL_TXT_EDH "EDH"
+#define SSL_TXT_RSA "RSA"
+#define SSL_TXT_ECDH "ECDH"
+#define SSL_TXT_ECDHE "ECDHE"
+#define SSL_TXT_EECDH "EECDH"
+#define SSL_TXT_ECDSA "ECDSA"
+#define SSL_TXT_PSK "PSK"
+#define SSL_TXT_3DES "3DES"
+#define SSL_TXT_RC4 "RC4"
+#define SSL_TXT_AES128 "AES128"
+#define SSL_TXT_AES256 "AES256"
+#define SSL_TXT_AES "AES"
+#define SSL_TXT_AES_GCM "AESGCM"
+#define SSL_TXT_CHACHA20 "CHACHA20"
+#define SSL_TXT_MD5 "MD5"
+#define SSL_TXT_SHA1 "SHA1"
+#define SSL_TXT_SHA "SHA"
+#define SSL_TXT_SHA256 "SHA256"
+#define SSL_TXT_SHA384 "SHA384"
+#define SSL_TXT_SSLV3 "SSLv3"
+#define SSL_TXT_TLSV1 "TLSv1"
+#define SSL_TXT_TLSV1_1 "TLSv1.1"
+#define SSL_TXT_TLSV1_2 "TLSv1.2"
+#define SSL_TXT_TLSV1_3 "TLSv1.3"
+#define SSL_TXT_ALL "ALL"
+#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
+
+typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
+
+// SSL_state returns `SSL_ST_INIT` if a handshake is in progress and `SSL_ST_OK`
+// otherwise.
+//
+// Use `SSL_is_init` instead.
+OPENSSL_EXPORT int SSL_state(const SSL *ssl);
+
+#define SSL_get_state(ssl) SSL_state(ssl)
+
+// SSL_set_shutdown causes `ssl` to behave as if the shutdown bitmask (see
+// `SSL_get_shutdown`) were `mode`. This may be used to skip sending or
+// receiving close_notify in `SSL_shutdown` by causing the implementation to
+// believe the events already happened.
+//
+// It is an error to use `SSL_set_shutdown` to unset a bit that has already been
+// set. Doing so will trigger an `assert` in debug builds and otherwise be
+// ignored.
+//
+// Use `SSL_CTX_set_quiet_shutdown` instead.
+OPENSSL_EXPORT void SSL_set_shutdown(SSL *ssl, int mode);
+
+// SSL_CTX_set_tmp_ecdh calls `SSL_CTX_set1_groups` with a one-element list
+// containing `ec_key`'s curve. The remainder of `ec_key` is ignored.
+OPENSSL_EXPORT int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key);
+
+// SSL_set_tmp_ecdh calls `SSL_set1_groups` with a one-element list containing
+// `ec_key`'s curve. The remainder of `ec_key` is ignored.
+OPENSSL_EXPORT int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key);
+
+#if !defined(OPENSSL_NO_FILESYSTEM)
+// SSL_add_dir_cert_subjects_to_stack lists files in directory `dir`. It calls
+// `SSL_add_file_cert_subjects_to_stack` on each file and returns one on success
+// or zero on error. This function is only available from the libdecrepit
+// library.
+OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
+                                                      const char *dir);
+#endif
+
+// SSL_CTX_enable_tls_channel_id calls `SSL_CTX_set_tls_channel_id_enabled`.
+OPENSSL_EXPORT int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx);
+
+// SSL_enable_tls_channel_id calls `SSL_set_tls_channel_id_enabled`.
+OPENSSL_EXPORT int SSL_enable_tls_channel_id(SSL *ssl);
+
+// BIO_f_ssl returns a `BIO_METHOD` that can wrap an `SSL*` in a `BIO*`. Note
+// that this has quite different behaviour from the version in OpenSSL (notably
+// that it doesn't try to auto renegotiate).
+//
+// IMPORTANT: if you are not curl, don't use this.
+OPENSSL_EXPORT const BIO_METHOD *BIO_f_ssl(void);
+
+// BIO_set_ssl sets `ssl` as the underlying connection for `bio`, which must
+// have been created using `BIO_f_ssl`. If `take_owership` is true, `bio` will
+// call `SSL_free` on `ssl` when closed. It returns one on success or something
+// other than one on error.
+OPENSSL_EXPORT long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership);
+
+// SSL_CTX_set_ecdh_auto returns one.
+#define SSL_CTX_set_ecdh_auto(ctx, onoff) 1
+
+// SSL_set_ecdh_auto returns one.
+#define SSL_set_ecdh_auto(ssl, onoff) 1
+
+// SSL_get_session returns a non-owning pointer to `ssl`'s session. For
+// historical reasons, which session it returns depends on `ssl`'s state.
+//
+// Prior to the start of the initial handshake, it returns the session the
+// caller set with `SSL_set_session`. After the initial handshake has finished
+// and if no additional handshakes are in progress, it returns the currently
+// active session. Its behavior is undefined while a handshake is in progress.
+//
+// If trying to add new sessions to an external session cache, use
+// `SSL_CTX_sess_set_new_cb` instead. In particular, using the callback is
+// required as of TLS 1.3. For compatibility, this function will return an
+// unresumable session which may be cached, but will never be resumed.
+//
+// If querying properties of the connection, use APIs on the `SSL` object.
+OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl);
+
+// SSL_get0_session is an alias for `SSL_get_session`.
+#define SSL_get0_session SSL_get_session
+
+// SSL_get1_session acts like `SSL_get_session` but returns a new reference to
+// the session.
+OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
+
+#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0
+#define OPENSSL_INIT_LOAD_SSL_STRINGS 0
+#define OPENSSL_INIT_SSL_DEFAULT 0
+
+// OPENSSL_init_ssl returns one.
+OPENSSL_EXPORT int OPENSSL_init_ssl(uint64_t opts,
+                                    const OPENSSL_INIT_SETTINGS *settings);
+
+// The following constants are legacy aliases for RSA-PSS with rsaEncryption
+// keys. Use the new names instead.
+#define SSL_SIGN_RSA_PSS_SHA256 SSL_SIGN_RSA_PSS_RSAE_SHA256
+#define SSL_SIGN_RSA_PSS_SHA384 SSL_SIGN_RSA_PSS_RSAE_SHA384
+#define SSL_SIGN_RSA_PSS_SHA512 SSL_SIGN_RSA_PSS_RSAE_SHA512
+
+// SSL_set_tlsext_status_type configures a client to request OCSP stapling if
+// `type` is `TLSEXT_STATUSTYPE_ocsp` and disables it otherwise. It returns one
+// on success and zero if handshake configuration has already been shed.
+//
+// Use `SSL_enable_ocsp_stapling` instead.
+OPENSSL_EXPORT int SSL_set_tlsext_status_type(SSL *ssl, int type);
+
+// SSL_get_tlsext_status_type returns `TLSEXT_STATUSTYPE_ocsp` if the client
+// requested OCSP stapling and `TLSEXT_STATUSTYPE_nothing` otherwise. On the
+// client, this reflects whether OCSP stapling was enabled via, e.g.,
+// `SSL_set_tlsext_status_type`. On the server, this is determined during the
+// handshake. It may be queried in callbacks set by `SSL_CTX_set_cert_cb`. The
+// result is undefined after the handshake completes.
+OPENSSL_EXPORT int SSL_get_tlsext_status_type(const SSL *ssl);
+
+// SSL_set_tlsext_status_ocsp_resp sets the OCSP response. It returns one on
+// success and zero on error. On success, `ssl` takes ownership of `resp`, which
+// must have been allocated by `OPENSSL_malloc`.
+//
+// Use `SSL_set_ocsp_response` instead.
+OPENSSL_EXPORT int SSL_set_tlsext_status_ocsp_resp(SSL *ssl, uint8_t *resp,
+                                                   size_t resp_len);
+
+// SSL_get_tlsext_status_ocsp_resp sets `*out` to point to the OCSP response
+// from the server. It returns the length of the response. If there was no
+// response, it sets `*out` to NULL and returns zero.
+//
+// Use `SSL_get0_ocsp_response` instead.
+//
+// WARNING: the returned data is not guaranteed to be well formed.
+OPENSSL_EXPORT size_t SSL_get_tlsext_status_ocsp_resp(const SSL *ssl,
+                                                      const uint8_t **out);
+
+// SSL_CTX_set_tlsext_status_cb configures the legacy OpenSSL OCSP callback and
+// returns one. Though the type signature is the same, this callback has
+// different behavior for client and server connections:
+//
+// For clients, the callback is called after certificate verification. It should
+// return one for success, zero for a bad OCSP response, and a negative number
+// for internal error. Instead, handle this as part of certificate verification.
+// (Historically, OpenSSL verified certificates just before parsing stapled OCSP
+// responses, but BoringSSL fixes this ordering. All server credentials are
+// available during verification.)
+//
+// Do not use this callback as a server. It is provided for compatibility
+// purposes only. For servers, it is called to configure server credentials. It
+// should return `SSL_TLSEXT_ERR_OK` on success, `SSL_TLSEXT_ERR_NOACK` to
+// ignore OCSP requests, or `SSL_TLSEXT_ERR_ALERT_FATAL` on error. It is usually
+// used to fetch OCSP responses on demand, which is not ideal. Instead, treat
+// OCSP responses like other server credentials, such as certificates or SCT
+// lists. Configure, store, and refresh them eagerly. This avoids downtime if
+// the CA's OCSP responder is briefly offline.
+OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
+                                                int (*callback)(SSL *ssl,
+                                                                void *arg));
+
+// SSL_CTX_set_tlsext_status_arg sets additional data for
+// `SSL_CTX_set_tlsext_status_cb`'s callback and returns one.
+OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
+
+// The following symbols are compatibility aliases for reason codes used when
+// receiving an alert from the peer. Use the other names instead, which fit the
+// naming convention.
+//
+// TODO(davidben): Fix references to `SSL_R_TLSV1_CERTIFICATE_REQUIRED` and
+// remove the compatibility value. The others come from OpenSSL.
+#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION \
+  SSL_R_TLSV1_ALERT_UNSUPPORTED_EXTENSION
+#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE \
+  SSL_R_TLSV1_ALERT_CERTIFICATE_UNOBTAINABLE
+#define SSL_R_TLSV1_UNRECOGNIZED_NAME SSL_R_TLSV1_ALERT_UNRECOGNIZED_NAME
+#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE \
+  SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE
+#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE \
+  SSL_R_TLSV1_ALERT_BAD_CERTIFICATE_HASH_VALUE
+#define SSL_R_TLSV1_CERTIFICATE_REQUIRED SSL_R_TLSV1_ALERT_CERTIFICATE_REQUIRED
+
+// The following symbols are compatibility aliases for `SSL_GROUP_*`.
+#define SSL_CURVE_SECP256R1 SSL_GROUP_SECP256R1
+#define SSL_CURVE_SECP384R1 SSL_GROUP_SECP384R1
+#define SSL_CURVE_SECP521R1 SSL_GROUP_SECP521R1
+#define SSL_CURVE_X25519 SSL_GROUP_X25519
+
+// SSL_get_curve_id calls `SSL_get_group_id`.
+OPENSSL_EXPORT uint16_t SSL_get_curve_id(const SSL *ssl);
+
+// SSL_get_curve_name calls `SSL_get_group_name`.
+OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t curve_id);
+
+// SSL_get_all_curve_names calls `SSL_get_all_group_names`.
+OPENSSL_EXPORT size_t SSL_get_all_curve_names(const char **out, size_t max_out);
+
+// SSL_CTX_set1_curves calls `SSL_CTX_set1_groups`.
+OPENSSL_EXPORT int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves,
+                                       size_t num_curves);
+
+// SSL_set1_curves calls `SSL_set1_groups`.
+OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves,
+                                   size_t num_curves);
+
+// SSL_CTX_set1_curves_list calls `SSL_CTX_set1_groups_list`.
+OPENSSL_EXPORT int SSL_CTX_set1_curves_list(SSL_CTX *ctx, const char *curves);
+
+// SSL_set1_curves_list calls `SSL_set1_groups_list`.
+OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
+
+// TLSEXT_nid_unknown is a constant used in OpenSSL for
+// `SSL_get_negotiated_group` to return an unrecognized group. BoringSSL never
+// returns this value, but we define this constant for compatibility.
+#define TLSEXT_nid_unknown 0x1000000
+
+// SSL_CTX_check_private_key returns one if `ctx` has both a certificate and
+// private key, and zero otherwise.
+//
+// This function does not check consistency because the library checks when the
+// certificate and key are individually configured. However, if the private key
+// is configured before the certificate, inconsistent private keys are silently
+// dropped. Some callers are inadvertently relying on this function to detect
+// when this happens.
+//
+// Instead, callers should configure the certificate first, then the private
+// key, checking for errors in each. This function is then unnecessary.
+OPENSSL_EXPORT int SSL_CTX_check_private_key(const SSL_CTX *ctx);
+
+// SSL_check_private_key returns one if `ssl` has both a certificate and private
+// key, and zero otherwise.
+//
+// See discussion in `SSL_CTX_check_private_key`.
+OPENSSL_EXPORT int SSL_check_private_key(const SSL *ssl);
+
+// SSL_CTX_get_security_level returns zero.
+//
+// This function is not meaningful in BoringSSL. OpenSSL has an arbitrary
+// mapping from algorithms to "security levels" and offers an API to filter TLS
+// configuration by those levels. In OpenSSL, this function does not return how
+// secure `ctx` is, just what security level the caller previously configured.
+// As BoringSSL does not implement this API, we return zero to report that the
+// security levels mechanism is not used.
+OPENSSL_EXPORT int SSL_CTX_get_security_level(const SSL_CTX *ctx);
+
+// SSL_CTX_set0_buffer_pool calls `SSL_CTX_set1_buffer_pool`. Use
+// `SSL_CTX_set1_buffer_pool` instead.
+//
+// WARNING: Despite being named set0, this function does not adopt the caller's
+// reference to `pool` and instead increments its own reference like a set1
+// function. Historically, `CRYPTO_BUFFER_POOL` was not reference-counted and
+// this function saved a non-owning pointer, expecting the caller to maintain a
+// lifetime relationship between the two objects. Now that pools are
+// reference-counted, the compatible behavior is to treat it as set0 rather than
+// ownership-transfering.
+OPENSSL_EXPORT void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx,
+                                             CRYPTO_BUFFER_POOL *pool);
+
+
+// Nodejs compatibility section (hidden).
+//
+// These defines exist for node.js, with the hope that we can eliminate the
+// need for them over time.
+
+#define SSLerr(function, reason) \
+  ERR_put_error(ERR_LIB_SSL, 0, reason, __FILE__, __LINE__)
+
+
+#if defined(__cplusplus)
+}  // extern "C"
+#endif
+
+#endif  // OPENSSL_HEADER_SSL_DEPRECATED_H
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index 8193d16..a5bb3fe 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -20,10 +20,18 @@
 )
 
 // copyHash returns a copy of |h|, which must be an instance of |hashType|.
-func copyHash(h hash.Hash, hash crypto.Hash) hash.Hash {
+func copyHash(h hash.Hash, hashType crypto.Hash) hash.Hash {
 	// While hash.Hash is not copyable, the documentation says all standard
-	// library hash.Hash implementations implement BinaryMarshaler and
-	// BinaryUnmarshaler interfaces.
+	// library hash.Hash implementations implement hash.Cloner, except with
+	// GOFIPS140=v1.0.0, where we use BinaryMarshaler and BinaryUnmarshaler.
+	if c, ok := h.(hash.Cloner); ok {
+		ret, err := c.Clone()
+		if err != nil {
+			panic(err)
+		}
+		return ret
+	}
+
 	m, ok := h.(encoding.BinaryMarshaler)
 	if !ok {
 		panic("hash did not implement encoding.BinaryMarshaler")
@@ -32,7 +40,7 @@
 	if err != nil {
 		panic(err)
 	}
-	ret := hash.New()
+	ret := hashType.New()
 	u, ok := ret.(encoding.BinaryUnmarshaler)
 	if !ok {
 		panic("hash did not implement BinaryUnmarshaler")
diff --git a/util/doc.config b/util/doc.config
index b40e62b..8bb279b 100644
--- a/util/doc.config
+++ b/util/doc.config
@@ -83,7 +83,8 @@
   },{
     "Name": "SSL implementation",
     "Headers": [
-      "include/openssl/ssl.h"
+      "include/openssl/ssl.h",
+      "include/openssl/ssl_deprecated.h"
     ]
   },{
     "Name": "Experimental APIs",
diff --git a/util/doc.go b/util/doc.go
index fed939f..769255f 100644
--- a/util/doc.go
+++ b/util/doc.go
@@ -156,7 +156,7 @@
 		restLineNo++
 	}
 
-	err = errors.New("hit EOF in comment")
+	err = fmt.Errorf("hit EOF in comment on line %d", restLineNo)
 	return
 }
 
@@ -442,7 +442,7 @@
 	}
 
 	if len(lines) == 0 || lines[0] != "extern \"C\" {" {
-		return nil, errors.New("no extern \"C\" found after C++ guard")
+		return nil, fmt.Errorf("no extern \"C\" found after C++ guard on line %d", lineNo)
 	}
 	lineNo += 2
 	lines = lines[2:]
@@ -469,7 +469,7 @@
 
 		if len(rest) > 0 && len(rest[0]) == 0 {
 			if len(rest) < 2 || len(rest[1]) != 0 {
-				return nil, errors.New("preamble comment should be followed by two blank lines")
+				return nil, fmt.Errorf("preamble comment should be followed by two blank lines on line %d", restLineNo)
 			}
 			header.Preamble = comment
 			lineNo = restLineNo + 2
@@ -484,7 +484,7 @@
 	for {
 		// Start of a section.
 		if len(lines) == 0 {
-			return nil, errors.New("unexpected end of file")
+			return nil, fmt.Errorf("unexpected end of file on line %d", lineNo)
 		}
 		line := lines[0]
 		if line == cppGuard {