#include #ifndef OPENSSL_FIPS # include int main(int argc, char **argv) { printf("No FIPS DSA support\n"); return (0); } #else # include # include # include # include # include # include # include # include "fips_utl.h" static void pbn(const char *name, BIGNUM *bn) { int len, i; unsigned char *tmp; len = BN_num_bytes(bn); tmp = OPENSSL_malloc(len); if (!tmp) { fprintf(stderr, "Memory allocation error\n"); return; } BN_bn2bin(bn, tmp); printf("%s = ", name); for (i = 0; i < len; i++) printf("%02X", tmp[i]); fputs("\n", stdout); OPENSSL_free(tmp); return; } static void primes() { char buf[10240]; char lbuf[10240]; char *keyword, *value; while (fgets(buf, sizeof buf, stdin) != NULL) { fputs(buf, stdout); if (!parse_line(&keyword, &value, lbuf, buf)) continue; if (!strcmp(keyword, "Prime")) { BIGNUM *pp; pp = BN_new(); do_hex2bn(&pp, value); printf("result= %c\n", BN_is_prime_ex(pp, 20, NULL, NULL) ? 'P' : 'F'); } } } static void pqg() { char buf[1024]; char lbuf[1024]; char *keyword, *value; int nmod = 0; while (fgets(buf, sizeof buf, stdin) != NULL) { if (!parse_line(&keyword, &value, lbuf, buf)) { fputs(buf, stdout); continue; } if (!strcmp(keyword, "[mod")) nmod = atoi(value); else if (!strcmp(keyword, "N")) { int n = atoi(value); printf("[mod = %d]\n\n", nmod); while (n--) { unsigned char seed[20]; DSA *dsa; int counter; unsigned long h; dsa = FIPS_dsa_new(); if (!DSA_generate_parameters_ex (dsa, nmod, seed, 0, &counter, &h, NULL)) { do_print_errors(); exit(1); } pbn("P", dsa->p); pbn("Q", dsa->q); pbn("G", dsa->g); pv("Seed", seed, 20); printf("c = %d\n", counter); printf("H = %lx\n", h); putc('\n', stdout); } } else fputs(buf, stdout); } } static void pqgver() { char buf[1024]; char lbuf[1024]; char *keyword, *value; BIGNUM *p = NULL, *q = NULL, *g = NULL; int counter, counter2; unsigned long h, h2; DSA *dsa = NULL; int nmod = 0; unsigned char seed[1024]; while (fgets(buf, sizeof buf, stdin) != NULL) { if (!parse_line(&keyword, &value, lbuf, buf)) { fputs(buf, stdout); continue; } fputs(buf, stdout); if (!strcmp(keyword, "[mod")) nmod = atoi(value); else if (!strcmp(keyword, "P")) p = hex2bn(value); else if (!strcmp(keyword, "Q")) q = hex2bn(value); else if (!strcmp(keyword, "G")) g = hex2bn(value); else if (!strcmp(keyword, "Seed")) { int slen = hex2bin(value, seed); if (slen != 20) { fprintf(stderr, "Seed parse length error\n"); exit(1); } } else if (!strcmp(keyword, "c")) counter = atoi(buf + 4); else if (!strcmp(keyword, "H")) { h = atoi(value); if (!p || !q || !g) { fprintf(stderr, "Parse Error\n"); exit(1); } dsa = FIPS_dsa_new(); if (!DSA_generate_parameters_ex (dsa, nmod, seed, 20, &counter2, &h2, NULL)) { do_print_errors(); exit(1); } if (BN_cmp(dsa->p, p) || BN_cmp(dsa->q, q) || BN_cmp(dsa->g, g) || (counter != counter2) || (h != h2)) printf("Result = F\n"); else printf("Result = P\n"); BN_free(p); BN_free(q); BN_free(g); p = NULL; q = NULL; g = NULL; FIPS_dsa_free(dsa); dsa = NULL; } } } /* * Keypair verification routine. NB: this isn't part of the standard * FIPS140-2 algorithm tests. It is an additional test to perform sanity * checks on the output of the KeyPair test. */ static int dss_paramcheck(int nmod, BIGNUM *p, BIGNUM *q, BIGNUM *g, BN_CTX *ctx) { BIGNUM *rem = NULL; if (BN_num_bits(p) != nmod) return 0; if (BN_num_bits(q) != 160) return 0; if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1) return 0; if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1) return 0; rem = BN_new(); if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem) || (BN_cmp(g, BN_value_one()) <= 0) || !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem)) { BN_free(rem); return 0; } /* Todo: check g */ BN_free(rem); return 1; } static void keyver() { char buf[1024]; char lbuf[1024]; char *keyword, *value; BIGNUM *p = NULL, *q = NULL, *g = NULL, *X = NULL, *Y = NULL; BIGNUM *Y2; BN_CTX *ctx = NULL; int nmod = 0, paramcheck = 0; ctx = BN_CTX_new(); Y2 = BN_new(); while (fgets(buf, sizeof buf, stdin) != NULL) { if (!parse_line(&keyword, &value, lbuf, buf)) { fputs(buf, stdout); continue; } if (!strcmp(keyword, "[mod")) { if (p) BN_free(p); p = NULL; if (q) BN_free(q); q = NULL; if (g) BN_free(g); g = NULL; paramcheck = 0; nmod = atoi(value); } else if (!strcmp(keyword, "P")) p = hex2bn(value); else if (!strcmp(keyword, "Q")) q = hex2bn(value); else if (!strcmp(keyword, "G")) g = hex2bn(value); else if (!strcmp(keyword, "X")) X = hex2bn(value); else if (!strcmp(keyword, "Y")) { Y = hex2bn(value); if (!p || !q || !g || !X || !Y) { fprintf(stderr, "Parse Error\n"); exit(1); } pbn("P", p); pbn("Q", q); pbn("G", g); pbn("X", X); pbn("Y", Y); if (!paramcheck) { if (dss_paramcheck(nmod, p, q, g, ctx)) paramcheck = 1; else paramcheck = -1; } if (paramcheck != 1) printf("Result = F\n"); else { if (!BN_mod_exp(Y2, g, X, p, ctx) || BN_cmp(Y2, Y)) printf("Result = F\n"); else printf("Result = P\n"); } BN_free(X); BN_free(Y); X = NULL; Y = NULL; } } if (p) BN_free(p); if (q) BN_free(q); if (g) BN_free(g); if (Y2) BN_free(Y2); } static void keypair() { char buf[1024]; char lbuf[1024]; char *keyword, *value; int nmod = 0; while (fgets(buf, sizeof buf, stdin) != NULL) { if (!parse_line(&keyword, &value, lbuf, buf)) { fputs(buf, stdout); continue; } if (!strcmp(keyword, "[mod")) nmod = atoi(value); else if (!strcmp(keyword, "N")) { DSA *dsa; int n = atoi(value); printf("[mod = %d]\n\n", nmod); dsa = FIPS_dsa_new(); if (!DSA_generate_parameters_ex (dsa, nmod, NULL, 0, NULL, NULL, NULL)) { do_print_errors(); exit(1); } pbn("P", dsa->p); pbn("Q", dsa->q); pbn("G", dsa->g); putc('\n', stdout); while (n--) { if (!DSA_generate_key(dsa)) { do_print_errors(); exit(1); } pbn("X", dsa->priv_key); pbn("Y", dsa->pub_key); putc('\n', stdout); } } } } static void siggen() { char buf[1024]; char lbuf[1024]; char *keyword, *value; int nmod = 0; DSA *dsa = NULL; while (fgets(buf, sizeof buf, stdin) != NULL) { if (!parse_line(&keyword, &value, lbuf, buf)) { fputs(buf, stdout); continue; } if (!strcmp(keyword, "[mod")) { nmod = atoi(value); printf("[mod = %d]\n\n", nmod); if (dsa) FIPS_dsa_free(dsa); dsa = FIPS_dsa_new(); if (!DSA_generate_parameters_ex (dsa, nmod, NULL, 0, NULL, NULL, NULL)) { do_print_errors(); exit(1); } pbn("P", dsa->p); pbn("Q", dsa->q); pbn("G", dsa->g); putc('\n', stdout); } else if (!strcmp(keyword, "Msg")) { unsigned char msg[1024]; unsigned char sbuf[60]; unsigned int slen; int n; EVP_PKEY pk; EVP_MD_CTX mctx; DSA_SIG *sig; EVP_MD_CTX_init(&mctx); n = hex2bin(value, msg); pv("Msg", msg, n); if (!DSA_generate_key(dsa)) { do_print_errors(); exit(1); } pk.type = EVP_PKEY_DSA; pk.pkey.dsa = dsa; pbn("Y", dsa->pub_key); EVP_SignInit_ex(&mctx, EVP_dss1(), NULL); EVP_SignUpdate(&mctx, msg, n); EVP_SignFinal(&mctx, sbuf, &slen, &pk); sig = DSA_SIG_new(); FIPS_dsa_sig_decode(sig, sbuf, slen); pbn("R", sig->r); pbn("S", sig->s); putc('\n', stdout); DSA_SIG_free(sig); EVP_MD_CTX_cleanup(&mctx); } } if (dsa) FIPS_dsa_free(dsa); } static void sigver() { DSA *dsa = NULL; char buf[1024]; char lbuf[1024]; unsigned char msg[1024]; char *keyword, *value; int nmod = 0, n = 0; DSA_SIG sg, *sig = &sg; sig->r = NULL; sig->s = NULL; while (fgets(buf, sizeof buf, stdin) != NULL) { if (!parse_line(&keyword, &value, lbuf, buf)) { fputs(buf, stdout); continue; } if (!strcmp(keyword, "[mod")) { nmod = atoi(value); if (dsa) FIPS_dsa_free(dsa); dsa = FIPS_dsa_new(); } else if (!strcmp(keyword, "P")) dsa->p = hex2bn(value); else if (!strcmp(keyword, "Q")) dsa->q = hex2bn(value); else if (!strcmp(keyword, "G")) { dsa->g = hex2bn(value); printf("[mod = %d]\n\n", nmod); pbn("P", dsa->p); pbn("Q", dsa->q); pbn("G", dsa->g); putc('\n', stdout); } else if (!strcmp(keyword, "Msg")) { n = hex2bin(value, msg); pv("Msg", msg, n); } else if (!strcmp(keyword, "Y")) dsa->pub_key = hex2bn(value); else if (!strcmp(keyword, "R")) sig->r = hex2bn(value); else if (!strcmp(keyword, "S")) { EVP_MD_CTX mctx; EVP_PKEY pk; unsigned char sigbuf[60]; unsigned int slen; int r; EVP_MD_CTX_init(&mctx); pk.type = EVP_PKEY_DSA; pk.pkey.dsa = dsa; sig->s = hex2bn(value); pbn("Y", dsa->pub_key); pbn("R", sig->r); pbn("S", sig->s); slen = FIPS_dsa_sig_encode(sigbuf, sig); EVP_VerifyInit_ex(&mctx, EVP_dss1(), NULL); EVP_VerifyUpdate(&mctx, msg, n); r = EVP_VerifyFinal(&mctx, sigbuf, slen, &pk); EVP_MD_CTX_cleanup(&mctx); printf("Result = %c\n", r == 1 ? 'P' : 'F'); putc('\n', stdout); } } } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "%s [prime|pqg|pqgver|keypair|siggen|sigver]\n", argv[0]); exit(1); } if (!FIPS_mode_set(1)) { do_print_errors(); exit(1); } if (!strcmp(argv[1], "prime")) primes(); else if (!strcmp(argv[1], "pqg")) pqg(); else if (!strcmp(argv[1], "pqgver")) pqgver(); else if (!strcmp(argv[1], "keypair")) keypair(); else if (!strcmp(argv[1], "keyver")) keyver(); else if (!strcmp(argv[1], "siggen")) siggen(); else if (!strcmp(argv[1], "sigver")) sigver(); else { fprintf(stderr, "Don't know how to %s.\n", argv[1]); exit(1); } return 0; } #endif