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