Skip to content

Commit

Permalink
Add ML-KEM CAST for KeyGen, Encaps, and Decaps (#1846)
Browse files Browse the repository at this point in the history
### Description of changes: 
* Per the I.G guidance a CAST using a KAT is required for ML-KEM key
generation
> if the module implements ML-KEM key generation, the module shall have
an ML-KEM key generation
CAST. The ML-KEM key generation does not take input and outputs an
encapsulation key (ek) and a
decapsulation key (dk). The CAST shall use the ML-KEM key generation
algorithm (i.e., Algorithm
19 in FIPS 203), and for a KAT, using a fixed/predetermined random
values (i.e., z and d), to
compare the resulting outputs to the pre-computed values of ek and dk.
* Per the I.G guidance a CAST using a KAT is required for ML-KEM
encapsulation
> if the module implements ML-KEM encapsulation, the module shall have a
CAST for the ML-KEM
encapsulation mechanism. The encapsulation algorithm of ML-KEM accepts
an encapsulation key
(ek) as input, requires randomness, and outputs a ciphertext (c) and a
shared secret (K). The CAST
shall use the ML-KEM encapsulation algorithm (i.e., Algorithm 20 in FIPS
203), and for a KAT,
using fixed/predetermined ek and m values, to compare the resulting
outputs to pre-computed values
of both c and K.
* Per the I.G. guidance a CAST using two KATs is required for mL-KEM
decapsulation, one to test the non-implicit rejection path, and the
other to test the rejection path.
> if the module implements ML-KEM decapsulation, the module shall have a
CAST for the ML-KEM
decapsulation mechanism. The decapsulation algorithm of ML-KEM accepts a
decapsulation key (dk)
and a ML-KEM ciphertext (c) as input, does not use any randomness, and
outputs a shared secret
(K’). The CAST shall use the ML-KEM decapsulation algorithm (i.e.,
Algorithm 21 in FIPS 203),
and for a KAT, using fixed/predetermined dk and c values, to compare the
resulting outputs to pre-
computed value of K'.
Note21: The ML-KEM decapsulation CASTs shall cover both the implicit
rejection and (unnamed)
non-rejection paths.

The source of the vectors were sourced from the ML-KEM ACVP demo server
vectors that had been previously validated with.

Also only one ML-KEM parameter variant needs to be tested per I.G.:
> Note22: The above CASTs shall be performed on at least one of the
following parameter-sets for ML-
KEM that are implemented in the approved mode: ML-KEM-512, ML-KEM-768,
or ML-KEM-1024.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
  • Loading branch information
skmcgrail authored Sep 11, 2024
1 parent 9a644b2 commit be42edd
Show file tree
Hide file tree
Showing 4 changed files with 749 additions and 2 deletions.
39 changes: 38 additions & 1 deletion crypto/fipsmodule/ml_kem/ml_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "./ml_kem_ref/reduce.c"
#include "./ml_kem_ref/symmetric-shake.c"
#include "./ml_kem_ref/verify.c"
#include "../../internal.h"

// Note: These methods currently default to using the reference code for ML_KEM.
// In a future where AWS-LC has optimized options available, those can be
Expand All @@ -25,13 +26,21 @@
int ml_kem_512_keypair_deterministic(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
return ml_kem_512_keypair_deterministic_no_self_test(public_key, secret_key, seed);
}

int ml_kem_512_keypair_deterministic_no_self_test(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */,
const uint8_t *seed /* IN */) {
ml_kem_params params;
ml_kem_512_params_init(&params);
return ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
}

int ml_kem_512_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_512_params_init(&params);
return ml_kem_keypair_ref(&params, public_key, secret_key);
Expand All @@ -41,14 +50,24 @@ int ml_kem_512_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
return ml_kem_512_encapsulate_deterministic_no_self_test(ciphertext, shared_secret, public_key, seed);
}

int ml_kem_512_encapsulate_deterministic_no_self_test(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */,
const uint8_t *seed /* IN */) {
ml_kem_params params;
ml_kem_512_params_init(&params);
return ml_kem_enc_derand_ref(&params, ciphertext, shared_secret, public_key, seed);
return ml_kem_enc_derand_ref(&params, ciphertext, shared_secret, public_key,
seed);
}

