fips_dssvs.c revision 296465
1#include <openssl/opensslconf.h>
2
3#ifndef OPENSSL_FIPS
4# include <stdio.h>
5
6int main(int argc, char **argv)
7{
8    printf("No FIPS DSA support\n");
9    return (0);
10}
11#else
12
13# include <openssl/bn.h>
14# include <openssl/dsa.h>
15# include <openssl/fips.h>
16# include <openssl/err.h>
17# include <openssl/evp.h>
18# include <string.h>
19# include <ctype.h>
20
21# include "fips_utl.h"
22
23static void pbn(const char *name, BIGNUM *bn)
24{
25    int len, i;
26    unsigned char *tmp;
27    len = BN_num_bytes(bn);
28    tmp = OPENSSL_malloc(len);
29    if (!tmp) {
30        fprintf(stderr, "Memory allocation error\n");
31        return;
32    }
33    BN_bn2bin(bn, tmp);
34    printf("%s = ", name);
35    for (i = 0; i < len; i++)
36        printf("%02X", tmp[i]);
37    fputs("\n", stdout);
38    OPENSSL_free(tmp);
39    return;
40}
41
42static void primes()
43{
44    char buf[10240];
45    char lbuf[10240];
46    char *keyword, *value;
47
48    while (fgets(buf, sizeof buf, stdin) != NULL) {
49        fputs(buf, stdout);
50        if (!parse_line(&keyword, &value, lbuf, buf))
51            continue;
52        if (!strcmp(keyword, "Prime")) {
53            BIGNUM *pp;
54
55            pp = BN_new();
56            do_hex2bn(&pp, value);
57            printf("result= %c\n",
58                   BN_is_prime_ex(pp, 20, NULL, NULL) ? 'P' : 'F');
59        }
60    }
61}
62
63static void pqg()
64{
65    char buf[1024];
66    char lbuf[1024];
67    char *keyword, *value;
68    int nmod = 0;
69
70    while (fgets(buf, sizeof buf, stdin) != NULL) {
71        if (!parse_line(&keyword, &value, lbuf, buf)) {
72            fputs(buf, stdout);
73            continue;
74        }
75        if (!strcmp(keyword, "[mod"))
76            nmod = atoi(value);
77        else if (!strcmp(keyword, "N")) {
78            int n = atoi(value);
79
80            printf("[mod = %d]\n\n", nmod);
81
82            while (n--) {
83                unsigned char seed[20];
84                DSA *dsa;
85                int counter;
86                unsigned long h;
87                dsa = FIPS_dsa_new();
88
89                if (!DSA_generate_parameters_ex
90                    (dsa, nmod, seed, 0, &counter, &h, NULL)) {
91                    do_print_errors();
92                    exit(1);
93                }
94                pbn("P", dsa->p);
95                pbn("Q", dsa->q);
96                pbn("G", dsa->g);
97                pv("Seed", seed, 20);
98                printf("c = %d\n", counter);
99                printf("H = %lx\n", h);
100                putc('\n', stdout);
101            }
102        } else
103            fputs(buf, stdout);
104    }
105}
106
107static void pqgver()
108{
109    char buf[1024];
110    char lbuf[1024];
111    char *keyword, *value;
112    BIGNUM *p = NULL, *q = NULL, *g = NULL;
113    int counter, counter2;
114    unsigned long h, h2;
115    DSA *dsa = NULL;
116    int nmod = 0;
117    unsigned char seed[1024];
118
119    while (fgets(buf, sizeof buf, stdin) != NULL) {
120        if (!parse_line(&keyword, &value, lbuf, buf)) {
121            fputs(buf, stdout);
122            continue;
123        }
124        fputs(buf, stdout);
125        if (!strcmp(keyword, "[mod"))
126            nmod = atoi(value);
127        else if (!strcmp(keyword, "P"))
128            p = hex2bn(value);
129        else if (!strcmp(keyword, "Q"))
130            q = hex2bn(value);
131        else if (!strcmp(keyword, "G"))
132            g = hex2bn(value);
133        else if (!strcmp(keyword, "Seed")) {
134            int slen = hex2bin(value, seed);
135            if (slen != 20) {
136                fprintf(stderr, "Seed parse length error\n");
137                exit(1);
138            }
139        } else if (!strcmp(keyword, "c"))
140            counter = atoi(buf + 4);
141        else if (!strcmp(keyword, "H")) {
142            h = atoi(value);
143            if (!p || !q || !g) {
144                fprintf(stderr, "Parse Error\n");
145                exit(1);
146            }
147            dsa = FIPS_dsa_new();
148            if (!DSA_generate_parameters_ex
149                (dsa, nmod, seed, 20, &counter2, &h2, NULL)) {
150                do_print_errors();
151                exit(1);
152            }
153            if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || BN_cmp(dsa->g, g)
154                || (counter != counter2) || (h != h2))
155                printf("Result = F\n");
156            else
157                printf("Result = P\n");
158            BN_free(p);
159            BN_free(q);
160            BN_free(g);
161            p = NULL;
162            q = NULL;
163            g = NULL;
164            FIPS_dsa_free(dsa);
165            dsa = NULL;
166        }
167    }
168}
169
170/*
171 * Keypair verification routine. NB: this isn't part of the standard
172 * FIPS140-2 algorithm tests. It is an additional test to perform sanity
173 * checks on the output of the KeyPair test.
174 */
175
176static int dss_paramcheck(int nmod, BIGNUM *p, BIGNUM *q, BIGNUM *g,
177                          BN_CTX *ctx)
178{
179    BIGNUM *rem = NULL;
180    if (BN_num_bits(p) != nmod)
181        return 0;
182    if (BN_num_bits(q) != 160)
183        return 0;
184    if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1)
185        return 0;
186    if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1)
187        return 0;
188    rem = BN_new();
189    if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem)
190        || (BN_cmp(g, BN_value_one()) <= 0)
191        || !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem)) {
192        BN_free(rem);
193        return 0;
194    }
195    /* Todo: check g */
196    BN_free(rem);
197    return 1;
198}
199
200static void keyver()
201{
202    char buf[1024];
203    char lbuf[1024];
204    char *keyword, *value;
205    BIGNUM *p = NULL, *q = NULL, *g = NULL, *X = NULL, *Y = NULL;
206    BIGNUM *Y2;
207    BN_CTX *ctx = NULL;
208    int nmod = 0, paramcheck = 0;
209
210    ctx = BN_CTX_new();
211    Y2 = BN_new();
212
213    while (fgets(buf, sizeof buf, stdin) != NULL) {
214        if (!parse_line(&keyword, &value, lbuf, buf)) {
215            fputs(buf, stdout);
216            continue;
217        }
218        if (!strcmp(keyword, "[mod")) {
219            if (p)
220                BN_free(p);
221            p = NULL;
222            if (q)
223                BN_free(q);
224            q = NULL;
225            if (g)
226                BN_free(g);
227            g = NULL;
228            paramcheck = 0;
229            nmod = atoi(value);
230        } else if (!strcmp(keyword, "P"))
231            p = hex2bn(value);
232        else if (!strcmp(keyword, "Q"))
233            q = hex2bn(value);
234        else if (!strcmp(keyword, "G"))
235            g = hex2bn(value);
236        else if (!strcmp(keyword, "X"))
237            X = hex2bn(value);
238        else if (!strcmp(keyword, "Y")) {
239            Y = hex2bn(value);
240            if (!p || !q || !g || !X || !Y) {
241                fprintf(stderr, "Parse Error\n");
242                exit(1);
243            }
244            pbn("P", p);
245            pbn("Q", q);
246            pbn("G", g);
247            pbn("X", X);
248            pbn("Y", Y);
249            if (!paramcheck) {
250                if (dss_paramcheck(nmod, p, q, g, ctx))
251                    paramcheck = 1;
252                else
253                    paramcheck = -1;
254            }
255            if (paramcheck != 1)
256                printf("Result = F\n");
257            else {
258                if (!BN_mod_exp(Y2, g, X, p, ctx) || BN_cmp(Y2, Y))
259                    printf("Result = F\n");
260                else
261                    printf("Result = P\n");
262            }
263            BN_free(X);
264            BN_free(Y);
265            X = NULL;
266            Y = NULL;
267        }
268    }
269    if (p)
270        BN_free(p);
271    if (q)
272        BN_free(q);
273    if (g)
274        BN_free(g);
275    if (Y2)
276        BN_free(Y2);
277}
278
279static void keypair()
280{
281    char buf[1024];
282    char lbuf[1024];
283    char *keyword, *value;
284    int nmod = 0;
285
286    while (fgets(buf, sizeof buf, stdin) != NULL) {
287        if (!parse_line(&keyword, &value, lbuf, buf)) {
288            fputs(buf, stdout);
289            continue;
290        }
291        if (!strcmp(keyword, "[mod"))
292            nmod = atoi(value);
293        else if (!strcmp(keyword, "N")) {
294            DSA *dsa;
295            int n = atoi(value);
296
297            printf("[mod = %d]\n\n", nmod);
298            dsa = FIPS_dsa_new();
299            if (!DSA_generate_parameters_ex
300                (dsa, nmod, NULL, 0, NULL, NULL, NULL)) {
301                do_print_errors();
302                exit(1);
303            }
304            pbn("P", dsa->p);
305            pbn("Q", dsa->q);
306            pbn("G", dsa->g);
307            putc('\n', stdout);
308
309            while (n--) {
310                if (!DSA_generate_key(dsa)) {
311                    do_print_errors();
312                    exit(1);
313                }
314
315                pbn("X", dsa->priv_key);
316                pbn("Y", dsa->pub_key);
317                putc('\n', stdout);
318            }
319        }
320    }
321}
322
323static void siggen()
324{
325    char buf[1024];
326    char lbuf[1024];
327    char *keyword, *value;
328    int nmod = 0;
329    DSA *dsa = NULL;
330
331    while (fgets(buf, sizeof buf, stdin) != NULL) {
332        if (!parse_line(&keyword, &value, lbuf, buf)) {
333            fputs(buf, stdout);
334            continue;
335        }
336        if (!strcmp(keyword, "[mod")) {
337            nmod = atoi(value);
338            printf("[mod = %d]\n\n", nmod);
339            if (dsa)
340                FIPS_dsa_free(dsa);
341            dsa = FIPS_dsa_new();
342            if (!DSA_generate_parameters_ex
343                (dsa, nmod, NULL, 0, NULL, NULL, NULL)) {
344                do_print_errors();
345                exit(1);
346            }
347            pbn("P", dsa->p);
348            pbn("Q", dsa->q);
349            pbn("G", dsa->g);
350            putc('\n', stdout);
351        } else if (!strcmp(keyword, "Msg")) {
352            unsigned char msg[1024];
353            unsigned char sbuf[60];
354            unsigned int slen;
355            int n;
356            EVP_PKEY pk;
357            EVP_MD_CTX mctx;
358            DSA_SIG *sig;
359            EVP_MD_CTX_init(&mctx);
360
361            n = hex2bin(value, msg);
362            pv("Msg", msg, n);
363
364            if (!DSA_generate_key(dsa)) {
365                do_print_errors();
366                exit(1);
367            }
368            pk.type = EVP_PKEY_DSA;
369            pk.pkey.dsa = dsa;
370            pbn("Y", dsa->pub_key);
371
372            EVP_SignInit_ex(&mctx, EVP_dss1(), NULL);
373            EVP_SignUpdate(&mctx, msg, n);
374            EVP_SignFinal(&mctx, sbuf, &slen, &pk);
375
376            sig = DSA_SIG_new();
377            FIPS_dsa_sig_decode(sig, sbuf, slen);
378
379            pbn("R", sig->r);
380            pbn("S", sig->s);
381            putc('\n', stdout);
382            DSA_SIG_free(sig);
383            EVP_MD_CTX_cleanup(&mctx);
384        }
385    }
386    if (dsa)
387        FIPS_dsa_free(dsa);
388}
389
390static void sigver()
391{
392    DSA *dsa = NULL;
393    char buf[1024];
394    char lbuf[1024];
395    unsigned char msg[1024];
396    char *keyword, *value;
397    int nmod = 0, n = 0;
398    DSA_SIG sg, *sig = &sg;
399
400    sig->r = NULL;
401    sig->s = NULL;
402
403    while (fgets(buf, sizeof buf, stdin) != NULL) {
404        if (!parse_line(&keyword, &value, lbuf, buf)) {
405            fputs(buf, stdout);
406            continue;
407        }
408        if (!strcmp(keyword, "[mod")) {
409            nmod = atoi(value);
410            if (dsa)
411                FIPS_dsa_free(dsa);
412            dsa = FIPS_dsa_new();
413        } else if (!strcmp(keyword, "P"))
414            dsa->p = hex2bn(value);
415        else if (!strcmp(keyword, "Q"))
416            dsa->q = hex2bn(value);
417        else if (!strcmp(keyword, "G")) {
418            dsa->g = hex2bn(value);
419
420            printf("[mod = %d]\n\n", nmod);
421            pbn("P", dsa->p);
422            pbn("Q", dsa->q);
423            pbn("G", dsa->g);
424            putc('\n', stdout);
425        } else if (!strcmp(keyword, "Msg")) {
426            n = hex2bin(value, msg);
427            pv("Msg", msg, n);
428        } else if (!strcmp(keyword, "Y"))
429            dsa->pub_key = hex2bn(value);
430        else if (!strcmp(keyword, "R"))
431            sig->r = hex2bn(value);
432        else if (!strcmp(keyword, "S")) {
433            EVP_MD_CTX mctx;
434            EVP_PKEY pk;
435            unsigned char sigbuf[60];
436            unsigned int slen;
437            int r;
438            EVP_MD_CTX_init(&mctx);
439            pk.type = EVP_PKEY_DSA;
440            pk.pkey.dsa = dsa;
441            sig->s = hex2bn(value);
442
443            pbn("Y", dsa->pub_key);
444            pbn("R", sig->r);
445            pbn("S", sig->s);
446
447            slen = FIPS_dsa_sig_encode(sigbuf, sig);
448            EVP_VerifyInit_ex(&mctx, EVP_dss1(), NULL);
449            EVP_VerifyUpdate(&mctx, msg, n);
450            r = EVP_VerifyFinal(&mctx, sigbuf, slen, &pk);
451            EVP_MD_CTX_cleanup(&mctx);
452
453            printf("Result = %c\n", r == 1 ? 'P' : 'F');
454            putc('\n', stdout);
455        }
456    }
457}
458
459int main(int argc, char **argv)
460{
461    if (argc != 2) {
462        fprintf(stderr, "%s [prime|pqg|pqgver|keypair|siggen|sigver]\n",
463                argv[0]);
464        exit(1);
465    }
466    if (!FIPS_mode_set(1)) {
467        do_print_errors();
468        exit(1);
469    }
470    if (!strcmp(argv[1], "prime"))
471        primes();
472    else if (!strcmp(argv[1], "pqg"))
473        pqg();
474    else if (!strcmp(argv[1], "pqgver"))
475        pqgver();
476    else if (!strcmp(argv[1], "keypair"))
477        keypair();
478    else if (!strcmp(argv[1], "keyver"))
479        keyver();
480    else if (!strcmp(argv[1], "siggen"))
481        siggen();
482    else if (!strcmp(argv[1], "sigver"))
483        sigver();
484    else {
485        fprintf(stderr, "Don't know how to %s.\n", argv[1]);
486        exit(1);
487    }
488
489    return 0;
490}
491
492#endif
493