Center EVP_PKEY_CTX creation on EVP_PKEY_ALG

This is in preparation for adding a way to generate an EVP_PKEY from an
EVP_PKEY_ALG, by internally creating EVP_PKEY_CTXs. It also means we
could, if we wanted to, expose an EVP_PKEY_ALG version of
EVP_PKEY_CTX_new_id.

Bug: 42290364
Change-Id: Id9a74b50764717c6a0f9212c187781833a8cab54
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/90607
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Lily Chen <chlily@google.com>
diff --git a/crypto/evp/evp_ctx.cc b/crypto/evp/evp_ctx.cc
index 1a827bb..a22bc80 100644
--- a/crypto/evp/evp_ctx.cc
+++ b/crypto/evp/evp_ctx.cc
@@ -27,24 +27,6 @@
 
 using namespace bssl;
 
-// |EVP_PKEY_RSA_PSS| is intentionally omitted from this list. These are types
-// that can be created without an |EVP_PKEY|, and we do not support
-// |EVP_PKEY_RSA_PSS| keygen.
-static const EVP_PKEY_CTX_METHOD *const evp_methods[] = {
-    &rsa_pkey_meth,    &ec_pkey_meth,   &ed25519_pkey_meth,
-    &x25519_pkey_meth, &hkdf_pkey_meth,
-};
-
-static const EVP_PKEY_CTX_METHOD *evp_pkey_meth_find(int type) {
-  for (auto method : evp_methods) {
-    if (method->pkey_id == type) {
-      return method;
-    }
-  }
-
-  return nullptr;
-}
-
 static EvpPkeyCtx *evp_pkey_ctx_new(EvpPkey *pkey,
                                     const EVP_PKEY_CTX_METHOD *pmeth) {
   UniquePtr<EvpPkeyCtx> ret = MakeUnique<EvpPkeyCtx>();
@@ -86,14 +68,34 @@
 }
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) {
-  const EVP_PKEY_CTX_METHOD *pkey_method = evp_pkey_meth_find(id);
-  if (pkey_method == nullptr) {
+  // |EVP_PKEY_RSA_PSS| is intentionally omitted from this list. These are types
+  // that can be created without an |EVP_PKEY|, and we do not support
+  // |EVP_PKEY_RSA_PSS| keygen.
+  const EVP_PKEY_ALG *alg = nullptr;
+  switch (id) {
+    case EVP_PKEY_RSA:
+      alg = EVP_pkey_rsa();
+      break;
+    case EVP_PKEY_EC:
+      alg = evp_pkey_ec_no_curve();
+      break;
+    case EVP_PKEY_ED25519:
+      alg = EVP_pkey_ed25519();
+      break;
+    case EVP_PKEY_X25519:
+      alg = EVP_pkey_x25519();
+      break;
+    case EVP_PKEY_HKDF:
+      alg = evp_pkey_hkdf();
+      break;
+  }
+  if (alg == nullptr || alg->pkey_method == nullptr) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
     ERR_add_error_dataf("algorithm %d", id);
     return nullptr;
   }
 
-  return evp_pkey_ctx_new(nullptr, pkey_method);
+  return evp_pkey_ctx_new(nullptr, alg->pkey_method);
 }
 
 EvpPkeyCtx::~EvpPkeyCtx() {
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
index 2a22810..05857ce 100644
--- a/crypto/evp/internal.h
+++ b/crypto/evp/internal.h
@@ -36,8 +36,9 @@
 BSSL_NAMESPACE_END
 
 struct evp_pkey_alg_st {
-  // method implements operations for this |EVP_PKEY_ALG|.
+  // method and pkey_method implement operations for this |EVP_PKEY_ALG|.
   const bssl::EVP_PKEY_ASN1_METHOD *method;
+  const bssl::EVP_PKEY_CTX_METHOD *pkey_method;
 };
 
 BSSL_NAMESPACE_BEGIN
@@ -281,13 +282,13 @@
   int (*ctrl)(EvpPkeyCtx *ctx, int type, int p1, void *p2);
 } /* EVP_PKEY_CTX_METHOD */;
 
