Implement tests for PKCS#5 PBKDF2 HMAC
[openssl.git] / crypto / ecdh / ech_lib.c
index f2abfed5108cc07ab015af2b3190ad507702f55d..75ff1da41dde9706fa7f7b8ce5ee4b5fcf79b4fb 100644 (file)
  *
  */
 
-#include "ecdh.h"
+#include "ech_locl.h"
 #include <string.h>
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
 #include <openssl/err.h>
 
-const char *ECDH_version="ECDH" OPENSSL_VERSION_PTEXT;
-
-static void ecdh_finish(EC_KEY *);
+const char ECDH_version[]="ECDH" OPENSSL_VERSION_PTEXT;
 
 static const ECDH_METHOD *default_ECDH_method = NULL;
 
+static void *ecdh_data_new(void);
+static void *ecdh_data_dup(void *);
+static void  ecdh_data_free(void *);
+
 void ECDH_set_default_method(const ECDH_METHOD *meth)
        {
        default_ECDH_method = meth;
@@ -94,7 +96,6 @@ const ECDH_METHOD *ECDH_get_default_method(void)
 
 int ECDH_set_method(EC_KEY *eckey, const ECDH_METHOD *meth)
        {
-       const ECDH_METHOD *mtmp;
        ECDH_DATA *ecdh;
 
        ecdh = ecdh_check(eckey);
@@ -102,8 +103,8 @@ int ECDH_set_method(EC_KEY *eckey, const ECDH_METHOD *meth)
        if (ecdh == NULL)
                return 0;
 
-        mtmp = ecdh->meth;
 #if 0
+        mtmp = ecdh->meth;
         if (mtmp->finish)
                mtmp->finish(eckey);
 #endif
@@ -122,24 +123,18 @@ int ECDH_set_method(EC_KEY *eckey, const ECDH_METHOD *meth)
         return 1;
        }
 
-ECDH_DATA *ECDH_DATA_new(void)
-       {
-       return ECDH_DATA_new_method(NULL);
-       }
-
-ECDH_DATA *ECDH_DATA_new_method(ENGINE *engine)
+static ECDH_DATA *ECDH_DATA_new_method(ENGINE *engine)
        {
        ECDH_DATA *ret;
 
        ret=(ECDH_DATA *)OPENSSL_malloc(sizeof(ECDH_DATA));
        if (ret == NULL)
                {
-               ECDHerr(ECDH_F_ECDH_DATA_NEW, ERR_R_MALLOC_FAILURE);
+               ECDHerr(ECDH_F_ECDH_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
                return(NULL);
                }
 
        ret->init = NULL;
-       ret->finish = ecdh_finish;
 
        ret->meth = ECDH_get_default_method();
        ret->engine = engine;
@@ -151,7 +146,7 @@ ECDH_DATA *ECDH_DATA_new_method(ENGINE *engine)
                ret->meth = ENGINE_get_ECDH(ret->engine);
                if (!ret->meth)
                        {
-                       ECDHerr(ECDH_F_ECDH_DATA_NEW, ERR_R_ENGINE_LIB);
+                       ECDHerr(ECDH_F_ECDH_DATA_NEW_METHOD, ERR_R_ENGINE_LIB);
                        ENGINE_finish(ret->engine);
                        OPENSSL_free(ret);
                        return NULL;
@@ -172,12 +167,26 @@ ECDH_DATA *ECDH_DATA_new_method(ENGINE *engine)
        return(ret);
        }
 
-void ECDH_DATA_free(ECDH_DATA *r)
+static void *ecdh_data_new(void)
        {
-#if 0
-       if (r->meth->finish)
-               r->meth->finish(r);
-#endif
+       return (void *)ECDH_DATA_new_method(NULL);
+       }
+
+static void *ecdh_data_dup(void *data)
+{
+       ECDH_DATA *r = (ECDH_DATA *)data;
+
+       /* XXX: dummy operation */
+       if (r == NULL)
+               return NULL;
+
+       return (void *)ecdh_data_new();
+}
+
+void ecdh_data_free(void *data)
+       {
+       ECDH_DATA *r = (ECDH_DATA *)data;
+
 #ifndef OPENSSL_NO_ENGINE
        if (r->engine)
                ENGINE_finish(r->engine);
@@ -192,26 +201,32 @@ void ECDH_DATA_free(ECDH_DATA *r)
 
 ECDH_DATA *ecdh_check(EC_KEY *key)
        {
-       if (key->meth_data)
-               {
-               if (key->meth_data->finish != ecdh_finish)
+       ECDH_DATA *ecdh_data;
+       void *data = EC_KEY_get_key_method_data(key, ecdh_data_dup,
+                                       ecdh_data_free, ecdh_data_free);
+       if (data == NULL)
+       {
+               ecdh_data = (ECDH_DATA *)ecdh_data_new();
+               if (ecdh_data == NULL)
+                       return NULL;
+               data = EC_KEY_insert_key_method_data(key, (void *)ecdh_data,
+                          ecdh_data_dup, ecdh_data_free, ecdh_data_free);
+               if (data != NULL)
                        {
-                       key->meth_data->finish(key);
-                       key->meth_data = (EC_KEY_METH_DATA *)ECDH_DATA_new();
+                       /* Another thread raced us to install the key_method
+                        * data and won. */
+                       ecdh_data_free(ecdh_data);
+                       ecdh_data = (ECDH_DATA *)data;
                        }
-               }
-       else
-               key->meth_data = (EC_KEY_METH_DATA *)ECDH_DATA_new();
-       return (ECDH_DATA *)key->meth_data;
        }
+       else
+               ecdh_data = (ECDH_DATA *)data;
+       
 
-static void ecdh_finish(EC_KEY *key)
-       {
-       if (key->meth_data && key->meth_data->finish == ecdh_finish)
-               ECDH_DATA_free((ECDH_DATA *)key->meth_data);
+       return ecdh_data;
        }
 
-
 int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
             CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
        {