Remove references to o_time.h
[openssl.git] / crypto / asn1 / ameth_lib.c
index d7537202de2885fbb50dc962c3ff8bb169ad0f32..5fff22612010cb7bd069d35f24e1e28f980c414b 100644 (file)
@@ -1,4 +1,4 @@
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2006.
  */
 /* ====================================================================
 #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[];
 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
 extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD cmac_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],
        &rsa_asn1_meths[1],
+#endif
+#ifndef OPENSSL_NO_DH
        &dh_asn1_meth,
+#endif
+#ifndef OPENSSL_NO_DSA
        &dsa_asn1_meths[0],
        &dsa_asn1_meths[1],
        &dsa_asn1_meths[2],
        &dsa_asn1_meths[3],
        &dsa_asn1_meths[4],
-       &eckey_asn1_meth
+#endif
+#ifndef OPENSSL_NO_EC
+       &eckey_asn1_meth,
+#endif
+       &hmac_asn1_meth,
+       &cmac_asn1_meth,
+#ifndef OPENSSL_NO_DH
+       &dhx_asn1_meth
+#endif
        };
 
 typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
-static STACK *app_methods = NULL;
+DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
+static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
 
 
 
@@ -99,51 +118,178 @@ void main()
        }
 #endif
 
+DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
+                          const EVP_PKEY_ASN1_METHOD *, ameth);
+
 static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
-                const EVP_PKEY_ASN1_METHOD * const *b)
+                    const EVP_PKEY_ASN1_METHOD * const *b)
        {
         return ((*a)->pkey_id - (*b)->pkey_id);
        }
 
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
+IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
+                            const EVP_PKEY_ASN1_METHOD *, ameth);
+
+int EVP_PKEY_asn1_get_count(void)
        {
-       EVP_PKEY_ASN1_METHOD tmp, *t = &tmp, **ret;
+       int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
+       if (app_methods)
+               num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
+       return num;
+       }
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
+       {
+       int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
+       if (idx < 0)
+               return NULL; 
+       if (idx < num)
+               return standard_methods[idx];
+       idx -= num;
+       return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
+       }
+
+static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
+       {
+       EVP_PKEY_ASN1_METHOD tmp;
+       const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
        tmp.pkey_id = type;
        if (app_methods)
                {
                int idx;
-               idx = sk_find(app_methods, (char *)&t);
-               if (idx > 0)
-                       return (EVP_PKEY_ASN1_METHOD *)
-                               sk_value(app_methods, idx);
+               idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
+               if (idx >= 0)
+                       return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
                }
-       ret = (EVP_PKEY_ASN1_METHOD **) OBJ_bsearch((char *)&t,
-                       (char *)standard_methods,
-                       sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *),
-                       sizeof(EVP_PKEY_ASN1_METHOD *),
-                       (int (*)(const void *, const void *))ameth_cmp);
+       ret = OBJ_bsearch_ameth(&t, standard_methods,
+                         sizeof(standard_methods)
+                         /sizeof(EVP_PKEY_ASN1_METHOD *));
        if (!ret || !*ret)
                return NULL;
-       if ((*ret)->pkey_flags & ASN1_PKEY_ALIAS)
-               return EVP_PKEY_asn1_find((*ret)->pkey_base_id);
        return *ret;
        }
 
-int EVP_PKEY_asn1_add(const EVP_PKEY_ASN1_METHOD *ameth)
+/* 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;
+
+       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
+               ENGINE *e;
+               /* 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;
+               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))
+                       return ameth;
+               }
+       return NULL;
+       }
+
+int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
        {
        if (app_methods == NULL)
                {
-               app_methods = sk_new((sk_cmp_fn_type *)ameth_cmp);
+               app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
                if (!app_methods)
                        return 0;
                }
-       if (!sk_push(app_methods, (char *)ameth))
+       if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
                return 0;
-       sk_sort(app_methods);
+       sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
        return 1;
        }
 
-EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
+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)
+               return 0;
+       ameth->pkey_base_id = to;
+       return EVP_PKEY_asn1_add0(ameth);
+       }
+
+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(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;
@@ -151,9 +297,11 @@ EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
        if (!ameth)
                return NULL;
 
+       memset(ameth, 0, sizeof(EVP_PKEY_ASN1_METHOD));
+
        ameth->pkey_id = id;
        ameth->pkey_base_id = id;
-       ameth->pkey_flags = ASN1_PKEY_DYNAMIC;
+       ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
 
        if (info)
                {
@@ -161,6 +309,8 @@ EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
                if (!ameth->info)
                        goto err;
                }
+       else
+               ameth->info = NULL;
 
        if (pem_str)
                {
@@ -168,17 +318,23 @@ EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
                if (!ameth->pem_str)
                        goto err;
                }
-       
+       else
+               ameth->pem_str = NULL;
+
        ameth->pub_decode = 0;
        ameth->pub_encode = 0;
        ameth->pub_cmp = 0;
        ameth->pub_print = 0;
 
-
        ameth->priv_decode = 0;
        ameth->priv_encode = 0;
        ameth->priv_print = 0;
-       
+
+       ameth->old_priv_encode = 0;
+       ameth->old_priv_decode = 0;
+
+       ameth->item_verify = 0;
+       ameth->item_sign = 0;
 
        ameth->pkey_size = 0;
        ameth->pkey_bits = 0;
@@ -190,7 +346,6 @@ EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
        ameth->param_cmp = 0;
        ameth->param_print = 0;
 
-
        ameth->pkey_free = 0;
        ameth->pkey_ctrl = 0;
 
@@ -203,6 +358,40 @@ EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
 
        }
 
+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))
@@ -244,8 +433,9 @@ void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
        }
 
 void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
-               int (*param_decode)(const EVP_PKEY *pk, X509_PUBKEY *pub),
-               int (*param_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
+               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),
@@ -267,7 +457,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;