sntrup761.c revision 1.1 1 1.1 christos /* $OpenBSD: sntrup761.c,v 1.5 2021/01/08 02:33:13 dtucker Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Public Domain, Authors:
5 1.1 christos * - Daniel J. Bernstein
6 1.1 christos * - Chitchanok Chuengsatiansup
7 1.1 christos * - Tanja Lange
8 1.1 christos * - Christine van Vredendaal
9 1.1 christos */
10 1.1 christos
11 1.1 christos #include <string.h>
12 1.1 christos #include "crypto_api.h"
13 1.1 christos
14 1.1 christos #define int8 crypto_int8
15 1.1 christos #define uint8 crypto_uint8
16 1.1 christos #define int16 crypto_int16
17 1.1 christos #define uint16 crypto_uint16
18 1.1 christos #define int32 crypto_int32
19 1.1 christos #define uint32 crypto_uint32
20 1.1 christos #define int64 crypto_int64
21 1.1 christos #define uint64 crypto_uint64
22 1.1 christos
23 1.1 christos /* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */
24 1.1 christos #define int32_MINMAX(a,b) \
25 1.1 christos do { \
26 1.1 christos int64_t ab = (int64_t)b ^ (int64_t)a; \
27 1.1 christos int64_t c = (int64_t)b - (int64_t)a; \
28 1.1 christos c ^= ab & (c ^ b); \
29 1.1 christos c >>= 31; \
30 1.1 christos c &= ab; \
31 1.1 christos a ^= c; \
32 1.1 christos b ^= c; \
33 1.1 christos } while(0)
34 1.1 christos
35 1.1 christos /* from supercop-20201130/crypto_sort/int32/portable4/sort.c */
36 1.1 christos
37 1.1 christos
38 1.1 christos static void crypto_sort_int32(void *array,long long n)
39 1.1 christos {
40 1.1 christos long long top,p,q,r,i,j;
41 1.1 christos int32 *x = array;
42 1.1 christos
43 1.1 christos if (n < 2) return;
44 1.1 christos top = 1;
45 1.1 christos while (top < n - top) top += top;
46 1.1 christos
47 1.1 christos for (p = top;p >= 1;p >>= 1) {
48 1.1 christos i = 0;
49 1.1 christos while (i + 2 * p <= n) {
50 1.1 christos for (j = i;j < i + p;++j)
51 1.1 christos int32_MINMAX(x[j],x[j+p]);
52 1.1 christos i += 2 * p;
53 1.1 christos }
54 1.1 christos for (j = i;j < n - p;++j)
55 1.1 christos int32_MINMAX(x[j],x[j+p]);
56 1.1 christos
57 1.1 christos i = 0;
58 1.1 christos j = 0;
59 1.1 christos for (q = top;q > p;q >>= 1) {
60 1.1 christos if (j != i) for (;;) {
61 1.1 christos if (j == n - q) goto done;
62 1.1 christos int32 a = x[j + p];
63 1.1 christos for (r = q;r > p;r >>= 1)
64 1.1 christos int32_MINMAX(a,x[j + r]);
65 1.1 christos x[j + p] = a;
66 1.1 christos ++j;
67 1.1 christos if (j == i + p) {
68 1.1 christos i += 2 * p;
69 1.1 christos break;
70 1.1 christos }
71 1.1 christos }
72 1.1 christos while (i + p <= n - q) {
73 1.1 christos for (j = i;j < i + p;++j) {
74 1.1 christos int32 a = x[j + p];
75 1.1 christos for (r = q;r > p;r >>= 1)
76 1.1 christos int32_MINMAX(a,x[j+r]);
77 1.1 christos x[j + p] = a;
78 1.1 christos }
79 1.1 christos i += 2 * p;
80 1.1 christos }
81 1.1 christos /* now i + p > n - q */
82 1.1 christos j = i;
83 1.1 christos while (j < n - q) {
84 1.1 christos int32 a = x[j + p];
85 1.1 christos for (r = q;r > p;r >>= 1)
86 1.1 christos int32_MINMAX(a,x[j+r]);
87 1.1 christos x[j + p] = a;
88 1.1 christos ++j;
89 1.1 christos }
90 1.1 christos
91 1.1 christos done: ;
92 1.1 christos }
93 1.1 christos }
94 1.1 christos }
95 1.1 christos
96 1.1 christos /* from supercop-20201130/crypto_sort/uint32/useint32/sort.c */
97 1.1 christos
98 1.1 christos /* can save time by vectorizing xor loops */
99 1.1 christos /* can save time by integrating xor loops with int32_sort */
100 1.1 christos
101 1.1 christos static void crypto_sort_uint32(void *array,long long n)
102 1.1 christos {
103 1.1 christos crypto_uint32 *x = array;
104 1.1 christos long long j;
105 1.1 christos for (j = 0;j < n;++j) x[j] ^= 0x80000000;
106 1.1 christos crypto_sort_int32(array,n);
107 1.1 christos for (j = 0;j < n;++j) x[j] ^= 0x80000000;
108 1.1 christos }
109 1.1 christos
110 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/uint32.c */
111 1.1 christos
112 1.1 christos /*
113 1.1 christos CPU division instruction typically takes time depending on x.
114 1.1 christos This software is designed to take time independent of x.
115 1.1 christos Time still varies depending on m; user must ensure that m is constant.
116 1.1 christos Time also varies on CPUs where multiplication is variable-time.
117 1.1 christos There could be more CPU issues.
118 1.1 christos There could also be compiler issues.
119 1.1 christos */
120 1.1 christos
121 1.1 christos static void uint32_divmod_uint14(uint32 *q,uint16 *r,uint32 x,uint16 m)
122 1.1 christos {
123 1.1 christos uint32 v = 0x80000000;
124 1.1 christos uint32 qpart;
125 1.1 christos uint32 mask;
126 1.1 christos
127 1.1 christos v /= m;
128 1.1 christos
129 1.1 christos /* caller guarantees m > 0 */
130 1.1 christos /* caller guarantees m < 16384 */
131 1.1 christos /* vm <= 2^31 <= vm+m-1 */
132 1.1 christos /* xvm <= 2^31 x <= xvm+x(m-1) */
133 1.1 christos
134 1.1 christos *q = 0;
135 1.1 christos
136 1.1 christos qpart = (x*(uint64)v)>>31;
137 1.1 christos /* 2^31 qpart <= xv <= 2^31 qpart + 2^31-1 */
138 1.1 christos /* 2^31 qpart m <= xvm <= 2^31 qpart m + (2^31-1)m */
139 1.1 christos /* 2^31 qpart m <= 2^31 x <= 2^31 qpart m + (2^31-1)m + x(m-1) */
140 1.1 christos /* 0 <= 2^31 newx <= (2^31-1)m + x(m-1) */
141 1.1 christos /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */
142 1.1 christos /* 0 <= newx <= (1-1/2^31)(2^14-1) + (2^32-1)((2^14-1)-1)/2^31 */
143 1.1 christos
144 1.1 christos x -= qpart*m; *q += qpart;
145 1.1 christos /* x <= 49146 */
146 1.1 christos
147 1.1 christos qpart = (x*(uint64)v)>>31;
148 1.1 christos /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */
149 1.1 christos /* 0 <= newx <= m + 49146(2^14-1)/2^31 */
150 1.1 christos /* 0 <= newx <= m + 0.4 */
151 1.1 christos /* 0 <= newx <= m */
152 1.1 christos
153 1.1 christos x -= qpart*m; *q += qpart;
154 1.1 christos /* x <= m */
155 1.1 christos
156 1.1 christos x -= m; *q += 1;
157 1.1 christos mask = -(x>>31);
158 1.1 christos x += mask&(uint32)m; *q += mask;
159 1.1 christos /* x < m */
160 1.1 christos
161 1.1 christos *r = x;
162 1.1 christos }
163 1.1 christos
164 1.1 christos
165 1.1 christos static uint16 uint32_mod_uint14(uint32 x,uint16 m)
166 1.1 christos {
167 1.1 christos uint32 q;
168 1.1 christos uint16 r;
169 1.1 christos uint32_divmod_uint14(&q,&r,x,m);
170 1.1 christos return r;
171 1.1 christos }
172 1.1 christos
173 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/int32.c */
174 1.1 christos
175 1.1 christos static void int32_divmod_uint14(int32 *q,uint16 *r,int32 x,uint16 m)
176 1.1 christos {
177 1.1 christos uint32 uq,uq2;
178 1.1 christos uint16 ur,ur2;
179 1.1 christos uint32 mask;
180 1.1 christos
181 1.1 christos uint32_divmod_uint14(&uq,&ur,0x80000000+(uint32)x,m);
182 1.1 christos uint32_divmod_uint14(&uq2,&ur2,0x80000000,m);
183 1.1 christos ur -= ur2; uq -= uq2;
184 1.1 christos mask = -(uint32)(ur>>15);
185 1.1 christos ur += mask&m; uq += mask;
186 1.1 christos *r = ur; *q = uq;
187 1.1 christos }
188 1.1 christos
189 1.1 christos
190 1.1 christos static uint16 int32_mod_uint14(int32 x,uint16 m)
191 1.1 christos {
192 1.1 christos int32 q;
193 1.1 christos uint16 r;
194 1.1 christos int32_divmod_uint14(&q,&r,x,m);
195 1.1 christos return r;
196 1.1 christos }
197 1.1 christos
198 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h */
199 1.1 christos /* pick one of these three: */
200 1.1 christos #define SIZE761
201 1.1 christos #undef SIZE653
202 1.1 christos #undef SIZE857
203 1.1 christos
204 1.1 christos /* pick one of these two: */
205 1.1 christos #define SNTRUP /* Streamlined NTRU Prime */
206 1.1 christos #undef LPR /* NTRU LPRime */
207 1.1 christos
208 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/params.h */
209 1.1 christos #ifndef params_H
210 1.1 christos #define params_H
211 1.1 christos
212 1.1 christos /* menu of parameter choices: */
213 1.1 christos
214 1.1 christos
215 1.1 christos /* what the menu means: */
216 1.1 christos
217 1.1 christos #if defined(SIZE761)
218 1.1 christos #define p 761
219 1.1 christos #define q 4591
220 1.1 christos #define Rounded_bytes 1007
221 1.1 christos #ifndef LPR
222 1.1 christos #define Rq_bytes 1158
223 1.1 christos #define w 286
224 1.1 christos #else
225 1.1 christos #define w 250
226 1.1 christos #define tau0 2156
227 1.1 christos #define tau1 114
228 1.1 christos #define tau2 2007
229 1.1 christos #define tau3 287
230 1.1 christos #endif
231 1.1 christos
232 1.1 christos #elif defined(SIZE653)
233 1.1 christos #define p 653
234 1.1 christos #define q 4621
235 1.1 christos #define Rounded_bytes 865
236 1.1 christos #ifndef LPR
237 1.1 christos #define Rq_bytes 994
238 1.1 christos #define w 288
239 1.1 christos #else
240 1.1 christos #define w 252
241 1.1 christos #define tau0 2175
242 1.1 christos #define tau1 113
243 1.1 christos #define tau2 2031
244 1.1 christos #define tau3 290
245 1.1 christos #endif
246 1.1 christos
247 1.1 christos #elif defined(SIZE857)
248 1.1 christos #define p 857
249 1.1 christos #define q 5167
250 1.1 christos #define Rounded_bytes 1152
251 1.1 christos #ifndef LPR
252 1.1 christos #define Rq_bytes 1322
253 1.1 christos #define w 322
254 1.1 christos #else
255 1.1 christos #define w 281
256 1.1 christos #define tau0 2433
257 1.1 christos #define tau1 101
258 1.1 christos #define tau2 2265
259 1.1 christos #define tau3 324
260 1.1 christos #endif
261 1.1 christos
262 1.1 christos #else
263 1.1 christos #error "no parameter set defined"
264 1.1 christos #endif
265 1.1 christos
266 1.1 christos #ifdef LPR
267 1.1 christos #define I 256
268 1.1 christos #endif
269 1.1 christos
270 1.1 christos #endif
271 1.1 christos
272 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.h */
273 1.1 christos #ifndef Decode_H
274 1.1 christos #define Decode_H
275 1.1 christos
276 1.1 christos
277 1.1 christos /* Decode(R,s,M,len) */
278 1.1 christos /* assumes 0 < M[i] < 16384 */
279 1.1 christos /* produces 0 <= R[i] < M[i] */
280 1.1 christos
281 1.1 christos #endif
282 1.1 christos
283 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.c */
284 1.1 christos
285 1.1 christos static void Decode(uint16 *out,const unsigned char *S,const uint16 *M,long long len)
286 1.1 christos {
287 1.1 christos if (len == 1) {
288 1.1 christos if (M[0] == 1)
289 1.1 christos *out = 0;
290 1.1 christos else if (M[0] <= 256)
291 1.1 christos *out = uint32_mod_uint14(S[0],M[0]);
292 1.1 christos else
293 1.1 christos *out = uint32_mod_uint14(S[0]+(((uint16)S[1])<<8),M[0]);
294 1.1 christos }
295 1.1 christos if (len > 1) {
296 1.1 christos uint16 R2[(len+1)/2];
297 1.1 christos uint16 M2[(len+1)/2];
298 1.1 christos uint16 bottomr[len/2];
299 1.1 christos uint32 bottomt[len/2];
300 1.1 christos long long i;
301 1.1 christos for (i = 0;i < len-1;i += 2) {
302 1.1 christos uint32 m = M[i]*(uint32) M[i+1];
303 1.1 christos if (m > 256*16383) {
304 1.1 christos bottomt[i/2] = 256*256;
305 1.1 christos bottomr[i/2] = S[0]+256*S[1];
306 1.1 christos S += 2;
307 1.1 christos M2[i/2] = (((m+255)>>8)+255)>>8;
308 1.1 christos } else if (m >= 16384) {
309 1.1 christos bottomt[i/2] = 256;
310 1.1 christos bottomr[i/2] = S[0];
311 1.1 christos S += 1;
312 1.1 christos M2[i/2] = (m+255)>>8;
313 1.1 christos } else {
314 1.1 christos bottomt[i/2] = 1;
315 1.1 christos bottomr[i/2] = 0;
316 1.1 christos M2[i/2] = m;
317 1.1 christos }
318 1.1 christos }
319 1.1 christos if (i < len)
320 1.1 christos M2[i/2] = M[i];
321 1.1 christos Decode(R2,S,M2,(len+1)/2);
322 1.1 christos for (i = 0;i < len-1;i += 2) {
323 1.1 christos uint32 r = bottomr[i/2];
324 1.1 christos uint32 r1;
325 1.1 christos uint16 r0;
326 1.1 christos r += bottomt[i/2]*R2[i/2];
327 1.1 christos uint32_divmod_uint14(&r1,&r0,r,M[i]);
328 1.1 christos r1 = uint32_mod_uint14(r1,M[i+1]); /* only needed for invalid inputs */
329 1.1 christos *out++ = r0;
330 1.1 christos *out++ = r1;
331 1.1 christos }
332 1.1 christos if (i < len)
333 1.1 christos *out++ = R2[i/2];
334 1.1 christos }
335 1.1 christos }
336 1.1 christos
337 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.h */
338 1.1 christos #ifndef Encode_H
339 1.1 christos #define Encode_H
340 1.1 christos
341 1.1 christos
342 1.1 christos /* Encode(s,R,M,len) */
343 1.1 christos /* assumes 0 <= R[i] < M[i] < 16384 */
344 1.1 christos
345 1.1 christos #endif
346 1.1 christos
347 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.c */
348 1.1 christos
349 1.1 christos /* 0 <= R[i] < M[i] < 16384 */
350 1.1 christos static void Encode(unsigned char *out,const uint16 *R,const uint16 *M,long long len)
351 1.1 christos {
352 1.1 christos if (len == 1) {
353 1.1 christos uint16 r = R[0];
354 1.1 christos uint16 m = M[0];
355 1.1 christos while (m > 1) {
356 1.1 christos *out++ = r;
357 1.1 christos r >>= 8;
358 1.1 christos m = (m+255)>>8;
359 1.1 christos }
360 1.1 christos }
361 1.1 christos if (len > 1) {
362 1.1 christos uint16 R2[(len+1)/2];
363 1.1 christos uint16 M2[(len+1)/2];
364 1.1 christos long long i;
365 1.1 christos for (i = 0;i < len-1;i += 2) {
366 1.1 christos uint32 m0 = M[i];
367 1.1 christos uint32 r = R[i]+R[i+1]*m0;
368 1.1 christos uint32 m = M[i+1]*m0;
369 1.1 christos while (m >= 16384) {
370 1.1 christos *out++ = r;
371 1.1 christos r >>= 8;
372 1.1 christos m = (m+255)>>8;
373 1.1 christos }
374 1.1 christos R2[i/2] = r;
375 1.1 christos M2[i/2] = m;
376 1.1 christos }
377 1.1 christos if (i < len) {
378 1.1 christos R2[i/2] = R[i];
379 1.1 christos M2[i/2] = M[i];
380 1.1 christos }
381 1.1 christos Encode(out,R2,M2,(len+1)/2);
382 1.1 christos }
383 1.1 christos }
384 1.1 christos
385 1.1 christos /* from supercop-20201130/crypto_kem/sntrup761/ref/kem.c */
386 1.1 christos
387 1.1 christos #ifdef LPR
388 1.1 christos #endif
389 1.1 christos
390 1.1 christos
391 1.1 christos /* ----- masks */
392 1.1 christos
393 1.1 christos #ifndef LPR
394 1.1 christos
395 1.1 christos /* return -1 if x!=0; else return 0 */
396 1.1 christos static int int16_nonzero_mask(int16 x)
397 1.1 christos {
398 1.1 christos uint16 u = x; /* 0, else 1...65535 */
399 1.1 christos uint32 v = u; /* 0, else 1...65535 */
400 1.1 christos v = -v; /* 0, else 2^32-65535...2^32-1 */
401 1.1 christos v >>= 31; /* 0, else 1 */
402 1.1 christos return -v; /* 0, else -1 */
403 1.1 christos }
404 1.1 christos
405 1.1 christos #endif
406 1.1 christos
407 1.1 christos /* return -1 if x<0; otherwise return 0 */
408 1.1 christos static int int16_negative_mask(int16 x)
409 1.1 christos {
410 1.1 christos uint16 u = x;
411 1.1 christos u >>= 15;
412 1.1 christos return -(int) u;
413 1.1 christos /* alternative with gcc -fwrapv: */
414 1.1 christos /* x>>15 compiles to CPU's arithmetic right shift */
415 1.1 christos }
416 1.1 christos
417 1.1 christos /* ----- arithmetic mod 3 */
418 1.1 christos
419 1.1 christos typedef int8 small;
420 1.1 christos
421 1.1 christos /* F3 is always represented as -1,0,1 */
422 1.1 christos /* so ZZ_fromF3 is a no-op */
423 1.1 christos
424 1.1 christos /* x must not be close to top int16 */
425 1.1 christos static small F3_freeze(int16 x)
426 1.1 christos {
427 1.1 christos return int32_mod_uint14(x+1,3)-1;
428 1.1 christos }
429 1.1 christos
430 1.1 christos /* ----- arithmetic mod q */
431 1.1 christos
432 1.1 christos #define q12 ((q-1)/2)
433 1.1 christos typedef int16 Fq;
434 1.1 christos /* always represented as -q12...q12 */
435 1.1 christos /* so ZZ_fromFq is a no-op */
436 1.1 christos
437 1.1 christos /* x must not be close to top int32 */
438 1.1 christos static Fq Fq_freeze(int32 x)
439 1.1 christos {
440 1.1 christos return int32_mod_uint14(x+q12,q)-q12;
441 1.1 christos }
442 1.1 christos
443 1.1 christos #ifndef LPR
444 1.1 christos
445 1.1 christos static Fq Fq_recip(Fq a1)
446 1.1 christos {
447 1.1 christos int i = 1;
448 1.1 christos Fq ai = a1;
449 1.1 christos
450 1.1 christos while (i < q-2) {
451 1.1 christos ai = Fq_freeze(a1*(int32)ai);
452 1.1 christos i += 1;
453 1.1 christos }
454 1.1 christos return ai;
455 1.1 christos }
456 1.1 christos
457 1.1 christos #endif
458 1.1 christos
459 1.1 christos /* ----- Top and Right */
460 1.1 christos
461 1.1 christos #ifdef LPR
462 1.1 christos #define tau 16
463 1.1 christos
464 1.1 christos static int8 Top(Fq C)
465 1.1 christos {
466 1.1 christos return (tau1*(int32)(C+tau0)+16384)>>15;
467 1.1 christos }
468 1.1 christos
469 1.1 christos static Fq Right(int8 T)
470 1.1 christos {
471 1.1 christos return Fq_freeze(tau3*(int32)T-tau2);
472 1.1 christos }
473 1.1 christos #endif
474 1.1 christos
475 1.1 christos /* ----- small polynomials */
476 1.1 christos
477 1.1 christos #ifndef LPR
478 1.1 christos
479 1.1 christos /* 0 if Weightw_is(r), else -1 */
480 1.1 christos static int Weightw_mask(small *r)
481 1.1 christos {
482 1.1 christos int weight = 0;
483 1.1 christos int i;
484 1.1 christos
485 1.1 christos for (i = 0;i < p;++i) weight += r[i]&1;
486 1.1 christos return int16_nonzero_mask(weight-w);
487 1.1 christos }
488 1.1 christos
489 1.1 christos /* R3_fromR(R_fromRq(r)) */
490 1.1 christos static void R3_fromRq(small *out,const Fq *r)
491 1.1 christos {
492 1.1 christos int i;
493 1.1 christos for (i = 0;i < p;++i) out[i] = F3_freeze(r[i]);
494 1.1 christos }
495 1.1 christos
496 1.1 christos /* h = f*g in the ring R3 */
497 1.1 christos static void R3_mult(small *h,const small *f,const small *g)
498 1.1 christos {
499 1.1 christos small fg[p+p-1];
500 1.1 christos small result;
501 1.1 christos int i,j;
502 1.1 christos
503 1.1 christos for (i = 0;i < p;++i) {
504 1.1 christos result = 0;
505 1.1 christos for (j = 0;j <= i;++j) result = F3_freeze(result+f[j]*g[i-j]);
506 1.1 christos fg[i] = result;
507 1.1 christos }
508 1.1 christos for (i = p;i < p+p-1;++i) {
509 1.1 christos result = 0;
510 1.1 christos for (j = i-p+1;j < p;++j) result = F3_freeze(result+f[j]*g[i-j]);
511 1.1 christos fg[i] = result;
512 1.1 christos }
513 1.1 christos
514 1.1 christos for (i = p+p-2;i >= p;--i) {
515 1.1 christos fg[i-p] = F3_freeze(fg[i-p]+fg[i]);
516 1.1 christos fg[i-p+1] = F3_freeze(fg[i-p+1]+fg[i]);
517 1.1 christos }
518 1.1 christos
519 1.1 christos for (i = 0;i < p;++i) h[i] = fg[i];
520 1.1 christos }
521 1.1 christos
522 1.1 christos /* returns 0 if recip succeeded; else -1 */
523 1.1 christos static int R3_recip(small *out,const small *in)
524 1.1 christos {
525 1.1 christos small f[p+1],g[p+1],v[p+1],r[p+1];
526 1.1 christos int i,loop,delta;
527 1.1 christos int sign,swap,t;
528 1.1 christos
529 1.1 christos for (i = 0;i < p+1;++i) v[i] = 0;
530 1.1 christos for (i = 0;i < p+1;++i) r[i] = 0;
531 1.1 christos r[0] = 1;
532 1.1 christos for (i = 0;i < p;++i) f[i] = 0;
533 1.1 christos f[0] = 1; f[p-1] = f[p] = -1;
534 1.1 christos for (i = 0;i < p;++i) g[p-1-i] = in[i];
535 1.1 christos g[p] = 0;
536 1.1 christos
537 1.1 christos delta = 1;
538 1.1 christos
539 1.1 christos for (loop = 0;loop < 2*p-1;++loop) {
540 1.1 christos for (i = p;i > 0;--i) v[i] = v[i-1];
541 1.1 christos v[0] = 0;
542 1.1 christos
543 1.1 christos sign = -g[0]*f[0];
544 1.1 christos swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]);
545 1.1 christos delta ^= swap&(delta^-delta);
546 1.1 christos delta += 1;
547 1.1 christos
548 1.1 christos for (i = 0;i < p+1;++i) {
549 1.1 christos t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t;
550 1.1 christos t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t;
551 1.1 christos }
552 1.1 christos
553 1.1 christos for (i = 0;i < p+1;++i) g[i] = F3_freeze(g[i]+sign*f[i]);
554 1.1 christos for (i = 0;i < p+1;++i) r[i] = F3_freeze(r[i]+sign*v[i]);
555 1.1 christos
556 1.1 christos for (i = 0;i < p;++i) g[i] = g[i+1];
557 1.1 christos g[p] = 0;
558 1.1 christos }
559 1.1 christos
560 1.1 christos sign = f[0];
561 1.1 christos for (i = 0;i < p;++i) out[i] = sign*v[p-1-i];
562 1.1 christos
563 1.1 christos return int16_nonzero_mask(delta);
564 1.1 christos }
565 1.1 christos
566 1.1 christos #endif
567 1.1 christos
568 1.1 christos /* ----- polynomials mod q */
569 1.1 christos
570 1.1 christos /* h = f*g in the ring Rq */
571 1.1 christos static void Rq_mult_small(Fq *h,const Fq *f,const small *g)
572 1.1 christos {
573 1.1 christos Fq fg[p+p-1];
574 1.1 christos Fq result;
575 1.1 christos int i,j;
576 1.1 christos
577 1.1 christos for (i = 0;i < p;++i) {
578 1.1 christos result = 0;
579 1.1 christos for (j = 0;j <= i;++j) result = Fq_freeze(result+f[j]*(int32)g[i-j]);
580 1.1 christos fg[i] = result;
581 1.1 christos }
582 1.1 christos for (i = p;i < p+p-1;++i) {
583 1.1 christos result = 0;
584 1.1 christos for (j = i-p+1;j < p;++j) result = Fq_freeze(result+f[j]*(int32)g[i-j]);
585 1.1 christos fg[i] = result;
586 1.1 christos }
587 1.1 christos
588 1.1 christos for (i = p+p-2;i >= p;--i) {
589 1.1 christos fg[i-p] = Fq_freeze(fg[i-p]+fg[i]);
590 1.1 christos fg[i-p+1] = Fq_freeze(fg[i-p+1]+fg[i]);
591 1.1 christos }
592 1.1 christos
593 1.1 christos for (i = 0;i < p;++i) h[i] = fg[i];
594 1.1 christos }
595 1.1 christos
596 1.1 christos #ifndef LPR
597 1.1 christos
598 1.1 christos /* h = 3f in Rq */
599 1.1 christos static void Rq_mult3(Fq *h,const Fq *f)
600 1.1 christos {
601 1.1 christos int i;
602 1.1 christos
603 1.1 christos for (i = 0;i < p;++i) h[i] = Fq_freeze(3*f[i]);
604 1.1 christos }
605 1.1 christos
606 1.1 christos /* out = 1/(3*in) in Rq */
607 1.1 christos /* returns 0 if recip succeeded; else -1 */
608 1.1 christos static int Rq_recip3(Fq *out,const small *in)
609 1.1 christos {
610 1.1 christos Fq f[p+1],g[p+1],v[p+1],r[p+1];
611 1.1 christos int i,loop,delta;
612 1.1 christos int swap,t;
613 1.1 christos int32 f0,g0;
614 1.1 christos Fq scale;
615 1.1 christos
616 1.1 christos for (i = 0;i < p+1;++i) v[i] = 0;
617 1.1 christos for (i = 0;i < p+1;++i) r[i] = 0;
618 1.1 christos r[0] = Fq_recip(3);
619 1.1 christos for (i = 0;i < p;++i) f[i] = 0;
620 1.1 christos f[0] = 1; f[p-1] = f[p] = -1;
621 1.1 christos for (i = 0;i < p;++i) g[p-1-i] = in[i];
622 1.1 christos g[p] = 0;
623 1.1 christos
624 1.1 christos delta = 1;
625 1.1 christos
626 1.1 christos for (loop = 0;loop < 2*p-1;++loop) {
627 1.1 christos for (i = p;i > 0;--i) v[i] = v[i-1];
628 1.1 christos v[0] = 0;
629 1.1 christos
630 1.1 christos swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]);
631 1.1 christos delta ^= swap&(delta^-delta);
632 1.1 christos delta += 1;
633 1.1 christos
634 1.1 christos for (i = 0;i < p+1;++i) {
635 1.1 christos t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t;
636 1.1 christos t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t;
637 1.1 christos }
638 1.1 christos
639 1.1 christos f0 = f[0];
640 1.1 christos g0 = g[0];
641 1.1 christos for (i = 0;i < p+1;++i) g[i] = Fq_freeze(f0*g[i]-g0*f[i]);
642 1.1 christos for (i = 0;i < p+1;++i) r[i] = Fq_freeze(f0*r[i]-g0*v[i]);
643 1.1 christos
644 1.1 christos for (i = 0;i < p;++i) g[i] = g[i+1];
645 1.1 christos g[p] = 0;
646 1.1 christos }
647 1.1 christos
648 1.1 christos scale = Fq_recip(f[0]);
649 1.1 christos for (i = 0;i < p;++i) out[i] = Fq_freeze(scale*(int32)v[p-1-i]);
650 1.1 christos
651 1.1 christos return int16_nonzero_mask(delta);
652 1.1 christos }
653 1.1 christos
654 1.1 christos #endif
655 1.1 christos
656 1.1 christos /* ----- rounded polynomials mod q */
657 1.1 christos
658 1.1 christos static void Round(Fq *out,const Fq *a)
659 1.1 christos {
660 1.1 christos int i;
661 1.1 christos for (i = 0;i < p;++i) out[i] = a[i]-F3_freeze(a[i]);
662 1.1 christos }
663 1.1 christos
664 1.1 christos /* ----- sorting to generate short polynomial */
665 1.1 christos
666 1.1 christos static void Short_fromlist(small *out,const uint32 *in)
667 1.1 christos {
668 1.1 christos uint32 L[p];
669 1.1 christos int i;
670 1.1 christos
671 1.1 christos for (i = 0;i < w;++i) L[i] = in[i]&(uint32)-2;
672 1.1 christos for (i = w;i < p;++i) L[i] = (in[i]&(uint32)-3)|1;
673 1.1 christos crypto_sort_uint32(L,p);
674 1.1 christos for (i = 0;i < p;++i) out[i] = (L[i]&3)-1;
675 1.1 christos }
676 1.1 christos
677 1.1 christos /* ----- underlying hash function */
678 1.1 christos
679 1.1 christos #define Hash_bytes 32
680 1.1 christos
681 1.1 christos /* e.g., b = 0 means out = Hash0(in) */
682 1.1 christos static void Hash_prefix(unsigned char *out,int b,const unsigned char *in,int inlen)
683 1.1 christos {
684 1.1 christos unsigned char x[inlen+1];
685 1.1 christos unsigned char h[64];
686 1.1 christos int i;
687 1.1 christos
688 1.1 christos x[0] = b;
689 1.1 christos for (i = 0;i < inlen;++i) x[i+1] = in[i];
690 1.1 christos crypto_hash_sha512(h,x,inlen+1);
691 1.1 christos for (i = 0;i < 32;++i) out[i] = h[i];
692 1.1 christos }
693 1.1 christos
694 1.1 christos /* ----- higher-level randomness */
695 1.1 christos
696 1.1 christos static uint32 urandom32(void)
697 1.1 christos {
698 1.1 christos unsigned char c[4];
699 1.1 christos uint32 out[4];
700 1.1 christos
701 1.1 christos randombytes(c,4);
702 1.1 christos out[0] = (uint32)c[0];
703 1.1 christos out[1] = ((uint32)c[1])<<8;
704 1.1 christos out[2] = ((uint32)c[2])<<16;
705 1.1 christos out[3] = ((uint32)c[3])<<24;
706 1.1 christos return out[0]+out[1]+out[2]+out[3];
707 1.1 christos }
708 1.1 christos
709 1.1 christos static void Short_random(small *out)
710 1.1 christos {
711 1.1 christos uint32 L[p];
712 1.1 christos int i;
713 1.1 christos
714 1.1 christos for (i = 0;i < p;++i) L[i] = urandom32();
715 1.1 christos Short_fromlist(out,L);
716 1.1 christos }
717 1.1 christos
718 1.1 christos #ifndef LPR
719 1.1 christos
720 1.1 christos static void Small_random(small *out)
721 1.1 christos {
722 1.1 christos int i;
723 1.1 christos
724 1.1 christos for (i = 0;i < p;++i) out[i] = (((urandom32()&0x3fffffff)*3)>>30)-1;
725 1.1 christos }
726 1.1 christos
727 1.1 christos #endif
728 1.1 christos
729 1.1 christos /* ----- Streamlined NTRU Prime Core */
730 1.1 christos
731 1.1 christos #ifndef LPR
732 1.1 christos
733 1.1 christos /* h,(f,ginv) = KeyGen() */
734 1.1 christos static void KeyGen(Fq *h,small *f,small *ginv)
735 1.1 christos {
736 1.1 christos small g[p];
737 1.1 christos Fq finv[p];
738 1.1 christos
739 1.1 christos for (;;) {
740 1.1 christos Small_random(g);
741 1.1 christos if (R3_recip(ginv,g) == 0) break;
742 1.1 christos }
743 1.1 christos Short_random(f);
744 1.1 christos Rq_recip3(finv,f); /* always works */
745 1.1 christos Rq_mult_small(h,finv,g);
746 1.1 christos }
747 1.1 christos
748 1.1 christos /* c = Encrypt(r,h) */
749 1.1 christos static void Encrypt(Fq *c,const small *r,const Fq *h)
750 1.1 christos {
751 1.1 christos Fq hr[p];
752 1.1 christos
753 1.1 christos Rq_mult_small(hr,h,r);
754 1.1 christos Round(c,hr);
755 1.1 christos }
756 1.1 christos
757 1.1 christos /* r = Decrypt(c,(f,ginv)) */
758 1.1 christos static void Decrypt(small *r,const Fq *c,const small *f,const small *ginv)
759 1.1 christos {
760 1.1 christos Fq cf[p];
761 1.1 christos Fq cf3[p];
762 1.1 christos small e[p];
763 1.1 christos small ev[p];
764 1.1 christos int mask;
765 1.1 christos int i;
766 1.1 christos
767 1.1 christos Rq_mult_small(cf,c,f);
768 1.1 christos Rq_mult3(cf3,cf);
769 1.1 christos R3_fromRq(e,cf3);
770 1.1 christos R3_mult(ev,e,ginv);
771 1.1 christos
772 1.1 christos mask = Weightw_mask(ev); /* 0 if weight w, else -1 */
773 1.1 christos for (i = 0;i < w;++i) r[i] = ((ev[i]^1)&~mask)^1;
774 1.1 christos for (i = w;i < p;++i) r[i] = ev[i]&~mask;
775 1.1 christos }
776 1.1 christos
777 1.1 christos #endif
778 1.1 christos
779 1.1 christos /* ----- NTRU LPRime Core */
780 1.1 christos
781 1.1 christos #ifdef LPR
782 1.1 christos
783 1.1 christos /* (G,A),a = KeyGen(G); leaves G unchanged */
784 1.1 christos static void KeyGen(Fq *A,small *a,const Fq *G)
785 1.1 christos {
786 1.1 christos Fq aG[p];
787 1.1 christos
788 1.1 christos Short_random(a);
789 1.1 christos Rq_mult_small(aG,G,a);
790 1.1 christos Round(A,aG);
791 1.1 christos }
792 1.1 christos
793 1.1 christos /* B,T = Encrypt(r,(G,A),b) */
794 1.1 christos static void Encrypt(Fq *B,int8 *T,const int8 *r,const Fq *G,const Fq *A,const small *b)
795 1.1 christos {
796 1.1 christos Fq bG[p];
797 1.1 christos Fq bA[p];
798 1.1 christos int i;
799 1.1 christos
800 1.1 christos Rq_mult_small(bG,G,b);
801 1.1 christos Round(B,bG);
802 1.1 christos Rq_mult_small(bA,A,b);
803 1.1 christos for (i = 0;i < I;++i) T[i] = Top(Fq_freeze(bA[i]+r[i]*q12));
804 1.1 christos }
805 1.1 christos
806 1.1 christos /* r = Decrypt((B,T),a) */
807 1.1 christos static void Decrypt(int8 *r,const Fq *B,const int8 *T,const small *a)
808 1.1 christos {
809 1.1 christos Fq aB[p];
810 1.1 christos int i;
811 1.1 christos
812 1.1 christos Rq_mult_small(aB,B,a);
813 1.1 christos for (i = 0;i < I;++i)
814 1.1 christos r[i] = -int16_negative_mask(Fq_freeze(Right(T[i])-aB[i]+4*w+1));
815 1.1 christos }
816 1.1 christos
817 1.1 christos #endif
818 1.1 christos
819 1.1 christos /* ----- encoding I-bit inputs */
820 1.1 christos
821 1.1 christos #ifdef LPR
822 1.1 christos
823 1.1 christos #define Inputs_bytes (I/8)
824 1.1 christos typedef int8 Inputs[I]; /* passed by reference */
825 1.1 christos
826 1.1 christos static void Inputs_encode(unsigned char *s,const Inputs r)
827 1.1 christos {
828 1.1 christos int i;
829 1.1 christos for (i = 0;i < Inputs_bytes;++i) s[i] = 0;
830 1.1 christos for (i = 0;i < I;++i) s[i>>3] |= r[i]<<(i&7);
831 1.1 christos }
832 1.1 christos
833 1.1 christos #endif
834 1.1 christos
835 1.1 christos /* ----- Expand */
836 1.1 christos
837 1.1 christos #ifdef LPR
838 1.1 christos
839 1.1 christos static const unsigned char aes_nonce[16] = {0};
840 1.1 christos
841 1.1 christos static void Expand(uint32 *L,const unsigned char *k)
842 1.1 christos {
843 1.1 christos int i;
844 1.1 christos crypto_stream_aes256ctr((unsigned char *) L,4*p,aes_nonce,k);
845 1.1 christos for (i = 0;i < p;++i) {
846 1.1 christos uint32 L0 = ((unsigned char *) L)[4*i];
847 1.1 christos uint32 L1 = ((unsigned char *) L)[4*i+1];
848 1.1 christos uint32 L2 = ((unsigned char *) L)[4*i+2];
849 1.1 christos uint32 L3 = ((unsigned char *) L)[4*i+3];
850 1.1 christos L[i] = L0+(L1<<8)+(L2<<16)+(L3<<24);
851 1.1 christos }
852 1.1 christos }
853 1.1 christos
854 1.1 christos #endif
855 1.1 christos
856 1.1 christos /* ----- Seeds */
857 1.1 christos
858 1.1 christos #ifdef LPR
859 1.1 christos
860 1.1 christos #define Seeds_bytes 32
861 1.1 christos
862 1.1 christos static void Seeds_random(unsigned char *s)
863 1.1 christos {
864 1.1 christos randombytes(s,Seeds_bytes);
865 1.1 christos }
866 1.1 christos
867 1.1 christos #endif
868 1.1 christos
869 1.1 christos /* ----- Generator, HashShort */
870 1.1 christos
871 1.1 christos #ifdef LPR
872 1.1 christos
873 1.1 christos /* G = Generator(k) */
874 1.1 christos static void Generator(Fq *G,const unsigned char *k)
875 1.1 christos {
876 1.1 christos uint32 L[p];
877 1.1 christos int i;
878 1.1 christos
879 1.1 christos Expand(L,k);
880 1.1 christos for (i = 0;i < p;++i) G[i] = uint32_mod_uint14(L[i],q)-q12;
881 1.1 christos }
882 1.1 christos
883 1.1 christos /* out = HashShort(r) */
884 1.1 christos static void HashShort(small *out,const Inputs r)
885 1.1 christos {
886 1.1 christos unsigned char s[Inputs_bytes];
887 1.1 christos unsigned char h[Hash_bytes];
888 1.1 christos uint32 L[p];
889 1.1 christos
890 1.1 christos Inputs_encode(s,r);
891 1.1 christos Hash_prefix(h,5,s,sizeof s);
892 1.1 christos Expand(L,h);
893 1.1 christos Short_fromlist(out,L);
894 1.1 christos }
895 1.1 christos
896 1.1 christos #endif
897 1.1 christos
898 1.1 christos /* ----- NTRU LPRime Expand */
899 1.1 christos
900 1.1 christos #ifdef LPR
901 1.1 christos
902 1.1 christos /* (S,A),a = XKeyGen() */
903 1.1 christos static void XKeyGen(unsigned char *S,Fq *A,small *a)
904 1.1 christos {
905 1.1 christos Fq G[p];
906 1.1 christos
907 1.1 christos Seeds_random(S);
908 1.1 christos Generator(G,S);
909 1.1 christos KeyGen(A,a,G);
910 1.1 christos }
911 1.1 christos
912 1.1 christos /* B,T = XEncrypt(r,(S,A)) */
913 1.1 christos static void XEncrypt(Fq *B,int8 *T,const int8 *r,const unsigned char *S,const Fq *A)
914 1.1 christos {
915 1.1 christos Fq G[p];
916 1.1 christos small b[p];
917 1.1 christos
918 1.1 christos Generator(G,S);
919 1.1 christos HashShort(b,r);
920 1.1 christos Encrypt(B,T,r,G,A,b);
921 1.1 christos }
922 1.1 christos
923 1.1 christos #define XDecrypt Decrypt
924 1.1 christos
925 1.1 christos #endif
926 1.1 christos
927 1.1 christos /* ----- encoding small polynomials (including short polynomials) */
928 1.1 christos
929 1.1 christos #define Small_bytes ((p+3)/4)
930 1.1 christos
931 1.1 christos /* these are the only functions that rely on p mod 4 = 1 */
932 1.1 christos
933 1.1 christos static void Small_encode(unsigned char *s,const small *f)
934 1.1 christos {
935 1.1 christos small x;
936 1.1 christos int i;
937 1.1 christos
938 1.1 christos for (i = 0;i < p/4;++i) {
939 1.1 christos x = *f++ + 1;
940 1.1 christos x += (*f++ + 1)<<2;
941 1.1 christos x += (*f++ + 1)<<4;
942 1.1 christos x += (*f++ + 1)<<6;
943 1.1 christos *s++ = x;
944 1.1 christos }
945 1.1 christos x = *f++ + 1;
946 1.1 christos *s++ = x;
947 1.1 christos }
948 1.1 christos
949 1.1 christos static void Small_decode(small *f,const unsigned char *s)
950 1.1 christos {
951 1.1 christos unsigned char x;
952 1.1 christos int i;
953 1.1 christos
954 1.1 christos for (i = 0;i < p/4;++i) {
955 1.1 christos x = *s++;
956 1.1 christos *f++ = ((small)(x&3))-1; x >>= 2;
957 1.1 christos *f++ = ((small)(x&3))-1; x >>= 2;
958 1.1 christos *f++ = ((small)(x&3))-1; x >>= 2;
959 1.1 christos *f++ = ((small)(x&3))-1;
960 1.1 christos }
961 1.1 christos x = *s++;
962 1.1 christos *f++ = ((small)(x&3))-1;
963 1.1 christos }
964 1.1 christos
965 1.1 christos /* ----- encoding general polynomials */
966 1.1 christos
967 1.1 christos #ifndef LPR
968 1.1 christos
969 1.1 christos static void Rq_encode(unsigned char *s,const Fq *r)
970 1.1 christos {
971 1.1 christos uint16 R[p],M[p];
972 1.1 christos int i;
973 1.1 christos
974 1.1 christos for (i = 0;i < p;++i) R[i] = r[i]+q12;
975 1.1 christos for (i = 0;i < p;++i) M[i] = q;
976 1.1 christos Encode(s,R,M,p);
977 1.1 christos }
978 1.1 christos
979 1.1 christos static void Rq_decode(Fq *r,const unsigned char *s)
980 1.1 christos {
981 1.1 christos uint16 R[p],M[p];
982 1.1 christos int i;
983 1.1 christos
984 1.1 christos for (i = 0;i < p;++i) M[i] = q;
985 1.1 christos Decode(R,s,M,p);
986 1.1 christos for (i = 0;i < p;++i) r[i] = ((Fq)R[i])-q12;
987 1.1 christos }
988 1.1 christos
989 1.1 christos #endif
990 1.1 christos
991 1.1 christos /* ----- encoding rounded polynomials */
992 1.1 christos
993 1.1 christos static void Rounded_encode(unsigned char *s,const Fq *r)
994 1.1 christos {
995 1.1 christos uint16 R[p],M[p];
996 1.1 christos int i;
997 1.1 christos
998 1.1 christos for (i = 0;i < p;++i) R[i] = ((r[i]+q12)*10923)>>15;
999 1.1 christos for (i = 0;i < p;++i) M[i] = (q+2)/3;
1000 1.1 christos Encode(s,R,M,p);
1001 1.1 christos }
1002 1.1 christos
1003 1.1 christos static void Rounded_decode(Fq *r,const unsigned char *s)
1004 1.1 christos {
1005 1.1 christos uint16 R[p],M[p];
1006 1.1 christos int i;
1007 1.1 christos
1008 1.1 christos for (i = 0;i < p;++i) M[i] = (q+2)/3;
1009 1.1 christos Decode(R,s,M,p);
1010 1.1 christos for (i = 0;i < p;++i) r[i] = R[i]*3-q12;
1011 1.1 christos }
1012 1.1 christos
1013 1.1 christos /* ----- encoding top polynomials */
1014 1.1 christos
1015 1.1 christos #ifdef LPR
1016 1.1 christos
1017 1.1 christos #define Top_bytes (I/2)
1018 1.1 christos
1019 1.1 christos static void Top_encode(unsigned char *s,const int8 *T)
1020 1.1 christos {
1021 1.1 christos int i;
1022 1.1 christos for (i = 0;i < Top_bytes;++i)
1023 1.1 christos s[i] = T[2*i]+(T[2*i+1]<<4);
1024 1.1 christos }
1025 1.1 christos
1026 1.1 christos static void Top_decode(int8 *T,const unsigned char *s)
1027 1.1 christos {
1028 1.1 christos int i;
1029 1.1 christos for (i = 0;i < Top_bytes;++i) {
1030 1.1 christos T[2*i] = s[i]&15;
1031 1.1 christos T[2*i+1] = s[i]>>4;
1032 1.1 christos }
1033 1.1 christos }
1034 1.1 christos
1035 1.1 christos #endif
1036 1.1 christos
1037 1.1 christos /* ----- Streamlined NTRU Prime Core plus encoding */
1038 1.1 christos
1039 1.1 christos #ifndef LPR
1040 1.1 christos
1041 1.1 christos typedef small Inputs[p]; /* passed by reference */
1042 1.1 christos #define Inputs_random Short_random
1043 1.1 christos #define Inputs_encode Small_encode
1044 1.1 christos #define Inputs_bytes Small_bytes
1045 1.1 christos
1046 1.1 christos #define Ciphertexts_bytes Rounded_bytes
1047 1.1 christos #define SecretKeys_bytes (2*Small_bytes)
1048 1.1 christos #define PublicKeys_bytes Rq_bytes
1049 1.1 christos
1050 1.1 christos /* pk,sk = ZKeyGen() */
1051 1.1 christos static void ZKeyGen(unsigned char *pk,unsigned char *sk)
1052 1.1 christos {
1053 1.1 christos Fq h[p];
1054 1.1 christos small f[p],v[p];
1055 1.1 christos
1056 1.1 christos KeyGen(h,f,v);
1057 1.1 christos Rq_encode(pk,h);
1058 1.1 christos Small_encode(sk,f); sk += Small_bytes;
1059 1.1 christos Small_encode(sk,v);
1060 1.1 christos }
1061 1.1 christos
1062 1.1 christos /* C = ZEncrypt(r,pk) */
1063 1.1 christos static void ZEncrypt(unsigned char *C,const Inputs r,const unsigned char *pk)
1064 1.1 christos {
1065 1.1 christos Fq h[p];
1066 1.1 christos Fq c[p];
1067 1.1 christos Rq_decode(h,pk);
1068 1.1 christos Encrypt(c,r,h);
1069 1.1 christos Rounded_encode(C,c);
1070 1.1 christos }
1071 1.1 christos
1072 1.1 christos /* r = ZDecrypt(C,sk) */
1073 1.1 christos static void ZDecrypt(Inputs r,const unsigned char *C,const unsigned char *sk)
1074 1.1 christos {
1075 1.1 christos small f[p],v[p];
1076 1.1 christos Fq c[p];
1077 1.1 christos
1078 1.1 christos Small_decode(f,sk); sk += Small_bytes;
1079 1.1 christos Small_decode(v,sk);
1080 1.1 christos Rounded_decode(c,C);
1081 1.1 christos Decrypt(r,c,f,v);
1082 1.1 christos }
1083 1.1 christos
1084 1.1 christos #endif
1085 1.1 christos
1086 1.1 christos /* ----- NTRU LPRime Expand plus encoding */
1087 1.1 christos
1088 1.1 christos #ifdef LPR
1089 1.1 christos
1090 1.1 christos #define Ciphertexts_bytes (Rounded_bytes+Top_bytes)
1091 1.1 christos #define SecretKeys_bytes Small_bytes
1092 1.1 christos #define PublicKeys_bytes (Seeds_bytes+Rounded_bytes)
1093 1.1 christos
1094 1.1 christos static void Inputs_random(Inputs r)
1095 1.1 christos {
1096 1.1 christos unsigned char s[Inputs_bytes];
1097 1.1 christos int i;
1098 1.1 christos
1099 1.1 christos randombytes(s,sizeof s);
1100 1.1 christos for (i = 0;i < I;++i) r[i] = 1&(s[i>>3]>>(i&7));
1101 1.1 christos }
1102 1.1 christos
1103 1.1 christos /* pk,sk = ZKeyGen() */
1104 1.1 christos static void ZKeyGen(unsigned char *pk,unsigned char *sk)
1105 1.1 christos {
1106 1.1 christos Fq A[p];
1107 1.1 christos small a[p];
1108 1.1 christos
1109 1.1 christos XKeyGen(pk,A,a); pk += Seeds_bytes;
1110 1.1 christos Rounded_encode(pk,A);
1111 1.1 christos Small_encode(sk,a);
1112 1.1 christos }
1113 1.1 christos
1114 1.1 christos /* c = ZEncrypt(r,pk) */
1115 1.1 christos static void ZEncrypt(unsigned char *c,const Inputs r,const unsigned char *pk)
1116 1.1 christos {
1117 1.1 christos Fq A[p];
1118 1.1 christos Fq B[p];
1119 1.1 christos int8 T[I];
1120 1.1 christos
1121 1.1 christos Rounded_decode(A,pk+Seeds_bytes);
1122 1.1 christos XEncrypt(B,T,r,pk,A);
1123 1.1 christos Rounded_encode(c,B); c += Rounded_bytes;
1124 1.1 christos Top_encode(c,T);
1125 1.1 christos }
1126 1.1 christos
1127 1.1 christos /* r = ZDecrypt(C,sk) */
1128 1.1 christos static void ZDecrypt(Inputs r,const unsigned char *c,const unsigned char *sk)
1129 1.1 christos {
1130 1.1 christos small a[p];
1131 1.1 christos Fq B[p];
1132 1.1 christos int8 T[I];
1133 1.1 christos
1134 1.1 christos Small_decode(a,sk);
1135 1.1 christos Rounded_decode(B,c);
1136 1.1 christos Top_decode(T,c+Rounded_bytes);
1137 1.1 christos XDecrypt(r,B,T,a);
1138 1.1 christos }
1139 1.1 christos
1140 1.1 christos #endif
1141 1.1 christos
1142 1.1 christos /* ----- confirmation hash */
1143 1.1 christos
1144 1.1 christos #define Confirm_bytes 32
1145 1.1 christos
1146 1.1 christos /* h = HashConfirm(r,pk,cache); cache is Hash4(pk) */
1147 1.1 christos static void HashConfirm(unsigned char *h,const unsigned char *r,const unsigned char *pk,const unsigned char *cache)
1148 1.1 christos {
1149 1.1 christos #ifndef LPR
1150 1.1 christos unsigned char x[Hash_bytes*2];
1151 1.1 christos int i;
1152 1.1 christos
1153 1.1 christos Hash_prefix(x,3,r,Inputs_bytes);
1154 1.1 christos for (i = 0;i < Hash_bytes;++i) x[Hash_bytes+i] = cache[i];
1155 1.1 christos #else
1156 1.1 christos unsigned char x[Inputs_bytes+Hash_bytes];
1157 1.1 christos int i;
1158 1.1 christos
1159 1.1 christos for (i = 0;i < Inputs_bytes;++i) x[i] = r[i];
1160 1.1 christos for (i = 0;i < Hash_bytes;++i) x[Inputs_bytes+i] = cache[i];
1161 1.1 christos #endif
1162 1.1 christos Hash_prefix(h,2,x,sizeof x);
1163 1.1 christos }
1164 1.1 christos
1165 1.1 christos /* ----- session-key hash */
1166 1.1 christos
1167 1.1 christos /* k = HashSession(b,y,z) */
1168 1.1 christos static void HashSession(unsigned char *k,int b,const unsigned char *y,const unsigned char *z)
1169 1.1 christos {
1170 1.1 christos #ifndef LPR
1171 1.1 christos unsigned char x[Hash_bytes+Ciphertexts_bytes+Confirm_bytes];
1172 1.1 christos int i;
1173 1.1 christos
1174 1.1 christos Hash_prefix(x,3,y,Inputs_bytes);
1175 1.1 christos for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Hash_bytes+i] = z[i];
1176 1.1 christos #else
1177 1.1 christos unsigned char x[Inputs_bytes+Ciphertexts_bytes+Confirm_bytes];
1178 1.1 christos int i;
1179 1.1 christos
1180 1.1 christos for (i = 0;i < Inputs_bytes;++i) x[i] = y[i];
1181 1.1 christos for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Inputs_bytes+i] = z[i];
1182 1.1 christos #endif
1183 1.1 christos Hash_prefix(k,b,x,sizeof x);
1184 1.1 christos }
1185 1.1 christos
1186 1.1 christos /* ----- Streamlined NTRU Prime and NTRU LPRime */
1187 1.1 christos
1188 1.1 christos /* pk,sk = KEM_KeyGen() */
1189 1.1 christos static void KEM_KeyGen(unsigned char *pk,unsigned char *sk)
1190 1.1 christos {
1191 1.1 christos int i;
1192 1.1 christos
1193 1.1 christos ZKeyGen(pk,sk); sk += SecretKeys_bytes;
1194 1.1 christos for (i = 0;i < PublicKeys_bytes;++i) *sk++ = pk[i];
1195 1.1 christos randombytes(sk,Inputs_bytes); sk += Inputs_bytes;
1196 1.1 christos Hash_prefix(sk,4,pk,PublicKeys_bytes);
1197 1.1 christos }
1198 1.1 christos
1199 1.1 christos /* c,r_enc = Hide(r,pk,cache); cache is Hash4(pk) */
1200 1.1 christos static void Hide(unsigned char *c,unsigned char *r_enc,const Inputs r,const unsigned char *pk,const unsigned char *cache)
1201 1.1 christos {
1202 1.1 christos Inputs_encode(r_enc,r);
1203 1.1 christos ZEncrypt(c,r,pk); c += Ciphertexts_bytes;
1204 1.1 christos HashConfirm(c,r_enc,pk,cache);
1205 1.1 christos }
1206 1.1 christos
1207 1.1 christos /* c,k = Encap(pk) */
1208 1.1 christos static void Encap(unsigned char *c,unsigned char *k,const unsigned char *pk)
1209 1.1 christos {
1210 1.1 christos Inputs r;
1211 1.1 christos unsigned char r_enc[Inputs_bytes];
1212 1.1 christos unsigned char cache[Hash_bytes];
1213 1.1 christos
1214 1.1 christos Hash_prefix(cache,4,pk,PublicKeys_bytes);
1215 1.1 christos Inputs_random(r);
1216 1.1 christos Hide(c,r_enc,r,pk,cache);
1217 1.1 christos HashSession(k,1,r_enc,c);
1218 1.1 christos }
1219 1.1 christos
1220 1.1 christos /* 0 if matching ciphertext+confirm, else -1 */
1221 1.1 christos static int Ciphertexts_diff_mask(const unsigned char *c,const unsigned char *c2)
1222 1.1 christos {
1223 1.1 christos uint16 differentbits = 0;
1224 1.1 christos int len = Ciphertexts_bytes+Confirm_bytes;
1225 1.1 christos
1226 1.1 christos while (len-- > 0) differentbits |= (*c++)^(*c2++);
1227 1.1 christos return (1&((differentbits-1)>>8))-1;
1228 1.1 christos }
1229 1.1 christos
1230 1.1 christos /* k = Decap(c,sk) */
1231 1.1 christos static void Decap(unsigned char *k,const unsigned char *c,const unsigned char *sk)
1232 1.1 christos {
1233 1.1 christos const unsigned char *pk = sk + SecretKeys_bytes;
1234 1.1 christos const unsigned char *rho = pk + PublicKeys_bytes;
1235 1.1 christos const unsigned char *cache = rho + Inputs_bytes;
1236 1.1 christos Inputs r;
1237 1.1 christos unsigned char r_enc[Inputs_bytes];
1238 1.1 christos unsigned char cnew[Ciphertexts_bytes+Confirm_bytes];
1239 1.1 christos int mask;
1240 1.1 christos int i;
1241 1.1 christos
1242 1.1 christos ZDecrypt(r,c,sk);
1243 1.1 christos Hide(cnew,r_enc,r,pk,cache);
1244 1.1 christos mask = Ciphertexts_diff_mask(c,cnew);
1245 1.1 christos for (i = 0;i < Inputs_bytes;++i) r_enc[i] ^= mask&(r_enc[i]^rho[i]);
1246 1.1 christos HashSession(k,1+mask,r_enc,c);
1247 1.1 christos }
1248 1.1 christos
1249 1.1 christos /* ----- crypto_kem API */
1250 1.1 christos
1251 1.1 christos
1252 1.1 christos int crypto_kem_sntrup761_keypair(unsigned char *pk,unsigned char *sk)
1253 1.1 christos {
1254 1.1 christos KEM_KeyGen(pk,sk);
1255 1.1 christos return 0;
1256 1.1 christos }
1257 1.1 christos
1258 1.1 christos int crypto_kem_sntrup761_enc(unsigned char *c,unsigned char *k,const unsigned char *pk)
1259 1.1 christos {
1260 1.1 christos Encap(c,k,pk);
1261 1.1 christos return 0;
1262 1.1 christos }
1263 1.1 christos
1264 1.1 christos int crypto_kem_sntrup761_dec(unsigned char *k,const unsigned char *c,const unsigned char *sk)
1265 1.1 christos {
1266 1.1 christos Decap(k,c,sk);
1267 1.1 christos return 0;
1268 1.1 christos }
1269 1.1 christos
1270