Skip to content

Commit 07fa974

Browse files
committed
Make tests and examples compatible with reduced-API configurations
Add MLK_CONFIG_NO_KEYPAIR_API, MLK_CONFIG_NO_ENCAPS_API and MLK_CONFIG_NO_DECAPS_API, and guard public and internal APIs accordingly. Generate deterministic KEM vectors so tests and examples can exercise each enabled operation independently. Adapt ACVP, Wycheproof, allocation, RNG failure and stack tests to reduced builds; stack analysis measures only enabled APIs. Cover all non-empty reduced API combinations in CI. Signed-off-by: Hanno Becker <beckphan@amazon.co.uk>
1 parent 2cf613b commit 07fa974

133 files changed

Lines changed: 5850 additions & 1503 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/config-variations/action.yml

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ inputs:
1111
description: 'List of tests to run (space-separated IDs) or "all" for all tests. Available IDs: pct-enabled,
1212
pct-enabled-broken, custom-alloc-heap, custom-zeroize, native-cap-ON, native-cap-OFF, native-cap-ID_AA64PFR1_EL1,
1313
native-cap-CPUID_AVX2, no-asm, serial-fips202, custom-randombytes, custom-memcpy, custom-memset, custom-stdlib,
14-
nblocks-1, nblocks-2, nblocks-4'
14+
nblocks-1, nblocks-2, nblocks-4, keygen-only, encaps-only, decaps-only, keygen-encaps, keygen-decaps, encaps-decaps'
1515
required: false
1616
default: 'all'
1717
opt:
@@ -276,3 +276,93 @@ runs:
276276
examples: false # Some examples use a custom config themselves
277277
alloc: false # Requires custom config
278278
rng_fail: true
279+
- name: "Keygen-only API"
280+
if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'keygen-only') }}
281+
uses: ./.github/actions/multi-functest
282+
with:
283+
gh_token: ${{ inputs.gh_token }}
284+
compile_mode: native
285+
cflags: "-DMLK_CONFIG_NO_ENCAPS_API -DMLK_CONFIG_NO_DECAPS_API -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
286+
ldflags: "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
287+
func: true
288+
kat: true
289+
acvp: true
290+
stack: true
291+
rng_fail: true
292+
opt: ${{ inputs.opt }}
293+
examples: true
294+
- name: "Encaps-only API"
295+
if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'encaps-only') }}
296+
uses: ./.github/actions/multi-functest
297+
with:
298+
gh_token: ${{ inputs.gh_token }}
299+
compile_mode: native
300+
cflags: "-DMLK_CONFIG_NO_KEYPAIR_API -DMLK_CONFIG_NO_DECAPS_API -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
301+
ldflags: "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
302+
func: true
303+
kat: true
304+
acvp: true
305+
stack: true
306+
rng_fail: true
307+
opt: ${{ inputs.opt }}
308+
examples: true
309+
- name: "Decaps-only API"
310+
if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'decaps-only') }}
311+
uses: ./.github/actions/multi-functest
312+
with:
313+
gh_token: ${{ inputs.gh_token }}
314+
compile_mode: native
315+
cflags: "-DMLK_CONFIG_NO_KEYPAIR_API -DMLK_CONFIG_NO_ENCAPS_API -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
316+
ldflags: "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
317+
func: true
318+
kat: true
319+
acvp: true
320+
stack: true
321+
rng_fail: true
322+
opt: ${{ inputs.opt }}
323+
examples: true
324+
- name: "Keygen+Encaps API (no decaps)"
325+
if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'keygen-encaps') }}
326+
uses: ./.github/actions/multi-functest
327+
with:
328+
gh_token: ${{ inputs.gh_token }}
329+
compile_mode: native
330+
cflags: "-DMLK_CONFIG_NO_DECAPS_API -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
331+
ldflags: "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
332+
func: true
333+
kat: true
334+
acvp: true
335+
stack: true
336+
rng_fail: true
337+
opt: ${{ inputs.opt }}
338+
examples: true
339+
- name: "Keygen+Decaps API (no encaps)"
340+
if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'keygen-decaps') }}
341+
uses: ./.github/actions/multi-functest
342+
with:
343+
gh_token: ${{ inputs.gh_token }}
344+
compile_mode: native
345+
cflags: "-DMLK_CONFIG_NO_ENCAPS_API -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
346+
ldflags: "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
347+
func: true
348+
kat: true
349+
acvp: true
350+
stack: true
351+
rng_fail: true
352+
opt: ${{ inputs.opt }}
353+
examples: true
354+
- name: "Encaps+Decaps API (no keygen)"
355+
if: ${{ inputs.tests == 'all' || contains(inputs.tests, 'encaps-decaps') }}
356+
uses: ./.github/actions/multi-functest
357+
with:
358+
gh_token: ${{ inputs.gh_token }}
359+
compile_mode: native
360+
cflags: "-DMLK_CONFIG_NO_KEYPAIR_API -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
361+
ldflags: "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
362+
func: true
363+
kat: true
364+
acvp: true
365+
stack: true
366+
rng_fail: true
367+
opt: ${{ inputs.opt }}
368+
examples: true

