ml_dsa 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +104 -0
  3. data/LICENSE +14 -0
  4. data/LICENSE-APACHE +185 -0
  5. data/LICENSE-MIT +21 -0
  6. data/README.md +234 -0
  7. data/ext/ml_dsa/extconf.rb +47 -0
  8. data/ext/ml_dsa/fips202.c +933 -0
  9. data/ext/ml_dsa/fips202.h +166 -0
  10. data/ext/ml_dsa/ml-dsa-44/clean/api.h +52 -0
  11. data/ext/ml_dsa/ml-dsa-44/clean/ntt.c +98 -0
  12. data/ext/ml_dsa/ml-dsa-44/clean/ntt.h +10 -0
  13. data/ext/ml_dsa/ml-dsa-44/clean/packing.c +261 -0
  14. data/ext/ml_dsa/ml-dsa-44/clean/packing.h +31 -0
  15. data/ext/ml_dsa/ml-dsa-44/clean/params.h +44 -0
  16. data/ext/ml_dsa/ml-dsa-44/clean/poly.c +848 -0
  17. data/ext/ml_dsa/ml-dsa-44/clean/poly.h +52 -0
  18. data/ext/ml_dsa/ml-dsa-44/clean/polyvec.c +415 -0
  19. data/ext/ml_dsa/ml-dsa-44/clean/polyvec.h +65 -0
  20. data/ext/ml_dsa/ml-dsa-44/clean/reduce.c +69 -0
  21. data/ext/ml_dsa/ml-dsa-44/clean/reduce.h +17 -0
  22. data/ext/ml_dsa/ml-dsa-44/clean/rounding.c +98 -0
  23. data/ext/ml_dsa/ml-dsa-44/clean/rounding.h +14 -0
  24. data/ext/ml_dsa/ml-dsa-44/clean/sign.c +417 -0
  25. data/ext/ml_dsa/ml-dsa-44/clean/sign.h +49 -0
  26. data/ext/ml_dsa/ml-dsa-44/clean/symmetric-shake.c +26 -0
  27. data/ext/ml_dsa/ml-dsa-44/clean/symmetric.h +34 -0
  28. data/ext/ml_dsa/ml-dsa-65/clean/api.h +52 -0
  29. data/ext/ml_dsa/ml-dsa-65/clean/ntt.c +98 -0
  30. data/ext/ml_dsa/ml-dsa-65/clean/ntt.h +10 -0
  31. data/ext/ml_dsa/ml-dsa-65/clean/packing.c +261 -0
  32. data/ext/ml_dsa/ml-dsa-65/clean/packing.h +31 -0
  33. data/ext/ml_dsa/ml-dsa-65/clean/params.h +44 -0
  34. data/ext/ml_dsa/ml-dsa-65/clean/poly.c +799 -0
  35. data/ext/ml_dsa/ml-dsa-65/clean/poly.h +52 -0
  36. data/ext/ml_dsa/ml-dsa-65/clean/polyvec.c +415 -0
  37. data/ext/ml_dsa/ml-dsa-65/clean/polyvec.h +65 -0
  38. data/ext/ml_dsa/ml-dsa-65/clean/reduce.c +69 -0
  39. data/ext/ml_dsa/ml-dsa-65/clean/reduce.h +17 -0
  40. data/ext/ml_dsa/ml-dsa-65/clean/rounding.c +92 -0
  41. data/ext/ml_dsa/ml-dsa-65/clean/rounding.h +14 -0
  42. data/ext/ml_dsa/ml-dsa-65/clean/sign.c +415 -0
  43. data/ext/ml_dsa/ml-dsa-65/clean/sign.h +49 -0
  44. data/ext/ml_dsa/ml-dsa-65/clean/symmetric-shake.c +26 -0
  45. data/ext/ml_dsa/ml-dsa-65/clean/symmetric.h +34 -0
  46. data/ext/ml_dsa/ml-dsa-87/clean/api.h +52 -0
  47. data/ext/ml_dsa/ml-dsa-87/clean/ntt.c +98 -0
  48. data/ext/ml_dsa/ml-dsa-87/clean/ntt.h +10 -0
  49. data/ext/ml_dsa/ml-dsa-87/clean/packing.c +261 -0
  50. data/ext/ml_dsa/ml-dsa-87/clean/packing.h +31 -0
  51. data/ext/ml_dsa/ml-dsa-87/clean/params.h +44 -0
  52. data/ext/ml_dsa/ml-dsa-87/clean/poly.c +823 -0
  53. data/ext/ml_dsa/ml-dsa-87/clean/poly.h +52 -0
  54. data/ext/ml_dsa/ml-dsa-87/clean/polyvec.c +415 -0
  55. data/ext/ml_dsa/ml-dsa-87/clean/polyvec.h +65 -0
  56. data/ext/ml_dsa/ml-dsa-87/clean/reduce.c +69 -0
  57. data/ext/ml_dsa/ml-dsa-87/clean/reduce.h +17 -0
  58. data/ext/ml_dsa/ml-dsa-87/clean/rounding.c +92 -0
  59. data/ext/ml_dsa/ml-dsa-87/clean/rounding.h +14 -0
  60. data/ext/ml_dsa/ml-dsa-87/clean/sign.c +415 -0
  61. data/ext/ml_dsa/ml-dsa-87/clean/sign.h +49 -0
  62. data/ext/ml_dsa/ml-dsa-87/clean/symmetric-shake.c +26 -0
  63. data/ext/ml_dsa/ml-dsa-87/clean/symmetric.h +34 -0
  64. data/ext/ml_dsa/ml_dsa_44_impl.c +10 -0
  65. data/ext/ml_dsa/ml_dsa_65_impl.c +10 -0
  66. data/ext/ml_dsa/ml_dsa_87_impl.c +10 -0
  67. data/ext/ml_dsa/ml_dsa_ext.c +1360 -0
  68. data/ext/ml_dsa/ml_dsa_impl_template.h +35 -0
  69. data/ext/ml_dsa/ml_dsa_internal.h +188 -0
  70. data/ext/ml_dsa/randombytes.c +48 -0
  71. data/ext/ml_dsa/randombytes.h +15 -0
  72. data/lib/ml_dsa/batch_builder.rb +57 -0
  73. data/lib/ml_dsa/config.rb +69 -0
  74. data/lib/ml_dsa/internal.rb +76 -0
  75. data/lib/ml_dsa/key_pair.rb +39 -0
  76. data/lib/ml_dsa/parameter_set.rb +89 -0
  77. data/lib/ml_dsa/public_key.rb +180 -0
  78. data/lib/ml_dsa/requests.rb +96 -0
  79. data/lib/ml_dsa/secret_key.rb +221 -0
  80. data/lib/ml_dsa/version.rb +5 -0
  81. data/lib/ml_dsa.rb +277 -0
  82. data/patches/README.md +55 -0
  83. data/patches/pqclean-explicit-rnd.patch +64 -0
  84. data/sig/ml_dsa.rbs +178 -0
  85. data/test/fixtures/kat_vectors.yaml +16 -0
  86. metadata +194 -0
