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