- {
- int ok=0;
- unsigned int i;
- BN_CTX ctx;
- BN_MONT_CTX *mont;
- BIGNUM *pub_key=NULL,*priv_key=NULL;
-
- BN_CTX_init(&ctx);
-
- if (dh->priv_key == NULL)
- {
- i=dh->length;
- if (i == 0)
- {
- /* Make the number p-1 bits long */
- i=BN_num_bits(dh->p)-1;
- }
- priv_key=BN_new();
- if (priv_key == NULL) goto err;
- if (!BN_rand(priv_key,i,0,0)) goto err;
- }
- else
- priv_key=dh->priv_key;
-
- if (dh->pub_key == NULL)
- {
- pub_key=BN_new();
- if (pub_key == NULL) goto err;
- }
- else
- pub_key=dh->pub_key;
-
- if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
- {
- if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
- if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
- dh->p,&ctx)) goto err;
- }
- mont=(BN_MONT_CTX *)dh->method_mont_p;
-
- if (!ENGINE_get_DH(dh->engine)->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;
- ok=1;
-err:
- if (ok != 1)
- DHerr(DH_F_DH_GENERATE_KEY,ERR_R_BN_LIB);
-
- if ((pub_key != NULL) && (dh->pub_key == NULL)) BN_free(pub_key);
- if ((priv_key != NULL) && (dh->priv_key == NULL)) BN_free(priv_key);
- BN_CTX_free(&ctx);
- return(ok);
- }
-
-static int compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh)
- {
- BN_CTX ctx;
- BN_MONT_CTX *mont;
- BIGNUM *tmp;
- int ret= -1;
-
- BN_CTX_init(&ctx);
- BN_CTX_start(&ctx);
- tmp = BN_CTX_get(&ctx);
-
- if (dh->priv_key == NULL)
- {
- DHerr(DH_F_DH_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE);
- goto err;
- }
- if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P))
- {
- if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
- if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p,
- dh->p,&ctx)) goto err;
- }
-
- mont=(BN_MONT_CTX *)dh->method_mont_p;
- if (!ENGINE_get_DH(dh->engine)->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;
- }
-
- ret=BN_bn2bin(tmp,key);
-err:
- BN_CTX_end(&ctx);
- 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)
- {
- if (a->top == 1)
- {
- BN_ULONG A = a->d[0];
- return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx);
- }
- else
- return BN_mod_exp_mont(r,a,p,m,ctx,m_ctx);
- }
+{
+ int ok = 0;
+ int generate_new_key = 0;
+ unsigned l;
+ BN_CTX *ctx;
+ BN_MONT_CTX *mont = NULL;
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL)
+ goto err;
+
+ if (dh->priv_key == NULL) {
+ priv_key = BN_secure_new();
+ if (priv_key == NULL)
+ goto err;
+ generate_new_key = 1;
+ } else
+ priv_key = dh->priv_key;
+
+ if (dh->pub_key == NULL) {
+ pub_key = BN_new();
+ if (pub_key == NULL)
+ goto err;
+ } else
+ pub_key = dh->pub_key;
+
+ if (dh->flags & DH_FLAG_CACHE_MONT_P) {
+ mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
+ CRYPTO_LOCK_DH, dh->p, ctx);
+ if (!mont)
+ goto err;
+ }
+
+ if (generate_new_key) {
+ if (dh->q) {
+ do {
+ if (!BN_rand_range(priv_key, dh->q))
+ goto err;
+ }
+ while (BN_is_zero(priv_key) || BN_is_one(priv_key));
+ } else {
+ /* secret exponent length */
+ l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
+ if (!BN_rand(priv_key, l, 0, 0))
+ goto err;
+ }
+ }
+
+ {
+ BIGNUM *local_prk = NULL;
+ BIGNUM *prk;
+
+ if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) {
+ local_prk = prk = BN_new();
+ BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
+ } else
+ prk = priv_key;