Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_mldsa_poly.c
Go to the documentation of this file.
1/*****************************************************************************
2 * (c) 2026 Ledger SAS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
24#include "cx_mldsa_poly.h"
25
26// clang-format off
27static const int32_t mldsa_zetas[MLDSA_N] = {
28 0, 25847, -2608894, -518909, 237124, -777960, -876248,
29 466468, 1826347, 2353451, -359251, -2091905, 3119733, -2884855,
30 3111497, 2680103, 2725464, 1024112, -1079900, 3585928, -549488,
31 -1119584, 2619752, -2108549, -2118186, -3859737, -1399561, -3277672,
32 1757237, -19422, 4010497, 280005, 2706023, 95776, 3077325,
33 3530437, -1661693, -3592148, -2537516, 3915439, -3861115, -3043716,
34 3574422, -2867647, 3539968, -300467, 2348700, -539299, -1699267,
35 -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596,
36 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892,
37 -2797779, -3930395, -1528703, -3677745, -3041255, -1452451, 3475950,
38 2176455, -1585221, -1257611, 1939314, -4083598, -1000202, -3190144,
39 -3157330, -3632928, 126922, 3412210, -983419, 2147896, 2715295,
40 -2967645, -3693493, -411027, -2477047, -671102, -1228525, -22981,
41 -1308169, -381987, 1349076, 1852771, -1430430, -3343383, 264944,
42 508951, 3097992, 44288, -1100098, 904516, 3958618, -3724342,
43 -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856,
44 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589,
45 1341330, 1285669, -1584928, -812732, -1439742, -3019102, -3881060,
46 -3628969, 3839961, 2091667, 3407706, 2316500, 3817976, -3342478,
47 2244091, -2446433, -3562462, 266997, 2434439, -1235728, 3513181,
48 -3520352, -3759364, -1197226, -3193378, 900702, 1859098, 909542,
49 819034, 495491, -1613174, -43260, -522500, -655327, -3122442,
50 2031748, 3207046, -3556995, -525098, -768622, -3595838, 342297,
51 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044,
52 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353,
53 1595974, -3767016, 1250494, 2635921, -3548272, -2994039, 1869119,
54 1903435, -1050970, -1333058, 1237275, -3318210, -1430225, -451100,
55 1312455, 3306115, -1962642, -1279661, 1917081, -2546312, -1374803,
56 1500165, 777191, 2235880, 3406031, -542412, -2831860, -1671176,
57 -1846953, -2584293, -3724270, 594136, -3776993, -2013608, 2432395,
58 2454455, -164721, 1957272, 3369112, 185531, -1207385, -3183426,
59 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107,
60 -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735,
61 472078, -426683, 1723600, -1803090, 1910376, -1667432, -1104333,
62 -260646, -3833893, -2939036, -2235985, -420899, -2286327, 183443,
63 -976891, 1612842, -3545687, -554416, 3919660, -48306, -1362209,
64 3937738, 1400424, -846154, 1976782,
65};
66// clang-format on
67
69{
70 int32_t t;
71 t = (int32_t) ((int64_t) (int32_t) a * (int64_t) MLDSA_QINV);
72 t = (int32_t) ((a - (int64_t) t * (int64_t) MLDSA_Q) >> 32);
73 return t;
74}
75
76int32_t MLDSA_POLY_reduce32(int32_t a)
77{
78 int32_t t;
79 t = (a + (1 << 22)) >> 23;
80 t = a - t * MLDSA_Q;
81 return t;
82}
83
84int32_t MLDSA_POLY_caddq(int32_t a)
85{
86 a += (a >> 31) & MLDSA_Q;
87 return a;
88}
89
91{
92 for (uint32_t i = 0U; i < MLDSA_N; i++) {
93 a->coeffs[i] = MLDSA_POLY_reduce32(a->coeffs[i]);
94 }
95}
96
98{
99 for (uint32_t i = 0U; i < MLDSA_N; i++) {
100 a->coeffs[i] = MLDSA_POLY_caddq(a->coeffs[i]);
101 }
102}
103
105{
106 for (uint32_t i = 0U; i < MLDSA_N; i++) {
107 a->coeffs[i] += b->coeffs[i];
108 }
109}
110
112{
113 for (uint32_t i = 0U; i < MLDSA_N; i++) {
114 a->coeffs[i] -= b->coeffs[i];
115 }
116}
117
119{
120 for (uint32_t i = 0U; i < MLDSA_N; i++) {
121 a->coeffs[i] <<= MLDSA_D;
122 }
123}
124
126{
127 uint32_t k = 0U;
128 for (uint32_t len = 128U; len >= 1U; len >>= 1U) {
129 for (uint32_t start = 0U; start < MLDSA_N; start += 2U * len) {
130 k++;
131 int32_t zeta = mldsa_zetas[k];
132 for (uint32_t j = start; j < start + len; j++) {
133 int32_t t = MLDSA_POLY_montgomery_reduce((int64_t) zeta * a->coeffs[j + len]);
134 a->coeffs[j + len] = a->coeffs[j] - t;
135 a->coeffs[j] = a->coeffs[j] + t;
136 }
137 }
138 }
139}
140
142{
143 uint32_t k = MLDSA_N;
144 int32_t f = 41978; // mont^2 / 256
145 for (uint32_t len = 1U; len < MLDSA_N; len <<= 1U) {
146 for (uint32_t start = 0U; start < MLDSA_N; start += 2U * len) {
147 k--;
148 int32_t zeta = -mldsa_zetas[k];
149 for (uint32_t j = start; j < start + len; j++) {
150 int32_t t = a->coeffs[j];
151 a->coeffs[j] = t + a->coeffs[j + len];
152 a->coeffs[j + len] = t - a->coeffs[j + len];
153 a->coeffs[j + len]
154 = MLDSA_POLY_montgomery_reduce((int64_t) zeta * a->coeffs[j + len]);
155 }
156 }
157 }
158 for (uint32_t j = 0U; j < MLDSA_N; j++) {
159 a->coeffs[j] = MLDSA_POLY_montgomery_reduce((int64_t) f * a->coeffs[j]);
160 }
161}
162
164 const mldsa_poly *a,
165 const mldsa_poly *b,
166 int first)
167{
168 for (uint32_t i = 0U; i < MLDSA_N; i++) {
169 int32_t t = MLDSA_POLY_montgomery_reduce((int64_t) a->coeffs[i] * b->coeffs[i]);
170 if (first) {
171 c->coeffs[i] = t;
172 }
173 else {
174 c->coeffs[i] += t;
175 }
176 }
177}
178
179int MLDSA_POLY_chknorm(const mldsa_poly *a, int32_t B)
180{
181 if (B > (MLDSA_Q - 1) / 8) {
182 return 1;
183 }
184 for (uint32_t i = 0U; i < MLDSA_N; i++) {
185 int32_t t = a->coeffs[i] >> 31;
186 t = a->coeffs[i] - (t & (2 * a->coeffs[i]));
187 if (t >= B) {
188 return 1;
189 }
190 }
191 return 0;
192}
void MLDSA_POLY_reduce(mldsa_poly *a)
Applies reduce32 to all coefficients of a polynomial.
int32_t MLDSA_POLY_caddq(int32_t a)
Adds q if input is negative.
int32_t MLDSA_POLY_montgomery_reduce(int64_t a)
Montgomery reduction: given a 64-bit integer, compute a*q^{-1} mod 2^32.
int MLDSA_POLY_chknorm(const mldsa_poly *a, int32_t B)
Checks infinity norm of polynomial against bound B.
void MLDSA_POLY_ntt(mldsa_poly *a)
Forward NTT in place.
int32_t MLDSA_POLY_reduce32(int32_t a)
Reduce coefficient to representative in about (-6283009, 6283009).
static const int32_t mldsa_zetas[MLDSA_N]
void MLDSA_POLY_sub(mldsa_poly *a, const mldsa_poly *b)
Subtracts polynomial b from polynomial a in place.
void MLDSA_POLY_shiftl(mldsa_poly *a)
Shifts all coefficients left by D bits.
void MLDSA_POLY_caddq_all(mldsa_poly *a)
Applies caddq to all coefficients of a polynomial.
void MLDSA_POLY_add(mldsa_poly *a, const mldsa_poly *b)
Adds polynomial b to polynomial a in place.
void MLDSA_POLY_invntt_tomont(mldsa_poly *a)
Inverse NTT and multiply by Montgomery factor.
void MLDSA_POLY_pointwise_montgomery(mldsa_poly *c, const mldsa_poly *a, const mldsa_poly *b, int first)
Pointwise multiplication (Montgomery) with accumulation.
#define MLDSA_QINV
#define MLDSA_D
Definition lcx_mldsa.h:39
#define MLDSA_N
Definition lcx_mldsa.h:37
#define MLDSA_Q
Definition lcx_mldsa.h:38
Polynomial with MLDSA_N int32_t coefficients.
int32_t coeffs[MLDSA_N]