diff options
Diffstat (limited to 'crypto/dsa/dsa_gen.c')
-rw-r--r-- | crypto/dsa/dsa_gen.c | 646 |
1 files changed, 60 insertions, 586 deletions
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 02c2bd8083..aa6b84c091 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,13 +7,6 @@ * https://www.openssl.org/source/license.html */ -/* - * Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186, - * also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB - * 180-1) - */ -#define xxxHASH EVP_sha1() - #include <openssl/opensslconf.h> #include <stdio.h> #include "internal/cryptlib.h" @@ -21,598 +14,79 @@ #include <openssl/bn.h> #include <openssl/rand.h> #include <openssl/sha.h> +#include "crypto/dsa.h" #include "dsa_local.h" -int DSA_generate_parameters_ex(DSA *ret, int bits, - const unsigned char *seed_in, int seed_len, - int *counter_ret, unsigned long *h_ret, - BN_GENCB *cb) +int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type, + int pbits, int qbits, int gindex, + BN_GENCB *cb) { - if (ret->meth->dsa_paramgen) - return ret->meth->dsa_paramgen(ret, bits, seed_in, seed_len, - counter_ret, h_ret, cb); - else { - const EVP_MD *evpmd = bits >= 2048 ? EVP_sha256() : EVP_sha1(); - size_t qbits = EVP_MD_size(evpmd) * 8; + int ret = 0, res; - return dsa_builtin_paramgen(ret, bits, qbits, evpmd, - seed_in, seed_len, NULL, counter_ret, - h_ret, cb); + if (qbits <= 0) { + const EVP_MD *evpmd = pbits >= 2048 ? EVP_sha256() : EVP_sha1(); + + qbits = EVP_MD_size(evpmd) * 8; } + dsa->params.gindex = gindex; +#ifndef FIPS_MODE + if (type == DSA_PARAMGEN_TYPE_FIPS_186_2) + ret = ffc_params_FIPS186_2_generate(libctx, &dsa->params, + FFC_PARAM_TYPE_DSA, + pbits, qbits, NULL, &res, cb); + else +#endif + ret = ffc_params_FIPS186_4_generate(libctx, &dsa->params, + FFC_PARAM_TYPE_DSA, + pbits, qbits, NULL, &res, cb); + if (ret > 0) + dsa->dirty_cnt++; + return ret; } -int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, - const EVP_MD *evpmd, const unsigned char *seed_in, - size_t seed_len, unsigned char *seed_out, - int *counter_ret, unsigned long *h_ret, BN_GENCB *cb) +int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits, + const unsigned char *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb) { - int ok = 0; - unsigned char seed[SHA256_DIGEST_LENGTH]; - unsigned char md[SHA256_DIGEST_LENGTH]; - unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH]; - BIGNUM *r0, *W, *X, *c, *test; - BIGNUM *g = NULL, *q = NULL, *p = NULL; - BN_MONT_CTX *mont = NULL; - int i, k, n = 0, m = 0, qsize = qbits >> 3; - int counter = 0; - int r = 0; - BN_CTX *ctx = NULL; - unsigned int h = 2; - - if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH && - qsize != SHA256_DIGEST_LENGTH) - /* invalid q size */ +#ifndef FIPS_MODE + if (dsa->meth->dsa_paramgen) + return dsa->meth->dsa_paramgen(dsa, bits, seed_in, seed_len, + counter_ret, h_ret, cb); +#endif + if (seed_in != NULL + && !ffc_params_set_validate_params(&dsa->params, seed_in, seed_len, -1)) return 0; - if (evpmd == NULL) { - if (qsize == SHA_DIGEST_LENGTH) - evpmd = EVP_sha1(); - else if (qsize == SHA224_DIGEST_LENGTH) - evpmd = EVP_sha224(); - else - evpmd = EVP_sha256(); - } else { - qsize = EVP_MD_size(evpmd); - } - - if (bits < 512) - bits = 512; - - bits = (bits + 63) / 64 * 64; - - if (seed_in != NULL) { - if (seed_len < (size_t)qsize) { - DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_SEED_LEN_SMALL); +#ifndef FIPS_MODE + /* The old code used FIPS 186-2 DSA Parameter generation */ + if (bits <= 1024 && seed_len == 20) { + if (!dsa_generate_ffc_parameters(libctx, dsa, + DSA_PARAMGEN_TYPE_FIPS_186_2, + bits, 160, -1, cb)) + return 0; + } else +#endif + { + if (!dsa_generate_ffc_parameters(libctx, dsa, + DSA_PARAMGEN_TYPE_FIPS_186_4, + bits, -1, -1, cb)) return 0; - } - if (seed_len > (size_t)qsize) { - /* Only consume as much seed as is expected. */ - seed_len = qsize; - } - memcpy(seed, seed_in, seed_len); - } - - if ((mont = BN_MONT_CTX_new()) == NULL) - goto err; - - if ((ctx = BN_CTX_new()) == NULL) - goto err; - - BN_CTX_start(ctx); - - 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 (test == NULL) - goto err; - - if (!BN_lshift(test, BN_value_one(), bits - 1)) - goto err; - - for (;;) { - for (;;) { /* find q */ - int use_random_seed = (seed_in == NULL); - - /* step 1 */ - if (!BN_GENCB_call(cb, 0, m++)) - goto err; - - if (use_random_seed) { - if (RAND_bytes(seed, qsize) <= 0) - goto err; - } else { - /* If we come back through, use random seed next time. */ - seed_in = NULL; - } - memcpy(buf, seed, qsize); - memcpy(buf2, seed, qsize); - /* precompute "SEED + 1" for step 7: */ - for (i = qsize - 1; i >= 0; i--) { - buf[i]++; - if (buf[i] != 0) - break; - } - - /* step 2 */ - if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL)) - goto err; - if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) - goto err; - for (i = 0; i < qsize; i++) - md[i] ^= buf2[i]; - - /* step 3 */ - md[0] |= 0x80; - md[qsize - 1] |= 0x01; - if (!BN_bin2bn(md, qsize, q)) - goto err; - - /* step 4 */ - r = BN_check_prime(q, ctx, cb); - if (r > 0) - break; - if (r != 0) - goto err; - - /* do a callback call */ - /* step 5 */ - } - - if (!BN_GENCB_call(cb, 2, 0)) - goto err; - if (!BN_GENCB_call(cb, 3, 0)) - goto err; - - /* step 6 */ - counter = 0; - /* "offset = 2" */ - - n = (bits - 1) / 160; - - for (;;) { - if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) - goto err; - - /* step 7 */ - BN_zero(W); - /* now 'buf' contains "SEED + offset - 1" */ - for (k = 0; k <= n; k++) { - /* - * obtain "SEED + offset + k" by incrementing: - */ - for (i = qsize - 1; i >= 0; i--) { - buf[i]++; - if (buf[i] != 0) - break; - } - - if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) - goto err; - - /* step 8 */ - if (!BN_bin2bn(md, qsize, r0)) - goto err; - if (!BN_lshift(r0, r0, (qsize << 3) * k)) - goto err; - if (!BN_add(W, W, r0)) - goto err; - } - - /* more of step 8 */ - if (!BN_mask_bits(W, bits - 1)) - goto err; - if (!BN_copy(X, W)) - goto err; - if (!BN_add(X, X, test)) - goto err; - - /* step 9 */ - if (!BN_lshift1(r0, q)) - goto err; - if (!BN_mod(c, X, r0, ctx)) - goto err; - if (!BN_sub(r0, c, BN_value_one())) - goto err; - if (!BN_sub(p, X, r0)) - goto err; - - /* step 10 */ - if (BN_cmp(p, test) >= 0) { - /* step 11 */ - r = BN_check_prime(p, ctx, cb); - if (r > 0) - goto end; /* found it */ - if (r != 0) - goto err; - } - - /* step 13 */ - counter++; - /* "offset = offset + n + 1" */ - - /* step 14 */ - if (counter >= 4096) - break; - } - } - end: - if (!BN_GENCB_call(cb, 2, 1)) - goto err; - - /* 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 (!BN_MONT_CTX_set(mont, p, ctx)) - goto err; - - for (;;) { - /* 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; - h++; } - if (!BN_GENCB_call(cb, 3, 1)) - goto err; - - ok = 1; - err: - if (ok) { - BN_free(ret->params.p); - BN_free(ret->params.q); - BN_free(ret->params.g); - ret->params.p = BN_dup(p); - ret->params.q = BN_dup(q); - ret->params.g = BN_dup(g); - ret->dirty_cnt++; - if (ret->params.p == NULL - || ret->params.q == NULL - || ret->params.g == NULL) { - ok = 0; - goto err; - } - if (counter_ret != NULL) - *counter_ret = counter; - if (h_ret != NULL) - *h_ret = h; - if (seed_out) - memcpy(seed_out, seed, qsize); - } - BN_CTX_end(ctx); - BN_CTX_free(ctx); - BN_MONT_CTX_free(mont); - return ok; + if (counter_ret != NULL) + *counter_ret = dsa->params.pcounter; + if (h_ret != NULL) + *h_ret = dsa->params.h; + return 1; } -/* - * This is a parameter generation algorithm for the DSA2 algorithm as - * described in FIPS 186-3. - */ - -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, int idx, unsigned char *seed_out, - int *counter_ret, unsigned long *h_ret, - BN_GENCB *cb) +int DSA_generate_parameters_ex(DSA *dsa, int bits, + const unsigned char *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb) { - int ok = -1; - unsigned char *seed = NULL, *seed_tmp = NULL; - unsigned char md[EVP_MAX_MD_SIZE]; - int mdsize; - BIGNUM *r0, *W, *X, *c, *test; - BIGNUM *g = NULL, *q = NULL, *p = NULL; - BN_MONT_CTX *mont = NULL; - int i, k, n = 0, m = 0, qsize = N >> 3; - int counter = 0; - int r = 0; - BN_CTX *ctx = NULL; - EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - unsigned int h = 2; - - if (mctx == NULL) - goto err; - - /* make sure L > N, otherwise we'll get trapped in an infinite loop */ - if (L <= N) { - DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS); - goto err; - } - - if (evpmd == NULL) { - if (N == 160) - evpmd = EVP_sha1(); - else if (N == 224) - evpmd = EVP_sha224(); - else - evpmd = EVP_sha256(); - } - - mdsize = EVP_MD_size(evpmd); - /* If unverifiable g generation only don't need seed */ - if (!ret->params.p || !ret->params.q || idx >= 0) { - if (seed_len == 0) - seed_len = mdsize; - - seed = OPENSSL_malloc(seed_len); - - if (seed_out) - seed_tmp = seed_out; - else - seed_tmp = OPENSSL_malloc(seed_len); - - if (seed == NULL || seed_tmp == NULL) - goto err; - - if (seed_in) - memcpy(seed, seed_in, seed_len); - - } - - if ((ctx = BN_CTX_new()) == NULL) - goto err; - - if ((mont = BN_MONT_CTX_new()) == NULL) - goto err; - - BN_CTX_start(ctx); - r0 = BN_CTX_get(ctx); - g = BN_CTX_get(ctx); - W = BN_CTX_get(ctx); - X = BN_CTX_get(ctx); - c = BN_CTX_get(ctx); - test = BN_CTX_get(ctx); - if (test == NULL) - goto err; - - /* if p, q already supplied generate g only */ - if (ret->params.p && ret->params.q) { - p = ret->params.p; - q = ret->params.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 (q == NULL) - goto err; - } - - if (!BN_lshift(test, BN_value_one(), L - 1)) - goto err; - for (;;) { - for (;;) { /* find q */ - unsigned char *pmd; - /* step 1 */ - if (!BN_GENCB_call(cb, 0, m++)) - goto err; - - if (!seed_in) { - if (RAND_bytes(seed, seed_len) <= 0) - goto err; - } - /* step 2 */ - if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL)) - goto err; - /* Take least significant bits of md */ - if (mdsize > qsize) - pmd = md + mdsize - qsize; - else - pmd = md; - - if (mdsize < qsize) - memset(md + mdsize, 0, qsize - mdsize); - - /* step 3 */ - pmd[0] |= 0x80; - pmd[qsize - 1] |= 0x01; - if (!BN_bin2bn(pmd, qsize, q)) - goto err; - - /* step 4 */ - r = BN_check_prime(q, ctx, cb); - if (r > 0) - break; - if (r != 0) - goto err; - /* Provided seed didn't produce a prime: error */ - if (seed_in) { - ok = 0; - DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_Q_NOT_PRIME); - goto err; - } - - /* do a callback call */ - /* step 5 */ - } - /* Copy seed to seed_out before we mess with it */ - if (seed_out) - memcpy(seed_out, seed, seed_len); - - if (!BN_GENCB_call(cb, 2, 0)) - goto err; - if (!BN_GENCB_call(cb, 3, 0)) - goto err; - - /* step 6 */ - counter = 0; - /* "offset = 1" */ - - n = (L - 1) / (mdsize << 3); - - for (;;) { - if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) - goto err; - - /* step 7 */ - BN_zero(W); - /* now 'buf' contains "SEED + offset - 1" */ - for (k = 0; k <= n; k++) { - /* - * obtain "SEED + offset + k" by incrementing: - */ - for (i = seed_len - 1; i >= 0; i--) { - seed[i]++; - if (seed[i] != 0) - break; - } - - if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL)) - goto err; - - /* step 8 */ - if (!BN_bin2bn(md, mdsize, r0)) - goto err; - if (!BN_lshift(r0, r0, (mdsize << 3) * k)) - goto err; - if (!BN_add(W, W, r0)) - goto err; - } - - /* more of step 8 */ - if (!BN_mask_bits(W, L - 1)) - goto err; - if (!BN_copy(X, W)) - goto err; - if (!BN_add(X, X, test)) - goto err; - - /* step 9 */ - if (!BN_lshift1(r0, q)) - goto err; - if (!BN_mod(c, X, r0, ctx)) - goto err; - if (!BN_sub(r0, c, BN_value_one())) - goto err; - if (!BN_sub(p, X, r0)) - goto err; - - /* step 10 */ - if (BN_cmp(p, test) >= 0) { - /* step 11 */ - r = BN_check_prime(p, ctx, cb); - if (r > 0) - goto end; /* found it */ - if (r != 0) - goto err; - } - - /* step 13 */ - counter++; - /* "offset = offset + n + 1" */ - - /* step 14 */ - 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 (idx < 0) { - if (!BN_set_word(test, h)) - goto err; - } else - h = 1; - if (!BN_MONT_CTX_set(mont, p, ctx)) - goto err; - - for (;;) { - 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 (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)) - goto err; - - ok = 1; - err: - if (ok == 1) { - if (p != ret->params.p) { - BN_free(ret->params.p); - ret->params.p = BN_dup(p); - } - if (q != ret->params.q) { - BN_free(ret->params.q); - ret->params.q = BN_dup(q); - } - BN_free(ret->params.g); - ret->params.g = BN_dup(g); - if (ret->params.p == NULL - || ret->params.q == NULL - || ret->params.g == NULL) { - ok = -1; - goto err; - } - ret->dirty_cnt++; - if (counter_ret != NULL) - *counter_ret = counter; - if (h_ret != NULL) - *h_ret = h; - } - OPENSSL_free(seed); - if (seed_out != seed_tmp) - OPENSSL_free(seed_tmp); - BN_CTX_end(ctx); - BN_CTX_free(ctx); - BN_MONT_CTX_free(mont); - EVP_MD_CTX_free(mctx); - return ok; + return dsa_generate_parameters_ctx(NULL, dsa, bits, + seed_in, seed_len, + counter_ret, h_ret, cb); } |