Переглянути джерело

Add support for canonical generation of DSA parameter g.
Modify fips_dssvs to support appropriate file format.

Dr. Stephen Henson 12 роки тому
батько
коміт
f55f5f775e
4 змінених файлів з 153 додано та 25 видалено
  1. 3 0
      CHANGES
  2. 107 11
      crypto/dsa/dsa_gen.c
  3. 4 2
      crypto/dsa/dsa_locl.h
  4. 39 12
      fips/dsa/fips_dssvs.c

+ 3 - 0
CHANGES

@@ -4,6 +4,9 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) Add support for canonical generation of DSA parameter 'g'. See 
+     FIPS 186-3 A.2.3.
+
   *) Add support for HMAC DRBG from SP800-90. Update algorithm and POST
      to handle HMAC cases.
      [Steve Henson]

+ 107 - 11
crypto/dsa/dsa_gen.c

@@ -452,11 +452,11 @@ int fips_check_dsa_prng(DSA *dsa, size_t L, size_t N)
 
 int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
 	const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
-	unsigned char *seed_out,
+	int idx, unsigned char *seed_out,
 	int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
 	{
 	int ok=-1;
-	unsigned char *seed = NULL;
+	unsigned char *seed = NULL, *seed_tmp = NULL;
 	unsigned char md[EVP_MAX_MD_SIZE];
 	int mdsize;
 	BIGNUM *r0,*W,*X,*c,*test;
@@ -466,8 +466,11 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
 	int counter=0;
 	int r=0;
 	BN_CTX *ctx=NULL;
+	EVP_MD_CTX mctx;
 	unsigned int h=2;
 
+	EVP_MD_CTX_init(&mctx);
+
 #ifdef OPENSSL_FIPS
 	if(FIPS_selftest_failed())
 	    {
@@ -497,7 +500,12 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
 
 	seed = OPENSSL_malloc(seed_len);
 
-	if (!seed)
+	if (seed_out)
+		seed_tmp = seed_out;
+	else
+		seed_tmp = OPENSSL_malloc(seed_len);
+
+	if (!seed || !seed_tmp)
 		goto err;
 
 	if (seed_in)
@@ -513,12 +521,24 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
 	r0 = BN_CTX_get(ctx);
 	g = BN_CTX_get(ctx);
 	W = BN_CTX_get(ctx);
-	q = BN_CTX_get(ctx);
 	X = BN_CTX_get(ctx);
 	c = BN_CTX_get(ctx);
-	p = BN_CTX_get(ctx);
 	test = BN_CTX_get(ctx);
 
+	/* if p, q already supplied generate g only */
+	if (ret->p && ret->q)
+		{
+		p = ret->p;
+		q = ret->q;
+		memcpy(seed_tmp, seed, seed_len);
+		goto g_only;
+		}
+	else
+		{
+		p = BN_CTX_get(ctx);
+		q = BN_CTX_get(ctx);
+		}
+
 	if (!BN_lshift(test,BN_value_one(),L-1))
 		goto err;
 	for (;;)
@@ -648,21 +668,50 @@ end:
 	if(!BN_GENCB_call(cb, 2, 1))
 		goto err;
 
+	g_only:
+
 	/* We now need to generate g */
 	/* Set r0=(p-1)/q */
 	if (!BN_sub(test,p,BN_value_one())) goto err;
 	if (!BN_div(r0,NULL,test,q,ctx)) goto err;
 
-	if (!BN_set_word(test,h)) goto err;
+	if (idx < 0)
+		{
+		if (!BN_set_word(test,h))
+			goto err;
+		}
+	else
+		h = 1;
 	if (!BN_MONT_CTX_set(mont,p,ctx)) goto err;
 
 	for (;;)
 		{
+		static const unsigned char ggen[4] = {0x67,0x67,0x65,0x6e};
+		if (idx >= 0)
+			{
+			md[0] = idx & 0xff;
+			md[1] = (h >> 8) & 0xff;
+			md[2] = h & 0xff;
+			if (!EVP_DigestInit_ex(&mctx, evpmd, NULL))
+				goto err;
+			if (!EVP_DigestUpdate(&mctx, seed_tmp, seed_len))
+				goto err;
+			if (!EVP_DigestUpdate(&mctx, ggen, sizeof(ggen)))
+				goto err;
+			if (!EVP_DigestUpdate(&mctx, md, 3))
+				goto err;
+			if (!EVP_DigestFinal_ex(&mctx, md, NULL))
+				goto err;
+			if (!BN_bin2bn(md, mdsize, test))
+				goto err;
+			}
 		/* g=test^r0%p */
 		if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err;
 		if (!BN_is_one(g)) break;
-		if (!BN_add(test,test,BN_value_one())) goto err;
+		if (idx < 0 && !BN_add(test,test,BN_value_one())) goto err;
 		h++;
+		if ( idx >= 0 && h > 0xffff)
+			goto err;
 		}
 
 	if(!BN_GENCB_call(cb, 3, 1))
@@ -672,11 +721,17 @@ end:
 err:
 	if (ok == 1)
 		{
-		if(ret->p) BN_free(ret->p);
-		if(ret->q) BN_free(ret->q);
+		if (p != ret->p)
+			{
+			if(ret->p) BN_free(ret->p);
+			ret->p=BN_dup(p);
+			}
+		if (q != ret->q)
+			{
+			if(ret->q) BN_free(ret->q);
+			ret->q=BN_dup(q);
+			}
 		if(ret->g) BN_free(ret->g);
-		ret->p=BN_dup(p);
-		ret->q=BN_dup(q);
 		ret->g=BN_dup(g);
 		if (ret->p == NULL || ret->q == NULL || ret->g == NULL)
 			{
@@ -688,12 +743,53 @@ err:
 		}
 	if (seed)
 		OPENSSL_free(seed);
+	if (seed_out != seed_tmp)
+		OPENSSL_free(seed_tmp);
 	if(ctx)
 		{
 		BN_CTX_end(ctx);
 		BN_CTX_free(ctx);
 		}
 	if (mont != NULL) BN_MONT_CTX_free(mont);
+	EVP_MD_CTX_cleanup(&mctx);
 	return ok;
 	}
+
+int dsa_paramgen_check_g(DSA *dsa)
+	{
+	BN_CTX *ctx;
+	BIGNUM *tmp;
+	BN_MONT_CTX *mont = NULL;
+	int rv = -1;
+	ctx = BN_CTX_new();
+	if (!ctx)
+		return -1;
+	BN_CTX_start(ctx);
+	if (BN_cmp(dsa->g, BN_value_one()) <= 0)
+		return 0;
+	if (BN_cmp(dsa->g, dsa->p) >= 0)
+		return 0;
+	tmp = BN_CTX_get(ctx);
+	if (!tmp)
+		goto err;
+	if ((mont=BN_MONT_CTX_new()) == NULL)
+		goto err;
+	if (!BN_MONT_CTX_set(mont,dsa->p,ctx))
+		goto err;
+	/* Work out g^q mod p */
+	if (!BN_mod_exp_mont(tmp,dsa->g,dsa->q, dsa->p, ctx, mont))
+		goto err;
+	if (!BN_cmp(tmp, BN_value_one()))
+		rv = 1;
+	else
+		rv = 0;
+	err:
+	BN_CTX_end(ctx);
+	if (mont)
+		BN_MONT_CTX_free(mont);
+	BN_CTX_free(ctx);
+	return rv;
+
+	}
+
 #endif

+ 4 - 2
crypto/dsa/dsa_locl.h

@@ -59,7 +59,9 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
 	unsigned char *seed_out,
 	int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
 
-int dsa_builtin_paramgen2(DSA *ret, size_t bits, size_t qbits,
+int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
 	const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
-	unsigned char *seed_out,
+	int idx, unsigned char *seed_out,
 	int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
+
+int dsa_paramgen_check_g(DSA *dsa);

+ 39 - 12
fips/dsa/fips_dssvs.c

@@ -111,9 +111,9 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
 	const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
 	unsigned char *seed_out,
 	int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
-int dsa_builtin_paramgen2(DSA *ret, size_t bits, size_t qbits,
+int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
 	const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
-	unsigned char *seed_out,
+	int idx, unsigned char *seed_out,
 	int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
 
 static void pqg(FILE *in, FILE *out)
@@ -160,7 +160,7 @@ static void pqg(FILE *in, FILE *out)
 			exit(1);
 			}
 		if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
-						NULL, 0, seed,
+						NULL, 0, -1, seed,
 						&counter, &h, NULL) <= 0)
 			{
 			fprintf(stderr, "Parameter Generation error\n");
@@ -191,8 +191,8 @@ static void pqgver(FILE *in, FILE *out)
     DSA *dsa=NULL;
     int dsa2, L, N, part_test = 0;
     const EVP_MD *md = NULL;
-    int seedlen=-1;
-    unsigned char seed[1024];
+    int seedlen=-1, idxlen, idx = -1;
+    unsigned char seed[1024], idtmp[1024];
 
     while(fgets(buf,sizeof buf,in) != NULL)
 	{
@@ -221,7 +221,8 @@ static void pqgver(FILE *in, FILE *out)
 	    q=hex2bn(value);
 	else if(!strcmp(keyword,"G"))
 	    g=hex2bn(value);
-	else if(!strcmp(keyword,"Seed"))
+	else if(!strcmp(keyword,"Seed")
+		|| !strcmp(keyword,"domain_parameter_seed"))
 	    {
 	    seedlen = hex2bin(value, seed);
 	    if (!dsa2 && seedlen != 20)
@@ -229,9 +230,21 @@ static void pqgver(FILE *in, FILE *out)
 		fprintf(stderr, "Seed parse length error\n");
 		exit (1);
 		}
+	    if (idx > 0)
+		part_test = 1;
+	    }
+	else if(!strcmp(keyword,"index"))
+	    {
+	    idxlen = hex2bin(value, idtmp);
+            if (idxlen != 1)
+		{
+		fprintf(stderr, "Index value error\n");
+		exit (1);
+		}
+	    idx = idtmp[0];
 	    }
 	else if(!strcmp(keyword,"c"))
-	    counter =atoi(buf+4);
+	    counter = atoi(buf+4);
 	partial:
 	if(!strcmp(keyword,"H") || part_test)
 	    {
@@ -243,6 +256,11 @@ static void pqgver(FILE *in, FILE *out)
 		exit (1);
 		}
 	    dsa = FIPS_dsa_new();
+	    if (idx >= 0)
+		{
+		dsa->p = BN_dup(p);
+		dsa->q = BN_dup(q);
+		}
 	    if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md,
 					seed, seedlen, NULL,
 					&counter2, &h2, NULL))
