To go along with the fix for #2957, please consider the following 
enhancement.

It adds support for the option to genpkey:
     -pkeyopt dh_paramgen_private_len:${S_BITS}
for DH Parameter generation.  It also sets the size to 160 in the 
absence of this parameter.  The genpkey pod file is updated as well.

The justification for these changes is that IETF-style Diffie-Hellman, 
though it does not have a 'subprime' private key order like X9.42 (or 
IEEE 1363 or...) to govern private key, there are suggestions for 
"private key size" for the various MODP groups.  This recognizes that 
having a private key size as long as the prime hurts performance and 
does not help security.


-- 
*  - Ron*

Ronald B Harvey
Senior Member of Technical Staff
Security Technology Center
Freescale Semiconductor, Inc.

diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h
index ea59e61..543916c 100644
--- a/crypto/dh/dh.h
+++ b/crypto/dh/dh.h
@@ -229,8 +229,13 @@ int	DHparams_print(char *bp, const DH *x);
 	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
 			EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL)
 
+#define EVP_PKEY_CTX_set_dh_paramgen_private_len(ctx, bitlen) \
+	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
+			EVP_PKEY_CTRL_DH_PARAMGEN_PRIVATE_LEN, bitlen, NULL)
+
 #define	EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN	(EVP_PKEY_ALG_CTRL + 1)
 #define	EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR	(EVP_PKEY_ALG_CTRL + 2)
+#define	EVP_PKEY_CTRL_DH_PARAMGEN_PRIVATE_LEN	(EVP_PKEY_ALG_CTRL + 3)
 		
 
 /* BEGIN ERROR CODES */
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index 02ec2d4..d059fc1 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -423,6 +423,15 @@ static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
 		BN_free(to->pkey.dh->g);
 	to->pkey.dh->g=a;
 
+	if ((a=BN_dup(from->pkey.dh->q)) != NULL)
+        {
+		if (to->pkey.dh->q != NULL)
+			BN_free(to->pkey.dh->q);
+                to->pkey.dh->q=a;
+        }
+
+        to->pkey.dh->length = from->pkey.dh->length;
+
 	return 1;
 	}
 
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index 5ae72b7..cf1e170 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -72,6 +72,7 @@ typedef struct
 	int prime_len;
 	int generator;
 	int use_dsa;
+        int private_len;
 	/* Keygen callback info */
 	int gentmp[2];
 	/* message digest */
@@ -86,6 +87,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
 	dctx->prime_len = 1024;
 	dctx->generator = 2;
 	dctx->use_dsa = 0;
+	dctx->private_len = 160;
 
 	ctx->data = dctx;
 	ctx->keygen_info = dctx->gentmp;
@@ -104,6 +106,7 @@ static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
 	dctx->prime_len = sctx->prime_len;
 	dctx->generator = sctx->generator;
 	dctx->use_dsa = sctx->use_dsa;
+	dctx->private_len = sctx->private_len;
 	return 1;
 	}
 
@@ -129,6 +132,12 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
 		dctx->generator = p1;
 		return 1;
 
+		case EVP_PKEY_CTRL_DH_PARAMGEN_PRIVATE_LEN:
+		if (p1 !=0 && p1 < 64)
+			return -2;
+		dctx->private_len = p1;
+		return 1;
+
 		case EVP_PKEY_CTRL_PEER_KEY:
 		/* Default behaviour is OK */
 		return 1;
@@ -155,6 +164,12 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
 		len = atoi(value);
 		return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
 		}
+	if (!strcmp(type, "dh_paramgen_private_len"))
+		{
+		int bitlen;
+		bitlen = atoi(value);
+		return EVP_PKEY_CTX_set_dh_paramgen_private_len(ctx, bitlen);
+		}
 	return -2;
 	}
 
@@ -171,13 +186,18 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 		}
 	else
 		pcb = NULL;
+        if (dctx->prime_len < dctx->private_len)
+                return 0;
 	dh = DH_new();
 	if (!dh)
 		return 0;
 	ret = DH_generate_parameters_ex(dh,
 					dctx->prime_len, dctx->generator, pcb);
 	if (ret)
+                {  
 		EVP_PKEY_assign_DH(pkey, dh);
+                dh->length = dctx->private_len;
+                }
 	else
 		DH_free(dh);
 	return ret;
diff --git a/doc/apps/genpkey.pod b/doc/apps/genpkey.pod
index c74d097..370f2b3 100644
--- a/doc/apps/genpkey.pod
+++ b/doc/apps/genpkey.pod
@@ -124,6 +124,14 @@ The number of bits in the generated parameters. If not specified 1024 is used.
 
 The number of bits in the prime parameter B<p>.
 
+=over 4
+
+=item B<dh_paramgen_private_len:numbits>
+
+The recommended number of bits for a private key.
+If not specified 160 is used.  Can be set 0, but otherwise
+must be less than prime len B<p>.
+
 =item B<dh_paramgen_generator:value>
 
 The value to use for the generator B<g>.

Reply via email to