Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIPS 203 IPD update: ML-KEM-IPD-768 and ML-KEM-IPD-1024 #1724

Merged
merged 7 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ add_library(
lhash/lhash.c
mem.c
ml_kem/ml_kem_512_ipd.c
ml_kem/ml_kem_768_ipd.c
ml_kem/ml_kem_1024_ipd.c
ml_kem/ml_kem.c
obj/obj.c
obj/obj_xref.c
Expand Down
2 changes: 2 additions & 0 deletions crypto/evp_extra/evp_extra_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2073,6 +2073,8 @@ static const struct KnownKEM kKEMs[] = {
{"Kyber768r3", NID_KYBER768_R3, 1184, 2400, 1088, 32, 64, 32, "kyber/kat/kyber768r3.txt"},
{"Kyber1024r3", NID_KYBER1024_R3, 1568, 3168, 1568, 32, 64, 32, "kyber/kat/kyber1024r3.txt"},
{"MLKEM512IPD", NID_MLKEM512IPD, 800, 1632, 768, 32, 64, 32, "ml_kem/kat/mlkem512ipd.txt"},
{"MLKEM768IPD", NID_MLKEM768IPD, 1184, 2400, 1088, 32, 64, 32, "ml_kem/kat/mlkem768ipd.txt"},
{"MLKEM1024IPD", NID_MLKEM1024IPD, 1568, 3168, 1568, 32, 64, 32, "ml_kem/kat/mlkem1024ipd.txt"},
};

class PerKEMTest : public testing::TestWithParam<KnownKEM> {};
Expand Down
2 changes: 2 additions & 0 deletions crypto/kem/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ extern const KEM_METHOD kem_kyber512r3_method;
extern const KEM_METHOD kem_kyber768r3_method;
extern const KEM_METHOD kem_kyber1024r3_method;
extern const KEM_METHOD kem_ml_kem_512_ipd_method;
extern const KEM_METHOD kem_ml_kem_768_ipd_method;
extern const KEM_METHOD kem_ml_kem_1024_ipd_method;

// KEM structure and helper functions.
typedef struct {
Expand Down
38 changes: 33 additions & 5 deletions crypto/kem/kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
// - Kyber is not standardized yet, so we use the latest specification
// from Round 3 of NIST PQC project.

#define AWSLC_NUM_BUILT_IN_KEMS 4
#define AWSLC_NUM_BUILT_IN_KEMS 6

// TODO(awslc): placeholder OIDs, replace with the real ones when available.
static const uint8_t kOIDKyber512r3[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDKyber768r3[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDKyber1024r3[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDMLKEM512IPD[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDKyber512r3[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDKyber768r3[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDKyber1024r3[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDMLKEM512IPD[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDMLKEM768IPD[] = {0xff, 0xff, 0xff, 0xff};
static const uint8_t kOIDMLKEM1024IPD[] = {0xff, 0xff, 0xff, 0xff};

static const KEM built_in_kems[AWSLC_NUM_BUILT_IN_KEMS] = {
{
Expand Down Expand Up @@ -82,6 +84,32 @@ static const KEM built_in_kems[AWSLC_NUM_BUILT_IN_KEMS] = {
MLKEM512IPD_ENCAPS_SEED_LEN, // kem.encaps_seed_len
&kem_ml_kem_512_ipd_method, // kem.method
},
{
NID_MLKEM768IPD, // kem.nid
kOIDMLKEM768IPD, // kem.oid
sizeof(kOIDMLKEM768IPD), // kem.oid_len
"MLKEM768 IPD", // kem.comment
MLKEM768IPD_PUBLIC_KEY_BYTES, // kem.public_key_len
MLKEM768IPD_SECRET_KEY_BYTES, // kem.secret_key_len
MLKEM768IPD_CIPHERTEXT_BYTES, // kem.ciphertext_len
MLKEM768IPD_SHARED_SECRET_LEN, // kem.shared_secret_len
MLKEM768IPD_KEYGEN_SEED_LEN, // kem.keygen_seed_len
MLKEM768IPD_ENCAPS_SEED_LEN, // kem.encaps_seed_len
&kem_ml_kem_768_ipd_method, // kem.method
},
{
NID_MLKEM1024IPD, // kem.nid
kOIDMLKEM1024IPD, // kem.oid
sizeof(kOIDMLKEM1024IPD), // kem.oid_len
"MLKEM1024 IPD", // kem.comment
MLKEM1024IPD_PUBLIC_KEY_BYTES, // kem.public_key_len
MLKEM1024IPD_SECRET_KEY_BYTES, // kem.secret_key_len
MLKEM1024IPD_CIPHERTEXT_BYTES, // kem.ciphertext_len
MLKEM1024IPD_SHARED_SECRET_LEN, // kem.shared_secret_len
MLKEM1024IPD_KEYGEN_SEED_LEN, // kem.keygen_seed_len
MLKEM1024IPD_ENCAPS_SEED_LEN, // kem.encaps_seed_len
&kem_ml_kem_1024_ipd_method, // kem.method
},
};

const KEM *KEM_find_kem_by_nid(int nid) {
Expand Down
76 changes: 76 additions & 0 deletions crypto/kem/kem_methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,79 @@ const KEM_METHOD kem_ml_kem_512_ipd_method = {
ml_kem_512_ipd_encaps,
ml_kem_512_ipd_decaps,
};

static int ml_kem_768_ipd_keygen_deterministic(uint8_t *public_key,
uint8_t *secret_key,
const uint8_t *seed) {
return ml_kem_768_ipd_keypair_deterministic(public_key, secret_key, seed) == 0;
}

static int ml_kem_768_ipd_keygen(uint8_t *public_key,
uint8_t *secret_key) {
return ml_kem_768_ipd_keypair(public_key, secret_key) == 0;
}

static int ml_kem_768_ipd_encaps_deterministic(uint8_t *ciphertext,
uint8_t *shared_secret,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_768_ipd_encapsulate_deterministic(ciphertext, shared_secret, public_key, seed) == 0;
}

static int ml_kem_768_ipd_encaps(uint8_t *ciphertext,
uint8_t *shared_secret,
const uint8_t *public_key) {
return ml_kem_768_ipd_encapsulate(ciphertext, shared_secret, public_key) == 0;
}

static int ml_kem_768_ipd_decaps(uint8_t *shared_secret,
const uint8_t *ciphertext,
const uint8_t *secret_key) {
return ml_kem_768_ipd_decapsulate(shared_secret, ciphertext, secret_key) == 0;
}

const KEM_METHOD kem_ml_kem_768_ipd_method = {
ml_kem_768_ipd_keygen_deterministic,
ml_kem_768_ipd_keygen,
ml_kem_768_ipd_encaps_deterministic,
ml_kem_768_ipd_encaps,
ml_kem_768_ipd_decaps,
};

static int ml_kem_1024_ipd_keygen_deterministic(uint8_t *public_key,
uint8_t *secret_key,
const uint8_t *seed) {
return ml_kem_1024_ipd_keypair_deterministic(public_key, secret_key, seed) == 0;
}

static int ml_kem_1024_ipd_keygen(uint8_t *public_key,
uint8_t *secret_key) {
return ml_kem_1024_ipd_keypair(public_key, secret_key) == 0;
}

static int ml_kem_1024_ipd_encaps_deterministic(uint8_t *ciphertext,
uint8_t *shared_secret,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_1024_ipd_encapsulate_deterministic(ciphertext, shared_secret, public_key, seed) == 0;
}

static int ml_kem_1024_ipd_encaps(uint8_t *ciphertext,
uint8_t *shared_secret,
const uint8_t *public_key) {
return ml_kem_1024_ipd_encapsulate(ciphertext, shared_secret, public_key) == 0;
}

static int ml_kem_1024_ipd_decaps(uint8_t *shared_secret,
const uint8_t *ciphertext,
const uint8_t *secret_key) {
return ml_kem_1024_ipd_decapsulate(shared_secret, ciphertext, secret_key) == 0;
}

const KEM_METHOD kem_ml_kem_1024_ipd_method = {
ml_kem_1024_ipd_keygen_deterministic,
ml_kem_1024_ipd_keygen,
ml_kem_1024_ipd_encaps_deterministic,
ml_kem_1024_ipd_encaps,
ml_kem_1024_ipd_decaps,
};
8 changes: 4 additions & 4 deletions crypto/ml_kem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ NOTE: THIS IS AN IMPLEMENTATION OF THE DRAFT VERSION OF FIPS 203, NOT THE FINAL

The following changes were made to the source code in `ml_kem_ipd_ref_common` directory:
- `randombytes.{h|c}` are deleted because we are using the randomness generation functions provided by AWS-LC.
- `kem.c`: call to randombytes function is replaced with a call to pq_custom_randombytes and the appropriate header file is included (crypto/rand_extra/pq_custom_randombytes.h).
- `kem.c`: call to randombytes function is replaced with a call to RAND_bytes and the appropriate header file is included (openssl/rand.h).
- `fips202.{h|c}` are deleted and the ones from `crypto/kyber/pqcrystals_kyber_ref_common` directory are used.
- `symmetric-shake.c`: unnecessary include of fips202.h is removed.
- `api.h`: `pqcrystals` prefix substituted with `ml_kem` (to be able build alongside `crypto/kyber`).
* `poly.c`: the `poly_frommsg` function was modified to address the constant-time issue described [here](https://github.com/pq-crystals/kyber/commit/9b8d30698a3e7449aeb34e62339d4176f11e3c6c).
- `api.h`: `pqcrystals` prefix substituted with `ml_kem` (to be able to build alongside `crypto/kyber`).
- `poly.c`: the `poly_frommsg` function was modified to address the constant-time issue described [here](https://github.com/pq-crystals/kyber/commit/9b8d30698a3e7449aeb34e62339d4176f11e3c6c).

The KATs were generated by compiling and running the KAT generator tests from the official repository. Specifically, running `make` in the `ref` folder produces `nistkat/PQCgenKAT_kem512` binary that can generates the test vectors.
The KATs were generated by compiling and running the KAT generator tests from the official repository. Specifically, running `make` in the `ref` folder produces `nistkat/PQCgenKAT_kem512` binary that can generates the test vectors. The files in `ml_kem/kat/mlkem{512|768|1024}ipd.txt` utilize the deterministic API for testing, and instead use the intermediate seed values (`keypair_coins` and `encap_coins`) instead of a call to randomness generation. The same intermediate values can be extracted from the official repository from the `coins` generated during keypair, and encapsulate.
Loading
Loading