From: Pauli Date: Thu, 30 Jan 2025 23:38:28 +0000 (+1100) Subject: dh: add FIPS 140-3 PCT on key import. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=db969c3ab08240cf9652cb621fbf1936d056464c;p=thirdparty%2Fopenssl.git dh: add FIPS 140-3 PCT on key import. This is mandated by FIPS 140-3 IG 10.3.A additional comment 1 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/28122) --- diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index ae23f61839e..1993f8674b2 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -16,6 +16,7 @@ #include #include "internal/cryptlib.h" #include +#include #include "dh_local.h" #include "crypto/dh.h" @@ -329,17 +330,27 @@ end: * FFC pairwise check from SP800-56A R3. * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency */ -int ossl_dh_check_pairwise(const DH *dh) +int ossl_dh_check_pairwise(const DH *dh, int return_on_null_numbers) { int ret = 0; BN_CTX *ctx = NULL; BIGNUM *pub_key = NULL; + OSSL_SELF_TEST *st = NULL; + OSSL_CALLBACK *stcb = NULL; + void *stcbarg = NULL; if (dh->params.p == NULL || dh->params.g == NULL || dh->priv_key == NULL || dh->pub_key == NULL) - return 0; + return return_on_null_numbers; + + OSSL_SELF_TEST_get_callback(dh->libctx, &stcb, &stcbarg); + st = OSSL_SELF_TEST_new(stcb, stcbarg); + if (st == NULL) + goto err; + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, + OSSL_SELF_TEST_DESC_PCT_DH); ctx = BN_CTX_new_ex(dh->libctx); if (ctx == NULL) @@ -351,10 +362,27 @@ int ossl_dh_check_pairwise(const DH *dh) /* recalculate the public key = (g ^ priv) mod p */ if (!ossl_dh_generate_public_key(ctx, dh, dh->priv_key, pub_key)) goto err; + +#ifdef FIPS_MODULE + { + int len; + unsigned char bytes[1024] = {0}; /* Max key size of 8192 bits */ + + if (BN_num_bytes(pub_key) > (int)sizeof(bytes)) + goto err; + len = BN_bn2bin(pub_key, bytes); + OSSL_SELF_TEST_oncorrupt_byte(st, bytes); + if (BN_bin2bn(bytes, len, pub_key) == NULL) + goto err; + } +#endif /* check it matches the existing public_key */ ret = BN_cmp(pub_key, dh->pub_key) == 0; -err: + err: BN_free(pub_key); BN_CTX_free(ctx); + + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); return ret; } diff --git a/include/crypto/dh.h b/include/crypto/dh.h index 51232d18c24..624c0bf9cc8 100644 --- a/include/crypto/dh.h +++ b/include/crypto/dh.h @@ -42,7 +42,7 @@ int ossl_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); int ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret); int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret); -int ossl_dh_check_pairwise(const DH *dh); +int ossl_dh_check_pairwise(const DH *dh, int return_on_null_numbers); const DH_METHOD *ossl_dh_get_method(const DH *dh); diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index a8c552c8a55..5afda2eeaac 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -19,10 +19,12 @@ #include #include #include +#include #include "prov/implementations.h" #include "prov/providercommon.h" #include "prov/provider_ctx.h" #include "crypto/dh.h" +#include "internal/fips.h" #include "internal/sizes.h" static OSSL_FUNC_keymgmt_new_fn dh_newdata; @@ -207,6 +209,18 @@ static int dh_import(void *keydata, int selection, const OSSL_PARAM params[]) selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; ok = ok && ossl_dh_key_fromdata(dh, params, include_private); +#ifdef FIPS_MODULE + /* + * FIPS 140-3 IG 10.3.A additional comment 1 mandates that a pairwise + * consistency check be undertaken on key import. The required test + * is described in SP 800-56Ar3 5.6.2.1.4. + */ + if (ok > 0 && !ossl_fips_self_testing()) { + ok = ossl_dh_check_pairwise(dh, 1); + if (ok <= 0) + ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); + } +#endif /* FIPS_MODULE */ } return ok; @@ -444,7 +458,7 @@ static int dh_validate(const void *keydata, int selection, int checktype) if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) - ok = ok && ossl_dh_check_pairwise(dh); + ok = ok && ossl_dh_check_pairwise(dh, 0); return ok; }