DSA_METHOD to make it more consistent with RSA_METHOD.
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
"getservbyname",
"readdir",
"RSA_blinding",
-#if CRYPTO_NUM_LOCKS != 24
+ "dh",
+#if CRYPTO_NUM_LOCKS != 25
# error "Inconsistency between crypto.h and cryptlib.c"
#endif
};
#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
#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 */
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 */
(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);
#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;
}
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;
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;
}
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;
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);
+}
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;
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));
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;
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))
{
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);
}
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);
}