d355fcb6ff10220fae0f15c0444209fea625b8bb
[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             no_err = 1;
318             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md,
319                                         seed, seedlen, NULL,
320                                         &counter2, &h2, NULL))
321                         {
322                         fprintf(stderr, "Parameter Generation error\n");
323                         exit(1);
324                         }
325             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
326                                         seed, seedlen, idx, NULL,
327                                         &counter2, &h2, NULL) < 0)
328                         {
329                         fprintf(stderr, "Parameter Generation error\n");
330                         exit(1);
331                         }
332             no_err = 0;
333             if (idx >= 0)
334                 {
335                 if (BN_cmp(dsa->g, g))
336                         fprintf(out, "Result = F\n");
337                 else
338                         fprintf(out, "Result = P\n");
339                 }
340             else if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || 
341                 (!part_test &&
342                 ((BN_cmp(dsa->g, g) || (counter != counter2) || (h != h2)))))
343                 fprintf(out, "Result = F\n");
344             else
345                 fprintf(out, "Result = P\n");
346             BN_free(p);
347             BN_free(q);
348             BN_free(g);
349             p = NULL;
350             q = NULL;
351             g = NULL;
352             FIPS_dsa_free(dsa);
353             dsa = NULL;
354             if (part_test)
355                 {
356                 if (idx == -1)
357                         fputs(buf,out);
358                 part_test = 0;
359                 }
360             idx = -1;
361             }
362         }
363     }
364
365 /* Keypair verification routine. NB: this isn't part of the standard FIPS140-2
366  * algorithm tests. It is an additional test to perform sanity checks on the
367  * output of the KeyPair test.
368  */
369
370 static int dss_paramcheck(int L, int N, BIGNUM *p, BIGNUM *q, BIGNUM *g,
371                                                         BN_CTX *ctx)
372     {
373     BIGNUM *rem = NULL;
374     if (BN_num_bits(p) != L)
375         return 0;
376     if (BN_num_bits(q) != N)
377         return 0;
378     if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1)
379         return 0;
380     if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1)
381         return 0;
382     rem = BN_new();
383     if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem)
384         || (BN_cmp(g, BN_value_one()) <= 0)
385         || !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem))
386         {
387         BN_free(rem);
388         return 0;
389         }
390     /* Todo: check g */
391     BN_free(rem);
392     return 1;
393     }
394
395 static void keyver(FILE *in, FILE *out)
396     {
397     char buf[1024];
398     char lbuf[1024];
399     char *keyword, *value;
400     BIGNUM *p = NULL, *q = NULL, *g = NULL, *X = NULL, *Y = NULL;
401     BIGNUM *Y2;
402     BN_CTX *ctx = NULL;
403     int dsa2, L, N;
404     int paramcheck = 0;
405
406     ctx = BN_CTX_new();
407     Y2 = BN_new();
408
409     while(fgets(buf,sizeof buf,in) != NULL)
410         {
411         if (!parse_line(&keyword, &value, lbuf, buf))
412                 {
413                 fputs(buf,out);
414                 continue;
415                 }
416         if(!strcmp(keyword,"[mod"))
417             {
418             if (p)
419                 BN_free(p);
420             p = NULL;
421             if (q)
422                 BN_free(q);
423             q = NULL;
424             if (g)
425                 BN_free(g);
426             g = NULL;
427             paramcheck = 0;
428             if (!parse_mod(value, &dsa2, &L, &N, NULL))
429                 {
430                 fprintf(stderr, "Mod Parse Error\n");
431                 exit (1);
432                 }
433             }
434         else if(!strcmp(keyword,"P"))
435             p=hex2bn(value);
436         else if(!strcmp(keyword,"Q"))
437             q=hex2bn(value);
438         else if(!strcmp(keyword,"G"))
439             g=hex2bn(value);
440         else if(!strcmp(keyword,"X"))
441             X=hex2bn(value);
442         else if(!strcmp(keyword,"Y"))
443             {
444             Y=hex2bn(value);
445             if (!p || !q || !g || !X || !Y)
446                 {
447                 fprintf(stderr, "Parse Error\n");
448                 exit (1);
449                 }
450             do_bn_print_name(out, "P",p);
451             do_bn_print_name(out, "Q",q);
452             do_bn_print_name(out, "G",g);
453             do_bn_print_name(out, "X",X);
454             do_bn_print_name(out, "Y",Y);
455             if (!paramcheck)
456                 {
457                 if (dss_paramcheck(L, N, p, q, g, ctx))
458                         paramcheck = 1;
459                 else
460                         paramcheck = -1;
461                 }
462             if (paramcheck != 1)
463                 fprintf(out, "Result = F\n");
464             else
465                 {
466                 if (!BN_mod_exp(Y2, g, X, p, ctx) || BN_cmp(Y2, Y))
467                         fprintf(out, "Result = F\n");
468                 else
469                         fprintf(out, "Result = P\n");
470                 }
471             BN_free(X);
472             BN_free(Y);
473             X = NULL;
474             Y = NULL;
475             }
476         }
477         if (p)
478             BN_free(p);
479         if (q)
480             BN_free(q);
481         if (g)
482             BN_free(g);
483         if (Y2)
484             BN_free(Y2);
485     }
486
487 static void keypair(FILE *in, FILE *out)
488     {
489     char buf[1024];
490     char lbuf[1024];
491     char *keyword, *value;
492     int dsa2, L, N;
493
494     while(fgets(buf,sizeof buf,in) != NULL)
495         {
496         if (!parse_line(&keyword, &value, lbuf, buf))
497                 {
498                 continue;
499                 }
500         if(!strcmp(keyword,"[mod"))
501             {
502             if (!parse_mod(value, &dsa2, &L, &N, NULL))
503                 {
504                 fprintf(stderr, "Mod Parse Error\n");
505                 exit (1);
506                 }
507             fputs(buf,out);
508             }
509         else if(!strcmp(keyword,"N"))
510             {
511             DSA *dsa;
512             int n=atoi(value);
513
514             dsa = FIPS_dsa_new();
515             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, NULL, NULL, 0,
516                                                 NULL, NULL, NULL, NULL))
517                         {
518                         fprintf(stderr, "Parameter Generation error\n");
519                         exit(1);
520                         }
521             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, NULL, NULL, 0, -1,
522                                                 NULL, NULL, NULL, NULL) <= 0)
523                         {
524                         fprintf(stderr, "Parameter Generation error\n");
525                         exit(1);
526                         }
527             do_bn_print_name(out, "P",dsa->p);
528             do_bn_print_name(out, "Q",dsa->q);
529             do_bn_print_name(out, "G",dsa->g);
530             fputs("\n", out);
531
532             while(n--)
533                 {
534                 if (!DSA_generate_key(dsa))
535                         exit(1);
536
537                 do_bn_print_name(out, "X",dsa->priv_key);
538                 do_bn_print_name(out, "Y",dsa->pub_key);
539                 fputs("\n", out);
540                 }
541             }
542         }
543     }
544
545 static void siggen(FILE *in, FILE *out)
546     {
547     char buf[1024];
548     char lbuf[1024];
549     char *keyword, *value;
550     int dsa2, L, N;
551     const EVP_MD *md = NULL;
552     DSA *dsa=NULL;
553
554     while(fgets(buf,sizeof buf,in) != NULL)
555         {
556         if (!parse_line(&keyword, &value, lbuf, buf))
557                 {
558                 fputs(buf,out);
559                 continue;
560                 }
561         fputs(buf,out);
562         if(!strcmp(keyword,"[mod"))
563             {
564             if (!parse_mod(value, &dsa2, &L, &N, &md))
565                 {
566                 fprintf(stderr, "Mod Parse Error\n");
567                 exit (1);
568                 }
569             if (dsa)
570                 FIPS_dsa_free(dsa);
571             dsa = FIPS_dsa_new();
572             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md, NULL, 0,
573                                                 NULL, NULL, NULL, NULL))
574                         {
575                         fprintf(stderr, "Parameter Generation error\n");
576                         exit(1);
577                         }
578             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md, NULL, 0, -1,
579                                                 NULL, NULL, NULL, NULL) <= 0)
580                         {
581                         fprintf(stderr, "Parameter Generation error\n");
582                         exit(1);
583                         }
584             do_bn_print_name(out, "P",dsa->p);
585             do_bn_print_name(out, "Q",dsa->q);
586             do_bn_print_name(out, "G",dsa->g);
587             fputs("\n", out);
588             }
589         else if(!strcmp(keyword,"Msg"))
590             {
591             unsigned char msg[1024];
592             int n;
593             EVP_MD_CTX mctx;
594             DSA_SIG *sig;
595             FIPS_md_ctx_init(&mctx);
596
597             n=hex2bin(value,msg);
598
599             if (!DSA_generate_key(dsa))
600                 exit(1);
601             do_bn_print_name(out, "Y",dsa->pub_key);
602
603             FIPS_digestinit(&mctx, md);
604             FIPS_digestupdate(&mctx, msg, n);
605             sig = FIPS_dsa_sign_ctx(dsa, &mctx);
606
607             do_bn_print_name(out, "R",sig->r);
608             do_bn_print_name(out, "S",sig->s);
609             fputs("\n", out);
610             FIPS_dsa_sig_free(sig);
611             FIPS_md_ctx_cleanup(&mctx);
612             }
613         }
614         if (dsa)
615                 FIPS_dsa_free(dsa);
616     }
617
618 static void sigver(FILE *in, FILE *out)
619     {
620     DSA *dsa=NULL;
621     char buf[1024];
622     char lbuf[1024];
623     unsigned char msg[1024];
624     char *keyword, *value;
625     int n=0;
626     int dsa2, L, N;
627     const EVP_MD *md = NULL;
628     DSA_SIG sg, *sig = &sg;
629
630     sig->r = NULL;
631     sig->s = NULL;
632
633     while(fgets(buf,sizeof buf,in) != NULL)
634         {
635         if (!parse_line(&keyword, &value, lbuf, buf))
636                 {
637                 fputs(buf,out);
638                 continue;
639                 }
640         fputs(buf,out);
641         if(!strcmp(keyword,"[mod"))
642             {
643             if (!parse_mod(value, &dsa2, &L, &N, &md))
644                 {
645                 fprintf(stderr, "Mod Parse Error\n");
646                 exit (1);
647                 }
648             if (dsa)
649                 FIPS_dsa_free(dsa);
650             dsa = FIPS_dsa_new();
651             }
652         else if(!strcmp(keyword,"P"))
653             dsa->p=hex2bn(value);
654         else if(!strcmp(keyword,"Q"))
655             dsa->q=hex2bn(value);
656         else if(!strcmp(keyword,"G"))
657             dsa->g=hex2bn(value);
658         else if(!strcmp(keyword,"Msg"))
659             n=hex2bin(value,msg);
660         else if(!strcmp(keyword,"Y"))
661             dsa->pub_key=hex2bn(value);
662         else if(!strcmp(keyword,"R"))
663             sig->r=hex2bn(value);
664         else if(!strcmp(keyword,"S"))
665             {
666             EVP_MD_CTX mctx;
667             int r;
668             FIPS_md_ctx_init(&mctx);
669             sig->s=hex2bn(value);
670
671             FIPS_digestinit(&mctx, md);
672             FIPS_digestupdate(&mctx, msg, n);
673             no_err = 1;
674             r = FIPS_dsa_verify_ctx(dsa, &mctx, sig);
675             no_err = 0;
676             FIPS_md_ctx_cleanup(&mctx);
677         
678             fprintf(out, "Result = %c\n\n", r == 1 ? 'P' : 'F');
679             }
680         }
681     }
682
683 int main(int argc,char **argv)
684     {
685     FILE *in, *out;
686     if (argc == 4)
687         {
688         in = fopen(argv[2], "r");
689         if (!in)
690                 {
691                 fprintf(stderr, "Error opening input file\n");
692                 exit(1);
693                 }
694         out = fopen(argv[3], "w");
695         if (!out)
696                 {
697                 fprintf(stderr, "Error opening output file\n");
698                 exit(1);
699                 }
700         }
701     else if (argc == 2)
702         {
703         in = stdin;
704         out = stdout;
705         }
706     else
707         {
708         fprintf(stderr,"%s [prime|pqg|pqgver|keypair|keyver|siggen|sigver]\n",argv[0]);
709         exit(1);
710         }
711     fips_algtest_init();
712     if(!strcmp(argv[1],"prime"))
713         primes(in, out);
714     else if(!strcmp(argv[1],"pqg"))
715         pqg(in, out);
716     else if(!strcmp(argv[1],"pqgver"))
717         pqgver(in, out);
718     else if(!strcmp(argv[1],"keypair"))
719         keypair(in, out);
720     else if(!strcmp(argv[1],"keyver"))
721         keyver(in, out);
722     else if(!strcmp(argv[1],"siggen"))
723         siggen(in, out);
724     else if(!strcmp(argv[1],"sigver"))
725         sigver(in, out);
726     else
727         {
728         fprintf(stderr,"Don't know how to %s.\n",argv[1]);
729         exit(1);
730         }
731
732     if (argc == 4)
733         {
734         fclose(in);
735         fclose(out);
736         }
737
738     return 0;
739     }
740
741 #endif