Reject private keys with an incorrect pk hash

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/26674)
This commit is contained in:
Viktor Dukhovni 2025-02-09 13:41:04 +11:00 committed by Tomas Mraz
parent 3138976041
commit 8cc7ebf6fe
4 changed files with 31 additions and 5 deletions

View File

@ -764,6 +764,7 @@ int ossl_ml_dsa_sk_decode(ML_DSA_KEY *key, const uint8_t *in, size_t in_len)
DECODE_FN *decode_fn;
const ML_DSA_PARAMS *params = key->params;
size_t i, k = params->k, l = params->l;
uint8_t input_tr[ML_DSA_TR_BYTES];
PACKET pkt;
/* When loading from an explicit key, drop the seed. */
@ -788,7 +789,7 @@ int ossl_ml_dsa_sk_decode(ML_DSA_KEY *key, const uint8_t *in, size_t in_len)
if (!PACKET_buf_init(&pkt, in, in_len)
|| !PACKET_copy_bytes(&pkt, key->rho, sizeof(key->rho))
|| !PACKET_copy_bytes(&pkt, key->K, sizeof(key->K))
|| !PACKET_copy_bytes(&pkt, key->tr, sizeof(key->tr)))
|| !PACKET_copy_bytes(&pkt, input_tr, sizeof(input_tr)))
return 0;
for (i = 0; i < l; ++i)
@ -805,7 +806,17 @@ int ossl_ml_dsa_sk_decode(ML_DSA_KEY *key, const uint8_t *in, size_t in_len)
if (key->priv_encoding == NULL
&& (key->priv_encoding = OPENSSL_memdup(in, in_len)) == NULL)
return 0;
return ossl_ml_dsa_key_public_from_private(key);
/*
* Computing the public key also computes its hash, which must be equal to
* the |tr| value in the private key, else the key was corrupted.
*/
if (ossl_ml_dsa_key_public_from_private(key) != 0
&& memcmp(input_tr, key->tr, sizeof(input_tr)) == 0)
return 1;
/* On error, reset the key back to uninitialised. */
ossl_ml_dsa_key_reset(key);
return 0;
}
/*

View File

@ -132,7 +132,7 @@ int ossl_ml_dsa_key_priv_alloc(ML_DSA_KEY *key)
}
/**
* @brief Destroy a ML_DSA_KEY object
* @brief Destroy an ML_DSA_KEY object
*/
void ossl_ml_dsa_key_free(ML_DSA_KEY *key)
{
@ -141,6 +141,15 @@ void ossl_ml_dsa_key_free(ML_DSA_KEY *key)
EVP_MD_free(key->shake128_md);
EVP_MD_free(key->shake256_md);
ossl_ml_dsa_key_reset(key);
OPENSSL_free(key);
}
/**
* @brief Factory reset an ML_DSA_KEY object
*/
void ossl_ml_dsa_key_reset(ML_DSA_KEY *key)
{
vector_zero(&key->s2);
vector_zero(&key->s1);
vector_zero(&key->t0);
@ -148,11 +157,13 @@ void ossl_ml_dsa_key_free(ML_DSA_KEY *key)
vector_free(&key->t1);
OPENSSL_cleanse(key->K, sizeof(key->K));
OPENSSL_free(key->pub_encoding);
key->pub_encoding = NULL;
if (key->priv_encoding != NULL)
OPENSSL_clear_free(key->priv_encoding, key->params->sk_len);
key->priv_encoding = NULL;
if (key->seed != NULL)
OPENSSL_clear_free(key->seed, ML_DSA_SEED_BYTES);
OPENSSL_free(key);
key->seed = NULL;
}
/**

View File

@ -70,6 +70,8 @@ const ML_DSA_PARAMS *ossl_ml_dsa_params_get(int evp_type);
const ML_DSA_PARAMS *ossl_ml_dsa_key_params(const ML_DSA_KEY *key);
__owur ML_DSA_KEY *ossl_ml_dsa_key_new(OSSL_LIB_CTX *libctx, const char *propq,
int evp_type);
/* Factory reset for keys that fail initialisation */
void ossl_ml_dsa_key_reset(ML_DSA_KEY *key);
__owur int ossl_ml_dsa_key_pub_alloc(ML_DSA_KEY *key);
__owur int ossl_ml_dsa_key_priv_alloc(ML_DSA_KEY *key);
void ossl_ml_dsa_key_free(ML_DSA_KEY *key);

View File

@ -255,8 +255,10 @@ static int ml_dsa_import(void *keydata, int selection, const OSSL_PARAM params[]
#ifdef FIPS_MODULE
if (res > 0) {
res = ml_dsa_pairwise_test(key);
if (res <= 0)
if (res <= 0) {
ossl_ml_dsa_key_reset(key);
ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
}
}
#endif
return res;