-extern const EVP_PKEY_CTX_METHOD rsa_pkey_meth;
-extern const EVP_PKEY_CTX_METHOD rsa_pss_pkey_meth;
-extern const EVP_PKEY_CTX_METHOD ec_pkey_meth;
-extern const EVP_PKEY_CTX_METHOD ed25519_pkey_meth;
-extern const EVP_PKEY_CTX_METHOD x25519_pkey_meth;
-extern const EVP_PKEY_CTX_METHOD hkdf_pkey_meth;
-extern const EVP_PKEY_CTX_METHOD dh_pkey_meth;
+// evp_pkey_ec_no_curve returns an internal curveless EC |EVP_PKEY_ALG|. This
+// cannot be used to parse anything and is only useful for key generation.
+const EVP_PKEY_ALG *evp_pkey_ec_no_curve();
+
+// evp_pkey_hkdf returns an internal |EVP_PKEY_ALG| used to implement
+// |EVP_PKEY_HKDF|. It has no associated key type.
+const EVP_PKEY_ALG *evp_pkey_hkdf();
 
 // evp_pkey_set0 sets |pkey|'s method to |method| and data to |pkey_data|,
 // freeing any key that may previously have been configured. This function takes
diff --git a/crypto/evp/p_dh.cc b/crypto/evp/p_dh.cc
index 2b4d28a..87efdc9 100644
--- a/crypto/evp/p_dh.cc
+++ b/crypto/evp/p_dh.cc
@@ -30,6 +30,10 @@
 
 using namespace bssl;
 
+namespace {
+
+extern const EVP_PKEY_CTX_METHOD dh_pkey_meth;
+
 static void dh_free(EvpPkey *pkey) {
   DH_free(reinterpret_cast<DH *>(pkey->pkey));
   pkey->pkey = nullptr;
@@ -133,46 +137,12 @@
     /*pkey_free=*/dh_free,
 };
 
-int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) {
-  if (EVP_PKEY_assign_DH(pkey, key)) {
-    DH_up_ref(key);
-    return 1;
-  }
-  return 0;
-}
-
-int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) {
-  if (key == nullptr) {
-    return 0;
-  }
-  evp_pkey_set0(FromOpaque(pkey), &dh_asn1_meth, key);
-  return 1;
-}
-
-DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey) {
-  if (EVP_PKEY_id(pkey) != EVP_PKEY_DH) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DH_KEY);
-    return nullptr;
-  }
-  return reinterpret_cast<DH *>(const_cast<EvpPkey *>(FromOpaque(pkey))->pkey);
-}
-
-DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey) {
-  DH *dh = EVP_PKEY_get0_DH(pkey);
-  if (dh != nullptr) {
-    DH_up_ref(dh);
-  }
-  return dh;
-}
-
-namespace {
-typedef struct dh_pkey_ctx_st {
-  int pad;
-} DH_PKEY_CTX;
-}  // namespace
+struct DH_PKEY_CTX {
+  int pad = 0;
+};
 
 static int pkey_dh_init(EvpPkeyCtx *ctx) {
-  DH_PKEY_CTX *dctx = NewZeroed<DH_PKEY_CTX>();
+  DH_PKEY_CTX *dctx = New<DH_PKEY_CTX>();
   if (dctx == nullptr) {
     return 0;
   }
@@ -272,7 +242,7 @@
   }
 }
 
