Skip to content

Commit 4743633

Browse files
committed
Add new example basic_deterministic
This commit: - Adds the `basic_deterministic` example demonstrating deterministic API usage (without a `randombytes()` implementation). - Uses only the `crypto_kem_*_derand` functions, no `randombytes()` required. - Updates the expected key outputs for deterministic entropy inputs (Alice: all 0 input, Bob: all 1 input). Signed-off-by: willieyz <[email protected]>
1 parent df54483 commit 4743633

File tree

11 files changed

+775
-0
lines changed

11 files changed

+775
-0
lines changed

.github/workflows/base.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ jobs:
227227
- name: basic
228228
run: |
229229
CFLAGS="-O0" make run -C examples/basic
230+
- name: basic_deterministic
231+
run: |
232+
CFLAGS="-O0" make run -C examples/basic_deterministic
230233
- name: bring_your_own_fips202
231234
run: |
232235
CFLAGS="-O0" make run -C examples/bring_your_own_fips202

BIBLIOGRAPHY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ source code and documentation.
2626
- National Institute of Standards and Technology
2727
* URL: https://csrc.nist.gov/projects/cryptographic-module-validation-program/fips-140-3-ig-announcements
2828
* Referenced from:
29+
- [examples/basic_deterministic/mlkem_native/custom_no_randomized_config.h](examples/basic_deterministic/mlkem_native/custom_no_randomized_config.h)
2930
- [integration/liboqs/config_aarch64.h](integration/liboqs/config_aarch64.h)
3031
- [integration/liboqs/config_c.h](integration/liboqs/config_c.h)
3132
- [integration/liboqs/config_x86_64.h](integration/liboqs/config_x86_64.h)

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ clean:
218218
-make clean -C examples/bring_your_own_fips202 >/dev/null
219219
-make clean -C examples/custom_backend >/dev/null
220220
-make clean -C examples/basic >/dev/null
221+
-make clean -C examples/basic_deterministic >/dev/null
221222
-make clean -C examples/monolithic_build >/dev/null
222223
-make clean -C examples/monolithic_build_native >/dev/null
223224
-make clean -C examples/monolithic_build_multilevel >/dev/null

examples/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ This directory contains minimal examples demonstrating how you can use mlkem-nat
88

99
See [basic](basic) for a basic example of how to build a single instance of mlkem-native.
1010

11+
## Basic_deterministic
12+
13+
See [basic_deterministic](basic_deterministic) for a basic example of how to build a single instance of mlkem-native without `randombytes()` implementation. This allows users to build mlkem-native using only the deterministic API when randomized functions are not required.
1114
## Multi-level build (C only)
1215

