Skip to content

Commit 5b598cc

Browse files
committed
C-ref NTT: merge layer pairs, switch fqmul to twisted Montgomery
Rewrite mlk_poly_ntt_c / mlk_poly_invntt_tomont_c to process two layers at a time, with three 2-layer passes plus the leftover layer 7 as a single layer. Introduces shared mlk_ct_butterfly and mlk_gs_butterfly helpers; the inverse 2-layer block applies four GS butterflies and then Barrett-reduces the additive outputs explicitly. mlk_fqmul now takes a precomputed b_twisted = b * MLKEM_Q^{-1} mod 2^16 and uses a hi-mul / lo-mul-and-correct sequence in place of an inline mlk_montgomery_reduce, dropping the QINV multiply. The mlk_zetas table is regenerated as int16_t[128][2] of (zeta_mont, zeta_twisted) pairs. Signed-off-by: Hanno Becker <beckphan@amazon.co.uk>
1 parent 57d18f4 commit 5b598cc

16 files changed

Lines changed: 588 additions & 100 deletions

File tree

mlkem/src/poly.c

Lines changed: 280 additions & 71 deletions
Large diffs are not rendered by default.

mlkem/src/zetas.inc

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,39 @@
1212

1313
/*
1414
* Table of zeta values used in the reference NTT and inverse NTT.
15-
* See autogen for details.
15+
* Each row is (zeta_mont, zeta_twisted); see autogen for details.
1616
*/
17-
static MLK_ALIGN const int16_t mlk_zetas[128] = {
18-
-1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577,
19-
182, 962, -1202, -1474, 1468, 573, -1325, 264, 383, -829, 1458,
20-
-1602, -130, -681, 1017, 732, 608, -1542, 411, -205, -1571, 1223,
21-
652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666,
22-
-1618, -1162, 126, 1469, -853, -90, -271, 830, 107, -1421, -247,
23-
-951, -398, 961, -1508, -725, 448, -1065, 677, -1275, -1103, 430,
24-
555, 843, -1251, 871, 1550, 105, 422, 587, 177, -235, -291,
25-
-460, 1574, 1653, -246, 778, 1159, -147, -777, 1483, -602, 1119,
26-
-1590, 644, -872, 349, 418, 329, -156, -75, 817, 1097, 603,
27-
610, 1322, -1285, -1465, 384, -1215, -136, 1218, -1335, -874, 220,
28-
-1187, -1659, -1185, -1530, -1278, 794, -1510, -854, -870, 478, -108,
29-
-308, 996, 991, 958, -1460, 1522, 1628,
17+
static MLK_ALIGN const int16_t mlk_zetas[128][2] = {
18+
{-1044, -20}, {-758, 31498}, {-359, 14745}, {-1517, 787},
19+
{1493, 13525}, {1422, -12402}, {287, 28191}, {202, -16694},
20+
{-171, -20907}, {622, 27758}, {1577, -3799}, {182, -15690},
21+
{962, 10690}, {-1202, 1358}, {-1474, -11202}, {1468, 31164},
22+
{573, -5827}, {-1325, 17363}, {264, -26360}, {383, -29057},
23+
{-829, 5571}, {1458, -1102}, {-1602, 21438}, {-130, -26242},
24+
{-681, -28073}, {1017, 24313}, {732, -10532}, {608, 8800},
25+
{-1542, 18426}, {411, 8859}, {-205, 26675}, {-1571, -16163},
26+
{1223, -5689}, {652, -6516}, {-552, 1496}, {1015, 30967},
27+
{-1293, -23565}, {1491, 20179}, {-282, 20710}, {-1544, 25080},
28+
{516, -12796}, {-8, 26616}, {-320, 16064}, {-666, -12442},
29+
{-1618, 9134}, {-1162, -650}, {126, -25986}, {1469, 27837},
30+
{-853, 19883}, {-90, -28250}, {-271, -15887}, {830, -8898},
31+
{107, -28309}, {-1421, 9075}, {-247, -30199}, {-951, 18249},
32+
{-398, 13426}, {961, 14017}, {-1508, -29156}, {-725, -12757},
33+
{448, 16832}, {-1065, 4311}, {677, -24155}, {-1275, -17915},
34+
{-1103, -335}, {430, 11182}, {555, -11477}, {843, 13387},
35+
{-1251, -32227}, {871, -14233}, {1550, 20494}, {105, -21655},
36+
{422, -27738}, {587, 13131}, {177, 945}, {-235, -4587},
37+
{-291, -14883}, {-460, 23092}, {1574, 6182}, {1653, 5493},
38+
{-246, 32010}, {778, -32502}, {1159, 10631}, {-147, 30317},
39+
{-777, 29175}, {1483, -18741}, {-602, -28762}, {1119, 12639},
40+
{-1590, -18486}, {644, 20100}, {-872, 17560}, {349, 18525},
41+
{418, -14430}, {329, 19529}, {-156, -5276}, {-75, -12619},
42+
{817, -31183}, {1097, 20297}, {603, 25435}, {610, 2146},
43+
{1322, -7382}, {-1285, 15355}, {-1465, 24391}, {384, -32384},
44+
{-1215, -20927}, {-136, -6280}, {1218, 10946}, {-1335, -14903},
45+
{-874, 24214}, {220, -11044}, {-1187, 16989}, {-1659, 14469},
46+
{-1185, 10335}, {-1530, -21498}, {-1278, -7934}, {794, -20198},
47+
{-1510, -22502}, {-854, 23210}, {-870, 10906}, {478, -17442},
48+
{-108, 31636}, {-308, -23860}, {996, 28644}, {991, -20257},
49+
{958, 23998}, {-1460, 7756}, {1522, -17422}, {1628, 23132},
3050
};

proofs/cbmc/fqmul/fqmul_harness.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
#include "common.h"
77

88

9-
int16_t mlk_fqmul(int16_t a, int16_t b);
9+
int16_t mlk_fqmul(int16_t a, int16_t b, int16_t b_twisted);
1010

1111
void harness(void)
1212
{
13-
int16_t a, b, r;
13+
int16_t a, b, b_twisted, r;
1414

15-
r = mlk_fqmul(a, b);
15+
r = mlk_fqmul(a, b, b_twisted);
1616
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright (c) The mlkem-native project authors
2+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
include ../Makefile_params.common
5+
6+
HARNESS_ENTRY = harness
7+
HARNESS_FILE = invntt_2_layers_harness
8+
9+
# This should be a unique identifier for this proof, and will appear on the
10+
# Litani dashboard. It can be human-readable and contain spaces if you wish.
11+
PROOF_UID = mlk_invntt_2_layers
12+
13+
DEFINES +=
14+
INCLUDES +=
15+
16+
REMOVE_FUNCTION_BODY +=
17+
UNWINDSET +=
18+
19+
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
20+
PROJECT_SOURCES += $(SRCDIR)/mlkem/src/poly.c
21+
22+
CHECK_FUNCTION_CONTRACTS=mlk_invntt_2_layers
23+
USE_FUNCTION_CONTRACTS=mlk_invntt_2_layers_block
24+
APPLY_LOOP_CONTRACTS=on
25+
USE_DYNAMIC_FRAMES=1
26+
27+
EXTERNAL_SAT_SOLVER=
28+
CBMCFLAGS=--smt2
29+
30+
FUNCTION_NAME = mlk_invntt_2_layers
31+
32+
CBMC_OBJECT_BITS = 8
33+
34+
include ../Makefile.common
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) The mlkem-native project authors
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: MIT-0
4+
5+
#include "poly.h"
6+
7+
8+
void mlk_invntt_2_layers(int16_t *r, unsigned layer);
9+
10+
void harness(void)
11+
{
12+
int16_t *r;
13+
unsigned layer;
14+
mlk_invntt_2_layers(r, layer);
15+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright (c) The mlkem-native project authors
2+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
include ../Makefile_params.common
5+
6+
HARNESS_ENTRY = harness
7+
HARNESS_FILE = invntt_2_layers_block_harness
8+
9+
PROOF_UID = mlk_invntt_2_layers_block
10+
11+
DEFINES +=
12+
INCLUDES +=
13+
14+
REMOVE_FUNCTION_BODY +=
15+
UNWINDSET +=
16+
17+
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
18+
PROJECT_SOURCES += $(SRCDIR)/mlkem/src/poly.c
19+
20+
CHECK_FUNCTION_CONTRACTS=mlk_invntt_2_layers_block
21+
USE_FUNCTION_CONTRACTS = mlk_fqmul
22+
USE_FUNCTION_CONTRACTS += mlk_barrett_reduce
23+
APPLY_LOOP_CONTRACTS=on
24+
USE_DYNAMIC_FRAMES=1
25+
26+
EXTERNAL_SAT_SOLVER=
27+
CBMCFLAGS=--smt2
28+
29+
FUNCTION_NAME = mlk_invntt_2_layers_block
30+
31+
CBMC_OBJECT_BITS = 9
32+
33+
include ../Makefile.common
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) The mlkem-native project authors
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: MIT-0
4+
5+
#include <stdint.h>
6+
#include "common.h"
7+
8+
9+
void mlk_invntt_2_layers_block(int16_t *r, unsigned start, unsigned len,
10+
int16_t z0, int16_t z0_twst, int16_t z1,
11+
int16_t z1_twst, int16_t z2, int16_t z2_twst);
12+
13+
void harness(void)
14+
{
15+
int16_t *r;
16+
unsigned start, len;
17+
int16_t z0, z0_twst, z1, z1_twst, z2, z2_twst;
18+
mlk_invntt_2_layers_block(r, start, len, z0, z0_twst, z1, z1_twst, z2,
19+
z2_twst);
20+
}

proofs/cbmc/ntt_2_layers/Makefile

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright (c) The mlkem-native project authors
2+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
include ../Makefile_params.common
5+
6+
HARNESS_ENTRY = harness
7+
HARNESS_FILE = ntt_2_layers_harness
8+
9+
# This should be a unique identifier for this proof, and will appear on the
10+
# Litani dashboard. It can be human-readable and contain spaces if you wish.
11+
PROOF_UID = mlk_ntt_2_layers
12+
13+
DEFINES +=
14+
INCLUDES +=
15+
16+
REMOVE_FUNCTION_BODY +=
17+
UNWINDSET +=
18+
19+
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
20+
PROJECT_SOURCES += $(SRCDIR)/mlkem/src/poly.c
21+
22+
CHECK_FUNCTION_CONTRACTS=mlk_ntt_2_layers
23+
USE_FUNCTION_CONTRACTS=mlk_ntt_2_layers_block
24+
APPLY_LOOP_CONTRACTS=on
25+
USE_DYNAMIC_FRAMES=1
26+
27+
# Disable any setting of EXTERNAL_SAT_SOLVER, and choose SMT backend instead
28+
EXTERNAL_SAT_SOLVER=
29+
CBMCFLAGS=--bitwuzla
30+
31+
FUNCTION_NAME = mlk_ntt_2_layers
32+
33+
# If this proof is found to consume huge amounts of RAM, you can set the
34+
# EXPENSIVE variable. With new enough versions of the proof tools, this will
35+
# restrict the number of EXPENSIVE CBMC jobs running at once. See the
36+
# documentation in Makefile.common under the "Job Pools" heading for details.
37+
# EXPENSIVE = true
38+
39+
# This function is large enough to need...
40+
CBMC_OBJECT_BITS = 8
41+
42+
include ../Makefile.common
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) The mlkem-native project authors
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: MIT-0
4+
5+
#include "poly.h"
6+
7+
8+
void mlk_ntt_2_layers(int16_t *r, unsigned layer);
9+
10+
void harness(void)
11+
{
12+
int16_t *r;
13+
unsigned layer;
14+
mlk_ntt_2_layers(r, layer);
15+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright (c) The mlkem-native project authors
2+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
3+
4+
include ../Makefile_params.common
5+
6+
HARNESS_ENTRY = harness
7+
HARNESS_FILE = ntt_2_layers_block_harness
8+
9+
PROOF_UID = mlk_ntt_2_layers_block
10+
11+
DEFINES +=
12+
INCLUDES +=
13+
14+
REMOVE_FUNCTION_BODY +=
15+
UNWINDSET +=
16+
17+
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
18+
PROJECT_SOURCES += $(SRCDIR)/mlkem/src/poly.c
19+
20+
CHECK_FUNCTION_CONTRACTS=mlk_ntt_2_layers_block
21+
USE_FUNCTION_CONTRACTS=mlk_fqmul
22+
APPLY_LOOP_CONTRACTS=on
23+
USE_DYNAMIC_FRAMES=1
24+
25+
EXTERNAL_SAT_SOLVER=
26+
CBMCFLAGS=--bitwuzla
27+
28+
FUNCTION_NAME = mlk_ntt_2_layers_block
29+
30+
CBMC_OBJECT_BITS = 9
31+
32+
include ../Makefile.common

0 commit comments

Comments
 (0)