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

ML-KEM memory safety #2263

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
8 changes: 6 additions & 2 deletions crypto/fipsmodule/evp/p_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@ static int pkey_kem_keygen_deterministic(EVP_PKEY_CTX *ctx,
}

KEM_KEY *key = KEM_KEY_new();
size_t public_len = kem->public_key_len;
size_t secret_len = kem->secret_key_len;
if (key == NULL ||
!KEM_KEY_init(key, kem) ||
!kem->method->keygen_deterministic(key->public_key, key->secret_key, seed) ||
!kem->method->keygen_deterministic(key->public_key, &public_len, key->secret_key, &secret_len, seed) ||
!EVP_PKEY_assign(pkey, EVP_PKEY_KEM, key)) {
KEM_KEY_free(key);
return 0;
Expand All @@ -92,9 +94,11 @@ static int pkey_kem_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
}

KEM_KEY *key = KEM_KEY_new();
size_t public_len = kem->public_key_len;
size_t secret_len = kem->secret_key_len;
if (key == NULL ||
!KEM_KEY_init(key, kem) ||
!kem->method->keygen(key->public_key, key->secret_key) ||
!kem->method->keygen(key->public_key, &public_len, key->secret_key, &secret_len) ||
!EVP_PKEY_set_type(pkey, EVP_PKEY_KEM)) {
KEM_KEY_free(key);
return 0;
Expand Down
8 changes: 7 additions & 1 deletion crypto/fipsmodule/kem/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ extern "C" {
// KEM_METHOD structure and helper functions.
typedef struct {
int (*keygen_deterministic)(uint8_t *ctx,
size_t *ctx_len,
uint8_t *pkey,
size_t *pkey_len,
const uint8_t *seed);

int (*keygen)(uint8_t *public_key,
uint8_t *secret_key);
size_t *public_key_len,
uint8_t *secret_key,
size_t *secret_key_len);

int (*encaps_deterministic)(uint8_t *ciphertext,
uint8_t *shared_secret,
Expand Down Expand Up @@ -53,7 +57,9 @@ typedef struct {
struct kem_key_st {
const KEM *kem;
uint8_t *public_key;
size_t *public_key_len;
uint8_t *secret_key;
size_t *secret_key_len;
};

const KEM *KEM_find_kem_by_nid(int nid);
Expand Down
30 changes: 21 additions & 9 deletions crypto/fipsmodule/kem/kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ static const uint8_t kOIDMLKEM768[] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04
static const uint8_t kOIDMLKEM1024[] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x04, 0x03};

static int ml_kem_1024_keygen_deterministic(uint8_t *public_key,
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len,
const uint8_t *seed) {
return ml_kem_1024_keypair_deterministic(public_key, secret_key, seed) == 0;
return ml_kem_1024_keypair_deterministic(public_key, public_len, secret_key, secret_len, seed) == 0;
}

static int ml_kem_1024_keygen(uint8_t *public_key,
uint8_t *secret_key) {
return ml_kem_1024_keypair(public_key, secret_key) == 0;
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len) {
return ml_kem_1024_keypair(public_key, public_len, secret_key, secret_len) == 0;
}

static int ml_kem_1024_encaps_deterministic(uint8_t *ciphertext,
Expand Down Expand Up @@ -55,14 +59,18 @@ DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_1024_method) {
}

static int ml_kem_768_keygen_deterministic(uint8_t *public_key,
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len,
const uint8_t *seed) {
return ml_kem_768_keypair_deterministic(public_key, secret_key, seed) == 0;
return ml_kem_768_keypair_deterministic(public_key, public_len, secret_key, secret_len, seed) == 0;
}

static int ml_kem_768_keygen(uint8_t *public_key,
uint8_t *secret_key) {
return ml_kem_768_keypair(public_key, secret_key) == 0;
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len) {
return ml_kem_768_keypair(public_key, public_len, secret_key, secret_len) == 0;
}

static int ml_kem_768_encaps_deterministic(uint8_t *ciphertext,
Expand Down Expand Up @@ -93,14 +101,18 @@ DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_768_method) {
}

static int ml_kem_512_keygen_deterministic(uint8_t *public_key,
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len,
const uint8_t *seed) {
return ml_kem_512_keypair_deterministic(public_key, secret_key, seed) == 0;
return ml_kem_512_keypair_deterministic(public_key, public_len, secret_key, secret_len, seed) == 0;
}

static int ml_kem_512_keygen(uint8_t *public_key,
uint8_t *secret_key) {
return ml_kem_512_keypair(public_key, secret_key) == 0;
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len) {
return ml_kem_512_keypair(public_key, public_len, secret_key, secret_len) == 0;
}

static int ml_kem_512_encaps_deterministic(uint8_t *ciphertext,
Expand Down
64 changes: 60 additions & 4 deletions crypto/fipsmodule/ml_kem/ml_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,61 @@
// platform support.

int ml_kem_512_keypair_deterministic(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_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);
return ml_kem_512_keypair_deterministic_no_self_test(public_key, public_len, secret_key, secret_len, seed);
}

int ml_kem_512_keypair_deterministic_no_self_test(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */,
const uint8_t *seed /* IN */) {
ml_kem_params params;
int res;
ml_kem_512_params_init(&params);
if (*public_len < params.public_key_bytes || *secret_len < params.secret_key_bytes) {
return 0;
}
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");
}
#endif
if (res == 0) {
*public_len = params.public_key_bytes;
*secret_len = params.secret_key_bytes;
}
return res;
}

int ml_kem_512_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */) {
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */) {
boringssl_ensure_ml_kem_self_test();
int res;
ml_kem_params params;
ml_kem_512_params_init(&params);
if (*public_len < params.public_key_bytes || *secret_len < params.secret_key_bytes) {
return 0;
}
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");
}
#endif
if (res == 0) {
*public_len = params.public_key_bytes;
*secret_len = params.secret_key_bytes;
}
return res;
}

