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 <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28122)
This commit is contained in:
Pauli 2025-01-31 10:38:28 +11:00 committed by Tomas Mraz
parent 88a1309566
commit db969c3ab0
3 changed files with 47 additions and 5 deletions

View File

@ -16,6 +16,7 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/self_test.h>
#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;
}

View File

@ -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);

View File

@ -19,10 +19,12 @@
#include <openssl/core_names.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/self_test.h>
#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;
}