Skip to content

Commit 9683251

Browse files
authored
Merge pull request #1188 from pq-code-package/backend_test
Add unit test target
2 parents 6296011 + 4578d05 commit 9683251

File tree

13 files changed

+818
-97
lines changed

13 files changed

+818
-97
lines changed

Makefile

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ quickcheck: test
3737
build: func kat acvp
3838
$(Q)echo " Everything builds fine!"
3939

40-
test: run_kat run_func run_acvp
40+
test: run_kat run_func run_acvp run_unit
4141
$(Q)echo " Everything checks fine!"
4242

4343
# Detect available SHA256 command
@@ -62,6 +62,14 @@ run_func_1024: func_1024
6262
$(W) $(MLKEM1024_DIR)/bin/test_mlkem1024
6363
run_func: run_func_512 run_func_768 run_func_1024
6464

65+
run_unit_512: unit_512
66+
$(W) $(MLKEM512_DIR)/bin/test_unit512
67+
run_unit_768: unit_768
68+
$(W) $(MLKEM768_DIR)/bin/test_unit768
69+
run_unit_1024: unit_1024
70+
$(W) $(MLKEM1024_DIR)/bin/test_unit1024
71+
run_unit: run_unit_512 run_unit_768 run_unit_1024
72+
6573
run_acvp: acvp
6674
python3 ./test/acvp_client.py $(if $(ACVP_VERSION),--version $(ACVP_VERSION))
6775

@@ -73,6 +81,14 @@ func_1024: $(MLKEM1024_DIR)/bin/test_mlkem1024
7381
$(Q)echo " FUNC ML-KEM-1024: $^"
7482
func: func_512 func_768 func_1024
7583

84+
unit_512: $(MLKEM512_DIR)/bin/test_unit512
85+
$(Q)echo " UNIT ML-KEM-512: $^"
86+
unit_768: $(MLKEM768_DIR)/bin/test_unit768
87+
$(Q)echo " UNIT ML-KEM-768: $^"
88+
unit_1024: $(MLKEM1024_DIR)/bin/test_unit1024
89+
$(Q)echo " UNIT ML-KEM-1024: $^"
90+
unit: unit_512 unit_768 unit_1024
91+
7692
kat_512: $(MLKEM512_DIR)/bin/gen_KAT512
7793
$(Q)echo " KAT ML-KEM-512: $^"
7894
kat_768: $(MLKEM768_DIR)/bin/gen_KAT768

mlkem/mlkem_native.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@
331331
#undef MLK_INLINE
332332
#undef MLK_MUST_CHECK_RETURN_VALUE
333333
#undef MLK_RESTRICT
334+
#undef MLK_STATIC_TESTABLE
334335
#undef MLK_SYS_AARCH64
335336
#undef MLK_SYS_AARCH64_EB
336337
#undef MLK_SYS_APPLE

mlkem/mlkem_native.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@
318318
#undef MLK_INLINE
319319
#undef MLK_MUST_CHECK_RETURN_VALUE
320320
#undef MLK_RESTRICT
321+
#undef MLK_STATIC_TESTABLE
321322
#undef MLK_SYS_AARCH64
322323
#undef MLK_SYS_AARCH64_EB
323324
#undef MLK_SYS_APPLE

