Skip to content

Commit

Permalink
Introduce publich header for mlkem-native API
Browse files Browse the repository at this point in the history
Application sources using an mlkem-native build should not have to
add the source tree of mlkem-native to the include paths. Instead,
there should be a single standaloe header sufficient to include
all necessary declarations.

Previously, this was not true: Applications would need to include
`kem.h` from the source tree, which in turn would pull in, for example,
`config.h` and `cbmc.h`.

On the other hand, the header of mlkem-native is not static, but
depends on information from the build, namely the security level
and the namespacing: The security level determines the sizes of
key material which callers need to know about. The namespacing
determines the name of the function symbols, which callers need
to know about.
It is therefore not possible to completely detach the mlkem-native
API header from the source tree used to build mlkem-native.

One way to address this is to merely require the build configuration
header to be included in the public API header. This works well for
single-level builds, but is inconvenient if the consumer wants to use
multiple instances of mlkem-native for different security levels; in
this case, including the public header multiple times would pull in
multiple configuration files, which would lead to clashes of #define's
clauses.
On the other hand, requiring the consumer to duplicate the level and
namespacing information in the API header is inconvenient for simple
tests or single-level builds.

This introduces a public API header mlkem-native.h, which addresses
the above as follows:

mlkem-native.h requires the build level and build namespace. By default,
it is obtained by including the underlying build configuration
(assumed to be present in the include paths). Alternatively, the user
can set BUILD_INFO_LVL and BUILD_INFO_NAMESPACE explicitly in mlkem-native.h,
and thereby avoid any dependency between mlkem-native.h and config.h.
In this setting, mlkem-native.h leaves no other traces than static size
declarations and build-specific API declarations. In particular, it can
be included multiple times.

This commit adjusts all tests and examples to no longer include `kem.h`,
but only `mlkem-native.h`. In all cases but the monolithic build example,
no further change is required, with the API header pulling the underlying
configuration automatically.

The monolithic build test `examples/monolithic_build` is adjusted as follows:
Where previously it included two instances of mlkem-native, it now includes
three, one per security level. The previous `mlkem_native_all.c` is renamed
to `mlkem_native_monobuild.c`, and is the source file needed for a monolithic
build of a _single_ configuration. This is then included 3 times in `mlkem_native_all.c`.
To provide a header for this file, we include `mlkem-native.h` 3 times, using
manually set `BUILD_INFO_LVL` and `BUILD_INFO_NAMESPACE` to avoid nameclashes
from pulling in the full configuration.

Signed-off-by: Hanno Becker <[email protected]>
  • Loading branch information
hanno-becker authored and mkannwischer committed Jan 7, 2025
1 parent 4b4e881 commit 06d16c9
Show file tree
Hide file tree
Showing 28 changed files with 3,543 additions and 2,937 deletions.
2 changes: 0 additions & 2 deletions examples/bring_your_own_fips202/custom_fips202/fips202x4.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
#include <stdint.h>

#include "cbmc.h"
#include "namespace.h"

#include "fips202.h"

typedef shake128ctx shake128x4ctx[4];
Expand Down
2 changes: 1 addition & 1 deletion examples/bring_your_own_fips202/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <stdio.h>
#include <string.h>

#include <kem.h>
#include <mlkem_native.h>

