*
*/
/* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*
*/
-#include "ecdh.h"
+#include "ech_locl.h"
#include <string.h>
+#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
+#endif
+#include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
-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;
const ECDH_METHOD *ECDH_get_default_method(void)
{
if(!default_ECDH_method)
+ {
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ return FIPS_ecdh_openssl();
+ else
+ return ECDH_OpenSSL();
+#else
default_ECDH_method = ECDH_OpenSSL();
+#endif
+ }
return default_ECDH_method;
}
int ECDH_set_method(EC_KEY *eckey, const ECDH_METHOD *meth)
{
- const ECDH_METHOD *mtmp;
ECDH_DATA *ecdh;
ecdh = ecdh_check(eckey);
if (ecdh == NULL)
return 0;
- mtmp = ecdh->meth;
#if 0
+ mtmp = ecdh->meth;
if (mtmp->finish)
mtmp->finish(eckey);
#endif
+#ifndef OPENSSL_NO_ENGINE
if (ecdh->engine)
{
ENGINE_finish(ecdh->engine);
ecdh->engine = NULL;
}
+#endif
ecdh->meth = meth;
#if 0
if (meth->init)
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;
+#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, ERR_R_ENGINE_LIB);
+ ECDHerr(ECDH_F_ECDH_DATA_NEW_METHOD, ERR_R_ENGINE_LIB);
ENGINE_finish(ret->engine);
OPENSSL_free(ret);
return NULL;
}
}
+#endif
ret->flags = ret->meth->flags;
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDH, ret, &ret->ex_data);
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);
+#endif
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDH, r, &r->ex_data);
- memset((void *)r, 0x0, sizeof(ECDH_DATA));
+ OPENSSL_cleanse((void *)r, sizeof(ECDH_DATA));
OPENSSL_free(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;
- }
-
-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);
}
+ else
+ ecdh_data = (ECDH_DATA *)data;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !(ecdh_data->flags & ECDH_FLAG_FIPS_METHOD)
+ && !(EC_KEY_get_flags(key) & EC_FLAG_NON_FIPS_ALLOW))
+ {
+ ECDHerr(ECDH_F_ECDH_CHECK, ECDH_R_NON_FIPS_METHOD);
+ return NULL;
+ }
+#endif
+
-
-int ECDH_size(const EC_KEY *ecdh)
- {
- return 20;
+ 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)
{