From 4f2271d58a36b2aee125062ffb9626c6208fa394 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Wed, 17 Jun 2020 11:33:16 +1000 Subject: Add ACVP fips module tests For FIPS validation purposes - Automated Cryptographic Validation Protocol (ACVP) tests need to be performed. (See https://github.com/usnistgov/ACVP). These tests are very similiar to the old CAVS tests. This PR uses a hardwired subset of these test vectors to perform similiar operations, to show the usage and prove that the API's are able to perform the required operations. It may also help with communication with the lab (i.e- The lab could add a test here to show a unworking use case - which we can then address). The EVP layer performs these tests instead of calling lower level API's as was done in the old FOM. Some of these tests require access to internals that are not normally allowed/required. The config option 'acvp_tests' (enabled by default) has been added so that this access may be removed. The mechanism has been implemented as additional OSSL_PARAM values that can be set and get. A callback mechanism did not seem to add any additional benefit. These params will not be added to the gettables lists. Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/11572) --- crypto/dh/dh_check.c | 4 +- crypto/dh/dh_gen.c | 15 +-- crypto/dh/dh_pmeth.c | 17 ++-- crypto/dsa/dsa_check.c | 4 +- crypto/dsa/dsa_gen.c | 27 ++--- crypto/dsa/dsa_pmeth.c | 6 +- crypto/ffc/ffc_backend.c | 22 ++++ crypto/ffc/ffc_params.c | 59 +++++++++++ crypto/ffc/ffc_params_generate.c | 208 ++++++++++++++++++++------------------ crypto/ffc/ffc_params_validate.c | 24 ++--- crypto/rsa/build.info | 4 + crypto/rsa/rsa_acvp_test_params.c | 167 ++++++++++++++++++++++++++++++ crypto/rsa/rsa_backend.c | 8 +- crypto/rsa/rsa_gen.c | 4 +- crypto/rsa/rsa_lib.c | 5 + crypto/rsa/rsa_local.h | 38 +++++-- crypto/rsa/rsa_sp800_56b_gen.c | 74 +++++++++----- 17 files changed, 489 insertions(+), 197 deletions(-) create mode 100644 crypto/rsa/rsa_acvp_test_params.c (limited to 'crypto') diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 9dd595ae12..a223121cd0 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -62,8 +62,8 @@ int DH_check_params(const DH *dh, int *ret) * (2b) FFC domain params conform to FIPS-186-4 explicit domain param * validity tests. */ - return ffc_params_FIPS186_4_validate(&dh->params, FFC_PARAM_TYPE_DH, NULL, - FFC_PARAMS_VALIDATE_ALL, ret, NULL); + return ffc_params_FIPS186_4_validate(dh->libctx, &dh->params, + FFC_PARAM_TYPE_DH, ret, NULL); } #else int DH_check_params(const DH *dh, int *ret) diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c index 8c1518ad9b..52f3151bc8 100644 --- a/crypto/dh/dh_gen.c +++ b/crypto/dh/dh_gen.c @@ -35,28 +35,21 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb); #endif /* FIPS_MODULE */ -int dh_generate_ffc_parameters(DH *dh, int type, int pbits, - int qbits, EVP_MD *md, BN_GENCB *cb) +int dh_generate_ffc_parameters(DH *dh, int type, int pbits, int qbits, + BN_GENCB *cb) { int ret, res; - if (qbits <= 0) { - if (md != NULL) - qbits = EVP_MD_size(md) * 8; - else - qbits = (pbits >= 2048 ? SHA256_DIGEST_LENGTH : - SHA_DIGEST_LENGTH) * 8; - } #ifndef FIPS_MODULE if (type == DH_PARAMGEN_TYPE_FIPS_186_2) ret = ffc_params_FIPS186_2_generate(dh->libctx, &dh->params, FFC_PARAM_TYPE_DH, - pbits, qbits, md, &res, cb); + pbits, qbits, &res, cb); else #endif ret = ffc_params_FIPS186_4_generate(dh->libctx, &dh->params, FFC_PARAM_TYPE_DH, - pbits, qbits, md, &res, cb); + pbits, qbits, &res, cb); if (ret > 0) dh->dirty_cnt++; return ret; diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c index 23527acf04..39b79ffb36 100644 --- a/crypto/dh/dh_pmeth.c +++ b/crypto/dh/dh_pmeth.c @@ -286,7 +286,6 @@ static DH *ffc_params_generate(OPENSSL_CTX *libctx, DH_PKEY_CTX *dctx, int res; int prime_len = dctx->prime_len; int subprime_len = dctx->subprime_len; - const EVP_MD *md = dctx->md; if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4) return NULL; @@ -300,26 +299,22 @@ static DH *ffc_params_generate(OPENSSL_CTX *libctx, DH_PKEY_CTX *dctx, else subprime_len = 160; } - if (md == NULL) { - if (prime_len >= 2048) - md = EVP_sha256(); - else - md = EVP_sha1(); - } + + if (dctx->md != NULL) + ffc_set_digest(&ret->params, EVP_MD_name(dctx->md), NULL); + # ifndef FIPS_MODULE if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2) rv = ffc_params_FIPS186_2_generate(libctx, &ret->params, FFC_PARAM_TYPE_DH, - prime_len, subprime_len, md, &res, - pcb); + prime_len, subprime_len, &res, pcb); else # endif /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */ if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) rv = ffc_params_FIPS186_4_generate(libctx, &ret->params, FFC_PARAM_TYPE_DH, - prime_len, subprime_len, md, &res, - pcb); + prime_len, subprime_len, &res, pcb); if (rv <= 0) { DH_free(ret); return NULL; diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c index dc42ec5f5f..01cf0f6341 100644 --- a/crypto/dsa/dsa_check.c +++ b/crypto/dsa/dsa_check.c @@ -19,8 +19,8 @@ int dsa_check_params(const DSA *dsa, int *ret) * (2b) FFC domain params conform to FIPS-186-4 explicit domain param * validity tests. */ - return ffc_params_FIPS186_4_validate(&dsa->params, FFC_PARAM_TYPE_DSA, NULL, - FFC_PARAMS_VALIDATE_ALL, ret, NULL); + return ffc_params_FIPS186_4_validate(dsa->libctx, &dsa->params, + FFC_PARAM_TYPE_DSA, ret, NULL); } /* diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index acd088ee79..9d5e91de29 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -23,29 +23,21 @@ #include "crypto/dsa.h" #include "dsa_local.h" -int dsa_generate_ffc_parameters(DSA *dsa, int type, - int pbits, int qbits, - EVP_MD *md, BN_GENCB *cb) +int dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits, + BN_GENCB *cb) { int ret = 0, res; - if (qbits <= 0) { - if (md != NULL) - qbits = EVP_MD_size(md) * 8; - else - qbits = (pbits >= 2048 ? SHA256_DIGEST_LENGTH : - SHA_DIGEST_LENGTH) * 8; - } #ifndef FIPS_MODULE if (type == DSA_PARAMGEN_TYPE_FIPS_186_2) ret = ffc_params_FIPS186_2_generate(dsa->libctx, &dsa->params, FFC_PARAM_TYPE_DSA, - pbits, qbits, md, &res, cb); + pbits, qbits, &res, cb); else #endif ret = ffc_params_FIPS186_4_generate(dsa->libctx, &dsa->params, FFC_PARAM_TYPE_DSA, - pbits, qbits, md, &res, cb); + pbits, qbits, &res, cb); if (ret > 0) dsa->dirty_cnt++; return ret; @@ -57,26 +49,21 @@ int DSA_generate_parameters_ex(DSA *dsa, int bits, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb) { -#ifndef FIPS_MODULE 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; -#ifndef FIPS_MODULE /* The old code used FIPS 186-2 DSA Parameter generation */ if (bits <= 1024 && seed_len == 20) { if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_2, - bits, 160, NULL, cb)) + bits, 160, cb)) return 0; - } else -#endif - { + } else { if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_4, - bits, -1, NULL, cb)) + bits, -1, cb)) return 0; } diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c index 7f7f57f6d3..7b364059e7 100644 --- a/crypto/dsa/dsa_pmeth.c +++ b/crypto/dsa/dsa_pmeth.c @@ -217,9 +217,11 @@ static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) BN_GENCB_free(pcb); return 0; } + if (dctx->md != NULL) + ffc_set_digest(&dsa->params, EVP_MD_name(dctx->md), NULL); + ret = ffc_params_FIPS186_4_generate(NULL, &dsa->params, FFC_PARAM_TYPE_DSA, - dctx->nbits, dctx->qbits, dctx->pmd, - &res, pcb); + dctx->nbits, dctx->qbits, &res, pcb); BN_GENCB_free(pcb); if (ret > 0) EVP_PKEY_assign_DSA(pkey, dsa); diff --git a/crypto/ffc/ffc_backend.c b/crypto/ffc/ffc_backend.c index c34e79bf4f..49f42d70d0 100644 --- a/crypto/ffc/ffc_backend.c +++ b/crypto/ffc/ffc_backend.c @@ -78,6 +78,28 @@ int ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]) if (!ffc_params_set_seed(ffc, prm->data, prm->data_size)) goto err; } + prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_TYPE); + if (prm != NULL) { + if (prm->data_type != OSSL_PARAM_UTF8_STRING) + goto err; + ffc_params_set_flags(ffc, ffc_params_flags_from_name(prm->data)); + } + prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST); + if (prm != NULL) { + const OSSL_PARAM *p1; + const char *props = NULL; + + if (prm->data_type != OSSL_PARAM_UTF8_STRING) + goto err; + p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS); + if (p1 != NULL) { + if (p1->data_type != OSSL_PARAM_UTF8_STRING) + goto err; + } + if (!ffc_set_digest(ffc, prm->data, props)) + goto err; + } + ffc_params_set0_pqg(ffc, p, q, g); ffc_params_set0_j(ffc, j); return 1; diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c index a95a2fa12b..0796d34337 100644 --- a/crypto/ffc/ffc_params.c +++ b/crypto/ffc/ffc_params.c @@ -11,6 +11,8 @@ #include #include "internal/ffc.h" #include "internal/param_build_set.h" +#include "internal/nelem.h" +#include "e_os.h" /* strcasecmp */ #ifndef FIPS_MODULE # include /* ffc_params_print */ @@ -21,6 +23,7 @@ void ffc_params_init(FFC_PARAMS *params) memset(params, 0, sizeof(*params)); params->pcounter = -1; params->gindex = FFC_UNVERIFIABLE_GINDEX; + params->flags = FFC_PARAM_FLAG_VALIDATE_ALL; } void ffc_params_cleanup(FFC_PARAMS *params) @@ -109,6 +112,18 @@ void ffc_params_set_h(FFC_PARAMS *params, int index) params->h = index; } +void ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags) +{ + params->flags = flags; +} + +int ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props) +{ + params->mdname = alg; + params->mdprops = props; + return 1; +} + int ffc_params_set_validate_params(FFC_PARAMS *params, const unsigned char *seed, size_t seedlen, int counter) @@ -182,6 +197,36 @@ int ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q) && (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */ } +static const OSSL_ITEM flag_map[] = { + { FFC_PARAM_FLAG_VALIDATE_PQ, OSSL_FFC_PARAM_VALIDATE_PQ }, + { FFC_PARAM_FLAG_VALIDATE_G, OSSL_FFC_PARAM_VALIDATE_G }, + { FFC_PARAM_FLAG_VALIDATE_ALL, OSSL_FFC_PARAM_VALIDATE_PQG }, + { 0, "" } +}; + +int ffc_params_flags_from_name(const char *name) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(flag_map); ++i) { + if (strcasecmp(flag_map[i].ptr, name) == 0) + return flag_map[i].id; + } + return NID_undef; +} + +const char *ffc_params_flags_to_name(int flags) +{ + size_t i; + + flags &= FFC_PARAM_FLAG_VALIDATE_ALL; + for (i = 0; i < OSSL_NELEM(flag_map); ++i) { + if ((int)flag_map[i].id == flags) + return flag_map[i].ptr; + } + return ""; +} + int ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) { @@ -228,6 +273,20 @@ int ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld, return 0; #endif } + if (!ossl_param_build_set_utf8_string(bld, params, + OSSL_PKEY_PARAM_FFC_VALIDATE_TYPE, + ffc_params_flags_to_name(ffc->flags))) + return 0; + if (ffc->mdname != NULL + && !ossl_param_build_set_utf8_string(bld, params, + OSSL_PKEY_PARAM_FFC_DIGEST, + ffc->mdname)) + return 0; + if (ffc->mdprops != NULL + && !ossl_param_build_set_utf8_string(bld, params, + OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, + ffc->mdprops)) + return 0; return 1; } diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c index 624c24dd21..b3ab476f3f 100644 --- a/crypto/ffc/ffc_params_generate.c +++ b/crypto/ffc/ffc_params_generate.c @@ -413,18 +413,15 @@ err: return ret; } -static EVP_MD *fetch_default_md(OPENSSL_CTX *libctx, size_t N) +static const char *default_mdname(size_t N) { - char *name = NULL; - if (N == 160) - name = "SHA1"; + return "SHA1"; else if (N == 224) - name = "SHA-224"; + return "SHA-224"; else if (N == 256) - name = "SHA-256"; - - return name != NULL ? EVP_MD_fetch(libctx, name, "") : NULL; + return "SHA-256"; + return NULL; } /* @@ -446,6 +443,13 @@ static EVP_MD *fetch_default_md(OPENSSL_CTX *libctx, size_t N) * the seed and index used during generation as input. * * params: used to pass in values for generation and validation. + * params->md: is the digest to use, If this value is NULL, then the digest is + * chosen using the value of N. + * params->flags: + * For validation one of: + * -FFC_PARAM_FLAG_VALIDATE_PQ + * -FFC_PARAM_FLAG_VALIDATE_G + * -FFC_PARAM_FLAG_VALIDATE_ALL * For generation of p & q: * - This is skipped if p & q are passed in. * - If the seed is passed in then generation of p & q uses this seed (and if @@ -462,48 +466,58 @@ static EVP_MD *fetch_default_md(OPENSSL_CTX *libctx, size_t N) * - For a partial validation : p, q and g are required. * - For a canonical validation : the gindex and seed used for generation are * also required. + * mode: The mode - either FFC_PARAM_MODE_GENERATE or FFC_PARAM_MODE_VERIFY. * type: The key type - FFC_PARAM_TYPE_DSA or FFC_PARAM_TYPE_DH. * L: is the size of the prime p in bits (e.g 2048) * N: is the size of the prime q in bits (e.g 256) - * evpmd: is the digest to use, If this value is NULL, then the digest is chosen - * using the value of N. - * validate_flags: - * or generation: FFC_PARAMS_GENERATE. - * For validation one of: - * -FFC_PARAMS_VALIDATE_PQ - * -FFC_PARAMS_VALIDATE_G - * -FFC_PARAMS_VALIDATE_ALL * res: A returned failure reason (One of FFC_CHECK_XXXX), * or 0 for general failures. * cb: A callback (can be NULL) that is called during different phases * * Returns: - * - FFC_PARAMS_RET_STATUS_FAILED: if there was an error, or validation failed. - * - FFC_PARAMS_RET_STATUS_SUCCESS if the generation or validation succeeded. - * - FFC_PARAMS_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded, + * - FFC_PARAM_RET_STATUS_FAILED: if there was an error, or validation failed. + * - FFC_PARAM_RET_STATUS_SUCCESS if the generation or validation succeeded. + * - FFC_PARAM_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded, * but G is unverifiable. */ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, - int type, size_t L, size_t N, - const EVP_MD *evpmd, int validate_flags, + int mode, int type, size_t L, size_t N, int *res, BN_GENCB *cb) { - int ok = FFC_PARAMS_RET_STATUS_FAILED; + int ok = FFC_PARAM_RET_STATUS_FAILED; unsigned char *seed = NULL, *seed_tmp = NULL; int mdsize, counter = 0, pcounter = 0, r = 0; size_t seedlen = 0; BIGNUM *tmp, *pm1, *e, *test; BIGNUM *g = NULL, *q = NULL, *p = NULL; BN_MONT_CTX *mont = NULL; - int n = 0, m = 0, qsize = N >> 3; + int n = 0, m = 0, qsize; int canonical_g = 0, hret = 0; BN_CTX *ctx = NULL; EVP_MD_CTX *mctx = NULL; - int generate = (validate_flags == 0); - EVP_MD *evpmd_fetch = NULL; + EVP_MD *md = NULL; + int verify = (mode == FFC_PARAM_MODE_VERIFY); + unsigned int flags = verify ? params->flags : 0; *res = 0; + if (params->mdname != NULL) { + md = EVP_MD_fetch(libctx, params->mdname, params->mdprops); + } else { + if (N <= 0) + N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8; + md = EVP_MD_fetch(libctx, default_mdname(N), NULL); + } + if (md == NULL) + goto err; + mdsize = EVP_MD_size(md); + if (mdsize <= 0) + goto err; + + if (N <= 0) + N = mdsize * 8; + qsize = N >> 3; + /* * A.1.1.2 Step (1) AND * A.1.1.3 Step (3) @@ -518,15 +532,6 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, if (mctx == NULL) goto err; - if (evpmd == NULL) { - evpmd_fetch = fetch_default_md(libctx, N); - evpmd = evpmd_fetch; - } - - mdsize = EVP_MD_size(evpmd); - if (mdsize <= 0) - goto err; - if ((ctx = BN_CTX_new_ex(libctx)) == NULL) goto err; @@ -546,7 +551,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, if (params->seed != NULL) seed = params->seed; - if (generate) { + if (!verify) { /* For generation: p & q must both be NULL or NON-NULL */ if ((params->p == NULL) != (params->q == NULL)) { *res = FFC_CHECK_INVALID_PQ; @@ -554,13 +559,13 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, } } else { /* Validation of p,q requires seed and counter to be valid */ - if ((validate_flags & FFC_PARAMS_VALIDATE_PQ) != 0) { + if ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0) { if (seed == NULL || params->pcounter < 0) { *res = FFC_CHECK_MISSING_SEED_OR_COUNTER; goto err; } } - if ((validate_flags & FFC_PARAMS_VALIDATE_G) != 0) { + if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) { /* validation of g also requires g to be set */ if (params->g == NULL) { *res = FFC_CHECK_INVALID_G; @@ -574,7 +579,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, * validate_flags = 0 then skip the generation of PQ. * validate_flags = VALIDATE_G then also skip the validation of PQ. */ - if (params->p != NULL && ((validate_flags & FFC_PARAMS_VALIDATE_PQ) == 0)) { + if (params->p != NULL && ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) == 0)) { /* p and q already exists so only generate g */ p = params->p; q = params->q; @@ -604,7 +609,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, if (seed == NULL) { /* Validation requires the seed to be supplied */ - if (validate_flags) { + if (verify) { *res = FFC_CHECK_MISSING_SEED_OR_COUNTER; goto err; } @@ -617,7 +622,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, /* A.1.1.2 Step (11): max loop count = 4L - 1 */ counter = 4 * L - 1; /* Validation requires the counter to be supplied */ - if (validate_flags) { + if (verify) { /* A.1.1.3 Step (4) : if (counter > (4L -1)) return INVALID */ if (params->pcounter > counter) { *res = FFC_CHECK_INVALID_COUNTER; @@ -638,11 +643,11 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, goto err; for (;;) { - if (!generate_q_fips186_4(ctx, q, evpmd, qsize, seed, seedlen, + if (!generate_q_fips186_4(ctx, q, md, qsize, seed, seedlen, seed != params->seed, &m, res, cb)) goto err; /* A.1.1.3 Step (9): Verify that q matches the expected value */ - if (validate_flags && (BN_cmp(q, params->q) != 0)) { + if (verify && (BN_cmp(q, params->q) != 0)) { *res = FFC_CHECK_Q_MISMATCH; goto err; } @@ -652,8 +657,8 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, goto err; memcpy(seed_tmp, seed, seedlen); - r = generate_p(ctx, evpmd, counter, n, seed_tmp, seedlen, q, p, L, cb, - &pcounter, res); + r = generate_p(ctx, md, counter, n, seed_tmp, seedlen, q, p, L, + cb, &pcounter, res); if (r > 0) break; /* found p */ if (r < 0) @@ -674,11 +679,11 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, * Gets here if we found p. * A.1.1.3 Step (14): return error if i != counter OR computed_p != known_p. */ - if (validate_flags && (pcounter != counter || (BN_cmp(p, params->p) != 0))) + if (verify && (pcounter != counter || (BN_cmp(p, params->p) != 0))) goto err; /* If validating p & q only then skip the g validation test */ - if ((validate_flags & FFC_PARAMS_VALIDATE_ALL) == FFC_PARAMS_VALIDATE_PQ) + if ((flags & FFC_PARAM_FLAG_VALIDATE_ALL) == FFC_PARAM_FLAG_VALIDATE_PQ) goto pass; g_only: if ((mont = BN_MONT_CTX_new()) == NULL) @@ -686,7 +691,7 @@ g_only: if (!BN_MONT_CTX_set(mont, p, ctx)) goto err; - if (((validate_flags & FFC_PARAMS_VALIDATE_G) != 0) + if (((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) && !ffc_params_validate_unverifiable_g(ctx, mont, p, q, params->g, tmp, res)) goto err; @@ -703,17 +708,17 @@ g_only: /* Canonical g requires a seed and index to be set */ if ((seed != NULL) && (params->gindex != FFC_UNVERIFIABLE_GINDEX)) { canonical_g = 1; - if (!generate_canonical_g(ctx, mont, evpmd, g, tmp, p, e, + if (!generate_canonical_g(ctx, mont, md, g, tmp, p, e, params->gindex, seed, seedlen)) { *res = FFC_CHECK_INVALID_G; goto err; } /* A.2.4 Step (13): Return valid if computed_g == g */ - if (validate_flags && BN_cmp(g, params->g) != 0) { + if (verify && BN_cmp(g, params->g) != 0) { *res = FFC_CHECK_G_MISMATCH; goto err; } - } else if (generate) { + } else if (!verify) { if (!generate_unverifiable_g(ctx, mont, g, tmp, p, e, pm1, &hret)) goto err; } @@ -721,7 +726,7 @@ g_only: if (!BN_GENCB_call(cb, 3, 1)) goto err; - if (generate) { + if (!verify) { if (p != params->p) { BN_free(params->p); params->p = BN_dup(p); @@ -741,11 +746,11 @@ g_only: params->h = hret; } pass: - if ((validate_flags & FFC_PARAMS_VALIDATE_G) != 0 && (canonical_g == 0)) + if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0 && (canonical_g == 0)) /* Return for the case where g is partially valid */ - ok = FFC_PARAMS_RET_STATUS_UNVERIFIABLE_G; + ok = FFC_PARAM_RET_STATUS_UNVERIFIABLE_G; else - ok = FFC_PARAMS_RET_STATUS_SUCCESS; + ok = FFC_PARAM_RET_STATUS_SUCCESS; err: if (seed != params->seed) OPENSSL_free(seed); @@ -754,33 +759,47 @@ err: BN_CTX_end(ctx); BN_CTX_free(ctx); BN_MONT_CTX_free(mont); - EVP_MD_free(evpmd_fetch); EVP_MD_CTX_free(mctx); + EVP_MD_free(md); return ok; } int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, - int type, size_t L, size_t N, - const EVP_MD *evpmd, int validate_flags, + int mode, int type, size_t L, size_t N, int *res, BN_GENCB *cb) { - int ok = FFC_PARAMS_RET_STATUS_FAILED; + int ok = FFC_PARAM_RET_STATUS_FAILED; unsigned char seed[SHA256_DIGEST_LENGTH]; unsigned char buf[SHA256_DIGEST_LENGTH]; BIGNUM *r0, *test, *tmp, *g = NULL, *q = NULL, *p = NULL; BN_MONT_CTX *mont = NULL; - size_t qsize = N >> 3; + EVP_MD *md = NULL; + size_t qsize; int n = 0, m = 0; int counter = 0, pcounter = 0, use_random_seed; int rv; BN_CTX *ctx = NULL; int hret = -1; - int generate = (validate_flags == 0); unsigned char *seed_in = params->seed; size_t seed_len = params->seedlen; - EVP_MD *evpmd_fetch = NULL; + int verify = (mode == FFC_PARAM_MODE_VERIFY); + unsigned int flags = verify ? params->flags : 0; *res = 0; + + if (params->mdname != NULL) { + md = EVP_MD_fetch(libctx, params->mdname, params->mdprops); + } else { + if (N <= 0) + N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8; + md = EVP_MD_fetch(libctx, default_mdname(N), NULL); + } + if (md == NULL) + goto err; + if (N <= 0) + N = EVP_MD_size(md) * 8; + qsize = N >> 3; + #ifdef FIPS_MODULE /* * FIPS 186-4 states that validation can only be done for this pair. @@ -788,7 +807,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, */ if (L != 1024 || N != 160) { *res = FFC_CHECK_BAD_LN_PAIR; - return FFC_PARAMS_RET_STATUS_FAILED; + goto err; } #endif if (qsize != SHA_DIGEST_LENGTH @@ -796,17 +815,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, && qsize != SHA256_DIGEST_LENGTH) { /* invalid q size */ *res = FFC_CHECK_INVALID_Q_VALUE; - return FFC_PARAMS_RET_STATUS_FAILED; - } - - if (evpmd == NULL) { - evpmd_fetch = fetch_default_md(libctx, qsize * 8); - evpmd = evpmd_fetch; - } else { - rv = EVP_MD_size(evpmd); - if (rv <= 0) - return 0; - qsize = (size_t)rv; + goto err; } if (L < 512) @@ -817,12 +826,11 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, if (seed_in != NULL) { if (seed_len < qsize) { *res = FFC_CHECK_INVALID_SEED_SIZE; - return 0; + goto err; } - if (seed_len > qsize) { - /* Only consume as much seed as is expected. */ + /* Only consume as much seed as is expected. */ + if (seed_len > qsize) seed_len = qsize; - } memcpy(seed, seed_in, seed_len); } @@ -844,21 +852,21 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, if (!BN_lshift(test, BN_value_one(), L - 1)) goto err; - if (generate) { + if (!verify) { /* For generation: p & q must both be NULL or NON-NULL */ if ((params->p != NULL) != (params->q != NULL)) { *res = FFC_CHECK_INVALID_PQ; goto err; } } else { - if ((validate_flags & FFC_PARAMS_VALIDATE_PQ) != 0) { + if ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0) { /* Validation of p,q requires seed and counter to be valid */ if (seed_in == NULL || params->pcounter < 0) { *res = FFC_CHECK_MISSING_SEED_OR_COUNTER; goto err; } } - if ((validate_flags & FFC_PARAMS_VALIDATE_G) != 0) { + if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) { /* validation of g also requires g to be set */ if (params->g == NULL) { *res = FFC_CHECK_INVALID_G; @@ -867,7 +875,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, } } - if (params->p != NULL && ((validate_flags & FFC_PARAMS_VALIDATE_PQ) == 0)) { + if (params->p != NULL && ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) == 0)) { /* p and q already exists so only generate g */ p = params->p; q = params->q; @@ -877,7 +885,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, use_random_seed = (seed_in == NULL); for (;;) { - if (!generate_q_fips186_2(ctx, q, evpmd, buf, seed, qsize, + if (!generate_q_fips186_2(ctx, q, md, buf, seed, qsize, use_random_seed, &m, res, cb)) goto err; @@ -890,7 +898,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, n = (L - 1) / 160; counter = 4 * L - 1; /* Was 4096 */ /* Validation requires the counter to be supplied */ - if (validate_flags) { + if (verify) { if (params->pcounter > counter) { *res = FFC_CHECK_INVALID_COUNTER; goto err; @@ -898,7 +906,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, counter = params->pcounter; } - rv = generate_p(ctx, evpmd, counter, n, buf, qsize, q, p, L, cb, + rv = generate_p(ctx, md, counter, n, buf, qsize, q, p, L, cb, &pcounter, res); if (rv > 0) break; /* found it */ @@ -911,7 +919,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, if (!BN_GENCB_call(cb, 2, 1)) goto err; - if (validate_flags) { + if (verify) { if (pcounter != counter) { *res = FFC_CHECK_COUNTER_MISMATCH; goto err; @@ -922,7 +930,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, } } /* If validating p & q only then skip the g validation test */ - if ((validate_flags & FFC_PARAMS_VALIDATE_ALL) == FFC_PARAMS_VALIDATE_PQ) + if ((flags & FFC_PARAM_FLAG_VALIDATE_ALL) == FFC_PARAM_FLAG_VALIDATE_PQ) goto pass; g_only: if ((mont = BN_MONT_CTX_new()) == NULL) @@ -930,7 +938,7 @@ g_only: if (!BN_MONT_CTX_set(mont, p, ctx)) goto err; - if (generate) { + if (!verify) { /* We now need to generate g */ /* set test = p - 1 */ if (!BN_sub(test, p, BN_value_one())) @@ -940,7 +948,7 @@ g_only: goto err; if (!generate_unverifiable_g(ctx, mont, g, tmp, p, r0, test, &hret)) goto err; - } else if (((validate_flags & FFC_PARAMS_VALIDATE_G) != 0) + } else if (((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) && !ffc_params_validate_unverifiable_g(ctx, mont, p, q, params->g, tmp, res)) { goto err; @@ -949,7 +957,7 @@ g_only: if (!BN_GENCB_call(cb, 3, 1)) goto err; - if (generate) { + if (!verify) { if (p != params->p) { BN_free(params->p); params->p = BN_dup(p); @@ -969,32 +977,34 @@ g_only: params->h = hret; } pass: - if ((validate_flags & FFC_PARAMS_VALIDATE_G) != 0) - ok = FFC_PARAMS_RET_STATUS_UNVERIFIABLE_G; + if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) + ok = FFC_PARAM_RET_STATUS_UNVERIFIABLE_G; else - ok = FFC_PARAMS_RET_STATUS_SUCCESS; + ok = FFC_PARAM_RET_STATUS_SUCCESS; err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(ctx); - EVP_MD_free(evpmd_fetch); BN_MONT_CTX_free(mont); + EVP_MD_free(md); return ok; } int ffc_params_FIPS186_4_generate(OPENSSL_CTX *libctx, FFC_PARAMS *params, int type, size_t L, size_t N, - const EVP_MD *evpmd, int *res, BN_GENCB *cb) + int *res, BN_GENCB *cb) { - return ffc_params_FIPS186_4_gen_verify(libctx, params, type, L, N, evpmd, 0, - res, cb); + return ffc_params_FIPS186_4_gen_verify(libctx, params, + FFC_PARAM_MODE_GENERATE, + type, L, N, res, cb); } /* This should no longer be used in FIPS mode */ int ffc_params_FIPS186_2_generate(OPENSSL_CTX *libctx, FFC_PARAMS *params, int type, size_t L, size_t N, - const EVP_MD *evpmd, int *res, BN_GENCB *cb) + int *res, BN_GENCB *cb) { - return ffc_params_FIPS186_2_gen_verify(libctx, params, type, L, N, evpmd, - 0, res, cb); + return ffc_params_FIPS186_2_gen_verify(libctx, params, + FFC_PARAM_MODE_GENERATE, + type, L, N, res, cb); } diff --git a/crypto/ffc/ffc_params_validate.c b/crypto/ffc/ffc_params_validate.c index 4d0a4d837f..f3df0c2b39 100644 --- a/crypto/ffc/ffc_params_validate.c +++ b/crypto/ffc/ffc_params_validate.c @@ -44,37 +44,37 @@ int ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, return 1; } -int ffc_params_FIPS186_4_validate(const FFC_PARAMS *params, int type, - const EVP_MD *evpmd, int validate_flags, - int *res, BN_GENCB *cb) +int ffc_params_FIPS186_4_validate(OPENSSL_CTX *libctx, const FFC_PARAMS *params, + int type, int *res, BN_GENCB *cb) { size_t L, N; if (params == NULL || params->p == NULL || params->q == NULL) - return FFC_PARAMS_RET_STATUS_FAILED; + return FFC_PARAM_RET_STATUS_FAILED; /* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */ L = BN_num_bits(params->p); N = BN_num_bits(params->q); - return ffc_params_FIPS186_4_gen_verify(NULL, (FFC_PARAMS *)params, type, L, N, - evpmd, validate_flags, res, cb); + return ffc_params_FIPS186_4_gen_verify(libctx, (FFC_PARAMS *)params, + FFC_PARAM_MODE_VERIFY, type, + L, N, res, cb); } /* This may be used in FIPS mode to validate deprecated FIPS-186-2 Params */ -int ffc_params_FIPS186_2_validate(const FFC_PARAMS *params, int type, - const EVP_MD *evpmd, int validate_flags, - int *res, BN_GENCB *cb) +int ffc_params_FIPS186_2_validate(OPENSSL_CTX *libctx, const FFC_PARAMS *params, + int type, int *res, BN_GENCB *cb) { size_t L, N; if (params->p == NULL || params->q == NULL) { *res = FFC_CHECK_INVALID_PQ; - return FFC_PARAMS_RET_STATUS_FAILED; + return FFC_PARAM_RET_STATUS_FAILED; } /* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */ L = BN_num_bits(params->p); N = BN_num_bits(params->q); - return ffc_params_FIPS186_2_gen_verify(NULL, (FFC_PARAMS *)params, type, L, N, - evpmd, validate_flags, res, cb); + return ffc_params_FIPS186_2_gen_verify(libctx, (FFC_PARAMS *)params, + FFC_PARAM_MODE_VERIFY, type, + L, N, res, cb); } diff --git a/crypto/rsa/build.info b/crypto/rsa/build.info index 984ad775d5..1614996049 100644 --- a/crypto/rsa/build.info +++ b/crypto/rsa/build.info @@ -13,3 +13,7 @@ IF[{- !$disabled{'deprecated-0.9.8'} -}] ENDIF SOURCE[../../providers/libfips.a]=$COMMON + +IF[{- !$disabled{'acvp-tests'} -}] + SOURCE[../../providers/libfips.a]=rsa_acvp_test_params.c +ENDIF \ No newline at end of file diff --git a/crypto/rsa/rsa_acvp_test_params.c b/crypto/rsa/rsa_acvp_test_params.c new file mode 100644 index 0000000000..c1d07cb334 --- /dev/null +++ b/crypto/rsa/rsa_acvp_test_params.c @@ -0,0 +1,167 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include /* memcpy */ +#include +#include +#include "crypto/rsa.h" +#include "rsa_local.h" + +int rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[]) +{ + const OSSL_PARAM *p, *s; + OSSL_PARAM *d, *alloc = NULL; + int ret = 1; + + static const OSSL_PARAM settable[] = { + OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP1, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP2, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ1, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ2, NULL, 0), + OSSL_PARAM_END + }; + + /* Assume the first element is a required field if this feature is used */ + p = OSSL_PARAM_locate_const(src, settable[0].key); + if (p == NULL) + return 1; + + /* Zeroing here means the terminator is always set at the end */ + alloc = OPENSSL_zalloc(sizeof(settable)); + if (alloc == NULL) + return 0; + + d = alloc; + for (s = settable; s->key != NULL; ++s) { + /* If src contains a key from settable then copy the src to the dest */ + p = OSSL_PARAM_locate_const(src, s->key); + if (p != NULL) { + *d = *s; /* shallow copy from the static settable[] */ + d->data_size = p->data_size; + d->data = OPENSSL_memdup(p->data, p->data_size); + if (d->data == NULL) + ret = 0; + ++d; + } + } + if (ret == 0) { + rsa_acvp_test_gen_params_free(alloc); + alloc = NULL; + } + if (*dst != NULL) + rsa_acvp_test_gen_params_free(*dst); + *dst = alloc; + return ret; +} + +void rsa_acvp_test_gen_params_free(OSSL_PARAM *dst) +{ + OSSL_PARAM *p; + + if (dst == NULL) + return; + + for (p = dst; p->key != NULL; ++p) { + OPENSSL_free(p->data); + p->data = NULL; + } + OPENSSL_free(dst); +} + +int rsa_acvp_test_set_params(RSA *r, const OSSL_PARAM params[]) +{ + RSA_ACVP_TEST *t; + const OSSL_PARAM *p; + + if (r->acvp_test != NULL) { + rsa_acvp_test_free(r->acvp_test); + r->acvp_test = NULL; + } + + t = OPENSSL_zalloc(sizeof(*t)); + if (t == NULL) + return 0; + + /* Set the input parameters */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP1)) != NULL + && !OSSL_PARAM_get_BN(p, &t->Xp1)) + goto err; + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP2)) != NULL + && !OSSL_PARAM_get_BN(p, &t->Xp2)) + goto err; + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP)) != NULL + && !OSSL_PARAM_get_BN(p, &t->Xp)) + goto err; + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ1)) != NULL + && !OSSL_PARAM_get_BN(p, &t->Xq1)) + goto err; + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ2)) != NULL + && !OSSL_PARAM_get_BN(p, &t->Xq2)) + goto err; + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ)) != NULL + && !OSSL_PARAM_get_BN(p, &t->Xq)) + goto err; + + /* Setup the output parameters */ + t->p1 = BN_new(); + t->p2 = BN_new(); + t->q1 = BN_new(); + t->q2 = BN_new(); + r->acvp_test = t; + return 1; +err: + rsa_acvp_test_free(t); + return 0; +} + +int rsa_acvp_test_get_params(RSA *r, OSSL_PARAM params[]) +{ + RSA_ACVP_TEST *t; + OSSL_PARAM *p; + + if (r == NULL) + return 0; + + t = r->acvp_test; + if (t != NULL) { + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P1)) != NULL + && !OSSL_PARAM_set_BN(p, t->p1)) + return 0; + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P2)) != NULL + && !OSSL_PARAM_set_BN(p, t->p2)) + return 0; + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q1)) != NULL + && !OSSL_PARAM_set_BN(p, t->q1)) + return 0; + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q2)) != NULL + && !OSSL_PARAM_set_BN(p, t->q2)) + return 0; + } + return 1; +} + +void rsa_acvp_test_free(RSA_ACVP_TEST *t) +{ + if (t != NULL) { + BN_free(t->Xp1); + BN_free(t->Xp2); + BN_free(t->Xp); + BN_free(t->Xq1); + BN_free(t->Xq2); + BN_free(t->Xq); + BN_free(t->p1); + BN_free(t->p2); + BN_free(t->q1); + BN_free(t->q2); + OPENSSL_free(t); + } +} + diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index 7497a8579c..985a21127a 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -88,6 +88,7 @@ int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]) goto err; } + sk_BIGNUM_free(factors); sk_BIGNUM_free(exps); sk_BIGNUM_free(coeffs); @@ -126,7 +127,7 @@ int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) int numcoeffs = sk_BIGNUM_const_num(coeffs); /* - * It's permisssible to have zero primes, i.e. no CRT params. + * It's permissible to have zero primes, i.e. no CRT params. * Otherwise, there must be at least two, as many exponents, * and one coefficient less. */ @@ -145,6 +146,11 @@ int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) || !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_coeff_names, coeffs)) goto err; +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + /* The acvp test results are not meant for export so check for bld == NULL */ + if (bld == NULL) + rsa_acvp_test_get_params(rsa, params); +#endif ret = 1; err: sk_BIGNUM_const_free(factors); diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c index e52bce6355..1495cefa83 100644 --- a/crypto/rsa/rsa_gen.c +++ b/crypto/rsa/rsa_gen.c @@ -66,8 +66,8 @@ int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, else return 0; } -#endif /* FIPS_MODULE */ - return rsa_keygen(NULL, rsa, bits, primes, e_value, cb, 0); +#endif /* FIPS_MODUKE */ + return rsa_keygen(rsa->libctx, rsa, bits, primes, e_value, cb, 0); } #ifndef FIPS_MODULE diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index e80416ed3f..428cd145fa 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -162,6 +162,11 @@ void RSA_free(RSA *r) BN_clear_free(r->dmp1); BN_clear_free(r->dmq1); BN_clear_free(r->iqmp); + +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + rsa_acvp_test_free(r->acvp_test); +#endif + #ifndef FIPS_MODULE RSA_PSS_PARAMS_free(r->pss); sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free); diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h index 65fd6022f7..666e18ec65 100644 --- a/crypto/rsa/rsa_local.h +++ b/crypto/rsa/rsa_local.h @@ -10,7 +10,7 @@ #ifndef OSSL_CRYPTO_RSA_LOCAL_H #define OSSL_CRYPTO_RSA_LOCAL_H -#include +#include "crypto/rsa.h" #include "internal/refcount.h" #include "crypto/rsa.h" @@ -29,6 +29,24 @@ typedef struct rsa_prime_info_st { DECLARE_ASN1_ITEM(RSA_PRIME_INFO) DEFINE_STACK_OF(RSA_PRIME_INFO) +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) +struct rsa_acvp_test_st { + /* optional inputs */ + BIGNUM *Xp1; + BIGNUM *Xp2; + BIGNUM *Xq1; + BIGNUM *Xq2; + BIGNUM *Xp; + BIGNUM *Xq; + + /* optional outputs */ + BIGNUM *p1; + BIGNUM *p2; + BIGNUM *q1; + BIGNUM *q2; +}; +#endif + struct rsa_st { /* * #legacy @@ -58,12 +76,14 @@ struct rsa_st { */ /* This is used uniquely by OpenSSL provider implementations. */ RSA_PSS_PARAMS_30 pss_params; -#ifndef FIPS_MODULE - /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */ - RSA_PSS_PARAMS *pss; + +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + RSA_ACVP_TEST *acvp_test; #endif #ifndef FIPS_MODULE + /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */ + RSA_PSS_PARAMS *pss; /* for multi-prime RSA, defined in RFC 8017 */ STACK_OF(RSA_PRIME_INFO) *prime_infos; /* Be careful using this if the RSA structure is shared */ @@ -172,13 +192,9 @@ int rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed, int rsa_sp800_56b_derive_params_from_pq(RSA *rsa, int nbits, const BIGNUM *e, BN_CTX *ctx); -int rsa_fips186_4_gen_prob_primes(RSA *rsa, BIGNUM *p1, BIGNUM *p2, - BIGNUM *Xpout, const BIGNUM *Xp, - const BIGNUM *Xp1, const BIGNUM *Xp2, - BIGNUM *q1, BIGNUM *q2, BIGNUM *Xqout, - const BIGNUM *Xq, const BIGNUM *Xq1, - const BIGNUM *Xq2, int nbits, - const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb); +int rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test, + int nbits, const BIGNUM *e, BN_CTX *ctx, + BN_GENCB *cb); int rsa_padding_add_SSLv23_with_libctx(OPENSSL_CTX *libctx, unsigned char *to, int tlen, const unsigned char *from, diff --git a/crypto/rsa/rsa_sp800_56b_gen.c b/crypto/rsa/rsa_sp800_56b_gen.c index d1673d5c98..9d7e1f1ebf 100644 --- a/crypto/rsa/rsa_sp800_56b_gen.c +++ b/crypto/rsa/rsa_sp800_56b_gen.c @@ -10,6 +10,7 @@ #include #include +#include #include "crypto/bn.h" #include "crypto/security_bits.h" #include "rsa_local.h" @@ -25,20 +26,23 @@ * * Params: * rsa Object used to store primes p & q. - * p1, p2 The returned auxiliary primes for p. If NULL they are not returned. - * Xpout An optionally returned random number used during generation of p. - * Xp An optional passed in value (that is random number used during - * generation of p). - * Xp1, Xp2 Optionally passed in randomly generated numbers from which - * auxiliary primes p1 & p2 are calculated. If NULL these values - * are generated internally. - * q1, q2 The returned auxiliary primes for q. If NULL they are not returned. - * Xqout An optionally returned random number used during generation of q. - * Xq An optional passed in value (that is random number used during - * generation of q). - * Xq1, Xq2 Optionally passed in randomly generated numbers from which - * auxiliary primes q1 & q2 are calculated. If NULL these values - * are generated internally. + * test Object used for CAVS testing only.that contains.. + * p1, p2 The returned auxiliary primes for p. + * If NULL they are not returned. + * Xpout An optionally returned random number used during generation of p. + * Xp An optional passed in value (that is random number used during + * generation of p). + * Xp1, Xp2 Optionally passed in randomly generated numbers from which + * auxiliary primes p1 & p2 are calculated. If NULL these values + * are generated internally. + * q1, q2 The returned auxiliary primes for q. + * If NULL they are not returned. + * Xqout An optionally returned random number used during generation of q. + * Xq An optional passed in value (that is random number used during + * generation of q). + * Xq1, Xq2 Optionally passed in randomly generated numbers from which + * auxiliary primes q1 & q2 are calculated. If NULL these values + * are generated internally. * nbits The key size in bits (The size of the modulus n). * e The public exponent. * ctx A BN_CTX object. @@ -49,16 +53,34 @@ * Xp, Xp1, Xp2, Xq, Xq1, Xq2 are optionally passed in. * (Required for CAVS testing). */ -int rsa_fips186_4_gen_prob_primes(RSA *rsa, BIGNUM *p1, BIGNUM *p2, - BIGNUM *Xpout, const BIGNUM *Xp, - const BIGNUM *Xp1, const BIGNUM *Xp2, - BIGNUM *q1, BIGNUM *q2, BIGNUM *Xqout, - const BIGNUM *Xq, const BIGNUM *Xq1, - const BIGNUM *Xq2, int nbits, +int rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test, int nbits, const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb) { int ret = 0, ok; + /* Temp allocated BIGNUMS */ BIGNUM *Xpo = NULL, *Xqo = NULL, *tmp = NULL; + /* Intermediate BIGNUMS that can be returned for testing */ + BIGNUM *p1 = NULL, *p2 = NULL; + BIGNUM *q1 = NULL, *q2 = NULL; + /* Intermediate BIGNUMS that can be input for testing */ + BIGNUM *Xpout = NULL, *Xqout = NULL; + BIGNUM *Xp = NULL, *Xp1 = NULL, *Xp2 = NULL; + BIGNUM *Xq = NULL, *Xq1 = NULL, *Xq2 = NULL; + +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + if (test != NULL) { + Xp1 = test->Xp1; + Xp2 = test->Xp2; + Xq1 = test->Xq1; + Xq2 = test->Xq2; + Xp = test->Xp; + Xq = test->Xq; + p1 = test->p1; + p2 = test->p2; + q1 = test->q1; + q2 = test->q2; + } +#endif /* (Step 1) Check key length * NOTE: SP800-131A Rev1 Disallows key lengths of < 2048 bits for RSA @@ -294,6 +316,11 @@ int rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed, int ok; BN_CTX *ctx = NULL; BIGNUM *e = NULL; + RSA_ACVP_TEST *info = NULL; + +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + info = rsa->acvp_test; +#endif /* (Steps 1a-1b) : Currently ignores the strength check */ if (!rsa_sp800_56b_validate_strength(nbits, -1)) @@ -311,13 +338,12 @@ int rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed, } else { e = (BIGNUM *)efixed; } - /* (Step 1c) fixed exponent is checked later . */ + /* (Step 1c) fixed exponent is checked later .*/ for (;;) { /* (Step 2) Generate prime factors */ - if (!rsa_fips186_4_gen_prob_primes(rsa, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, nbits, e, ctx, cb)) + if (!rsa_fips186_4_gen_prob_primes(rsa, info, nbits, e, ctx, + cb)) goto err; /* (Steps 3-5) Compute params d, n, dP, dQ, qInv */ ok = rsa_sp800_56b_derive_params_from_pq(rsa, nbits, e, ctx); -- cgit v1.2.3