-const EVP_PKEY_CTX_METHOD bssl::dh_pkey_meth = {
+const EVP_PKEY_CTX_METHOD dh_pkey_meth = {
     /*pkey_id=*/EVP_PKEY_DH,
     /*init=*/pkey_dh_init,
     /*copy=*/pkey_dh_copy,
@@ -290,6 +260,40 @@
     /*ctrl=*/pkey_dh_ctrl,
 };
 
+}  // namespace
+
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) {
+  if (EVP_PKEY_assign_DH(pkey, key)) {
+    DH_up_ref(key);
+    return 1;
+  }
+  return 0;
+}
+
+int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) {
+  if (key == nullptr) {
+    return 0;
+  }
+  evp_pkey_set0(FromOpaque(pkey), &dh_asn1_meth, key);
+  return 1;
+}
+
+DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey) {
+  if (EVP_PKEY_id(pkey) != EVP_PKEY_DH) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DH_KEY);
+    return nullptr;
+  }
+  return reinterpret_cast<DH *>(const_cast<EvpPkey *>(FromOpaque(pkey))->pkey);
+}
+
+DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey) {
+  DH *dh = EVP_PKEY_get0_DH(pkey);
+  if (dh != nullptr) {
+    DH_up_ref(dh);
+  }
+  return dh;
+}
+
 int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) {
   return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE,
                            EVP_PKEY_CTRL_DH_PAD, pad, nullptr);
diff --git a/crypto/evp/p_dsa.cc b/crypto/evp/p_dsa.cc
index d664710..eb08b99 100644
--- a/crypto/evp/p_dsa.cc
+++ b/crypto/evp/p_dsa.cc
@@ -258,7 +258,7 @@
 }  // namespace
 
 const EVP_PKEY_ALG *EVP_pkey_dsa() {
-  static const EVP_PKEY_ALG kAlg = {&dsa_asn1_meth};
+  static const EVP_PKEY_ALG kAlg = {&dsa_asn1_meth, nullptr};
   return &kAlg;
 }
 
diff --git a/crypto/evp/p_ec.cc b/crypto/evp/p_ec.cc
index abc5e14..0fdab8d 100644
--- a/crypto/evp/p_ec.cc
+++ b/crypto/evp/p_ec.cc
@@ -45,6 +45,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) {
   const EC_KEY *ec_key = reinterpret_cast<const EC_KEY *>(key->pkey);
@@ -73,10 +74,15 @@
 static 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;
+  }
+
   // See RFC 5480, section 2.
 
   // Check that |params| matches |alg|. Only the namedCurve form is allowed.
-  const EC_GROUP *group = static_cast<const EVP_PKEY_ALG_EC*>(alg)->ec_group();
+  const EC_GROUP *group = ec_alg->ec_group();
   if (ec_key_parse_curve_name(params, Span(&group, 1)) == nullptr) {
     if (ERR_equals(ERR_peek_last_error(), ERR_LIB_EC, EC_R_UNKNOWN_GROUP)) {
       ERR_clear_error();
@@ -113,8 +119,13 @@
 static 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;
+  }
+
   // See RFC 5915.
-  const EC_GROUP *group = static_cast<const EVP_PKEY_ALG_EC *>(alg)->ec_group();
+  const EC_GROUP *group = ec_alg->ec_group();
   if (ec_key_parse_parameters(params, Span(&group, 1)) == nullptr) {
     if (ERR_equals(ERR_peek_last_error(), ERR_LIB_EC, EC_R_UNKNOWN_GROUP)) {
       ERR_clear_error();
@@ -301,80 +312,6 @@
     int_ec_free,
 };
 
-}  // namespace
-
-const EVP_PKEY_ALG *EVP_pkey_ec_p224() {
-  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth}, &EC_group_p224};
-  return &kAlg;
-}
-
-const EVP_PKEY_ALG *EVP_pkey_ec_p256() {
-  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth}, &EC_group_p256};
-  return &kAlg;
-}
-
-const EVP_PKEY_ALG *EVP_pkey_ec_p384() {
-  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth}, &EC_group_p384};
-  return &kAlg;
-}
-
-const EVP_PKEY_ALG *EVP_pkey_ec_p521() {
-  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth}, &EC_group_p521};
-  return &kAlg;
-}
-
-int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
-  if (EVP_PKEY_assign_EC_KEY(pkey, key)) {
-    EC_KEY_up_ref(key);
-    return 1;
-  }
-  return 0;
-}
-
-int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
-  if (key == nullptr) {
-    return 0;
-  }
-  evp_pkey_set0(FromOpaque(pkey), &ec_asn1_meth, key);
-  return 1;
-}
-
-EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) {
-  if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_EC_KEY);
-    return nullptr;
-  }
-  return reinterpret_cast<EC_KEY *>(FromOpaque(pkey)->pkey);
-}
-
-EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey) {
-  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
-  if (ec_key != nullptr) {
-    EC_KEY_up_ref(ec_key);
-  }
-  return ec_key;
-}
-
-int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey) {
-  const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
-  if (ec_key == nullptr) {
-    return NID_undef;
-  }
-  const EC_GROUP *group = EC_KEY_get0_group(ec_key);
-  if (group == nullptr) {
-    return NID_undef;
-  }
-  return EC_GROUP_get_curve_name(group);
-}
-
-int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey) {
-  const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
-  if (ec_key == nullptr) {
-    return 0;
-  }
-  return EC_KEY_get_conv_form(ec_key);
-}
-
 typedef struct {
   // message digest
   const EVP_MD *md;
@@ -536,7 +473,7 @@
   return 1;
 }
 