Expand Down Expand Up @@ -106,35 +126,53 @@ int ml_kem_512_decapsulate_no_self_test(uint8_t *shared_secret /* OUT */,


int ml_kem_768_keypair_deterministic(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
int res;
ml_kem_768_params_init(&params);
if (*public_len < params.public_key_bytes || *secret_len < params.secret_key_bytes) {
return 0;
}
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");
}
#endif
if (res == 0) {
*public_len = params.public_key_bytes;
*secret_len = params.secret_key_bytes;
}
return res;
}

int ml_kem_768_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */) {
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
int res;
ml_kem_768_params_init(&params);
if (*public_len < params.public_key_bytes || *secret_len < params.secret_key_bytes) {
return 0;
}
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");
}
#endif
if (res == 0) {
*public_len = params.public_key_bytes;
*secret_len = params.secret_key_bytes;
}
return res;
}

Expand Down Expand Up @@ -167,35 +205,53 @@ int ml_kem_768_decapsulate(uint8_t *shared_secret /* OUT */,
}

int ml_kem_1024_keypair_deterministic(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */,
const uint8_t *seed /* IN */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
int res;
ml_kem_1024_params_init(&params);
if (*public_len < params.public_key_bytes || *secret_len < params.secret_key_bytes) {
return 0;
}
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");
}
#endif
if (res == 0) {
*public_len = params.public_key_bytes;
*secret_len = params.secret_key_bytes;
}
return res;
}

int ml_kem_1024_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */) {
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */) {
boringssl_ensure_ml_kem_self_test();
ml_kem_params params;
int res;
ml_kem_1024_params_init(&params);
if (*public_len < params.public_key_bytes || *secret_len < params.secret_key_bytes) {
return 0;
}
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");
}
#endif
if (res == 0) {
*public_len = params.public_key_bytes;
*secret_len = params.secret_key_bytes;
}
return res;
}

Expand Down
20 changes: 17 additions & 3 deletions crypto/fipsmodule/ml_kem/ml_kem.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,21 @@
#define MLKEM1024_CIPHERTEXT_BYTES (1568)

