/* crypto/ecdsa/ecs_lib.c */
/* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2005 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 <string.h>
-#include "ecdsa.h"
+#include "ecs_locl.h"
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
#include <openssl/err.h>
#include <openssl/bn.h>
-const char *ECDSA_version="ECDSA" OPENSSL_VERSION_PTEXT;
-
-static void ecdsa_finish(EC_KEY *);
+const char ECDSA_version[]="ECDSA" OPENSSL_VERSION_PTEXT;
static const ECDSA_METHOD *default_ECDSA_method = NULL;
+static void *ecdsa_data_new(void);
+static void *ecdsa_data_dup(void *);
+static void ecdsa_data_free(void *);
+
void ECDSA_set_default_method(const ECDSA_METHOD *meth)
{
default_ECDSA_method = meth;
int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth)
{
- const ECDSA_METHOD *mtmp;
ECDSA_DATA *ecdsa;
ecdsa = ecdsa_check(eckey);
if (ecdsa == NULL)
return 0;
- mtmp = ecdsa->meth;
-#if 0
- if (mtmp->finish)
- mtmp->finish(eckey);
-#endif
#ifndef OPENSSL_NO_ENGINE
if (ecdsa->engine)
{
}
#endif
ecdsa->meth = meth;
-#if 0
- if (meth->init)
- meth->init(eckey);
-#endif
- return 1;
-}
-ECDSA_DATA *ECDSA_DATA_new(void)
-{
- return ECDSA_DATA_new_method(NULL);
+ return 1;
}
-ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine)
+static ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine)
{
ECDSA_DATA *ret;
ret=(ECDSA_DATA *)OPENSSL_malloc(sizeof(ECDSA_DATA));
if (ret == NULL)
{
- ECDSAerr(ECDSA_F_ECDSA_DATA_NEW, ERR_R_MALLOC_FAILURE);
+ ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
return(NULL);
}
ret->init = NULL;
- ret->finish = ecdsa_finish;
-
- ret->kinv = NULL;
- ret->r = NULL;
ret->meth = ECDSA_get_default_method();
ret->engine = engine;
ret->meth = ENGINE_get_ECDSA(ret->engine);
if (!ret->meth)
{
- ECDSAerr(ECDSA_F_ECDSA_DATA_NEW, ERR_R_ENGINE_LIB);
+ ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_ENGINE_LIB);
ENGINE_finish(ret->engine);
OPENSSL_free(ret);
return NULL;
return(ret);
}
-void ECDSA_DATA_free(ECDSA_DATA *r)
+static void *ecdsa_data_new(void)
{
- if (r->kinv)
- BN_clear_free(r->kinv);
- if (r->r)
- BN_clear_free(r->r);
+ return (void *)ECDSA_DATA_new_method(NULL);
+}
+
+static void *ecdsa_data_dup(void *data)
+{
+ ECDSA_DATA *r = (ECDSA_DATA *)data;
+
+ /* XXX: dummy operation */
+ if (r == NULL)
+ return NULL;
+
+ return ecdsa_data_new();
+}
+
+static void ecdsa_data_free(void *data)
+{
+ ECDSA_DATA *r = (ECDSA_DATA *)data;
-#if 0
- if (r->meth->finish)
- r->meth->finish(r);
-#endif
#ifndef OPENSSL_NO_ENGINE
if (r->engine)
ENGINE_finish(r->engine);
#endif
-
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_data);
OPENSSL_cleanse((void *)r, sizeof(ECDSA_DATA));
ECDSA_DATA *ecdsa_check(EC_KEY *key)
{
- if (key->meth_data)
+ ECDSA_DATA *ecdsa_data;
+
+ void *data = EC_KEY_get_key_method_data(key, ecdsa_data_dup,
+ ecdsa_data_free, ecdsa_data_free);
+ if (data == NULL)
{
- if (key->meth_data->finish != ecdsa_finish)
- {
- key->meth_data->finish(key);
- key->meth_data = (EC_KEY_METH_DATA *)ECDSA_DATA_new();
- }
+ ecdsa_data = (ECDSA_DATA *)ecdsa_data_new();
+ if (ecdsa_data == NULL)
+ return NULL;
+ 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
- key->meth_data = (EC_KEY_METH_DATA *)ECDSA_DATA_new();
- return (ECDSA_DATA *)key->meth_data;
-}
+ ecdsa_data = (ECDSA_DATA *)data;
+
-static void ecdsa_finish(EC_KEY *key)
-{
- if (key->meth_data && key->meth_data->finish == ecdsa_finish)
- ECDSA_DATA_free((ECDSA_DATA *)key->meth_data);
+ return ecdsa_data;
}
int ECDSA_size(const EC_KEY *r)
ASN1_INTEGER bs;
BIGNUM *order=NULL;
unsigned char buf[4];
+ const EC_GROUP *group;
- if (r == NULL || r->group == NULL)
+ if (r == NULL)
+ return 0;
+ group = EC_KEY_get0_group(r);
+ if (group == NULL)
return 0;
+
if ((order = BN_new()) == NULL) return 0;
- if (!EC_GROUP_get_order(r->group,order,NULL))
+ if (!EC_GROUP_get_order(group,order,NULL))
{
BN_clear_free(order);
return 0;
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);
+ }
+
+void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app)
+ {
+ ecdsa_method->app_data = app;
+ }
+
+void * ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method)
+ {
+ return ecdsa_method->app_data;
+ }