+ *pe = NULL;
+ }
+ return t;
+}
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
+ const char *str, int len)
+{
+ int i;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ if (len == -1)
+ len = strlen(str);
+ if (pe) {
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *e;
+ ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
+ if (ameth) {
+ /*
+ * Convert structural into functional reference
+ */
+ if (!ENGINE_init(e))
+ ameth = NULL;
+ ENGINE_free(e);
+ *pe = e;
+ return ameth;
+ }
+#endif
+ *pe = NULL;
+ }
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ ameth = EVP_PKEY_asn1_get0(i);
+ if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
+ continue;
+ if (((int)strlen(ameth->pem_str) == len)
+ && (strncasecmp(ameth->pem_str, str, len) == 0))
+ return ameth;
+ }
+ return NULL;
+}
+
+int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
+{
+ if (app_methods == NULL) {
+ app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
+ if (app_methods == NULL)
+ return 0;
+ }
+ if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
+ return 0;
+ sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
+ return 1;
+}
+
+int EVP_PKEY_asn1_add_alias(int to, int from)
+{
+ EVP_PKEY_ASN1_METHOD *ameth;
+ ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
+ if (ameth == NULL)
+ return 0;
+ ameth->pkey_base_id = to;
+ if (!EVP_PKEY_asn1_add0(ameth)) {
+ EVP_PKEY_asn1_free(ameth);
+ return 0;
+ }
+ return 1;
+}
+
+int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id,
+ int *ppkey_flags, const char **pinfo,
+ const char **ppem_str,
+ const EVP_PKEY_ASN1_METHOD *ameth)
+{
+ if (!ameth)
+ return 0;
+ if (ppkey_id)
+ *ppkey_id = ameth->pkey_id;
+ if (ppkey_base_id)
+ *ppkey_base_id = ameth->pkey_base_id;
+ if (ppkey_flags)
+ *ppkey_flags = ameth->pkey_flags;
+ if (pinfo)
+ *pinfo = ameth->info;
+ if (ppem_str)
+ *ppem_str = ameth->pem_str;
+ return 1;
+}
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
+{
+ return pkey->ameth;
+}
+
+EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
+ const char *pem_str, const char *info)
+{
+ EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth));
+
+ if (ameth == NULL)
+ return NULL;
+
+ ameth->pkey_id = id;
+ ameth->pkey_base_id = id;
+ ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
+
+ if (info) {
+ ameth->info = OPENSSL_strdup(info);
+ if (!ameth->info)
+ goto err;
+ }
+
+ if (pem_str) {
+ ameth->pem_str = OPENSSL_strdup(pem_str);
+ if (!ameth->pem_str)
+ goto err;
+ }
+
+ return ameth;
+
+ err:
+ EVP_PKEY_asn1_free(ameth);
+ return NULL;
+
+}
+
+void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
+ const EVP_PKEY_ASN1_METHOD *src)
+{
+
+ dst->pub_decode = src->pub_decode;
+ dst->pub_encode = src->pub_encode;
+ dst->pub_cmp = src->pub_cmp;
+ dst->pub_print = src->pub_print;
+
+ dst->priv_decode = src->priv_decode;
+ dst->priv_encode = src->priv_encode;
+ dst->priv_print = src->priv_print;
+
+ dst->old_priv_encode = src->old_priv_encode;
+ dst->old_priv_decode = src->old_priv_decode;
+
+ dst->pkey_size = src->pkey_size;
+ dst->pkey_bits = src->pkey_bits;
+
+ dst->param_decode = src->param_decode;
+ dst->param_encode = src->param_encode;
+ dst->param_missing = src->param_missing;
+ dst->param_copy = src->param_copy;
+ dst->param_cmp = src->param_cmp;
+ dst->param_print = src->param_print;
+
+ dst->pkey_free = src->pkey_free;
+ dst->pkey_ctrl = src->pkey_ctrl;
+
+ dst->item_sign = src->item_sign;
+ dst->item_verify = src->item_verify;
+
+}
+
+void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
+{
+ if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
+ OPENSSL_free(ameth->pem_str);
+ OPENSSL_free(ameth->info);
+ OPENSSL_free(ameth);
+ }
+}
+
+void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
+ int (*pub_decode) (EVP_PKEY *pk,
+ X509_PUBKEY *pub),
+ int (*pub_encode) (X509_PUBKEY *pub,
+ const EVP_PKEY *pk),
+ int (*pub_cmp) (const EVP_PKEY *a,
+ const EVP_PKEY *b),
+ int (*pub_print) (BIO *out,
+ const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx),
+ int (*pkey_size) (const EVP_PKEY *pk),
+ int (*pkey_bits) (const EVP_PKEY *pk))
+{
+ ameth->pub_decode = pub_decode;
+ ameth->pub_encode = pub_encode;
+ ameth->pub_cmp = pub_cmp;
+ ameth->pub_print = pub_print;
+ ameth->pkey_size = pkey_size;
+ ameth->pkey_bits = pkey_bits;
+}
+
+void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
+ int (*priv_decode) (EVP_PKEY *pk,
+ const PKCS8_PRIV_KEY_INFO
+ *p8inf),
+ int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
+ const EVP_PKEY *pk),
+ int (*priv_print) (BIO *out,
+ const EVP_PKEY *pkey,
+ int indent,
+ ASN1_PCTX *pctx))
+{
+ ameth->priv_decode = priv_decode;
+ ameth->priv_encode = priv_encode;
+ ameth->priv_print = priv_print;
+}
+
+void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
+ int (*param_decode) (EVP_PKEY *pkey,
+ const unsigned char **pder,
+ int derlen),
+ int (*param_encode) (const EVP_PKEY *pkey,
+ unsigned char **pder),
+ int (*param_missing) (const EVP_PKEY *pk),
+ int (*param_copy) (EVP_PKEY *to,
+ const EVP_PKEY *from),
+ int (*param_cmp) (const EVP_PKEY *a,
+ const EVP_PKEY *b),
+ int (*param_print) (BIO *out,
+ const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx))
+{
+ ameth->param_decode = param_decode;
+ ameth->param_encode = param_encode;
+ ameth->param_missing = param_missing;
+ ameth->param_copy = param_copy;
+ ameth->param_cmp = param_cmp;
+ ameth->param_print = param_print;
+}
+
+void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
+ void (*pkey_free) (EVP_PKEY *pkey))
+{
+ ameth->pkey_free = pkey_free;
+}
+
+void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
+ int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
+ long arg1, void *arg2))
+{
+ ameth->pkey_ctrl = pkey_ctrl;
+}