forked from aws/aws-lc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move KEM API and ML-KEM definitions to FIPS module (aws#1828)
In this PR, we first move the ML-KEM definitions under the FIPS module and the set of KEM API. There are two objects to keep track of: `KEM` is the "context" object of a kem method storing e.g. size information, unique identifiers, and a reference to a method table (of type `KEM_METHOD`). `KEM_METHOD` is the method table that stores references to implementations for each abstract operation. Both `KEM` and `KEM_METHOD` has been defined outside the FIPS module. Move this under the module now. Previously, also the KEM method function tables were defined in their own source code file. Move these together with the definitions of the KEMs. They will later go to their own file. Note, that `KEM` was defined with only `const` fields. I think this was my invention but it was not an optimal choice. It only allows static initialization. This is not good with the current static FIPS build, so remove the `const` qualifier from all non-pointer fields in `KEM`. Finally, drop part of the table search method. KEMs are now directly referenced instead of searching through a table. Retain the table search for the legacy Kyber kems for now though to minimize code changes in each PR.
- Loading branch information
1 parent
b15bf7e
commit 16ca6e7
Showing
8 changed files
with
380 additions
and
330 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#ifndef AWSLC_HEADER_KEM_INTERNAL_H | ||
#define AWSLC_HEADER_KEM_INTERNAL_H | ||
|
||
#include <openssl/base.h> | ||
|
||
|
||
#if defined(__cplusplus) | ||
extern "C" { | ||
#endif | ||
|
||
// KEM_METHOD structure and helper functions. | ||
typedef struct { | ||
int (*keygen_deterministic)(uint8_t *ctx, | ||
uint8_t *pkey, | ||
const uint8_t *seed); | ||
|
||
int (*keygen)(uint8_t *public_key, | ||
uint8_t *secret_key); | ||
|
||
int (*encaps_deterministic)(uint8_t *ciphertext, | ||
uint8_t *shared_secret, | ||
const uint8_t *public_key, | ||
const uint8_t *seed); | ||
|
||
int (*encaps)(uint8_t *ciphertext, | ||
uint8_t *shared_secret, | ||
const uint8_t *public_key); | ||
|
||
int (*decaps)(uint8_t *shared_secret, | ||
const uint8_t *ciphertext, | ||
const uint8_t *secret_key); | ||
} KEM_METHOD; | ||
|
||
// KEM structure and helper functions. | ||
typedef struct { | ||
int nid; | ||
const uint8_t *oid; | ||
uint8_t oid_len; | ||
const char *comment; | ||
size_t public_key_len; | ||
size_t secret_key_len; | ||
size_t ciphertext_len; | ||
size_t shared_secret_len; | ||
size_t keygen_seed_len; | ||
size_t encaps_seed_len; | ||
const KEM_METHOD *method; | ||
} KEM; | ||
|
||
// KEM_KEY structure and helper functions. | ||
struct kem_key_st { | ||
const KEM *kem; | ||
uint8_t *public_key; | ||
uint8_t *secret_key; | ||
}; | ||
|
||
const KEM *KEM_find_kem_by_nid(int nid); | ||
|
||
KEM_KEY *KEM_KEY_new(void); | ||
int KEM_KEY_init(KEM_KEY *key, const KEM *kem); | ||
void KEM_KEY_free(KEM_KEY *key); | ||
const KEM *KEM_KEY_get0_kem(KEM_KEY* key); | ||
|
||
// KEM_KEY_set_raw_public_key function allocates the public key buffer | ||
// within the given |key| and copies the contents of |in| to it. | ||
// | ||
// NOTE: No checks are done in this function, the caller has to ensure | ||
// that the pointers are valid and |in| has the correct size. | ||
int KEM_KEY_set_raw_public_key(KEM_KEY *key, const uint8_t *in); | ||
|
||
// KEM_KEY_set_raw_secret_key function allocates the secret key buffer | ||
// within the given |key| and copies the contents of |in| to it. | ||
// | ||
// NOTE: No checks are done in this function, the caller has to ensure | ||
// that the pointers are valid and |in| has the correct size. | ||
int KEM_KEY_set_raw_secret_key(KEM_KEY *key, const uint8_t *in); | ||
|
||
// KEM_KEY_set_raw_key function allocates the public and secret key buffers | ||
// within the given |key| and copies the contents of |in_public| and | ||
// |in_secret| to them. | ||
// | ||
// NOTE: No checks are done in this function, the caller has to ensure | ||
// that the pointers are valid and |in_public| and |in_secret| | ||
// have the correct size. | ||
int KEM_KEY_set_raw_key(KEM_KEY *key, const uint8_t *in_public, | ||
const uint8_t *in_secret); | ||
|
||
#if defined(__cplusplus) | ||
} // extern C | ||
#endif | ||
|
||
#endif // AWSLC_HEADER_KEM_TEST_INTERNAL_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#include <openssl/base.h> | ||
|
||
#include "../../kem/internal.h" | ||
#include "../delocate.h" | ||
#include "../ml_kem/ml_kem.h" | ||
#include "internal.h" | ||
|
||
static const uint8_t kOIDMLKEM512[] = {0xff, 0xff, 0xff, 0xff}; | ||
static const uint8_t kOIDMLKEM768[] = {0xff, 0xff, 0xff, 0xff}; | ||
static const uint8_t kOIDMLKEM1024[] = {0xff, 0xff, 0xff, 0xff}; | ||
|
||
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; | ||
} | ||
|
||
static int ml_kem_1024_keygen(uint8_t *public_key, | ||
uint8_t *secret_key) { | ||
return ml_kem_1024_keypair(public_key, secret_key) == 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; | ||
} | ||
|
||
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; | ||
} | ||
|
||
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; | ||
} | ||
|
||
DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_1024_method) { | ||
out->keygen_deterministic = ml_kem_1024_keygen_deterministic; | ||
out->keygen = ml_kem_1024_keygen; | ||
out->encaps_deterministic = ml_kem_1024_encaps_deterministic; | ||
out->encaps = ml_kem_1024_encaps; | ||
out->decaps = ml_kem_1024_decaps; | ||
} | ||
|
||
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; | ||
} | ||
|
||
static int ml_kem_768_keygen(uint8_t *public_key, | ||
uint8_t *secret_key) { | ||
return ml_kem_768_keypair(public_key, secret_key) == 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; | ||
} | ||
|
||
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; | ||
} | ||
|
||
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; | ||
} | ||
|
||
DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_768_method) { | ||
out->keygen_deterministic = ml_kem_768_keygen_deterministic; | ||
out->keygen = ml_kem_768_keygen; | ||
out->encaps_deterministic = ml_kem_768_encaps_deterministic; | ||
out->encaps = ml_kem_768_encaps; | ||
out->decaps = ml_kem_768_decaps; | ||
} | ||
|
||
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; | ||
} | ||
|
||
static int ml_kem_512_keygen(uint8_t *public_key, | ||
uint8_t *secret_key) { | ||
return ml_kem_512_keypair(public_key, secret_key) == 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; | ||
} | ||
|
||
static int ml_kem_512_encaps(uint8_t *ciphertext, | ||
uint8_t *shared_secret, | ||
const uint8_t *public_key) { | ||
return ml_kem_512_encapsulate(ciphertext, shared_secret, public_key) == 0; | ||
} | ||
|
||
static int ml_kem_512_decaps(uint8_t *shared_secret, | ||
const uint8_t *ciphertext, | ||
const uint8_t *secret_key) { | ||
return ml_kem_512_decapsulate(shared_secret, ciphertext, secret_key) == 0; | ||
} | ||
|
||
DEFINE_LOCAL_DATA(KEM_METHOD, kem_ml_kem_512_method) { | ||
out->keygen_deterministic = ml_kem_512_keygen_deterministic; | ||
out->keygen = ml_kem_512_keygen; | ||
out->encaps_deterministic = ml_kem_512_encaps_deterministic; | ||
out->encaps = ml_kem_512_encaps; | ||
out->decaps = ml_kem_512_decaps; | ||
} | ||
|
||
DEFINE_LOCAL_DATA(KEM, KEM_ml_kem_512) { | ||
out->nid = NID_MLKEM512; | ||
out->oid = kOIDMLKEM512; | ||
out->oid_len = sizeof(kOIDMLKEM512); | ||
out->comment = "MLKEM512 "; | ||
out->public_key_len = MLKEM512_PUBLIC_KEY_BYTES; | ||
out->secret_key_len = MLKEM512_SECRET_KEY_BYTES; | ||
out->ciphertext_len = MLKEM512_CIPHERTEXT_BYTES; | ||
out->shared_secret_len = MLKEM512_SHARED_SECRET_LEN; | ||
out->keygen_seed_len = MLKEM512_KEYGEN_SEED_LEN; | ||
out->encaps_seed_len = MLKEM512_ENCAPS_SEED_LEN; | ||
out->method = kem_ml_kem_512_method(); | ||
} | ||
|
||
DEFINE_LOCAL_DATA(KEM, KEM_ml_kem_768) { | ||
out->nid = NID_MLKEM768; | ||
out->oid = kOIDMLKEM768; | ||
out->oid_len = sizeof(kOIDMLKEM768); | ||
out->comment = "MLKEM768 "; | ||
out->public_key_len = MLKEM768_PUBLIC_KEY_BYTES; | ||
out->secret_key_len = MLKEM768_SECRET_KEY_BYTES; | ||
out->ciphertext_len = MLKEM768_CIPHERTEXT_BYTES; | ||
out->shared_secret_len = MLKEM768_SHARED_SECRET_LEN; | ||
out->keygen_seed_len = MLKEM768_KEYGEN_SEED_LEN; | ||
out->encaps_seed_len = MLKEM768_ENCAPS_SEED_LEN; | ||
out->method = kem_ml_kem_768_method(); | ||
} | ||
|
||
DEFINE_LOCAL_DATA(KEM, KEM_ml_kem_1024) { | ||
out->nid = NID_MLKEM1024; | ||
out->oid = kOIDMLKEM1024; | ||
out->oid_len = sizeof(kOIDMLKEM1024); | ||
out->comment = "MLKEM1024 "; | ||
out->public_key_len = MLKEM1024_PUBLIC_KEY_BYTES; | ||
out->secret_key_len = MLKEM1024_SECRET_KEY_BYTES; | ||
out->ciphertext_len = MLKEM1024_CIPHERTEXT_BYTES; | ||
out->shared_secret_len = MLKEM1024_SHARED_SECRET_LEN; | ||
out->keygen_seed_len = MLKEM1024_KEYGEN_SEED_LEN; | ||
out->encaps_seed_len = MLKEM1024_ENCAPS_SEED_LEN; | ||
out->method = kem_ml_kem_1024_method(); | ||
} | ||
|
||
const KEM *KEM_find_kem_by_nid(int nid) { | ||
|
||
switch (nid) { | ||
case NID_MLKEM512: | ||
return KEM_ml_kem_512(); | ||
case NID_MLKEM768: | ||
return KEM_ml_kem_768(); | ||
case NID_MLKEM1024: | ||
return KEM_ml_kem_1024(); | ||
default: | ||
break; | ||
} | ||
|
||
// We couldn't match a known KEM. Try legacy KEMs. | ||
const KEM *legacy_kems = get_legacy_kems(); | ||
for (size_t i = 0; i < AWSLC_NUM_LEGACY_KEMS; i++) { | ||
if (legacy_kems[i].nid == nid) { | ||
return &legacy_kems[i]; | ||
} | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
KEM_KEY *KEM_KEY_new(void) { | ||
KEM_KEY *ret = OPENSSL_zalloc(sizeof(KEM_KEY)); | ||
if (ret == NULL) { | ||
return NULL; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
static void KEM_KEY_clear(KEM_KEY *key) { | ||
key->kem = NULL; | ||
OPENSSL_free(key->public_key); | ||
OPENSSL_free(key->secret_key); | ||
key->public_key = NULL; | ||
key->secret_key = NULL; | ||
} | ||
|
||
int KEM_KEY_init(KEM_KEY *key, const KEM *kem) { | ||
if (key == NULL || kem == NULL) { | ||
return 0; | ||
} | ||
// If the key is already initialized clear it. | ||
KEM_KEY_clear(key); | ||
|
||
key->kem = kem; | ||
key->public_key = OPENSSL_malloc(kem->public_key_len); | ||
key->secret_key = OPENSSL_malloc(kem->secret_key_len); | ||
if (key->public_key == NULL || key->secret_key == NULL) { | ||
KEM_KEY_clear(key); | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
void KEM_KEY_free(KEM_KEY *key) { | ||
if (key == NULL) { | ||
return; | ||
} | ||
KEM_KEY_clear(key); | ||
OPENSSL_free(key); | ||
} | ||
|
||
const KEM *KEM_KEY_get0_kem(KEM_KEY* key) { | ||
return key->kem; | ||
} | ||
|
||
int KEM_KEY_set_raw_public_key(KEM_KEY *key, const uint8_t *in) { | ||
key->public_key = OPENSSL_memdup(in, key->kem->public_key_len); | ||
if (key->public_key == NULL) { | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
int KEM_KEY_set_raw_secret_key(KEM_KEY *key, const uint8_t *in) { | ||
key->secret_key = OPENSSL_memdup(in, key->kem->secret_key_len); | ||
if (key->secret_key == NULL) { | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
int KEM_KEY_set_raw_key(KEM_KEY *key, const uint8_t *in_public, | ||
const uint8_t *in_secret) { | ||
key->public_key = OPENSSL_memdup(in_public, key->kem->public_key_len); | ||
key->secret_key = OPENSSL_memdup(in_secret, key->kem->secret_key_len); | ||
if (key->public_key == NULL || key->secret_key == NULL) { | ||
KEM_KEY_clear(key); | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} |
Oops, something went wrong.