1#include <openssl/opensslconf.h>
2
3#ifndef OPENSSL_FIPS
4#include <stdio.h>
5
6int main(int argc, char **argv)
7{
8    printf("No FIPS DSA support\n");
9    return(0);
10}
11#else
12
13#include <openssl/bn.h>
14#include <openssl/dsa.h>
15#include <openssl/fips.h>
16#include <openssl/err.h>
17#include <openssl/evp.h>
18#include <string.h>
19#include <ctype.h>
20
21#include "fips_utl.h"
22
23static void pbn(const char *name, BIGNUM *bn)
24	{
25	int len, i;
26	unsigned char *tmp;
27	len = BN_num_bytes(bn);
28	tmp = OPENSSL_malloc(len);
29	if (!tmp)
30		{
31		fprintf(stderr, "Memory allocation error\n");
32		return;
33		}
34	BN_bn2bin(bn, tmp);
35	printf("%s = ", name);
36	for (i = 0; i < len; i++)
37		printf("%02X", tmp[i]);
38	fputs("\n", stdout);
39	OPENSSL_free(tmp);
40	return;
41	}
42
43static void primes()
44    {
45    char buf[10240];
46    char lbuf[10240];
47    char *keyword, *value;
48
49    while(fgets(buf,sizeof buf,stdin) != NULL)
50	{
51	fputs(buf,stdout);
52	if (!parse_line(&keyword, &value, lbuf, buf))
53		continue;
54	if(!strcmp(keyword,"Prime"))
55	    {
56	    BIGNUM *pp;
57
58	    pp=BN_new();
59	    do_hex2bn(&pp,value);
60	    printf("result= %c\n",
61		   BN_is_prime_ex(pp,20,NULL,NULL) ? 'P' : 'F');
62	    }
63	}
64    }
65
66static void pqg()
67    {
68    char buf[1024];
69    char lbuf[1024];
70    char *keyword, *value;
71    int nmod=0;
72
73    while(fgets(buf,sizeof buf,stdin) != NULL)
74	{
75	if (!parse_line(&keyword, &value, lbuf, buf))
76		{
77		fputs(buf,stdout);
78		continue;
79		}
80	if(!strcmp(keyword,"[mod"))
81	    nmod=atoi(value);
82	else if(!strcmp(keyword,"N"))
83	    {
84	    int n=atoi(value);
85
86	    printf("[mod = %d]\n\n",nmod);
87
88	    while(n--)
89		{
90		unsigned char seed[20];
91		DSA *dsa;
92		int counter;
93		unsigned long h;
94		dsa = FIPS_dsa_new();
95
96		if (!DSA_generate_parameters_ex(dsa, nmod,seed,0,&counter,&h,NULL))
97			{
98			do_print_errors();
99			exit(1);
100			}
101		pbn("P",dsa->p);
102		pbn("Q",dsa->q);
103		pbn("G",dsa->g);
104		pv("Seed",seed,20);
105		printf("c = %d\n",counter);
106		printf("H = %lx\n",h);
107		putc('\n',stdout);
108		}
109	    }
110	else
111	    fputs(buf,stdout);
112	}
113    }
114
115static void pqgver()
116    {
117    char buf[1024];
118    char lbuf[1024];
119    char *keyword, *value;
120    BIGNUM *p = NULL, *q = NULL, *g = NULL;
121    int counter, counter2;
122    unsigned long h, h2;
123    DSA *dsa=NULL;
124    int nmod=0;
125    unsigned char seed[1024];
126
127    while(fgets(buf,sizeof buf,stdin) != NULL)
128	{
129	if (!parse_line(&keyword, &value, lbuf, buf))
130		{
131		fputs(buf,stdout);
132		continue;
133		}
134	fputs(buf, stdout);
135	if(!strcmp(keyword,"[mod"))
136	    nmod=atoi(value);
137	else if(!strcmp(keyword,"P"))
138	    p=hex2bn(value);
139	else if(!strcmp(keyword,"Q"))
140	    q=hex2bn(value);
141	else if(!strcmp(keyword,"G"))
142	    g=hex2bn(value);
143	else if(!strcmp(keyword,"Seed"))
144	    {
145	    int slen = hex2bin(value, seed);
146	    if (slen != 20)
147		{
148		fprintf(stderr, "Seed parse length error\n");
149		exit (1);
150		}
151	    }
152	else if(!strcmp(keyword,"c"))
153	    counter =atoi(buf+4);
154	else if(!strcmp(keyword,"H"))
155	    {
156	    h = atoi(value);
157	    if (!p || !q || !g)
158		{
159		fprintf(stderr, "Parse Error\n");
160		exit (1);
161		}
162	    dsa = FIPS_dsa_new();
163	    if (!DSA_generate_parameters_ex(dsa, nmod,seed,20 ,&counter2,&h2,NULL))
164			{
165			do_print_errors();
166			exit(1);
167			}
168            if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || BN_cmp(dsa->g, g)
169		|| (counter != counter2) || (h != h2))
170	    	printf("Result = F\n");
171	    else
172	    	printf("Result = P\n");
173	    BN_free(p);
174	    BN_free(q);
175	    BN_free(g);
176	    p = NULL;
177	    q = NULL;
178	    g = NULL;
179	    FIPS_dsa_free(dsa);
180	    dsa = NULL;
181	    }
182	}
183    }
184
185/* Keypair verification routine. NB: this isn't part of the standard FIPS140-2
186 * algorithm tests. It is an additional test to perform sanity checks on the
187 * output of the KeyPair test.
188 */
189
190static int dss_paramcheck(int nmod, BIGNUM *p, BIGNUM *q, BIGNUM *g,
191							BN_CTX *ctx)
192    {
193    BIGNUM *rem = NULL;
194    if (BN_num_bits(p) != nmod)
195	return 0;
196    if (BN_num_bits(q) != 160)
197	return 0;
198    if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1)
199	return 0;
200    if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1)
201	return 0;
202    rem = BN_new();
203    if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem)
204    	|| (BN_cmp(g, BN_value_one()) <= 0)
205	|| !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem))
206	{
207	BN_free(rem);
208	return 0;
209	}
210    /* Todo: check g */
211    BN_free(rem);
212    return 1;
213    }
214
215static void keyver()
216    {
217    char buf[1024];
218    char lbuf[1024];
219    char *keyword, *value;
220    BIGNUM *p = NULL, *q = NULL, *g = NULL, *X = NULL, *Y = NULL;
221    BIGNUM *Y2;
222    BN_CTX *ctx = NULL;
223    int nmod=0, paramcheck = 0;
224
225    ctx = BN_CTX_new();
226    Y2 = BN_new();
227
228    while(fgets(buf,sizeof buf,stdin) != NULL)
229	{
230	if (!parse_line(&keyword, &value, lbuf, buf))
231		{
232		fputs(buf,stdout);
233		continue;
234		}
235	if(!strcmp(keyword,"[mod"))
236	    {
237	    if (p)
238		BN_free(p);
239	    p = NULL;
240	    if (q)
241		BN_free(q);
242	    q = NULL;
243	    if (g)
244		BN_free(g);
245	    g = NULL;
246	    paramcheck = 0;
247	    nmod=atoi(value);
248	    }
249	else if(!strcmp(keyword,"P"))
250	    p=hex2bn(value);
251	else if(!strcmp(keyword,"Q"))
252	    q=hex2bn(value);
253	else if(!strcmp(keyword,"G"))
254	    g=hex2bn(value);
255	else if(!strcmp(keyword,"X"))
256	    X=hex2bn(value);
257	else if(!strcmp(keyword,"Y"))
258	    {
259	    Y=hex2bn(value);
260	    if (!p || !q || !g || !X || !Y)
261		{
262		fprintf(stderr, "Parse Error\n");
263		exit (1);
264		}
265	    pbn("P",p);
266	    pbn("Q",q);
267	    pbn("G",g);
268	    pbn("X",X);
269	    pbn("Y",Y);
270	    if (!paramcheck)
271		{
272		if (dss_paramcheck(nmod, p, q, g, ctx))
273			paramcheck = 1;
274		else
275			paramcheck = -1;
276		}
277	    if (paramcheck != 1)
278	   	printf("Result = F\n");
279	    else
280		{
281		if (!BN_mod_exp(Y2, g, X, p, ctx) || BN_cmp(Y2, Y))
282	    		printf("Result = F\n");
283	        else
284	    		printf("Result = P\n");
285		}
286	    BN_free(X);
287	    BN_free(Y);
288	    X = NULL;
289	    Y = NULL;
290	    }
291	}
292	if (p)
293	    BN_free(p);
294	if (q)
295	    BN_free(q);
296	if (g)
297	    BN_free(g);
298	if (Y2)
299	    BN_free(Y2);
300    }
301
302static void keypair()
303    {
304    char buf[1024];
305    char lbuf[1024];
306    char *keyword, *value;
307    int nmod=0;
308
309    while(fgets(buf,sizeof buf,stdin) != NULL)
310	{
311	if (!parse_line(&keyword, &value, lbuf, buf))
312		{
313		fputs(buf,stdout);
314		continue;
315		}
316	if(!strcmp(keyword,"[mod"))
317	    nmod=atoi(value);
318	else if(!strcmp(keyword,"N"))
319	    {
320	    DSA *dsa;
321	    int n=atoi(value);
322
323	    printf("[mod = %d]\n\n",nmod);
324	    dsa = FIPS_dsa_new();
325	    if (!DSA_generate_parameters_ex(dsa, nmod,NULL,0,NULL,NULL,NULL))
326		{
327		do_print_errors();
328		exit(1);
329		}
330	    pbn("P",dsa->p);
331	    pbn("Q",dsa->q);
332	    pbn("G",dsa->g);
333	    putc('\n',stdout);
334
335	    while(n--)
336		{
337		if (!DSA_generate_key(dsa))
338			{
339			do_print_errors();
340			exit(1);
341			}
342
343		pbn("X",dsa->priv_key);
344		pbn("Y",dsa->pub_key);
345		putc('\n',stdout);
346		}
347	    }
348	}
349    }
350
351static void siggen()
352    {
353    char buf[1024];
354    char lbuf[1024];
355    char *keyword, *value;
356    int nmod=0;
357    DSA *dsa=NULL;
358
359    while(fgets(buf,sizeof buf,stdin) != NULL)
360	{
361	if (!parse_line(&keyword, &value, lbuf, buf))
362		{
363		fputs(buf,stdout);
364		continue;
365		}
366	if(!strcmp(keyword,"[mod"))
367	    {
368	    nmod=atoi(value);
369	    printf("[mod = %d]\n\n",nmod);
370	    if (dsa)
371		FIPS_dsa_free(dsa);
372	    dsa = FIPS_dsa_new();
373	    if (!DSA_generate_parameters_ex(dsa, nmod,NULL,0,NULL,NULL,NULL))
374		{
375		do_print_errors();
376		exit(1);
377		}
378	    pbn("P",dsa->p);
379	    pbn("Q",dsa->q);
380	    pbn("G",dsa->g);
381	    putc('\n',stdout);
382	    }
383	else if(!strcmp(keyword,"Msg"))
384	    {
385	    unsigned char msg[1024];
386	    unsigned char sbuf[60];
387	    unsigned int slen;
388	    int n;
389	    EVP_PKEY pk;
390	    EVP_MD_CTX mctx;
391	    DSA_SIG *sig;
392	    EVP_MD_CTX_init(&mctx);
393
394	    n=hex2bin(value,msg);
395	    pv("Msg",msg,n);
396
397	    if (!DSA_generate_key(dsa))
398		{
399		do_print_errors();
400		exit(1);
401		}
402	    pk.type = EVP_PKEY_DSA;
403	    pk.pkey.dsa = dsa;
404	    pbn("Y",dsa->pub_key);
405
406	    EVP_SignInit_ex(&mctx, EVP_dss1(), NULL);
407	    EVP_SignUpdate(&mctx, msg, n);
408	    EVP_SignFinal(&mctx, sbuf, &slen, &pk);
409
410	    sig = DSA_SIG_new();
411	    FIPS_dsa_sig_decode(sig, sbuf, slen);
412
413	    pbn("R",sig->r);
414	    pbn("S",sig->s);
415	    putc('\n',stdout);
416	    DSA_SIG_free(sig);
417	    EVP_MD_CTX_cleanup(&mctx);
418	    }
419	}
420	if (dsa)
421		FIPS_dsa_free(dsa);
422    }
423
424static void sigver()
425    {
426    DSA *dsa=NULL;
427    char buf[1024];
428    char lbuf[1024];
429    unsigned char msg[1024];
430    char *keyword, *value;
431    int nmod=0, n=0;
432    DSA_SIG sg, *sig = &sg;
433
434    sig->r = NULL;
435    sig->s = NULL;
436
437    while(fgets(buf,sizeof buf,stdin) != NULL)
438	{
439	if (!parse_line(&keyword, &value, lbuf, buf))
440		{
441		fputs(buf,stdout);
442		continue;
443		}
444	if(!strcmp(keyword,"[mod"))
445	    {
446	    nmod=atoi(value);
447	    if(dsa)
448		FIPS_dsa_free(dsa);
449	    dsa=FIPS_dsa_new();
450	    }
451	else if(!strcmp(keyword,"P"))
452	    dsa->p=hex2bn(value);
453	else if(!strcmp(keyword,"Q"))
454	    dsa->q=hex2bn(value);
455	else if(!strcmp(keyword,"G"))
456	    {
457	    dsa->g=hex2bn(value);
458
459	    printf("[mod = %d]\n\n",nmod);
460	    pbn("P",dsa->p);
461	    pbn("Q",dsa->q);
462	    pbn("G",dsa->g);
463	    putc('\n',stdout);
464	    }
465	else if(!strcmp(keyword,"Msg"))
466	    {
467	    n=hex2bin(value,msg);
468	    pv("Msg",msg,n);
469	    }
470	else if(!strcmp(keyword,"Y"))
471	    dsa->pub_key=hex2bn(value);
472	else if(!strcmp(keyword,"R"))
473	    sig->r=hex2bn(value);
474	else if(!strcmp(keyword,"S"))
475	    {
476	    EVP_MD_CTX mctx;
477	    EVP_PKEY pk;
478	    unsigned char sigbuf[60];
479	    unsigned int slen;
480	    int r;
481	    EVP_MD_CTX_init(&mctx);
482	    pk.type = EVP_PKEY_DSA;
483	    pk.pkey.dsa = dsa;
484	    sig->s=hex2bn(value);
485
486	    pbn("Y",dsa->pub_key);
487	    pbn("R",sig->r);
488	    pbn("S",sig->s);
489
490	    slen = FIPS_dsa_sig_encode(sigbuf, sig);
491	    EVP_VerifyInit_ex(&mctx, EVP_dss1(), NULL);
492	    EVP_VerifyUpdate(&mctx, msg, n);
493	    r = EVP_VerifyFinal(&mctx, sigbuf, slen, &pk);
494	    EVP_MD_CTX_cleanup(&mctx);
495
496	    printf("Result = %c\n", r == 1 ? 'P' : 'F');
497	    putc('\n',stdout);
498	    }
499	}
500    }
501
502int main(int argc,char **argv)
503    {
504    if(argc != 2)
505	{
506	fprintf(stderr,"%s [prime|pqg|pqgver|keypair|siggen|sigver]\n",argv[0]);
507	exit(1);
508	}
509    if(!FIPS_mode_set(1))
510	{
511	do_print_errors();
512	exit(1);
513	}
514    if(!strcmp(argv[1],"prime"))
515	primes();
516    else if(!strcmp(argv[1],"pqg"))
517	pqg();
518    else if(!strcmp(argv[1],"pqgver"))
519	pqgver();
520    else if(!strcmp(argv[1],"keypair"))
521	keypair();
522    else if(!strcmp(argv[1],"keyver"))
523	keyver();
524    else if(!strcmp(argv[1],"siggen"))
525	siggen();
526    else if(!strcmp(argv[1],"sigver"))
527	sigver();
528    else
529	{
530	fprintf(stderr,"Don't know how to %s.\n",argv[1]);
531	exit(1);
532	}
533
534    return 0;
535    }
536
537#endif
538