Initialize old_priv_encode, old_priv_decode.
[openssl.git] / crypto / asn1 / ameth_lib.c
index 60d159477cb6ad3c4bcc5de2693fd7a708756602..5a3132ab034bdbd8f661d85f2fdf944039212893 100644 (file)
@@ -59,7 +59,9 @@
 #include "cryptlib.h"
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
-#include <openssl/ec.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
 #include "asn1_locl.h"
 
 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
@@ -68,7 +70,7 @@ extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
 
 /* Keep this sorted in type order !! */
-const EVP_PKEY_ASN1_METHOD *standard_methods[] = 
+static const EVP_PKEY_ASN1_METHOD *standard_methods[] = 
        {
 #ifndef OPENSSL_NO_RSA
        &rsa_asn1_meths[0],
@@ -132,7 +134,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
        return (const EVP_PKEY_ASN1_METHOD *)sk_value(app_methods, idx);
        }
 
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
+static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
        {
        EVP_PKEY_ASN1_METHOD tmp, *t = &tmp, **ret;
        tmp.pkey_id = type;
@@ -151,21 +153,78 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
                        (int (*)(const void *, const void *))ameth_cmp);
        if (!ret || !*ret)
                return NULL;
-       if ((*ret)->pkey_flags & ASN1_PKEY_ALIAS)
-               return EVP_PKEY_asn1_find((*ret)->pkey_base_id);
        return *ret;
        }
 
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(const char *str, int len)
+/* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
+ * also search through engines and set *pe to a functional reference
+ * to the engine implementing 'type' or NULL if no engine implements 
+ * it.
+ */
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
+       {
+       const EVP_PKEY_ASN1_METHOD *t;
+       ENGINE *e;
+
+       for (;;)
+               {
+               t = pkey_asn1_find(type);
+               if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
+                       break;
+               type = t->pkey_base_id;
+               }
+       if (pe)
+               {
+#ifndef OPENSSL_NO_ENGINE
+               /* type will contain the final unaliased type */
+               e = ENGINE_get_pkey_asn1_meth_engine(type);
+               if (e)
+                       {
+                       *pe = e;
+                       return ENGINE_get_pkey_asn1_meth(e, type);
+                       }
+#endif
+               *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;
+               for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+                       {
+                       ameth = ENGINE_get_pkey_asn1_meth_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 ((strlen(ameth->pem_str) == len) && 
+               if (((int)strlen(ameth->pem_str) == len) && 
                        !strncasecmp(ameth->pem_str, str, len))
                        return ameth;
                }
@@ -189,11 +248,10 @@ int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
 int EVP_PKEY_asn1_add_alias(int to, int from)
        {
        EVP_PKEY_ASN1_METHOD *ameth;
-       ameth = EVP_PKEY_asn1_new(from, NULL, NULL);
+       ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
        if (!ameth)
                return 0;
        ameth->pkey_base_id = to;
-       ameth->pkey_flags |= ASN1_PKEY_ALIAS;
        return EVP_PKEY_asn1_add0(ameth);
        }
 
@@ -216,7 +274,7 @@ int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
        return 1;
        }
 
-EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
+EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id, int flags,
                                        const char *pem_str, const char *info)
        {
        EVP_PKEY_ASN1_METHOD *ameth;
@@ -226,7 +284,7 @@ EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
 
        ameth->pkey_id = id;
        ameth->pkey_base_id = id;
-       ameth->pkey_flags = ASN1_PKEY_DYNAMIC;
+       ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
 
        if (info)
                {
@@ -251,6 +309,9 @@ EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
        ameth->priv_encode = 0;
        ameth->priv_print = 0;
 
+       ameth->old_priv_encode = 0;
+       ameth->old_priv_decode = 0;
+
        ameth->pkey_size = 0;
        ameth->pkey_bits = 0;
 
@@ -338,7 +399,7 @@ void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
        }
 
 void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
-               void (*pkey_ctrl)(EVP_PKEY *pkey, int op,
+               int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
                                                        long arg1, void *arg2))
        {
        ameth->pkey_ctrl = pkey_ctrl;