diff options
author | Dr. Stephen Henson <steve@openssl.org> | 1999-08-23 23:11:32 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 1999-08-23 23:11:32 +0000 |
commit | 13066cee601cb7b2d6980fbb7eba51db4b489ebd (patch) | |
tree | d9218ef55d2d3644fb8d806fe169599bc3a4fc72 /crypto/dh | |
parent | c0711f7f0fc026ab87fe6607bb5136ab790e2334 (diff) |
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.
Diffstat (limited to 'crypto/dh')
-rw-r--r-- | crypto/dh/dh.h | 43 | ||||
-rw-r--r-- | crypto/dh/dh_key.c | 61 | ||||
-rw-r--r-- | crypto/dh/dh_lib.c | 79 |
3 files changed, 174 insertions, 9 deletions
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 <openssl/bn.h> +#include <openssl/crypto.h> #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,8 +62,42 @@ #include <openssl/rand.h> #include <openssl/dh.h> +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; BN_CTX ctx; @@ -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)); |