Skip to content

ML-KEM memory safety #2263

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

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0f27070
Update keygen functions for memory safety
m271828 Mar 11, 2025
a333b20
Plumb size through to KEM layer. (Kyber also uses KEM so APIs need to…
m271828 Mar 12, 2025
d52e282
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 12, 2025
bde3e83
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 12, 2025
e17132e
Add length checks to self_check
m271828 Mar 13, 2025
9e7aaa7
Merge branch 'memory-safety-ml-kem' of github.com:m271828/aws-lc into…
m271828 Mar 13, 2025
8965154
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 13, 2025
398b012
Add length checks to enc/decap functions
m271828 Mar 13, 2025
49b3c18
Merge branch 'memory-safety-ml-kem' of github.com:m271828/aws-lc into…
m271828 Mar 13, 2025
9ca6930
Remove unneeded include
m271828 Mar 13, 2025
6ca8db6
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 13, 2025
f0b1273
Remove unused code
m271828 Mar 15, 2025
2d43ad5
Merge branch 'memory-safety-ml-kem' of github.com:m271828/aws-lc into…
m271828 Mar 15, 2025
a827090
Add unit test file
m271828 Mar 18, 2025
79954a1
Add unit test file
m271828 Mar 18, 2025
45f85d2
Remove tests from self_check
m271828 Mar 18, 2025
2365123
Add parameterized tests for short, exact and long length inputs
m271828 Mar 20, 2025
505006f
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 20, 2025
f775a2a
Add C code indicator around ml_kem header
m271828 Mar 20, 2025
2f07a28
Fix unit test
m271828 Mar 20, 2025
2d0fee4
Try to work around EVP layer
m271828 Mar 20, 2025
606e7ca
Quietly export functions needed for testing
m271828 Mar 24, 2025
b239b14
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 24, 2025
79df814
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 25, 2025
7ce15b7
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 26, 2025
ceb7b8f
Merge branch 'main' into memory-safety-ml-kem
m271828 Mar 27, 2025
34ff02b
Merge branch 'main' into memory-safety-ml-kem
m271828 Apr 1, 2025
122b6e2
Make length an exact check
m271828 Apr 1, 2025
2ab7a11
Merge branch 'memory-safety-ml-kem' of github.com:m271828/aws-lc into…
m271828 Apr 1, 2025
e67cf52
Remove exports on *_no_self_test functions
m271828 Apr 1, 2025
8549d1e
Merge branch 'main' into memory-safety-ml-kem
m271828 Apr 1, 2025
28abe12
Match external API which allows buffers to be longer than required le…
m271828 Apr 3, 2025
1f570a1
Make length parameters in/out to match EVP API
m271828 Apr 4, 2025
44a5e85
Merge branch 'main' into memory-safety-ml-kem
m271828 Apr 4, 2025
a7fef2e
Fix type
m271828 Apr 4, 2025
3df81d6
Adjust array initialization
m271828 Apr 4, 2025
56cb64e
Fix logic for two parameter length checks
m271828 Apr 4, 2025
c03d982
Remove debug statements
m271828 Apr 4, 2025
8c9ca17
Remove zero'ing of unwritten buffer
m271828 Apr 4, 2025
de7cf39
Merge branch 'main' into memory-safety-ml-kem
m271828 Apr 8, 2025
adcedf4
Update to work with new internal structure
m271828 Apr 9, 2025
73160b6
Code cleanup
m271828 Apr 9, 2025
2be97e8
Wrote parameter name
m271828 Apr 9, 2025
dfd25bb
Code review revisions
m271828 Apr 15, 2025
8834067
Merge branch 'main' into memory-safety-ml-kem
m271828 Apr 15, 2025
d3ac208
Merge branch 'main' into memory-safety-ml-kem
m271828 May 13, 2025
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
1 change: 1 addition & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,7 @@ if(BUILD_TESTING)
fipsmodule/evp/evp_ctx_test.cc
fipsmodule/kdf/kdf_test.cc
fipsmodule/md5/md5_test.cc
fipsmodule/ml_kem/ml_kem_test.cc
fipsmodule/modes/gcm_test.cc
fipsmodule/modes/xts_test.cc
fipsmodule/pbkdf/pbkdf_test.cc
Expand Down
14 changes: 9 additions & 5 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 pubkey_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, &pubkey_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 pubkey_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, &pubkey_len, key->secret_key, &secret_len) ||
!EVP_PKEY_set_type(pkey, EVP_PKEY_KEM)) {
KEM_KEY_free(key);
return 0;
Expand Down Expand Up @@ -172,7 +176,7 @@ static int pkey_kem_encapsulate_deterministic(EVP_PKEY_CTX *ctx,
return 0;
}

if (!kem->method->encaps_deterministic(ciphertext, shared_secret, key->public_key, seed)) {
if (!kem->method->encaps_deterministic(ciphertext, ciphertext_len, shared_secret, shared_secret_len, key->public_key, seed)) {
return 0;
}

Expand Down Expand Up @@ -235,7 +239,7 @@ static int pkey_kem_encapsulate(EVP_PKEY_CTX *ctx,
return 0;
}

if (!kem->method->encaps(ciphertext, shared_secret, key->public_key)) {
if (!kem->method->encaps(ciphertext, ciphertext_len, shared_secret, shared_secret_len, key->public_key)) {
return 0;
}

Expand Down Expand Up @@ -290,7 +294,7 @@ static int pkey_kem_decapsulate(EVP_PKEY_CTX *ctx,
return 0;
}

if (!kem->method->decaps(shared_secret, ciphertext, key->secret_key)) {
if (!kem->method->decaps(shared_secret, shared_secret_len, ciphertext, key->secret_key)) {
return 0;
}

Expand Down
11 changes: 10 additions & 1 deletion crypto/fipsmodule/kem/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,31 @@ 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,
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key,
const uint8_t *seed);

int (*encaps)(uint8_t *ciphertext,
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key);

int (*decaps)(uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *ciphertext,
const uint8_t *secret_key);
} KEM_METHOD;
Expand Down
109 changes: 68 additions & 41 deletions crypto/fipsmodule/kem/kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,42 @@ 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,
uint8_t *secret_key,
const uint8_t *seed) {
return ml_kem_1024_keypair_deterministic(public_key, secret_key, seed) == 0;
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len,
const uint8_t *seed) {
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,
uint8_t *shared_secret,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_1024_encapsulate_deterministic(ciphertext, shared_secret, public_key, seed) == 0;
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_1024_encapsulate_deterministic(ciphertext, ciphertext_len, shared_secret, shared_secret_len, public_key, seed) == 0;
}

static int ml_kem_1024_encaps(uint8_t *ciphertext,
uint8_t *shared_secret,
const uint8_t *public_key) {
return ml_kem_1024_encapsulate(ciphertext, shared_secret, public_key) == 0;
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key) {
return ml_kem_1024_encapsulate(ciphertext, ciphertext_len, shared_secret, shared_secret_len, public_key) == 0;
}

static int ml_kem_1024_decaps(uint8_t *shared_secret,
const uint8_t *ciphertext,
const uint8_t *secret_key) {
return ml_kem_1024_decapsulate(shared_secret, ciphertext, secret_key) == 0;
size_t *shared_secret_len,
const uint8_t *ciphertext,
const uint8_t *secret_key) {
return ml_kem_1024_decapsulate(shared_secret, shared_secret_len, ciphertext, secret_key) == 0;
}

DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_1024_method) {
Expand All @@ -55,33 +64,42 @@ DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_1024_method) {
}

