X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fecdsa%2Fecs_lib.c;h=6fd3ceefda56932938c547f69bf8648cecc01d87;hp=e7a12f5126857990a91b7fc193a714facbbb706a;hb=8c6ef7869aa3ce4bb57b1c88a1d14f119c6e7323;hpb=aa4ce7315f65fdf8940d5bc9e562aa478f0335d3 diff --git a/crypto/ecdsa/ecs_lib.c b/crypto/ecdsa/ecs_lib.c index e7a12f5126..6fd3ceefda 100644 --- a/crypto/ecdsa/ecs_lib.c +++ b/crypto/ecdsa/ecs_lib.c @@ -1,13 +1,13 @@ /* 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 * 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 @@ -54,209 +54,258 @@ */ #include -#include "ecdsa.h" +#include "ecs_locl.h" #ifndef OPENSSL_NO_ENGINE -#include +# include #endif #include #include -const char *ECDSA_version="ECDSA" OPENSSL_VERSION_PTEXT; - -static void ecdsa_finish(EC_KEY *); - 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; + default_ECDSA_method = meth; } const ECDSA_METHOD *ECDSA_get_default_method(void) { - if(!default_ECDSA_method) - default_ECDSA_method = ECDSA_OpenSSL(); - return default_ECDSA_method; + return default_ECDSA_method; } int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth) { - const ECDSA_METHOD *mtmp; - ECDSA_DATA *ecdsa; + ECDSA_DATA *ecdsa; - ecdsa = ecdsa_check(eckey); + ecdsa = ecdsa_check(eckey); - if (ecdsa == NULL) - return 0; + if (ecdsa == NULL) + return 0; - mtmp = ecdsa->meth; -#if 0 - if (mtmp->finish) - mtmp->finish(eckey); -#endif #ifndef OPENSSL_NO_ENGINE - if (ecdsa->engine) - { - ENGINE_finish(ecdsa->engine); - ecdsa->engine = NULL; - } + if (ecdsa->engine) { + ENGINE_finish(ecdsa->engine); + ecdsa->engine = NULL; + } #endif - ecdsa->meth = meth; -#if 0 - if (meth->init) - meth->init(eckey); + ecdsa->meth = meth; + + return 1; +} + +static ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine) +{ + ECDSA_DATA *ret; + + ret = OPENSSL_malloc(sizeof(*ret)); + if (ret == NULL) { + 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_F_ECDSA_DATA_NEW_METHOD, ERR_R_ENGINE_LIB); + ENGINE_finish(ret->engine); + OPENSSL_free(ret); + return NULL; + } + } #endif - return 1; + + ret->flags = ret->meth->flags; + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data); + return (ret); } -ECDSA_DATA *ECDSA_DATA_new(void) +static void *ecdsa_data_new(void) { - return ECDSA_DATA_new_method(NULL); + return (void *)ECDSA_DATA_new_method(NULL); } -ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine) +static void *ecdsa_data_dup(void *data) { - ECDSA_DATA *ret; + ECDSA_DATA *r = (ECDSA_DATA *)data; - ret=(ECDSA_DATA *)OPENSSL_malloc(sizeof(ECDSA_DATA)); - if (ret == NULL) - { - ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE); - return(NULL); - } + /* XXX: dummy operation */ + if (r == NULL) + return NULL; - ret->init = NULL; - ret->finish = ecdsa_finish; + return ecdsa_data_new(); +} - ret->kinv = NULL; - ret->r = NULL; +static void ecdsa_data_free(void *data) +{ + ECDSA_DATA *r = (ECDSA_DATA *)data; - 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_F_ECDSA_DATA_NEW_METHOD, ERR_R_ENGINE_LIB); - ENGINE_finish(ret->engine); - OPENSSL_free(ret); - return NULL; - } - } + if (r->engine) + ENGINE_finish(r->engine); #endif + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_data); - 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); + OPENSSL_clear_free((void *)r, sizeof(ECDSA_DATA)); } -void ECDSA_DATA_free(ECDSA_DATA *r) +ECDSA_DATA *ecdsa_check(EC_KEY *key) { - if (r->kinv) - BN_clear_free(r->kinv); - if (r->r) - BN_clear_free(r->r); - -#if 0 - if (r->meth->finish) - r->meth->finish(r); -#endif -#ifndef OPENSSL_NO_ENGINE - if (r->engine) - ENGINE_finish(r->engine); -#endif + 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; +} - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_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; - OPENSSL_cleanse((void *)r, sizeof(ECDSA_DATA)); + if (r == NULL) + return 0; + group = EC_KEY_get0_group(r); + if (group == NULL) + return 0; - OPENSSL_free(r); + if ((order = BN_new()) == NULL) + return 0; + if (!EC_GROUP_get_order(group, order, NULL)) { + BN_clear_free(order); + return 0; + } + i = BN_num_bits(order); + bs.length = (i + 7) / 8; + bs.data = buf; + bs.type = V_ASN1_INTEGER; + /* If the top bit is set the asn1 encoding is 1 larger. */ + buf[0] = 0xff; + + i = i2d_ASN1_INTEGER(&bs, NULL); + i += i; /* r and s */ + ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); + BN_clear_free(order); + return (ret); } -ECDSA_DATA *ecdsa_check(EC_KEY *key) +int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg) { - if (key->meth_data) - { - if (key->meth_data->finish != ecdsa_finish) - { - key->meth_data->finish(key); - key->meth_data = (EC_KEY_METH_DATA *)ECDSA_DATA_new(); - } - } - else - key->meth_data = (EC_KEY_METH_DATA *)ECDSA_DATA_new(); - return (ECDSA_DATA *)key->meth_data; + ECDSA_DATA *ecdsa; + ecdsa = ecdsa_check(d); + if (ecdsa == NULL) + return 0; + return (CRYPTO_set_ex_data(&ecdsa->ex_data, idx, arg)); } -static void ecdsa_finish(EC_KEY *key) +void *ECDSA_get_ex_data(EC_KEY *d, int idx) { - if (key->meth_data && key->meth_data->finish == ecdsa_finish) - ECDSA_DATA_free((ECDSA_DATA *)key->meth_data); + ECDSA_DATA *ecdsa; + ecdsa = ecdsa_check(d); + if (ecdsa == NULL) + return NULL; + return (CRYPTO_get_ex_data(&ecdsa->ex_data, idx)); } -int ECDSA_size(const EC_KEY *r) +ECDSA_METHOD *ECDSA_METHOD_new(const ECDSA_METHOD *ecdsa_meth) { - int ret,i; - ASN1_INTEGER bs; - BIGNUM *order=NULL; - unsigned char buf[4]; - - if (r == NULL || r->group == NULL) - return 0; - if ((order = BN_new()) == NULL) return 0; - if (!EC_GROUP_get_order(r->group,order,NULL)) - { - BN_clear_free(order); - return 0; - } - i=BN_num_bits(order); - bs.length=(i+7)/8; - bs.data=buf; - bs.type=V_ASN1_INTEGER; - /* If the top bit is set the asn1 encoding is 1 larger. */ - buf[0]=0xff; - - i=i2d_ASN1_INTEGER(&bs,NULL); - i+=i; /* r and s */ - ret=ASN1_object_size(1,i,V_ASN1_SEQUENCE); - BN_clear_free(order); - return(ret); + ECDSA_METHOD *ret; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ECDSAerr(ECDSA_F_ECDSA_METHOD_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (ecdsa_meth) + *ret = *ecdsa_meth; + 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; +} -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) +void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method, + int (*ecdsa_sign_setup) (EC_KEY *eckey, + BN_CTX *ctx, + BIGNUM **kinv, + BIGNUM **r)) { - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDSA, argl, argp, - new_func, dup_func, free_func); + ecdsa_method->ecdsa_sign_setup = ecdsa_sign_setup; } -int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg) +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_DATA *ecdsa; - ecdsa = ecdsa_check(d); - if (ecdsa == NULL) - return 0; - return(CRYPTO_set_ex_data(&ecdsa->ex_data,idx,arg)); + ecdsa_method->ecdsa_do_verify = ecdsa_do_verify; } -void *ECDSA_get_ex_data(EC_KEY *d, int idx) +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) + return; + 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) { - ECDSA_DATA *ecdsa; - ecdsa = ecdsa_check(d); - if (ecdsa == NULL) - return NULL; - return(CRYPTO_get_ex_data(&ecdsa->ex_data,idx)); + return ecdsa_method->app_data; }