Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_mldsa_packing.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 *****************************************************************************/
21#include <string.h>
22#include "cx_mldsa_packing.h"
23
24/*---------------------------------------------------------------------------
25 * t1 packing: 10 bits per coefficient, 256 coefficients = 320 bytes.
26 *---------------------------------------------------------------------------*/
28{
29 for (uint32_t i = 0U; i < MLDSA_N / 4U; i++) {
30 r[5U * i + 0U] = (uint8_t) (a->coeffs[4U * i + 0U] >> 0U);
31 r[5U * i + 1U]
32 = (uint8_t) ((a->coeffs[4U * i + 0U] >> 8U) | (a->coeffs[4U * i + 1U] << 2U));
33 r[5U * i + 2U]
34 = (uint8_t) ((a->coeffs[4U * i + 1U] >> 6U) | (a->coeffs[4U * i + 2U] << 4U));
35 r[5U * i + 3U]
36 = (uint8_t) ((a->coeffs[4U * i + 2U] >> 4U) | (a->coeffs[4U * i + 3U] << 6U));
37 r[5U * i + 4U] = (uint8_t) (a->coeffs[4U * i + 3U] >> 2U);
38 }
39}
40
42{
43 for (uint32_t i = 0U; i < MLDSA_N / 4U; i++) {
44 r->coeffs[4U * i + 0U]
45 = (((uint32_t) a[5U * i + 0U] >> 0U) | ((uint32_t) a[5U * i + 1U] << 8U)) & 0x3FFU;
46 r->coeffs[4U * i + 1U]
47 = (((uint32_t) a[5U * i + 1U] >> 2U) | ((uint32_t) a[5U * i + 2U] << 6U)) & 0x3FFU;
48 r->coeffs[4U * i + 2U]
49 = (((uint32_t) a[5U * i + 2U] >> 4U) | ((uint32_t) a[5U * i + 3U] << 4U)) & 0x3FFU;
50 r->coeffs[4U * i + 3U]
51 = (((uint32_t) a[5U * i + 3U] >> 6U) | ((uint32_t) a[5U * i + 4U] << 2U)) & 0x3FFU;
52 }
53}
54
55/*---------------------------------------------------------------------------
56 * t0 packing: 13 bits per coefficient, coefficients in (-(2^12), 2^12].
57 *---------------------------------------------------------------------------*/
59{
60 int32_t t[8];
61 for (uint32_t i = 0U; i < MLDSA_N / 8U; i++) {
62 t[0] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 0U];
63 t[1] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 1U];
64 t[2] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 2U];
65 t[3] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 3U];
66 t[4] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 4U];
67 t[5] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 5U];
68 t[6] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 6U];
69 t[7] = (1 << (MLDSA_D - 1)) - a->coeffs[8U * i + 7U];
70
71 r[13U * i + 0U] = (uint8_t) t[0];
72 r[13U * i + 1U] = (uint8_t) (t[0] >> 8U);
73 r[13U * i + 1U] |= (uint8_t) (t[1] << 5U);
74 r[13U * i + 2U] = (uint8_t) (t[1] >> 3U);
75 r[13U * i + 3U] = (uint8_t) (t[1] >> 11U);
76 r[13U * i + 3U] |= (uint8_t) (t[2] << 2U);
77 r[13U * i + 4U] = (uint8_t) (t[2] >> 6U);
78 r[13U * i + 4U] |= (uint8_t) (t[3] << 7U);
79 r[13U * i + 5U] = (uint8_t) (t[3] >> 1U);
80 r[13U * i + 6U] = (uint8_t) (t[3] >> 9U);
81 r[13U * i + 6U] |= (uint8_t) (t[4] << 4U);
82 r[13U * i + 7U] = (uint8_t) (t[4] >> 4U);
83 r[13U * i + 8U] = (uint8_t) (t[4] >> 12U);
84 r[13U * i + 8U] |= (uint8_t) (t[5] << 1U);
85 r[13U * i + 9U] = (uint8_t) (t[5] >> 7U);
86 r[13U * i + 9U] |= (uint8_t) (t[6] << 6U);
87 r[13U * i + 10U] = (uint8_t) (t[6] >> 2U);
88 r[13U * i + 11U] = (uint8_t) (t[6] >> 10U);
89 r[13U * i + 11U] |= (uint8_t) (t[7] << 3U);
90 r[13U * i + 12U] = (uint8_t) (t[7] >> 5U);
91 }
92}
93
95{
96 for (uint32_t i = 0U; i < MLDSA_N / 8U; i++) {
97 r->coeffs[8U * i + 0U]
98 = (int32_t) (((uint32_t) a[13U * i + 0U] | ((uint32_t) a[13U * i + 1U] << 8U))
99 & 0x1FFFU);
100 r->coeffs[8U * i + 1U]
101 = (int32_t) ((((uint32_t) a[13U * i + 1U] >> 5U) | ((uint32_t) a[13U * i + 2U] << 3U)
102 | ((uint32_t) a[13U * i + 3U] << 11U))
103 & 0x1FFFU);
104 r->coeffs[8U * i + 2U]
105 = (int32_t) ((((uint32_t) a[13U * i + 3U] >> 2U) | ((uint32_t) a[13U * i + 4U] << 6U))
106 & 0x1FFFU);
107 r->coeffs[8U * i + 3U]
108 = (int32_t) ((((uint32_t) a[13U * i + 4U] >> 7U) | ((uint32_t) a[13U * i + 5U] << 1U)
109 | ((uint32_t) a[13U * i + 6U] << 9U))
110 & 0x1FFFU);
111 r->coeffs[8U * i + 4U]
112 = (int32_t) ((((uint32_t) a[13U * i + 6U] >> 4U) | ((uint32_t) a[13U * i + 7U] << 4U)
113 | ((uint32_t) a[13U * i + 8U] << 12U))
114 & 0x1FFFU);
115 r->coeffs[8U * i + 5U]
116 = (int32_t) ((((uint32_t) a[13U * i + 8U] >> 1U) | ((uint32_t) a[13U * i + 9U] << 7U))
117 & 0x1FFFU);
118 r->coeffs[8U * i + 6U]
119 = (int32_t) ((((uint32_t) a[13U * i + 9U] >> 6U) | ((uint32_t) a[13U * i + 10U] << 2U)
120 | ((uint32_t) a[13U * i + 11U] << 10U))
121 & 0x1FFFU);
122 r->coeffs[8U * i + 7U]
123 = (int32_t) ((((uint32_t) a[13U * i + 11U] >> 3U) | ((uint32_t) a[13U * i + 12U] << 5U))
124 & 0x1FFFU);
125
126 r->coeffs[8U * i + 0U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 0U];
127 r->coeffs[8U * i + 1U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 1U];
128 r->coeffs[8U * i + 2U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 2U];
129 r->coeffs[8U * i + 3U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 3U];
130 r->coeffs[8U * i + 4U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 4U];
131 r->coeffs[8U * i + 5U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 5U];
132 r->coeffs[8U * i + 6U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 6U];
133 r->coeffs[8U * i + 7U] = (1 << (MLDSA_D - 1)) - r->coeffs[8U * i + 7U];
134 }
135}
136
137/*---------------------------------------------------------------------------
138 * eta packing
139 *---------------------------------------------------------------------------*/
140uint32_t MLDSA_PACK_polyeta(uint8_t *r, const mldsa_poly *a, uint8_t eta)
141{
142 if (eta == 2U) {
143 // 3 bits per coefficient, pack 8 coefficients in 3 bytes
144 for (uint32_t i = 0U; i < MLDSA_N / 8U; i++) {
145 uint8_t t[8];
146 for (uint32_t j = 0U; j < 8U; j++) {
147 t[j] = (uint8_t) ((int32_t) eta - a->coeffs[8U * i + j]);
148 }
149
150 r[3U * i + 0U] = (t[0] >> 0U) | (t[1] << 3U) | (t[2] << 6U);
151 r[3U * i + 1U] = (t[2] >> 2U) | (t[3] << 1U) | (t[4] << 4U) | (t[5] << 7U);
152 r[3U * i + 2U] = (t[5] >> 1U) | (t[6] << 2U) | (t[7] << 5U);
153 }
154 return MLDSA_N * 3U / 8U; // 96 bytes
155 }
156 else {
157 // eta == 4: 4 bits per coefficient
158 for (uint32_t i = 0U; i < MLDSA_N / 2U; i++) {
159 uint8_t t0 = (uint8_t) ((int32_t) eta - a->coeffs[2U * i + 0U]);
160 uint8_t t1 = (uint8_t) ((int32_t) eta - a->coeffs[2U * i + 1U]);
161 r[i] = t0 | (t1 << 4U);
162 }
163 return MLDSA_N / 2U; // 128 bytes
164 }
165}
166
167uint32_t MLDSA_PACK_unpack_polyeta(mldsa_poly *r, const uint8_t *a, uint8_t eta)
168{
169 if (eta == 2U) {
170 for (uint32_t i = 0U; i < MLDSA_N / 8U; i++) {
171 r->coeffs[8U * i + 0U] = (int32_t) ((a[3U * i + 0U] >> 0U) & 7U);
172 r->coeffs[8U * i + 1U] = (int32_t) ((a[3U * i + 0U] >> 3U) & 7U);
173 r->coeffs[8U * i + 2U]
174 = (int32_t) (((a[3U * i + 0U] >> 6U) | (a[3U * i + 1U] << 2U)) & 7U);
175 r->coeffs[8U * i + 3U] = (int32_t) ((a[3U * i + 1U] >> 1U) & 7U);
176 r->coeffs[8U * i + 4U] = (int32_t) ((a[3U * i + 1U] >> 4U) & 7U);
177 r->coeffs[8U * i + 5U]
178 = (int32_t) (((a[3U * i + 1U] >> 7U) | (a[3U * i + 2U] << 1U)) & 7U);
179 r->coeffs[8U * i + 6U] = (int32_t) ((a[3U * i + 2U] >> 2U) & 7U);
180 r->coeffs[8U * i + 7U] = (int32_t) ((a[3U * i + 2U] >> 5U) & 7U);
181
182 r->coeffs[8U * i + 0U] = (int32_t) eta - r->coeffs[8U * i + 0U];
183 r->coeffs[8U * i + 1U] = (int32_t) eta - r->coeffs[8U * i + 1U];
184 r->coeffs[8U * i + 2U] = (int32_t) eta - r->coeffs[8U * i + 2U];
185 r->coeffs[8U * i + 3U] = (int32_t) eta - r->coeffs[8U * i + 3U];
186 r->coeffs[8U * i + 4U] = (int32_t) eta - r->coeffs[8U * i + 4U];
187 r->coeffs[8U * i + 5U] = (int32_t) eta - r->coeffs[8U * i + 5U];
188 r->coeffs[8U * i + 6U] = (int32_t) eta - r->coeffs[8U * i + 6U];
189 r->coeffs[8U * i + 7U] = (int32_t) eta - r->coeffs[8U * i + 7U];
190 }
191 return MLDSA_N * 3U / 8U;
192 }
193 else {
194 for (uint32_t i = 0U; i < MLDSA_N / 2U; i++) {
195 r->coeffs[2U * i + 0U] = (int32_t) (a[i] & 0x0FU);
196 r->coeffs[2U * i + 1U] = (int32_t) (a[i] >> 4U);
197 r->coeffs[2U * i + 0U] = (int32_t) eta - r->coeffs[2U * i + 0U];
198 r->coeffs[2U * i + 1U] = (int32_t) eta - r->coeffs[2U * i + 1U];
199 }
200 return MLDSA_N / 2U;
201 }
202}
203
204/*---------------------------------------------------------------------------
205 * z packing
206 *---------------------------------------------------------------------------*/
207uint32_t MLDSA_PACK_polyz(uint8_t *r, const mldsa_poly *a, int32_t gamma1)
208{
209 int32_t t[4];
210
211 if (gamma1 == (1 << 17)) {
212 // 18 bits per coefficient
213 for (uint32_t i = 0U; i < MLDSA_N / 4U; i++) {
214 t[0] = gamma1 - a->coeffs[4U * i + 0U];
215 t[1] = gamma1 - a->coeffs[4U * i + 1U];
216 t[2] = gamma1 - a->coeffs[4U * i + 2U];
217 t[3] = gamma1 - a->coeffs[4U * i + 3U];
218
219 r[9U * i + 0U] = (uint8_t) t[0];
220 r[9U * i + 1U] = (uint8_t) (t[0] >> 8U);
221 r[9U * i + 2U] = (uint8_t) ((t[0] >> 16U) | (t[1] << 2U));
222 r[9U * i + 3U] = (uint8_t) (t[1] >> 6U);
223 r[9U * i + 4U] = (uint8_t) ((t[1] >> 14U) | (t[2] << 4U));
224 r[9U * i + 5U] = (uint8_t) (t[2] >> 4U);
225 r[9U * i + 6U] = (uint8_t) ((t[2] >> 12U) | (t[3] << 6U));
226 r[9U * i + 7U] = (uint8_t) (t[3] >> 2U);
227 r[9U * i + 8U] = (uint8_t) (t[3] >> 10U);
228 }
229 return 576U;
230 }
231 else {
232 // 20 bits per coefficient
233 for (uint32_t i = 0U; i < MLDSA_N / 2U; i++) {
234 t[0] = gamma1 - a->coeffs[2U * i + 0U];
235 t[1] = gamma1 - a->coeffs[2U * i + 1U];
236
237 r[5U * i + 0U] = (uint8_t) t[0];
238 r[5U * i + 1U] = (uint8_t) (t[0] >> 8U);
239 r[5U * i + 2U] = (uint8_t) ((t[0] >> 16U) | (t[1] << 4U));
240 r[5U * i + 3U] = (uint8_t) (t[1] >> 4U);
241 r[5U * i + 4U] = (uint8_t) (t[1] >> 12U);
242 }
243 return 640U;
244 }
245}
246
247uint32_t MLDSA_PACK_unpack_polyz(mldsa_poly *r, const uint8_t *a, int32_t gamma1)
248{
249 if (gamma1 == (1 << 17)) {
250 for (uint32_t i = 0U; i < MLDSA_N / 4U; i++) {
251 r->coeffs[4U * i + 0U]
252 = (int32_t) (((uint32_t) a[9U * i + 0U] | ((uint32_t) a[9U * i + 1U] << 8U)
253 | ((uint32_t) a[9U * i + 2U] << 16U))
254 & 0x3FFFFU);
255 r->coeffs[4U * i + 1U]
256 = (int32_t) ((((uint32_t) a[9U * i + 2U] >> 2U) | ((uint32_t) a[9U * i + 3U] << 6U)
257 | ((uint32_t) a[9U * i + 4U] << 14U))
258 & 0x3FFFFU);
259 r->coeffs[4U * i + 2U]
260 = (int32_t) ((((uint32_t) a[9U * i + 4U] >> 4U) | ((uint32_t) a[9U * i + 5U] << 4U)
261 | ((uint32_t) a[9U * i + 6U] << 12U))
262 & 0x3FFFFU);
263 r->coeffs[4U * i + 3U]
264 = (int32_t) ((((uint32_t) a[9U * i + 6U] >> 6U) | ((uint32_t) a[9U * i + 7U] << 2U)
265 | ((uint32_t) a[9U * i + 8U] << 10U))
266 & 0x3FFFFU);
267
268 r->coeffs[4U * i + 0U] = gamma1 - r->coeffs[4U * i + 0U];
269 r->coeffs[4U * i + 1U] = gamma1 - r->coeffs[4U * i + 1U];
270 r->coeffs[4U * i + 2U] = gamma1 - r->coeffs[4U * i + 2U];
271 r->coeffs[4U * i + 3U] = gamma1 - r->coeffs[4U * i + 3U];
272 }
273 return 576U;
274 }
275 else {
276 for (uint32_t i = 0U; i < MLDSA_N / 2U; i++) {
277 r->coeffs[2U * i + 0U]
278 = (int32_t) (((uint32_t) a[5U * i + 0U] | ((uint32_t) a[5U * i + 1U] << 8U)
279 | ((uint32_t) a[5U * i + 2U] << 16U))
280 & 0xFFFFFU);
281 r->coeffs[2U * i + 1U]
282 = (int32_t) ((((uint32_t) a[5U * i + 2U] >> 4U) | ((uint32_t) a[5U * i + 3U] << 4U)
283 | ((uint32_t) a[5U * i + 4U] << 12U))
284 & 0xFFFFFU);
285
286 r->coeffs[2U * i + 0U] = gamma1 - r->coeffs[2U * i + 0U];
287 r->coeffs[2U * i + 1U] = gamma1 - r->coeffs[2U * i + 1U];
288 }
289 return 640U;
290 }
291}
292
293/*---------------------------------------------------------------------------
294 * w1 packing
295 *---------------------------------------------------------------------------*/
296uint32_t MLDSA_PACK_polyw1(uint8_t *r, const mldsa_poly *a, int32_t gamma2)
297{
298 if (gamma2 == (MLDSA_Q - 1) / 88) {
299 // 6 bits per coefficient (values in [0, 43])
300 for (uint32_t i = 0U; i < MLDSA_N / 4U; i++) {
301 r[3U * i + 0U] = (uint8_t) (a->coeffs[4U * i + 0U] | (a->coeffs[4U * i + 1U] << 6U));
302 r[3U * i + 1U]
303 = (uint8_t) ((a->coeffs[4U * i + 1U] >> 2U) | (a->coeffs[4U * i + 2U] << 4U));
304 r[3U * i + 2U]
305 = (uint8_t) ((a->coeffs[4U * i + 2U] >> 4U) | (a->coeffs[4U * i + 3U] << 2U));
306 }
307 return 192U;
308 }
309 else {
310 // gamma2 == (q-1)/32: 4 bits per coefficient (values in [0, 15])
311 for (uint32_t i = 0U; i < MLDSA_N / 2U; i++) {
312 r[i] = (uint8_t) (a->coeffs[2U * i + 0U] | (a->coeffs[2U * i + 1U] << 4U));
313 }
314 return 128U;
315 }
316}
317
318/*---------------------------------------------------------------------------
319 * Key packing
320 *---------------------------------------------------------------------------*/
321void MLDSA_PACK_pk(uint8_t *pk,
322 const uint8_t rho[MLDSA_SEEDBYTES],
323 const mldsa_poly *t1,
324 const MLDSA_param_info_t *p)
325{
326 memcpy(pk, rho, MLDSA_SEEDBYTES);
327 for (uint32_t i = 0U; i < p->k; i++) {
329 }
330}
331
333 mldsa_poly *t1,
334 const uint8_t *pk,
335 const MLDSA_param_info_t *p)
336{
337 memcpy(rho, pk, MLDSA_SEEDBYTES);
338 for (uint32_t i = 0U; i < p->k; i++) {
340 }
341}
342
343void MLDSA_PACK_sk(uint8_t *sk,
344 const uint8_t rho[MLDSA_SEEDBYTES],
345 const uint8_t K[MLDSA_SEEDBYTES],
346 const uint8_t tr[MLDSA_TRBYTES],
347 const mldsa_poly *s1,
348 const mldsa_poly *s2,
349 const mldsa_poly *t0,
350 const MLDSA_param_info_t *p)
351{
352 uint32_t offset = 0U;
353
354 memcpy(sk + offset, rho, MLDSA_SEEDBYTES);
355 offset += MLDSA_SEEDBYTES;
356
357 memcpy(sk + offset, K, MLDSA_SEEDBYTES);
358 offset += MLDSA_SEEDBYTES;
359
360 memcpy(sk + offset, tr, MLDSA_TRBYTES);
361 offset += MLDSA_TRBYTES;
362
363 for (uint32_t i = 0U; i < p->l; i++) {
364 MLDSA_PACK_polyeta(sk + offset, &s1[i], p->eta);
365 offset += p->polyeta_packed_bytes;
366 }
367
368 for (uint32_t i = 0U; i < p->k; i++) {
369 MLDSA_PACK_polyeta(sk + offset, &s2[i], p->eta);
370 offset += p->polyeta_packed_bytes;
371 }
372
373 for (uint32_t i = 0U; i < p->k; i++) {
374 MLDSA_PACK_polyt0(sk + offset, &t0[i]);
375 offset += MLDSA_POLYT0_PACKEDBYTES;
376 }
377}
378
380 uint8_t K[MLDSA_SEEDBYTES],
381 uint8_t tr[MLDSA_TRBYTES],
382 mldsa_poly *s1,
383 mldsa_poly *s2,
384 mldsa_poly *t0,
385 const uint8_t *sk,
386 const MLDSA_param_info_t *p)
387{
388 uint32_t offset = 0U;
389
390 memcpy(rho, sk + offset, MLDSA_SEEDBYTES);
391 offset += MLDSA_SEEDBYTES;
392
393 memcpy(K, sk + offset, MLDSA_SEEDBYTES);
394 offset += MLDSA_SEEDBYTES;
395
396 memcpy(tr, sk + offset, MLDSA_TRBYTES);
397 offset += MLDSA_TRBYTES;
398
399 for (uint32_t i = 0U; i < p->l; i++) {
400 MLDSA_PACK_unpack_polyeta(&s1[i], sk + offset, p->eta);
401 offset += p->polyeta_packed_bytes;
402 }
403
404 for (uint32_t i = 0U; i < p->k; i++) {
405 MLDSA_PACK_unpack_polyeta(&s2[i], sk + offset, p->eta);
406 offset += p->polyeta_packed_bytes;
407 }
408
409 for (uint32_t i = 0U; i < p->k; i++) {
410 MLDSA_PACK_unpack_polyt0(&t0[i], sk + offset);
411 offset += MLDSA_POLYT0_PACKEDBYTES;
412 }
413}
414
415/*---------------------------------------------------------------------------
416 * Signature packing
417 *---------------------------------------------------------------------------*/
418void MLDSA_PACK_sig(uint8_t *sig,
419 const uint8_t *ctilde,
420 const mldsa_poly *z,
421 const mldsa_poly *h,
422 const MLDSA_param_info_t *p)
423{
424 uint32_t offset = 0U;
425
426 // c_tilde
427 memcpy(sig, ctilde, p->ctilde_bytes);
428 offset += p->ctilde_bytes;
429
430 // z
431 for (uint32_t i = 0U; i < p->l; i++) {
432 MLDSA_PACK_polyz(sig + offset, &z[i], p->gamma1);
433 offset += p->polyz_packed_bytes;
434 }
435
436 // h (hint encoding): for each polynomial i in [0, k), encode positions
437 // where hint is 1, then pad with zeros and set last byte to total count.
438 memset(sig + offset, 0, p->polyvech_packed_bytes);
439 uint32_t k_offset = 0U;
440 for (uint32_t i = 0U; i < p->k; i++) {
441 for (uint32_t j = 0U; j < MLDSA_N; j++) {
442 if (h[i].coeffs[j] != 0) {
443 sig[offset + k_offset] = (uint8_t) j;
444 k_offset++;
445 }
446 }
447 sig[offset + p->omega + i] = (uint8_t) k_offset;
448 }
449}
450
451int MLDSA_PACK_unpack_sig(uint8_t *ctilde,
452 mldsa_poly *z,
453 mldsa_poly *h,
454 const uint8_t *sig,
455 const MLDSA_param_info_t *p)
456{
457 uint32_t offset = 0U;
458
459 // c_tilde
460 memcpy(ctilde, sig, p->ctilde_bytes);
461 offset += p->ctilde_bytes;
462
463 // z
464 for (uint32_t i = 0U; i < p->l; i++) {
465 MLDSA_PACK_unpack_polyz(&z[i], sig + offset, p->gamma1);
466 offset += p->polyz_packed_bytes;
467 }
468
469 // h (hint)
470 uint32_t k_offset = 0U;
471 for (uint32_t i = 0U; i < p->k; i++) {
472 for (uint32_t j = 0U; j < MLDSA_N; j++) {
473 h[i].coeffs[j] = 0;
474 }
475 }
476
477 for (uint32_t i = 0U; i < p->k; i++) {
478 uint32_t limit = (uint32_t) sig[offset + p->omega + i];
479
480 if (limit < k_offset) {
481 return 1; // Invalid hint encoding
482 }
483 if (limit > p->omega) {
484 return 1;
485 }
486
487 for (uint32_t j = k_offset; j < limit; j++) {
488 // Coefficients must be in increasing order
489 if ((j > k_offset) && (sig[offset + j] <= sig[offset + j - 1U])) {
490 return 1;
491 }
492 h[i].coeffs[sig[offset + j]] = 1;
493 }
494
495 k_offset = limit;
496 }
497
498 // Check remaining bytes are zero
499 for (uint32_t j = k_offset; j < p->omega; j++) {
500 if (sig[offset + j] != 0U) {
501 return 1;
502 }
503 }
504
505 return 0;
506}
void MLDSA_PACK_sig(uint8_t *sig, const uint8_t *ctilde, const mldsa_poly *z, const mldsa_poly *h, const MLDSA_param_info_t *p)
Pack signature (c_tilde || z || h).
uint32_t MLDSA_PACK_polyw1(uint8_t *r, const mldsa_poly *a, int32_t gamma2)
Bit-pack polynomial w1 with coefficients fitting in ceil(log2((q-1)/(2*gamma2))) bits.
uint32_t MLDSA_PACK_unpack_polyeta(mldsa_poly *r, const uint8_t *a, uint8_t eta)
Unpack polynomial with coefficients in [-eta, eta].
void MLDSA_PACK_sk(uint8_t *sk, const uint8_t rho[MLDSA_SEEDBYTES], const uint8_t K[MLDSA_SEEDBYTES], const uint8_t tr[MLDSA_TRBYTES], const mldsa_poly *s1, const mldsa_poly *s2, const mldsa_poly *t0, const MLDSA_param_info_t *p)
Pack the secret key (rho || K || tr || s1 || s2 || t0).
void MLDSA_PACK_unpack_polyt0(mldsa_poly *r, const uint8_t a[MLDSA_POLYT0_PACKEDBYTES])
Unpack polynomial t0 from bytes.
void MLDSA_PACK_unpack_pk(uint8_t rho[MLDSA_SEEDBYTES], mldsa_poly *t1, const uint8_t *pk, const MLDSA_param_info_t *p)
Unpack the public key.
void MLDSA_PACK_unpack_sk(uint8_t rho[MLDSA_SEEDBYTES], uint8_t K[MLDSA_SEEDBYTES], uint8_t tr[MLDSA_TRBYTES], mldsa_poly *s1, mldsa_poly *s2, mldsa_poly *t0, const uint8_t *sk, const MLDSA_param_info_t *p)
Unpack the secret key.
void MLDSA_PACK_polyt1(uint8_t r[MLDSA_POLYT1_PACKEDBYTES], const mldsa_poly *a)
Bit-pack polynomial with coefficients a1 from power2round (10-bit values). Each coefficient uses 10 b...
uint32_t MLDSA_PACK_unpack_polyz(mldsa_poly *r, const uint8_t *a, int32_t gamma1)
Unpack polynomial z.
void MLDSA_PACK_pk(uint8_t *pk, const uint8_t rho[MLDSA_SEEDBYTES], const mldsa_poly *t1, const MLDSA_param_info_t *p)
Pack the public key (rho || t1).
int MLDSA_PACK_unpack_sig(uint8_t *ctilde, mldsa_poly *z, mldsa_poly *h, const uint8_t *sig, const MLDSA_param_info_t *p)
Unpack signature.
void MLDSA_PACK_unpack_polyt1(mldsa_poly *r, const uint8_t a[MLDSA_POLYT1_PACKEDBYTES])
Unpack polynomial t1 from bytes.
void MLDSA_PACK_polyt0(uint8_t r[MLDSA_POLYT0_PACKEDBYTES], const mldsa_poly *a)
Bit-pack polynomial with coefficients a0 from power2round. Coefficients in (-(2^{D-1}-1),...
uint32_t MLDSA_PACK_polyeta(uint8_t *r, const mldsa_poly *a, uint8_t eta)
Bit-pack polynomial with coefficients in [-eta, eta].
uint32_t MLDSA_PACK_polyz(uint8_t *r, const mldsa_poly *a, int32_t gamma1)
Bit-pack polynomial z with coefficients in [-(gamma1-1), gamma1].
#define MLDSA_TRBYTES
Definition lcx_mldsa.h:42
#define MLDSA_POLYT0_PACKEDBYTES
Definition lcx_mldsa.h:46
#define MLDSA_D
Definition lcx_mldsa.h:39
#define MLDSA_N
Definition lcx_mldsa.h:37
#define MLDSA_SEEDBYTES
Definition lcx_mldsa.h:40
#define MLDSA_POLYT1_PACKEDBYTES
Definition lcx_mldsa.h:45
#define MLDSA_Q
Definition lcx_mldsa.h:38
ML-DSA parameter set descriptor holding all derived sizes.
Definition lcx_mldsa.h:179
uint16_t polyvech_packed_bytes
Definition lcx_mldsa.h:192
uint16_t polyz_packed_bytes
Definition lcx_mldsa.h:190
uint16_t polyeta_packed_bytes
Definition lcx_mldsa.h:189
Polynomial with MLDSA_N int32_t coefficients.
int32_t coeffs[MLDSA_N]