const uint8_t expected_key[] = {0xe9, 0x13, 0x77, 0x84, 0x0e, 0x6b, 0x66, 0x94,
0xea, 0xa9, 0xf0, 0x1c, 0x97, 0xff, 0x68, 0x87,
Expand Down
2 changes: 1 addition & 1 deletion examples/custom_backend/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <stdio.h>
#include <string.h>

#include <kem.h>
#include <mlkem_native.h>

const uint8_t expected_key[] = {0xe9, 0x13, 0x77, 0x84, 0x0e, 0x6b, 0x66, 0x94,
0xea, 0xa9, 0xf0, 0x1c, 0x97, 0xff, 0x68, 0x87,
Expand Down
10 changes: 10 additions & 0 deletions examples/custom_backend/mlkem_native/custom_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,14 @@
*****************************************************************************/
#define MLKEM_NATIVE_FIPS202_BACKEND "fips202/native/custom/custom.h"

/******************************************************************************
* Name: MLKEM_NATIVE_API_STANDARD
*
* Description: Define this to extend api.h to also export key sizes and public
* API in the CRYPTO_xxx and crypto_kem_xxx format as used e.g. by
* SUPERCOP.
*
*****************************************************************************/
#define MLKEM_NATIVE_API_STANDARD

#endif /* MLkEM_NATIVE_CONFIG_H */
1 change: 1 addition & 0 deletions examples/custom_backend/mlkem_native/mlkem/mlkem_native.h
1 change: 0 additions & 1 deletion examples/custom_backend/mlkem_native/mlkem/namespace.h

This file was deleted.

2 changes: 1 addition & 1 deletion examples/mlkem_native_as_code_package/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <stdio.h>
#include <string.h>

#include <kem.h>
#include <mlkem_native.h>

int main(void)
{
Expand Down
17 changes: 15 additions & 2 deletions examples/monolithic_build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,27 @@ RNG_SOURCE=$(wildcard test_only_rng/*.c)
# Part C:
#
# Your application source code
APP_SOURCE=main.c
APP_SOURCE=main.c mlkem_native_all.c

ALL_SOURCE=$(MLKEM_NATIVE_SOURCE) $(RNG_SOURCE) $(APP_SOURCE)

BUILD_DIR=build
BIN=test_binary

CFLAGS=-std=c90
CFLAGS := \
-Wall \
-Wextra \
-Wmissing-prototypes \
-Wshadow \
-Wpointer-arith \
-Wno-long-long \
-Wno-unknown-pragmas \
-Wno-unused-command-line-argument \
-O3 \
-fomit-frame-pointer \
-std=c90 \
-pedantic \
-MMD

BINARY_NAME_FULL=$(BUILD_DIR)/$(BIN)

Expand Down
File renamed without changes.
97 changes: 97 additions & 0 deletions examples/monolithic_build/config_512.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2024 The mlkem-native project authors
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef MLKEM_NATIVE_CONFIG_H
#define MLKEM_NATIVE_CONFIG_H

/******************************************************************************
* Name: MLKEM_K
*
* Description: Determines the security level for ML-KEM
* - MLKEM_K=2 corresponds to ML-KEM-512
* - MLKEM_K=3 corresponds to ML-KEM-768
* - MLKEM_K=4 corresponds to ML-KEM-1024
*
* This can also be set using CFLAGS.
*
*****************************************************************************/
#ifndef MLKEM_K
#define MLKEM_K 2 /* Change this for different security strengths */
#endif

/******************************************************************************
* Name: MLKEM_NATIVE_CONFIG_FILE
*
* Description: If defined, this is a header that will be included instead
* of mlkem/config.h.
*
* This _must_ be set on the command line using
* `-DMLKEM_NATIVE_CONFIG_FILE="..."`.
*
* When you need to build mlkem-native in multiple configurations,
* using varying MLKEM_NATIE_CONFIG_FILE can be more convenient
* then configuring everything through CFLAGS.
*
*****************************************************************************/
/* #define MLKEM_NATIVE_CONFIG_FILE "config.h" */

/******************************************************************************
* Name: MLKEM_NAMESPACE
*
* Description: The macros to use to namespace global symbols
* from mlkem/.
*****************************************************************************/
#define CONCAT(a, b) a##b
#define MLKEM_NAMESPACE(sym) CONCAT(mlkem512_, sym)

/******************************************************************************
* Name: FIPS202_NAMESPACE
*
* Description: The macros to use to namespace global symbols
* from mlkem/fips202/.
*****************************************************************************/
#define FIPS202_NAMESPACE(sym) CONCAT(mlkem512_, sym)

/******************************************************************************
* Name: MLKEM_USE_NATIVE
*
* Description: Determines whether a native backend should
* be used, if available.
*
* This can also be set using CFLAGS.
*
*****************************************************************************/
/* #define MLKEM_USE_NATIVE */

/******************************************************************************
* Name: MLKEM_NATIVE_ARITH_BACKEND
*
* Description: The arithmetic backend to use.
*
* This must be the filename of an arithmetic backend.
* See the existing backends for examples.
*
* This can be set using CFLAGS.
*
*****************************************************************************/
#if defined(MLKEM_USE_NATIVE) && !defined(MLKEM_NATIVE_ARITH_BACKEND)
#define MLKEM_NATIVE_ARITH_BACKEND "native/default.h"
#endif /* MLKEM_NATIVE_ARITH_BACKEND */

/******************************************************************************
* Name: MLKEM_NATIVE_FIPS202_BACKEND
*
* Description: The FIPS-202 backend to use.
*
* This must be the filename of an FIPS-202 backend.
*
* This can be set using CFLAGS.
*
*****************************************************************************/
#if defined(MLKEM_USE_NATIVE) && !defined(MLKEM_NATIVE_FIPS202_BACKEND)
#define MLKEM_NATIVE_FIPS202_BACKEND "fips202/native/default.h"
#endif /* MLKEM_NATIVE_FIPS202_BACKEND */

#endif /* MLkEM_NATIVE_CONFIG_H */
File renamed without changes.
75 changes: 39 additions & 36 deletions examples/monolithic_build/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,38 @@
* SPDX-License-Identifier: Apache-2.0
*/

#define MLKEM_NATIVE_CONFIG_FILE "config_a.h"
#include "mlkem_native_all.c"
#undef MLKEM_NATIVE_CONFIG_FILE

#define MLKEM_NATIVE_CONFIG_FILE "config_b.h"
#include "mlkem_native_all.c"
#undef MLKEM_NATIVE_CONFIG_FILE

/* Some scheme parameters from META.json
*
* TODO: One should be able to get those more easily,
* but after mlkem_native_all.c the MLKEM_XXX macros
* have already been undefined.
* This should be sorted by providing a new api.h
* header that can be included and relies solely on
* the config.h; the present kem.h does not yet have
* this property. */
#define MLKEM768_SECRETKEYBYTES 2400
#define MLKEM768_PUBLICKEYBYTES 1184
#define MLKEM768_CIPHERTEXTBYTES 1088
#define MLKEM768_BYTES 32

#define MLKEM1024_SECRETKEYBYTES 3168
#define MLKEM1024_PUBLICKEYBYTES 1568
#define MLKEM1024_CIPHERTEXTBYTES 1568
#define MLKEM1024_BYTES 32

/* Public API declaration -- those, too, should not be done
* manually, but come from a config-dependent api.h. */
int mlkem768_keypair(uint8_t *pk, uint8_t *sk);
int mlkem768_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
int mlkem768_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);

int mlkem1024_keypair(uint8_t *pk, uint8_t *sk);
int mlkem1024_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
int mlkem1024_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "mlkem_native_all.h"

static int test_keys_mlkem512(void)
{
uint8_t pk[MLKEM512_PUBLICKEYBYTES];
uint8_t sk[MLKEM512_SECRETKEYBYTES];
uint8_t ct[MLKEM512_CIPHERTEXTBYTES];
uint8_t key_a[MLKEM512_BYTES];
uint8_t key_b[MLKEM512_BYTES];

/* Alice generates a public key */
mlkem512_keypair(pk, sk);

/* Bob derives a secret key and creates a response */
mlkem512_enc(ct, key_b, pk);

/* Alice uses Bobs response to get her shared key */
mlkem512_dec(key_a, ct, sk);

if (memcmp(key_a, key_b, MLKEM512_BYTES))
{
printf("[MLKEM-512] ERROR keys\n");
return 1;
}

printf("[MLKEM-512] OK\n");
return 0;
}

static int test_keys_mlkem768(void)
{
Expand All @@ -63,6 +59,7 @@ static int test_keys_mlkem768(void)
return 1;
}

printf("[MLKEM-768] OK\n");
return 0;
}

Expand All @@ -89,11 +86,17 @@ static int test_keys_mlkem1024(void)
return 1;
}

printf("[MLKEM-1024] OK\n");
return 0;
}

int main(void)
{
if (test_keys_mlkem512() != 0)
{
return 1;
}

if (test_keys_mlkem768() != 0)
{
return 1;
Expand Down
Loading

0 comments on commit 06d16c9

Please sign in to comment.