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