-const EVP_PKEY_CTX_METHOD bssl::ec_pkey_meth = {
+const EVP_PKEY_CTX_METHOD ec_pkey_meth = {
     EVP_PKEY_EC,
     pkey_ec_init,
     pkey_ec_copy,
@@ -554,6 +491,89 @@
     pkey_ec_ctrl,
 };
 
+}  // namespace
+
+const EVP_PKEY_ALG *EVP_pkey_ec_p224() {
+  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth, &ec_pkey_meth},
+                                       &EC_group_p224};
+  return &kAlg;
+}
+
+const EVP_PKEY_ALG *EVP_pkey_ec_p256() {
+  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth, &ec_pkey_meth},
+                                       &EC_group_p256};
+  return &kAlg;
+}
+
+const EVP_PKEY_ALG *EVP_pkey_ec_p384() {
+  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth, &ec_pkey_meth},
+                                       &EC_group_p384};
+  return &kAlg;
+}
+
+const EVP_PKEY_ALG *EVP_pkey_ec_p521() {
+  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth, &ec_pkey_meth},
+                                       &EC_group_p521};
+  return &kAlg;
+}
+
+const EVP_PKEY_ALG *bssl::evp_pkey_ec_no_curve() {
+  static const EVP_PKEY_ALG_EC kAlg = {{&ec_asn1_meth, &ec_pkey_meth}, nullptr};
+  return &kAlg;
+}
+
+int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
+  if (EVP_PKEY_assign_EC_KEY(pkey, key)) {
+    EC_KEY_up_ref(key);
+    return 1;
+  }
+  return 0;
+}
+
+int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
+  if (key == nullptr) {
+    return 0;
+  }
+  evp_pkey_set0(FromOpaque(pkey), &ec_asn1_meth, key);
+  return 1;
+}
+
+EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) {
+  if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_EC_KEY);
+    return nullptr;
+  }
+  return reinterpret_cast<EC_KEY *>(FromOpaque(pkey)->pkey);
+}
+
+EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey) {
+  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
+  if (ec_key != nullptr) {
+    EC_KEY_up_ref(ec_key);
+  }
+  return ec_key;
+}
+
+int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey) {
+  const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
+  if (ec_key == nullptr) {
+    return NID_undef;
+  }
+  const EC_GROUP *group = EC_KEY_get0_group(ec_key);
+  if (group == nullptr) {
+    return NID_undef;
+  }
+  return EC_GROUP_get_curve_name(group);
+}
+
+int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey) {
+  const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
+  if (ec_key == nullptr) {
+    return 0;
+  }
+  return EC_KEY_get_conv_form(ec_key);
+}
+
 int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) {
   const EC_GROUP *group = EC_GROUP_new_by_curve_name(nid);
   if (group == nullptr) {
diff --git a/crypto/evp/p_ed25519.cc b/crypto/evp/p_ed25519.cc
index f10b09a..617c249 100644
--- a/crypto/evp/p_ed25519.cc
+++ b/crypto/evp/p_ed25519.cc
@@ -37,6 +37,7 @@
 };
 
 extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth;
+extern const EVP_PKEY_CTX_METHOD ed25519_pkey_meth;
 
 #define ED25519_PUBLIC_KEY_OFFSET 32
 
@@ -314,9 +315,7 @@
   return 1;
 }
 
