Add support for DSA2 PQG generation of g parameter.
[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     BIGNUM *p = NULL, *q = NULL;
127     enum pqtype { PQG_NONE, PQG_PQ, PQG_G, PQG_GCANON}
128                 pqg_type = PQG_NONE;
129     int seedlen=-1, idxlen, idx = -1;
130     unsigned char seed[1024], idtmp[1024];
131
132     while(fgets(buf,sizeof buf,in) != NULL)
133         {
134         if (buf[0] == '[')
135                 {
136                 if (strstr(buf, "Probable"))
137                         pqg_type = PQG_PQ;
138                 else if (strstr(buf, "Unverifiable"))
139                         pqg_type = PQG_G;
140                 else if (strstr(buf, "Canonical"))
141                         pqg_type = PQG_GCANON;
142                 }
143         if (!parse_line(&keyword, &value, lbuf, buf))
144                 {
145                 fputs(buf,out);
146                 continue;
147                 }
148         fputs(buf,out);
149         if(!strcmp(keyword,"[mod"))
150             {
151             if (!parse_mod(value, &dsa2, &L, &N, &md))
152                 {
153                 fprintf(stderr, "Mod Parse Error\n");
154                 exit (1);
155                 }
156             }
157         else if(!strcmp(keyword,"N") 
158                 || (!strcmp(keyword, "Num") && pqg_type == PQG_PQ))
159             {
160             int n=atoi(value);
161
162             while(n--)
163                 {
164                 DSA *dsa;
165                 int counter;
166                 unsigned long h;
167                 dsa = FIPS_dsa_new();
168
169                 if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md,
170                                                 NULL, 0, seed,
171                                                 &counter, &h, NULL))
172                         {
173                         fprintf(stderr, "Parameter Generation error\n");
174                         exit(1);
175                         }
176                 if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
177                                                 NULL, 0, -1, seed,
178                                                 &counter, &h, NULL) <= 0)
179                         {
180                         fprintf(stderr, "Parameter Generation error\n");
181                         exit(1);
182                         }
183  
184                 do_bn_print_name(out, "P",dsa->p);
185                 do_bn_print_name(out, "Q",dsa->q);
186                 if (!dsa2)
187                         do_bn_print_name(out, "G",dsa->g);
188                 OutputValue(dsa2 ? "domain_parameter_seed" : "Seed",
189                                 seed, M_EVP_MD_size(md), out, 0);
190                 if (!dsa2)
191                         {
192                         fprintf(out, "c = %d\n",counter);
193                         fprintf(out, "H = %lx\n\n",h);
194                         }
195                 else
196                         fputs("\n", out);
197                 }
198             }
199         else if(!strcmp(keyword,"P"))
200             p=hex2bn(value);
201         else if(!strcmp(keyword,"Q"))
202             q=hex2bn(value);
203         else if(!strcmp(keyword,"domain_parameter_seed"))
204             seedlen = hex2bin(value, seed);
205         else if(!strcmp(keyword,"index"))
206             {
207             idxlen = hex2bin(value, idtmp);
208             if (idxlen != 1)
209                 {
210                 fprintf(stderr, "Index value error\n");
211                 exit (1);
212                 }
213             idx = idtmp[0];
214             }
215         if ((idx >= 0 && pqg_type == PQG_GCANON) || (q && pqg_type == PQG_G))
216                 {
217                 DSA *dsa;
218                 dsa = FIPS_dsa_new();
219                 dsa->p = p;
220                 dsa->q = q;
221                 p = q = NULL;
222                 if (dsa_builtin_paramgen2(dsa, L, N, md,
223                                                 seed, seedlen, idx, NULL,
224                                                 NULL, NULL, NULL) <= 0)
225                         {
226                         fprintf(stderr, "Parameter Generation error\n");
227                         exit(1);
228                         }
229                 do_bn_print_name(out, "G",dsa->g);
230                 FIPS_dsa_free(dsa);
231                 idx = -1;
232                 }
233         }
234     }
235
236 static void pqgver(FILE *in, FILE *out)
237     {
238     char buf[1024];
239     char lbuf[1024];
240     char *keyword, *value;
241     BIGNUM *p = NULL, *q = NULL, *g = NULL;
242     int counter=-1, counter2;
243     unsigned long h=0, h2;
244     DSA *dsa=NULL;
245     int dsa2, L, N, part_test = 0;
246     const EVP_MD *md = NULL;
247     int seedlen=-1, idxlen, idx = -1;
248     unsigned char seed[1024], idtmp[1024];
249
250     while(fgets(buf,sizeof buf,in) != NULL)
251         {
252         if (!parse_line(&keyword, &value, lbuf, buf))
253                 {
254                 if (p && q)
255                         {
256                         part_test = 1;
257                         goto partial;
258                         }
259                 fputs(buf,out);
260                 continue;
261                 }
262         fputs(buf, out);
263         if(!strcmp(keyword,"[mod"))
264             {
265             if (!parse_mod(value, &dsa2, &L, &N, &md))
266                 {
267                 fprintf(stderr, "Mod Parse Error\n");
268                 exit (1);
269                 }
270             }
271         else if(!strcmp(keyword,"P"))
272             p=hex2bn(value);
273         else if(!strcmp(keyword,"Q"))
274             q=hex2bn(value);
275         else if(!strcmp(keyword,"G"))
276             g=hex2bn(value);
277         else if(!strcmp(keyword,"Seed")
278                 || !strcmp(keyword,"domain_parameter_seed"))
279             {
280             seedlen = hex2bin(value, seed);
281             if (!dsa2 && seedlen != 20)
282                 {
283                 fprintf(stderr, "Seed parse length error\n");
284                 exit (1);
285                 }
286             if (idx > 0)
287                 part_test = 1;
288             }
289         else if(!strcmp(keyword,"index"))
290             {
291             idxlen = hex2bin(value, idtmp);
292             if (idxlen != 1)
293                 {
294                 fprintf(stderr, "Index value error\n");
295                 exit (1);
296                 }
297             idx = idtmp[0];
298             }
299         else if(!strcmp(keyword,"c"))
300             counter = atoi(buf+4);
301         partial:
302         if(!strcmp(keyword,"H") || part_test)
303             {
304             if (!part_test)
305                 h = atoi(value);
306             if (!p || !q || (!g && !part_test))
307                 {
308                 fprintf(stderr, "Parse Error\n");
309                 exit (1);
310                 }
311             dsa = FIPS_dsa_new();
312             if (idx >= 0)
313                 {
314                 dsa->p = BN_dup(p);
315                 dsa->q = BN_dup(q);
316                 }
317             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md,
318                                         seed, seedlen, NULL,
319                                         &counter2, &h2, NULL))
320                         {
321                         fprintf(stderr, "Parameter Generation error\n");
322                         exit(1);
323                         }
324             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
325                                         seed, seedlen, idx, NULL,
326                                         &counter2, &h2, NULL) < 0)
327                         {
328                         fprintf(stderr, "Parameter Generation error\n");
329                         exit(1);
330                         }
331             if (idx >= 0)
332                 {
333                 if (BN_cmp(dsa->g, g))
334                         fprintf(out, "Result = F\n");
335                 else
336                         fprintf(out, "Result = P\n");
337                 }
338             else if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || 
339                 (!part_test &&
340                 ((BN_cmp(dsa->g, g) || (counter != counter2) || (h != h2)))))
341                 fprintf(out, "Result = F\n");
342             else
343                 fprintf(out, "Result = P\n");
344             BN_free(p);
345             BN_free(q);
346             BN_free(g);
347             p = NULL;
348             q = NULL;
349             g = NULL;
350             FIPS_dsa_free(dsa);
351             dsa = NULL;
352             if (part_test)
353                 {
354                 if (idx == -1)
355                         fputs(buf,out);
356                 part_test = 0;
357                 }
358             idx = -1;
359             }
360         }
361     }
362
363 /* Keypair verification routine. NB: this isn't part of the standard FIPS140-2
364  * algorithm tests. It is an additional test to perform sanity checks on the
365  * output of the KeyPair test.
366  */
367
368 static int dss_paramcheck(int L, int N, BIGNUM *p, BIGNUM *q, BIGNUM *g,
369                                                         BN_CTX *ctx)
370     {
371     BIGNUM *rem = NULL;
372     if (BN_num_bits(p) != L)
373         return 0;
374     if (BN_num_bits(q) != N)
375         return 0;
376     if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1)
377         return 0;
378     if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1)
379         return 0;
380     rem = BN_new();
381     if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem)
382         || (BN_cmp(g, BN_value_one()) <= 0)
383         || !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem))
384         {
385         BN_free(rem);
386         return 0;
387         }
388     /* Todo: check g */
389     BN_free(rem);
390     return 1;
391     }
392
393 static void keyver(FILE *in, FILE *out)
394     {
395     char buf[1024];
396     char lbuf[1024];
397     char *keyword, *value;
398     BIGNUM *p = NULL, *q = NULL, *g = NULL, *X = NULL, *Y = NULL;
399     BIGNUM *Y2;
400     BN_CTX *ctx = NULL;
401     int dsa2, L, N;
402     int paramcheck = 0;
403
404     ctx = BN_CTX_new();
405     Y2 = BN_new();
406
407     while(fgets(buf,sizeof buf,in) != NULL)
408         {
409         if (!parse_line(&keyword, &value, lbuf, buf))
410                 {
411                 fputs(buf,out);
412                 continue;
413                 }
414         if(!strcmp(keyword,"[mod"))
415             {
416             if (p)
417                 BN_free(p);
418             p = NULL;
419             if (q)
420                 BN_free(q);
421             q = NULL;
422             if (g)
423                 BN_free(g);
424             g = NULL;
425             paramcheck = 0;
426             if (!parse_mod(value, &dsa2, &L, &N, NULL))
427                 {
428                 fprintf(stderr, "Mod Parse Error\n");
429                 exit (1);
430                 }
431             }
432         else if(!strcmp(keyword,"P"))
433             p=hex2bn(value);
434         else if(!strcmp(keyword,"Q"))
435             q=hex2bn(value);
436         else if(!strcmp(keyword,"G"))
437             g=hex2bn(value);
438         else if(!strcmp(keyword,"X"))
439             X=hex2bn(value);
440         else if(!strcmp(keyword,"Y"))
441             {
442             Y=hex2bn(value);
443             if (!p || !q || !g || !X || !Y)
444                 {
445                 fprintf(stderr, "Parse Error\n");
446                 exit (1);
447                 }
448             do_bn_print_name(out, "P",p);
449             do_bn_print_name(out, "Q",q);
450             do_bn_print_name(out, "G",g);
451             do_bn_print_name(out, "X",X);
452             do_bn_print_name(out, "Y",Y);
453             if (!paramcheck)
454                 {
455                 if (dss_paramcheck(L, N, p, q, g, ctx))
456                         paramcheck = 1;
457                 else
458                         paramcheck = -1;
459                 }
460             if (paramcheck != 1)
461                 fprintf(out, "Result = F\n");
462             else
463                 {
464                 if (!BN_mod_exp(Y2, g, X, p, ctx) || BN_cmp(Y2, Y))
465                         fprintf(out, "Result = F\n");
466                 else
467                         fprintf(out, "Result = P\n");
468                 }
469             BN_free(X);
470             BN_free(Y);
471             X = NULL;
472             Y = NULL;
473             }
474         }
475         if (p)
476             BN_free(p);
477         if (q)
478             BN_free(q);
479         if (g)
480             BN_free(g);
481         if (Y2)
482             BN_free(Y2);
483     }
484
485 static void keypair(FILE *in, FILE *out)
486     {
487     char buf[1024];
488     char lbuf[1024];
489     char *keyword, *value;
490     int dsa2, L, N;
491
492     while(fgets(buf,sizeof buf,in) != NULL)
493         {
494         if (!parse_line(&keyword, &value, lbuf, buf))
495                 {
496                 continue;
497                 }
498         if(!strcmp(keyword,"[mod"))
499             {
500             if (!parse_mod(value, &dsa2, &L, &N, NULL))
501                 {
502                 fprintf(stderr, "Mod Parse Error\n");
503                 exit (1);
504                 }
505             fputs(buf,out);
506             }
507         else if(!strcmp(keyword,"N"))
508             {
509             DSA *dsa;
510             int n=atoi(value);
511
512             dsa = FIPS_dsa_new();
513             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, NULL, NULL, 0,
514                                                 NULL, NULL, NULL, NULL))
515                         {
516                         fprintf(stderr, "Parameter Generation error\n");
517                         exit(1);
518                         }
519             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, NULL, NULL, 0, -1,
520                                                 NULL, NULL, NULL, NULL) <= 0)
521                         {
522                         fprintf(stderr, "Parameter Generation error\n");
523                         exit(1);
524                         }
525             do_bn_print_name(out, "P",dsa->p);
526             do_bn_print_name(out, "Q",dsa->q);
527             do_bn_print_name(out, "G",dsa->g);
528             fputs("\n", out);
529
530             while(n--)
531                 {
532                 if (!DSA_generate_key(dsa))
533                         exit(1);
534
535                 do_bn_print_name(out, "X",dsa->priv_key);
536                 do_bn_print_name(out, "Y",dsa->pub_key);
537                 fputs("\n", out);
538                 }
539             }
540         }
541     }
542
543 static void siggen(FILE *in, FILE *out)
544     {
545     char buf[1024];
546     char lbuf[1024];
547     char *keyword, *value;
548     int dsa2, L, N;
549     const EVP_MD *md = NULL;
550     DSA *dsa=NULL;
551
552     while(fgets(buf,sizeof buf,in) != NULL)
553         {
554         if (!parse_line(&keyword, &value, lbuf, buf))
555                 {
556                 fputs(buf,out);
557                 continue;
558                 }
559         fputs(buf,out);
560         if(!strcmp(keyword,"[mod"))
561             {
562             if (!parse_mod(value, &dsa2, &L, &N, &md))
563                 {
564                 fprintf(stderr, "Mod Parse Error\n");
565                 exit (1);
566                 }
567             if (dsa)
568                 FIPS_dsa_free(dsa);
569             dsa = FIPS_dsa_new();
570             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md, NULL, 0,
571                                                 NULL, NULL, NULL, NULL))
572                         {
573                         fprintf(stderr, "Parameter Generation error\n");
574                         exit(1);
575                         }
576             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md, NULL, 0, -1,
577                                                 NULL, NULL, NULL, NULL) <= 0)
578                         {
579                         fprintf(stderr, "Parameter Generation error\n");
580                         exit(1);
581                         }
582             do_bn_print_name(out, "P",dsa->p);
583             do_bn_print_name(out, "Q",dsa->q);
584             do_bn_print_name(out, "G",dsa->g);
585             fputs("\n", out);
586             }
587         else if(!strcmp(keyword,"Msg"))
588             {
589             unsigned char msg[1024];
590             int n;
591             EVP_MD_CTX mctx;
592             DSA_SIG *sig;
593             FIPS_md_ctx_init(&mctx);
594
595             n=hex2bin(value,msg);
596
597             if (!DSA_generate_key(dsa))
598                 exit(1);
599             do_bn_print_name(out, "Y",dsa->pub_key);
600
601             FIPS_digestinit(&mctx, md);
602             FIPS_digestupdate(&mctx, msg, n);
603             sig = FIPS_dsa_sign_ctx(dsa, &mctx);
604
605             do_bn_print_name(out, "R",sig->r);
606             do_bn_print_name(out, "S",sig->s);
607             fputs("\n", out);
608             FIPS_dsa_sig_free(sig);
609             FIPS_md_ctx_cleanup(&mctx);
610             }
611         }
612         if (dsa)
613                 FIPS_dsa_free(dsa);
614     }
615
616 static void sigver(FILE *in, FILE *out)
617     {
618     DSA *dsa=NULL;
619     char buf[1024];
620     char lbuf[1024];
621     unsigned char msg[1024];
622     char *keyword, *value;
623     int n=0;
624     int dsa2, L, N;
625     const EVP_MD *md = NULL;
626     DSA_SIG sg, *sig = &sg;
627
628     sig->r = NULL;
629     sig->s = NULL;
630
631     while(fgets(buf,sizeof buf,in) != NULL)
632         {
633         if (!parse_line(&keyword, &value, lbuf, buf))
634                 {
635                 fputs(buf,out);
636                 continue;
637                 }
638         fputs(buf,out);
639         if(!strcmp(keyword,"[mod"))
640             {
641             if (!parse_mod(value, &dsa2, &L, &N, &md))
642                 {
643                 fprintf(stderr, "Mod Parse Error\n");
644                 exit (1);
645                 }
646             if (dsa)
647                 FIPS_dsa_free(dsa);
648             dsa = FIPS_dsa_new();
649             }
650         else if(!strcmp(keyword,"P"))
651             dsa->p=hex2bn(value);
652         else if(!strcmp(keyword,"Q"))
653             dsa->q=hex2bn(value);
654         else if(!strcmp(keyword,"G"))
655             dsa->g=hex2bn(value);
656         else if(!strcmp(keyword,"Msg"))
657             n=hex2bin(value,msg);
658         else if(!strcmp(keyword,"Y"))
659             dsa->pub_key=hex2bn(value);
660         else if(!strcmp(keyword,"R"))
661             sig->r=hex2bn(value);
662         else if(!strcmp(keyword,"S"))
663             {
664             EVP_MD_CTX mctx;
665             int r;
666             FIPS_md_ctx_init(&mctx);
667             sig->s=hex2bn(value);
668
669             FIPS_digestinit(&mctx, md);
670             FIPS_digestupdate(&mctx, msg, n);
671             no_err = 1;
672             r = FIPS_dsa_verify_ctx(dsa, &mctx, sig);
673             no_err = 0;
674             FIPS_md_ctx_cleanup(&mctx);
675         
676             fprintf(out, "Result = %c\n\n", r == 1 ? 'P' : 'F');
677             }
678         }
679     }
680
681 int main(int argc,char **argv)
682     {
683     FILE *in, *out;
684     if (argc == 4)
685         {
686         in = fopen(argv[2], "r");
687         if (!in)
688                 {
689                 fprintf(stderr, "Error opening input file\n");
690                 exit(1);
691                 }
692         out = fopen(argv[3], "w");
693         if (!out)
694                 {
695                 fprintf(stderr, "Error opening output file\n");
696                 exit(1);
697                 }
698         }
699     else if (argc == 2)
700         {
701         in = stdin;
702         out = stdout;
703         }
704     else
705         {
706         fprintf(stderr,"%s [prime|pqg|pqgver|keypair|keyver|siggen|sigver]\n",argv[0]);
707         exit(1);
708         }
709     fips_algtest_init();
710     if(!strcmp(argv[1],"prime"))
711         primes(in, out);
712     else if(!strcmp(argv[1],"pqg"))
713         pqg(in, out);
714     else if(!strcmp(argv[1],"pqgver"))
715         pqgver(in, out);
716     else if(!strcmp(argv[1],"keypair"))
717         keypair(in, out);
718     else if(!strcmp(argv[1],"keyver"))
719         keyver(in, out);
720     else if(!strcmp(argv[1],"siggen"))
721         siggen(in, out);
722     else if(!strcmp(argv[1],"sigver"))
723         sigver(in, out);
724     else
725         {
726         fprintf(stderr,"Don't know how to %s.\n",argv[1]);
727         exit(1);
728         }
729
730     if (argc == 4)
731         {
732         fclose(in);
733         fclose(out);
734         }
735
736     return 0;
737     }
738
739 #endif