Add functions returning security bits.
[openssl.git] / crypto / evp / p_lib.c
index 1a1e61a..42a8be1 100644 (file)
 #include <openssl/dh.h>
 #endif
 
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+
 #include "asn1_locl.h"
 
 static void EVP_PKEY_free_it(EVP_PKEY *x);
@@ -85,6 +89,15 @@ int EVP_PKEY_bits(EVP_PKEY *pkey)
        return 0;
        }
 
+int EVP_PKEY_security_bits(const EVP_PKEY *pkey)
+       {
+       if (pkey == NULL)
+               return 0;
+       if (!pkey->ameth || !pkey->ameth->pkey_security_bits)
+               return -2;
+       return pkey->ameth->pkey_security_bits(pkey);
+       }
+
 int EVP_PKEY_size(EVP_PKEY *pkey)
        {
        if (pkey && pkey->ameth && pkey->ameth->pkey_size)
@@ -149,7 +162,7 @@ int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
                return -1;
        if (a->ameth && a->ameth->param_cmp)
                return a->ameth->param_cmp(a, b);
-       return -1;
+       return -2;
        }
 
 int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
@@ -157,11 +170,20 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
        if (a->type != b->type)
                return -1;
 
-       if (EVP_PKEY_cmp_parameters(a, b) == 0)
-               return 0;
-
-       if (a->ameth && a->ameth->pub_cmp)
-               return a->ameth->pub_cmp(a, b);
+       if (a->ameth)
+               {
+               int ret;
+               /* Compare parameters if the algorithm has them */
+               if (a->ameth->param_cmp)
+                       {
+                       ret = a->ameth->param_cmp(a, b);
+                       if (ret <= 0)
+                               return ret;
+                       }
+
+               if (a->ameth->pub_cmp)
+                       return a->ameth->pub_cmp(a, b);
+               }
 
        return -2;
        }
@@ -177,26 +199,82 @@ EVP_PKEY *EVP_PKEY_new(void)
                return(NULL);
                }
        ret->type=EVP_PKEY_NONE;
+       ret->save_type=EVP_PKEY_NONE;
        ret->references=1;
        ret->ameth=NULL;
+       ret->engine=NULL;
        ret->pkey.ptr=NULL;
        ret->attributes=NULL;
        ret->save_parameters=1;
        return(ret);
        }
 
-int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
+/* Setup a public key ASN1 method and ENGINE from a NID or a string.
+ * If pkey is NULL just return 1 or 0 if the algorithm exists.
+ */
+
+static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
        {
        const EVP_PKEY_ASN1_METHOD *ameth;
-       if (pkey == NULL) return(0);
-       if (pkey->pkey.ptr != NULL)
-               EVP_PKEY_free_it(pkey);
-       ameth = EVP_PKEY_asn1_find(type);
-       pkey->ameth = ameth;
-       pkey->type = ameth->pkey_id;
-       pkey->save_type=type;
+       ENGINE *e = NULL;
+       if (pkey)
+               {
+               if (pkey->pkey.ptr)
+                       EVP_PKEY_free_it(pkey);
+               /* If key type matches and a method exists then this
+                * lookup has succeeded once so just indicate success.
+                */
+               if ((type == pkey->save_type) && pkey->ameth)
+                       return 1;
+#ifndef OPENSSL_NO_ENGINE
+               /* If we have an ENGINE release it */
+               if (pkey->engine)
+                       {
+                       ENGINE_finish(pkey->engine);
+                       pkey->engine = NULL;
+                       }
+#endif
+               }
+       if (str)
+               ameth = EVP_PKEY_asn1_find_str(&e, str, len);
+       else
+               ameth = EVP_PKEY_asn1_find(&e, type);
+#ifndef OPENSSL_NO_ENGINE
+       if (!pkey && e)
+               ENGINE_finish(e);
+#endif
+       if (!ameth)
+               {
+               EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
+               return 0;
+               }
+       if (pkey)
+               {
+               pkey->ameth = ameth;
+               pkey->engine = e;
+
+               pkey->type = pkey->ameth->pkey_id;
+               pkey->save_type=type;
+               }
+       return 1;
+       }
+
+int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
+       {
+       return pkey_set_type(pkey, type, NULL, -1);
+       }
+
+int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
+       {
+       return pkey_set_type(pkey, EVP_PKEY_NONE, str, len);
+       }
+
+int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
+       {
+       if (!EVP_PKEY_set_type(pkey, type))
+               return 0;
        pkey->pkey.ptr=key;
-       return(key != NULL);
+       return (key != NULL);
        }
 
 void *EVP_PKEY_get0(EVP_PKEY *pkey)
@@ -279,7 +357,7 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
 
 DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
        {
-       if(pkey->type != EVP_PKEY_DH) {
+       if(pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
                EVPerr(EVP_F_EVP_PKEY_GET1_DH, EVP_R_EXPECTING_A_DH_KEY);
                return NULL;
        }
@@ -290,11 +368,29 @@ DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
 
 int EVP_PKEY_type(int type)
        {
+       int ret;
        const EVP_PKEY_ASN1_METHOD *ameth;
-       ameth = EVP_PKEY_asn1_find(type);
+       ENGINE *e;
+       ameth = EVP_PKEY_asn1_find(&e, type);
        if (ameth)
-               return ameth->pkey_id;
-       return NID_undef;
+               ret = ameth->pkey_id;
+       else
+               ret = NID_undef;
+#ifndef OPENSSL_NO_ENGINE
+       if (e)
+               ENGINE_finish(e);
+#endif
+       return ret;
+       }
+
+int EVP_PKEY_id(const EVP_PKEY *pkey)
+       {
+       return pkey->type;
+       }
+
+int EVP_PKEY_base_id(const EVP_PKEY *pkey)
+       {
+       return EVP_PKEY_type(pkey->type);
        }
 
 void EVP_PKEY_free(EVP_PKEY *x)
@@ -324,15 +420,25 @@ void EVP_PKEY_free(EVP_PKEY *x)
 static void EVP_PKEY_free_it(EVP_PKEY *x)
        {
        if (x->ameth && x->ameth->pkey_free)
+               {
                x->ameth->pkey_free(x);
+               x->pkey.ptr = NULL;
+               }
+#ifndef OPENSSL_NO_ENGINE
+       if (x->engine)
+               {
+               ENGINE_finish(x->engine);
+               x->engine = NULL;
+               }
+#endif
        }
 
 static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
                                const char *kstr)
        {
        BIO_indent(out, indent, 128);
-       BIO_printf(out, "%s %s, algorithm, unsupported\n",
-                                               OBJ_nid2ln(pkey->type), kstr);
+       BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
+                                               kstr, OBJ_nid2ln(pkey->type));
        return 1;
        }
 
@@ -361,3 +467,12 @@ int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
                return pkey->ameth->param_print(out, pkey, indent, pctx);
        return unsup_alg(out, pkey, indent, "Parameters");
        }
+
+int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
+       {
+       if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
+               return -2;
+       return pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID,
+                                               0, pnid);
+       }
+