Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

738 строки
28 KiB

  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. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_reduce
  10. *
  11. * Description: Reduce all coefficients of input polynomial to representative
  12. * in [0,2*Q[.
  13. *
  14. * Arguments: - poly *a: pointer to input/output polynomial
  15. **************************************************/
  16. void PQCLEAN_DILITHIUM3_CLEAN_poly_reduce(poly *a) {
  17. unsigned int i;
  18. for (i = 0; i < N; ++i) {
  19. a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_reduce32(a->coeffs[i]);
  20. }
  21. }
  22. /*************************************************
  23. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_csubq
  24. *
  25. * Description: For all coefficients of input polynomial subtract Q if
  26. * coefficient is bigger than Q.
  27. *
  28. * Arguments: - poly *a: pointer to input/output polynomial
  29. **************************************************/
  30. void PQCLEAN_DILITHIUM3_CLEAN_poly_csubq(poly *a) {
  31. unsigned int i;
  32. for (i = 0; i < N; ++i) {
  33. a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_csubq(a->coeffs[i]);
  34. }
  35. }
  36. /*************************************************
  37. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_freeze
  38. *
  39. * Description: Reduce all coefficients of the polynomial to standard
  40. * representatives.
  41. *
  42. * Arguments: - poly *a: pointer to input/output polynomial
  43. **************************************************/
  44. void PQCLEAN_DILITHIUM3_CLEAN_poly_freeze(poly *a) {
  45. unsigned int i;
  46. for (i = 0; i < N; ++i) {
  47. a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_freeze(a->coeffs[i]);
  48. }
  49. }
  50. /*************************************************
  51. * Name: PQCLEAN_DILITHIUM3_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_DILITHIUM3_CLEAN_poly_add(poly *c, const poly *a, const poly *b) {
  60. unsigned int i;
  61. for (i = 0; i < N; ++i) {
  62. c->coeffs[i] = a->coeffs[i] + b->coeffs[i];
  63. }
  64. }
  65. /*************************************************
  66. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_sub
  67. *
  68. * Description: Subtract polynomials. Assumes coefficients of second input
  69. * polynomial to be less than 2*Q. No modular reduction is
  70. * performed.
  71. *
  72. * Arguments: - poly *c: pointer to output polynomial
  73. * - const poly *a: pointer to first input polynomial
  74. * - const poly *b: pointer to second input polynomial to be
  75. * subtraced from first input polynomial
  76. **************************************************/
  77. void PQCLEAN_DILITHIUM3_CLEAN_poly_sub(poly *c, const poly *a, const poly *b) {
  78. unsigned int i;
  79. for (i = 0; i < N; ++i) {
  80. c->coeffs[i] = a->coeffs[i] + 2 * Q - b->coeffs[i];
  81. }
  82. }
  83. /*************************************************
  84. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_shiftl
  85. *
  86. * Description: Multiply polynomial by 2^D without modular reduction. Assumes
  87. * input coefficients to be less than 2^{32-D}.
  88. *
  89. * Arguments: - poly *a: pointer to input/output polynomial
  90. **************************************************/
  91. void PQCLEAN_DILITHIUM3_CLEAN_poly_shiftl(poly *a) {
  92. unsigned int i;
  93. for (i = 0; i < N; ++i) {
  94. a->coeffs[i] <<= D;
  95. }
  96. }
  97. /*************************************************
  98. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_ntt
  99. *
  100. * Description: Forward NTT. Output coefficients can be up to 16*Q larger than
  101. * input coefficients.
  102. *
  103. * Arguments: - poly *a: pointer to input/output polynomial
  104. **************************************************/
  105. void PQCLEAN_DILITHIUM3_CLEAN_poly_ntt(poly *a) {
  106. PQCLEAN_DILITHIUM3_CLEAN_ntt(a->coeffs);
  107. }
  108. /*************************************************
  109. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery
  110. *
  111. * Description: Inverse NTT and multiplication with 2^{32}. Input coefficients
  112. * need to be less than 2*Q. Output coefficients are less than 2*Q.
  113. *
  114. * Arguments: - poly *a: pointer to input/output polynomial
  115. **************************************************/
  116. void PQCLEAN_DILITHIUM3_CLEAN_poly_invntt_montgomery(poly *a) {
  117. PQCLEAN_DILITHIUM3_CLEAN_invntt_frominvmont(a->coeffs);
  118. }
  119. /*************************************************
  120. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery
  121. *
  122. * Description: Pointwise multiplication of polynomials in NTT domain
  123. * representation and multiplication of resulting polynomial
  124. * with 2^{-32}. Output coefficients are less than 2*Q if input
  125. * coefficient are less than 22*Q.
  126. *
  127. * Arguments: - poly *c: pointer to output polynomial
  128. * - const poly *a: pointer to first input polynomial
  129. * - const poly *b: pointer to second input polynomial
  130. **************************************************/
  131. void PQCLEAN_DILITHIUM3_CLEAN_poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) {
  132. unsigned int i;
  133. for (i = 0; i < N; ++i) {
  134. c->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_montgomery_reduce((uint64_t)a->coeffs[i] * b->coeffs[i]);
  135. }
  136. }
  137. /*************************************************
  138. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_power2round
  139. *
  140. * Description: For all coefficients c of the input polynomial,
  141. * compute c0, c1 such that c mod Q = c1*2^D + c0
  142. * with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be
  143. * standard representatives.
  144. *
  145. * Arguments: - poly *a1: pointer to output polynomial with coefficients c1
  146. * - poly *a0: pointer to output polynomial with coefficients Q + a0
  147. * - const poly *v: pointer to input polynomial
  148. **************************************************/
  149. void PQCLEAN_DILITHIUM3_CLEAN_poly_power2round(poly *a1, poly *a0, const poly *a) {
  150. unsigned int i;
  151. for (i = 0; i < N; ++i) {
  152. a1->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_power2round(a->coeffs[i], &a0->coeffs[i]);
  153. }
  154. }
  155. /*************************************************
  156. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_decompose
  157. *
  158. * Description: For all coefficients c of the input polynomial,
  159. * compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0
  160. * with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we
  161. * set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0.
  162. * Assumes coefficients to be standard representatives.
  163. *
  164. * Arguments: - poly *a1: pointer to output polynomial with coefficients c1
  165. * - poly *a0: pointer to output polynomial with coefficients Q + a0
  166. * - const poly *c: pointer to input polynomial
  167. **************************************************/
  168. void PQCLEAN_DILITHIUM3_CLEAN_poly_decompose(poly *a1, poly *a0, const poly *a) {
  169. unsigned int i;
  170. for (i = 0; i < N; ++i) {
  171. a1->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_decompose(a->coeffs[i], &a0->coeffs[i]);
  172. }
  173. }
  174. /*************************************************
  175. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_make_hint
  176. *
  177. * Description: Compute hint polynomial. The coefficients of which indicate
  178. * whether the low bits of the corresponding coefficient of
  179. * the input polynomial overflow into the high bits.
  180. *
  181. * Arguments: - poly *h: pointer to output hint polynomial
  182. * - const poly *a0: pointer to low part of input polynomial
  183. * - const poly *a1: pointer to high part of input polynomial
  184. *
  185. * Returns number of 1 bits.
  186. **************************************************/
  187. unsigned int PQCLEAN_DILITHIUM3_CLEAN_poly_make_hint(poly *h, const poly *a0, const poly *a1) {
  188. unsigned int i, s = 0;
  189. for (i = 0; i < N; ++i) {
  190. h->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_make_hint(a0->coeffs[i], a1->coeffs[i]);
  191. s += h->coeffs[i];
  192. }
  193. return s;
  194. }
  195. /*************************************************
  196. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_use_hint
  197. *
  198. * Description: Use hint polynomial to correct the high bits of a polynomial.
  199. *
  200. * Arguments: - poly *a: pointer to output polynomial with corrected high bits
  201. * - const poly *b: pointer to input polynomial
  202. * - const poly *h: pointer to input hint polynomial
  203. **************************************************/
  204. void PQCLEAN_DILITHIUM3_CLEAN_poly_use_hint(poly *a, const poly *b, const poly *h) {
  205. unsigned int i;
  206. for (i = 0; i < N; ++i) {
  207. a->coeffs[i] = PQCLEAN_DILITHIUM3_CLEAN_use_hint(b->coeffs[i], h->coeffs[i]);
  208. }
  209. }
  210. /*************************************************
  211. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_chknorm
  212. *
  213. * Description: Check infinity norm of polynomial against given bound.
  214. * Assumes input coefficients to be standard representatives.
  215. *
  216. * Arguments: - const poly *a: pointer to polynomial
  217. * - uint32_t B: norm bound
  218. *
  219. * Returns 0 if norm is strictly smaller than B and 1 otherwise.
  220. **************************************************/
  221. int PQCLEAN_DILITHIUM3_CLEAN_poly_chknorm(const poly *a, uint32_t B) {
  222. unsigned int i;
  223. int32_t t;
  224. /* It is ok to leak which coefficient violates the bound since
  225. the probability for each coefficient is independent of secret
  226. data but we must not leak the sign of the centralized representative. */
  227. for (i = 0; i < N; ++i) {
  228. /* Absolute value of centralized representative */
  229. t = (int32_t) ((Q - 1) / 2 - a->coeffs[i]);
  230. t ^= (t >> 31);
  231. t = (Q - 1) / 2 - t;
  232. if ((uint32_t)t >= B) {
  233. return 1;
  234. }
  235. }
  236. return 0;
  237. }
  238. /*************************************************
  239. * Name: rej_uniform
  240. *
  241. * Description: Sample uniformly random coefficients in [0, Q-1] by
  242. * performing rejection sampling using array of random bytes.
  243. *
  244. * Arguments: - uint32_t *a: pointer to output array (allocated)
  245. * - unsigned int len: number of coefficients to be sampled
  246. * - const unsigned char *buf: array of random bytes
  247. * - unsigned int buflen: length of array of random bytes
  248. *
  249. * Returns number of sampled coefficients. Can be smaller than len if not enough
  250. * random bytes were given.
  251. **************************************************/
  252. static unsigned int rej_uniform(uint32_t *a,
  253. unsigned int len,
  254. const unsigned char *buf,
  255. unsigned int buflen) {
  256. unsigned int ctr, pos;
  257. uint32_t t;
  258. ctr = pos = 0;
  259. while (ctr < len && pos + 3 <= buflen) {
  260. t = buf[pos++];
  261. t |= (uint32_t)buf[pos++] << 8;
  262. t |= (uint32_t)buf[pos++] << 16;
  263. t &= 0x7FFFFF;
  264. if (t < Q) {
  265. a[ctr++] = t;
  266. }
  267. }
  268. return ctr;
  269. }
  270. /*************************************************
  271. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_uniform
  272. *
  273. * Description: Sample polynomial with uniformly random coefficients
  274. * in [0,Q-1] by performing rejection sampling using the
  275. * output stream from SHAKE256(seed|nonce).
  276. *
  277. * Arguments: - poly *a: pointer to output polynomial
  278. * - const unsigned char seed[]: byte array with seed of length
  279. * SEEDBYTES
  280. * - uint16_t nonce: 2-byte nonce
  281. **************************************************/
  282. #define POLY_UNIFORM_NBLOCKS ((769 + STREAM128_BLOCKBYTES)/STREAM128_BLOCKBYTES)
  283. #define POLY_UNIFORM_BUFLEN (POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES)
  284. void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform(poly *a,
  285. const unsigned char seed[SEEDBYTES],
  286. uint16_t nonce) {
  287. unsigned int i, ctr, off;
  288. unsigned int buflen = POLY_UNIFORM_BUFLEN;
  289. unsigned char buf[POLY_UNIFORM_BUFLEN + 2];
  290. shake128ctx state;
  291. stream128_init(&state, seed, nonce);
  292. stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state);
  293. ctr = rej_uniform(a->coeffs, N, buf, buflen);
  294. while (ctr < N) {
  295. off = buflen % 3;
  296. for (i = 0; i < off; ++i) {
  297. buf[i] = buf[buflen - off + i];
  298. }
  299. buflen = STREAM128_BLOCKBYTES + off;
  300. stream128_squeezeblocks(buf + off, 1, &state);
  301. ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen);
  302. }
  303. }
  304. /*************************************************
  305. * Name: rej_eta
  306. *
  307. * Description: Sample uniformly random coefficients in [-ETA, ETA] by
  308. * performing rejection sampling using array of random bytes.
  309. *
  310. * Arguments: - uint32_t *a: pointer to output array (allocated)
  311. * - unsigned int len: number of coefficients to be sampled
  312. * - const unsigned char *buf: array of random bytes
  313. * - unsigned int buflen: length of array of random bytes
  314. *
  315. * Returns number of sampled coefficients. Can be smaller than len if not enough
  316. * random bytes were given.
  317. **************************************************/
  318. static unsigned int rej_eta(uint32_t *a,
  319. unsigned int len,
  320. const unsigned char *buf,
  321. unsigned int buflen) {
  322. unsigned int ctr, pos;
  323. uint32_t t0, t1;
  324. ctr = pos = 0;
  325. while (ctr < len && pos < buflen) {
  326. t0 = buf[pos] & 0x0F;
  327. t1 = buf[pos++] >> 4;
  328. if (t0 <= 2 * ETA) {
  329. a[ctr++] = Q + ETA - t0;
  330. }
  331. if (t1 <= 2 * ETA && ctr < len) {
  332. a[ctr++] = Q + ETA - t1;
  333. }
  334. }
  335. return ctr;
  336. }
  337. /*************************************************
  338. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_eta
  339. *
  340. * Description: Sample polynomial with uniformly random coefficients
  341. * in [-ETA,ETA] by performing rejection sampling using the
  342. * output stream from SHAKE256(seed|nonce).
  343. *
  344. * Arguments: - poly *a: pointer to output polynomial
  345. * - const unsigned char seed[]: byte array with seed of length
  346. * SEEDBYTES
  347. * - uint16_t nonce: 2-byte nonce
  348. **************************************************/
  349. #define POLY_UNIFORM_ETA_NBLOCKS (((N/2 * (1U << SETABITS)) / (2*ETA + 1)\
  350. + STREAM128_BLOCKBYTES) / STREAM128_BLOCKBYTES)
  351. #define POLY_UNIFORM_ETA_BUFLEN (POLY_UNIFORM_ETA_NBLOCKS*STREAM128_BLOCKBYTES)
  352. void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_eta(poly *a,
  353. const unsigned char seed[SEEDBYTES],
  354. uint16_t nonce) {
  355. unsigned int ctr;
  356. unsigned char buf[POLY_UNIFORM_ETA_BUFLEN];
  357. shake128ctx state;
  358. stream128_init(&state, seed, nonce);
  359. stream128_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state);
  360. ctr = rej_eta(a->coeffs, N, buf, POLY_UNIFORM_ETA_BUFLEN);
  361. while (ctr < N) {
  362. stream128_squeezeblocks(buf, 1, &state);
  363. ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM128_BLOCKBYTES);
  364. }
  365. }
  366. /*************************************************
  367. * Name: rej_gamma1m1
  368. *
  369. * Description: Sample uniformly random coefficients
  370. * in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection sampling
  371. * using array of random bytes.
  372. *
  373. * Arguments: - uint32_t *a: pointer to output array (allocated)
  374. * - unsigned int len: number of coefficients to be sampled
  375. * - const unsigned char *buf: array of random bytes
  376. * - unsigned int buflen: length of array of random bytes
  377. *
  378. * Returns number of sampled coefficients. Can be smaller than len if not enough
  379. * random bytes were given.
  380. **************************************************/
  381. static unsigned int rej_gamma1m1(uint32_t *a,
  382. unsigned int len,
  383. const unsigned char *buf,
  384. unsigned int buflen) {
  385. unsigned int ctr, pos;
  386. uint32_t t0, t1;
  387. ctr = pos = 0;
  388. while (ctr < len && pos + 5 <= buflen) {
  389. t0 = buf[pos];
  390. t0 |= (uint32_t)buf[pos + 1] << 8;
  391. t0 |= (uint32_t)buf[pos + 2] << 16;
  392. t0 &= 0xFFFFF;
  393. t1 = buf[pos + 2] >> 4;
  394. t1 |= (uint32_t)buf[pos + 3] << 4;
  395. t1 |= (uint32_t)buf[pos + 4] << 12;
  396. pos += 5;
  397. if (t0 <= 2 * GAMMA1 - 2) {
  398. a[ctr++] = Q + GAMMA1 - 1 - t0;
  399. }
  400. if (t1 <= 2 * GAMMA1 - 2 && ctr < len) {
  401. a[ctr++] = Q + GAMMA1 - 1 - t1;
  402. }
  403. }
  404. return ctr;
  405. }
  406. /*************************************************
  407. * Name: PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_gamma1m1
  408. *
  409. * Description: Sample polynomial with uniformly random coefficients
  410. * in [-(GAMMA1 - 1), GAMMA1 - 1] by performing rejection
  411. * sampling on output stream of SHAKE256(seed|nonce).
  412. *
  413. * Arguments: - poly *a: pointer to output polynomial
  414. * - const unsigned char seed[]: byte array with seed of length
  415. * CRHBYTES
  416. * - uint16_t nonce: 16-bit nonce
  417. **************************************************/
  418. #define POLY_UNIFORM_GAMMA1M1_NBLOCKS ((641 + STREAM256_BLOCKBYTES) / STREAM256_BLOCKBYTES)
  419. #define POLY_UNIFORM_GAMMA1M1_BUFLEN (POLY_UNIFORM_GAMMA1M1_NBLOCKS * STREAM256_BLOCKBYTES)
  420. void PQCLEAN_DILITHIUM3_CLEAN_poly_uniform_gamma1m1(poly *a,
  421. const unsigned char seed[CRHBYTES],
  422. uint16_t nonce) {
  423. unsigned int i, ctr, off;
  424. unsigned int buflen = POLY_UNIFORM_GAMMA1M1_BUFLEN;
  425. unsigned char buf[POLY_UNIFORM_GAMMA1M1_BUFLEN + 4];
  426. shake256ctx state;
  427. stream256_init(&state, seed, nonce);
  428. stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1M1_NBLOCKS, &state);
  429. ctr = rej_gamma1m1(a->coeffs, N, buf, buflen);
  430. while (ctr < N) {
  431. off = buflen % 5;
  432. for (i = 0; i < off; ++i) {
  433. buf[i] = buf[buflen - off + i];
  434. }
  435. buflen = STREAM256_BLOCKBYTES + off;
  436. stream256_squeezeblocks(buf + off, 1, &state);
  437. ctr += rej_gamma1m1(a->coeffs + ctr, N - ctr, buf, buflen);
  438. }
  439. }
  440. /*************************************************
  441. * Name: PQCLEAN_DILITHIUM3_CLEAN_polyeta_pack
  442. *
  443. * Description: Bit-pack polynomial with coefficients in [-ETA,ETA].
  444. * Input coefficients are assumed to lie in [Q-ETA,Q+ETA].
  445. *
  446. * Arguments: - unsigned char *r: pointer to output byte array with at least
  447. * POLETA_SIZE_PACKED bytes
  448. * - const poly *a: pointer to input polynomial
  449. **************************************************/
  450. void PQCLEAN_DILITHIUM3_CLEAN_polyeta_pack(unsigned char *r, const poly *a) {
  451. unsigned int i;
  452. unsigned char t[8];
  453. for (i = 0; i < N / 2; ++i) {
  454. t[0] = (uint8_t) (Q + ETA - a->coeffs[2 * i + 0]);
  455. t[1] = (uint8_t) (Q + ETA - a->coeffs[2 * i + 1]);
  456. r[i] = (uint8_t) (t[0] | (t[1] << 4));
  457. }
  458. }
  459. /*************************************************
  460. * Name: PQCLEAN_DILITHIUM3_CLEAN_polyeta_unpack
  461. *
  462. * Description: Unpack polynomial with coefficients in [-ETA,ETA].
  463. * Output coefficients lie in [Q-ETA,Q+ETA].
  464. *
  465. * Arguments: - poly *r: pointer to output polynomial
  466. * - const unsigned char *a: byte array with bit-packed polynomial
  467. **************************************************/
  468. void PQCLEAN_DILITHIUM3_CLEAN_polyeta_unpack(poly *r, const unsigned char *a) {
  469. unsigned int i;
  470. for (i = 0; i < N / 2; ++i) {
  471. r->coeffs[2 * i + 0] = a[i] & 0x0F;
  472. r->coeffs[2 * i + 1] = a[i] >> 4;
  473. r->coeffs[2 * i + 0] = Q + ETA - r->coeffs[2 * i + 0];
  474. r->coeffs[2 * i + 1] = Q + ETA - r->coeffs[2 * i + 1];
  475. }
  476. }
  477. /*************************************************
  478. * Name: polyt1_pack
  479. *
  480. * Description: Bit-pack polynomial t1 with coefficients fitting in 9 bits.
  481. * Input coefficients are assumed to be standard representatives.
  482. *
  483. * Arguments: - unsigned char *r: pointer to output byte array with at least
  484. * POLT1_SIZE_PACKED bytes
  485. * - const poly *a: pointer to input polynomial
  486. **************************************************/
  487. void PQCLEAN_DILITHIUM3_CLEAN_polyt1_pack(unsigned char *r, const poly *a) {
  488. unsigned int i;
  489. for (i = 0; i < N / 8; ++i) {
  490. r[9 * i + 0] = (uint8_t) ((a->coeffs[8 * i + 0] >> 0));
  491. r[9 * i + 1] = (uint8_t) ((a->coeffs[8 * i + 0] >> 8) | (a->coeffs[8 * i + 1] << 1));
  492. r[9 * i + 2] = (uint8_t) ((a->coeffs[8 * i + 1] >> 7) | (a->coeffs[8 * i + 2] << 2));
  493. r[9 * i + 3] = (uint8_t) ((a->coeffs[8 * i + 2] >> 6) | (a->coeffs[8 * i + 3] << 3));
  494. r[9 * i + 4] = (uint8_t) ((a->coeffs[8 * i + 3] >> 5) | (a->coeffs[8 * i + 4] << 4));
  495. r[9 * i + 5] = (uint8_t) ((a->coeffs[8 * i + 4] >> 4) | (a->coeffs[8 * i + 5] << 5));
  496. r[9 * i + 6] = (uint8_t) ((a->coeffs[8 * i + 5] >> 3) | (a->coeffs[8 * i + 6] << 6));
  497. r[9 * i + 7] = (uint8_t) ((a->coeffs[8 * i + 6] >> 2) | (a->coeffs[8 * i + 7] << 7));
  498. r[9 * i + 8] = (uint8_t) ((a->coeffs[8 * i + 7] >> 1));
  499. }
  500. }
  501. /*************************************************
  502. * Name: polyt1_unpack
  503. *
  504. * Description: Unpack polynomial t1 with 9-bit coefficients.
  505. * Output coefficients are standard representatives.
  506. *
  507. * Arguments: - poly *r: pointer to output polynomial
  508. * - const unsigned char *a: byte array with bit-packed polynomial
  509. **************************************************/
  510. void PQCLEAN_DILITHIUM3_CLEAN_polyt1_unpack(poly *r, const unsigned char *a) {
  511. unsigned int i;
  512. for (i = 0; i < N / 8; ++i) {
  513. r->coeffs[8 * i + 0] = ((a[9 * i + 0] ) | ((uint32_t)a[9 * i + 1] << 8)) & 0x1FF;
  514. r->coeffs[8 * i + 1] = ((a[9 * i + 1] >> 1) | ((uint32_t)a[9 * i + 2] << 7)) & 0x1FF;
  515. r->coeffs[8 * i + 2] = ((a[9 * i + 2] >> 2) | ((uint32_t)a[9 * i + 3] << 6)) & 0x1FF;
  516. r->coeffs[8 * i + 3] = ((a[9 * i + 3] >> 3) | ((uint32_t)a[9 * i + 4] << 5)) & 0x1FF;
  517. r->coeffs[8 * i + 4] = ((a[9 * i + 4] >> 4) | ((uint32_t)a[9 * i + 5] << 4)) & 0x1FF;
  518. r->coeffs[8 * i + 5] = ((a[9 * i + 5] >> 5) | ((uint32_t)a[9 * i + 6] << 3)) & 0x1FF;
  519. r->coeffs[8 * i + 6] = ((a[9 * i + 6] >> 6) | ((uint32_t)a[9 * i + 7] << 2)) & 0x1FF;
  520. r->coeffs[8 * i + 7] = ((a[9 * i + 7] >> 7) | ((uint32_t)a[9 * i + 8] << 1)) & 0x1FF;
  521. }
  522. }
  523. /*************************************************
  524. * Name: PQCLEAN_DILITHIUM3_CLEAN_polyt0_pack
  525. *
  526. * Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
  527. * Input coefficients are assumed to lie in ]Q-2^{D-1}, Q+2^{D-1}].
  528. *
  529. * Arguments: - unsigned char *r: pointer to output byte array with at least
  530. * POLT0_SIZE_PACKED bytes
  531. * - const poly *a: pointer to input polynomial
  532. **************************************************/
  533. void PQCLEAN_DILITHIUM3_CLEAN_polyt0_pack(unsigned char *r, const poly *a) {
  534. unsigned int i;
  535. uint32_t t[4];
  536. for (i = 0; i < N / 4; ++i) {
  537. t[0] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 0];
  538. t[1] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 1];
  539. t[2] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 2];
  540. t[3] = Q + (1U << (D - 1)) - a->coeffs[4 * i + 3];
  541. r[7 * i + 0] = (uint8_t) (t[0]);
  542. r[7 * i + 1] = (uint8_t) (t[0] >> 8);
  543. r[7 * i + 1] |= (uint8_t) (t[1] << 6);
  544. r[7 * i + 2] = (uint8_t) (t[1] >> 2);
  545. r[7 * i + 3] = (uint8_t) (t[1] >> 10);
  546. r[7 * i + 3] |= (uint8_t) (t[2] << 4);
  547. r[7 * i + 4] = (uint8_t) (t[2] >> 4);
  548. r[7 * i + 5] = (uint8_t) (t[2] >> 12);
  549. r[7 * i + 5] |= (uint8_t) (t[3] << 2);
  550. r[7 * i + 6] = (uint8_t) (t[3] >> 6);
  551. }
  552. }
  553. /*************************************************
  554. * Name: PQCLEAN_DILITHIUM3_CLEAN_polyt0_unpack
  555. *
  556. * Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}].
  557. * Output coefficients lie in ]Q-2^{D-1},Q+2^{D-1}].
  558. *
  559. * Arguments: - poly *r: pointer to output polynomial
  560. * - const unsigned char *a: byte array with bit-packed polynomial
  561. **************************************************/
  562. void PQCLEAN_DILITHIUM3_CLEAN_polyt0_unpack(poly *r, const unsigned char *a) {
  563. unsigned int i;
  564. for (i = 0; i < N / 4; ++i) {
  565. r->coeffs[4 * i + 0] = a[7 * i + 0];
  566. r->coeffs[4 * i + 0] |= (uint32_t)(a[7 * i + 1] & 0x3F) << 8;
  567. r->coeffs[4 * i + 1] = a[7 * i + 1] >> 6;
  568. r->coeffs[4 * i + 1] |= (uint32_t)a[7 * i + 2] << 2;
  569. r->coeffs[4 * i + 1] |= (uint32_t)(a[7 * i + 3] & 0x0F) << 10;
  570. r->coeffs[4 * i + 2] = a[7 * i + 3] >> 4;
  571. r->coeffs[4 * i + 2] |= (uint32_t)a[7 * i + 4] << 4;
  572. r->coeffs[4 * i + 2] |= (uint32_t)(a[7 * i + 5] & 0x03) << 12;
  573. r->coeffs[4 * i + 3] = a[7 * i + 5] >> 2;
  574. r->coeffs[4 * i + 3] |= (uint32_t)a[7 * i + 6] << 6;
  575. r->coeffs[4 * i + 0] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 0];
  576. r->coeffs[4 * i + 1] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 1];
  577. r->coeffs[4 * i + 2] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 2];
  578. r->coeffs[4 * i + 3] = Q + (1U << (D - 1)) - r->coeffs[4 * i + 3];
  579. }
  580. }
  581. /*************************************************
  582. * Name: PQCLEAN_DILITHIUM3_CLEAN_polyz_pack
  583. *
  584. * Description: Bit-pack polynomial z with coefficients
  585. * in [-(GAMMA1 - 1), GAMMA1 - 1].
  586. * Input coefficients are assumed to be standard representatives.
  587. *
  588. * Arguments: - unsigned char *r: pointer to output byte array with at least
  589. * POLZ_SIZE_PACKED bytes
  590. * - const poly *a: pointer to input polynomial
  591. **************************************************/
  592. void PQCLEAN_DILITHIUM3_CLEAN_polyz_pack(unsigned char *r, const poly *a) {
  593. unsigned int i;
  594. uint32_t t[2];
  595. for (i = 0; i < N / 2; ++i) {
  596. /* Map to {0,...,2*GAMMA1 - 2} */
  597. t[0] = GAMMA1 - 1 - a->coeffs[2 * i + 0];
  598. t[0] += ((int32_t)t[0] >> 31) & Q;
  599. t[1] = GAMMA1 - 1 - a->coeffs[2 * i + 1];
  600. t[1] += ((int32_t)t[1] >> 31) & Q;
  601. r[5 * i + 0] = (uint8_t) (t[0]);
  602. r[5 * i + 1] = (uint8_t) (t[0] >> 8);
  603. r[5 * i + 2] = (uint8_t) (t[0] >> 16);
  604. r[5 * i + 2] |= (uint8_t) (t[1] << 4);
  605. r[5 * i + 3] = (uint8_t) (t[1] >> 4);
  606. r[5 * i + 4] = (uint8_t) (t[1] >> 12);
  607. }
  608. }
  609. /*************************************************
  610. * Name: PQCLEAN_DILITHIUM3_CLEAN_polyz_unpack
  611. *
  612. * Description: Unpack polynomial z with coefficients
  613. * in [-(GAMMA1 - 1), GAMMA1 - 1].
  614. * Output coefficients are standard representatives.
  615. *
  616. * Arguments: - poly *r: pointer to output polynomial
  617. * - const unsigned char *a: byte array with bit-packed polynomial
  618. **************************************************/
  619. void PQCLEAN_DILITHIUM3_CLEAN_polyz_unpack(poly *r, const unsigned char *a) {
  620. unsigned int i;
  621. for (i = 0; i < N / 2; ++i) {
  622. r->coeffs[2 * i + 0] = a[5 * i + 0];
  623. r->coeffs[2 * i + 0] |= (uint32_t)a[5 * i + 1] << 8;
  624. r->coeffs[2 * i + 0] |= (uint32_t)(a[5 * i + 2] & 0x0F) << 16;
  625. r->coeffs[2 * i + 1] = a[5 * i + 2] >> 4;
  626. r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 3] << 4;
  627. r->coeffs[2 * i + 1] |= (uint32_t)a[5 * i + 4] << 12;
  628. r->coeffs[2 * i + 0] = GAMMA1 - 1 - r->coeffs[2 * i + 0];
  629. r->coeffs[2 * i + 0] += ((int32_t)r->coeffs[2 * i + 0] >> 31) & Q;
  630. r->coeffs[2 * i + 1] = GAMMA1 - 1 - r->coeffs[2 * i + 1];
  631. r->coeffs[2 * i + 1] += ((int32_t)r->coeffs[2 * i + 1] >> 31) & Q;
  632. }
  633. }
  634. /*************************************************
  635. * Name: PQCLEAN_DILITHIUM3_CLEAN_polyw1_pack
  636. *
  637. * Description: Bit-pack polynomial w1 with coefficients in [0, 15].
  638. * Input coefficients are assumed to be standard representatives.
  639. *
  640. * Arguments: - unsigned char *r: pointer to output byte array with at least
  641. * POLW1_SIZE_PACKED bytes
  642. * - const poly *a: pointer to input polynomial
  643. **************************************************/
  644. void PQCLEAN_DILITHIUM3_CLEAN_polyw1_pack(unsigned char *r, const poly *a) {
  645. unsigned int i;
  646. for (i = 0; i < N / 2; ++i) {
  647. r[i] = (uint8_t) (a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4));
  648. }
  649. }