From b8237707d483719e527313cc007c09e96ef7d778 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Sat, 29 Aug 2020 12:54:00 +1000 Subject: Add fips checks for dh key agreement Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/12745) --- providers/implementations/exchange/build.info | 5 ++- providers/implementations/exchange/dh_exch.c | 47 +++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 5 deletions(-) (limited to 'providers') diff --git a/providers/implementations/exchange/build.info b/providers/implementations/exchange/build.info index 92932b9d28..3ae86309c7 100644 --- a/providers/implementations/exchange/build.info +++ b/providers/implementations/exchange/build.info @@ -1,13 +1,12 @@ # We make separate GOAL variables for each algorithm, to make it easy to # switch each to the Legacy provider when needed. -$DH_GOAL=../../libimplementations.a $ECX_GOAL=../../libimplementations.a -$ECDH_GOAL=../../libimplementations.a $KDF_GOAL=../../libimplementations.a IF[{- !$disabled{dh} -}] - SOURCE[$DH_GOAL]=dh_exch.c + SOURCE[../../libfips.a]=dh_exch.c + SOURCE[../../libnonfips.a]=dh_exch.c ENDIF IF[{- !$disabled{asm} -}] diff --git a/providers/implementations/exchange/dh_exch.c b/providers/implementations/exchange/dh_exch.c index fad38ec93d..a8a0d43319 100644 --- a/providers/implementations/exchange/dh_exch.c +++ b/providers/implementations/exchange/dh_exch.c @@ -23,6 +23,7 @@ #include "prov/providercommon.h" #include "prov/implementations.h" #include "prov/provider_ctx.h" +#include "prov/provider_util.h" #include "crypto/dh.h" static OSSL_FUNC_keyexch_newctx_fn dh_newctx; @@ -91,6 +92,43 @@ static void *dh_newctx(void *provctx) return pdhctx; } +/* + * For DH key agreement refer to SP800-56A + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf + * "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and + * "Appendix D" FFC Safe-prime Groups + */ +static int dh_check_key(const DH *dh) +{ +#ifdef FIPS_MODULE + size_t L, N; + const BIGNUM *p, *q; + + if (dh == NULL) + return 0; + + p = DH_get0_p(dh); + q = DH_get0_q(dh); + if (p == NULL || q == NULL) + return 0; + + L = BN_num_bits(p); + if (L < 2048) + return 0; + + /* If it is a safe prime group then it is ok */ + if (DH_get_nid(dh)) + return 1; + + /* If not then it must be FFC, which only allows certain sizes. */ + N = BN_num_bits(q); + + return (L == 2048 && (N == 224 || N == 256)); +#else + return 1; +#endif +} + static int dh_init(void *vpdhctx, void *vdh) { PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; @@ -103,7 +141,7 @@ static int dh_init(void *vpdhctx, void *vdh) DH_free(pdhctx->dh); pdhctx->dh = vdh; pdhctx->kdf_type = PROV_DH_KDF_NONE; - return 1; + return dh_check_key(vdh); } static int dh_set_peer(void *vpdhctx, void *vdh) @@ -320,7 +358,12 @@ static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[]) EVP_MD_free(pdhctx->kdf_md); pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops); - +#ifdef FIPS_MODULE + if (!ossl_prov_digest_get_approved_nid(pdhctx->kdf_md, 1)) { + EVP_MD_free(pdhctx->kdf_md); + pdhctx->kdf_md = NULL; + } +#endif if (pdhctx->kdf_md == NULL) return 0; } -- cgit v1.2.3