* [including the GNU Public Licence.]
*/
+/* NB: These functions have been upgraded - the previous prototypes are in
+ * dh_depr.c as wrappers to these ones.
+ * - Geoff
+ */
+
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/bn.h>
#include <openssl/dh.h>
+static int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb);
+
+int DH_generate_parameters_ex(DH *ret, int prime_len, int generator, BN_GENCB *cb)
+ {
+ if(ret->meth->generate_params)
+ return ret->meth->generate_params(ret, prime_len, generator, cb);
+ return dh_builtin_genparams(ret, prime_len, generator, cb);
+ }
+
/* We generate DH parameters as follows
* find a prime q which is prime_len/2 bits long.
* p=(2*q)+1 or (p-1)/2 = q
* Having said all that,
* there is another special case method for the generators 2, 3 and 5.
* for 2, p mod 24 == 11
- * for 3, p mod 12 == 5 <<<<< does not work for strong primes.
+ * for 3, p mod 12 == 5 <<<<< does not work for safe primes.
* for 5, p mod 10 == 3 or 7
*
* Thanks to Phil Karn <karn@qualcomm.com> for the pointers about the
* special generators and for answering some of my questions.
*
* I've implemented the second simple method :-).
- * Since DH should be using a strong prime (both p and q are prime),
+ * Since DH should be using a safe prime (both p and q are prime),
* this generator function can take a very very long time to run.
*/
-
-DH *DH_generate_parameters(int prime_len, int generator,
- void (*callback)(int,int,char *), char *cb_arg)
+/* Actually there is no reason to insist that 'generator' be a generator.
+ * It's just as OK (and in some sense better) to use a generator of the
+ * order-q subgroup.
+ */
+static int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb)
{
- BIGNUM *p=NULL,*t1,*t2;
- DH *ret=NULL;
+ BIGNUM *t1,*t2;
int g,ok= -1;
BN_CTX *ctx=NULL;
- ret=DH_new();
ctx=BN_CTX_new();
if (ctx == NULL) goto err;
- t1= &(ctx->bn[0]);
- t2= &(ctx->bn[1]);
- ctx->tos=2;
+ BN_CTX_start(ctx);
+ t1 = BN_CTX_get(ctx);
+ t2 = BN_CTX_get(ctx);
+ if (t1 == NULL || t2 == NULL) goto err;
+
+ /* Make sure 'ret' has the necessary elements */
+ if(!ret->p && ((ret->p = BN_new()) == NULL)) goto err;
+ if(!ret->g && ((ret->g = BN_new()) == NULL)) goto err;
+ if (generator <= 1)
+ {
+ DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
+ goto err;
+ }
if (generator == DH_GENERATOR_2)
{
- BN_set_word(t1,24);
- BN_set_word(t2,11);
+ if (!BN_set_word(t1,24)) goto err;
+ if (!BN_set_word(t2,11)) goto err;
g=2;
}
-#ifdef undef /* does not work for strong primes */
+#if 0 /* does not work for safe primes */
else if (generator == DH_GENERATOR_3)
{
- BN_set_word(t1,12);
- BN_set_word(t2,5);
+ if (!BN_set_word(t1,12)) goto err;
+ if (!BN_set_word(t2,5)) goto err;
g=3;
}
#endif
else if (generator == DH_GENERATOR_5)
{
- BN_set_word(t1,10);
- BN_set_word(t2,3);
+ if (!BN_set_word(t1,10)) goto err;
+ if (!BN_set_word(t2,3)) goto err;
/* BN_set_word(t3,7); just have to miss
* out on these ones :-( */
g=5;
}
else
+ {
+ /* in the general case, don't worry if 'generator' is a
+ * generator or not: since we are using safe primes,
+ * it will generate either an order-q or an order-2q group,
+ * which both is OK */
+ if (!BN_set_word(t1,2)) goto err;
+ if (!BN_set_word(t2,1)) goto err;
g=generator;
+ }
- p=BN_generate_prime(NULL,prime_len,1,t1,t2,callback,cb_arg);
- if (p == NULL) goto err;
- if (callback != NULL) callback(3,0,cb_arg);
- ret->p=p;
- ret->g=BN_new();
+ if(!BN_generate_prime_ex(ret->p,prime_len,1,t1,t2,cb)) goto err;
+ if(!BN_GENCB_call(cb, 3, 0)) goto err;
if (!BN_set_word(ret->g,g)) goto err;
ok=1;
err:
if (ok == -1)
{
- DHerr(DH_F_DH_GENERATE_PARAMETERS,ERR_R_BN_LIB);
+ DHerr(DH_F_DH_BUILTIN_GENPARAMS,ERR_R_BN_LIB);
ok=0;
}
- if (ctx != NULL) BN_CTX_free(ctx);
- if (!ok && (ret != NULL))
+ if (ctx != NULL)
{
- DH_free(ret);
- ret=NULL;
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
}
- return(ret);
+ return ok;
}