int ml_kem_512_keypair_deterministic(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */,
const uint8_t *seed /* IN */);

int ml_kem_512_keypair_deterministic_no_self_test(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */,
const uint8_t *seed /* IN */);

int ml_kem_512_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */);
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */);

int ml_kem_512_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
Expand All @@ -62,11 +68,15 @@ int ml_kem_512_decapsulate_no_self_test(uint8_t *shared_secret /* OUT */,
const uint8_t *secret_key /* IN */);

int ml_kem_768_keypair_deterministic(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */,
const uint8_t *seed /* IN */);

int ml_kem_768_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */);
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */);

int ml_kem_768_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
Expand All @@ -82,11 +92,15 @@ int ml_kem_768_decapsulate(uint8_t *shared_secret /* OUT */,
const uint8_t *secret_key /* IN */);

int ml_kem_1024_keypair_deterministic(uint8_t *public_key /* OUT */,
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */,
const uint8_t *seed /* IN */);

int ml_kem_1024_keypair(uint8_t *public_key /* OUT */,
uint8_t *secret_key /* OUT */);
size_t *public_len /* IN_OUT */,
uint8_t *secret_key /* OUT */,
size_t *secret_len /* IN_OUT */);

int ml_kem_1024_encapsulate_deterministic(uint8_t *ciphertext /* OUT */,
uint8_t *shared_secret /* OUT */,
Expand Down
16 changes: 12 additions & 4 deletions crypto/fipsmodule/self_check/self_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,11 +890,15 @@ static int boringssl_self_test_ml_kem(void) {
0x1d, 0x2d, 0x8c, 0xaf, 0x5a, 0xf4, 0xa6, 0x92};
uint8_t keygen_decaps[MLKEM512_SECRET_KEY_BYTES] = {0};
uint8_t keygen_encaps[MLKEM512_PUBLIC_KEY_BYTES] = {0};
size_t decaps_len = MLKEM512_SECRET_KEY_BYTES;
size_t encaps_len = MLKEM512_PUBLIC_KEY_BYTES;

if (ml_kem_512_keypair_deterministic_no_self_test(
keygen_encaps, keygen_decaps, kKeyGenEKSeed) ||
keygen_encaps, &encaps_len, keygen_decaps, &decaps_len, kKeyGenEKSeed) ||
!check_test(kKeyGenEK, keygen_encaps, sizeof(keygen_encaps),
"ML-KEM-keyGen-encaps")) {
"ML-KEM-keyGen-encaps") ||
decaps_len > MLKEM512_SECRET_KEY_BYTES ||
encaps_len > MLKEM512_PUBLIC_KEY_BYTES) {
goto err;
}

Expand Down Expand Up @@ -1049,10 +1053,14 @@ static int boringssl_self_test_ml_kem(void) {
0x2f, 0x55, 0xa2, 0x46, 0x1b, 0x07, 0x4b, 0xff, 0x80, 0x44, 0x44, 0x5e,
0x11, 0x66, 0x0b, 0x1b, 0x6b, 0x26, 0xdf, 0x24, 0x2b, 0x8f, 0xc0, 0x2b,
0x9e, 0x8d, 0xf5, 0x38, 0xdb, 0x17, 0xa6, 0x39, 0xd7, 0xc4, 0x61, 0x32};
encaps_len = MLKEM512_PUBLIC_KEY_BYTES;
decaps_len = MLKEM512_SECRET_KEY_BYTES;
if (ml_kem_512_keypair_deterministic_no_self_test(
keygen_encaps, keygen_decaps, kKeyGenDKSeed) ||
keygen_encaps, &encaps_len, keygen_decaps, &decaps_len, kKeyGenDKSeed) ||
!check_test(kKeyGenDK, keygen_decaps, sizeof(keygen_decaps),
"ML-KEM-keyGen-decaps")) {
"ML-KEM-keyGen-decaps") ||
encaps_len > MLKEM512_PUBLIC_KEY_BYTES ||
decaps_len > MLKEM512_SECRET_KEY_BYTES) {
goto err;
}

Expand Down
Loading
Loading