-}  // namespace
-
-const EVP_PKEY_CTX_METHOD bssl::ed25519_pkey_meth = {
+const EVP_PKEY_CTX_METHOD ed25519_pkey_meth = {
     /*pkey_id=*/EVP_PKEY_ED25519,
     /*init=*/nullptr,
     /*copy=*/pkey_ed25519_copy,
@@ -334,7 +333,9 @@
     /*ctrl=*/nullptr,
 };
 
+}  // namespace
+
 const EVP_PKEY_ALG *EVP_pkey_ed25519() {
-  static const EVP_PKEY_ALG kAlg = {&ed25519_asn1_meth};
+  static const EVP_PKEY_ALG kAlg = {&ed25519_asn1_meth, &ed25519_pkey_meth};
   return &kAlg;
 }
diff --git a/crypto/evp/p_hkdf.cc b/crypto/evp/p_hkdf.cc
index e8395ee..4812197 100644
--- a/crypto/evp/p_hkdf.cc
+++ b/crypto/evp/p_hkdf.cc
@@ -27,6 +27,8 @@
 
 using namespace bssl;
 
+namespace {
+
 typedef struct {
   int mode;
   const EVP_MD *md;
@@ -185,8 +187,10 @@
   }
 }
 
-const EVP_PKEY_CTX_METHOD bssl::hkdf_pkey_meth = {
-    /*pkey_id=*/EVP_PKEY_HKDF,  pkey_hkdf_init,   pkey_hkdf_copy,
+const EVP_PKEY_CTX_METHOD hkdf_pkey_meth = {
+    EVP_PKEY_HKDF,
+    pkey_hkdf_init,
+    pkey_hkdf_copy,
     pkey_hkdf_cleanup,
     /*keygen=*/nullptr,
     /*sign=*/nullptr,
@@ -195,10 +199,19 @@
     /*verify_message=*/nullptr,
     /*verify_recover=*/nullptr,
     /*encrypt=*/nullptr,
-    /*decrypt=*/nullptr,        pkey_hkdf_derive,
-    /*paramgen=*/nullptr,       pkey_hkdf_ctrl,
+    /*decrypt=*/nullptr,
+    pkey_hkdf_derive,
+    /*paramgen=*/nullptr,
+    pkey_hkdf_ctrl,
 };
 
+}  // namespace
+
+const EVP_PKEY_ALG *bssl::evp_pkey_hkdf() {
+  static const EVP_PKEY_ALG kAlg = {nullptr, &hkdf_pkey_meth};
+  return &kAlg;
+}
+
 int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode) {
   return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_HKDF, EVP_PKEY_OP_DERIVE,
                            EVP_PKEY_CTRL_HKDF_MODE, mode, nullptr);
diff --git a/crypto/evp/p_mldsa.cc b/crypto/evp/p_mldsa.cc
index f855799..dd20d74 100644
--- a/crypto/evp/p_mldsa.cc
+++ b/crypto/evp/p_mldsa.cc
@@ -497,7 +497,7 @@
   }
 
   static constexpr EVP_PKEY_ASN1_METHOD asn1_method = BuildASN1Method();
