Add functions to set ECDSA_METHOD structure.
[openssl.git] / crypto / ecdsa / ecs_lib.c
index 1fb9bc9600c86434c43465578446cb27cc72fbd5..d559c9e1cb4a90cfa2b3193d8142ee56dd8b6991 100644 (file)
@@ -61,7 +61,7 @@
 #include <openssl/err.h>
 #include <openssl/bn.h>
 
-const char *ECDSA_version="ECDSA" OPENSSL_VERSION_PTEXT;
+const char ECDSA_version[]="ECDSA" OPENSSL_VERSION_PTEXT;
 
 static const ECDSA_METHOD *default_ECDSA_method = NULL;
 
@@ -83,7 +83,6 @@ const ECDSA_METHOD *ECDSA_get_default_method(void)
 
 int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth)
 {
-        const ECDSA_METHOD *mtmp;
        ECDSA_DATA *ecdsa;
 
        ecdsa = ecdsa_check(eckey);
@@ -91,7 +90,6 @@ int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth)
        if (ecdsa == NULL)
                return 0;
 
-        mtmp = ecdsa->meth;
 #ifndef OPENSSL_NO_ENGINE
        if (ecdsa->engine)
        {
@@ -190,8 +188,15 @@ ECDSA_DATA *ecdsa_check(EC_KEY *key)
                ecdsa_data = (ECDSA_DATA *)ecdsa_data_new();
                if (ecdsa_data == NULL)
                        return NULL;
-               EC_KEY_insert_key_method_data(key, (void *)ecdsa_data,
-                       ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free);
+               data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data,
+                          ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free);
+               if (data != NULL)
+                       {
+                       /* Another thread raced us to install the key_method
+                        * data and won. */
+                       ecdsa_data_free(ecdsa_data);
+                       ecdsa_data = (ECDSA_DATA *)data;
+                       }
        }
        else
                ecdsa_data = (ECDSA_DATA *)data;
@@ -259,3 +264,68 @@ void *ECDSA_get_ex_data(EC_KEY *d, int idx)
                return NULL;
        return(CRYPTO_get_ex_data(&ecdsa->ex_data,idx));
 }
+
+ECDSA_METHOD *ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_meth)
+       {
+       ECDSA_METHOD  *ret;
+
+       ret = OPENSSL_malloc(sizeof(ECDSA_METHOD));
+       if (ret == NULL)
+               {
+               ECDSAerr(ECDSA_F_ECDSA_METHOD_NEW, ERR_R_MALLOC_FAILURE);
+               return NULL;
+               }
+
+       if (ecdsa_meth)
+               *ret = *ecdsa_meth;
+       else
+               {
+               ret->ecdsa_sign_setup = 0;
+               ret->ecdsa_do_sign = 0;
+               ret->ecdsa_do_verify = 0;
+               ret->name = NULL;
+               ret->flags = 0;
+               }
+       ret->flags |= ECDSA_METHOD_FLAG_ALLOCATED;
+       return ret;
+       }
+
+
+void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method,
+       ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len,
+               const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey))
+       {
+       ecdsa_method->ecdsa_do_sign = ecdsa_do_sign;
+       }
+
+void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method,
+       int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
+               BIGNUM **r))
+       {
+       ecdsa_method->ecdsa_sign_setup = ecdsa_sign_setup;
+       }
+
+void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method,
+       int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len,
+               const ECDSA_SIG *sig, EC_KEY *eckey))
+       {
+       ecdsa_method->ecdsa_do_verify = ecdsa_do_verify;
+       }
+
+void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags)
+       {
+       ecdsa_method->flags = flags | ECDSA_METHOD_FLAG_ALLOCATED;
+       }
+
+void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name)
+       {
+       ecdsa_method->name = name;
+       }
+
+void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method)
+       {
+       if (ecdsa_method->flags & ECDSA_METHOD_FLAG_ALLOCATED)
+               OPENSSL_free(ecdsa_method);
+       }
+
+