/* 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 "ecdsa.h"
+#include <string.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;
+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;
return default_ECDSA_method;
}
-ECDSA *ECDSA_new(void)
+int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth)
{
- return ECDSA_new_method(NULL);
-}
+ ECDSA_DATA *ecdsa;
-int ECDSA_set_method(ECDSA *ecdsa, const ECDSA_METHOD *meth)
-{
- const ECDSA_METHOD *mtmp;
- mtmp = ecdsa->meth;
- if (mtmp->finish) mtmp->finish(ecdsa);
+ ecdsa = ecdsa_check(eckey);
+
+ if (ecdsa == NULL)
+ return 0;
+
+#ifndef OPENSSL_NO_ENGINE
if (ecdsa->engine)
{
ENGINE_finish(ecdsa->engine);
ecdsa->engine = NULL;
}
+#endif
ecdsa->meth = meth;
- if (meth->init) meth->init(ecdsa);
+
return 1;
}
-ECDSA *ECDSA_new_method(ENGINE *engine)
+static ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine)
{
- ECDSA *ret;
+ ECDSA_DATA *ret;
- ret=(ECDSA *)OPENSSL_malloc(sizeof(ECDSA));
+ ret=(ECDSA_DATA *)OPENSSL_malloc(sizeof(ECDSA_DATA));
if (ret == NULL)
{
- ECDSAerr(ECDSA_F_ECDSA_NEW,ERR_R_MALLOC_FAILURE);
+ ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
return(NULL);
}
+ ret->init = NULL;
+
ret->meth = ECDSA_get_default_method();
ret->engine = engine;
+#ifndef OPENSSL_NO_ENGINE
if (!ret->engine)
ret->engine = ENGINE_get_default_ECDSA();
if (ret->engine)
ret->meth = ENGINE_get_ECDSA(ret->engine);
if (!ret->meth)
{
- ECDSAerr(ECDSA_R_ECDSA_F_ECDSA_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;
}
}
+#endif
- ret->version = 1;
- ret->conversion_form = ECDSA_get_default_conversion_form();
- ret->group = NULL;
-
- ret->pub_key = NULL;
- ret->priv_key = NULL;
-
- ret->kinv = NULL;
- ret->r = NULL;
-
- ret->enc_flag = 0;
-
- ret->references = 1;
ret->flags = ret->meth->flags;
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data);
+#if 0
if ((ret->meth->init != NULL) && !ret->meth->init(ret))
{
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data);
OPENSSL_free(ret);
ret=NULL;
}
-
+#endif
return(ret);
}
-void ECDSA_free(ECDSA *r)
+static void *ecdsa_data_new(void)
{
- int i;
+ return (void *)ECDSA_DATA_new_method(NULL);
+}
- if (r == NULL) return;
+static void *ecdsa_data_dup(void *data)
+{
+ ECDSA_DATA *r = (ECDSA_DATA *)data;
- i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_ECDSA);
-#ifdef REF_PRINT
- REF_PRINT("ECDSA",r);
-#endif
- if (i > 0) return;
-#ifdef REF_CHECK
- if (i < 0)
- {
- fprintf(stderr,"ECDSA_free, bad reference count\n");
- abort();
- }
-#endif
+ /* XXX: dummy operation */
+ if (r == NULL)
+ return NULL;
+
+ return ecdsa_data_new();
+}
- if (r->meth->finish)
- r->meth->finish(r);
+static void ecdsa_data_free(void *data)
+{
+ ECDSA_DATA *r = (ECDSA_DATA *)data;
+
+#ifndef OPENSSL_NO_ENGINE
if (r->engine)
ENGINE_finish(r->engine);
-
+#endif
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_data);
- if (r->group != NULL) EC_GROUP_free(r->group);
- if (r->pub_key != NULL) EC_POINT_free(r->pub_key);
- if (r->priv_key != NULL) BN_clear_free(r->priv_key);
- if (r->kinv != NULL) BN_clear_free(r->kinv);
- if (r->r != NULL) BN_clear_free(r->r);
+ OPENSSL_cleanse((void *)r, sizeof(ECDSA_DATA));
+
OPENSSL_free(r);
}
-int ECDSA_size(const ECDSA *r)
+ECDSA_DATA *ecdsa_check(EC_KEY *key)
+{
+ 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)
+ {
+ 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
+ ecdsa_data = (ECDSA_DATA *)data;
+
+
+ return ecdsa_data;
+}
+
+int ECDSA_size(const EC_KEY *r)
{
int ret,i;
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(ret);
}
+
int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
{
new_func, dup_func, free_func);
}
-int ECDSA_set_ex_data(ECDSA *d, int idx, void *arg)
+int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg)
{
- return(CRYPTO_set_ex_data(&d->ex_data,idx,arg));
+ ECDSA_DATA *ecdsa;
+ ecdsa = ecdsa_check(d);
+ if (ecdsa == NULL)
+ return 0;
+ return(CRYPTO_set_ex_data(&ecdsa->ex_data,idx,arg));
}
-void *ECDSA_get_ex_data(ECDSA *d, int idx)
+void *ECDSA_get_ex_data(EC_KEY *d, int idx)
{
- return(CRYPTO_get_ex_data(&d->ex_data,idx));
+ ECDSA_DATA *ecdsa;
+ ecdsa = ecdsa_check(d);
+ if (ecdsa == NULL)
+ return NULL;
+ return(CRYPTO_get_ex_data(&ecdsa->ex_data,idx));
}
-int ECDSA_up_ref(ECDSA *ecdsa)
-{
- int i = CRYPTO_add(&ecdsa->references, 1, CRYPTO_LOCK_ECDSA);
-#ifdef REF_PRINT
- REF_PRINT("ECDSA",r);
-#endif
-#ifdef REF_CHECK
- if (i < 2)
+ECDSA_METHOD *ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_meth)
{
- fprintf(stderr, "ECDSA_up_ref, bad reference count\n");
- abort();
- }
-#endif
- return ((i > 1) ? 1 : 0);
-}
-
-void ECDSA_set_conversion_form(ECDSA *ecdsa, const point_conversion_form_t form)
-{
- if (ecdsa) ecdsa->conversion_form = form;
-}
+ ECDSA_METHOD *ret;
-point_conversion_form_t ECDSA_get_conversion_form(const ECDSA *ecdsa)
-{
- return ecdsa ? ecdsa->conversion_form : 0;
-}
+ ret = OPENSSL_malloc(sizeof(ECDSA_METHOD));
+ if (ret == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_METHOD_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
-static point_conversion_form_t default_conversion_form = POINT_CONVERSION_UNCOMPRESSED;
+ 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_set_default_conversion_form(const point_conversion_form_t form)
-{
- default_conversion_form = form;
-}
-point_conversion_form_t ECDSA_get_default_conversion_form(void)
-{
- return default_conversion_form;
-}
+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);
+ }
-unsigned int ECDSA_get_enc_flag(const ECDSA *ecdsa)
-{
- return ecdsa->enc_flag;
-}
-void ECDSA_set_enc_flag(ECDSA *ecdsa, unsigned int flag)
-{
- ecdsa->enc_flag = flag;
-}