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