Commit f55f5f77 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add support for canonical generation of DSA parameter g.

Modify fips_dssvs to support appropriate file format.
parent 7daf0efa
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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))
@@ -671,12 +720,18 @@ end:
	ok=1;
err:
	if (ok == 1)
		{
		if (p != ret->p)
			{
			if(ret->p) BN_free(ret->p);
		if(ret->q) BN_free(ret->q);
		if(ret->g) BN_free(ret->g);
			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->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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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,6 +230,18 @@ 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);
@@ -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)
		{
		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");