@@ -251,13 +269,20 @@ static void pqgver(FILE *in, FILE *out)
 			exit(1);
 			}
 	    if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
-					seed, seedlen, NULL,
+					seed, seedlen, idx, NULL,
 					&counter2, &h2, NULL) < 0)
 			{
 			fprintf(stderr, "Parameter Generation error\n");
 			exit(1);
 			}
-            if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || 
+	    if (idx >= 0)
+		{
+		if (BN_cmp(dsa->g, g))
+			fprintf(out, "Result = F\n");
+		else
+			fprintf(out, "Result = P\n");
+		}
+            else if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || 
 		(!part_test &&
 		((BN_cmp(dsa->g, g) || (counter != counter2) || (h != h2)))))
 	    	fprintf(out, "Result = F\n");
@@ -273,9 +298,11 @@ static void pqgver(FILE *in, FILE *out)
 	    dsa = NULL;
 	    if (part_test)
 		{
-		fputs(buf,out);
+		if (idx == -1)
+			fputs(buf,out);
 		part_test = 0;
 		}
+	    idx = -1;
 	    }
 	}
     }
@@ -436,7 +463,7 @@ static void keypair(FILE *in, FILE *out)
 			fprintf(stderr, "Parameter Generation error\n");
 			exit(1);
 			}
-	    if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, NULL, NULL, 0,
+	    if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, NULL, NULL, 0, -1,
 						NULL, NULL, NULL, NULL) <= 0)
 			{
 			fprintf(stderr, "Parameter Generation error\n");
@@ -493,7 +520,7 @@ static void siggen(FILE *in, FILE *out)
 			fprintf(stderr, "Parameter Generation error\n");
 			exit(1);
 			}
-	    if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md, NULL, 0,
+	    if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md, NULL, 0, -1,
 						NULL, NULL, NULL, NULL) <= 0)
 			{
 			fprintf(stderr, "Parameter Generation error\n");