+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DH
+# define dh_evp_type EVP_PKEY_DH
+# define dh_evp_extract (extract_key_fn *)EVP_PKEY_get1_DH
+# define dh_d2i_private_key NULL
+# define dh_d2i_public_key NULL
+# define dh_d2i_key_params (d2i_of_void *)d2i_DHparams
+# define dh_free (free_key_fn *)DH_free
+
+# define dhx_evp_type EVP_PKEY_DHX
+# define dhx_evp_extract (extract_key_fn *)EVP_PKEY_get1_DH
+# define dhx_d2i_private_key NULL
+# define dhx_d2i_public_key NULL
+# define dhx_d2i_key_params (d2i_of_void *)d2i_DHxparams
+# define dhx_free (free_key_fn *)DH_free
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DSA
+# define dsa_evp_type EVP_PKEY_DSA
+# define dsa_evp_extract (extract_key_fn *)EVP_PKEY_get1_DSA
+# define dsa_d2i_private_key (d2i_of_void *)d2i_DSAPrivateKey
+# define dsa_d2i_public_key (d2i_of_void *)d2i_DSAPublicKey
+# define dsa_d2i_key_params (d2i_of_void *)d2i_DSAparams
+# define dsa_free (free_key_fn *)DSA_free
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_EC
+# define ec_evp_type EVP_PKEY_EC
+# define ec_evp_extract (extract_key_fn *)EVP_PKEY_get1_EC_KEY
+# define ec_d2i_private_key (d2i_of_void *)d2i_ECPrivateKey
+# define ec_d2i_public_key NULL
+# define ec_d2i_key_params (d2i_of_void *)d2i_ECParameters
+# define ec_free (free_key_fn *)EC_KEY_free
+
+/*
+ * ED25519, ED448, X25519, X448 only implement PKCS#8 and SubjectPublicKeyInfo,
+ * so no d2i functions to be had.
+ */
+# define ed25519_evp_type EVP_PKEY_ED25519
+# define ed25519_evp_extract (extract_key_fn *)evp_pkey_get1_ED25519
+# define ed25519_d2i_private_key NULL
+# define ed25519_d2i_public_key NULL
+# define ed25519_d2i_key_params NULL
+# define ed25519_free (free_key_fn *)ecx_key_free
+
+# define ed448_evp_type EVP_PKEY_ED448
+# define ed448_evp_extract (extract_key_fn *)evp_pkey_get1_ED448
+# define ed448_d2i_private_key NULL
+# define ed448_d2i_public_key NULL
+# define ed448_d2i_key_params NULL
+# define ed448_free (free_key_fn *)ecx_key_free
+
+# define x25519_evp_type EVP_PKEY_X25519
+# define x25519_evp_extract (extract_key_fn *)evp_pkey_get1_X25519
+# define x25519_d2i_private_key NULL
+# define x25519_d2i_public_key NULL
+# define x25519_d2i_key_params NULL
+# define x25519_free (free_key_fn *)ecx_key_free
+
+# define x448_evp_type EVP_PKEY_X448
+# define x448_evp_extract (extract_key_fn *)evp_pkey_get1_X448
+# define x448_d2i_private_key NULL
+# define x448_d2i_public_key NULL
+# define x448_d2i_key_params NULL
+# define x448_free (free_key_fn *)ecx_key_free
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#define rsa_evp_type EVP_PKEY_RSA
+#define rsa_evp_extract (extract_key_fn *)EVP_PKEY_get1_RSA
+#define rsa_d2i_private_key (d2i_of_void *)d2i_RSAPrivateKey
+#define rsa_d2i_public_key (d2i_of_void *)d2i_RSAPublicKey
+#define rsa_d2i_key_params NULL
+#define rsa_free (free_key_fn *)RSA_free
+
+#define rsapss_evp_type EVP_PKEY_RSA_PSS
+#define rsapss_evp_extract (extract_key_fn *)EVP_PKEY_get1_RSA
+#define rsapss_d2i_private_key (d2i_of_void *)d2i_RSAPrivateKey
+#define rsapss_d2i_public_key (d2i_of_void *)d2i_RSAPublicKey
+#define rsapss_d2i_key_params NULL
+#define rsapss_free (free_key_fn *)RSA_free
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * The DO_ macros help define the selection mask and the method functions
+ * for each kind of object we want to decode.
+ */
+#define DO_type_specific_keypair(keytype) \
+ "type-specific", 0, \
+ ( OSSL_KEYMGMT_SELECT_KEYPAIR ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ NULL, \
+ NULL, \
+ keytype##_free
+
+#define DO_type_specific_pub(keytype) \
+ "type-specific", 0, \
+ ( OSSL_KEYMGMT_SELECT_PUBLIC_KEY ), \
+ NULL, \
+ keytype##_d2i_public_key, \
+ NULL, \
+ NULL, \
+ keytype##_free
+
+#define DO_type_specific_priv(keytype) \
+ "type-specific", 0, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY ), \
+ keytype##_d2i_private_key, \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_free
+
+#define DO_type_specific_params(keytype) \
+ "type-specific", 0, \
+ ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ NULL, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ keytype##_free
+
+#define DO_type_specific(keytype) \
+ "type-specific", 0, \
+ ( OSSL_KEYMGMT_SELECT_ALL ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ keytype##_free
+
+#define DO_type_specific_no_pub(keytype) \
+ "type-specific", 0, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY \
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ keytype##_d2i_private_key, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ keytype##_free
+
+#define DO_PKCS8(keytype) \
+ "pkcs8", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY ), \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_evp_extract, \
+ keytype##_free
+
+#define DO_SubjectPublicKeyInfo(keytype) \
+ "SubjectPublicKeyInfo", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PUBLIC_KEY ), \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_evp_extract, \
+ keytype##_free
+
+#define DO_DH(keytype) \
+ "DH", 0, \
+ ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ NULL, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ keytype##_free
+
+#define DO_DHX(keytype) \
+ "DHX", 0, \
+ ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ NULL, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ keytype##_free
+
+#define DO_DSA(keytype) \
+ "DSA", 0, \
+ ( OSSL_KEYMGMT_SELECT_ALL ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ keytype##_free
+
+#define DO_EC(keytype) \
+ "EC", 0, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY \
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ keytype##_d2i_private_key, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ keytype##_free
+
+#define DO_RSA(keytype) \
+ "RSA", 0, \
+ ( OSSL_KEYMGMT_SELECT_KEYPAIR ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ NULL, \
+ NULL, \
+ keytype##_free
+
+/*
+ * MAKE_DECODER is the single driver for creating OSSL_DISPATCH tables.
+ * It takes the following arguments:
+ *
+ * keytype_name The implementation key type as a string.
+ * keytype The implementation key type. This must correspond exactly
+ * to our existing keymgmt keytype names... in other words,
+ * there must exist an ossl_##keytype##_keymgmt_functions.
+ * type The type name for the set of functions that implement the
+ * decoder for the key type. This isn't necessarily the same
+ * as keytype. For example, the key types ed25519, ed448,
+ * x25519 and x448 are all handled by the same functions with
+ * the common type name ecx.
+ * kind The kind of support to implement. This translates into
+ * the DO_##kind macros above, to populate the keytype_desc_st
+ * structure.
+ */
+#define MAKE_DECODER(keytype_name, keytype, type, kind) \
+ static const struct keytype_desc_st kind##_##keytype##_desc = \
+ { keytype_name, ossl_##keytype##_keymgmt_functions, \
+ DO_##kind(keytype) }; \
+ \
+ static OSSL_FUNC_decoder_newctx_fn kind##_der2##keytype##_newctx; \
+ static OSSL_FUNC_decoder_gettable_params_fn \
+ kind##_der2##keytype##_gettable_params; \
+ static OSSL_FUNC_decoder_get_params_fn \
+ kind##_der2##keytype##_get_params; \
+ \
+ static void *kind##_der2##keytype##_newctx(void *provctx) \
+ { \
+ return der2key_newctx(provctx, &kind##_##keytype##_desc); \
+ } \
+ static const OSSL_PARAM * \
+ kind##_der2##keytype##_gettable_params(void *provctx) \
+ { \
+ return \
+ der2key_gettable_params(provctx, &kind##_##keytype##_desc); \
+ } \
+ static int kind##_der2##keytype##_get_params(OSSL_PARAM params[]) \
+ { \
+ return der2key_get_params(params, &kind##_##keytype##_desc); \
+ } \
+ static int kind##_der2##keytype##_does_selection(void *provctx, \
+ int selection) \