Skip to content

Commit

Permalink
fixup! fips: add pairwise consistency test for ML-KEM key generation
Browse files Browse the repository at this point in the history
  • Loading branch information
paulidale committed Jan 10, 2025
1 parent c27841a commit 5261405
Showing 1 changed file with 75 additions and 63 deletions.
138 changes: 75 additions & 63 deletions providers/implementations/keymgmt/ml_kem_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,72 @@ typedef struct ml_kem_gen_ctx_st {
uint8_t *seed;
} PROV_ML_KEM_GEN_CTX;

#ifdef FIPS_MODULE
static int ml_kem_pairwise_test(const ML_KEM_KEY *key)
{
int ret = 0;
OSSL_SELF_TEST *st = NULL;
OSSL_CALLBACK *cb = NULL;
void *cbarg = NULL;
unsigned char secret[ML_KEM_SHARED_SECRET_BYTES];
unsigned char out[ML_KEM_SHARED_SECRET_BYTES];
unsigned char entropy[ML_KEM_RANDOM_BYTES];
unsigned char *ctext = NULL;
const ML_KEM_VINFO *v = ossl_ml_kem_key_vinfo(key);
int operation_result = 0;

/* Unless we have both a public and private key, we can't do the test */
if (!ossl_ml_kem_have_prvkey(key) || !ossl_ml_kem_have_pubkey(key))
return 1;

/*
* The functions `OSSL_SELF_TEST_*` will return directly if parameter `st`
* is NULL.
*/
OSSL_SELF_TEST_get_callback(key->libctx, &cb, &cbarg);

st = OSSL_SELF_TEST_new(cb, cbarg);
if (st == NULL)
return 0;

OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
OSSL_SELF_TEST_DESC_PCT_ML_KEM);

/*
* Initialise output buffers to avoid collecting random stack memory.
* The `entropy' buffer is filled with an arbitrary non-zero value.
*/
memset(out, 0, sizeof(out));
memset(entropy, 0125, sizeof(entropy));

ctext = OPENSSL_malloc(v->ctext_bytes);
if (ctext == NULL)
goto err;

operation_result = ossl_ml_kem_encap_seed(ctext, v->ctext_bytes,
secret, sizeof(secret),
entropy, sizeof(entropy),
key);
if (operation_result != 1)
goto err;

OSSL_SELF_TEST_oncorrupt_byte(st, ctext);

operation_result = ossl_ml_kem_decap(out, sizeof(out), ctext, v->ctext_bytes,
key);
if (operation_result != 1
|| memcmp(out, secret, sizeof(out)) != 0)
goto err;

ret = 1;
err:
OPENSSL_free(ctext);
OSSL_SELF_TEST_onend(st, ret);
OSSL_SELF_TEST_free(st);
return ret;
}
#endif /* FIPS_MODULE */

static void *ml_kem_new(OSSL_LIB_CTX *libctx, char *propq, int variant)
{
if (!ossl_prov_is_running())
Expand Down Expand Up @@ -244,6 +310,7 @@ static int ml_kem_import(void *vkey, int selection, const OSSL_PARAM params[])
{
ML_KEM_KEY *key = vkey;
int include_private;
int res;

if (!ossl_prov_is_running() || key == NULL)
return 0;
Expand All @@ -252,7 +319,14 @@ static int ml_kem_import(void *vkey, int selection, const OSSL_PARAM params[])
return 0;

include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
return ml_kem_key_fromdata(key, params, include_private);
res = ml_kem_key_fromdata(key, params, include_private);
#ifdef FIPS_MODULE
if (res > 0 && include_private && !ml_kem_pairwise_test(key)) {
ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
res = 0;
}
#endif /* FIPS_MODULE */
return res;
}

static const OSSL_PARAM *ml_kem_gettable_params(void *provctx)
Expand Down Expand Up @@ -436,68 +510,6 @@ static const OSSL_PARAM *ml_kem_gen_settable_params(ossl_unused void *vgctx,
return settable;
}

#ifdef FIPS_MODULE
static int ml_kem_pairwise_test(const ML_KEM_KEY *key)
{
int ret = 0;
OSSL_SELF_TEST *st = NULL;
OSSL_CALLBACK *cb = NULL;
void *cbarg = NULL;
unsigned char secret[ML_KEM_SHARED_SECRET_BYTES];
unsigned char out[ML_KEM_SHARED_SECRET_BYTES];
unsigned char entropy[ML_KEM_RANDOM_BYTES];
unsigned char *ctext = NULL;
const ML_KEM_VINFO *v = ossl_ml_kem_key_vinfo(key);
int operation_result = 0;

/*
* The functions `OSSL_SELF_TEST_*` will return directly if parameter `st`
* is NULL.
*/
OSSL_SELF_TEST_get_callback(key->libctx, &cb, &cbarg);

st = OSSL_SELF_TEST_new(cb, cbarg);
if (st == NULL)
return 0;

OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
OSSL_SELF_TEST_DESC_PCT_ML_KEM);

/*
* Initialise output buffers to avoid collecting random stack memory.
* The `entropy' buffer is filled with an arbitrary non-zero value.
*/
memset(out, 0, sizeof(out));
memset(entropy, 0125, sizeof(entropy));

ctext = OPENSSL_malloc(v->ctext_bytes);
if (ctext == NULL)
goto err;

operation_result = ossl_ml_kem_encap_seed(ctext, v->ctext_bytes,
secret, sizeof(secret),
entropy, sizeof(entropy),
key);
if (operation_result != 1)
goto err;

OSSL_SELF_TEST_oncorrupt_byte(st, ctext);

operation_result = ossl_ml_kem_decap(out, sizeof(out), ctext, v->ctext_bytes,
key);
if (operation_result != 1
|| memcmp(out, secret, sizeof(out)) != 0)
goto err;

ret = 1;
err:
OPENSSL_free(ctext);
OSSL_SELF_TEST_onend(st, ret);
OSSL_SELF_TEST_free(st);
return ret;
}
#endif /* FIPS_MODULE */

static void *ml_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
PROV_ML_KEM_GEN_CTX *gctx = vgctx;
Expand Down

0 comments on commit 5261405

Please sign in to comment.