mlkem/src/compress.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
* unsigned canonical coefficients here.
3535
* The reference implementation works with coefficients
3636
* in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
37-
static void mlk_poly_compress_d4_c(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D4],
38-
const mlk_poly *a)
37+
MLK_STATIC_TESTABLE void mlk_poly_compress_d4_c(
38+
uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D4], const mlk_poly *a)
3939
{
4040
unsigned i;
4141
mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
@@ -83,8 +83,8 @@ void mlk_poly_compress_d4(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D4],
8383
* unsigned canonical coefficients here.
8484
* The reference implementation works with coefficients
8585
* in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
86-
static void mlk_poly_compress_d10_c(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D10],
87-
const mlk_poly *a)
86+
MLK_STATIC_TESTABLE void mlk_poly_compress_d10_c(
87+
uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D10], const mlk_poly *a)
8888
{
8989
unsigned j;
9090
mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
@@ -132,7 +132,7 @@ void mlk_poly_compress_d10(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D10],
132132

133133
/* Reference: `poly_decompress()` in the reference implementation @[REF],
134134
* for ML-KEM-{512,768}. */
135-
static void mlk_poly_decompress_d4_c(
135+
MLK_STATIC_TESTABLE void mlk_poly_decompress_d4_c(
136136
mlk_poly *r, const uint8_t a[MLKEM_POLYCOMPRESSEDBYTES_D4])
137137
{
138138
unsigned i;
@@ -167,7 +167,7 @@ void mlk_poly_decompress_d4(mlk_poly *r,
167167

168168
/* Reference: Embedded into `polyvec_decompress()` in the
169169
* reference implementation, for ML-KEM-{512,768}. */
170-
static void mlk_poly_decompress_d10_c(
170+
MLK_STATIC_TESTABLE void mlk_poly_decompress_d10_c(
171171
mlk_poly *r, const uint8_t a[MLKEM_POLYCOMPRESSEDBYTES_D10])
172172
{
173173
unsigned j;
@@ -222,8 +222,8 @@ void mlk_poly_decompress_d10(mlk_poly *r,
222222
* unsigned canonical coefficients here.
223223
* The reference implementation works with coefficients
224224
* in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
225-
static void mlk_poly_compress_d5_c(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D5],
226-
const mlk_poly *a)
225+
MLK_STATIC_TESTABLE void mlk_poly_compress_d5_c(
226+
uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D5], const mlk_poly *a)
227227
{
228228
unsigned i;
229229
mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
@@ -277,8 +277,8 @@ void mlk_poly_compress_d5(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D5],
277277
* unsigned canonical coefficients here.
278278
* The reference implementation works with coefficients
279279
* in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
280-
static void mlk_poly_compress_d11_c(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D11],
281-
const mlk_poly *a)
280+
MLK_STATIC_TESTABLE void mlk_poly_compress_d11_c(
281+
uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D11], const mlk_poly *a)
282282
{
283283
unsigned j;
284284
mlk_assert_bound(a, MLKEM_N, 0, MLKEM_Q);
@@ -333,7 +333,7 @@ void mlk_poly_compress_d11(uint8_t r[MLKEM_POLYCOMPRESSEDBYTES_D11],
333333

334334
/* Reference: `poly_decompress()` in the reference implementation @[REF],
335335
* for ML-KEM-1024. */
336-
static void mlk_poly_decompress_d5_c(
336+
MLK_STATIC_TESTABLE void mlk_poly_decompress_d5_c(
337337
mlk_poly *r, const uint8_t a[MLKEM_POLYCOMPRESSEDBYTES_D5])
338338
{
339339
unsigned i;
@@ -396,7 +396,7 @@ void mlk_poly_decompress_d5(mlk_poly *r,
396396

397397
/* Reference: Embedded into `polyvec_decompress()` in the
398398
* reference implementation, for ML-KEM-1024. */
399-
static void mlk_poly_decompress_d11_c(
399+
MLK_STATIC_TESTABLE void mlk_poly_decompress_d11_c(
400400
mlk_poly *r, const uint8_t a[MLKEM_POLYCOMPRESSEDBYTES_D11])
401401
{
402402
unsigned j;
@@ -455,7 +455,8 @@ void mlk_poly_decompress_d11(mlk_poly *r,
455455
* unsigned canonical coefficients here.
456456
* The reference implementation works with coefficients
457457
* in the range (-MLKEM_Q+1,...,MLKEM_Q-1). */
458-
static void mlk_poly_tobytes_c(uint8_t r[MLKEM_POLYBYTES], const mlk_poly *a)
458+
MLK_STATIC_TESTABLE void mlk_poly_tobytes_c(uint8_t r[MLKEM_POLYBYTES],
459+
const mlk_poly *a)
459460
__contract__(
460461
requires(memory_no_alias(r, MLKEM_POLYBYTES))
461462
requires(memory_no_alias(a, sizeof(mlk_poly)))
@@ -509,7 +510,8 @@ void mlk_poly_tobytes(uint8_t r[MLKEM_POLYBYTES], const mlk_poly *a)
509510
}
510511

511512
/* Reference: `poly_frombytes()` in the reference implementation @[REF]. */
512-
static void mlk_poly_frombytes_c(mlk_poly *r, const uint8_t a[MLKEM_POLYBYTES])
513+
MLK_STATIC_TESTABLE void mlk_poly_frombytes_c(mlk_poly *r,
514+
const uint8_t a[MLKEM_POLYBYTES])
513515
__contract__(
514516
requires(memory_no_alias(a, MLKEM_POLYBYTES))
515517
requires(memory_no_alias(r, sizeof(mlk_poly)))

mlkem/src/poly.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ __contract__(
114114
}
115115

116116
/* Reference: `poly_tomont()` in the reference implementation @[REF]. */
117-
static void mlk_poly_tomont_c(mlk_poly *r)
117+
MLK_STATIC_TESTABLE void mlk_poly_tomont_c(mlk_poly *r)
118118
__contract__(
119119
requires(memory_no_alias(r, sizeof(mlk_poly)))
120120
assigns(memory_slice(r, sizeof(mlk_poly)))
@@ -188,7 +188,7 @@ __contract__(
188188
* here to go from signed to unsigned representatives.
189189
* This conditional addition is then dropped from all
190190
* polynomial compression functions instead (see `compress.c`). */
191-
static void mlk_poly_reduce_c(mlk_poly *r)
191+
MLK_STATIC_TESTABLE void mlk_poly_reduce_c(mlk_poly *r)
192192
__contract__(
193193
requires(memory_no_alias(r, sizeof(mlk_poly)))
194194
assigns(memory_slice(r, sizeof(mlk_poly)))
@@ -267,7 +267,8 @@ void mlk_poly_sub(mlk_poly *r, const mlk_poly *b)
267267
* - The reference implementation does not use a
268268
* multiplication cache ('mulcache'). This idea originates
269269
* from @[NeonNTT] and is used at the C level here. */
270-
static void mlk_poly_mulcache_compute_c(mlk_poly_mulcache *x, const mlk_poly *a)
270+
MLK_STATIC_TESTABLE void mlk_poly_mulcache_compute_c(mlk_poly_mulcache *x,
271+
const mlk_poly *a)
271272
__contract__(
272273
requires(memory_no_alias(x, sizeof(mlk_poly_mulcache)))
273274
requires(memory_no_alias(a, sizeof(mlk_poly)))
@@ -416,7 +417,7 @@ __contract__(
416417
/* Reference: `ntt()` in the reference implementation @[REF].
417418
* - Iterate over `layer` instead of `len` in the outer loop
418419
* to simplify computation of zeta index. */
419-
static void mlk_poly_ntt_c(mlk_poly *p)
420+
MLK_STATIC_TESTABLE void mlk_poly_ntt_c(mlk_poly *p)
420421
__contract__(
421422
requires(memory_no_alias(p, sizeof(mlk_poly)))
422423
requires(array_abs_bound(p->coeffs, 0, MLKEM_N, MLKEM_Q))
@@ -506,7 +507,7 @@ __contract__(
506507
* while the reference implementation normalizes at
507508
* the end. This allows us to drop a call to `poly_reduce()`
508509
* from the base multiplication. */
509-
static void mlk_poly_invntt_tomont_c(mlk_poly *p)
510+
MLK_STATIC_TESTABLE void mlk_poly_invntt_tomont_c(mlk_poly *p)
510511
__contract__(
511512
requires(memory_no_alias(p, sizeof(mlk_poly)))
512513
assigns(memory_slice(p, sizeof(mlk_poly)))

mlkem/src/poly_k.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ void mlk_polyvec_invntt_tomont(mlk_polyvec r)
148148
* at the end. The reference implementation uses 2 * MLKEM_K
149149
* more modular reductions since it reduces after every modular
150150
* multiplication. */
151-
static void mlk_polyvec_basemul_acc_montgomery_cached_c(
151+
MLK_STATIC_TESTABLE void mlk_polyvec_basemul_acc_montgomery_cached_c(
152152
mlk_poly *r, const mlk_polyvec a, const mlk_polyvec b,
153153
const mlk_polyvec_mulcache b_cache)
154154
__contract__(

mlkem/src/sampling.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
* in that it adds the offset and always expects the base of the
3030
* target buffer. This avoids shifting the buffer base in the
3131
* caller, which appears tricky to reason about. */
32-
static unsigned mlk_rej_uniform_c(int16_t *r, unsigned target, unsigned offset,
33-
const uint8_t *buf, unsigned buflen)
32+
MLK_STATIC_TESTABLE unsigned mlk_rej_uniform_c(int16_t *r, unsigned target,
33+
unsigned offset,
34+
const uint8_t *buf,
35+
unsigned buflen)
3436
__contract__(
3537
requires(offset <= target && target <= 4096 && buflen <= 4096 && buflen % 3 == 0)
3638
requires(memory_no_alias(r, sizeof(int16_t) * target))

mlkem/src/sys.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@
119119
#endif /* inline */
120120
#endif /* !MLK_INLINE */
121121

122+
#ifndef MLK_STATIC_TESTABLE
123+
#define MLK_STATIC_TESTABLE static
124+
#endif
125+
122126
/*
123127
* C90 does not have the restrict compiler directive yet.
124128
* We don't use it in C90 builds.

scripts/tests

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ class TEST_TYPES(Enum):
209209
STACK = 15
210210
SIZE = 16
211211
BASIC_DETERMINISTIC = 17
212+
UNIT = 18
212213

213214
def is_benchmark(self):
214215
return self in [TEST_TYPES.BENCH, TEST_TYPES.BENCH_COMPONENTS]
@@ -278,6 +279,8 @@ class TEST_TYPES(Enum):
278279
return "Example (multilevel build, native)"
279280
if self == TEST_TYPES.SIZE:
280281
return "Measurement Code Size"
282+
if self == TEST_TYPES.UNIT:
283+
return "Unit Test"
281284

282285
def make_dir(self):
283286
if self == TEST_TYPES.BRING_YOUR_OWN_FIPS202:
@@ -337,6 +340,8 @@ class TEST_TYPES(Enum):
337340
return ""
338341
if self == TEST_TYPES.SIZE:
339342
return "size"
343+
if self == TEST_TYPES.UNIT:
344+
return "unit"
340345

341346
def make_run_target(self, scheme):
342347
t = self.make_target()
@@ -618,6 +623,19 @@ class Tests:
618623

619624
self.check_fail()
620625

626+
def unit(self):
627+
def _unit(opt):
628+
self._compile_schemes(TEST_TYPES.UNIT, opt)
629+
if self.args.run:
630+
self._run_schemes(TEST_TYPES.UNIT, opt)
631+
632+
if self.do_no_opt():
633+
_unit(False)
634+
if self.do_opt():
635+
_unit(True)
636+
637+
self.check_fail()
638+
621639
def acvp(self):
622640
def _acvp(opt):
623641
self._compile_schemes(TEST_TYPES.ACVP, opt)
@@ -751,6 +769,7 @@ class Tests:
751769
acvp = self.args.acvp
752770
examples = self.args.examples
753771
stack = self.args.stack
772+
unit = self.args.unit
754773

755774
def _all(opt):
756775
if func is True:
@@ -761,6 +780,8 @@ class Tests:
761780
self._compile_schemes(TEST_TYPES.ACVP, opt)
762781
if stack is True:
763782
self._compile_schemes(TEST_TYPES.STACK, opt)
783+
if unit is True:
784+
self._compile_schemes(TEST_TYPES.UNIT, opt)
764785

765786
if self.args.run is False:
766787
return
@@ -773,6 +794,8 @@ class Tests:
773794
self._run_scheme(TEST_TYPES.ACVP, opt, None)
774795
if stack is True:
775796
self._run_schemes(TEST_TYPES.STACK, opt, suppress_output=False)
797+
if unit is True:
798+
self._run_schemes(TEST_TYPES.UNIT, opt)
776799

777800
if self.do_no_opt():
778801
_all(False)
@@ -1066,6 +1089,14 @@ def cli():
10661089
"--no-acvp", action="store_false", dest="acvp", help="Do not run acvp test"
10671090
)
10681091

1092+
unit_group = all_parser.add_mutually_exclusive_group()
1093+
unit_group.add_argument(
1094+
"--unit", action="store_true", dest="unit", help="Run unit test", default=True
1095+
)
1096+
unit_group.add_argument(
1097+
"--no-unit", action="store_false", dest="unit", help="Do not run unit test"
1098+
)
1099+
10691100
examples_group = all_parser.add_mutually_exclusive_group()
10701101
examples_group.add_argument(
10711102
"--examples",
@@ -1286,6 +1317,13 @@ def cli():
12861317
"kat", help="Run the kat tests for all parameter sets", parents=[common_parser]
12871318
)
12881319

1320+
# unit arguments
1321+
unit_parser = cmd_subparsers.add_parser(
1322+
"unit",
1323+
help="Run the unit tests for all parameter sets",
1324+
parents=[common_parser],
1325+
)
1326+
12891327
# stack arguments
12901328
stack_parser = cmd_subparsers.add_parser(
12911329
"stack",
@@ -1330,6 +1368,8 @@ def cli():
13301368
Tests(args).func()
13311369
elif args.cmd == "kat":
13321370
Tests(args).kat()
1371+
elif args.cmd == "unit":
1372+
Tests(args).unit()
13331373
elif args.cmd == "stack":
13341374
Tests(args).stack()
13351375
elif args.cmd == "size":

0 commit comments

Comments
 (0)