diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-07-09 13:43:10 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-07-09 13:43:10 +1000 |
commit | 63794b048cbe46ac9abb883df4dd703f522e4643 (patch) | |
tree | 62a0882fc7e5be0e4579440468fb412684636bad /crypto | |
parent | eae4a008341149783b540198470f04f85b22730e (diff) |
Add multiple fixes for ffc key generation using invalid p,q,g parameters.
Fixes #11864
- The dsa keygen assumed valid p, q, g values were being passed. If this is not correct then it is
possible that dsa keygen can either hang or segfault.
The fix was to do a partial validation of p, q, and g inside the keygen.
- Fixed a potential double free in the dsa keypair test in the case when in failed (It should never fail!).
It freed internal object members without setting them to NULL.
- Changed the FFC key validation to accept 1024 bit keys in non fips mode.
- Added tests that use both the default provider & fips provider to test these cases.
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/12176)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/dh/dh_key.c | 4 | ||||
-rw-r--r-- | crypto/dsa/dsa_key.c | 7 | ||||
-rw-r--r-- | crypto/ffc/ffc_params_generate.c | 11 | ||||
-rw-r--r-- | crypto/ffc/ffc_params_validate.c | 26 |
4 files changed, 47 insertions, 1 deletions
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index 5d2acca25c..3b4da19cd2 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -287,6 +287,10 @@ static int generate_key(DH *dh) } else #endif { + /* Do a partial check for invalid p, q, g */ + if (!ffc_params_simple_validate(dh->libctx, &dh->params, + FFC_PARAM_TYPE_DH)) + goto err; /* * For FFC FIPS 186-4 keygen * security strength s = 112, diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index 7bd9c5ff2e..b537ec0b3c 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -74,6 +74,11 @@ static int dsa_keygen(DSA *dsa, int pairwise_test) priv_key = dsa->priv_key; } + /* Do a partial check for invalid p, q, g */ + if (!ffc_params_simple_validate(dsa->libctx, &dsa->params, + FFC_PARAM_TYPE_DSA)) + goto err; + /* * For FFC FIPS 186-4 keygen * security strength s = 112, @@ -110,6 +115,8 @@ static int dsa_keygen(DSA *dsa, int pairwise_test) if (!ok) { BN_free(dsa->pub_key); BN_clear_free(dsa->priv_key); + dsa->pub_key = NULL; + dsa->priv_key = NULL; BN_CTX_free(ctx); return ok; } diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c index 325eb6768f..8a0b77e7f8 100644 --- a/crypto/ffc/ffc_params_generate.c +++ b/crypto/ffc/ffc_params_generate.c @@ -39,6 +39,11 @@ */ static int ffc_validate_LN(size_t L, size_t N, int type) { +#ifndef FIPS_MODULE + if (L == 1024 && N == 160) + return 80; +#endif + if (type == FFC_PARAM_TYPE_DH) { /* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */ if (L == 2048 && (N == 224 || N == 256)) @@ -498,6 +503,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, EVP_MD *md = NULL; int verify = (mode == FFC_PARAM_MODE_VERIFY); unsigned int flags = verify ? params->flags : 0; + const char *def_name; *res = 0; @@ -506,7 +512,10 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, } else { if (N == 0) N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8; - md = EVP_MD_fetch(libctx, default_mdname(N), NULL); + def_name = default_mdname(N); + if (def_name == NULL) + goto err; + md = EVP_MD_fetch(libctx, def_name, NULL); } if (md == NULL) goto err; diff --git a/crypto/ffc/ffc_params_validate.c b/crypto/ffc/ffc_params_validate.c index f3df0c2b39..821ff3e88a 100644 --- a/crypto/ffc/ffc_params_validate.c +++ b/crypto/ffc/ffc_params_validate.c @@ -78,3 +78,29 @@ int ffc_params_FIPS186_2_validate(OPENSSL_CTX *libctx, const FFC_PARAMS *params, FFC_PARAM_MODE_VERIFY, type, L, N, res, cb); } + +/* + * This does a simple check of L and N and partial g. + * It makes no attempt to do a full validation of p, q or g since these require + * extra parameters such as the digest and seed, which may not be available for + * this test. + */ +int ffc_params_simple_validate(OPENSSL_CTX *libctx, FFC_PARAMS *params, int type) +{ + int ret, res = 0; + int save_gindex; + unsigned int save_flags; + + if (params == NULL) + return 0; + + save_flags = params->flags; + save_gindex = params->gindex; + params->flags = FFC_PARAM_FLAG_VALIDATE_G; + params->gindex = FFC_UNVERIFIABLE_GINDEX; + + ret = ffc_params_FIPS186_4_validate(libctx, params, type, &res, NULL); + params->flags = save_flags; + params->gindex = save_gindex; + return ret != FFC_PARAM_RET_STATUS_FAILED; +} |