From 13066cee601cb7b2d6980fbb7eba51db4b489ebd Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 23 Aug 1999 23:11:32 +0000 Subject: [PATCH] Initial support for DH_METHOD. Also added a DH lock. A few changes made to DSA_METHOD to make it more consistent with RSA_METHOD. --- CHANGES | 5 +++ crypto/cryptlib.c | 3 +- crypto/crypto.h | 3 +- crypto/dh/dh.h | 43 +++++++++++++++++++++-- crypto/dh/dh_key.c | 61 +++++++++++++++++++++++++++++++-- crypto/dh/dh_lib.c | 79 ++++++++++++++++++++++++++++++++++++++++--- crypto/dsa/dsa_lib.c | 9 ++--- crypto/dsa/dsa_ossl.c | 4 ++- 8 files changed, 189 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 4da34e86e3..5ad39ca2bd 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,11 @@ Changes between 0.9.4 and 0.9.5 [xx XXX 1999] + *) Initial support for DH_METHOD. Again based on RSA_METHOD. Also added + a few extra parameters to the DH structure: these will be useful if + for example we want the value of 'q' or implement X9.42 DH. + [Steve Henson] + *) Initial support for DSA_METHOD. This is based on the RSA_METHOD and provides hooks that allow the default DSA functions or functions on a "per key" basis to be replaced. This allows hardware acceleration and diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 356c476a99..b9586ce1bb 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -92,7 +92,8 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] = "getservbyname", "readdir", "RSA_blinding", -#if CRYPTO_NUM_LOCKS != 24 + "dh", +#if CRYPTO_NUM_LOCKS != 25 # error "Inconsistency between crypto.h and cryptlib.c" #endif }; diff --git a/crypto/crypto.h b/crypto/crypto.h index 8ad8c25e5a..f7f52dbdd4 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -111,7 +111,8 @@ extern "C" { #define CRYPTO_LOCK_GETSERVBYNAME 21 #define CRYPTO_LOCK_READDIR 22 #define CRYPTO_LOCK_RSA_BLINDING 23 -#define CRYPTO_NUM_LOCKS 24 +#define CRYPTO_LOCK_DH 24 +#define CRYPTO_NUM_LOCKS 25 #define CRYPTO_LOCK 1 #define CRYPTO_UNLOCK 2 diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h index 2cc3797a94..5d17a27a2a 100644 --- a/crypto/dh/dh.h +++ b/crypto/dh/dh.h @@ -68,10 +68,28 @@ extern "C" { #endif #include +#include #define DH_FLAG_CACHE_MONT_P 0x01 -typedef struct dh_st +typedef struct dh_st DH; + +typedef struct dh_method { + const char *name; + /* Methods here */ + int (*generate_key)(DH *dh); + int (*compute_key)(unsigned char *key,BIGNUM *pub_key,DH *dh); + int (*bn_mod_exp)(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); /* Can be null */ + + int (*init)(DH *dh); + int (*finish)(DH *dh); + int flags; + char *app_data; +} DH_METHOD; + +struct dh_st { /* This first argument is used to pick up errors when * a DH is passed instead of a EVP_PKEY */ @@ -85,7 +103,17 @@ typedef struct dh_st int flags; char *method_mont_p; - } DH; + /* Place holders if we want to do X9.42 DH */ + BIGNUM *q; + BIGNUM *j; + unsigned *seed; + int seedlen; + BIGNUM *counter; + + int references; + CRYPTO_EX_DATA ex_data; + DH_METHOD *meth; + }; #define DH_GENERATOR_2 2 /* #define DH_GENERATOR_3 3 */ @@ -113,9 +141,20 @@ typedef struct dh_st (unsigned char *)(x)) #endif +DH_METHOD *DH_OpenSSL(void); + +void DH_set_default_method(DH_METHOD *meth); +DH_METHOD *DH_get_default_method(void); +DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth); +DH *DH_new_method(DH_METHOD *meth); + DH * DH_new(void); void DH_free(DH *dh); int DH_size(DH *dh); +int DH_get_ex_new_index(long argl, char *argp, int (*new_func)(), + int (*dup_func)(), void (*free_func)()); +int DH_set_ex_data(DH *d, int idx, char *arg); +char *DH_get_ex_data(DH *d, int idx); DH * DH_generate_parameters(int prime_len,int generator, void (*callback)(int,int,void *),void *cb_arg); int DH_check(DH *dh,int *codes); diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index cede53bfc1..4e6a0fc0ef 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -62,7 +62,41 @@ #include #include +static int generate_key(DH *dh); +static int compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh); +static int dh_bn_mod_exp(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +static int dh_init(DH *dh); +static int dh_finish(DH *dh); + int DH_generate_key(DH *dh) + { + return dh->meth->generate_key(dh); + } + +int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) + { + return dh->meth->compute_key(key, pub_key, dh); + } + +static DH_METHOD dh_ossl = { +"OpenSSL DH Method", +generate_key, +compute_key, +dh_bn_mod_exp, +dh_init, +dh_finish, +0, +NULL +}; + +DH_METHOD *DH_OpenSSL(void) +{ + return &dh_ossl; +} + +static int generate_key(DH *dh) { int ok=0; unsigned int i; @@ -103,7 +137,8 @@ int DH_generate_key(DH *dh) } mont=(BN_MONT_CTX *)dh->method_mont_p; - if (!BN_mod_exp_mont(pub_key,dh->g,priv_key,dh->p,&ctx,mont)) goto err; + if (!dh->meth->bn_mod_exp(dh, pub_key,dh->g,priv_key,dh->p,&ctx,mont)) + goto err; dh->pub_key=pub_key; dh->priv_key=priv_key; @@ -118,7 +153,7 @@ err: return(ok); } -int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) +static int compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) { BN_CTX ctx; BN_MONT_CTX *mont; @@ -141,7 +176,7 @@ int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) } mont=(BN_MONT_CTX *)dh->method_mont_p; - if (!BN_mod_exp_mont(tmp,pub_key,dh->priv_key,dh->p,&ctx,mont)) + if (!dh->meth->bn_mod_exp(dh, tmp,pub_key,dh->priv_key,dh->p,&ctx,mont)) { DHerr(DH_F_DH_COMPUTE_KEY,ERR_R_BN_LIB); goto err; @@ -152,3 +187,23 @@ err: BN_CTX_free(&ctx); return(ret); } + +static int dh_bn_mod_exp(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) +{ + return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); +} + +static int dh_init(DH *dh) +{ + dh->flags |= DH_FLAG_CACHE_MONT_P; + return(1); +} + +static int dh_finish(DH *dh) +{ + if(dh->method_mont_p) + BN_MONT_CTX_free((BN_MONT_CTX *)dh->method_mont_p); + return(1); +} diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 61e0720e8a..ef622629f7 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -63,16 +63,49 @@ const char *DH_version="Diffie-Hellman" OPENSSL_VERSION_PTEXT; +static DH_METHOD *default_DH_method; +static int dh_meth_num = 0; +static STACK *dh_meth = NULL; + +void DH_set_default_method(DH_METHOD *meth) +{ + default_DH_method = meth; +} + +DH_METHOD *DH_get_default_method(void) +{ + if(!default_DH_method) default_DH_method = DH_OpenSSL(); + return default_DH_method; +} + +DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth) +{ + DH_METHOD *mtmp; + mtmp = dh->meth; + if (mtmp->finish) mtmp->finish(dh); + dh->meth = meth; + if (meth->init) meth->init(dh); + return mtmp; +} + DH *DH_new(void) +{ + return DH_new_method(NULL); +} + +DH *DH_new_method(DH_METHOD *meth) { DH *ret; - ret=(DH *)Malloc(sizeof(DH)); + if (ret == NULL) { DHerr(DH_F_DH_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } + if(!default_DH_method) default_DH_method = DH_OpenSSL(); + if(meth) ret->meth = meth; + else ret->meth = default_DH_method; ret->pad=0; ret->version=0; ret->p=NULL; @@ -80,23 +113,61 @@ DH *DH_new(void) ret->length=0; ret->pub_key=NULL; ret->priv_key=NULL; - ret->flags=DH_FLAG_CACHE_MONT_P; ret->method_mont_p=NULL; + ret->references = 1; + ret->flags=ret->meth->flags; + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + Free(ret); + ret=NULL; + } + else + CRYPTO_new_ex_data(dh_meth,(char *)ret,&ret->ex_data); return(ret); } void DH_free(DH *r) { + int i; if(r == NULL) return; + i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH); +#ifdef REF_PRINT + REF_PRINT("DH",r); +#endif + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"DH_free, bad reference count\n"); + abort(); + } +#endif + if (r->p != NULL) BN_clear_free(r->p); if (r->g != NULL) BN_clear_free(r->g); if (r->pub_key != NULL) BN_clear_free(r->pub_key); if (r->priv_key != NULL) BN_clear_free(r->priv_key); - if (r->method_mont_p != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)r->method_mont_p); Free(r); } +int DH_get_ex_new_index(long argl, char *argp, int (*new_func)(), + int (*dup_func)(), void (*free_func)()) + { + dh_meth_num++; + return(CRYPTO_get_ex_new_index(dh_meth_num-1, + &dh_meth,argl,argp,new_func,dup_func,free_func)); + } + +int DH_set_ex_data(DH *d, int idx, char *arg) + { + return(CRYPTO_set_ex_data(&d->ex_data,idx,arg)); + } + +char *DH_get_ex_data(DH *d, int idx) + { + return(CRYPTO_get_ex_data(&d->ex_data,idx)); + } + int DH_size(DH *dh) { return(BN_num_bytes(dh->p)); diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index ff8b254b40..5ce81fb856 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -102,14 +102,14 @@ DSA *DSA_new_method(DSA_METHOD *meth) DSA *ret; ret=(DSA *)Malloc(sizeof(DSA)); - if(!default_DSA_method) default_DSA_method = DSA_OpenSSL(); - if(meth) ret->meth = meth; - else ret->meth = default_DSA_method; if (ret == NULL) { DSAerr(DSA_F_DSA_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } + if(!default_DSA_method) default_DSA_method = DSA_OpenSSL(); + if(meth) ret->meth = meth; + else ret->meth = default_DSA_method; ret->pad=0; ret->version=0; ret->write_params=1; @@ -125,7 +125,6 @@ DSA *DSA_new_method(DSA_METHOD *meth) ret->method_mont_p=NULL; ret->references=1; - /* ret->flags=DSA_FLAG_CACHE_MONT_P; */ ret->flags=ret->meth->flags; if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { @@ -168,8 +167,6 @@ void DSA_free(DSA *r) 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); - if (r->method_mont_p != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)r->method_mont_p); Free(r); } diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 06575bdc98..74a84b6e04 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -295,12 +295,14 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, static int dsa_init(DSA *dsa) { - dsa->flags=DSA_FLAG_CACHE_MONT_P; + dsa->flags|=DSA_FLAG_CACHE_MONT_P; return(1); } static int dsa_finish(DSA *dsa) { + if(dsa->method_mont_p) + BN_MONT_CTX_free((BN_MONT_CTX *)dsa->method_mont_p); return(1); } -- 2.25.1