Provisional, experimental support for DSA2 parameter generation algorithm.
[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                 *pmd = EVP_sha1();
39                 return 1;
40                 }
41         *pdsa2 = 1;
42         *p = 0;
43         if (!parse_line(&keyword, &value, lbuf, line))
44                 return 0;
45         if (strcmp(keyword, "L"))
46                 return 0;
47         *pL = atoi(value);
48         strcpy(line, p + 1);
49         p = strchr(line, ',');
50         if (!p)
51                 return 0;
52         *p = 0;
53         if (!parse_line(&keyword, &value, lbuf, line))
54                 return 0;
55         if (strcmp(keyword, "N"))
56                 return 0;
57         *pN = atoi(value);
58         strcpy(line, p + 1);
59         p = strchr(line, ']');
60         if (!p)
61                 return 0;
62         *p = 0;
63         p = line;
64         while(isspace(*p))
65                 p++;
66         if (!strcmp(p, "SHA-1"))
67                 *pmd = EVP_sha1();
68         else if (!strcmp(p, "SHA-224"))
69                 *pmd = EVP_sha224();
70         else if (!strcmp(p, "SHA-256"))
71                 *pmd = EVP_sha256();
72         else if (!strcmp(p, "SHA-384"))
73                 *pmd = EVP_sha384();
74         else if (!strcmp(p, "SHA-512"))
75                 *pmd = EVP_sha512();
76         else
77                 return 0;
78         return 1;
79         }
80
81
82
83 static void pbn(const char *name, BIGNUM *bn)
84         {
85         int len, i;
86         unsigned char *tmp;
87         len = BN_num_bytes(bn);
88         tmp = OPENSSL_malloc(len);
89         if (!tmp)
90                 {
91                 fprintf(stderr, "Memory allocation error\n");
92                 return;
93                 }
94         BN_bn2bin(bn, tmp);
95         printf("%s = ", name);
96         for (i = 0; i < len; i++)
97                 printf("%02X", tmp[i]);
98         fputs("\n", stdout);
99         OPENSSL_free(tmp);
100         return;
101         }
102
103 static void primes()
104     {
105     char buf[10240];
106     char lbuf[10240];
107     char *keyword, *value;
108
109     while(fgets(buf,sizeof buf,stdin) != NULL)
110         {
111         fputs(buf,stdout);
112         if (!parse_line(&keyword, &value, lbuf, buf))
113                 continue;
114         if(!strcmp(keyword,"Prime"))
115             {
116             BIGNUM *pp;
117
118             pp=BN_new();
119             do_hex2bn(&pp,value);
120             printf("result= %c\n",
121                    BN_is_prime_ex(pp,20,NULL,NULL) ? 'P' : 'F');
122             }       
123         }
124     }
125
126 int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
127         const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
128         unsigned char *seed_out,
129         int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
130 int dsa_builtin_paramgen2(DSA *ret, size_t bits, size_t qbits,
131         const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
132         unsigned char *seed_out,
133         int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
134
135 static void pqg()
136     {
137     char buf[1024];
138     char lbuf[1024];
139     char *keyword, *value;
140     int nmod=0;
141
142     while(fgets(buf,sizeof buf,stdin) != NULL)
143         {
144         if (!parse_line(&keyword, &value, lbuf, buf))
145                 {
146                 fputs(buf,stdout);
147                 continue;
148                 }
149         if(!strcmp(keyword,"[mod"))
150             {
151             nmod=atoi(value);
152             }
153         else if(!strcmp(keyword,"N"))
154             {
155             int n=atoi(value);
156
157             printf("[mod = %d]\n\n",nmod);
158
159             while(n--)
160                 {
161                 unsigned char seed[EVP_MAX_MD_SIZE];
162                 DSA *dsa;
163                 int counter;
164                 unsigned long h;
165                 dsa = FIPS_dsa_new();
166
167                 if (!dsa_builtin_paramgen(dsa, nmod, 160, NULL, NULL, 0,
168                                         seed,&counter,&h,NULL))
169                         exit(1);
170                 pbn("P",dsa->p);
171                 pbn("Q",dsa->q);
172                 pbn("G",dsa->g);
173                 pv("Seed",seed,20);
174                 printf("c = %d\n",counter);
175                 printf("H = %lx\n",h);
176                 putc('\n',stdout);
177                 }
178             }
179         else
180             fputs(buf,stdout);
181         }
182     }
183
184 static void pqgver()
185     {
186     char buf[1024];
187     char lbuf[1024];
188     char *keyword, *value;
189     BIGNUM *p = NULL, *q = NULL, *g = NULL;
190     int counter, counter2;
191     unsigned long h, h2;
192     DSA *dsa=NULL;
193     int dsa2, L, N;
194     const EVP_MD *md = NULL;
195     int seedlen;
196     unsigned char seed[1024];
197
198     while(fgets(buf,sizeof buf,stdin) != NULL)
199         {
200         if (!parse_line(&keyword, &value, lbuf, buf))
201                 {
202                 fputs(buf,stdout);
203                 continue;
204                 }
205         fputs(buf, stdout);
206         if(!strcmp(keyword,"[mod"))
207             {
208             if (!parse_mod(value, &dsa2, &L, &N, &md))
209                 {
210                 fprintf(stderr, "Mod Parse Error\n");
211                 exit (1);
212                 }
213             }
214         else if(!strcmp(keyword,"P"))
215             p=hex2bn(value);
216         else if(!strcmp(keyword,"Q"))
217             q=hex2bn(value);
218         else if(!strcmp(keyword,"G"))
219             g=hex2bn(value);
220         else if(!strcmp(keyword,"Seed"))
221             {
222             seedlen = hex2bin(value, seed);
223             if (!dsa2 && seedlen != 20)
224                 {
225                 fprintf(stderr, "Seed parse length error\n");
226                 exit (1);
227                 }
228             }
229         else if(!strcmp(keyword,"c"))
230             counter =atoi(buf+4);
231         else if(!strcmp(keyword,"H"))
232             {
233             h = atoi(value);
234             if (!p || !q || !g)
235                 {
236                 fprintf(stderr, "Parse Error\n");
237                 exit (1);
238                 }
239             dsa = FIPS_dsa_new();
240             if (!dsa2 && !dsa_builtin_paramgen(dsa, L, N, md,
241                                         seed, seedlen, NULL,
242                                         &counter2, &h2, NULL))
243                         {
244                         fprintf(stderr, "Parameter Generation error\n");
245                         exit(1);
246                         }
247             if (dsa2 && dsa_builtin_paramgen2(dsa, L, N, md,
248                                         seed, seedlen, NULL,
249                                         &counter2, &h2, NULL) < 0)
250                         {
251                         fprintf(stderr, "Parameter Generation error\n");
252                         exit(1);
253                         }
254             if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || BN_cmp(dsa->g, g)
255                 || (counter != counter2) || (h != h2))
256                 printf("Result = F\n");
257             else
258                 printf("Result = P\n");
259             BN_free(p);
260             BN_free(q);
261             BN_free(g);
262             p = NULL;
263             q = NULL;
264             g = NULL;
265             FIPS_dsa_free(dsa);
266             dsa = NULL;
267             }
268         }
269     }
270
271 /* Keypair verification routine. NB: this isn't part of the standard FIPS140-2
272  * algorithm tests. It is an additional test to perform sanity checks on the
273  * output of the KeyPair test.
274  */
275
276 static int dss_paramcheck(int nmod, BIGNUM *p, BIGNUM *q, BIGNUM *g,
277                                                         BN_CTX *ctx)
278     {
279     BIGNUM *rem = NULL;
280     if (BN_num_bits(p) != nmod)
281         return 0;
282     if (BN_num_bits(q) != 160)
283         return 0;
284     if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1)
285         return 0;
286     if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1)
287         return 0;
288     rem = BN_new();
289     if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem)
290         || (BN_cmp(g, BN_value_one()) <= 0)
291         || !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem))
292         {
293         BN_free(rem);
294         return 0;
295         }
296     /* Todo: check g */
297     BN_free(rem);
298     return 1;
299     }
300
301 static void keyver()
302     {
303     char buf[1024];
304     char lbuf[1024];
305     char *keyword, *value;
306     BIGNUM *p = NULL, *q = NULL, *g = NULL, *X = NULL, *Y = NULL;
307     BIGNUM *Y2;
308     BN_CTX *ctx = NULL;
309     int nmod=0, paramcheck = 0;
310
311     ctx = BN_CTX_new();
312     Y2 = BN_new();
313
314     while(fgets(buf,sizeof buf,stdin) != NULL)
315         {
316         if (!parse_line(&keyword, &value, lbuf, buf))
317                 {
318                 fputs(buf,stdout);
319                 continue;
320                 }
321         if(!strcmp(keyword,"[mod"))
322             {
323             if (p)
324                 BN_free(p);
325             p = NULL;
326             if (q)
327                 BN_free(q);
328             q = NULL;
329             if (g)
330                 BN_free(g);
331             g = NULL;
332             paramcheck = 0;
333             nmod=atoi(value);
334             }
335         else if(!strcmp(keyword,"P"))
336             p=hex2bn(value);
337         else if(!strcmp(keyword,"Q"))
338             q=hex2bn(value);
339         else if(!strcmp(keyword,"G"))
340             g=hex2bn(value);
341         else if(!strcmp(keyword,"X"))
342             X=hex2bn(value);
343         else if(!strcmp(keyword,"Y"))
344             {
345             Y=hex2bn(value);
346             if (!p || !q || !g || !X || !Y)
347                 {
348                 fprintf(stderr, "Parse Error\n");
349                 exit (1);
350                 }
351             pbn("P",p);
352             pbn("Q",q);
353             pbn("G",g);
354             pbn("X",X);
355             pbn("Y",Y);
356             if (!paramcheck)
357                 {
358                 if (dss_paramcheck(nmod, p, q, g, ctx))
359                         paramcheck = 1;
360                 else
361                         paramcheck = -1;
362                 }
363             if (paramcheck != 1)
364                 printf("Result = F\n");
365             else
366                 {
367                 if (!BN_mod_exp(Y2, g, X, p, ctx) || BN_cmp(Y2, Y))
368                         printf("Result = F\n");
369                 else
370                         printf("Result = P\n");
371                 }
372             BN_free(X);
373             BN_free(Y);
374             X = NULL;
375             Y = NULL;
376             }
377         }
378         if (p)
379             BN_free(p);
380         if (q)
381             BN_free(q);
382         if (g)
383             BN_free(g);
384         if (Y2)
385             BN_free(Y2);
386     }
387
388 static void keypair()
389     {
390     char buf[1024];
391     char lbuf[1024];
392     char *keyword, *value;
393     int nmod=0;
394
395     while(fgets(buf,sizeof buf,stdin) != NULL)
396         {
397         if (!parse_line(&keyword, &value, lbuf, buf))
398                 {
399                 fputs(buf,stdout);
400                 continue;
401                 }
402         if(!strcmp(keyword,"[mod"))
403             nmod=atoi(value);
404         else if(!strcmp(keyword,"N"))
405             {
406             DSA *dsa;
407             int n=atoi(value);
408
409             printf("[mod = %d]\n\n",nmod);
410             dsa = FIPS_dsa_new();
411             if (!DSA_generate_parameters_ex(dsa, nmod,NULL,0,NULL,NULL,NULL))
412                 exit(1);
413             pbn("P",dsa->p);
414             pbn("Q",dsa->q);
415             pbn("G",dsa->g);
416             putc('\n',stdout);
417
418             while(n--)
419                 {
420                 if (!DSA_generate_key(dsa))
421                         exit(1);
422
423                 pbn("X",dsa->priv_key);
424                 pbn("Y",dsa->pub_key);
425                 putc('\n',stdout);
426                 }
427             }
428         }
429     }
430
431 static void siggen()
432     {
433     char buf[1024];
434     char lbuf[1024];
435     char *keyword, *value;
436     int nmod=0;
437     DSA *dsa=NULL;
438
439     while(fgets(buf,sizeof buf,stdin) != NULL)
440         {
441         if (!parse_line(&keyword, &value, lbuf, buf))
442                 {
443                 fputs(buf,stdout);
444                 continue;
445                 }
446         if(!strcmp(keyword,"[mod"))
447             {
448             nmod=atoi(value);
449             printf("[mod = %d]\n\n",nmod);
450             if (dsa)
451                 FIPS_dsa_free(dsa);
452             dsa = FIPS_dsa_new();
453             if (!DSA_generate_parameters_ex(dsa, nmod,NULL,0,NULL,NULL,NULL))
454                 exit(1);
455             pbn("P",dsa->p);
456             pbn("Q",dsa->q);
457             pbn("G",dsa->g);
458             putc('\n',stdout);
459             }
460         else if(!strcmp(keyword,"Msg"))
461             {
462             unsigned char msg[1024];
463             int n;
464             EVP_MD_CTX mctx;
465             DSA_SIG *sig;
466             EVP_MD_CTX_init(&mctx);
467
468             n=hex2bin(value,msg);
469             pv("Msg",msg,n);
470
471             if (!DSA_generate_key(dsa))
472                 exit(1);
473             pbn("Y",dsa->pub_key);
474
475             EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL);
476             EVP_DigestUpdate(&mctx, msg, n);
477             sig = FIPS_dsa_sign_ctx(dsa, &mctx);
478
479             pbn("R",sig->r);
480             pbn("S",sig->s);
481             putc('\n',stdout);
482             DSA_SIG_free(sig);
483             EVP_MD_CTX_cleanup(&mctx);
484             }
485         }
486         if (dsa)
487                 FIPS_dsa_free(dsa);
488     }
489
490 static void sigver()
491     {
492     DSA *dsa=NULL;
493     char buf[1024];
494     char lbuf[1024];
495     unsigned char msg[1024];
496     char *keyword, *value;
497     int nmod=0, n=0;
498     DSA_SIG sg, *sig = &sg;
499
500     sig->r = NULL;
501     sig->s = NULL;
502
503     while(fgets(buf,sizeof buf,stdin) != NULL)
504         {
505         if (!parse_line(&keyword, &value, lbuf, buf))
506                 {
507                 fputs(buf,stdout);
508                 continue;
509                 }
510         if(!strcmp(keyword,"[mod"))
511             {
512             nmod=atoi(value);
513             if(dsa)
514                 FIPS_dsa_free(dsa);
515             dsa=FIPS_dsa_new();
516             }
517         else if(!strcmp(keyword,"P"))
518             dsa->p=hex2bn(value);
519         else if(!strcmp(keyword,"Q"))
520             dsa->q=hex2bn(value);
521         else if(!strcmp(keyword,"G"))
522             {
523             dsa->g=hex2bn(value);
524
525             printf("[mod = %d]\n\n",nmod);
526             pbn("P",dsa->p);
527             pbn("Q",dsa->q);
528             pbn("G",dsa->g);
529             putc('\n',stdout);
530             }
531         else if(!strcmp(keyword,"Msg"))
532             {
533             n=hex2bin(value,msg);
534             pv("Msg",msg,n);
535             }
536         else if(!strcmp(keyword,"Y"))
537             dsa->pub_key=hex2bn(value);
538         else if(!strcmp(keyword,"R"))
539             sig->r=hex2bn(value);
540         else if(!strcmp(keyword,"S"))
541             {
542             EVP_MD_CTX mctx;
543             int r;
544             EVP_MD_CTX_init(&mctx);
545             sig->s=hex2bn(value);
546         
547             pbn("Y",dsa->pub_key);
548             pbn("R",sig->r);
549             pbn("S",sig->s);
550             EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL);
551             EVP_DigestUpdate(&mctx, msg, n);
552             no_err = 1;
553             r = FIPS_dsa_verify_ctx(dsa, &mctx, sig);
554             no_err = 0;
555             EVP_MD_CTX_cleanup(&mctx);
556         
557             printf("Result = %c\n", r == 1 ? 'P' : 'F');
558             putc('\n',stdout);
559             }
560         }
561     }
562
563 int main(int argc,char **argv)
564     {
565     if(argc != 2)
566         {
567         fprintf(stderr,"%s [prime|pqg|pqgver|keypair|siggen|sigver]\n",argv[0]);
568         exit(1);
569         }
570     fips_set_error_print();
571     if(!FIPS_mode_set(1))
572         exit(1);
573     if(!strcmp(argv[1],"prime"))
574         primes();
575     else if(!strcmp(argv[1],"pqg"))
576         pqg();
577     else if(!strcmp(argv[1],"pqgver"))
578         pqgver();
579     else if(!strcmp(argv[1],"keypair"))
580         keypair();
581     else if(!strcmp(argv[1],"keyver"))
582         keyver();
583     else if(!strcmp(argv[1],"siggen"))
584         siggen();
585     else if(!strcmp(argv[1],"sigver"))
586         sigver();
587     else
588         {
589         fprintf(stderr,"Don't know how to %s.\n",argv[1]);
590         exit(1);
591         }
592
593     return 0;
594     }
595
596 #endif