META.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
# Checks the KAT output of a gen_KAT binary against META.yml.
66
#
77
# Reads the KAT bytes from stdin, hashes them with SHA-256, and compares
8-
# against the kat-sha256 field for the given scheme in META.yml.
8+
# against the kat-sha256 field for the given scheme in META.yml. If stdin is
9+
# "SKIPPED" (emitted by gen_KAT for reduced-API builds), the check is reported
10+
# as skipped.
911
#
1012
# To run manually, pipe a gen_KAT binary into it, e.g.:
1113
#
@@ -53,9 +55,16 @@ def main():
5355
err(f"META.yml: no kat-sha256 entry for {scheme_name}")
5456
sys.exit(1)
5557

56-
# Hash the raw bytes piped in from gen_KAT on stdin. Read in binary mode so
58+
# Read the raw bytes piped in from gen_KAT on stdin. Read in binary mode so
5759
# that no newline translation occurs on Windows.
58-
computed = hashlib.sha256(sys.stdin.buffer.read()).hexdigest()
60+
data = sys.stdin.buffer.read()
61+
62+
# Reduced-API builds emit "SKIPPED" instead of KAT bytes; report as skipped.
63+
if data.startswith(b"SKIPPED"):
64+
info(f"META.yml {scheme_name} kat-sha256: SKIPPED")
65+
sys.exit(0)
66+
67+
computed = hashlib.sha256(data).hexdigest()
5968

6069
if computed == ref:
6170
info(f"META.yml {scheme_name} kat-sha256: OK")

dev/aarch64_clean/meta.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static MLK_INLINE int mlk_ntt_native(int16_t data[MLKEM_N])
3737
return MLK_NATIVE_FUNC_SUCCESS;
3838
}
3939

40+
#if !defined(MLK_CONFIG_NO_ENCAPS_API) || !defined(MLK_CONFIG_NO_DECAPS_API)
4041
MLK_MUST_CHECK_RETURN_VALUE
4142
static MLK_INLINE int mlk_intt_native(int16_t data[MLKEM_N])
4243
{
@@ -48,6 +49,7 @@ static MLK_INLINE int mlk_intt_native(int16_t data[MLKEM_N])
4849
mlk_aarch64_invntt_zetas_layer67);
4950
return MLK_NATIVE_FUNC_SUCCESS;
5051
}
52+
#endif /* !MLK_CONFIG_NO_ENCAPS_API || !MLK_CONFIG_NO_DECAPS_API */
5153

