CBD_FUNC cbd_1 = CBD1(vinfo->evp_type);
int rank = vinfo->rank;
uint8_t counter = 0;
+ int ret = 0;
/*
* Use the "d" seed salted with the rank to derive the public and private
memcpy(augmented_seed, d, ML_KEM_RANDOM_BYTES);
augmented_seed[ML_KEM_RANDOM_BYTES] = (uint8_t) rank;
if (!hash_g(hashed, augmented_seed, sizeof(augmented_seed), mdctx, key))
- return 0;
+ goto end;
memcpy(key->rho, hashed, ML_KEM_RANDOM_BYTES);
/* The |rho| matrix seed is public */
CONSTTIME_DECLASSIFY(key->rho, ML_KEM_RANDOM_BYTES);
if (!matrix_expand(mdctx, key)
|| !gencbd_vector_ntt(key->s, cbd_1, &counter, sigma, rank, mdctx, key)
|| !gencbd_vector_ntt(key->t, cbd_1, &counter, sigma, rank, mdctx, key))
- return 0;
+ goto end;
/* To |e| we now add the product of transpose |m| and |s|, giving |t|. */
matrix_mult_transpose_add(key->t, key->m, key->s, rank);
if (pubenc == NULL) {
/* Incremental digest of public key without in-full serialisation. */
if (!hash_h_pubkey(key->pkhash, mdctx, key))
- return 0;
+ goto end;
} else {
encode_pubkey(pubenc, key);
if (!hash_h(key->pkhash, pubenc, vinfo->pubkey_bytes, mdctx, key))
- return 0;
+ goto end;
}
/* Save |z| portion of seed for "implicit rejection" on failure. */
memcpy(key->z, z, ML_KEM_RANDOM_BYTES);
/* Also save |d| portion, in suport of likely alternative key format. */
memcpy(key->d = key->z + ML_KEM_RANDOM_BYTES, d, ML_KEM_RANDOM_BYTES);
- return 1;
+
+ ret = 1;
+ end:
+ OPENSSL_cleanse((void *)augmented_seed, ML_KEM_RANDOM_BYTES);
+ OPENSSL_cleanse((void *)sigma, ML_KEM_RANDOM_BYTES);
+ return ret;
}
/*-
uint8_t input[ML_KEM_RANDOM_BYTES + ML_KEM_PKHASH_BYTES];
uint8_t Kr[ML_KEM_SHARED_SECRET_BYTES + ML_KEM_RANDOM_BYTES];
uint8_t *r = Kr + ML_KEM_SHARED_SECRET_BYTES;
+ int ret;
memcpy(input, entropy, ML_KEM_RANDOM_BYTES);
memcpy(input + ML_KEM_RANDOM_BYTES, key->pkhash, ML_KEM_PKHASH_BYTES);
- if (!hash_g(Kr, input, sizeof(input), mdctx, key)
- || !encrypt_cpa(ctext, entropy, r, tmp, mdctx, key))
- return 0;
- memcpy(secret, Kr, ML_KEM_SHARED_SECRET_BYTES);
- return 1;
+ ret = hash_g(Kr, input, sizeof(input), mdctx, key)
+ && encrypt_cpa(ctext, entropy, r, tmp, mdctx, key);
+
+ if (ret)
+ memcpy(secret, Kr, ML_KEM_SHARED_SECRET_BYTES);
+ OPENSSL_cleanse((void *)input, sizeof(input));
+ return ret;
}
/*
if (!hash_g(Kr, decrypted, sizeof(decrypted), mdctx, key)
|| !encrypt_cpa(tmp_ctext, decrypted, r, tmp, mdctx, key)) {
memcpy(secret, failure_key, ML_KEM_SHARED_SECRET_BYTES);
+ OPENSSL_cleanse(decrypted, ML_KEM_SHARED_SECRET_BYTES);
return 1;
}
mask = constant_time_eq_int_8(0,
CRYPTO_memcmp(ctext, tmp_ctext, vinfo->ctext_bytes));
for (i = 0; i < ML_KEM_SHARED_SECRET_BYTES; i++)
secret[i] = constant_time_select_8(mask, Kr[i], failure_key[i]);
+ OPENSSL_cleanse(decrypted, ML_KEM_SHARED_SECRET_BYTES);
+ OPENSSL_cleanse(Kr, sizeof(Kr));
return 1;
}
{
if (key->t == NULL)
return;
+ /*-
+ * Cleanse any sensitive data:
+ * - The private vector |s| is immediately followed by the FO failure
+ * secret |z|, and seed |d|, we can cleanse all three in one call.
+ */
+ if (ossl_ml_kem_have_prvkey(key))
+ OPENSSL_cleanse(key->s,
+ key->vinfo->vector_bytes + 2 * ML_KEM_RANDOM_BYTES);
OPENSSL_free(key->t);
key->d = key->z = (uint8_t *)(key->s = key->m = key->t = NULL);
}
if (key == NULL
|| (ret = OPENSSL_memdup(key, sizeof(*key))) == NULL)
return NULL;
+ ret->d = ret->z = NULL;
+ ret->s = ret->m = ret->t = NULL;
/* Clear selection bits we can't fulfill */
if (!ossl_ml_kem_have_pubkey(key))
switch (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) {
case 0:
- ret->z = (uint8_t *)(ret->s = ret->m = ret->t = NULL);
ok = 1;
break;
case OSSL_KEYMGMT_SELECT_PUBLIC_KEY:
EVP_MD_free(key->sha3_256_md);
EVP_MD_free(key->sha3_512_md);
- /*-
- * Cleanse any sensitive data:
- * - The private vector |s| is immediately followed by the FO failure
- * secret |z|, and seed |d|, we can cleanse all three in one call.
- */
- if (key->s != NULL)
- OPENSSL_cleanse(key->s,
- key->vinfo->vector_bytes + 2 * ML_KEM_RANDOM_BYTES);
-
- /* Free the key material */
- OPENSSL_free(key->t);
+ free_storage(key);
OPENSSL_free(key);
}
scalar tmp[2 * ML_KEM_##bits##_RANK]; \
\
ret = encap(ctext, shared_secret, entropy, tmp, mdctx, key); \
+ OPENSSL_cleanse((void *)tmp, sizeof(tmp)); \
break; \
}
switch (vinfo->evp_type) {
scalar tmp[2 * ML_KEM_##bits##_RANK]; \
\
ret = decap(shared_secret, ctext, cbuf, tmp, mdctx, key); \
+ OPENSSL_cleanse((void *)tmp, sizeof(tmp)); \
break; \
}
switch (vinfo->evp_type) {