-  static constexpr EVP_PKEY_ALG pkey_alg = {&asn1_method};
+  static constexpr EVP_PKEY_ALG pkey_alg = {&asn1_method, &pkey_method};
 };
 
 }  // namespace
diff --git a/crypto/evp/p_rsa.cc b/crypto/evp/p_rsa.cc
index 356d28f..154fcc1 100644
--- a/crypto/evp/p_rsa.cc
+++ b/crypto/evp/p_rsa.cc
@@ -43,6 +43,8 @@
 
 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
+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) {
   // See RFC 3279, section 2.3.1.
@@ -821,28 +823,70 @@
   return 1;
 }
 
+const EVP_PKEY_CTX_METHOD rsa_pkey_meth = {
+    EVP_PKEY_RSA,
+    pkey_rsa_init,
+    pkey_rsa_copy,
+    pkey_rsa_cleanup,
+    pkey_rsa_keygen,
+    pkey_rsa_sign,
+    /*sign_message=*/nullptr,
+    pkey_rsa_verify,
+    /*verify_message=*/nullptr,
+    pkey_rsa_verify_recover,
+    pkey_rsa_encrypt,
+    pkey_rsa_decrypt,
+    /*derive=*/nullptr,
+    /*paramgen=*/nullptr,
+    pkey_rsa_ctrl,
+};
+
+const EVP_PKEY_CTX_METHOD rsa_pss_pkey_meth = {
+    EVP_PKEY_RSA_PSS,
+    pkey_rsa_init,
+    pkey_rsa_copy,
+    pkey_rsa_cleanup,
+    // In OpenSSL, |EVP_PKEY_RSA_PSS| supports key generation and fills in PSS
+    // parameters based on a separate set of keygen-targetted setters:
+    // |EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen|,
+    // |EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md|, and
+    // |EVP_PKEY_CTX_rsa_pss_key_digest|. We do not currently implement this
+    // because we only support one parameter set.
+    /*keygen=*/nullptr,
+    pkey_rsa_sign,
+    /*sign_message=*/nullptr,
+    pkey_rsa_verify,
+    /*verify_message=*/nullptr,
+    /*verify_recover=*/nullptr,
+    /*encrypt=*/nullptr,
+    /*decrypt=*/nullptr,
+    /*derive=*/nullptr,
+    /*paramgen=*/nullptr,
+    pkey_rsa_ctrl,
+};
+
 }  // namespace
 
 const EVP_PKEY_ALG *EVP_pkey_rsa() {
-  static const EVP_PKEY_ALG kAlg = {&rsa_asn1_meth};
+  static const EVP_PKEY_ALG kAlg = {&rsa_asn1_meth, &rsa_pkey_meth};
   return &kAlg;
 }
 
 const EVP_PKEY_ALG *EVP_pkey_rsa_pss_sha256() {
-  static const EVP_PKEY_ALG_RSA_PSS kAlg = {{&rsa_pss_asn1_meth},
-                                            rsa_pss_sha256};
+  static const EVP_PKEY_ALG_RSA_PSS kAlg = {
+      {&rsa_pss_asn1_meth, &rsa_pss_pkey_meth}, rsa_pss_sha256};
   return &kAlg;
 }
 
 const EVP_PKEY_ALG *EVP_pkey_rsa_pss_sha384() {
-  static const EVP_PKEY_ALG_RSA_PSS kAlg = {{&rsa_pss_asn1_meth},
-                                            rsa_pss_sha384};
+  static const EVP_PKEY_ALG_RSA_PSS kAlg = {
+      {&rsa_pss_asn1_meth, &rsa_pss_pkey_meth}, rsa_pss_sha384};
   return &kAlg;
 }
 
 const EVP_PKEY_ALG *EVP_pkey_rsa_pss_sha512() {
-  static const EVP_PKEY_ALG_RSA_PSS kAlg = {{&rsa_pss_asn1_meth},
-                                            rsa_pss_sha512};
+  static const EVP_PKEY_ALG_RSA_PSS kAlg = {
+      {&rsa_pss_asn1_meth, &rsa_pss_pkey_meth}, rsa_pss_sha512};
   return &kAlg;
 }
 