@@ -0,0 +1,848 @@
1
+ #include "ntt.h"
2
+ #include "params.h"
3
+ #include "poly.h"
4
+ #include "reduce.h"
5
+ #include "rounding.h"
6
+ #include "symmetric.h"
7
+ #include <stdint.h>
8
+
9
+ #define DBENCH_START()
10
+ #define DBENCH_STOP(t)
11
+
12
+ /*************************************************
13
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_reduce
14
+ *
15
+ * Description: Inplace reduction of all coefficients of polynomial to
16
+ * representative in [-6283008,6283008].
17
+ *
18
+ * Arguments: - poly *a: pointer to input/output polynomial
19
+ **************************************************/
20
+ void PQCLEAN_MLDSA44_CLEAN_poly_reduce(poly *a) {
21
+ unsigned int i;
22
+ DBENCH_START();
23
+
24
+ for (i = 0; i < N; ++i) {
25
+ a->coeffs[i] = PQCLEAN_MLDSA44_CLEAN_reduce32(a->coeffs[i]);
26
+ }
27
+
28
+ DBENCH_STOP(*tred);
29
+ }
30
+
31
+ /*************************************************
32
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_caddq
33
+ *
34
+ * Description: For all coefficients of in/out polynomial add Q if
35
+ * coefficient is negative.
36
+ *
37
+ * Arguments: - poly *a: pointer to input/output polynomial
38
+ **************************************************/
39
+ void PQCLEAN_MLDSA44_CLEAN_poly_caddq(poly *a) {
40
+ unsigned int i;
41
+ DBENCH_START();
42
+
43
+ for (i = 0; i < N; ++i) {
44
+ a->coeffs[i] = PQCLEAN_MLDSA44_CLEAN_caddq(a->coeffs[i]);
45
+ }
46
+
47
+ DBENCH_STOP(*tred);
48
+ }
49
+
50
+ /*************************************************
51
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_add
52
+ *
53
+ * Description: Add polynomials. No modular reduction is performed.
54
+ *
55
+ * Arguments: - poly *c: pointer to output polynomial
56
+ * - const poly *a: pointer to first summand
57
+ * - const poly *b: pointer to second summand
58
+ **************************************************/
59
+ void PQCLEAN_MLDSA44_CLEAN_poly_add(poly *c, const poly *a, const poly *b) {
60
+ unsigned int i;
61
+ DBENCH_START();
62
+
63
+ for (i = 0; i < N; ++i) {
64
+ c->coeffs[i] = a->coeffs[i] + b->coeffs[i];
65
+ }
66
+
67
+ DBENCH_STOP(*tadd);
68
+ }
69
+
70
+ /*************************************************
71
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_sub
72
+ *
73
+ * Description: Subtract polynomials. No modular reduction is
74
+ * performed.
75
+ *
76
+ * Arguments: - poly *c: pointer to output polynomial
77
+ * - const poly *a: pointer to first input polynomial
78
+ * - const poly *b: pointer to second input polynomial to be
79
+ * subtraced from first input polynomial
80
+ **************************************************/
81
+ void PQCLEAN_MLDSA44_CLEAN_poly_sub(poly *c, const poly *a, const poly *b) {
82
+ unsigned int i;
83
+ DBENCH_START();
84
+
85
+ for (i = 0; i < N; ++i) {
86
+ c->coeffs[i] = a->coeffs[i] - b->coeffs[i];
87
+ }
88
+
89
+ DBENCH_STOP(*tadd);
90
+ }
91
+
92
+ /*************************************************
93
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_shiftl
94
+ *
95
+ * Description: Multiply polynomial by 2^D without modular reduction. Assumes
96
+ * input coefficients to be less than 2^{31-D} in absolute value.
97
+ *
98
+ * Arguments: - poly *a: pointer to input/output polynomial
99
+ **************************************************/
100
+ void PQCLEAN_MLDSA44_CLEAN_poly_shiftl(poly *a) {
101
+ unsigned int i;
102
+ DBENCH_START();
103
+
104
+ for (i = 0; i < N; ++i) {
105
+ a->coeffs[i] <<= D;
106
+ }
107
+
108
+ DBENCH_STOP(*tmul);
109
+ }
110
+
111
+ /*************************************************
112
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_ntt
113
+ *
114
+ * Description: Inplace forward NTT. Coefficients can grow by
115
+ * 8*Q in absolute value.
116
+ *
117
+ * Arguments: - poly *a: pointer to input/output polynomial
118
+ **************************************************/
119
+ void PQCLEAN_MLDSA44_CLEAN_poly_ntt(poly *a) {
120
+ DBENCH_START();
121
+
122
+ PQCLEAN_MLDSA44_CLEAN_ntt(a->coeffs);
123
+
124
+ DBENCH_STOP(*tmul);
125
+ }
126
+
127
+ /*************************************************
128
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_invntt_tomont
129
+ *
130
+ * Description: Inplace inverse NTT and multiplication by 2^{32}.
131
+ * Input coefficients need to be less than Q in absolute
132
+ * value and output coefficients are again bounded by Q.
133
+ *
134
+ * Arguments: - poly *a: pointer to input/output polynomial
135
+ **************************************************/
136
+ void PQCLEAN_MLDSA44_CLEAN_poly_invntt_tomont(poly *a) {
137
+ DBENCH_START();
138
+
139
+ PQCLEAN_MLDSA44_CLEAN_invntt_tomont(a->coeffs);
140
+
141
+ DBENCH_STOP(*tmul);
142
+ }
143
+
144
+ /*************************************************
145
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_pointwise_montgomery
146
+ *
147
+ * Description: Pointwise multiplication of polynomials in NTT domain
148
+ * representation and multiplication of resulting polynomial
149
+ * by 2^{-32}.
150
+ *
151
+ * Arguments: - poly *c: pointer to output polynomial
152
+ * - const poly *a: pointer to first input polynomial
153
+ * - const poly *b: pointer to second input polynomial
154
+ **************************************************/
155
+ void PQCLEAN_MLDSA44_CLEAN_poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) {
156
+ unsigned int i;
157
+ DBENCH_START();
158
+
159
+ for (i = 0; i < N; ++i) {
160
+ c->coeffs[i] = PQCLEAN_MLDSA44_CLEAN_montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]);
161
+ }
162
+
163
+ DBENCH_STOP(*tmul);
164
+ }
165
+
166
+ /*************************************************
167
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_power2round
168
+ *
169
+ * Description: For all coefficients c of the input polynomial,
170
+ * compute c0, c1 such that c mod Q = c1*2^D + c0
171
+ * with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be
172
+ * standard representatives.
173
+ *
174
+ * Arguments: - poly *a1: pointer to output polynomial with coefficients c1
175
+ * - poly *a0: pointer to output polynomial with coefficients c0
176
+ * - const poly *a: pointer to input polynomial
177
+ **************************************************/
178
+ void PQCLEAN_MLDSA44_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a) {
179
+ unsigned int i;
180
+ DBENCH_START();
181
+
182
+ for (i = 0; i < N; ++i) {
183
+ a1->coeffs[i] = PQCLEAN_MLDSA44_CLEAN_power2round(&a0->coeffs[i], a->coeffs[i]);
184
+ }
185
+
186
+ DBENCH_STOP(*tround);
187
+ }
188
+
189
+ /*************************************************
190
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_decompose
191
+ *
192
+ * Description: For all coefficients c of the input polynomial,
193
+ * compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0
194
+ * with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we
195
+ * set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0.
196
+ * Assumes coefficients to be standard representatives.
197
+ *
198
+ * Arguments: - poly *a1: pointer to output polynomial with coefficients c1
199
+ * - poly *a0: pointer to output polynomial with coefficients c0
200
+ * - const poly *a: pointer to input polynomial
201
+ **************************************************/
202
+ void PQCLEAN_MLDSA44_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a) {
203
+ unsigned int i;
204
+ DBENCH_START();
205
+
206
+ for (i = 0; i < N; ++i) {
207
+ a1->coeffs[i] = PQCLEAN_MLDSA44_CLEAN_decompose(&a0->coeffs[i], a->coeffs[i]);
208
+ }
209
+
210
+ DBENCH_STOP(*tround);
211
+ }
212
+
213
+ /*************************************************
214
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_make_hint
215
+ *
216
+ * Description: Compute hint polynomial. The coefficients of which indicate
217
+ * whether the low bits of the corresponding coefficient of
218
+ * the input polynomial overflow into the high bits.
219
+ *
220
+ * Arguments: - poly *h: pointer to output hint polynomial
221
+ * - const poly *a0: pointer to low part of input polynomial
222
+ * - const poly *a1: pointer to high part of input polynomial
223
+ *
224
+ * Returns number of 1 bits.
225
+ **************************************************/
226
+ unsigned int PQCLEAN_MLDSA44_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1) {
227
+ unsigned int i, s = 0;
228
+ DBENCH_START();
229
+
230
+ for (i = 0; i < N; ++i) {
231
+ h->coeffs[i] = PQCLEAN_MLDSA44_CLEAN_make_hint(a0->coeffs[i], a1->coeffs[i]);
232
+ s += h->coeffs[i];
233
+ }
234
+
235
+ DBENCH_STOP(*tround);
236
+ return s;
237
+ }
238
+
239
+ /*************************************************
240
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_use_hint
241
+ *
242
+ * Description: Use hint polynomial to correct the high bits of a polynomial.
243
+ *
244
+ * Arguments: - poly *b: pointer to output polynomial with corrected high bits
245
+ * - const poly *a: pointer to input polynomial
246
+ * - const poly *h: pointer to input hint polynomial
247
+ **************************************************/
248
+ void PQCLEAN_MLDSA44_CLEAN_poly_use_hint(poly *b, const poly *a, const poly *h) {
249
+ unsigned int i;
250
+ DBENCH_START();
251
+
252
+ for (i = 0; i < N; ++i) {
253
+ b->coeffs[i] = PQCLEAN_MLDSA44_CLEAN_use_hint(a->coeffs[i], h->coeffs[i]);
254
+ }
255
+
256
+ DBENCH_STOP(*tround);
257
+ }
258
+
259
+ /*************************************************
260
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_chknorm
261
+ *
262
+ * Description: Check infinity norm of polynomial against given bound.
263
+ * Assumes input coefficients were reduced by PQCLEAN_MLDSA44_CLEAN_reduce32().
264
+ *
265
+ * Arguments: - const poly *a: pointer to polynomial
266
+ * - int32_t B: norm bound
267
+ *
268
+ * Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise.
269
+ **************************************************/
270
+ int PQCLEAN_MLDSA44_CLEAN_poly_chknorm(const poly *a, int32_t B) {
271
+ unsigned int i;
272
+ int32_t t;
273
+ DBENCH_START();
274
+
275
+ if (B > (Q - 1) / 8) {
276
+ return 1;
277
+ }
278
+
279
+ /* It is ok to leak which coefficient violates the bound since
280
+ the probability for each coefficient is independent of secret
281
+ data but we must not leak the sign of the centralized representative. */
282
+ for (i = 0; i < N; ++i) {
283
+ /* Absolute value */
284
+ t = a->coeffs[i] >> 31;
285
+ t = a->coeffs[i] - (t & 2 * a->coeffs[i]);
286
+
287
+ if (t >= B) {
288
+ DBENCH_STOP(*tsample);
289
+ return 1;
290
+ }
291
+ }
292
+
293
+ DBENCH_STOP(*tsample);
294
+ return 0;
295
+ }
296
+
297
+ /*************************************************
298
+ * Name: rej_uniform
299
+ *
300
+ * Description: Sample uniformly random coefficients in [0, Q-1] by
301
+ * performing rejection sampling on array of random bytes.
302
+ *
303
+ * Arguments: - int32_t *a: pointer to output array (allocated)
304
+ * - unsigned int len: number of coefficients to be sampled
305
+ * - const uint8_t *buf: array of random bytes
306
+ * - unsigned int buflen: length of array of random bytes
307
+ *
308
+ * Returns number of sampled coefficients. Can be smaller than len if not enough
309
+ * random bytes were given.
310
+ **************************************************/
311
+ static unsigned int rej_uniform(int32_t *a,
312
+ unsigned int len,
313
+ const uint8_t *buf,
314
+ unsigned int buflen) {
315
+ unsigned int ctr, pos;
316
+ uint32_t t;
317
+ DBENCH_START();
318
+
319
+ ctr = pos = 0;
320
+ while (ctr < len && pos + 3 <= buflen) {
321
+ t = buf[pos++];
322
+ t |= (uint32_t)buf[pos++] << 8;
323
+ t |= (uint32_t)buf[pos++] << 16;
324
+ t &= 0x7FFFFF;
325
+
326
+ if (t < Q) {
327
+ a[ctr++] = t;
328
+ }
329
+ }
330
+
331
+ DBENCH_STOP(*tsample);
332
+ return ctr;
333
+ }
334
+
335
+ /*************************************************
336
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_uniform
337
+ *
338
+ * Description: Sample polynomial with uniformly random coefficients
339
+ * in [0,Q-1] by performing rejection sampling on the
340
+ * output stream of SHAKE128(seed|nonce)
341
+ *
342
+ * Arguments: - poly *a: pointer to output polynomial
343
+ * - const uint8_t seed[]: byte array with seed of length SEEDBYTES
344
+ * - uint16_t nonce: 2-byte nonce
345
+ **************************************************/
346
+ #define POLY_UNIFORM_NBLOCKS ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES)
347
+ void PQCLEAN_MLDSA44_CLEAN_poly_uniform(poly *a,
348
+ const uint8_t seed[SEEDBYTES],
349
+ uint16_t nonce) {
350
+ unsigned int i, ctr, off;
351
+ unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES;
352
+ uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 2];
353
+ stream128_state state;
354
+
355
+ stream128_init(&state, seed, nonce);
356
+ stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state);
357
+
358
+ ctr = rej_uniform(a->coeffs, N, buf, buflen);
359
+
360
+ while (ctr < N) {
361
+ off = buflen % 3;
362
+ for (i = 0; i < off; ++i) {
363
+ buf[i] = buf[buflen - off + i];
364
+ }
365
+
366
+ stream128_squeezeblocks(buf + off, 1, &state);
367
+ buflen = STREAM128_BLOCKBYTES + off;
368
+ ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen);
369
+ }
370
+ stream128_release(&state);
371
+ }
372
+
373
+ /*************************************************
374
+ * Name: rej_eta
375
+ *
376
+ * Description: Sample uniformly random coefficients in [-ETA, ETA] by
377
+ * performing rejection sampling on array of random bytes.
378
+ *
379
+ * Arguments: - int32_t *a: pointer to output array (allocated)
380
+ * - unsigned int len: number of coefficients to be sampled
381
+ * - const uint8_t *buf: array of random bytes
382
+ * - unsigned int buflen: length of array of random bytes
383
+ *
384
+ * Returns number of sampled coefficients. Can be smaller than len if not enough
385
+ * random bytes were given.
386
+ **************************************************/
387
+ static unsigned int rej_eta(int32_t *a,
388
+ unsigned int len,
389
+ const uint8_t *buf,
390
+ unsigned int buflen) {
391
+ unsigned int ctr, pos;
392
+ uint32_t t0, t1;
393
+ DBENCH_START();
394
+
395
+ ctr = pos = 0;
396
+ while (ctr < len && pos < buflen) {
397
+ t0 = buf[pos] & 0x0F;
398
+ t1 = buf[pos++] >> 4;
399
+
400
+ if (t0 < 15) {
401
+ t0 = t0 - (205 * t0 >> 10) * 5;
402
+ a[ctr++] = 2 - t0;
403
+ }
404
+ if (t1 < 15 && ctr < len) {
405
+ t1 = t1 - (205 * t1 >> 10) * 5;
406
+ a[ctr++] = 2 - t1;
407
+ }
408
+ }
409
+
410
+ DBENCH_STOP(*tsample);
411
+ return ctr;
412
+ }
413
+
414
+ /*************************************************
415
+ * Name: PQCLEAN_MLDSA44_CLEAN_poly_uniform_eta
416
+ *
417
+ * Description: Sample polynomial with uniformly random coefficients
418
+ * in [-ETA,ETA] by performing rejection sampling on the
419
+ * output stream from SHAKE256(seed|nonce)
420
+ *
421
+ * Arguments: - poly *a: pointer to output polynomial
422
+ * - const uint8_t seed[]: byte array with seed of length CRHBYTES
423
+ * - uint16_t nonce: 2-byte nonce
424
+ **************************************************/
425
+ #define POLY_UNIFORM_ETA_NBLOCKS ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES)
426
+ void PQCLEAN_MLDSA44_CLEAN_poly_uniform_eta(poly *a,
427
+ const uint8_t seed[CRHBYTES],
428
+ uint16_t nonce) {
429
+ unsigned int ctr;
430
+ unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES;
431
+ uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES];
432
+ stream256_state state;
433
+
434
+ stream256_init(&state, seed, nonce);
435
+ stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);
436
+
437
+ ctr = rej_eta(a->coeffs, N, buf, buflen);
438
+
439
+ while (ctr < N) {
440
+ stream256_squeezeblocks(buf, 1, &state);
441
+ ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES);
442
+ }
443
+ stream256_release(&state);
444
+ }
445
+
446
+ /*************************************************
447
+ * Name: poly_uniform_gamma1m1
448
+ *
449
+ * Description: Sample polynomial with uniformly random coefficients
450
+ * in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream
451
+ * of SHAKE256(seed|nonce)
452
+ *
453
+ * Arguments: - poly *a: pointer to output polynomial
454
+ * - const uint8_t seed[]: byte array with seed of length CRHBYTES
455
+ * - uint16_t nonce: 16-bit nonce
456
+ **************************************************/
457
+ #define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES)
458
+ void PQCLEAN_MLDSA44_CLEAN_poly_uniform_gamma1(poly *a,
459
+ const uint8_t seed[CRHBYTES],
460
+ uint16_t nonce) {
461
+ uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS * STREAM256_BLOCKBYTES];
462
+ stream256_state state;
463
+
464
+ stream256_init(&state, seed, nonce);
465
+ stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS, &state);
466
+ stream256_release(&state);
467
+ PQCLEAN_MLDSA44_CLEAN_polyz_unpack(a, buf);
468
+ }
469
+
470
+ /*************************************************
471
+ * Name: challenge
472
+ *
473
+ * Description: Implementation of H. Samples polynomial with TAU nonzero
474
+ * coefficients in {-1,1} using the output stream of
475
+ * SHAKE256(seed).
476
+ *
477
+ * Arguments: - poly *c: pointer to output polynomial
478
+ * - const uint8_t mu[]: byte array containing seed of length CTILDEBYTES
479
+ **************************************************/
480
+ void PQCLEAN_MLDSA44_CLEAN_poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]) {
481
+ unsigned int i, b, pos;
482
+ uint64_t signs;
483
+ uint8_t buf[SHAKE256_RATE];
484
+ shake256incctx state;
485
+
486
+ shake256_inc_init(&state);
487
+ shake256_inc_absorb(&state, seed, CTILDEBYTES);
488
+ shake256_inc_finalize(&state);
489
+ shake256_inc_squeeze(buf, sizeof buf, &state);
490
+
491
+ signs = 0;
492
+ for (i = 0; i < 8; ++i) {
493
+ signs |= (uint64_t)buf[i] << 8 * i;
494
+ }
495
+ pos = 8;
496
+
497
+ for (i = 0; i < N; ++i) {
498
+ c->coeffs[i] = 0;
499
+ }
500
+ for (i = N - TAU; i < N; ++i) {
501
+ do {
502
+ if (pos >= SHAKE256_RATE) {
503
+ shake256_inc_squeeze(buf, sizeof buf, &state);
504
+ pos = 0;
505
+ }
506
+
507
+ b = buf[pos++];
508
+ } while (b > i);
509
+
510
+ c->coeffs[i] = c->coeffs[b];
511
+ c->coeffs[b] = 1 - 2 * (signs & 1);
512
+ signs >>= 1;
513
+ }
514
+ shake256_inc_ctx_release(&state);
515
+ }
516
+
517
+ /*************************************************
518
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyeta_pack
519
+ *
520
+ * Description: Bit-pack polynomial with coefficients in [-ETA,ETA].
521
+ *
522
+ * Arguments: - uint8_t *r: pointer to output byte array with at least
523
+ * POLYETA_PACKEDBYTES bytes
524
+ * - const poly *a: pointer to input polynomial
525
+ **************************************************/
526
+ void PQCLEAN_MLDSA44_CLEAN_polyeta_pack(uint8_t *r, const poly *a) {
527
+ unsigned int i;
528
+ uint8_t t[8];
529
+ DBENCH_START();
530
+
531
+ for (i = 0; i < N / 8; ++i) {
532
+ t[0] = (uint8_t) (ETA - a->coeffs[8 * i + 0]);
533
+ t[1] = (uint8_t) (ETA - a->coeffs[8 * i + 1]);
534
+ t[2] = (uint8_t) (ETA - a->coeffs[8 * i + 2]);
535
+ t[3] = (uint8_t) (ETA - a->coeffs[8 * i + 3]);
536
+ t[4] = (uint8_t) (ETA - a->coeffs[8 * i + 4]);
537
+ t[5] = (uint8_t) (ETA - a->coeffs[8 * i + 5]);
538
+ t[6] = (uint8_t) (ETA - a->coeffs[8 * i + 6]);
539
+ t[7] = (uint8_t) (ETA - a->coeffs[8 * i + 7]);
540
+
541
+ r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6);
542
+ r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7);
543
+ r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5);
544
+ }
545
+
546
+ DBENCH_STOP(*tpack);
547
+ }
548
+
549
+ /*************************************************
550
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyeta_unpack
551
+ *
552
+ * Description: Unpack polynomial with coefficients in [-ETA,ETA].
553
+ *
554
+ * Arguments: - poly *r: pointer to output polynomial
555
+ * - const uint8_t *a: byte array with bit-packed polynomial
556
+ **************************************************/
557
+ void PQCLEAN_MLDSA44_CLEAN_polyeta_unpack(poly *r, const uint8_t *a) {
558
+ unsigned int i;
559
+ DBENCH_START();
560
+
561
+ for (i = 0; i < N / 8; ++i) {
562
+ r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7;
563
+ r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7;
564
+ r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7;
565
+ r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7;
566
+ r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7;
567
+ r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7;
568
+ r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7;
569
+ r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7;
570
+
571
+ r->coeffs[8 * i + 0] = ETA - r->coeffs[8 * i + 0];
572
+ r->coeffs[8 * i + 1] = ETA - r->coeffs[8 * i + 1];
573
+ r->coeffs[8 * i + 2] = ETA - r->coeffs[8 * i + 2];
574
+ r->coeffs[8 * i + 3] = ETA - r->coeffs[8 * i + 3];
575
+ r->coeffs[8 * i + 4] = ETA - r->coeffs[8 * i + 4];
576
+ r->coeffs[8 * i + 5] = ETA - r->coeffs[8 * i + 5];
577
+ r->coeffs[8 * i + 6] = ETA - r->coeffs[8 * i + 6];
578
+ r->coeffs[8 * i + 7] = ETA - r->coeffs[8 * i + 7];
579
+ }
580
+
581
+ DBENCH_STOP(*tpack);
582
+ }
583
+
584
+ /*************************************************
585
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyt1_pack
586
+ *
587
+ * Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits.
588
+ * Input coefficients are assumed to be standard representatives.
589
+ *
590
+ * Arguments: - uint8_t *r: pointer to output byte array with at least
591
+ * POLYT1_PACKEDBYTES bytes
592
+ * - const poly *a: pointer to input polynomial
593
+ **************************************************/
594
+ void PQCLEAN_MLDSA44_CLEAN_polyt1_pack(uint8_t *r, const poly *a) {
595
+ unsigned int i;
596
+ DBENCH_START();
597
+
598
+ for (i = 0; i < N / 4; ++i) {
599
+ r[5 * i + 0] = (uint8_t) (a->coeffs[4 * i + 0] >> 0);
600
+ r[5 * i + 1] = (uint8_t) ((a->coeffs[4 * i + 0] >> 8) | (a->coeffs[4 * i + 1] << 2));
601
+ r[5 * i + 2] = (uint8_t) ((a->coeffs[4 * i + 1] >> 6) | (a->coeffs[4 * i + 2] << 4));
602
+ r[5 * i + 3] = (uint8_t) ((a->coeffs[4 * i + 2] >> 4) | (a->coeffs[4 * i + 3] << 6));
603
+ r[5 * i + 4] = (uint8_t) (a->coeffs[4 * i + 3] >> 2);
604
+ }
605
+
606
+ DBENCH_STOP(*tpack);
607
+ }
608
+
609
+ /*************************************************
610
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyt1_unpack
611
+ *
612
+ * Description: Unpack polynomial t1 with 10-bit coefficients.
613
+ * Output coefficients are standard representatives.
614
+ *
615
+ * Arguments: - poly *r: pointer to output polynomial
616
+ * - const uint8_t *a: byte array with bit-packed polynomial
617
+ **************************************************/
618
+ void PQCLEAN_MLDSA44_CLEAN_polyt1_unpack(poly *r, const uint8_t *a) {
619
+ unsigned int i;
620
+ DBENCH_START();
621
+
622
+ for (i = 0; i < N / 4; ++i) {
623
+ r->coeffs[4 * i + 0] = ((a[5 * i + 0] >> 0) | ((uint32_t)a[5 * i + 1] << 8)) & 0x3FF;
624
+ r->coeffs[4 * i + 1] = ((a[5 * i + 1] >> 2) | ((uint32_t)a[5 * i + 2] << 6)) & 0x3FF;
625
+ r->coeffs[4 * i + 2] = ((a[5 * i + 2] >> 4) | ((uint32_t)a[5 * i + 3] << 4)) & 0x3FF;
626
+ r->coeffs[4 * i + 3] = ((a[5 * i + 3] >> 6) | ((uint32_t)a[5 * i + 4] << 2)) & 0x3FF;
627
+ }
628
+
629
+ DBENCH_STOP(*tpack);
630
+ }
631
+
632
+ /*************************************************
633
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyt0_pack
634
+ *
635
+ * Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
636
+ *
637
+ * Arguments: - uint8_t *r: pointer to output byte array with at least
638
+ * POLYT0_PACKEDBYTES bytes
639
+ * - const poly *a: pointer to input polynomial
640
+ **************************************************/
641
+ void PQCLEAN_MLDSA44_CLEAN_polyt0_pack(uint8_t *r, const poly *a) {
642
+ unsigned int i;
643
+ uint32_t t[8];
644
+ DBENCH_START();
645
+
646
+ for (i = 0; i < N / 8; ++i) {
647
+ t[0] = (1 << (D - 1)) - a->coeffs[8 * i + 0];
648
+ t[1] = (1 << (D - 1)) - a->coeffs[8 * i + 1];
649
+ t[2] = (1 << (D - 1)) - a->coeffs[8 * i + 2];
650
+ t[3] = (1 << (D - 1)) - a->coeffs[8 * i + 3];
651
+ t[4] = (1 << (D - 1)) - a->coeffs[8 * i + 4];
652
+ t[5] = (1 << (D - 1)) - a->coeffs[8 * i + 5];
653
+ t[6] = (1 << (D - 1)) - a->coeffs[8 * i + 6];
654
+ t[7] = (1 << (D - 1)) - a->coeffs[8 * i + 7];
655
+
656
+ r[13 * i + 0] = (uint8_t) t[0];
657
+ r[13 * i + 1] = (uint8_t) (t[0] >> 8);
658
+ r[13 * i + 1] |= (uint8_t) (t[1] << 5);
659
+ r[13 * i + 2] = (uint8_t) (t[1] >> 3);
660
+ r[13 * i + 3] = (uint8_t) (t[1] >> 11);
661
+ r[13 * i + 3] |= (uint8_t) (t[2] << 2);
662
+ r[13 * i + 4] = (uint8_t) (t[2] >> 6);
663
+ r[13 * i + 4] |= (uint8_t) (t[3] << 7);
664
+ r[13 * i + 5] = (uint8_t) (t[3] >> 1);
665
+ r[13 * i + 6] = (uint8_t) (t[3] >> 9);
666
+ r[13 * i + 6] |= (uint8_t) (t[4] << 4);
667
+ r[13 * i + 7] = (uint8_t) (t[4] >> 4);
668
+ r[13 * i + 8] = (uint8_t) (t[4] >> 12);
669
+ r[13 * i + 8] |= (uint8_t) (t[5] << 1);
670
+ r[13 * i + 9] = (uint8_t) (t[5] >> 7);
671
+ r[13 * i + 9] |= (uint8_t) (t[6] << 6);
672
+ r[13 * i + 10] = (uint8_t) (t[6] >> 2);
673
+ r[13 * i + 11] = (uint8_t) (t[6] >> 10);
674
+ r[13 * i + 11] |= (uint8_t) (t[7] << 3);
675
+ r[13 * i + 12] = (uint8_t) (t[7] >> 5);
676
+ }
677
+
678
+ DBENCH_STOP(*tpack);
679
+ }
680
+
681
+ /*************************************************
682
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyt0_unpack
683
+ *
684
+ * Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
685
+ *
686
+ * Arguments: - poly *r: pointer to output polynomial
687
+ * - const uint8_t *a: byte array with bit-packed polynomial
688
+ **************************************************/
689
+ void PQCLEAN_MLDSA44_CLEAN_polyt0_unpack(poly *r, const uint8_t *a) {
690
+ unsigned int i;
691
+ DBENCH_START();
692
+
693
+ for (i = 0; i < N / 8; ++i) {
694
+ r->coeffs[8 * i + 0] = a[13 * i + 0];
695
+ r->coeffs[8 * i + 0] |= (uint32_t)a[13 * i + 1] << 8;
696
+ r->coeffs[8 * i + 0] &= 0x1FFF;
697
+
698
+ r->coeffs[8 * i + 1] = a[13 * i + 1] >> 5;
699
+ r->coeffs[8 * i + 1] |= (uint32_t)a[13 * i + 2] << 3;
700
+ r->coeffs[8 * i + 1] |= (uint32_t)a[13 * i + 3] << 11;
701
+ r->coeffs[8 * i + 1] &= 0x1FFF;
702
+
703
+ r->coeffs[8 * i + 2] = a[13 * i + 3] >> 2;
704
+ r->coeffs[8 * i + 2] |= (uint32_t)a[13 * i + 4] << 6;
705
+ r->coeffs[8 * i + 2] &= 0x1FFF;
706
+
707
+ r->coeffs[8 * i + 3] = a[13 * i + 4] >> 7;
708
+ r->coeffs[8 * i + 3] |= (uint32_t)a[13 * i + 5] << 1;
709
+ r->coeffs[8 * i + 3] |= (uint32_t)a[13 * i + 6] << 9;
710
+ r->coeffs[8 * i + 3] &= 0x1FFF;
711
+
712
+ r->coeffs[8 * i + 4] = a[13 * i + 6] >> 4;
713
+ r->coeffs[8 * i + 4] |= (uint32_t)a[13 * i + 7] << 4;
714
+ r->coeffs[8 * i + 4] |= (uint32_t)a[13 * i + 8] << 12;
715
+ r->coeffs[8 * i + 4] &= 0x1FFF;
716
+
717
+ r->coeffs[8 * i + 5] = a[13 * i + 8] >> 1;
718
+ r->coeffs[8 * i + 5] |= (uint32_t)a[13 * i + 9] << 7;
719
+ r->coeffs[8 * i + 5] &= 0x1FFF;
720
+
721
+ r->coeffs[8 * i + 6] = a[13 * i + 9] >> 6;
722
+ r->coeffs[8 * i + 6] |= (uint32_t)a[13 * i + 10] << 2;
723
+ r->coeffs[8 * i + 6] |= (uint32_t)a[13 * i + 11] << 10;
724
+ r->coeffs[8 * i + 6] &= 0x1FFF;
725
+
726
+ r->coeffs[8 * i + 7] = a[13 * i + 11] >> 3;
727
+ r->coeffs[8 * i + 7] |= (uint32_t)a[13 * i + 12] << 5;
728
+ r->coeffs[8 * i + 7] &= 0x1FFF;
729
+
730
+ r->coeffs[8 * i + 0] = (1 << (D - 1)) - r->coeffs[8 * i + 0];
731
+ r->coeffs[8 * i + 1] = (1 << (D - 1)) - r->coeffs[8 * i + 1];
732
+ r->coeffs[8 * i + 2] = (1 << (D - 1)) - r->coeffs[8 * i + 2];
733
+ r->coeffs[8 * i + 3] = (1 << (D - 1)) - r->coeffs[8 * i + 3];
734
+ r->coeffs[8 * i + 4] = (1 << (D - 1)) - r->coeffs[8 * i + 4];
735
+ r->coeffs[8 * i + 5] = (1 << (D - 1)) - r->coeffs[8 * i + 5];
736
+ r->coeffs[8 * i + 6] = (1 << (D - 1)) - r->coeffs[8 * i + 6];
737
+ r->coeffs[8 * i + 7] = (1 << (D - 1)) - r->coeffs[8 * i + 7];
738
+ }
739
+
740
+ DBENCH_STOP(*tpack);
741
+ }
742
+
743
+ /*************************************************
744
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyz_pack
745
+ *
746
+ * Description: Bit-pack polynomial with coefficients
747
+ * in [-(GAMMA1 - 1), GAMMA1].
748
+ *
749
+ * Arguments: - uint8_t *r: pointer to output byte array with at least
750
+ * POLYZ_PACKEDBYTES bytes
751
+ * - const poly *a: pointer to input polynomial
752
+ **************************************************/
753
+ void PQCLEAN_MLDSA44_CLEAN_polyz_pack(uint8_t *r, const poly *a) {
754
+ unsigned int i;
755
+ uint32_t t[4];
756
+ DBENCH_START();
757
+
758
+ for (i = 0; i < N / 4; ++i) {
759
+ t[0] = GAMMA1 - a->coeffs[4 * i + 0];
760
+ t[1] = GAMMA1 - a->coeffs[4 * i + 1];
761
+ t[2] = GAMMA1 - a->coeffs[4 * i + 2];
762
+ t[3] = GAMMA1 - a->coeffs[4 * i + 3];
763
+
764
+ r[9 * i + 0] = (uint8_t) t[0];
765
+ r[9 * i + 1] = (uint8_t) (t[0] >> 8);
766
+ r[9 * i + 2] = (uint8_t) (t[0] >> 16);
767
+ r[9 * i + 2] |= (uint8_t) (t[1] << 2);
768
+ r[9 * i + 3] = (uint8_t) (t[1] >> 6);
769
+ r[9 * i + 4] = (uint8_t) (t[1] >> 14);
770
+ r[9 * i + 4] |= (uint8_t) (t[2] << 4);
771
+ r[9 * i + 5] = (uint8_t) (t[2] >> 4);
772
+ r[9 * i + 6] = (uint8_t) (t[2] >> 12);
773
+ r[9 * i + 6] |= (uint8_t) (t[3] << 6);
774
+ r[9 * i + 7] = (uint8_t) (t[3] >> 2);
775
+ r[9 * i + 8] = (uint8_t) (t[3] >> 10);
776
+ }
777
+
778
+ DBENCH_STOP(*tpack);
779
+ }
780
+
781
+ /*************************************************
782
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyz_unpack
783
+ *
784
+ * Description: Unpack polynomial z with coefficients
785
+ * in [-(GAMMA1 - 1), GAMMA1].
786
+ *
787
+ * Arguments: - poly *r: pointer to output polynomial
788
+ * - const uint8_t *a: byte array with bit-packed polynomial
789
+ **************************************************/
790
+ void PQCLEAN_MLDSA44_CLEAN_polyz_unpack(poly *r, const uint8_t *a) {
791
+ unsigned int i;
792
+ DBENCH_START();
793
+
794
+ for (i = 0; i < N / 4; ++i) {
795
+ r->coeffs[4 * i + 0] = a[9 * i + 0];
796
+ r->coeffs[4 * i + 0] |= (uint32_t)a[9 * i + 1] << 8;
797
+ r->coeffs[4 * i + 0] |= (uint32_t)a[9 * i + 2] << 16;
798
+ r->coeffs[4 * i + 0] &= 0x3FFFF;
799
+
800
+ r->coeffs[4 * i + 1] = a[9 * i + 2] >> 2;
801
+ r->coeffs[4 * i + 1] |= (uint32_t)a[9 * i + 3] << 6;
802
+ r->coeffs[4 * i + 1] |= (uint32_t)a[9 * i + 4] << 14;
803
+ r->coeffs[4 * i + 1] &= 0x3FFFF;
804
+
805
+ r->coeffs[4 * i + 2] = a[9 * i + 4] >> 4;
806
+ r->coeffs[4 * i + 2] |= (uint32_t)a[9 * i + 5] << 4;
807
+ r->coeffs[4 * i + 2] |= (uint32_t)a[9 * i + 6] << 12;
808
+ r->coeffs[4 * i + 2] &= 0x3FFFF;
809
+
810
+ r->coeffs[4 * i + 3] = a[9 * i + 6] >> 6;
811
+ r->coeffs[4 * i + 3] |= (uint32_t)a[9 * i + 7] << 2;
812
+ r->coeffs[4 * i + 3] |= (uint32_t)a[9 * i + 8] << 10;
813
+ r->coeffs[4 * i + 3] &= 0x3FFFF;
814
+
815
+ r->coeffs[4 * i + 0] = GAMMA1 - r->coeffs[4 * i + 0];
816
+ r->coeffs[4 * i + 1] = GAMMA1 - r->coeffs[4 * i + 1];
817
+ r->coeffs[4 * i + 2] = GAMMA1 - r->coeffs[4 * i + 2];
818
+ r->coeffs[4 * i + 3] = GAMMA1 - r->coeffs[4 * i + 3];
819
+ }
820
+
821
+ DBENCH_STOP(*tpack);
822
+ }
823
+
824
+ /*************************************************
825
+ * Name: PQCLEAN_MLDSA44_CLEAN_polyw1_pack
826
+ *
827
+ * Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43].
828
+ * Input coefficients are assumed to be standard representatives.
829
+ *
830
+ * Arguments: - uint8_t *r: pointer to output byte array with at least
831
+ * POLYW1_PACKEDBYTES bytes
832
+ * - const poly *a: pointer to input polynomial
833
+ **************************************************/
834
+ void PQCLEAN_MLDSA44_CLEAN_polyw1_pack(uint8_t *r, const poly *a) {
835
+ unsigned int i;
836
+ DBENCH_START();
837
+
838
+ for (i = 0; i < N / 4; ++i) {
839
+ r[3 * i + 0] = (uint8_t) a->coeffs[4 * i + 0];
840
+ r[3 * i + 0] |= (uint8_t) (a->coeffs[4 * i + 1] << 6);
841
+ r[3 * i + 1] = (uint8_t) (a->coeffs[4 * i + 1] >> 2);
842
+ r[3 * i + 1] |= (uint8_t) (a->coeffs[4 * i + 2] << 4);
843
+ r[3 * i + 2] = (uint8_t) (a->coeffs[4 * i + 2] >> 4);
844
+ r[3 * i + 2] |= (uint8_t) (a->coeffs[4 * i + 3] << 2);
845
+ }
846
+
847
+ DBENCH_STOP(*tpack);
848
+ }