/src/libgcrypt/cipher/kyber-common.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* kyber-common.c - the Kyber key encapsulation mechanism (common part) |
2 | | * Copyright (C) 2024 g10 Code GmbH |
3 | | * |
4 | | * This file was modified for use by Libgcrypt. |
5 | | * |
6 | | * This file is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as |
8 | | * published by the Free Software Foundation; either version 2.1 of |
9 | | * the License, or (at your option) any later version. |
10 | | * |
11 | | * This file is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this program; if not, see <https://www.gnu.org/licenses/>. |
18 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
19 | | * |
20 | | * You can also use this file under the same licence of original code. |
21 | | * SPDX-License-Identifier: CC0 OR Apache-2.0 |
22 | | * |
23 | | */ |
24 | | /* |
25 | | Original code from: |
26 | | |
27 | | Repository: https://github.com/pq-crystals/kyber.git |
28 | | Branch: standard |
29 | | Commit: 11d00ff1f20cfca1f72d819e5a45165c1e0a2816 |
30 | | |
31 | | Licence: |
32 | | Public Domain (https://creativecommons.org/share-your-work/public-domain/cc0/); |
33 | | or Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0.html). |
34 | | |
35 | | Authors: |
36 | | Joppe Bos |
37 | | Léo Ducas |
38 | | Eike Kiltz |
39 | | Tancrède Lepoint |
40 | | Vadim Lyubashevsky |
41 | | John Schanck |
42 | | Peter Schwabe |
43 | | Gregor Seiler |
44 | | Damien Stehlé |
45 | | |
46 | | Kyber Home: https://www.pq-crystals.org/kyber/ |
47 | | */ |
48 | | /* |
49 | | * From original code, following modification was made. |
50 | | * |
51 | | * - C++ style comments are changed to C-style. |
52 | | * |
53 | | * - Functions "poly_cbd_eta1" "poly_cbd_eta2" are removed. |
54 | | * |
55 | | * - Constant "zeta" is static, not available outside. |
56 | | * |
57 | | * - "poly_compress" and "poly_decompress" are now two variants _128 |
58 | | * and _160. |
59 | | * |
60 | | * - "poly_getnoise_eta1" is now two variants _2 and _3_4. |
61 | | * |
62 | | * - "poly_getnoise_eta2" directly uses "cbd2" function. |
63 | | */ |
64 | | |
65 | | /*************** kyber/ref/cbd.c */ |
66 | | |
67 | | /************************************************* |
68 | | * Name: load32_littleendian |
69 | | * |
70 | | * Description: load 4 bytes into a 32-bit integer |
71 | | * in little-endian order |
72 | | * |
73 | | * Arguments: - const uint8_t *x: pointer to input byte array |
74 | | * |
75 | | * Returns 32-bit unsigned integer loaded from x |
76 | | **************************************************/ |
77 | | static uint32_t load32_littleendian(const uint8_t x[4]) |
78 | 0 | { |
79 | 0 | uint32_t r; |
80 | 0 | r = (uint32_t)x[0]; |
81 | 0 | r |= (uint32_t)x[1] << 8; |
82 | 0 | r |= (uint32_t)x[2] << 16; |
83 | 0 | r |= (uint32_t)x[3] << 24; |
84 | 0 | return r; |
85 | 0 | } |
86 | | |
87 | | /************************************************* |
88 | | * Name: load24_littleendian |
89 | | * |
90 | | * Description: load 3 bytes into a 32-bit integer |
91 | | * in little-endian order. |
92 | | * This function is only needed for Kyber-512 |
93 | | * |
94 | | * Arguments: - const uint8_t *x: pointer to input byte array |
95 | | * |
96 | | * Returns 32-bit unsigned integer loaded from x (most significant byte is zero) |
97 | | **************************************************/ |
98 | | #if !defined(KYBER_K) || KYBER_K == 2 |
99 | | static uint32_t load24_littleendian(const uint8_t x[3]) |
100 | 0 | { |
101 | 0 | uint32_t r; |
102 | 0 | r = (uint32_t)x[0]; |
103 | 0 | r |= (uint32_t)x[1] << 8; |
104 | 0 | r |= (uint32_t)x[2] << 16; |
105 | 0 | return r; |
106 | 0 | } |
107 | | #endif |
108 | | |
109 | | |
110 | | /************************************************* |
111 | | * Name: cbd2 |
112 | | * |
113 | | * Description: Given an array of uniformly random bytes, compute |
114 | | * polynomial with coefficients distributed according to |
115 | | * a centered binomial distribution with parameter eta=2 |
116 | | * |
117 | | * Arguments: - poly *r: pointer to output polynomial |
118 | | * - const uint8_t *buf: pointer to input byte array |
119 | | **************************************************/ |
120 | | static void cbd2(poly *r, const uint8_t buf[2*KYBER_N/4]) |
121 | 0 | { |
122 | 0 | unsigned int i,j; |
123 | 0 | uint32_t t,d; |
124 | 0 | int16_t a,b; |
125 | |
|
126 | 0 | for(i=0;i<KYBER_N/8;i++) { |
127 | 0 | t = load32_littleendian(buf+4*i); |
128 | 0 | d = t & 0x55555555; |
129 | 0 | d += (t>>1) & 0x55555555; |
130 | |
|
131 | 0 | for(j=0;j<8;j++) { |
132 | 0 | a = (d >> (4*j+0)) & 0x3; |
133 | 0 | b = (d >> (4*j+2)) & 0x3; |
134 | 0 | r->coeffs[8*i+j] = a - b; |
135 | 0 | } |
136 | 0 | } |
137 | 0 | } |
138 | | |
139 | | /************************************************* |
140 | | * Name: cbd3 |
141 | | * |
142 | | * Description: Given an array of uniformly random bytes, compute |
143 | | * polynomial with coefficients distributed according to |
144 | | * a centered binomial distribution with parameter eta=3. |
145 | | * This function is only needed for Kyber-512 |
146 | | * |
147 | | * Arguments: - poly *r: pointer to output polynomial |
148 | | * - const uint8_t *buf: pointer to input byte array |
149 | | **************************************************/ |
150 | | #if !defined(KYBER_K) || KYBER_K == 2 |
151 | | static void cbd3(poly *r, const uint8_t buf[3*KYBER_N/4]) |
152 | 0 | { |
153 | 0 | unsigned int i,j; |
154 | 0 | uint32_t t,d; |
155 | 0 | int16_t a,b; |
156 | |
|
157 | 0 | for(i=0;i<KYBER_N/4;i++) { |
158 | 0 | t = load24_littleendian(buf+3*i); |
159 | 0 | d = t & 0x00249249; |
160 | 0 | d += (t>>1) & 0x00249249; |
161 | 0 | d += (t>>2) & 0x00249249; |
162 | |
|
163 | 0 | for(j=0;j<4;j++) { |
164 | 0 | a = (d >> (6*j+0)) & 0x7; |
165 | 0 | b = (d >> (6*j+3)) & 0x7; |
166 | 0 | r->coeffs[4*i+j] = a - b; |
167 | 0 | } |
168 | 0 | } |
169 | 0 | } |
170 | | #endif |
171 | | |
172 | | /*************** kyber/ref/indcpa.c */ |
173 | | /************************************************* |
174 | | * Name: rej_uniform |
175 | | * |
176 | | * Description: Run rejection sampling on uniform random bytes to generate |
177 | | * uniform random integers mod q |
178 | | * |
179 | | * Arguments: - int16_t *r: pointer to output buffer |
180 | | * - unsigned int len: requested number of 16-bit integers (uniform mod q) |
181 | | * - const uint8_t *buf: pointer to input buffer (assumed to be uniformly random bytes) |
182 | | * - unsigned int buflen: length of input buffer in bytes |
183 | | * |
184 | | * Returns number of sampled 16-bit integers (at most len) |
185 | | **************************************************/ |
186 | | static unsigned int rej_uniform(int16_t *r, |
187 | | unsigned int len, |
188 | | const uint8_t *buf, |
189 | | unsigned int buflen) |
190 | 0 | { |
191 | 0 | unsigned int ctr, pos; |
192 | 0 | uint16_t val0, val1; |
193 | |
|
194 | 0 | ctr = pos = 0; |
195 | 0 | while(ctr < len && pos + 3 <= buflen) { |
196 | 0 | val0 = ((buf[pos+0] >> 0) | ((uint16_t)buf[pos+1] << 8)) & 0xFFF; |
197 | 0 | val1 = ((buf[pos+1] >> 4) | ((uint16_t)buf[pos+2] << 4)) & 0xFFF; |
198 | 0 | pos += 3; |
199 | |
|
200 | 0 | if(val0 < KYBER_Q) |
201 | 0 | r[ctr++] = val0; |
202 | 0 | if(ctr < len && val1 < KYBER_Q) |
203 | 0 | r[ctr++] = val1; |
204 | 0 | } |
205 | |
|
206 | 0 | return ctr; |
207 | 0 | } |
208 | | |
209 | | /*************** kyber/ref/ntt.c */ |
210 | | /* Code to generate zetas and zetas_inv used in the number-theoretic transform: |
211 | | |
212 | | #define KYBER_ROOT_OF_UNITY 17 |
213 | | |
214 | | static const uint8_t tree[128] = { |
215 | | 0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120, |
216 | | 4, 68, 36, 100, 20, 84, 52, 116, 12, 76, 44, 108, 28, 92, 60, 124, |
217 | | 2, 66, 34, 98, 18, 82, 50, 114, 10, 74, 42, 106, 26, 90, 58, 122, |
218 | | 6, 70, 38, 102, 22, 86, 54, 118, 14, 78, 46, 110, 30, 94, 62, 126, |
219 | | 1, 65, 33, 97, 17, 81, 49, 113, 9, 73, 41, 105, 25, 89, 57, 121, |
220 | | 5, 69, 37, 101, 21, 85, 53, 117, 13, 77, 45, 109, 29, 93, 61, 125, |
221 | | 3, 67, 35, 99, 19, 83, 51, 115, 11, 75, 43, 107, 27, 91, 59, 123, |
222 | | 7, 71, 39, 103, 23, 87, 55, 119, 15, 79, 47, 111, 31, 95, 63, 127 |
223 | | }; |
224 | | |
225 | | void init_ntt() { |
226 | | unsigned int i; |
227 | | int16_t tmp[128]; |
228 | | |
229 | | tmp[0] = MONT; |
230 | | for(i=1;i<128;i++) |
231 | | tmp[i] = fqmul(tmp[i-1],MONT*KYBER_ROOT_OF_UNITY % KYBER_Q); |
232 | | |
233 | | for(i=0;i<128;i++) { |
234 | | zetas[i] = tmp[tree[i]]; |
235 | | if(zetas[i] > KYBER_Q/2) |
236 | | zetas[i] -= KYBER_Q; |
237 | | if(zetas[i] < -KYBER_Q/2) |
238 | | zetas[i] += KYBER_Q; |
239 | | } |
240 | | } |
241 | | */ |
242 | | |
243 | | static const int16_t zetas[128] = { |
244 | | -1044, -758, -359, -1517, 1493, 1422, 287, 202, |
245 | | -171, 622, 1577, 182, 962, -1202, -1474, 1468, |
246 | | 573, -1325, 264, 383, -829, 1458, -1602, -130, |
247 | | -681, 1017, 732, 608, -1542, 411, -205, -1571, |
248 | | 1223, 652, -552, 1015, -1293, 1491, -282, -1544, |
249 | | 516, -8, -320, -666, -1618, -1162, 126, 1469, |
250 | | -853, -90, -271, 830, 107, -1421, -247, -951, |
251 | | -398, 961, -1508, -725, 448, -1065, 677, -1275, |
252 | | -1103, 430, 555, 843, -1251, 871, 1550, 105, |
253 | | 422, 587, 177, -235, -291, -460, 1574, 1653, |
254 | | -246, 778, 1159, -147, -777, 1483, -602, 1119, |
255 | | -1590, 644, -872, 349, 418, 329, -156, -75, |
256 | | 817, 1097, 603, 610, 1322, -1285, -1465, 384, |
257 | | -1215, -136, 1218, -1335, -874, 220, -1187, -1659, |
258 | | -1185, -1530, -1278, 794, -1510, -854, -870, 478, |
259 | | -108, -308, 996, 991, 958, -1460, 1522, 1628 |
260 | | }; |
261 | | |
262 | | /************************************************* |
263 | | * Name: fqmul |
264 | | * |
265 | | * Description: Multiplication followed by Montgomery reduction |
266 | | * |
267 | | * Arguments: - int16_t a: first factor |
268 | | * - int16_t b: second factor |
269 | | * |
270 | | * Returns 16-bit integer congruent to a*b*R^{-1} mod q |
271 | | **************************************************/ |
272 | 0 | static int16_t fqmul(int16_t a, int16_t b) { |
273 | 0 | return montgomery_reduce((int32_t)a*b); |
274 | 0 | } |
275 | | |
276 | | /************************************************* |
277 | | * Name: ntt |
278 | | * |
279 | | * Description: Inplace number-theoretic transform (NTT) in Rq. |
280 | | * input is in standard order, output is in bitreversed order |
281 | | * |
282 | | * Arguments: - int16_t r[256]: pointer to input/output vector of elements of Zq |
283 | | **************************************************/ |
284 | 0 | void ntt(int16_t r[256]) { |
285 | 0 | unsigned int len, start, j, k; |
286 | 0 | int16_t t, zeta; |
287 | |
|
288 | 0 | k = 1; |
289 | 0 | for(len = 128; len >= 2; len >>= 1) { |
290 | 0 | for(start = 0; start < 256; start = j + len) { |
291 | 0 | zeta = zetas[k++]; |
292 | 0 | for(j = start; j < start + len; j++) { |
293 | 0 | t = fqmul(zeta, r[j + len]); |
294 | 0 | r[j + len] = r[j] - t; |
295 | 0 | r[j] = r[j] + t; |
296 | 0 | } |
297 | 0 | } |
298 | 0 | } |
299 | 0 | } |
300 | | |
301 | | /************************************************* |
302 | | * Name: invntt_tomont |
303 | | * |
304 | | * Description: Inplace inverse number-theoretic transform in Rq and |
305 | | * multiplication by Montgomery factor 2^16. |
306 | | * Input is in bitreversed order, output is in standard order |
307 | | * |
308 | | * Arguments: - int16_t r[256]: pointer to input/output vector of elements of Zq |
309 | | **************************************************/ |
310 | 0 | void invntt(int16_t r[256]) { |
311 | 0 | unsigned int start, len, j, k; |
312 | 0 | int16_t t, zeta; |
313 | 0 | const int16_t f = 1441; /* mont^2/128 */ |
314 | |
|
315 | 0 | k = 127; |
316 | 0 | for(len = 2; len <= 128; len <<= 1) { |
317 | 0 | for(start = 0; start < 256; start = j + len) { |
318 | 0 | zeta = zetas[k--]; |
319 | 0 | for(j = start; j < start + len; j++) { |
320 | 0 | t = r[j]; |
321 | 0 | r[j] = barrett_reduce(t + r[j + len]); |
322 | 0 | r[j + len] = r[j + len] - t; |
323 | 0 | r[j + len] = fqmul(zeta, r[j + len]); |
324 | 0 | } |
325 | 0 | } |
326 | 0 | } |
327 | |
|
328 | 0 | for(j = 0; j < 256; j++) |
329 | 0 | r[j] = fqmul(r[j], f); |
330 | 0 | } |
331 | | |
332 | | /************************************************* |
333 | | * Name: basemul |
334 | | * |
335 | | * Description: Multiplication of polynomials in Zq[X]/(X^2-zeta) |
336 | | * used for multiplication of elements in Rq in NTT domain |
337 | | * |
338 | | * Arguments: - int16_t r[2]: pointer to the output polynomial |
339 | | * - const int16_t a[2]: pointer to the first factor |
340 | | * - const int16_t b[2]: pointer to the second factor |
341 | | * - int16_t zeta: integer defining the reduction polynomial |
342 | | **************************************************/ |
343 | | void basemul(int16_t r[2], const int16_t a[2], const int16_t b[2], int16_t zeta) |
344 | 0 | { |
345 | 0 | r[0] = fqmul(a[1], b[1]); |
346 | 0 | r[0] = fqmul(r[0], zeta); |
347 | 0 | r[0] += fqmul(a[0], b[0]); |
348 | 0 | r[1] = fqmul(a[0], b[1]); |
349 | 0 | r[1] += fqmul(a[1], b[0]); |
350 | 0 | } |
351 | | /*************** kyber/ref/poly.c */ |
352 | | |
353 | | /************************************************* |
354 | | * Name: poly_compress |
355 | | * |
356 | | * Description: Compression and subsequent serialization of a polynomial |
357 | | * |
358 | | * Arguments: - uint8_t *r: pointer to output byte array |
359 | | * (of length KYBER_POLYCOMPRESSEDBYTES) |
360 | | * - const poly *a: pointer to input polynomial |
361 | | **************************************************/ |
362 | | #if !defined(KYBER_K) || KYBER_K == 2 || KYBER_K == 3 |
363 | | void poly_compress_128(uint8_t r[KYBER_POLYCOMPRESSEDBYTES_2_3], const poly *a) |
364 | 0 | { |
365 | 0 | unsigned int i,j; |
366 | 0 | int32_t u; |
367 | 0 | uint32_t d0; |
368 | 0 | uint8_t t[8]; |
369 | |
|
370 | 0 | for(i=0;i<KYBER_N/8;i++) { |
371 | 0 | for(j=0;j<8;j++) { |
372 | | /* map to positive standard representatives */ |
373 | 0 | u = a->coeffs[8*i+j]; |
374 | 0 | u += (u >> 15) & KYBER_Q; |
375 | | /* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ |
376 | 0 | d0 = u << 4; |
377 | 0 | d0 += 1665; |
378 | 0 | d0 *= 80635; |
379 | 0 | d0 >>= 28; |
380 | 0 | t[j] = d0 & 0xf; |
381 | 0 | } |
382 | |
|
383 | 0 | r[0] = t[0] | (t[1] << 4); |
384 | 0 | r[1] = t[2] | (t[3] << 4); |
385 | 0 | r[2] = t[4] | (t[5] << 4); |
386 | 0 | r[3] = t[6] | (t[7] << 4); |
387 | 0 | r += 4; |
388 | 0 | } |
389 | 0 | } |
390 | | #endif |
391 | | |
392 | | #if !defined(KYBER_K) || KYBER_K == 4 |
393 | | void poly_compress_160(uint8_t r[KYBER_POLYCOMPRESSEDBYTES_4], const poly *a) |
394 | 0 | { |
395 | 0 | unsigned int i,j; |
396 | 0 | int32_t u; |
397 | 0 | uint32_t d0; |
398 | 0 | uint8_t t[8]; |
399 | |
|
400 | 0 | for(i=0;i<KYBER_N/8;i++) { |
401 | 0 | for(j=0;j<8;j++) { |
402 | | /* map to positive standard representatives */ |
403 | 0 | u = a->coeffs[8*i+j]; |
404 | 0 | u += (u >> 15) & KYBER_Q; |
405 | | /* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ |
406 | 0 | d0 = u << 5; |
407 | 0 | d0 += 1664; |
408 | 0 | d0 *= 40318; |
409 | 0 | d0 >>= 27; |
410 | 0 | t[j] = d0 & 0x1f; |
411 | 0 | } |
412 | |
|
413 | 0 | r[0] = (t[0] >> 0) | (t[1] << 5); |
414 | 0 | r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); |
415 | 0 | r[2] = (t[3] >> 1) | (t[4] << 4); |
416 | 0 | r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); |
417 | 0 | r[4] = (t[6] >> 2) | (t[7] << 3); |
418 | 0 | r += 5; |
419 | 0 | } |
420 | 0 | } |
421 | | #endif |
422 | | |
423 | | /************************************************* |
424 | | * Name: poly_decompress |
425 | | * |
426 | | * Description: De-serialization and subsequent decompression of a polynomial; |
427 | | * approximate inverse of poly_compress |
428 | | * |
429 | | * Arguments: - poly *r: pointer to output polynomial |
430 | | * - const uint8_t *a: pointer to input byte array |
431 | | * (of length KYBER_POLYCOMPRESSEDBYTES bytes) |
432 | | **************************************************/ |
433 | | #if !defined(KYBER_K) || KYBER_K == 2 || KYBER_K == 3 |
434 | | void poly_decompress_128(poly *r, const uint8_t a[KYBER_POLYCOMPRESSEDBYTES_2_3]) |
435 | 0 | { |
436 | 0 | unsigned int i; |
437 | 0 | for(i=0;i<KYBER_N/2;i++) { |
438 | 0 | r->coeffs[2*i+0] = (((uint16_t)(a[0] & 15)*KYBER_Q) + 8) >> 4; |
439 | 0 | r->coeffs[2*i+1] = (((uint16_t)(a[0] >> 4)*KYBER_Q) + 8) >> 4; |
440 | 0 | a += 1; |
441 | 0 | } |
442 | 0 | } |
443 | | #endif |
444 | | |
445 | | #if !defined(KYBER_K) || KYBER_K == 4 |
446 | | void poly_decompress_160(poly *r, const uint8_t a[KYBER_POLYCOMPRESSEDBYTES_4]) |
447 | 0 | { |
448 | 0 | unsigned int i; |
449 | 0 | unsigned int j; |
450 | 0 | uint8_t t[8]; |
451 | 0 | for(i=0;i<KYBER_N/8;i++) { |
452 | 0 | t[0] = (a[0] >> 0); |
453 | 0 | t[1] = (a[0] >> 5) | (a[1] << 3); |
454 | 0 | t[2] = (a[1] >> 2); |
455 | 0 | t[3] = (a[1] >> 7) | (a[2] << 1); |
456 | 0 | t[4] = (a[2] >> 4) | (a[3] << 4); |
457 | 0 | t[5] = (a[3] >> 1); |
458 | 0 | t[6] = (a[3] >> 6) | (a[4] << 2); |
459 | 0 | t[7] = (a[4] >> 3); |
460 | 0 | a += 5; |
461 | |
|
462 | 0 | for(j=0;j<8;j++) |
463 | 0 | r->coeffs[8*i+j] = ((uint32_t)(t[j] & 31)*KYBER_Q + 16) >> 5; |
464 | 0 | } |
465 | 0 | } |
466 | | #endif |
467 | | |
468 | | /************************************************* |
469 | | * Name: poly_tobytes |
470 | | * |
471 | | * Description: Serialization of a polynomial |
472 | | * |
473 | | * Arguments: - uint8_t *r: pointer to output byte array |
474 | | * (needs space for KYBER_POLYBYTES bytes) |
475 | | * - const poly *a: pointer to input polynomial |
476 | | **************************************************/ |
477 | | void poly_tobytes(uint8_t r[KYBER_POLYBYTES], const poly *a) |
478 | 0 | { |
479 | 0 | unsigned int i; |
480 | 0 | uint16_t t0, t1; |
481 | |
|
482 | 0 | for(i=0;i<KYBER_N/2;i++) { |
483 | | /* map to positive standard representatives */ |
484 | 0 | t0 = a->coeffs[2*i]; |
485 | 0 | t0 += ((int16_t)t0 >> 15) & KYBER_Q; |
486 | 0 | t1 = a->coeffs[2*i+1]; |
487 | 0 | t1 += ((int16_t)t1 >> 15) & KYBER_Q; |
488 | 0 | r[3*i+0] = (t0 >> 0); |
489 | 0 | r[3*i+1] = (t0 >> 8) | (t1 << 4); |
490 | 0 | r[3*i+2] = (t1 >> 4); |
491 | 0 | } |
492 | 0 | } |
493 | | |
494 | | /************************************************* |
495 | | * Name: poly_frombytes |
496 | | * |
497 | | * Description: De-serialization of a polynomial; |
498 | | * inverse of poly_tobytes |
499 | | * |
500 | | * Arguments: - poly *r: pointer to output polynomial |
501 | | * - const uint8_t *a: pointer to input byte array |
502 | | * (of KYBER_POLYBYTES bytes) |
503 | | **************************************************/ |
504 | | void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES]) |
505 | 0 | { |
506 | 0 | unsigned int i; |
507 | 0 | for(i=0;i<KYBER_N/2;i++) { |
508 | 0 | r->coeffs[2*i] = ((a[3*i+0] >> 0) | ((uint16_t)a[3*i+1] << 8)) & 0xFFF; |
509 | 0 | r->coeffs[2*i+1] = ((a[3*i+1] >> 4) | ((uint16_t)a[3*i+2] << 4)) & 0xFFF; |
510 | 0 | } |
511 | 0 | } |
512 | | |
513 | | /************************************************* |
514 | | * Name: poly_frommsg |
515 | | * |
516 | | * Description: Convert 32-byte message to polynomial |
517 | | * |
518 | | * Arguments: - poly *r: pointer to output polynomial |
519 | | * - const uint8_t *msg: pointer to input message |
520 | | **************************************************/ |
521 | | void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES]) |
522 | 0 | { |
523 | 0 | unsigned int i,j; |
524 | |
|
525 | | #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8) |
526 | | #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!" |
527 | | #endif |
528 | |
|
529 | 0 | for(i=0;i<KYBER_N/8;i++) { |
530 | 0 | for(j=0;j<8;j++) { |
531 | 0 | r->coeffs[8*i+j] = ct_int16_select (((KYBER_Q+1)/2), 0, (msg[i] >> j)&1); |
532 | 0 | } |
533 | 0 | } |
534 | 0 | } |
535 | | |
536 | | /************************************************* |
537 | | * Name: poly_tomsg |
538 | | * |
539 | | * Description: Convert polynomial to 32-byte message |
540 | | * |
541 | | * Arguments: - uint8_t *msg: pointer to output message |
542 | | * - const poly *a: pointer to input polynomial |
543 | | **************************************************/ |
544 | | void poly_tomsg(uint8_t msg[KYBER_INDCPA_MSGBYTES], const poly *a) |
545 | 0 | { |
546 | 0 | unsigned int i,j; |
547 | 0 | uint32_t t; |
548 | |
|
549 | 0 | for(i=0;i<KYBER_N/8;i++) { |
550 | 0 | msg[i] = 0; |
551 | 0 | for(j=0;j<8;j++) { |
552 | 0 | t = a->coeffs[8*i+j]; |
553 | | /* t += ((int16_t)t >> 15) & KYBER_Q; */ |
554 | | /* t = (((t << 1) + KYBER_Q/2)/KYBER_Q) & 1; */ |
555 | 0 | t <<= 1; |
556 | 0 | t += 1665; |
557 | 0 | t *= 80635; |
558 | 0 | t >>= 28; |
559 | 0 | t &= 1; |
560 | 0 | msg[i] |= t << j; |
561 | 0 | } |
562 | 0 | } |
563 | 0 | } |
564 | | |
565 | | /************************************************* |
566 | | * Name: poly_getnoise_eta1 |
567 | | * |
568 | | * Description: Sample a polynomial deterministically from a seed and a nonce, |
569 | | * with output polynomial close to centered binomial distribution |
570 | | * with parameter KYBER_ETA1 |
571 | | * |
572 | | * Arguments: - poly *r: pointer to output polynomial |
573 | | * - const uint8_t *seed: pointer to input seed |
574 | | * (of length KYBER_SYMBYTES bytes) |
575 | | * - uint8_t nonce: one-byte input nonce |
576 | | **************************************************/ |
577 | | #if !defined(KYBER_K) || KYBER_K == 2 |
578 | | void poly_getnoise_eta1_2(poly *r, const uint8_t seed[KYBER_SYMBYTES], uint8_t nonce) |
579 | 0 | { |
580 | 0 | uint8_t buf[KYBER_ETA1_2*KYBER_N/4]; |
581 | 0 | prf(buf, sizeof(buf), seed, nonce); |
582 | 0 | cbd3(r, buf); |
583 | 0 | } |
584 | | #endif |
585 | | |
586 | | #if !defined(KYBER_K) || KYBER_K == 3 || KYBER_K == 4 |
587 | | void poly_getnoise_eta1_3_4(poly *r, const uint8_t seed[KYBER_SYMBYTES], uint8_t nonce) |
588 | 0 | { |
589 | 0 | uint8_t buf[KYBER_ETA1_3_4*KYBER_N/4]; |
590 | 0 | prf(buf, sizeof(buf), seed, nonce); |
591 | 0 | cbd2(r, buf); |
592 | 0 | } |
593 | | #endif |
594 | | |
595 | | /************************************************* |
596 | | * Name: poly_getnoise_eta2 |
597 | | * |
598 | | * Description: Sample a polynomial deterministically from a seed and a nonce, |
599 | | * with output polynomial close to centered binomial distribution |
600 | | * with parameter KYBER_ETA2 |
601 | | * |
602 | | * Arguments: - poly *r: pointer to output polynomial |
603 | | * - const uint8_t *seed: pointer to input seed |
604 | | * (of length KYBER_SYMBYTES bytes) |
605 | | * - uint8_t nonce: one-byte input nonce |
606 | | **************************************************/ |
607 | | void poly_getnoise_eta2(poly *r, const uint8_t seed[KYBER_SYMBYTES], uint8_t nonce) |
608 | 0 | { |
609 | 0 | uint8_t buf[KYBER_ETA2*KYBER_N/4]; |
610 | 0 | prf(buf, sizeof(buf), seed, nonce); |
611 | 0 | cbd2(r, buf); |
612 | 0 | } |
613 | | |
614 | | |
615 | | /************************************************* |
616 | | * Name: poly_ntt |
617 | | * |
618 | | * Description: Computes negacyclic number-theoretic transform (NTT) of |
619 | | * a polynomial in place; |
620 | | * inputs assumed to be in normal order, output in bitreversed order |
621 | | * |
622 | | * Arguments: - uint16_t *r: pointer to in/output polynomial |
623 | | **************************************************/ |
624 | | void poly_ntt(poly *r) |
625 | 0 | { |
626 | 0 | ntt(r->coeffs); |
627 | 0 | poly_reduce(r); |
628 | 0 | } |
629 | | |
630 | | /************************************************* |
631 | | * Name: poly_invntt_tomont |
632 | | * |
633 | | * Description: Computes inverse of negacyclic number-theoretic transform (NTT) |
634 | | * of a polynomial in place; |
635 | | * inputs assumed to be in bitreversed order, output in normal order |
636 | | * |
637 | | * Arguments: - uint16_t *a: pointer to in/output polynomial |
638 | | **************************************************/ |
639 | | void poly_invntt_tomont(poly *r) |
640 | 0 | { |
641 | 0 | invntt(r->coeffs); |
642 | 0 | } |
643 | | |
644 | | /************************************************* |
645 | | * Name: poly_basemul_montgomery |
646 | | * |
647 | | * Description: Multiplication of two polynomials in NTT domain |
648 | | * |
649 | | * Arguments: - poly *r: pointer to output polynomial |
650 | | * - const poly *a: pointer to first input polynomial |
651 | | * - const poly *b: pointer to second input polynomial |
652 | | **************************************************/ |
653 | | void poly_basemul_montgomery(poly *r, const poly *a, const poly *b) |
654 | 0 | { |
655 | 0 | unsigned int i; |
656 | 0 | for(i=0;i<KYBER_N/4;i++) { |
657 | 0 | basemul(&r->coeffs[4*i], &a->coeffs[4*i], &b->coeffs[4*i], zetas[64+i]); |
658 | 0 | basemul(&r->coeffs[4*i+2], &a->coeffs[4*i+2], &b->coeffs[4*i+2], -zetas[64+i]); |
659 | 0 | } |
660 | 0 | } |
661 | | |
662 | | /************************************************* |
663 | | * Name: poly_tomont |
664 | | * |
665 | | * Description: Inplace conversion of all coefficients of a polynomial |
666 | | * from normal domain to Montgomery domain |
667 | | * |
668 | | * Arguments: - poly *r: pointer to input/output polynomial |
669 | | **************************************************/ |
670 | | void poly_tomont(poly *r) |
671 | 0 | { |
672 | 0 | unsigned int i; |
673 | 0 | const int16_t f = (1ULL << 32) % KYBER_Q; |
674 | 0 | for(i=0;i<KYBER_N;i++) |
675 | 0 | r->coeffs[i] = montgomery_reduce((int32_t)r->coeffs[i]*f); |
676 | 0 | } |
677 | | |
678 | | /************************************************* |
679 | | * Name: poly_reduce |
680 | | * |
681 | | * Description: Applies Barrett reduction to all coefficients of a polynomial |
682 | | * for details of the Barrett reduction see comments in reduce.c |
683 | | * |
684 | | * Arguments: - poly *r: pointer to input/output polynomial |
685 | | **************************************************/ |
686 | | void poly_reduce(poly *r) |
687 | 0 | { |
688 | 0 | unsigned int i; |
689 | 0 | for(i=0;i<KYBER_N;i++) |
690 | 0 | r->coeffs[i] = barrett_reduce(r->coeffs[i]); |
691 | 0 | } |
692 | | |
693 | | /************************************************* |
694 | | * Name: poly_add |
695 | | * |
696 | | * Description: Add two polynomials; no modular reduction is performed |
697 | | * |
698 | | * Arguments: - poly *r: pointer to output polynomial |
699 | | * - const poly *a: pointer to first input polynomial |
700 | | * - const poly *b: pointer to second input polynomial |
701 | | **************************************************/ |
702 | | void poly_add(poly *r, const poly *a, const poly *b) |
703 | 0 | { |
704 | 0 | unsigned int i; |
705 | 0 | for(i=0;i<KYBER_N;i++) |
706 | 0 | r->coeffs[i] = a->coeffs[i] + b->coeffs[i]; |
707 | 0 | } |
708 | | |
709 | | /************************************************* |
710 | | * Name: poly_sub |
711 | | * |
712 | | * Description: Subtract two polynomials; no modular reduction is performed |
713 | | * |
714 | | * Arguments: - poly *r: pointer to output polynomial |
715 | | * - const poly *a: pointer to first input polynomial |
716 | | * - const poly *b: pointer to second input polynomial |
717 | | **************************************************/ |
718 | | void poly_sub(poly *r, const poly *a, const poly *b) |
719 | 0 | { |
720 | 0 | unsigned int i; |
721 | 0 | for(i=0;i<KYBER_N;i++) |
722 | 0 | r->coeffs[i] = a->coeffs[i] - b->coeffs[i]; |
723 | 0 | } |
724 | | |
725 | | /*************** kyber/ref/reduce.c */ |
726 | | |
727 | | /************************************************* |
728 | | * Name: montgomery_reduce |
729 | | * |
730 | | * Description: Montgomery reduction; given a 32-bit integer a, computes |
731 | | * 16-bit integer congruent to a * R^-1 mod q, where R=2^16 |
732 | | * |
733 | | * Arguments: - int32_t a: input integer to be reduced; |
734 | | * has to be in {-q2^15,...,q2^15-1} |
735 | | * |
736 | | * Returns: integer in {-q+1,...,q-1} congruent to a * R^-1 modulo q. |
737 | | **************************************************/ |
738 | | int16_t montgomery_reduce(int32_t a) |
739 | 0 | { |
740 | 0 | int16_t t; |
741 | |
|
742 | 0 | t = (int16_t)a*QINV; |
743 | 0 | t = (a - (int32_t)t*KYBER_Q) >> 16; |
744 | 0 | return t; |
745 | 0 | } |
746 | | |
747 | | /************************************************* |
748 | | * Name: barrett_reduce |
749 | | * |
750 | | * Description: Barrett reduction; given a 16-bit integer a, computes |
751 | | * centered representative congruent to a mod q in {-(q-1)/2,...,(q-1)/2} |
752 | | * |
753 | | * Arguments: - int16_t a: input integer to be reduced |
754 | | * |
755 | | * Returns: integer in {-(q-1)/2,...,(q-1)/2} congruent to a modulo q. |
756 | | **************************************************/ |
757 | 0 | int16_t barrett_reduce(int16_t a) { |
758 | 0 | int16_t t; |
759 | 0 | const int16_t v = ((1<<26) + KYBER_Q/2)/KYBER_Q; |
760 | |
|
761 | 0 | t = ((int32_t)v*a + (1<<25)) >> 26; |
762 | 0 | t *= KYBER_Q; |
763 | 0 | return a - t; |
764 | 0 | } |