5254
MLK_MUST_CHECK_RETURN_VALUE
5355
static MLK_INLINE int mlk_poly_reduce_native(int16_t data[MLKEM_N])
@@ -60,6 +62,7 @@ static MLK_INLINE int mlk_poly_reduce_native(int16_t data[MLKEM_N])
6062
return MLK_NATIVE_FUNC_SUCCESS;
6163
}
6264

65+
#if !defined(MLK_CONFIG_NO_KEYPAIR_API)
6366
MLK_MUST_CHECK_RETURN_VALUE
6467
static MLK_INLINE int mlk_poly_tomont_native(int16_t data[MLKEM_N])
6568
{
@@ -70,6 +73,7 @@ static MLK_INLINE int mlk_poly_tomont_native(int16_t data[MLKEM_N])
7073
mlk_poly_tomont_aarch64_asm(data);
7174
return MLK_NATIVE_FUNC_SUCCESS;
7275
}
76+
#endif /* !MLK_CONFIG_NO_KEYPAIR_API */
7377

7478
MLK_MUST_CHECK_RETURN_VALUE
7579
static MLK_INLINE int mlk_poly_mulcache_compute_native(int16_t x[MLKEM_N / 2],
@@ -130,6 +134,7 @@ static MLK_INLINE int mlk_polyvec_basemul_acc_montgomery_cached_k4_native(
130134
}
131135
#endif /* MLK_CONFIG_MULTILEVEL_WITH_SHARED || MLKEM_K == 4 */
132136

137+
#if !defined(MLK_CONFIG_NO_KEYPAIR_API) || !defined(MLK_CONFIG_NO_ENCAPS_API)
133138
MLK_MUST_CHECK_RETURN_VALUE
134139
static MLK_INLINE int mlk_poly_tobytes_native(uint8_t r[MLKEM_POLYBYTES],
135140
const int16_t a[MLKEM_N])
@@ -141,6 +146,7 @@ static MLK_INLINE int mlk_poly_tobytes_native(uint8_t r[MLKEM_POLYBYTES],
141146
mlk_poly_tobytes_aarch64_asm(r, a);
142147
return MLK_NATIVE_FUNC_SUCCESS;
143148
}
149+
#endif /* !MLK_CONFIG_NO_KEYPAIR_API || !MLK_CONFIG_NO_ENCAPS_API */
144150

145151
MLK_MUST_CHECK_RETURN_VALUE
146152
static MLK_INLINE int mlk_rej_uniform_native(int16_t *r, unsigned len,

dev/aarch64_clean/src/aarch64_zetas.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
7979
10129, 10129, -3878, -3878, -11566, -11566,
8080
};
8181

82+
#if !defined(MLK_CONFIG_NO_ENCAPS_API) || !defined(MLK_CONFIG_NO_DECAPS_API)
8283
MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
8384
mlk_aarch64_invntt_zetas_layer12345[80] = {
8485
1583, 15582, -821, -8081, 1355, 13338, 0, 0, -569,
@@ -138,6 +139,7 @@ MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
138139
1041, -1637, -1637, -583, -583, -17, -17, 10247, 10247,
139140
-16113, -16113, -5739, -5739, -167, -167,
140141
};
142+
#endif /* !MLK_CONFIG_NO_ENCAPS_API || !MLK_CONFIG_NO_DECAPS_API */
141143

142144
MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
143145
mlk_aarch64_zetas_mulcache_native[128] = {

dev/aarch64_clean/src/intt_aarch64_asm.S

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252

5353
#include "../../../common.h"
5454
#if defined(MLK_ARITH_BACKEND_AARCH64) && \
55-
!defined(MLK_CONFIG_MULTILEVEL_NO_SHARED)
55+
!defined(MLK_CONFIG_MULTILEVEL_NO_SHARED) && \
56+
(!defined(MLK_CONFIG_NO_ENCAPS_API) || \
57+
!defined(MLK_CONFIG_NO_DECAPS_API))
5658
/* simpasm: header-end */
5759

5860
// Bounds:
@@ -400,4 +402,5 @@ intt_layer123_start:
400402
.unreq ninv_tw
401403

402404
/* simpasm: footer-start */
403-
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED */
405+
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED && \
406+
(!MLK_CONFIG_NO_ENCAPS_API || !MLK_CONFIG_NO_DECAPS_API) */

dev/aarch64_clean/src/poly_tobytes_aarch64_asm.S

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929

3030
#include "../../../common.h"
3131
#if defined(MLK_ARITH_BACKEND_AARCH64) && \
32-
!defined(MLK_CONFIG_MULTILEVEL_NO_SHARED)
32+
!defined(MLK_CONFIG_MULTILEVEL_NO_SHARED) && \
33+
(!defined(MLK_CONFIG_NO_KEYPAIR_API) || \
34+
!defined(MLK_CONFIG_NO_ENCAPS_API))
3335
/* simpasm: header-end */
3436

3537
.macro ld2_wrap a, ptr
@@ -94,4 +96,5 @@ poly_tobytes_loop_start:
9496
.unreq count
9597

9698
/* simpasm: footer-start */
97-
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED */
99+
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED && \
100+
(!MLK_CONFIG_NO_KEYPAIR_API || !MLK_CONFIG_NO_ENCAPS_API) */

dev/aarch64_clean/src/poly_tomont_aarch64_asm.S

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323

2424
#include "../../../common.h"
2525
#if defined(MLK_ARITH_BACKEND_AARCH64) && \
26-
!defined(MLK_CONFIG_MULTILEVEL_NO_SHARED)
26+
!defined(MLK_CONFIG_MULTILEVEL_NO_SHARED) && \
27+
!defined(MLK_CONFIG_NO_KEYPAIR_API)
2728
/* simpasm: header-end */
2829

2930
/* Montgomery multiplication, with precomputed Montgomery twist
@@ -103,4 +104,5 @@ poly_tomont_loop:
103104
.unreq tmp0
104105

105106
/* simpasm: footer-start */
106-
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED */
107+
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED && \
108+
!MLK_CONFIG_NO_KEYPAIR_API */

dev/aarch64_opt/meta.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static MLK_INLINE int mlk_ntt_native(int16_t data[MLKEM_N])
3737
return MLK_NATIVE_FUNC_SUCCESS;
3838
}
3939

40+
#if !defined(MLK_CONFIG_NO_ENCAPS_API) || !defined(MLK_CONFIG_NO_DECAPS_API)
4041
MLK_MUST_CHECK_RETURN_VALUE
4142
static MLK_INLINE int mlk_intt_native(int16_t data[MLKEM_N])
4243
{
@@ -48,6 +49,7 @@ static MLK_INLINE int mlk_intt_native(int16_t data[MLKEM_N])
4849
mlk_aarch64_invntt_zetas_layer67);
4950
return MLK_NATIVE_FUNC_SUCCESS;
5051
}
52+
#endif /* !MLK_CONFIG_NO_ENCAPS_API || !MLK_CONFIG_NO_DECAPS_API */
5153

