X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fdsa%2Fdsa_gen.c;h=9e3e57a828599e24c4d088319672c9575292bb41;hp=4d6bbc0d05928313e16f69ed879ee163003f509e;hb=2514fa79acba998c2a8d4e5a8288a5b3ae990377;hpb=cac4fb58e02d8cf799d75212179f56c69e652ec7 diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 4d6bbc0d05..9e3e57a828 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -141,7 +141,7 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, goto err; } - if (FIPS_mode() && !(ret->flags & DSA_FLAG_NON_FIPS_ALLOW) + if (FIPS_module_mode() && !(ret->flags & DSA_FLAG_NON_FIPS_ALLOW) && (bits < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) { DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_KEY_SIZE_TOO_SMALL); @@ -372,6 +372,8 @@ err: return ok; } +#ifdef OPENSSL_FIPS + /* Security strength of parameter values for (L,N): see FIPS186-3 4.2 * and SP800-131A */ @@ -403,14 +405,14 @@ static int dsa2_valid_parameters(size_t L, size_t N) if (L == 2048 && N == 256) return 112; if (L == 3072 && N == 256) - return 112; + return 128; return 0; } int fips_check_dsa_prng(DSA *dsa, size_t L, size_t N) { int strength; - if (!FIPS_mode()) + if (!FIPS_module_mode()) return 1; if (dsa->flags & (DSA_FLAG_NON_FIPS_ALLOW|DSA_FLAG_FIPS_CHECKED)) @@ -442,6 +444,7 @@ int fips_check_dsa_prng(DSA *dsa, size_t L, size_t N) return 0; } +#endif /* OPENSSL_FIPS */ /* This is a parameter generation algorithm for the DSA2 algorithm as * described in FIPS 186-3. @@ -449,11 +452,11 @@ int fips_check_dsa_prng(DSA *dsa, size_t L, size_t N) int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len, - unsigned char *seed_out, + int idx, unsigned char *seed_out, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb) { int ok=-1; - unsigned char *seed = NULL; + unsigned char *seed = NULL, *seed_tmp = NULL; unsigned char md[EVP_MAX_MD_SIZE]; int mdsize; BIGNUM *r0,*W,*X,*c,*test; @@ -463,8 +466,11 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, int counter=0; int r=0; BN_CTX *ctx=NULL; + EVP_MD_CTX mctx; unsigned int h=2; + EVP_MD_CTX_init(&mctx); + #ifdef OPENSSL_FIPS if(FIPS_selftest_failed()) { @@ -488,17 +494,26 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, } mdsize = M_EVP_MD_size(evpmd); + /* If unverificable g generation only don't need seed */ + if (!ret->p || !ret->q || idx >= 0) + { + if (seed_len == 0) + seed_len = mdsize; + + seed = OPENSSL_malloc(seed_len); - if (seed_len == 0) - seed_len = mdsize; + if (seed_out) + seed_tmp = seed_out; + else + seed_tmp = OPENSSL_malloc(seed_len); - seed = OPENSSL_malloc(seed_len); + if (!seed || !seed_tmp) + goto err; - if (!seed) - goto err; + if (seed_in) + memcpy(seed, seed_in, seed_len); - if (seed_in) - memcpy(seed, seed_in, seed_len); + } if ((ctx=BN_CTX_new()) == NULL) goto err; @@ -510,12 +525,25 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, r0 = BN_CTX_get(ctx); g = BN_CTX_get(ctx); W = BN_CTX_get(ctx); - q = BN_CTX_get(ctx); X = BN_CTX_get(ctx); c = BN_CTX_get(ctx); - p = BN_CTX_get(ctx); test = BN_CTX_get(ctx); + /* if p, q already supplied generate g only */ + if (ret->p && ret->q) + { + p = ret->p; + q = ret->q; + if (idx >= 0) + memcpy(seed_tmp, seed, seed_len); + goto g_only; + } + else + { + p = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + } + if (!BN_lshift(test,BN_value_one(),L-1)) goto err; for (;;) @@ -638,28 +666,64 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, /* "offset = offset + n + 1" */ /* step 14 */ - if (counter >= 4096) break; + if (counter >= (int)(4 * L)) break; + } + if (seed_in) + { + ok = 0; + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS); + goto err; } } end: if(!BN_GENCB_call(cb, 2, 1)) goto err; + g_only: + /* We now need to generate g */ /* Set r0=(p-1)/q */ if (!BN_sub(test,p,BN_value_one())) goto err; if (!BN_div(r0,NULL,test,q,ctx)) goto err; - if (!BN_set_word(test,h)) goto err; + if (idx < 0) + { + if (!BN_set_word(test,h)) + goto err; + } + else + h = 1; if (!BN_MONT_CTX_set(mont,p,ctx)) goto err; for (;;) { + __fips_constseg + static const unsigned char ggen[4] = {0x67,0x67,0x65,0x6e}; + if (idx >= 0) + { + md[0] = idx & 0xff; + md[1] = (h >> 8) & 0xff; + md[2] = h & 0xff; + if (!EVP_DigestInit_ex(&mctx, evpmd, NULL)) + goto err; + if (!EVP_DigestUpdate(&mctx, seed_tmp, seed_len)) + goto err; + if (!EVP_DigestUpdate(&mctx, ggen, sizeof(ggen))) + goto err; + if (!EVP_DigestUpdate(&mctx, md, 3)) + goto err; + if (!EVP_DigestFinal_ex(&mctx, md, NULL)) + goto err; + if (!BN_bin2bn(md, mdsize, test)) + goto err; + } /* g=test^r0%p */ if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err; if (!BN_is_one(g)) break; - if (!BN_add(test,test,BN_value_one())) goto err; + if (idx < 0 && !BN_add(test,test,BN_value_one())) goto err; h++; + if ( idx >= 0 && h > 0xffff) + goto err; } if(!BN_GENCB_call(cb, 3, 1)) @@ -669,11 +733,17 @@ end: err: if (ok == 1) { - if(ret->p) BN_free(ret->p); - if(ret->q) BN_free(ret->q); + if (p != ret->p) + { + if(ret->p) BN_free(ret->p); + ret->p=BN_dup(p); + } + if (q != ret->q) + { + if(ret->q) BN_free(ret->q); + ret->q=BN_dup(q); + } if(ret->g) BN_free(ret->g); - ret->p=BN_dup(p); - ret->q=BN_dup(q); ret->g=BN_dup(g); if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { @@ -685,12 +755,53 @@ err: } if (seed) OPENSSL_free(seed); + if (seed_out != seed_tmp) + OPENSSL_free(seed_tmp); if(ctx) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (mont != NULL) BN_MONT_CTX_free(mont); + EVP_MD_CTX_cleanup(&mctx); return ok; } + +int dsa_paramgen_check_g(DSA *dsa) + { + BN_CTX *ctx; + BIGNUM *tmp; + BN_MONT_CTX *mont = NULL; + int rv = -1; + ctx = BN_CTX_new(); + if (!ctx) + return -1; + BN_CTX_start(ctx); + if (BN_cmp(dsa->g, BN_value_one()) <= 0) + return 0; + if (BN_cmp(dsa->g, dsa->p) >= 0) + return 0; + tmp = BN_CTX_get(ctx); + if (!tmp) + goto err; + if ((mont=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(mont,dsa->p,ctx)) + goto err; + /* Work out g^q mod p */ + if (!BN_mod_exp_mont(tmp,dsa->g,dsa->q, dsa->p, ctx, mont)) + goto err; + if (!BN_cmp(tmp, BN_value_one())) + rv = 1; + else + rv = 0; + err: + BN_CTX_end(ctx); + if (mont) + BN_MONT_CTX_free(mont); + BN_CTX_free(ctx); + return rv; + + } + #endif