Initial support for DH_METHOD. Also added a DH lock. A few changes made to
authorDr. Stephen Henson <steve@openssl.org>
Mon, 23 Aug 1999 23:11:32 +0000 (23:11 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 23 Aug 1999 23:11:32 +0000 (23:11 +0000)
DSA_METHOD to make it more consistent with RSA_METHOD.

CHANGES
crypto/cryptlib.c
crypto/crypto.h
crypto/dh/dh.h
crypto/dh/dh_key.c
crypto/dh/dh_lib.c
crypto/dsa/dsa_lib.c
crypto/dsa/dsa_ossl.c

diff --git a/CHANGES b/CHANGES
index 4da34e86e376a13af8840f5384c115058770b74b..5ad39ca2bdc4394947f9d0000f89271fa0782b28 100644 (file)
--- 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
index 356c476a993db3f2511bc2e946a0d6f61639d1b6..b9586ce1bbc3f4011d0788ae52ad5f000b726065 100644 (file)
@@ -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
        };
index 8ad8c25e5a4a2d859613de7dacc1a3853c602ff9..f7f52dbdd4f60bdd38817d077fcfa879767cff00 100644 (file)
@@ -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
index 2cc3797a94e30311b9f83d3eb2640f7862e6f9d0..5d17a27a2a93416e65c431d15b745db409de0413 100644 (file)
@@ -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);
index cede53bfc17fec445bfab8b7d067900fb36b583d..4e6a0fc0ef35a6ac6ee4c5797181b4b05a3f753e 100644 (file)
 #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;
@@ -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);
+}
index 61e0720e8a7960bceba032b0b000945004eb44d5..ef622629f7ed1541912cc5297c71c63e15b7bb0d 100644 (file)
 
 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));
index ff8b254b40d904a60ffb3c81ad6e992bb0a39e8f..5ce81fb8562ad85835491f59382cf30b5ab452ed 100644 (file)
@@ -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);
        }
 
index 06575bdc98c31f24ccbba7db03eaacd33615a4e3..74a84b6e042f884f7e6d6c68a6849054ca0cf772 100644 (file)
@@ -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);
 }