5254
MLK_MUST_CHECK_RETURN_VALUE
5355
static MLK_INLINE int mlk_poly_reduce_native(int16_t data[MLKEM_N])
@@ -60,6 +62,7 @@ static MLK_INLINE int mlk_poly_reduce_native(int16_t data[MLKEM_N])
6062
return MLK_NATIVE_FUNC_SUCCESS;
6163
}
6264

65+
#if !defined(MLK_CONFIG_NO_KEYPAIR_API)
6366
MLK_MUST_CHECK_RETURN_VALUE
6467
static MLK_INLINE int mlk_poly_tomont_native(int16_t data[MLKEM_N])
6568
{
@@ -70,6 +73,7 @@ static MLK_INLINE int mlk_poly_tomont_native(int16_t data[MLKEM_N])
7073
mlk_poly_tomont_aarch64_asm(data);
7174
return MLK_NATIVE_FUNC_SUCCESS;
7275
}
76+
#endif /* !MLK_CONFIG_NO_KEYPAIR_API */
7377

7478
MLK_MUST_CHECK_RETURN_VALUE
7579
static MLK_INLINE int mlk_poly_mulcache_compute_native(int16_t x[MLKEM_N / 2],
@@ -130,6 +134,7 @@ static MLK_INLINE int mlk_polyvec_basemul_acc_montgomery_cached_k4_native(
130134
}
131135
#endif /* MLK_CONFIG_MULTILEVEL_WITH_SHARED || MLKEM_K == 4 */
132136

137+
#if !defined(MLK_CONFIG_NO_KEYPAIR_API) || !defined(MLK_CONFIG_NO_ENCAPS_API)
133138
MLK_MUST_CHECK_RETURN_VALUE
134139
static MLK_INLINE int mlk_poly_tobytes_native(uint8_t r[MLKEM_POLYBYTES],
135140
const int16_t a[MLKEM_N])
@@ -141,6 +146,7 @@ static MLK_INLINE int mlk_poly_tobytes_native(uint8_t r[MLKEM_POLYBYTES],
141146
mlk_poly_tobytes_aarch64_asm(r, a);
142147
return MLK_NATIVE_FUNC_SUCCESS;
143148
}
149+
#endif /* !MLK_CONFIG_NO_KEYPAIR_API || !MLK_CONFIG_NO_ENCAPS_API */
144150

145151
MLK_MUST_CHECK_RETURN_VALUE
146152
static MLK_INLINE int mlk_rej_uniform_native(int16_t *r, unsigned len,

dev/aarch64_opt/src/aarch64_zetas.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
7979
10129, 10129, -3878, -3878, -11566, -11566,
8080
};
8181

82+
#if !defined(MLK_CONFIG_NO_ENCAPS_API) || !defined(MLK_CONFIG_NO_DECAPS_API)
8283
MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
8384
mlk_aarch64_invntt_zetas_layer12345[80] = {
8485
1583, 15582, -821, -8081, 1355, 13338, 0, 0, -569,
@@ -138,6 +139,7 @@ MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
138139
1041, -1637, -1637, -583, -583, -17, -17, 10247, 10247,
139140
-16113, -16113, -5739, -5739, -167, -167,
140141
};
142+
#endif /* !MLK_CONFIG_NO_ENCAPS_API || !MLK_CONFIG_NO_DECAPS_API */
141143

142144
MLK_ALIGN MLK_INTERNAL_DATA_DEFINITION const int16_t
143145
mlk_aarch64_zetas_mulcache_native[128] = {

dev/aarch64_opt/src/intt_aarch64_asm.S

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@
5151
*/
5252

5353
#include "../../../common.h"
54-
#if defined(MLK_ARITH_BACKEND_AARCH64) && !defined(MLK_CONFIG_MULTILEVEL_NO_SHARED)
54+
#if defined(MLK_ARITH_BACKEND_AARCH64) && \
55+
!defined(MLK_CONFIG_MULTILEVEL_NO_SHARED) && \
56+
(!defined(MLK_CONFIG_NO_ENCAPS_API) || \
57+
!defined(MLK_CONFIG_NO_DECAPS_API))
5558
/* simpasm: header-end */
5659

5760
// Bounds:
@@ -1420,4 +1423,5 @@ intt_layer123_start:
14201423
.unreq ninv_tw
14211424

14221425
/* simpasm: footer-start */
1423-
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED */
1426+
#endif /* MLK_ARITH_BACKEND_AARCH64 && !MLK_CONFIG_MULTILEVEL_NO_SHARED && \
1427+
(!MLK_CONFIG_NO_ENCAPS_API || !MLK_CONFIG_NO_DECAPS_API) */

0 commit comments

Comments
 (0)