/src/libssh/src/external/sntrup761.c
Line | Count | Source |
1 | | /* |
2 | | * Derived from public domain source, written by (in alphabetical order): |
3 | | * - Daniel J. Bernstein |
4 | | * - Chitchanok Chuengsatiansup |
5 | | * - Tanja Lange |
6 | | * - Christine van Vredendaal |
7 | | */ |
8 | | |
9 | | #include <string.h> |
10 | | #include <stdint.h> |
11 | | |
12 | | #define SNTRUP761_SECRETKEY_SIZE 1763 |
13 | | #define SNTRUP761_PUBLICKEY_SIZE 1158 |
14 | | #define SNTRUP761_CIPHERTEXT_SIZE 1039 |
15 | | #define SNTRUP761_SIZE 32 |
16 | | |
17 | | typedef void sntrup761_random_func (void *ctx, size_t length, uint8_t *dst); |
18 | | |
19 | | void |
20 | | sntrup761_keypair (uint8_t *pk, uint8_t *sk, |
21 | | void *random_ctx, sntrup761_random_func *random); |
22 | | |
23 | | void |
24 | | sntrup761_enc (uint8_t *c, uint8_t *k, const uint8_t *pk, |
25 | | void *random_ctx, sntrup761_random_func *random); |
26 | | |
27 | | void |
28 | | sntrup761_dec (uint8_t *k, const uint8_t *c, const uint8_t *sk); |
29 | | |
30 | | extern int sha512(const unsigned char *digest, size_t len, unsigned char *hash); |
31 | | |
32 | | #define MAX_LEN 761 |
33 | | |
34 | | /* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */ |
35 | 0 | #define int32_MINMAX(a,b) \ |
36 | 0 | do { \ |
37 | 0 | int64_t ab = (int64_t)b ^ (int64_t)a; \ |
38 | 0 | int64_t c = (int64_t)b - (int64_t)a; \ |
39 | 0 | c ^= ab & (c ^ b); \ |
40 | 0 | c >>= 31; \ |
41 | 0 | c &= ab; \ |
42 | 0 | a ^= c; \ |
43 | 0 | b ^= c; \ |
44 | 0 | } while(0) |
45 | | |
46 | | /* from supercop-20201130/crypto_sort/int32/portable4/sort.c */ |
47 | | static void |
48 | | crypto_sort_int32 (void *array, long long n) |
49 | 0 | { |
50 | 0 | long long top, p, q, r, i, j; |
51 | 0 | int32_t *x = array; |
52 | |
|
53 | 0 | if (n < 2) |
54 | 0 | return; |
55 | 0 | top = 1; |
56 | 0 | while (top < n - top) |
57 | 0 | top += top; |
58 | |
|
59 | 0 | for (p = top; p >= 1; p >>= 1) |
60 | 0 | { |
61 | 0 | i = 0; |
62 | 0 | while (i + 2 * p <= n) |
63 | 0 | { |
64 | 0 | for (j = i; j < i + p; ++j) |
65 | 0 | int32_MINMAX (x[j], x[j + p]); |
66 | 0 | i += 2 * p; |
67 | 0 | } |
68 | 0 | for (j = i; j < n - p; ++j) |
69 | 0 | int32_MINMAX (x[j], x[j + p]); |
70 | |
|
71 | 0 | i = 0; |
72 | 0 | j = 0; |
73 | 0 | for (q = top; q > p; q >>= 1) |
74 | 0 | { |
75 | 0 | if (j != i) |
76 | 0 | for (;;) |
77 | 0 | { |
78 | 0 | int32_t a; |
79 | 0 | if (j == n - q) |
80 | 0 | goto done; |
81 | 0 | a = x[j + p]; |
82 | 0 | for (r = q; r > p; r >>= 1) |
83 | 0 | int32_MINMAX (a, x[j + r]); |
84 | 0 | x[j + p] = a; |
85 | 0 | ++j; |
86 | 0 | if (j == i + p) |
87 | 0 | { |
88 | 0 | i += 2 * p; |
89 | 0 | break; |
90 | 0 | } |
91 | 0 | } |
92 | 0 | while (i + p <= n - q) |
93 | 0 | { |
94 | 0 | for (j = i; j < i + p; ++j) |
95 | 0 | { |
96 | 0 | int32_t a = x[j + p]; |
97 | 0 | for (r = q; r > p; r >>= 1) |
98 | 0 | int32_MINMAX (a, x[j + r]); |
99 | 0 | x[j + p] = a; |
100 | 0 | } |
101 | 0 | i += 2 * p; |
102 | 0 | } |
103 | | /* now i + p > n - q */ |
104 | 0 | j = i; |
105 | 0 | while (j < n - q) |
106 | 0 | { |
107 | 0 | int32_t a = x[j + p]; |
108 | 0 | for (r = q; r > p; r >>= 1) |
109 | 0 | int32_MINMAX (a, x[j + r]); |
110 | 0 | x[j + p] = a; |
111 | 0 | ++j; |
112 | 0 | } |
113 | |
|
114 | 0 | done:; |
115 | 0 | } |
116 | 0 | } |
117 | 0 | } |
118 | | |
119 | | /* from supercop-20201130/crypto_sort/uint32/useint32/sort.c */ |
120 | | |
121 | | /* can save time by vectorizing xor loops */ |
122 | | /* can save time by integrating xor loops with int32_sort */ |
123 | | |
124 | | static void |
125 | | crypto_sort_uint32 (void *array, long long n) |
126 | 0 | { |
127 | 0 | uint32_t *x = array; |
128 | 0 | long long j; |
129 | 0 | for (j = 0; j < n; ++j) |
130 | 0 | x[j] ^= 0x80000000; |
131 | 0 | crypto_sort_int32 (array, n); |
132 | 0 | for (j = 0; j < n; ++j) |
133 | 0 | x[j] ^= 0x80000000; |
134 | 0 | } |
135 | | |
136 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/uint32.c */ |
137 | | |
138 | | /* |
139 | | CPU division instruction typically takes time depending on x. |
140 | | This software is designed to take time independent of x. |
141 | | Time still varies depending on m; user must ensure that m is constant. |
142 | | Time also varies on CPUs where multiplication is variable-time. |
143 | | There could be more CPU issues. |
144 | | There could also be compiler issues. |
145 | | */ |
146 | | |
147 | | static void |
148 | | uint32_divmod_uint14 (uint32_t * q, uint16_t * r, uint32_t x, uint16_t m) |
149 | 0 | { |
150 | 0 | uint32_t v = 0x80000000; |
151 | 0 | uint32_t qpart; |
152 | 0 | uint32_t mask; |
153 | |
|
154 | 0 | v /= m; |
155 | | |
156 | | /* caller guarantees m > 0 */ |
157 | | /* caller guarantees m < 16384 */ |
158 | | /* vm <= 2^31 <= vm+m-1 */ |
159 | | /* xvm <= 2^31 x <= xvm+x(m-1) */ |
160 | |
|
161 | 0 | *q = 0; |
162 | |
|
163 | 0 | qpart = (x * (uint64_t) v) >> 31; |
164 | | /* 2^31 qpart <= xv <= 2^31 qpart + 2^31-1 */ |
165 | | /* 2^31 qpart m <= xvm <= 2^31 qpart m + (2^31-1)m */ |
166 | | /* 2^31 qpart m <= 2^31 x <= 2^31 qpart m + (2^31-1)m + x(m-1) */ |
167 | | /* 0 <= 2^31 newx <= (2^31-1)m + x(m-1) */ |
168 | | /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */ |
169 | | /* 0 <= newx <= (1-1/2^31)(2^14-1) + (2^32-1)((2^14-1)-1)/2^31 */ |
170 | |
|
171 | 0 | x -= qpart * m; |
172 | 0 | *q += qpart; |
173 | | /* x <= 49146 */ |
174 | |
|
175 | 0 | qpart = (x * (uint64_t) v) >> 31; |
176 | | /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */ |
177 | | /* 0 <= newx <= m + 49146(2^14-1)/2^31 */ |
178 | | /* 0 <= newx <= m + 0.4 */ |
179 | | /* 0 <= newx <= m */ |
180 | |
|
181 | 0 | x -= qpart * m; |
182 | 0 | *q += qpart; |
183 | | /* x <= m */ |
184 | |
|
185 | 0 | x -= m; |
186 | 0 | *q += 1; |
187 | 0 | mask = -(x >> 31); |
188 | 0 | x += mask & (uint32_t) m; |
189 | 0 | *q += mask; |
190 | | /* x < m */ |
191 | |
|
192 | 0 | *r = x; |
193 | 0 | } |
194 | | |
195 | | |
196 | | static uint16_t |
197 | | uint32_mod_uint14 (uint32_t x, uint16_t m) |
198 | 0 | { |
199 | 0 | uint32_t q; |
200 | 0 | uint16_t r; |
201 | 0 | uint32_divmod_uint14 (&q, &r, x, m); |
202 | 0 | return r; |
203 | 0 | } |
204 | | |
205 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/int32.c */ |
206 | | |
207 | | static void |
208 | | int32_divmod_uint14 (int32_t * q, uint16_t * r, int32_t x, uint16_t m) |
209 | 0 | { |
210 | 0 | uint32_t uq, uq2; |
211 | 0 | uint16_t ur, ur2; |
212 | 0 | uint32_t mask; |
213 | |
|
214 | 0 | uint32_divmod_uint14 (&uq, &ur, 0x80000000 + (uint32_t) x, m); |
215 | 0 | uint32_divmod_uint14 (&uq2, &ur2, 0x80000000, m); |
216 | 0 | ur -= ur2; |
217 | 0 | uq -= uq2; |
218 | 0 | mask = -(uint32_t) (ur >> 15); |
219 | 0 | ur += mask & m; |
220 | 0 | uq += mask; |
221 | 0 | *r = ur; |
222 | 0 | *q = uq; |
223 | 0 | } |
224 | | |
225 | | |
226 | | static uint16_t |
227 | | int32_mod_uint14 (int32_t x, uint16_t m) |
228 | 0 | { |
229 | 0 | int32_t q; |
230 | 0 | uint16_t r; |
231 | 0 | int32_divmod_uint14 (&q, &r, x, m); |
232 | 0 | return r; |
233 | 0 | } |
234 | | |
235 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h */ |
236 | 0 | #define p 761 |
237 | 0 | #define q 4591 |
238 | 0 | #define Rounded_bytes 1007 |
239 | 0 | #define Rq_bytes 1158 |
240 | 0 | #define w 286 |
241 | | |
242 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.h */ |
243 | | |
244 | | /* Decode(R,s,M,len) */ |
245 | | /* assumes 0 < M[i] < 16384 */ |
246 | | /* produces 0 <= R[i] < M[i] */ |
247 | | |
248 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.c */ |
249 | | |
250 | | static void |
251 | | Decode (uint16_t * out, const unsigned char *S, const uint16_t * M, |
252 | | long long len) |
253 | 0 | { |
254 | 0 | if (len == 1) |
255 | 0 | { |
256 | 0 | if (M[0] == 1) |
257 | 0 | *out = 0; |
258 | 0 | else if (M[0] <= 256) |
259 | 0 | *out = uint32_mod_uint14 (S[0], M[0]); |
260 | 0 | else |
261 | 0 | *out = uint32_mod_uint14 (S[0] + (((uint16_t) S[1]) << 8), M[0]); |
262 | 0 | } |
263 | 0 | if (len > 1) |
264 | 0 | { |
265 | 0 | uint16_t R2[(MAX_LEN + 1) / 2]; |
266 | 0 | uint16_t M2[(MAX_LEN + 1) / 2]; |
267 | 0 | uint16_t bottomr[MAX_LEN / 2]; |
268 | 0 | uint32_t bottomt[MAX_LEN / 2]; |
269 | 0 | long long i; |
270 | 0 | for (i = 0; i < len - 1; i += 2) |
271 | 0 | { |
272 | 0 | uint32_t m = M[i] * (uint32_t) M[i + 1]; |
273 | 0 | if (m > 256 * 16383) |
274 | 0 | { |
275 | 0 | bottomt[i / 2] = 256 * 256; |
276 | 0 | bottomr[i / 2] = S[0] + 256 * S[1]; |
277 | 0 | S += 2; |
278 | 0 | M2[i / 2] = (((m + 255) >> 8) + 255) >> 8; |
279 | 0 | } |
280 | 0 | else if (m >= 16384) |
281 | 0 | { |
282 | 0 | bottomt[i / 2] = 256; |
283 | 0 | bottomr[i / 2] = S[0]; |
284 | 0 | S += 1; |
285 | 0 | M2[i / 2] = (m + 255) >> 8; |
286 | 0 | } |
287 | 0 | else |
288 | 0 | { |
289 | 0 | bottomt[i / 2] = 1; |
290 | 0 | bottomr[i / 2] = 0; |
291 | 0 | M2[i / 2] = m; |
292 | 0 | } |
293 | 0 | } |
294 | 0 | if (i < len) |
295 | 0 | M2[i / 2] = M[i]; |
296 | 0 | Decode (R2, S, M2, (len + 1) / 2); |
297 | 0 | for (i = 0; i < len - 1; i += 2) |
298 | 0 | { |
299 | 0 | uint32_t r = bottomr[i / 2]; |
300 | 0 | uint32_t r1; |
301 | 0 | uint16_t r0; |
302 | 0 | r += bottomt[i / 2] * R2[i / 2]; |
303 | 0 | uint32_divmod_uint14 (&r1, &r0, r, M[i]); |
304 | 0 | r1 = uint32_mod_uint14 (r1, M[i + 1]); /* only needed for invalid inputs */ |
305 | 0 | *out++ = r0; |
306 | 0 | *out++ = r1; |
307 | 0 | } |
308 | 0 | if (i < len) |
309 | 0 | *out++ = R2[i / 2]; |
310 | 0 | } |
311 | 0 | } |
312 | | |
313 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.h */ |
314 | | |
315 | | /* Encode(s,R,M,len) */ |
316 | | /* assumes 0 <= R[i] < M[i] < 16384 */ |
317 | | |
318 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.c */ |
319 | | |
320 | | /* 0 <= R[i] < M[i] < 16384 */ |
321 | | static void |
322 | | Encode (unsigned char *out, const uint16_t * R, const uint16_t * M, |
323 | | long long len) |
324 | 0 | { |
325 | 0 | if (len == 1) |
326 | 0 | { |
327 | 0 | uint16_t r = R[0]; |
328 | 0 | uint16_t m = M[0]; |
329 | 0 | while (m > 1) |
330 | 0 | { |
331 | 0 | *out++ = r; |
332 | 0 | r >>= 8; |
333 | 0 | m = (m + 255) >> 8; |
334 | 0 | } |
335 | 0 | } |
336 | 0 | if (len > 1) |
337 | 0 | { |
338 | 0 | uint16_t R2[(MAX_LEN + 1) / 2]; |
339 | 0 | uint16_t M2[(MAX_LEN + 1) / 2]; |
340 | 0 | long long i; |
341 | 0 | for (i = 0; i < len - 1; i += 2) |
342 | 0 | { |
343 | 0 | uint32_t m0 = M[i]; |
344 | 0 | uint32_t r = R[i] + R[i + 1] * m0; |
345 | 0 | uint32_t m = M[i + 1] * m0; |
346 | 0 | while (m >= 16384) |
347 | 0 | { |
348 | 0 | *out++ = r; |
349 | 0 | r >>= 8; |
350 | 0 | m = (m + 255) >> 8; |
351 | 0 | } |
352 | 0 | R2[i / 2] = r; |
353 | 0 | M2[i / 2] = m; |
354 | 0 | } |
355 | 0 | if (i < len) |
356 | 0 | { |
357 | 0 | R2[i / 2] = R[i]; |
358 | 0 | M2[i / 2] = M[i]; |
359 | 0 | } |
360 | 0 | Encode (out, R2, M2, (len + 1) / 2); |
361 | 0 | } |
362 | 0 | } |
363 | | |
364 | | /* from supercop-20201130/crypto_kem/sntrup761/ref/kem.c */ |
365 | | |
366 | | /* ----- masks */ |
367 | | |
368 | | /* return -1 if x!=0; else return 0 */ |
369 | | static int |
370 | | int16_t_nonzero_mask (int16_t x) |
371 | 0 | { |
372 | 0 | uint16_t u = x; /* 0, else 1...65535 */ |
373 | 0 | uint32_t v = u; /* 0, else 1...65535 */ |
374 | 0 | v = -v; /* 0, else 2^32-65535...2^32-1 */ |
375 | 0 | v >>= 31; /* 0, else 1 */ |
376 | 0 | return -v; /* 0, else -1 */ |
377 | 0 | } |
378 | | |
379 | | /* return -1 if x<0; otherwise return 0 */ |
380 | | static int |
381 | | int16_t_negative_mask (int16_t x) |
382 | 0 | { |
383 | 0 | uint16_t u = x; |
384 | 0 | u >>= 15; |
385 | 0 | return -(int) u; |
386 | | /* alternative with gcc -fwrapv: */ |
387 | | /* x>>15 compiles to CPU's arithmetic right shift */ |
388 | 0 | } |
389 | | |
390 | | /* ----- arithmetic mod 3 */ |
391 | | |
392 | | typedef int8_t small; |
393 | | |
394 | | /* F3 is always represented as -1,0,1 */ |
395 | | /* so ZZ_fromF3 is a no-op */ |
396 | | |
397 | | /* x must not be close to top int16_t */ |
398 | | static small |
399 | | F3_freeze (int16_t x) |
400 | 0 | { |
401 | 0 | return int32_mod_uint14 (x + 1, 3) - 1; |
402 | 0 | } |
403 | | |
404 | | /* ----- arithmetic mod q */ |
405 | | |
406 | 0 | #define q12 ((q-1)/2) |
407 | | typedef int16_t Fq; |
408 | | /* always represented as -q12...q12 */ |
409 | | /* so ZZ_fromFq is a no-op */ |
410 | | |
411 | | /* x must not be close to top int32 */ |
412 | | static Fq |
413 | | Fq_freeze (int32_t x) |
414 | 0 | { |
415 | 0 | return int32_mod_uint14 (x + q12, q) - q12; |
416 | 0 | } |
417 | | |
418 | | static Fq |
419 | | Fq_recip (Fq a1) |
420 | 0 | { |
421 | 0 | int i = 1; |
422 | 0 | Fq ai = a1; |
423 | |
|
424 | 0 | while (i < q - 2) |
425 | 0 | { |
426 | 0 | ai = Fq_freeze (a1 * (int32_t) ai); |
427 | 0 | i += 1; |
428 | 0 | } |
429 | 0 | return ai; |
430 | 0 | } |
431 | | |
432 | | /* ----- small polynomials */ |
433 | | |
434 | | /* 0 if Weightw_is(r), else -1 */ |
435 | | static int |
436 | | Weightw_mask (small * r) |
437 | 0 | { |
438 | 0 | int weight = 0; |
439 | 0 | int i; |
440 | |
|
441 | 0 | for (i = 0; i < p; ++i) |
442 | 0 | weight += r[i] & 1; |
443 | 0 | return int16_t_nonzero_mask (weight - w); |
444 | 0 | } |
445 | | |
446 | | /* R3_fromR(R_fromRq(r)) */ |
447 | | static void |
448 | | R3_fromRq (small * out, const Fq * r) |
449 | 0 | { |
450 | 0 | int i; |
451 | 0 | for (i = 0; i < p; ++i) |
452 | 0 | out[i] = F3_freeze (r[i]); |
453 | 0 | } |
454 | | |
455 | | /* h = f*g in the ring R3 */ |
456 | | static void |
457 | | R3_mult (small * h, const small * f, const small * g) |
458 | 0 | { |
459 | 0 | small fg[p + p - 1]; |
460 | 0 | small result; |
461 | 0 | int i, j; |
462 | |
|
463 | 0 | for (i = 0; i < p; ++i) |
464 | 0 | { |
465 | 0 | result = 0; |
466 | 0 | for (j = 0; j <= i; ++j) |
467 | 0 | result = F3_freeze (result + f[j] * g[i - j]); |
468 | 0 | fg[i] = result; |
469 | 0 | } |
470 | 0 | for (i = p; i < p + p - 1; ++i) |
471 | 0 | { |
472 | 0 | result = 0; |
473 | 0 | for (j = i - p + 1; j < p; ++j) |
474 | 0 | result = F3_freeze (result + f[j] * g[i - j]); |
475 | 0 | fg[i] = result; |
476 | 0 | } |
477 | |
|
478 | 0 | for (i = p + p - 2; i >= p; --i) |
479 | 0 | { |
480 | 0 | fg[i - p] = F3_freeze (fg[i - p] + fg[i]); |
481 | 0 | fg[i - p + 1] = F3_freeze (fg[i - p + 1] + fg[i]); |
482 | 0 | } |
483 | |
|
484 | 0 | for (i = 0; i < p; ++i) |
485 | 0 | h[i] = fg[i]; |
486 | 0 | } |
487 | | |
488 | | /* returns 0 if recip succeeded; else -1 */ |
489 | | static int |
490 | | R3_recip (small * out, const small * in) |
491 | 0 | { |
492 | 0 | small f[p + 1], g[p + 1], v[p + 1], r[p + 1]; |
493 | 0 | int i, loop, delta; |
494 | 0 | int sign, swap, t; |
495 | |
|
496 | 0 | for (i = 0; i < p + 1; ++i) |
497 | 0 | v[i] = 0; |
498 | 0 | for (i = 0; i < p + 1; ++i) |
499 | 0 | r[i] = 0; |
500 | 0 | r[0] = 1; |
501 | 0 | for (i = 0; i < p; ++i) |
502 | 0 | f[i] = 0; |
503 | 0 | f[0] = 1; |
504 | 0 | f[p - 1] = f[p] = -1; |
505 | 0 | for (i = 0; i < p; ++i) |
506 | 0 | g[p - 1 - i] = in[i]; |
507 | 0 | g[p] = 0; |
508 | |
|
509 | 0 | delta = 1; |
510 | |
|
511 | 0 | for (loop = 0; loop < 2 * p - 1; ++loop) |
512 | 0 | { |
513 | 0 | for (i = p; i > 0; --i) |
514 | 0 | v[i] = v[i - 1]; |
515 | 0 | v[0] = 0; |
516 | |
|
517 | 0 | sign = -g[0] * f[0]; |
518 | 0 | swap = int16_t_negative_mask (-delta) & int16_t_nonzero_mask (g[0]); |
519 | 0 | delta ^= swap & (delta ^ -delta); |
520 | 0 | delta += 1; |
521 | |
|
522 | 0 | for (i = 0; i < p + 1; ++i) |
523 | 0 | { |
524 | 0 | t = swap & (f[i] ^ g[i]); |
525 | 0 | f[i] ^= t; |
526 | 0 | g[i] ^= t; |
527 | 0 | t = swap & (v[i] ^ r[i]); |
528 | 0 | v[i] ^= t; |
529 | 0 | r[i] ^= t; |
530 | 0 | } |
531 | |
|
532 | 0 | for (i = 0; i < p + 1; ++i) |
533 | 0 | g[i] = F3_freeze (g[i] + sign * f[i]); |
534 | 0 | for (i = 0; i < p + 1; ++i) |
535 | 0 | r[i] = F3_freeze (r[i] + sign * v[i]); |
536 | |
|
537 | 0 | for (i = 0; i < p; ++i) |
538 | 0 | g[i] = g[i + 1]; |
539 | 0 | g[p] = 0; |
540 | 0 | } |
541 | |
|
542 | 0 | sign = f[0]; |
543 | 0 | for (i = 0; i < p; ++i) |
544 | 0 | out[i] = sign * v[p - 1 - i]; |
545 | |
|
546 | 0 | return int16_t_nonzero_mask (delta); |
547 | 0 | } |
548 | | |
549 | | /* ----- polynomials mod q */ |
550 | | |
551 | | /* h = f*g in the ring Rq */ |
552 | | static void |
553 | | Rq_mult_small (Fq * h, const Fq * f, const small * g) |
554 | 0 | { |
555 | 0 | Fq fg[p + p - 1]; |
556 | 0 | Fq result; |
557 | 0 | int i, j; |
558 | |
|
559 | 0 | for (i = 0; i < p; ++i) |
560 | 0 | { |
561 | 0 | result = 0; |
562 | 0 | for (j = 0; j <= i; ++j) |
563 | 0 | result = Fq_freeze (result + f[j] * (int32_t) g[i - j]); |
564 | 0 | fg[i] = result; |
565 | 0 | } |
566 | 0 | for (i = p; i < p + p - 1; ++i) |
567 | 0 | { |
568 | 0 | result = 0; |
569 | 0 | for (j = i - p + 1; j < p; ++j) |
570 | 0 | result = Fq_freeze (result + f[j] * (int32_t) g[i - j]); |
571 | 0 | fg[i] = result; |
572 | 0 | } |
573 | |
|
574 | 0 | for (i = p + p - 2; i >= p; --i) |
575 | 0 | { |
576 | 0 | fg[i - p] = Fq_freeze (fg[i - p] + fg[i]); |
577 | 0 | fg[i - p + 1] = Fq_freeze (fg[i - p + 1] + fg[i]); |
578 | 0 | } |
579 | |
|
580 | 0 | for (i = 0; i < p; ++i) |
581 | 0 | h[i] = fg[i]; |
582 | 0 | } |
583 | | |
584 | | /* h = 3f in Rq */ |
585 | | static void |
586 | | Rq_mult3 (Fq * h, const Fq * f) |
587 | 0 | { |
588 | 0 | int i; |
589 | |
|
590 | 0 | for (i = 0; i < p; ++i) |
591 | 0 | h[i] = Fq_freeze (3 * f[i]); |
592 | 0 | } |
593 | | |
594 | | /* out = 1/(3*in) in Rq */ |
595 | | /* returns 0 if recip succeeded; else -1 */ |
596 | | static int |
597 | | Rq_recip3 (Fq * out, const small * in) |
598 | 0 | { |
599 | 0 | Fq f[p + 1], g[p + 1], v[p + 1], r[p + 1]; |
600 | 0 | int i, loop, delta; |
601 | 0 | int swap, t; |
602 | 0 | int32_t f0, g0; |
603 | 0 | Fq scale; |
604 | |
|
605 | 0 | for (i = 0; i < p + 1; ++i) |
606 | 0 | v[i] = 0; |
607 | 0 | for (i = 0; i < p + 1; ++i) |
608 | 0 | r[i] = 0; |
609 | 0 | r[0] = Fq_recip (3); |
610 | 0 | for (i = 0; i < p; ++i) |
611 | 0 | f[i] = 0; |
612 | 0 | f[0] = 1; |
613 | 0 | f[p - 1] = f[p] = -1; |
614 | 0 | for (i = 0; i < p; ++i) |
615 | 0 | g[p - 1 - i] = in[i]; |
616 | 0 | g[p] = 0; |
617 | |
|
618 | 0 | delta = 1; |
619 | |
|
620 | 0 | for (loop = 0; loop < 2 * p - 1; ++loop) |
621 | 0 | { |
622 | 0 | for (i = p; i > 0; --i) |
623 | 0 | v[i] = v[i - 1]; |
624 | 0 | v[0] = 0; |
625 | |
|
626 | 0 | swap = int16_t_negative_mask (-delta) & int16_t_nonzero_mask (g[0]); |
627 | 0 | delta ^= swap & (delta ^ -delta); |
628 | 0 | delta += 1; |
629 | |
|
630 | 0 | for (i = 0; i < p + 1; ++i) |
631 | 0 | { |
632 | 0 | t = swap & (f[i] ^ g[i]); |
633 | 0 | f[i] ^= t; |
634 | 0 | g[i] ^= t; |
635 | 0 | t = swap & (v[i] ^ r[i]); |
636 | 0 | v[i] ^= t; |
637 | 0 | r[i] ^= t; |
638 | 0 | } |
639 | |
|
640 | 0 | f0 = f[0]; |
641 | 0 | g0 = g[0]; |
642 | 0 | for (i = 0; i < p + 1; ++i) |
643 | 0 | g[i] = Fq_freeze (f0 * g[i] - g0 * f[i]); |
644 | 0 | for (i = 0; i < p + 1; ++i) |
645 | 0 | r[i] = Fq_freeze (f0 * r[i] - g0 * v[i]); |
646 | |
|
647 | 0 | for (i = 0; i < p; ++i) |
648 | 0 | g[i] = g[i + 1]; |
649 | 0 | g[p] = 0; |
650 | 0 | } |
651 | |
|
652 | 0 | scale = Fq_recip (f[0]); |
653 | 0 | for (i = 0; i < p; ++i) |
654 | 0 | out[i] = Fq_freeze (scale * (int32_t) v[p - 1 - i]); |
655 | |
|
656 | 0 | return int16_t_nonzero_mask (delta); |
657 | 0 | } |
658 | | |
659 | | /* ----- rounded polynomials mod q */ |
660 | | |
661 | | static void |
662 | | Round (Fq * out, const Fq * a) |
663 | 0 | { |
664 | 0 | int i; |
665 | 0 | for (i = 0; i < p; ++i) |
666 | 0 | out[i] = a[i] - F3_freeze (a[i]); |
667 | 0 | } |
668 | | |
669 | | /* ----- sorting to generate short polynomial */ |
670 | | |
671 | | static void |
672 | | Short_fromlist (small * out, const uint32_t * in) |
673 | 0 | { |
674 | 0 | uint32_t L[p]; |
675 | 0 | int i; |
676 | |
|
677 | 0 | for (i = 0; i < w; ++i) |
678 | 0 | L[i] = in[i] & (uint32_t) - 2; |
679 | 0 | for (i = w; i < p; ++i) |
680 | 0 | L[i] = (in[i] & (uint32_t) - 3) | 1; |
681 | 0 | crypto_sort_uint32 (L, p); |
682 | 0 | for (i = 0; i < p; ++i) |
683 | 0 | out[i] = (L[i] & 3) - 1; |
684 | 0 | } |
685 | | |
686 | | /* ----- underlying hash function */ |
687 | | |
688 | 0 | #define Hash_bytes 32 |
689 | | |
690 | | /* e.g., b = 0 means out = Hash0(in) */ |
691 | | static void |
692 | | Hash_prefix (unsigned char *out, int b, const unsigned char *in, int inlen) |
693 | 0 | { |
694 | 0 | #define MAX_X_LEN 1158 |
695 | 0 | unsigned char x[MAX_X_LEN + 1]; |
696 | 0 | unsigned char h[64]; |
697 | 0 | int i; |
698 | |
|
699 | 0 | x[0] = b; |
700 | 0 | for (i = 0; i < inlen; ++i) |
701 | 0 | x[i + 1] = in[i]; |
702 | 0 | sha512 (x, inlen + 1, h); |
703 | 0 | for (i = 0; i < 32; ++i) |
704 | 0 | out[i] = h[i]; |
705 | 0 | } |
706 | | |
707 | | /* ----- higher-level randomness */ |
708 | | |
709 | | static uint32_t |
710 | | urandom32 (void *random_ctx, sntrup761_random_func * random) |
711 | 0 | { |
712 | 0 | unsigned char c[4]; |
713 | 0 | uint32_t out[4]; |
714 | |
|
715 | 0 | random (random_ctx, 4, c); |
716 | 0 | out[0] = (uint32_t) c[0]; |
717 | 0 | out[1] = ((uint32_t) c[1]) << 8; |
718 | 0 | out[2] = ((uint32_t) c[2]) << 16; |
719 | 0 | out[3] = ((uint32_t) c[3]) << 24; |
720 | 0 | return out[0] + out[1] + out[2] + out[3]; |
721 | 0 | } |
722 | | |
723 | | static void |
724 | | Short_random (small * out, void *random_ctx, sntrup761_random_func * random) |
725 | 0 | { |
726 | 0 | uint32_t L[p]; |
727 | 0 | int i; |
728 | |
|
729 | 0 | for (i = 0; i < p; ++i) |
730 | 0 | L[i] = urandom32 (random_ctx, random); |
731 | 0 | Short_fromlist (out, L); |
732 | 0 | } |
733 | | |
734 | | static void |
735 | | Small_random (small * out, void *random_ctx, sntrup761_random_func * random) |
736 | 0 | { |
737 | 0 | int i; |
738 | |
|
739 | 0 | for (i = 0; i < p; ++i) |
740 | 0 | out[i] = (((urandom32 (random_ctx, random) & 0x3fffffff) * 3) >> 30) - 1; |
741 | 0 | } |
742 | | |
743 | | /* ----- Streamlined NTRU Prime Core */ |
744 | | |
745 | | /* h,(f,ginv) = KeyGen() */ |
746 | | static void |
747 | | KeyGen (Fq * h, small * f, small * ginv, void *random_ctx, |
748 | | sntrup761_random_func * random) |
749 | 0 | { |
750 | 0 | small g[p]; |
751 | 0 | Fq finv[p]; |
752 | |
|
753 | 0 | for (;;) |
754 | 0 | { |
755 | 0 | Small_random (g, random_ctx, random); |
756 | 0 | if (R3_recip (ginv, g) == 0) |
757 | 0 | break; |
758 | 0 | } |
759 | 0 | Short_random (f, random_ctx, random); |
760 | 0 | Rq_recip3 (finv, f); /* always works */ |
761 | 0 | Rq_mult_small (h, finv, g); |
762 | 0 | } |
763 | | |
764 | | /* c = Encrypt(r,h) */ |
765 | | static void |
766 | | Encrypt (Fq * c, const small * r, const Fq * h) |
767 | 0 | { |
768 | 0 | Fq hr[p]; |
769 | |
|
770 | 0 | Rq_mult_small (hr, h, r); |
771 | 0 | Round (c, hr); |
772 | 0 | } |
773 | | |
774 | | /* r = Decrypt(c,(f,ginv)) */ |
775 | | static void |
776 | | Decrypt (small * r, const Fq * c, const small * f, const small * ginv) |
777 | 0 | { |
778 | 0 | Fq cf[p]; |
779 | 0 | Fq cf3[p]; |
780 | 0 | small e[p]; |
781 | 0 | small ev[p]; |
782 | 0 | int mask; |
783 | 0 | int i; |
784 | |
|
785 | 0 | Rq_mult_small (cf, c, f); |
786 | 0 | Rq_mult3 (cf3, cf); |
787 | 0 | R3_fromRq (e, cf3); |
788 | 0 | R3_mult (ev, e, ginv); |
789 | |
|
790 | 0 | mask = Weightw_mask (ev); /* 0 if weight w, else -1 */ |
791 | 0 | for (i = 0; i < w; ++i) |
792 | 0 | r[i] = ((ev[i] ^ 1) & ~mask) ^ 1; |
793 | 0 | for (i = w; i < p; ++i) |
794 | 0 | r[i] = ev[i] & ~mask; |
795 | 0 | } |
796 | | |
797 | | /* ----- encoding small polynomials (including short polynomials) */ |
798 | | |
799 | 0 | #define Small_bytes ((p+3)/4) |
800 | | |
801 | | /* these are the only functions that rely on p mod 4 = 1 */ |
802 | | |
803 | | static void |
804 | | Small_encode (unsigned char *s, const small * f) |
805 | 0 | { |
806 | 0 | small x; |
807 | 0 | int i; |
808 | |
|
809 | 0 | for (i = 0; i < p / 4; ++i) |
810 | 0 | { |
811 | 0 | x = *f++ + 1; |
812 | 0 | x += (*f++ + 1) << 2; |
813 | 0 | x += (*f++ + 1) << 4; |
814 | 0 | x += (*f++ + 1) << 6; |
815 | 0 | *s++ = x; |
816 | 0 | } |
817 | 0 | x = *f++ + 1; |
818 | 0 | *s++ = x; |
819 | 0 | } |
820 | | |
821 | | static void |
822 | | Small_decode (small * f, const unsigned char *s) |
823 | 0 | { |
824 | 0 | unsigned char x; |
825 | 0 | int i; |
826 | |
|
827 | 0 | for (i = 0; i < p / 4; ++i) |
828 | 0 | { |
829 | 0 | x = *s++; |
830 | 0 | *f++ = ((small) (x & 3)) - 1; |
831 | 0 | x >>= 2; |
832 | 0 | *f++ = ((small) (x & 3)) - 1; |
833 | 0 | x >>= 2; |
834 | 0 | *f++ = ((small) (x & 3)) - 1; |
835 | 0 | x >>= 2; |
836 | 0 | *f++ = ((small) (x & 3)) - 1; |
837 | 0 | } |
838 | 0 | x = *s++; |
839 | 0 | *f++ = ((small) (x & 3)) - 1; |
840 | 0 | } |
841 | | |
842 | | /* ----- encoding general polynomials */ |
843 | | |
844 | | static void |
845 | | Rq_encode (unsigned char *s, const Fq * r) |
846 | 0 | { |
847 | 0 | uint16_t R[p], M[p]; |
848 | 0 | int i; |
849 | |
|
850 | 0 | for (i = 0; i < p; ++i) |
851 | 0 | R[i] = r[i] + q12; |
852 | 0 | for (i = 0; i < p; ++i) |
853 | 0 | M[i] = q; |
854 | 0 | Encode (s, R, M, p); |
855 | 0 | } |
856 | | |
857 | | static void |
858 | | Rq_decode (Fq * r, const unsigned char *s) |
859 | 0 | { |
860 | 0 | uint16_t R[p], M[p]; |
861 | 0 | int i; |
862 | |
|
863 | 0 | for (i = 0; i < p; ++i) |
864 | 0 | M[i] = q; |
865 | 0 | Decode (R, s, M, p); |
866 | 0 | for (i = 0; i < p; ++i) |
867 | 0 | r[i] = ((Fq) R[i]) - q12; |
868 | 0 | } |
869 | | |
870 | | /* ----- encoding rounded polynomials */ |
871 | | |
872 | | static void |
873 | | Rounded_encode (unsigned char *s, const Fq * r) |
874 | 0 | { |
875 | 0 | uint16_t R[p], M[p]; |
876 | 0 | int i; |
877 | |
|
878 | 0 | for (i = 0; i < p; ++i) |
879 | 0 | R[i] = ((r[i] + q12) * 10923) >> 15; |
880 | 0 | for (i = 0; i < p; ++i) |
881 | 0 | M[i] = (q + 2) / 3; |
882 | 0 | Encode (s, R, M, p); |
883 | 0 | } |
884 | | |
885 | | static void |
886 | | Rounded_decode (Fq * r, const unsigned char *s) |
887 | 0 | { |
888 | 0 | uint16_t R[p], M[p]; |
889 | 0 | int i; |
890 | |
|
891 | 0 | for (i = 0; i < p; ++i) |
892 | 0 | M[i] = (q + 2) / 3; |
893 | 0 | Decode (R, s, M, p); |
894 | 0 | for (i = 0; i < p; ++i) |
895 | 0 | r[i] = R[i] * 3 - q12; |
896 | 0 | } |
897 | | |
898 | | /* ----- Streamlined NTRU Prime Core plus encoding */ |
899 | | |
900 | | typedef small Inputs[p]; /* passed by reference */ |
901 | 0 | #define Inputs_random Short_random |
902 | 0 | #define Inputs_encode Small_encode |
903 | 0 | #define Inputs_bytes Small_bytes |
904 | | |
905 | 0 | #define Ciphertexts_bytes Rounded_bytes |
906 | 0 | #define SecretKeys_bytes (2*Small_bytes) |
907 | 0 | #define PublicKeys_bytes Rq_bytes |
908 | | |
909 | | /* pk,sk = ZKeyGen() */ |
910 | | static void |
911 | | ZKeyGen (unsigned char *pk, unsigned char *sk, void *random_ctx, |
912 | | sntrup761_random_func * random) |
913 | 0 | { |
914 | 0 | Fq h[p]; |
915 | 0 | small f[p], v[p]; |
916 | |
|
917 | 0 | KeyGen (h, f, v, random_ctx, random); |
918 | 0 | Rq_encode (pk, h); |
919 | 0 | Small_encode (sk, f); |
920 | 0 | sk += Small_bytes; |
921 | 0 | Small_encode (sk, v); |
922 | 0 | } |
923 | | |
924 | | /* C = ZEncrypt(r,pk) */ |
925 | | static void |
926 | | ZEncrypt (unsigned char *C, const Inputs r, const unsigned char *pk) |
927 | 0 | { |
928 | 0 | Fq h[p]; |
929 | 0 | Fq c[p]; |
930 | 0 | Rq_decode (h, pk); |
931 | 0 | Encrypt (c, r, h); |
932 | 0 | Rounded_encode (C, c); |
933 | 0 | } |
934 | | |
935 | | /* r = ZDecrypt(C,sk) */ |
936 | | static void |
937 | | ZDecrypt (Inputs r, const unsigned char *C, const unsigned char *sk) |
938 | 0 | { |
939 | 0 | small f[p], v[p]; |
940 | 0 | Fq c[p]; |
941 | |
|
942 | 0 | Small_decode (f, sk); |
943 | 0 | sk += Small_bytes; |
944 | 0 | Small_decode (v, sk); |
945 | 0 | Rounded_decode (c, C); |
946 | 0 | Decrypt (r, c, f, v); |
947 | 0 | } |
948 | | |
949 | | /* ----- confirmation hash */ |
950 | | |
951 | 0 | #define Confirm_bytes 32 |
952 | | |
953 | | /* h = HashConfirm(r,pk,cache); cache is Hash4(pk) */ |
954 | | static void |
955 | | HashConfirm (unsigned char *h, const unsigned char *r, |
956 | | /* const unsigned char *pk, */ const unsigned char *cache) |
957 | 0 | { |
958 | 0 | unsigned char x[Hash_bytes * 2]; |
959 | 0 | int i; |
960 | |
|
961 | 0 | Hash_prefix (x, 3, r, Inputs_bytes); |
962 | 0 | for (i = 0; i < Hash_bytes; ++i) |
963 | 0 | x[Hash_bytes + i] = cache[i]; |
964 | 0 | Hash_prefix (h, 2, x, sizeof x); |
965 | 0 | } |
966 | | |
967 | | /* ----- session-key hash */ |
968 | | |
969 | | /* k = HashSession(b,y,z) */ |
970 | | static void |
971 | | HashSession (unsigned char *k, int b, const unsigned char *y, |
972 | | const unsigned char *z) |
973 | 0 | { |
974 | 0 | unsigned char x[Hash_bytes + Ciphertexts_bytes + Confirm_bytes]; |
975 | 0 | int i; |
976 | |
|
977 | 0 | Hash_prefix (x, 3, y, Inputs_bytes); |
978 | 0 | for (i = 0; i < Ciphertexts_bytes + Confirm_bytes; ++i) |
979 | 0 | x[Hash_bytes + i] = z[i]; |
980 | 0 | Hash_prefix (k, b, x, sizeof x); |
981 | 0 | } |
982 | | |
983 | | /* ----- Streamlined NTRU Prime */ |
984 | | |
985 | | /* pk,sk = KEM_KeyGen() */ |
986 | | void |
987 | | sntrup761_keypair (unsigned char *pk, unsigned char *sk, void *random_ctx, |
988 | | sntrup761_random_func * random) |
989 | 0 | { |
990 | 0 | int i; |
991 | |
|
992 | 0 | ZKeyGen (pk, sk, random_ctx, random); |
993 | 0 | sk += SecretKeys_bytes; |
994 | 0 | for (i = 0; i < PublicKeys_bytes; ++i) |
995 | 0 | *sk++ = pk[i]; |
996 | 0 | random (random_ctx, Inputs_bytes, sk); |
997 | 0 | sk += Inputs_bytes; |
998 | 0 | Hash_prefix (sk, 4, pk, PublicKeys_bytes); |
999 | 0 | } |
1000 | | |
1001 | | /* c,r_enc = Hide(r,pk,cache); cache is Hash4(pk) */ |
1002 | | static void |
1003 | | Hide (unsigned char *c, unsigned char *r_enc, const Inputs r, |
1004 | | const unsigned char *pk, const unsigned char *cache) |
1005 | 0 | { |
1006 | 0 | Inputs_encode (r_enc, r); |
1007 | 0 | ZEncrypt (c, r, pk); |
1008 | 0 | c += Ciphertexts_bytes; |
1009 | 0 | HashConfirm (c, r_enc, cache); |
1010 | 0 | } |
1011 | | |
1012 | | /* c,k = Encap(pk) */ |
1013 | | void |
1014 | | sntrup761_enc (unsigned char *c, unsigned char *k, const unsigned char *pk, |
1015 | | void *random_ctx, sntrup761_random_func * random) |
1016 | 0 | { |
1017 | 0 | Inputs r; |
1018 | 0 | unsigned char r_enc[Inputs_bytes]; |
1019 | 0 | unsigned char cache[Hash_bytes]; |
1020 | |
|
1021 | 0 | Hash_prefix (cache, 4, pk, PublicKeys_bytes); |
1022 | 0 | Inputs_random (r, random_ctx, random); |
1023 | 0 | Hide (c, r_enc, r, pk, cache); |
1024 | 0 | HashSession (k, 1, r_enc, c); |
1025 | 0 | } |
1026 | | |
1027 | | /* 0 if matching ciphertext+confirm, else -1 */ |
1028 | | static int |
1029 | | Ciphertexts_diff_mask (const unsigned char *c, const unsigned char *c2) |
1030 | 0 | { |
1031 | 0 | uint16_t differentbits = 0; |
1032 | 0 | int len = Ciphertexts_bytes + Confirm_bytes; |
1033 | |
|
1034 | 0 | while (len-- > 0) |
1035 | 0 | differentbits |= (*c++) ^ (*c2++); |
1036 | 0 | return (1 & ((differentbits - 1) >> 8)) - 1; |
1037 | 0 | } |
1038 | | |
1039 | | /* k = Decap(c,sk) */ |
1040 | | void |
1041 | | sntrup761_dec (unsigned char *k, const unsigned char *c, const unsigned char *sk) |
1042 | 0 | { |
1043 | 0 | const unsigned char *pk = sk + SecretKeys_bytes; |
1044 | 0 | const unsigned char *rho = pk + PublicKeys_bytes; |
1045 | 0 | const unsigned char *cache = rho + Inputs_bytes; |
1046 | 0 | Inputs r; |
1047 | 0 | unsigned char r_enc[Inputs_bytes]; |
1048 | 0 | unsigned char cnew[Ciphertexts_bytes + Confirm_bytes]; |
1049 | 0 | int mask; |
1050 | 0 | int i; |
1051 | |
|
1052 | 0 | ZDecrypt (r, c, sk); |
1053 | 0 | Hide (cnew, r_enc, r, pk, cache); |
1054 | 0 | mask = Ciphertexts_diff_mask (c, cnew); |
1055 | 0 | for (i = 0; i < Inputs_bytes; ++i) |
1056 | 0 | r_enc[i] ^= mask & (r_enc[i] ^ rho[i]); |
1057 | 0 | HashSession (k, 1 + mask, r_enc, c); |
1058 | 0 | } |