int ml_kem_512_encapsulate(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_512_params_init(&params);
return ml_kem_enc_ref(&params, ciphertext, shared_secret, public_key);
Expand All @@ -57,21 +76,31 @@ int ml_kem_512_encapsulate(uint8_t *ciphertext /* OUT */,
int ml_kem_512_decapsulate(uint8_t *shared_secret /* OUT */,
const uint8_t *ciphertext /* IN */,
const uint8_t *secret_key /* IN */) {
boringssl_ensure_ml_kem_self_test();
return ml_kem_512_decapsulate_no_self_test(shared_secret, ciphertext, secret_key);
}

int ml_kem_512_decapsulate_no_self_test(uint8_t *shared_secret /* OUT */,
const uint8_t *ciphertext /* IN */,
const uint8_t *secret_key /* IN */) {
ml_kem_params params;
ml_kem_512_params_init(&params);
return ml_kem_dec_ref(&params, shared_secret, ciphertext, secret_key);
}


int ml_kem_768_keypair_deterministic(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_768_params_init(&params);
return ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
}

int ml_kem_768_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_768_params_init(&params);
return ml_kem_keypair_ref(&params, public_key, secret_key);
Expand All @@ -81,6 +110,7 @@ int ml_kem_768_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_768_params_init(&params);
return ml_kem_enc_derand_ref(&params, ciphertext, shared_secret, public_key, seed);
Expand All @@ -89,6 +119,7 @@ int ml_kem_768_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
int ml_kem_768_encapsulate(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_768_params_init(&params);
return ml_kem_enc_ref(&params, ciphertext, shared_secret, public_key);
Expand All @@ -97,6 +128,7 @@ int ml_kem_768_encapsulate(uint8_t *ciphertext /* OUT */,
int ml_kem_768_decapsulate(uint8_t *shared_secret /* OUT */,
const uint8_t *ciphertext /* IN */,
const uint8_t *secret_key /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_768_params_init(&params);
return ml_kem_dec_ref(&params, shared_secret, ciphertext, secret_key);
Expand All @@ -105,13 +137,15 @@ int ml_kem_768_decapsulate(uint8_t *shared_secret /* OUT */,
int ml_kem_1024_keypair_deterministic(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_1024_params_init(&params);
return ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
}

int ml_kem_1024_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_1024_params_init(&params);
return ml_kem_keypair_ref(&params, public_key, secret_key);
Expand All @@ -121,6 +155,7 @@ int ml_kem_1024_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_1024_params_init(&params);
return ml_kem_enc_derand_ref(&params, ciphertext, shared_secret, public_key, seed);
Expand All @@ -129,6 +164,7 @@ int ml_kem_1024_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
int ml_kem_1024_encapsulate(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_1024_params_init(&params);
return ml_kem_enc_ref(&params, ciphertext, shared_secret, public_key);
Expand All @@ -137,6 +173,7 @@ int ml_kem_1024_encapsulate(uint8_t *ciphertext /* OUT */,
int ml_kem_1024_decapsulate(uint8_t *shared_secret /* OUT */,
const uint8_t *ciphertext /* IN */,
const uint8_t *secret_key /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
ml_kem_1024_params_init(&params);
return ml_kem_dec_ref(&params, shared_secret, ciphertext, secret_key);
Expand Down
13 changes: 13 additions & 0 deletions crypto/fipsmodule/ml_kem/ml_kem.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ int ml_kem_512_keypair_deterministic(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */,
const uint8_t *seed /* IN */);

int ml_kem_512_keypair_deterministic_no_self_test(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */,
const uint8_t *seed /* IN */);

int ml_kem_512_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */);

Expand All @@ -40,6 +44,11 @@ int ml_kem_512_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
const uint8_t *public_key /* IN */,
const uint8_t *seed /* IN */);

int ml_kem_512_encapsulate_deterministic_no_self_test(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */,
const uint8_t *seed /* IN */);

int ml_kem_512_encapsulate(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
const uint8_t *public_key /* IN */);
Expand All @@ -48,6 +57,10 @@ int ml_kem_512_decapsulate(uint8_t *shared_secret /* OUT */,
const uint8_t *ciphertext /* IN */,
const uint8_t *secret_key /* IN */);

int ml_kem_512_decapsulate_no_self_test(uint8_t *shared_secret /* OUT */,
const uint8_t *ciphertext /* IN */,
const uint8_t *secret_key /* IN */);

int ml_kem_768_keypair_deterministic(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */,
const uint8_t *seed /* IN */);
Expand Down
Loading

0 comments on commit be42edd

Please sign in to comment.