@@ -879,48 +923,6 @@
   return rsa;
 }
 
-const EVP_PKEY_CTX_METHOD bssl::rsa_pkey_meth = {
-    EVP_PKEY_RSA,
-    pkey_rsa_init,
-    pkey_rsa_copy,
-    pkey_rsa_cleanup,
-    pkey_rsa_keygen,
-    pkey_rsa_sign,
-    /*sign_message=*/nullptr,
-    pkey_rsa_verify,
-    /*verify_message=*/nullptr,
-    pkey_rsa_verify_recover,
-    pkey_rsa_encrypt,
-    pkey_rsa_decrypt,
-    /*derive=*/nullptr,
-    /*paramgen=*/nullptr,
-    pkey_rsa_ctrl,
-};
-
-const EVP_PKEY_CTX_METHOD bssl::rsa_pss_pkey_meth = {
-    EVP_PKEY_RSA_PSS,
-    pkey_rsa_init,
-    pkey_rsa_copy,
-    pkey_rsa_cleanup,
-    // In OpenSSL, |EVP_PKEY_RSA_PSS| supports key generation and fills in PSS
-    // parameters based on a separate set of keygen-targetted setters:
-    // |EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen|,
-    // |EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md|, and
-    // |EVP_PKEY_CTX_rsa_pss_key_digest|. We do not currently implement this
-    // because we only support one parameter set.
-    /*keygen=*/nullptr,
-    pkey_rsa_sign,
-    /*sign_message=*/nullptr,
-    pkey_rsa_verify,
-    /*verify_message=*/nullptr,
-    /*verify_recover=*/nullptr,
-    /*encrypt=*/nullptr,
-    /*decrypt=*/nullptr,
-    /*derive=*/nullptr,
-    /*paramgen=*/nullptr,
-    pkey_rsa_ctrl,
-};
-
 static int rsa_or_rsa_pss_ctrl(EvpPkeyCtx *ctx, int optype, int cmd, int p1,
                                void *p2) {
   if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
diff --git a/crypto/evp/p_x25519.cc b/crypto/evp/p_x25519.cc
index 9160a32..f18783a 100644
--- a/crypto/evp/p_x25519.cc
+++ b/crypto/evp/p_x25519.cc
@@ -35,6 +35,7 @@
 };
 
 extern const EVP_PKEY_ASN1_METHOD x25519_asn1_meth;
+extern const EVP_PKEY_CTX_METHOD x25519_pkey_meth;
 
 static void x25519_free(EvpPkey *pkey) {
   X25519_KEY *key = reinterpret_cast<X25519_KEY *>(pkey->pkey);
@@ -265,13 +266,6 @@
     x25519_free,
 };
 
-}  // namespace
-
-const EVP_PKEY_ALG *EVP_pkey_x25519() {
-  static const EVP_PKEY_ALG kAlg = {&x25519_asn1_meth};
-  return &kAlg;
-}
-
 // X25519 has no parameters to copy.
 static int pkey_x25519_copy(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; }
 
@@ -335,7 +329,7 @@
   }
 }
 
-const EVP_PKEY_CTX_METHOD bssl::x25519_pkey_meth = {
+const EVP_PKEY_CTX_METHOD x25519_pkey_meth = {
     /*pkey_id=*/EVP_PKEY_X25519,
     /*init=*/nullptr,
     /*copy=*/pkey_x25519_copy,
@@ -352,3 +346,10 @@
     /*paramgen=*/nullptr,
     /*ctrl=*/pkey_x25519_ctrl,
 };
+
+}  // namespace
+
+const EVP_PKEY_ALG *EVP_pkey_x25519() {
+  static const EVP_PKEY_ALG kAlg = {&x25519_asn1_meth, &x25519_pkey_meth};
+  return &kAlg;
+}