static int ml_kem_768_keygen_deterministic(uint8_t *public_key,
uint8_t *secret_key,
const uint8_t *seed) {
return ml_kem_768_keypair_deterministic(public_key, secret_key, seed) == 0;
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len,
const uint8_t *seed) {
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,
uint8_t *shared_secret,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_768_encapsulate_deterministic(ciphertext, shared_secret, public_key, seed) == 0;
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_768_encapsulate_deterministic(ciphertext, ciphertext_len, shared_secret, shared_secret_len, public_key, seed) == 0;
}

static int ml_kem_768_encaps(uint8_t *ciphertext,
uint8_t *shared_secret,
const uint8_t *public_key) {
return ml_kem_768_encapsulate(ciphertext, shared_secret, public_key) == 0;
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key) {
return ml_kem_768_encapsulate(ciphertext, ciphertext_len, shared_secret, shared_secret_len, public_key) == 0;
}

static int ml_kem_768_decaps(uint8_t *shared_secret,
const uint8_t *ciphertext,
const uint8_t *secret_key) {
return ml_kem_768_decapsulate(shared_secret, ciphertext, secret_key) == 0;
size_t *shared_secret_len,
const uint8_t *ciphertext,
const uint8_t *secret_key) {
return ml_kem_768_decapsulate(shared_secret, shared_secret_len, ciphertext, secret_key) == 0;
}

DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_768_method) {
Expand All @@ -93,33 +111,42 @@ DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_768_method) {
}

static int ml_kem_512_keygen_deterministic(uint8_t *public_key,
uint8_t *secret_key,
const uint8_t *seed) {
return ml_kem_512_keypair_deterministic(public_key, secret_key, seed) == 0;
size_t *public_len,
uint8_t *secret_key,
size_t *secret_len,
const uint8_t *seed) {
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,
uint8_t *shared_secret,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_512_encapsulate_deterministic(ciphertext, shared_secret, public_key, seed) == 0;
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key,
const uint8_t *seed) {
return ml_kem_512_encapsulate_deterministic(ciphertext, ciphertext_len, shared_secret, shared_secret_len, public_key, seed) == 0;
}

static int ml_kem_512_encaps(uint8_t *ciphertext,
size_t *ciphertext_len,
uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *public_key) {
return ml_kem_512_encapsulate(ciphertext, shared_secret, public_key) == 0;
return ml_kem_512_encapsulate(ciphertext, ciphertext_len, shared_secret, shared_secret_len, public_key) == 0;
}

static int ml_kem_512_decaps(uint8_t *shared_secret,
size_t *shared_secret_len,
const uint8_t *ciphertext,
const uint8_t *secret_key) {
return ml_kem_512_decapsulate(shared_secret, ciphertext, secret_key) == 0;
return ml_kem_512_decapsulate(shared_secret, shared_secret_len, ciphertext, secret_key) == 0;
}

DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_512_method) {
Expand Down
Loading
Loading