1316
See [multilevel_build](multilevel_build) for an example of how to build one instance of mlkem-native per security level,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
2+
3+
build
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# (SPDX-License-Identifier: CC-BY-4.0)
2+
3+
.PHONY: build run clean size
4+
.DEFAULT_GOAL := all
5+
6+
# Append cross-prefix for cross compilation
7+
# Remove or ignore for native builds
8+
CC ?= gcc
9+
SIZE ?= size
10+
# When called from the root Makefile, CROSS_PREFIX has already been added here
11+
ifeq (,$(findstring $(CROSS_PREFIX),$(CC)))
12+
CC := $(CROSS_PREFIX)$(CC)
13+
endif
14+
15+
ifeq (,$(findstring $(CROSS_PREFIX),$(SIZE)))
16+
SIZE := $(CROSS_PREFIX)$(SIZE)
17+
endif
18+
19+
# Part A:
20+
#
21+
# mlkem-native source and header files
22+
#
23+
# If you are not concerned about minimizing for a specific backend,
24+
# you can just include _all_ source files into your build.
25+
MLK_SOURCE=$(wildcard \
26+
mlkem_native/mlkem/src/*.c \
27+
mlkem_native/mlkem/src/**/*.c \
28+
mlkem_native/mlkem/src/**/**/*.c \
29+
mlkem_native/mlkem/src/**/**/**/*.c)
30+
31+
# Part B:
32+
#
33+
# Your application source code
34+
APP_SOURCE=$(wildcard *.c)
35+
36+
ALL_SOURCE=$(MLK_SOURCE) $(RNG_SOURCE) $(APP_SOURCE)
37+
38+
BUILD_DIR=build
39+
BIN=test_binary
40+
41+
CFLAGS := \
42+
-Wall \
43+
-Wextra \
44+
-Werror \
45+
-Wmissing-prototypes \
46+
-Wshadow \
47+
-Werror \
48+
-Wpointer-arith \
49+
-Wredundant-decls \
50+
-Wno-long-long \
51+
-Wno-unknown-pragmas \
52+
-Wno-unused-command-line-argument \
53+
-fomit-frame-pointer \
54+
-std=c99 \
55+
-pedantic \
56+
-MMD \
57+
-O3 \
58+
-Imlkem_native \
59+
$(CFLAGS)
60+
61+
CFLAGS += -DMLK_CONFIG_NAMESPACE_PREFIX=mlkem
62+
CFLAGS += -DMLK_CONFIG_FILE="\"custom_no_randomized_config.h\""
63+
64+
BINARY_NAME_FULL_512=$(BUILD_DIR)/$(BIN)512
65+
BINARY_NAME_FULL_768=$(BUILD_DIR)/$(BIN)768
66+
BINARY_NAME_FULL_1024=$(BUILD_DIR)/$(BIN)1024
67+
BINARIES_FULL=$(BINARY_NAME_FULL_512) $(BINARY_NAME_FULL_768) $(BINARY_NAME_FULL_1024)
68+
69+
$(BINARY_NAME_FULL_512): CFLAGS += -DMLK_CONFIG_PARAMETER_SET=512
70+
$(BINARY_NAME_FULL_768): CFLAGS += -DMLK_CONFIG_PARAMETER_SET=768
71+
$(BINARY_NAME_FULL_1024): CFLAGS += -DMLK_CONFIG_PARAMETER_SET=1024
72+
73+
$(BINARIES_FULL): $(ALL_SOURCE)
74+
echo "$@"
75+
mkdir -p $(BUILD_DIR)
76+
$(CC) $(CFLAGS) $^ -o $@
77+
78+
all: build size
79+
80+
build: $(BINARIES_FULL)
81+
82+
run: $(BINARIES_FULL)
83+
$(EXEC_WRAPPER) ./$(BINARY_NAME_FULL_512)
84+
$(EXEC_WRAPPER) ./$(BINARY_NAME_FULL_768)
85+
$(EXEC_WRAPPER) ./$(BINARY_NAME_FULL_1024)
86+
87+
size: build
88+
@echo "=== Size info for $(BINARY_NAME_FULL_512) ==="
89+
@$(SIZE) $(BINARY_NAME_FULL_512)
90+
@echo "=== Size info for $(BINARY_NAME_FULL_768) ==="
91+
@$(SIZE) $(BINARY_NAME_FULL_768)
92+
@echo "=== Size info for $(BINARY_NAME_FULL_1024) ==="
93+
@$(SIZE) $(BINARY_NAME_FULL_1024)
94+
95+
clean:
96+
rm -rf $(BUILD_DIR)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[//]: # (SPDX-License-Identifier: CC-BY-4.0)
2+
3+
# Building mlkem-native
4+
5+
This directory contains a minimal example showing how to build **mlkem-native** for use cases only requiring the deterministic key generation and encapsulation APIs (`crypto_kem_keypair_derand` and `crypto_kem_enc_derand`). In that case, no implementation of `randombytes()` has to be provided.
6+
7+
## Components
8+
9+
An application using mlkem-native as-is needs to include the following components:
10+
11+
1. mlkem-native source tree, including [`mlkem/src/`](../../mlkem/src) and [`mlkem/src/fips202/`](../../mlkem/src/fips202).
12+
2. The application source code
13+
14+
15+
## Usage
16+
17+
Build this example with `make build`, run with `make run`.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright (c) The mlkem-native project authors
3+
* SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
4+
*/
5+
6+
#include <stdio.h>
7+
#include <string.h>
8+
9+
/* Import public mlkem-native API
10+
*
11+
* This requires specifying the parameter set and namespace prefix
12+
* used for the build.
13+
*/
14+
#define MLK_CONFIG_API_PARAMETER_SET MLK_CONFIG_PARAMETER_SET
15+
#define MLK_CONFIG_API_NAMESPACE_PREFIX mlkem
16+
#include "mlkem_native/mlkem/mlkem_native.h"
17+
18+
/* No randombytes needed for deterministic API */
19+
20+
#define CHECK(x) \
21+
do \
22+
{ \
23+
int rc; \
24+
rc = (x); \
25+
if (!rc) \
26+
{ \
27+
fprintf(stderr, "ERROR (%s,%d)\n", __FILE__, __LINE__); \
28+
return 1; \
29+
} \
30+
} while (0)
31+
32+
int main(void)
33+
{
34+
uint8_t pk[CRYPTO_PUBLICKEYBYTES];
35+
uint8_t sk[CRYPTO_SECRETKEYBYTES];
36+
uint8_t ct[CRYPTO_CIPHERTEXTBYTES];
37+
uint8_t key_a[CRYPTO_BYTES];
38+
uint8_t key_b[CRYPTO_BYTES];
39+
uint8_t alice_en[2 * MLKEM_SYMBYTES] = {0};
40+
uint8_t bob_en[MLKEM_SYMBYTES] = {1};
41+
42+
43+
/* The PCT modifies the PRNG state, so the KAT tests don't work.
44+
* We run KAT tests only for disabled PCT.
45+
* Expected keys are generated using deterministic entropy:
46+
* keypair uses all-zero entropy {0}, enc uses all-one entropy {1} */
47+
#if !defined(MLK_CONFIG_KEYGEN_PCT)
48+
#if MLK_CONFIG_PARAMETER_SET == 512
49+
const uint8_t expected_key[] = {
50+
0x5f, 0x5f, 0x8c, 0xf5, 0x7c, 0x34, 0xd4, 0x68, 0x06, 0xa2, 0xe9,
51+
0xc9, 0x28, 0xba, 0x10, 0x5a, 0x46, 0xf2, 0x67, 0x1a, 0xc7, 0x81,
52+
0xdf, 0xf1, 0x4a, 0xbb, 0x27, 0xea, 0x46, 0x06, 0x46, 0x3c};
53+
#elif MLK_CONFIG_PARAMETER_SET == 768
54+
const uint8_t expected_key[] = {
55+
0x85, 0x21, 0xab, 0xc8, 0x14, 0xc7, 0x67, 0x70, 0x4f, 0xa6, 0x25,
56+
0xd9, 0x35, 0x95, 0xd0, 0x03, 0x79, 0xa8, 0xb3, 0x70, 0x35, 0x2c,
57+
0xa4, 0xba, 0xb3, 0xa6, 0x82, 0x46, 0x63, 0x0d, 0xb0, 0x8b};
58+
#elif MLK_CONFIG_PARAMETER_SET == 1024
59+
const uint8_t expected_key[] = {
60+
0x30, 0x4d, 0xbe, 0x54, 0xd6, 0x6f, 0x80, 0x66, 0xc6, 0xa8, 0x1c,
61+
0x6b, 0x36, 0xc4, 0x48, 0x9b, 0xf9, 0xe6, 0x05, 0x79, 0x83, 0x3c,
62+
0x4e, 0xdc, 0x8a, 0xc7, 0x92, 0xe5, 0x73, 0x0d, 0xdd, 0x85};
63+
#endif /* MLK_CONFIG_PARAMETER_SET == 1024 */
64+
#endif /* !MLK_CONFIG_KEYGEN_PCT */
65+
66+
/* No randombytes_reset() needed for deterministic API */
67+
68+
printf("Generating keypair ... ");
69+
70+
/* Alice generates a public key using deterministic API with all-zero entropy
71+
*/
72+
CHECK(crypto_kem_keypair_derand(pk, sk, alice_en) == 0);
73+
74+
printf("DONE\n");
75+
printf("Encaps... ");
76+
77+
/* Bob derives a secret key and creates a response using deterministic API
78+
* with all-one entropy */
79+
CHECK(crypto_kem_enc_derand(ct, key_b, pk, bob_en) == 0);
80+
81+
printf("DONE\n");
82+
printf("Decaps... ");
83+
84+
/* Alice uses Bobs response to get her shared key */
85+
CHECK(crypto_kem_dec(key_a, ct, sk) == 0);
86+
87+
printf("DONE\n");
88+
printf("Compare... ");
89+
90+
CHECK(memcmp(key_a, key_b, CRYPTO_BYTES) == 0);
91+
92+
printf("Shared secret: ");
93+
{
94+
size_t i;
95+
for (i = 0; i < sizeof(key_a); i++)
96+
{
97+
printf("%02x", key_a[i]);
98+
}
99+
}
100+
printf("\n");
101+
102+
/* Check against hardcoded result to make sure that
103+
* we integrated custom FIPS202 correctly */
104+
CHECK(memcmp(key_a, expected_key, CRYPTO_BYTES) == 0);
105+
106+
107+
printf("OK\n");
108+
return 0;
109+
}

0 commit comments

Comments
 (0)