mirror of
https://github.com/openssl/openssl.git
synced 2025-03-19 19:50:42 +08:00
Add fips checks for dh key agreement
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/12745)
This commit is contained in:
parent
0645110ebd
commit
b8237707d4
@ -37,14 +37,14 @@
|
||||
* Verify that the passed in L, N pair for DH or DSA is valid.
|
||||
* Returns 0 if invalid, otherwise it returns the security strength.
|
||||
*/
|
||||
static int ffc_validate_LN(size_t L, size_t N, int type)
|
||||
static int ffc_validate_LN(size_t L, size_t N, int type, int verify)
|
||||
{
|
||||
#ifndef FIPS_MODULE
|
||||
if (L == 1024 && N == 160)
|
||||
return 80;
|
||||
#endif
|
||||
|
||||
if (type == FFC_PARAM_TYPE_DH) {
|
||||
#ifndef FIPS_MODULE
|
||||
/* Allow legacy 1024/160 in non fips mode */
|
||||
if (L == 1024 && N == 160)
|
||||
return 80;
|
||||
#endif
|
||||
/* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */
|
||||
if (L == 2048 && (N == 224 || N == 256))
|
||||
return 112;
|
||||
@ -53,8 +53,12 @@ static int ffc_validate_LN(size_t L, size_t N, int type)
|
||||
#endif
|
||||
} else if (type == FFC_PARAM_TYPE_DSA) {
|
||||
/* Valid DSA L,N parameters from FIPS 186-4 Section 4.2 */
|
||||
if (L == 1024 && N == 160)
|
||||
return 80;
|
||||
#ifdef FIPS_MODULE
|
||||
/* In fips mode 1024/160 can only be used for verification */
|
||||
if (verify)
|
||||
#endif
|
||||
if (L == 1024 && N == 160)
|
||||
return 80;
|
||||
if (L == 2048 && (N == 224 || N == 256))
|
||||
return 112;
|
||||
if (L == 3072 && N == 256)
|
||||
@ -513,8 +517,10 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
|
||||
if (N == 0)
|
||||
N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8;
|
||||
def_name = default_mdname(N);
|
||||
if (def_name == NULL)
|
||||
if (def_name == NULL) {
|
||||
*res = FFC_CHECK_INVALID_Q_VALUE;
|
||||
goto err;
|
||||
}
|
||||
md = EVP_MD_fetch(libctx, def_name, NULL);
|
||||
}
|
||||
if (md == NULL)
|
||||
@ -532,7 +538,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
|
||||
* A.1.1.3 Step (3)
|
||||
* Check that the L,N pair is an acceptable pair.
|
||||
*/
|
||||
if (L <= N || !ffc_validate_LN(L, N, type)) {
|
||||
if (L <= N || !ffc_validate_LN(L, N, type, verify)) {
|
||||
*res = FFC_CHECK_BAD_LN_PAIR;
|
||||
goto err;
|
||||
}
|
||||
@ -773,6 +779,7 @@ err:
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Note this function is only used for verification in fips mode */
|
||||
int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
|
||||
int mode, int type, size_t L, size_t N,
|
||||
int *res, BN_GENCB *cb)
|
||||
@ -793,6 +800,7 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
|
||||
size_t seed_len = params->seedlen;
|
||||
int verify = (mode == FFC_PARAM_MODE_VERIFY);
|
||||
unsigned int flags = verify ? params->flags : 0;
|
||||
const char *def_name;
|
||||
|
||||
*res = 0;
|
||||
|
||||
@ -801,7 +809,12 @@ int ffc_params_FIPS186_2_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) {
|
||||
*res = FFC_CHECK_INVALID_Q_VALUE;
|
||||
goto err;
|
||||
}
|
||||
md = EVP_MD_fetch(libctx, def_name, NULL);
|
||||
}
|
||||
if (md == NULL)
|
||||
goto err;
|
||||
@ -809,16 +822,15 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
|
||||
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.
|
||||
* (Even though the original spec allowed L = 512 + 64*j (j = 0.. 8))
|
||||
* The original spec allowed L = 512 + 64*j (j = 0.. 8)
|
||||
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
|
||||
* says that 512 can be used for legacy verification.
|
||||
*/
|
||||
if (L != 1024 || N != 160) {
|
||||
if (L < 512) {
|
||||
*res = FFC_CHECK_BAD_LN_PAIR;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
if (qsize != SHA_DIGEST_LENGTH
|
||||
&& qsize != SHA224_DIGEST_LENGTH
|
||||
&& qsize != SHA256_DIGEST_LENGTH) {
|
||||
@ -827,9 +839,6 @@ int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (L < 512)
|
||||
L = 512;
|
||||
|
||||
L = (L + 63) / 64 * 64;
|
||||
|
||||
if (seed_in != NULL) {
|
||||
|
@ -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} -}]
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user