remove ECDH_METHOD from ENGINE
[openssl.git] / crypto / ecdh / ech_lib.c
index a0e4ef45f0d5ddd5fc776582acf9e6be2a83acd6..f402caf73cb99d033bb2eacebd88a95532c46de8 100644 (file)
@@ -21,7 +21,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *
  */
 
-#include "ecdh.h"
+#include "ech_locl.h"
 #include <string.h>
-#include <openssl/engine.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 *);
-
 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;
-       }
+{
+    default_ECDH_method = meth;
+}
 
 const ECDH_METHOD *ECDH_get_default_method(void)
-       {
-       if(!default_ECDH_method) 
-               default_ECDH_method = ECDH_OpenSSL();
-       return default_ECDH_method;
-       }
+{
+    if (!default_ECDH_method)
+        default_ECDH_method = ECDH_OpenSSL();
+    return default_ECDH_method;
+}
 
 int ECDH_set_method(EC_KEY *eckey, const ECDH_METHOD *meth)
-       {
-       const ECDH_METHOD *mtmp;
-       ECDH_DATA *ecdh;
+{
+    ECDH_DATA *ecdh;
 
-       ecdh = ecdh_check(eckey);
+    ecdh = ecdh_check(eckey);
 
-       if (ecdh == NULL)
-               return 0;
+    if (ecdh == NULL)
+        return 0;
 
-        mtmp = ecdh->meth;
-#if 0
-        if (mtmp->finish)
-               mtmp->finish(eckey);
-#endif
-       if (ecdh->engine)
-               {
-               ENGINE_finish(ecdh->engine);
-               ecdh->engine = NULL;
-               }
-        ecdh->meth = meth;
-#if 0
-        if (meth->init) 
-               meth->init(eckey);
+#ifndef OPENSSL_NO_ENGINE
+    if (ecdh->engine) {
+        ENGINE_finish(ecdh->engine);
+        ecdh->engine = NULL;
+    }
 #endif
-        return 1;
-       }
-
-ECDH_DATA *ECDH_DATA_new(void)
-       {
-       return ECDH_DATA_new_method(NULL);
-       }
-
-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);
-               return(NULL);
-               }
-
-       ret->init = NULL;
-       ret->finish = ecdh_finish;
-
-       ret->meth = ECDH_get_default_method();
-       ret->engine = engine;
-       if (!ret->engine)
-               ret->engine = ENGINE_get_default_ECDH();
-       if (ret->engine)
-               {
-               ret->meth = ENGINE_get_ECDH(ret->engine);
-               if (!ret->meth)
-                       {
-                       ECDHerr(ECDH_F_ECDH_DATA_NEW, ERR_R_ENGINE_LIB);
-                       ENGINE_finish(ret->engine);
-                       OPENSSL_free(ret);
-                       return NULL;
-                       }
-               }
-
-       ret->flags = ret->meth->flags;
-       CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDH, ret, &ret->ex_data);
-#if 0
-       if ((ret->meth->init != NULL) && !ret->meth->init(ret))
-               {
-               CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDH, ret, &ret->ex_data);
-               OPENSSL_free(ret);
-               ret=NULL;
-               }
-#endif 
-       return(ret);
-       }
-
-void ECDH_DATA_free(ECDH_DATA *r)
-       {
-#if 0
-       if (r->meth->finish)
-               r->meth->finish(r);
+    ecdh->meth = meth;
+    return 1;
+}
+
+static ECDH_DATA *ECDH_DATA_new_method(ENGINE *engine)
+{
+    ECDH_DATA *ret;
+
+    ret = OPENSSL_malloc(sizeof(*ret));
+    if (ret == NULL) {
+        ECDHerr(ECDH_F_ECDH_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+        return (NULL);
+    }
+
+    ret->init = NULL;
+
+    ret->meth = ECDH_get_default_method();
+    ret->engine = engine;
+#ifndef OPENSSL_NO_ENGINE
+    if (!ret->engine)
+        ret->engine = ENGINE_get_default_ECDH();
+    if (ret->engine) {
+        ret->meth = ENGINE_get_ECDH(ret->engine);
+        if (!ret->meth) {
+            ECDHerr(ECDH_F_ECDH_DATA_NEW_METHOD, ERR_R_ENGINE_LIB);
+            ENGINE_finish(ret->engine);
+            OPENSSL_free(ret);
+            return NULL;
+        }
+    }
 #endif
-       if (r->engine)
-               ENGINE_finish(r->engine);
 
-       CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDH, r, &r->ex_data);
+    ret->flags = ret->meth->flags;
+    CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDH, ret, &ret->ex_data);
+    return (ret);
+}
+
+static void *ecdh_data_new(void)
+{
+    return (void *)ECDH_DATA_new_method(NULL);
+}
 
-       OPENSSL_cleanse((void *)r, sizeof(ECDH_DATA));
+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);
+#endif
 
-       OPENSSL_free(r);
-       }
+    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDH, r, &r->ex_data);
+    OPENSSL_clear_free((void *)r, sizeof(ECDH_DATA));
+}
 
 ECDH_DATA *ecdh_check(EC_KEY *key)
-       {
-       if (key->meth_data)
-               {
-               if (key->meth_data->finish != ecdh_finish)
-                       {
-                       key->meth_data->finish(key);
-                       key->meth_data = (EC_KEY_METH_DATA *)ECDH_DATA_new();
-                       }
-               }
-       else
-               key->meth_data = (EC_KEY_METH_DATA *)ECDH_DATA_new();
-       return (ECDH_DATA *)key->meth_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);
-       }
-
-
-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)
-       {
-       return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDH, argl, argp,
-                               new_func, dup_func, free_func);
-       }
+{
+    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) {
+            /*
+             * Another thread raced us to install the key_method data and
+             * won.
+             */
+            ecdh_data_free(ecdh_data);
+            ecdh_data = (ECDH_DATA *)data;
+        }
+    } else
+        ecdh_data = (ECDH_DATA *)data;
+
+    return ecdh_data;
+}
 
 int ECDH_set_ex_data(EC_KEY *d, int idx, void *arg)
-       {
-       ECDH_DATA *ecdh;
-       ecdh = ecdh_check(d);
-       if (ecdh == NULL)
-               return 0;
-       return(CRYPTO_set_ex_data(&ecdh->ex_data,idx,arg));
-       }
+{
+    ECDH_DATA *ecdh;
+    ecdh = ecdh_check(d);
+    if (ecdh == NULL)
+        return 0;
+    return (CRYPTO_set_ex_data(&ecdh->ex_data, idx, arg));
+}
 
 void *ECDH_get_ex_data(EC_KEY *d, int idx)
-       {
-       ECDH_DATA *ecdh;
-       ecdh = ecdh_check(d);
-       if (ecdh == NULL)
-               return NULL;
-       return(CRYPTO_get_ex_data(&ecdh->ex_data,idx));
-       }
+{
+    ECDH_DATA *ecdh;
+    ecdh = ecdh_check(d);
+    if (ecdh == NULL)
+        return NULL;
+    return (CRYPTO_get_ex_data(&ecdh->ex_data, idx));
+}