Add support for canonical generation of DSA parameter g.
[openssl.git] / fips / dsa / fips_dssvs.c
1
2 #define OPENSSL_FIPSAPI
3 #include <openssl/opensslconf.h>
4
5 #ifndef OPENSSL_FIPS
6 #include <stdio.h>
7
8 int main(int argc, char **argv)
9 {
10     printf("No FIPS DSA support\n");
11     return(0);
12 }
13 #else
14
15 #include <openssl/bn.h>
16 #include <openssl/dsa.h>
17 #include <openssl/fips.h>
18 #include <openssl/err.h>
19 #include <openssl/evp.h>
20 #include <string.h>
21 #include <ctype.h>
22
23 #include "fips_utl.h"
24
25 static int parse_mod(char *line, int *pdsa2, int *pL, int *pN,
26                                 const EVP_MD **pmd)
27         {
28         char lbuf[10240];
29         char *keyword, *value;
30
31         char *p;
32         p = strchr(line, ',');
33         if (!p)
34                 {
35                 *pL = atoi(line);
36                 *pdsa2 = 0;
37                 *pN = 160;
38                 if (pmd)
39                         *pmd = EVP_sha1();
40                 return 1;
41                 }
42         *pdsa2 = 1;
43         *p = 0;
44         if (!parse_line2(&keyword, &value, lbuf, line, 0))
45                 return 0;
46         if (strcmp(keyword, "L"))
47                 return 0;
48         *pL = atoi(value);
49         strcpy(line, p + 1);
50         if (pmd)
51                 p = strchr(line, ',');
52         else
53                 p = strchr(line, ']');
54         if (!p)
55                 return 0;
56         *p = 0;
57         if (!parse_line2(&keyword, &value, lbuf, line, 0))
58                 return 0;
59         if (strcmp(keyword, "N"))
60                 return 0;
61         *pN = atoi(value);
62         if (!pmd)
63                 return 1;
64         strcpy(line, p + 1);
65         p = strchr(line, ']');
66         if (!p)
67                 return 0;
68         *p = 0;
69         p = line;
70         while(isspace(*p))
71                 p++;
72         if (!strcmp(p, "SHA-1"))
73                 *pmd = EVP_sha1();
74         else if (!strcmp(p, "SHA-224"))
75                 *pmd = EVP_sha224();
76         else if (!strcmp(p, "SHA-256"))
77                 *pmd = EVP_sha256();
78         else if (!strcmp(p, "SHA-384"))
79                 *pmd = EVP_sha384();
80         else if (!strcmp(p, "SHA-512"))
81                 *pmd = EVP_sha512();
82         else
83                 return 0;
84         return 1;
85         }
86
87 static void primes(FILE *in, FILE *out)
88     {
89     char buf[10240];
90     char lbuf[10240];
91     char *keyword, *value;
92
93     while(fgets(buf,sizeof buf,in) != NULL)
94         {
95         fputs(buf,out);
96         if (!parse_line(&keyword, &value, lbuf, buf))
97                 continue;
98         if(!strcmp(keyword,"Prime"))
99             {
100             BIGNUM *pp;
101
102             pp=BN_new();
103             do_hex2bn(&pp,value);
104             fprintf(out, "result= %c\n",
105                    BN_is_prime_ex(pp,20,NULL,NULL) ? 'P' : 'F');
106             }       
107         }
108     }
109
110 int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
111         const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
112         unsigned char *seed_out,
113         int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
114 int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
115         const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
116         int idx, unsigned char *seed_out,
117         int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
118
119 static void pqg(FILE *in, FILE *out)
120     {
121     char buf[1024];
122     char lbuf[1024];
123     char *keyword, *value;
124     int dsa2, L, N;
125     const EVP_MD *md = NULL;
126
127     while(fgets(buf,sizeof buf,in) != NULL)
128         {
129         if (!parse_line(&keyword, &value, lbuf, buf))
130                 {
131                 fputs(buf,out);
132                 continue;
133                 }
134         if(!strcmp(keyword,"[mod"))
135             {
136             fputs(buf,out);
137             if (!parse_mod(value, &dsa2, &L, &N, &md))
138                 {
139                 fprintf(stderr, "Mod Parse Error\n");
140                 exit (1);
141                 }
142             }
143         else if(!strcmp(keyword,"N"))
144             {
145             int n=atoi(value);
146
147             while(n--)
148                 {
149                 unsigned char seed[EVP_MAX_MD_SIZE];
150                 DSA *dsa;
151                 int counter;
152                 unsigned long h;
153                 dsa = FIPS_dsa_new();
154
155                 if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md,
156                                                 NULL, 0, seed,
157                                                 &counter, &h, NULL))
158                         {
159                         fprintf(stderr, "Parameter Generation error\n");
160                         exit(1);
161                         }
162                 if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
163                                                 NULL, 0, -1, seed,
164                                                 &counter, &h, NULL) <= 0)
165                         {
166                         fprintf(stderr, "Parameter Generation error\n");
167                         exit(1);
168                         }
169  
170                 do_bn_print_name(out, "P",dsa->p);
171                 do_bn_print_name(out, "Q",dsa->q);
172                 do_bn_print_name(out, "G",dsa->g);
173                 OutputValue("Seed",seed, M_EVP_MD_size(md), out, 0);
174                 fprintf(out, "c = %d\n",counter);
175                 fprintf(out, "H = %lx\n\n",h);
176                 }
177             }
178         else
179             fputs(buf,out);
180         }
181     }
182
183 static void pqgver(FILE *in, FILE *out)
184     {
185     char buf[1024];
186     char lbuf[1024];
187     char *keyword, *value;
188     BIGNUM *p = NULL, *q = NULL, *g = NULL;
189     int counter=-1, counter2;
190     unsigned long h=0, h2;
191     DSA *dsa=NULL;
192     int dsa2, L, N, part_test = 0;
193     const EVP_MD *md = NULL;
194     int seedlen=-1, idxlen, idx = -1;
195     unsigned char seed[1024], idtmp[1024];
196
197     while(fgets(buf,sizeof buf,in) != NULL)
198         {
199         if (!parse_line(&keyword, &value, lbuf, buf))
200                 {
201                 if (p && q)
202                         {
203                         part_test = 1;
204                         goto partial;
205                         }
206                 fputs(buf,out);
207                 continue;
208                 }
209         fputs(buf, out);
210         if(!strcmp(keyword,"[mod"))
211             {
212             if (!parse_mod(value, &dsa2, &L, &N, &md))
213                 {
214                 fprintf(stderr, "Mod Parse Error\n");
215                 exit (1);
216                 }
217             }
218         else if(!strcmp(keyword,"P"))
219             p=hex2bn(value);
220         else if(!strcmp(keyword,"Q"))
221             q=hex2bn(value);
222         else if(!strcmp(keyword,"G"))
223             g=hex2bn(value);
224         else if(!strcmp(keyword,"Seed")
225                 || !strcmp(keyword,"domain_parameter_seed"))
226             {
227             seedlen = hex2bin(value, seed);
228             if (!dsa2 && seedlen != 20)
229                 {
230                 fprintf(stderr, "Seed parse length error\n");
231                 exit (1);
232                 }
233             if (idx > 0)
234                 part_test = 1;
235             }
236         else if(!strcmp(keyword,"index"))
237             {
238             idxlen = hex2bin(value, idtmp);
239             if (idxlen != 1)
240                 {
241                 fprintf(stderr, "Index value error\n");
242                 exit (1);
243                 }
244             idx = idtmp[0];
245             }
246         else if(!strcmp(keyword,"c"))
247             counter = atoi(buf+4);
248         partial:
249         if(!strcmp(keyword,"H") || part_test)
250             {
251             if (!part_test)
252                 h = atoi(value);
253             if (!p || !q || (!g && !part_test))
254                 {
255                 fprintf(stderr, "Parse Error\n");
256                 exit (1);
257                 }
258             dsa = FIPS_dsa_new();
259             if (idx >= 0)
260                 {
261                 dsa->p = BN_dup(p);
262                 dsa->q = BN_dup(q);
263                 }
264             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md,
265                                         seed, seedlen, NULL,
266                                         &counter2, &h2, NULL))
267                         {
268                         fprintf(stderr, "Parameter Generation error\n");
269                         exit(1);
270                         }
271             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
272                                         seed, seedlen, idx, NULL,
273                                         &counter2, &h2, NULL) < 0)
274                         {
275                         fprintf(stderr, "Parameter Generation error\n");
276                         exit(1);
277                         }
278             if (idx >= 0)
279                 {
280                 if (BN_cmp(dsa->g, g))
281                         fprintf(out, "Result = F\n");
282                 else
283                         fprintf(out, "Result = P\n");
284                 }
285             else if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || 
286                 (!part_test &&
287                 ((BN_cmp(dsa->g, g) || (counter != counter2) || (h != h2)))))
288                 fprintf(out, "Result = F\n");
289             else
290                 fprintf(out, "Result = P\n");
291             BN_free(p);
292             BN_free(q);
293             BN_free(g);
294             p = NULL;
295             q = NULL;
296             g = NULL;
297             FIPS_dsa_free(dsa);
298             dsa = NULL;
299             if (part_test)
300                 {
301                 if (idx == -1)
302                         fputs(buf,out);
303                 part_test = 0;
304                 }
305             idx = -1;
306             }
307         }
308     }
309
310 /* Keypair verification routine. NB: this isn't part of the standard FIPS140-2
311  * algorithm tests. It is an additional test to perform sanity checks on the
312  * output of the KeyPair test.
313  */
314
315 static int dss_paramcheck(int L, int N, BIGNUM *p, BIGNUM *q, BIGNUM *g,
316                                                         BN_CTX *ctx)
317     {
318     BIGNUM *rem = NULL;
319     if (BN_num_bits(p) != L)
320         return 0;
321     if (BN_num_bits(q) != N)
322         return 0;
323     if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1)
324         return 0;
325     if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1)
326         return 0;
327     rem = BN_new();
328     if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem)
329         || (BN_cmp(g, BN_value_one()) <= 0)
330         || !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem))
331         {
332         BN_free(rem);
333         return 0;
334         }
335     /* Todo: check g */
336     BN_free(rem);
337     return 1;
338     }
339
340 static void keyver(FILE *in, FILE *out)
341     {
342     char buf[1024];
343     char lbuf[1024];
344     char *keyword, *value;
345     BIGNUM *p = NULL, *q = NULL, *g = NULL, *X = NULL, *Y = NULL;
346     BIGNUM *Y2;
347     BN_CTX *ctx = NULL;
348     int dsa2, L, N;
349     int paramcheck = 0;
350
351     ctx = BN_CTX_new();
352     Y2 = BN_new();
353
354     while(fgets(buf,sizeof buf,in) != NULL)
355         {
356         if (!parse_line(&keyword, &value, lbuf, buf))
357                 {
358                 fputs(buf,out);
359                 continue;
360                 }
361         if(!strcmp(keyword,"[mod"))
362             {
363             if (p)
364                 BN_free(p);
365             p = NULL;
366             if (q)
367                 BN_free(q);
368             q = NULL;
369             if (g)
370                 BN_free(g);
371             g = NULL;
372             paramcheck = 0;
373             if (!parse_mod(value, &dsa2, &L, &N, NULL))
374                 {
375                 fprintf(stderr, "Mod Parse Error\n");
376                 exit (1);
377                 }
378             }
379         else if(!strcmp(keyword,"P"))
380             p=hex2bn(value);
381         else if(!strcmp(keyword,"Q"))
382             q=hex2bn(value);
383         else if(!strcmp(keyword,"G"))
384             g=hex2bn(value);
385         else if(!strcmp(keyword,"X"))
386             X=hex2bn(value);
387         else if(!strcmp(keyword,"Y"))
388             {
389             Y=hex2bn(value);
390             if (!p || !q || !g || !X || !Y)
391                 {
392                 fprintf(stderr, "Parse Error\n");
393                 exit (1);
394                 }
395             do_bn_print_name(out, "P",p);
396             do_bn_print_name(out, "Q",q);
397             do_bn_print_name(out, "G",g);
398             do_bn_print_name(out, "X",X);
399             do_bn_print_name(out, "Y",Y);
400             if (!paramcheck)
401                 {
402                 if (dss_paramcheck(L, N, p, q, g, ctx))
403                         paramcheck = 1;
404                 else
405                         paramcheck = -1;
406                 }
407             if (paramcheck != 1)
408                 fprintf(out, "Result = F\n");
409             else
410                 {
411                 if (!BN_mod_exp(Y2, g, X, p, ctx) || BN_cmp(Y2, Y))
412                         fprintf(out, "Result = F\n");
413                 else
414                         fprintf(out, "Result = P\n");
415                 }
416             BN_free(X);
417             BN_free(Y);
418             X = NULL;
419             Y = NULL;
420             }
421         }
422         if (p)
423             BN_free(p);
424         if (q)
425             BN_free(q);
426         if (g)
427             BN_free(g);
428         if (Y2)
429             BN_free(Y2);
430     }
431
432 static void keypair(FILE *in, FILE *out)
433     {
434     char buf[1024];
435     char lbuf[1024];
436     char *keyword, *value;
437     int dsa2, L, N;
438
439     while(fgets(buf,sizeof buf,in) != NULL)
440         {
441         if (!parse_line(&keyword, &value, lbuf, buf))
442                 {
443                 continue;
444                 }
445         if(!strcmp(keyword,"[mod"))
446             {
447             if (!parse_mod(value, &dsa2, &L, &N, NULL))
448                 {
449                 fprintf(stderr, "Mod Parse Error\n");
450                 exit (1);
451                 }
452             fputs(buf,out);
453             }
454         else if(!strcmp(keyword,"N"))
455             {
456             DSA *dsa;
457             int n=atoi(value);
458
459             dsa = FIPS_dsa_new();
460             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, NULL, NULL, 0,
461                                                 NULL, NULL, NULL, NULL))
462                         {
463                         fprintf(stderr, "Parameter Generation error\n");
464                         exit(1);
465                         }
466             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, NULL, NULL, 0, -1,
467                                                 NULL, NULL, NULL, NULL) <= 0)
468                         {
469                         fprintf(stderr, "Parameter Generation error\n");
470                         exit(1);
471                         }
472             do_bn_print_name(out, "P",dsa->p);
473             do_bn_print_name(out, "Q",dsa->q);
474             do_bn_print_name(out, "G",dsa->g);
475             fputs("\n", out);
476
477             while(n--)
478                 {
479                 if (!DSA_generate_key(dsa))
480                         exit(1);
481
482                 do_bn_print_name(out, "X",dsa->priv_key);
483                 do_bn_print_name(out, "Y",dsa->pub_key);
484                 fputs("\n", out);
485                 }
486             }
487         }
488     }
489
490 static void siggen(FILE *in, FILE *out)
491     {
492     char buf[1024];
493     char lbuf[1024];
494     char *keyword, *value;
495     int dsa2, L, N;
496     const EVP_MD *md = NULL;
497     DSA *dsa=NULL;
498
499     while(fgets(buf,sizeof buf,in) != NULL)
500         {
501         if (!parse_line(&keyword, &value, lbuf, buf))
502                 {
503                 fputs(buf,out);
504                 continue;
505                 }
506         fputs(buf,out);
507         if(!strcmp(keyword,"[mod"))
508             {
509             if (!parse_mod(value, &dsa2, &L, &N, &md))
510                 {
511                 fprintf(stderr, "Mod Parse Error\n");
512                 exit (1);
513                 }
514             if (dsa)
515                 FIPS_dsa_free(dsa);
516             dsa = FIPS_dsa_new();
517             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md, NULL, 0,
518                                                 NULL, NULL, NULL, NULL))
519                         {
520                         fprintf(stderr, "Parameter Generation error\n");
521                         exit(1);
522                         }
523             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md, NULL, 0, -1,
524                                                 NULL, NULL, NULL, NULL) <= 0)
525                         {
526                         fprintf(stderr, "Parameter Generation error\n");
527                         exit(1);
528                         }
529             do_bn_print_name(out, "P",dsa->p);
530             do_bn_print_name(out, "Q",dsa->q);
531             do_bn_print_name(out, "G",dsa->g);
532             fputs("\n", out);
533             }
534         else if(!strcmp(keyword,"Msg"))
535             {
536             unsigned char msg[1024];
537             int n;
538             EVP_MD_CTX mctx;
539             DSA_SIG *sig;
540             FIPS_md_ctx_init(&mctx);
541
542             n=hex2bin(value,msg);
543
544             if (!DSA_generate_key(dsa))
545                 exit(1);
546             do_bn_print_name(out, "Y",dsa->pub_key);
547
548             FIPS_digestinit(&mctx, md);
549             FIPS_digestupdate(&mctx, msg, n);
550             sig = FIPS_dsa_sign_ctx(dsa, &mctx);
551
552             do_bn_print_name(out, "R",sig->r);
553             do_bn_print_name(out, "S",sig->s);
554             fputs("\n", out);
555             FIPS_dsa_sig_free(sig);
556             FIPS_md_ctx_cleanup(&mctx);
557             }
558         }
559         if (dsa)
560                 FIPS_dsa_free(dsa);
561     }
562
563 static void sigver(FILE *in, FILE *out)
564     {
565     DSA *dsa=NULL;
566     char buf[1024];
567     char lbuf[1024];
568     unsigned char msg[1024];
569     char *keyword, *value;
570     int n=0;
571     int dsa2, L, N;
572     const EVP_MD *md = NULL;
573     DSA_SIG sg, *sig = &sg;
574
575     sig->r = NULL;
576     sig->s = NULL;
577
578     while(fgets(buf,sizeof buf,in) != NULL)
579         {
580         if (!parse_line(&keyword, &value, lbuf, buf))
581                 {
582                 fputs(buf,out);
583                 continue;
584                 }
585         fputs(buf,out);
586         if(!strcmp(keyword,"[mod"))
587             {
588             if (!parse_mod(value, &dsa2, &L, &N, &md))
589                 {
590                 fprintf(stderr, "Mod Parse Error\n");
591                 exit (1);
592                 }
593             if (dsa)
594                 FIPS_dsa_free(dsa);
595             dsa = FIPS_dsa_new();
596             }
597         else if(!strcmp(keyword,"P"))
598             dsa->p=hex2bn(value);
599         else if(!strcmp(keyword,"Q"))
600             dsa->q=hex2bn(value);
601         else if(!strcmp(keyword,"G"))
602             dsa->g=hex2bn(value);
603         else if(!strcmp(keyword,"Msg"))
604             n=hex2bin(value,msg);
605         else if(!strcmp(keyword,"Y"))
606             dsa->pub_key=hex2bn(value);
607         else if(!strcmp(keyword,"R"))
608             sig->r=hex2bn(value);
609         else if(!strcmp(keyword,"S"))
610             {
611             EVP_MD_CTX mctx;
612             int r;
613             FIPS_md_ctx_init(&mctx);
614             sig->s=hex2bn(value);
615
616             FIPS_digestinit(&mctx, md);
617             FIPS_digestupdate(&mctx, msg, n);
618             no_err = 1;
619             r = FIPS_dsa_verify_ctx(dsa, &mctx, sig);
620             no_err = 0;
621             FIPS_md_ctx_cleanup(&mctx);
622         
623             fprintf(out, "Result = %c\n\n", r == 1 ? 'P' : 'F');
624             }
625         }
626     }
627
628 int main(int argc,char **argv)
629     {
630     FILE *in, *out;
631     if (argc == 4)
632         {
633         in = fopen(argv[2], "r");
634         if (!in)
635                 {
636                 fprintf(stderr, "Error opening input file\n");
637                 exit(1);
638                 }
639         out = fopen(argv[3], "w");
640         if (!out)
641                 {
642                 fprintf(stderr, "Error opening output file\n");
643                 exit(1);
644                 }
645         }
646     else if (argc == 2)
647         {
648         in = stdin;
649         out = stdout;
650         }
651     else
652         {
653         fprintf(stderr,"%s [prime|pqg|pqgver|keypair|keyver|siggen|sigver]\n",argv[0]);
654         exit(1);
655         }
656     fips_algtest_init();
657     if(!strcmp(argv[1],"prime"))
658         primes(in, out);
659     else if(!strcmp(argv[1],"pqg"))
660         pqg(in, out);
661     else if(!strcmp(argv[1],"pqgver"))
662         pqgver(in, out);
663     else if(!strcmp(argv[1],"keypair"))
664         keypair(in, out);
665     else if(!strcmp(argv[1],"keyver"))
666         keyver(in, out);
667     else if(!strcmp(argv[1],"siggen"))
668         siggen(in, out);
669     else if(!strcmp(argv[1],"sigver"))
670         sigver(in, out);
671     else
672         {
673         fprintf(stderr,"Don't know how to %s.\n",argv[1]);
674         exit(1);
675         }
676
677     if (argc == 4)
678         {
679         fclose(in);
680         fclose(out);
681         }
682
683     return 0;
684     }
685
686 #endif