Skip to content

Commit

Permalink
ML-KEM: Move FIPS-abort upon PCT failure to top-level API
Browse files Browse the repository at this point in the history
If AWSLC_FIPS is set, ML-KEM includes a PCT check after key generation,
in compliance with the FIPS-203 IG
https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf
If the PCT fails, AWS_LC_FIPS_failure is called to abort operation.

This commit hoists the call to AWS_LC_FIPS_failure one level up,
into the toplevel ML-KEM API of crypto/fipsmodule/ml_kem/ml_kem.h:
When the PCT fails, the lower-level key generation API that invokes
the PCT returns -1, which is caught by the top-level ML-KEM API
and converted into a call to AWS_LC_FIPS_failure. There is no other
failure condition during key generation.

When the PCT fails in the randomized key generation API, the coins are
still cleansed before propagating the PCT error. It could be considered
whether the PK and SK should be cleansed in this case, too, but this
commit does not change behvaiour in this regard.

The change facilitates replacing the ML-KEM reference implementation,
since only the return-value behaviour needs to be maintained, but an
alternative implementation need not be aware of the abort macro
AWS_LC_FIPS_failure.

Signed-off-by: Hanno Becker <[email protected]>
  • Loading branch information
hanno-becker committed Feb 13, 2025
1 parent 7518c78 commit 5ddb00b
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 12 deletions.
72 changes: 66 additions & 6 deletions crypto/fipsmodule/ml_kem/ml_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,36 @@ 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;
int res;
ml_kem_512_params_init(&params);
return ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
res = ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
#if defined(AWSLC_FIPS)
/* PCT failure is the only failure condition for key generation. */
if (res != 0) {
AWS_LC_FIPS_failure("ML-KEM keygen PCT failed");
}
#else
assert(res == 0);
#endif
return res;
}

int ml_kem_512_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */) {
boringssl_ensure_ml_kem_self_test();
int res;
ml_kem_params params;
ml_kem_512_params_init(&params);
return ml_kem_keypair_ref(&params, public_key, secret_key);
res = ml_kem_keypair_ref(&params, public_key, secret_key);
#if defined(AWSLC_FIPS)
/* PCT failure is the only failure condition for key generation. */
if (res != 0) {
AWS_LC_FIPS_failure("ML-KEM keygen PCT failed");
}
#else
assert(res == 0);
#endif
return res;
}

int ml_kem_512_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
Expand Down Expand Up @@ -94,16 +114,36 @@ int ml_kem_768_keypair_deterministic(uint8_t *public_key /* OUT */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
int res;
ml_kem_768_params_init(&params);
return ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
res = ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
#if defined(AWSLC_FIPS)
/* PCT failure is the only failure condition for key generation. */
if (res != 0) {
AWS_LC_FIPS_failure("ML-KEM keygen PCT failed");
}
#else
assert(res == 0);
#endif
return res;
}

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;
int res;
ml_kem_768_params_init(&params);
return ml_kem_keypair_ref(&params, public_key, secret_key);
res = ml_kem_keypair_ref(&params, public_key, secret_key);
#if defined(AWSLC_FIPS)
/* PCT failure is the only failure condition for key generation. */
if (res != 0) {
AWS_LC_FIPS_failure("ML-KEM keygen PCT failed");
}
#else
assert(res == 0);
#endif
return res;
}

int ml_kem_768_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
Expand Down Expand Up @@ -139,16 +179,36 @@ int ml_kem_1024_keypair_deterministic(uint8_t *public_key /* OUT */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
int res;
ml_kem_1024_params_init(&params);
return ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
res = ml_kem_keypair_derand_ref(&params, public_key, secret_key, seed);
#if defined(AWSLC_FIPS)
/* PCT failure is the only failure condition for key generation. */
if (res != 0) {
AWS_LC_FIPS_failure("ML-KEM keygen PCT failed");
}
#else
assert(res == 0);
#endif
return res;
}

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;
int res;
ml_kem_1024_params_init(&params);
return ml_kem_keypair_ref(&params, public_key, secret_key);
res = ml_kem_keypair_ref(&params, public_key, secret_key);
#if defined(AWSLC_FIPS)
/* PCT failure is the only failure condition for key generation. */
if (res != 0) {
AWS_LC_FIPS_failure("ML-KEM keygen PCT failed");
}
#else
assert(res == 0);
#endif
return res;
}

int ml_kem_1024_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
Expand Down
12 changes: 6 additions & 6 deletions crypto/fipsmodule/ml_kem/ml_kem_ref/kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "./verify.h"
#include "./reduce.h"
#include "./symmetric.h"
#include "../../../internal.h"

#include "openssl/rand.h"

Expand Down Expand Up @@ -40,8 +39,9 @@ static int keygen_pct(ml_kem_params *params, const uint8_t *ek, const uint8_t *d
* (an already allocated array of KYBER_SECRETKEYBYTES bytes)
* - uint8_t *coins: pointer to input randomness
* (an already allocated array filled with 2*KYBER_SYMBYTES random bytes)
**
* Returns 0 on success, aborts on failure.
*
* Returns: - 0 on success
* - -1 upon PCT failure (if AWSLC_FIPS is set)
**************************************************/
int crypto_kem_keypair_derand(ml_kem_params *params,
uint8_t *pk,
Expand All @@ -57,7 +57,7 @@ int crypto_kem_keypair_derand(ml_kem_params *params,
#if defined(AWSLC_FIPS)
// Abort in case of PCT failure.
if (keygen_pct(params, pk, sk)) {
AWS_LC_FIPS_failure("ML-KEM keygen PCT failed");
return -1;
}
#endif
return 0;
Expand All @@ -74,7 +74,8 @@ int crypto_kem_keypair_derand(ml_kem_params *params,
* - uint8_t *sk: pointer to output private key
* (an already allocated array of KYBER_SECRETKEYBYTES bytes)
*
* Returns 0 on success, aborts on failure.
* Returns: - 0 on success
* - -1 upon PCT failure (if AWSLC_FIPS is set)
**************************************************/
int crypto_kem_keypair(ml_kem_params *params,
uint8_t *pk,
Expand All @@ -83,7 +84,6 @@ int crypto_kem_keypair(ml_kem_params *params,
uint8_t coins[2*KYBER_SYMBYTES];
RAND_bytes(coins, 2*KYBER_SYMBYTES);
int res = crypto_kem_keypair_derand(params, pk, sk, coins);
assert(res == 0);

// FIPS 203. Section 3.3 Destruction of intermediate values.
OPENSSL_cleanse(coins, sizeof(coins));
Expand Down

0 comments on commit 5ddb00b

Please sign in to comment.