xref: /freebsd/crypto/openssh/sntrup761.c (revision f374ba41)
1*f374ba41SEd Maste /*  $OpenBSD: sntrup761.c,v 1.6 2023/01/11 02:13:52 djm Exp $ */
219261079SEd Maste 
319261079SEd Maste /*
419261079SEd Maste  * Public Domain, Authors:
519261079SEd Maste  * - Daniel J. Bernstein
619261079SEd Maste  * - Chitchanok Chuengsatiansup
719261079SEd Maste  * - Tanja Lange
819261079SEd Maste  * - Christine van Vredendaal
919261079SEd Maste  */
1019261079SEd Maste 
1119261079SEd Maste #include "includes.h"
1219261079SEd Maste 
1319261079SEd Maste #ifdef USE_SNTRUP761X25519
1419261079SEd Maste 
1519261079SEd Maste #include <string.h>
1619261079SEd Maste #include "crypto_api.h"
1719261079SEd Maste 
1819261079SEd Maste #define int8 crypto_int8
1919261079SEd Maste #define uint8 crypto_uint8
2019261079SEd Maste #define int16 crypto_int16
2119261079SEd Maste #define uint16 crypto_uint16
2219261079SEd Maste #define int32 crypto_int32
2319261079SEd Maste #define uint32 crypto_uint32
2419261079SEd Maste #define int64 crypto_int64
2519261079SEd Maste #define uint64 crypto_uint64
2619261079SEd Maste 
2719261079SEd Maste /* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */
2819261079SEd Maste #define int32_MINMAX(a,b) \
2919261079SEd Maste do { \
3019261079SEd Maste   int64_t ab = (int64_t)b ^ (int64_t)a; \
3119261079SEd Maste   int64_t c = (int64_t)b - (int64_t)a; \
3219261079SEd Maste   c ^= ab & (c ^ b); \
3319261079SEd Maste   c >>= 31; \
3419261079SEd Maste   c &= ab; \
3519261079SEd Maste   a ^= c; \
3619261079SEd Maste   b ^= c; \
3719261079SEd Maste } while(0)
3819261079SEd Maste 
3919261079SEd Maste /* from supercop-20201130/crypto_sort/int32/portable4/sort.c */
4019261079SEd Maste 
4119261079SEd Maste 
crypto_sort_int32(void * array,long long n)4219261079SEd Maste static void crypto_sort_int32(void *array,long long n)
4319261079SEd Maste {
4419261079SEd Maste   long long top,p,q,r,i,j;
4519261079SEd Maste   int32 *x = array;
4619261079SEd Maste 
4719261079SEd Maste   if (n < 2) return;
4819261079SEd Maste   top = 1;
4919261079SEd Maste   while (top < n - top) top += top;
5019261079SEd Maste 
5119261079SEd Maste   for (p = top;p >= 1;p >>= 1) {
5219261079SEd Maste     i = 0;
5319261079SEd Maste     while (i + 2 * p <= n) {
5419261079SEd Maste       for (j = i;j < i + p;++j)
5519261079SEd Maste         int32_MINMAX(x[j],x[j+p]);
5619261079SEd Maste       i += 2 * p;
5719261079SEd Maste     }
5819261079SEd Maste     for (j = i;j < n - p;++j)
5919261079SEd Maste       int32_MINMAX(x[j],x[j+p]);
6019261079SEd Maste 
6119261079SEd Maste     i = 0;
6219261079SEd Maste     j = 0;
6319261079SEd Maste     for (q = top;q > p;q >>= 1) {
6419261079SEd Maste       if (j != i) for (;;) {
6519261079SEd Maste         if (j == n - q) goto done;
6619261079SEd Maste         int32 a = x[j + p];
6719261079SEd Maste         for (r = q;r > p;r >>= 1)
6819261079SEd Maste           int32_MINMAX(a,x[j + r]);
6919261079SEd Maste         x[j + p] = a;
7019261079SEd Maste         ++j;
7119261079SEd Maste         if (j == i + p) {
7219261079SEd Maste           i += 2 * p;
7319261079SEd Maste           break;
7419261079SEd Maste         }
7519261079SEd Maste       }
7619261079SEd Maste       while (i + p <= n - q) {
7719261079SEd Maste         for (j = i;j < i + p;++j) {
7819261079SEd Maste           int32 a = x[j + p];
7919261079SEd Maste           for (r = q;r > p;r >>= 1)
8019261079SEd Maste             int32_MINMAX(a,x[j+r]);
8119261079SEd Maste           x[j + p] = a;
8219261079SEd Maste         }
8319261079SEd Maste         i += 2 * p;
8419261079SEd Maste       }
8519261079SEd Maste       /* now i + p > n - q */
8619261079SEd Maste       j = i;
8719261079SEd Maste       while (j < n - q) {
8819261079SEd Maste         int32 a = x[j + p];
8919261079SEd Maste         for (r = q;r > p;r >>= 1)
9019261079SEd Maste           int32_MINMAX(a,x[j+r]);
9119261079SEd Maste         x[j + p] = a;
9219261079SEd Maste         ++j;
9319261079SEd Maste       }
9419261079SEd Maste 
9519261079SEd Maste       done: ;
9619261079SEd Maste     }
9719261079SEd Maste   }
9819261079SEd Maste }
9919261079SEd Maste 
10019261079SEd Maste /* from supercop-20201130/crypto_sort/uint32/useint32/sort.c */
10119261079SEd Maste 
10219261079SEd Maste /* can save time by vectorizing xor loops */
10319261079SEd Maste /* can save time by integrating xor loops with int32_sort */
10419261079SEd Maste 
crypto_sort_uint32(void * array,long long n)10519261079SEd Maste static void crypto_sort_uint32(void *array,long long n)
10619261079SEd Maste {
10719261079SEd Maste   crypto_uint32 *x = array;
10819261079SEd Maste   long long j;
10919261079SEd Maste   for (j = 0;j < n;++j) x[j] ^= 0x80000000;
11019261079SEd Maste   crypto_sort_int32(array,n);
11119261079SEd Maste   for (j = 0;j < n;++j) x[j] ^= 0x80000000;
11219261079SEd Maste }
11319261079SEd Maste 
11419261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/uint32.c */
11519261079SEd Maste 
11619261079SEd Maste /*
11719261079SEd Maste CPU division instruction typically takes time depending on x.
11819261079SEd Maste This software is designed to take time independent of x.
11919261079SEd Maste Time still varies depending on m; user must ensure that m is constant.
12019261079SEd Maste Time also varies on CPUs where multiplication is variable-time.
12119261079SEd Maste There could be more CPU issues.
12219261079SEd Maste There could also be compiler issues.
12319261079SEd Maste */
12419261079SEd Maste 
uint32_divmod_uint14(uint32 * q,uint16 * r,uint32 x,uint16 m)12519261079SEd Maste static void uint32_divmod_uint14(uint32 *q,uint16 *r,uint32 x,uint16 m)
12619261079SEd Maste {
12719261079SEd Maste   uint32 v = 0x80000000;
12819261079SEd Maste   uint32 qpart;
12919261079SEd Maste   uint32 mask;
13019261079SEd Maste 
13119261079SEd Maste   v /= m;
13219261079SEd Maste 
13319261079SEd Maste   /* caller guarantees m > 0 */
13419261079SEd Maste   /* caller guarantees m < 16384 */
13519261079SEd Maste   /* vm <= 2^31 <= vm+m-1 */
13619261079SEd Maste   /* xvm <= 2^31 x <= xvm+x(m-1) */
13719261079SEd Maste 
13819261079SEd Maste   *q = 0;
13919261079SEd Maste 
14019261079SEd Maste   qpart = (x*(uint64)v)>>31;
14119261079SEd Maste   /* 2^31 qpart <= xv <= 2^31 qpart + 2^31-1 */
14219261079SEd Maste   /* 2^31 qpart m <= xvm <= 2^31 qpart m + (2^31-1)m */
14319261079SEd Maste   /* 2^31 qpart m <= 2^31 x <= 2^31 qpart m + (2^31-1)m + x(m-1) */
14419261079SEd Maste   /* 0 <= 2^31 newx <= (2^31-1)m + x(m-1) */
14519261079SEd Maste   /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */
14619261079SEd Maste   /* 0 <= newx <= (1-1/2^31)(2^14-1) + (2^32-1)((2^14-1)-1)/2^31 */
14719261079SEd Maste 
14819261079SEd Maste   x -= qpart*m; *q += qpart;
14919261079SEd Maste   /* x <= 49146 */
15019261079SEd Maste 
15119261079SEd Maste   qpart = (x*(uint64)v)>>31;
15219261079SEd Maste   /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */
15319261079SEd Maste   /* 0 <= newx <= m + 49146(2^14-1)/2^31 */
15419261079SEd Maste   /* 0 <= newx <= m + 0.4 */
15519261079SEd Maste   /* 0 <= newx <= m */
15619261079SEd Maste 
15719261079SEd Maste   x -= qpart*m; *q += qpart;
15819261079SEd Maste   /* x <= m */
15919261079SEd Maste 
16019261079SEd Maste   x -= m; *q += 1;
16119261079SEd Maste   mask = -(x>>31);
16219261079SEd Maste   x += mask&(uint32)m; *q += mask;
16319261079SEd Maste   /* x < m */
16419261079SEd Maste 
16519261079SEd Maste   *r = x;
16619261079SEd Maste }
16719261079SEd Maste 
16819261079SEd Maste 
uint32_mod_uint14(uint32 x,uint16 m)16919261079SEd Maste static uint16 uint32_mod_uint14(uint32 x,uint16 m)
17019261079SEd Maste {
17119261079SEd Maste   uint32 q;
17219261079SEd Maste   uint16 r;
17319261079SEd Maste   uint32_divmod_uint14(&q,&r,x,m);
17419261079SEd Maste   return r;
17519261079SEd Maste }
17619261079SEd Maste 
17719261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/int32.c */
17819261079SEd Maste 
int32_divmod_uint14(int32 * q,uint16 * r,int32 x,uint16 m)17919261079SEd Maste static void int32_divmod_uint14(int32 *q,uint16 *r,int32 x,uint16 m)
18019261079SEd Maste {
18119261079SEd Maste   uint32 uq,uq2;
18219261079SEd Maste   uint16 ur,ur2;
18319261079SEd Maste   uint32 mask;
18419261079SEd Maste 
18519261079SEd Maste   uint32_divmod_uint14(&uq,&ur,0x80000000+(uint32)x,m);
18619261079SEd Maste   uint32_divmod_uint14(&uq2,&ur2,0x80000000,m);
18719261079SEd Maste   ur -= ur2; uq -= uq2;
18819261079SEd Maste   mask = -(uint32)(ur>>15);
18919261079SEd Maste   ur += mask&m; uq += mask;
19019261079SEd Maste   *r = ur; *q = uq;
19119261079SEd Maste }
19219261079SEd Maste 
19319261079SEd Maste 
int32_mod_uint14(int32 x,uint16 m)19419261079SEd Maste static uint16 int32_mod_uint14(int32 x,uint16 m)
19519261079SEd Maste {
19619261079SEd Maste   int32 q;
19719261079SEd Maste   uint16 r;
19819261079SEd Maste   int32_divmod_uint14(&q,&r,x,m);
19919261079SEd Maste   return r;
20019261079SEd Maste }
20119261079SEd Maste 
20219261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h */
20319261079SEd Maste /* pick one of these three: */
20419261079SEd Maste #define SIZE761
20519261079SEd Maste #undef SIZE653
20619261079SEd Maste #undef SIZE857
20719261079SEd Maste 
20819261079SEd Maste /* pick one of these two: */
20919261079SEd Maste #define SNTRUP /* Streamlined NTRU Prime */
21019261079SEd Maste #undef LPR /* NTRU LPRime */
21119261079SEd Maste 
21219261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/params.h */
21319261079SEd Maste #ifndef params_H
21419261079SEd Maste #define params_H
21519261079SEd Maste 
21619261079SEd Maste /* menu of parameter choices: */
21719261079SEd Maste 
21819261079SEd Maste 
21919261079SEd Maste /* what the menu means: */
22019261079SEd Maste 
22119261079SEd Maste #if defined(SIZE761)
22219261079SEd Maste #define p 761
22319261079SEd Maste #define q 4591
22419261079SEd Maste #define Rounded_bytes 1007
22519261079SEd Maste #ifndef LPR
22619261079SEd Maste #define Rq_bytes 1158
22719261079SEd Maste #define w 286
22819261079SEd Maste #else
22919261079SEd Maste #define w 250
23019261079SEd Maste #define tau0 2156
23119261079SEd Maste #define tau1 114
23219261079SEd Maste #define tau2 2007
23319261079SEd Maste #define tau3 287
23419261079SEd Maste #endif
23519261079SEd Maste 
23619261079SEd Maste #elif defined(SIZE653)
23719261079SEd Maste #define p 653
23819261079SEd Maste #define q 4621
23919261079SEd Maste #define Rounded_bytes 865
24019261079SEd Maste #ifndef LPR
24119261079SEd Maste #define Rq_bytes 994
24219261079SEd Maste #define w 288
24319261079SEd Maste #else
24419261079SEd Maste #define w 252
24519261079SEd Maste #define tau0 2175
24619261079SEd Maste #define tau1 113
24719261079SEd Maste #define tau2 2031
24819261079SEd Maste #define tau3 290
24919261079SEd Maste #endif
25019261079SEd Maste 
25119261079SEd Maste #elif defined(SIZE857)
25219261079SEd Maste #define p 857
25319261079SEd Maste #define q 5167
25419261079SEd Maste #define Rounded_bytes 1152
25519261079SEd Maste #ifndef LPR
25619261079SEd Maste #define Rq_bytes 1322
25719261079SEd Maste #define w 322
25819261079SEd Maste #else
25919261079SEd Maste #define w 281
26019261079SEd Maste #define tau0 2433
26119261079SEd Maste #define tau1 101
26219261079SEd Maste #define tau2 2265
26319261079SEd Maste #define tau3 324
26419261079SEd Maste #endif
26519261079SEd Maste 
26619261079SEd Maste #else
26719261079SEd Maste #error "no parameter set defined"
26819261079SEd Maste #endif
26919261079SEd Maste 
27019261079SEd Maste #ifdef LPR
27119261079SEd Maste #define I 256
27219261079SEd Maste #endif
27319261079SEd Maste 
27419261079SEd Maste #endif
27519261079SEd Maste 
27619261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.h */
27719261079SEd Maste #ifndef Decode_H
27819261079SEd Maste #define Decode_H
27919261079SEd Maste 
28019261079SEd Maste 
28119261079SEd Maste /* Decode(R,s,M,len) */
28219261079SEd Maste /* assumes 0 < M[i] < 16384 */
28319261079SEd Maste /* produces 0 <= R[i] < M[i] */
28419261079SEd Maste 
28519261079SEd Maste #endif
28619261079SEd Maste 
28719261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.c */
28819261079SEd Maste 
Decode(uint16 * out,const unsigned char * S,const uint16 * M,long long len)28919261079SEd Maste static void Decode(uint16 *out,const unsigned char *S,const uint16 *M,long long len)
29019261079SEd Maste {
29119261079SEd Maste   if (len == 1) {
29219261079SEd Maste     if (M[0] == 1)
29319261079SEd Maste       *out = 0;
29419261079SEd Maste     else if (M[0] <= 256)
29519261079SEd Maste       *out = uint32_mod_uint14(S[0],M[0]);
29619261079SEd Maste     else
29719261079SEd Maste       *out = uint32_mod_uint14(S[0]+(((uint16)S[1])<<8),M[0]);
29819261079SEd Maste   }
29919261079SEd Maste   if (len > 1) {
30019261079SEd Maste     uint16 R2[(len+1)/2];
30119261079SEd Maste     uint16 M2[(len+1)/2];
30219261079SEd Maste     uint16 bottomr[len/2];
30319261079SEd Maste     uint32 bottomt[len/2];
30419261079SEd Maste     long long i;
30519261079SEd Maste     for (i = 0;i < len-1;i += 2) {
30619261079SEd Maste       uint32 m = M[i]*(uint32) M[i+1];
30719261079SEd Maste       if (m > 256*16383) {
30819261079SEd Maste         bottomt[i/2] = 256*256;
30919261079SEd Maste         bottomr[i/2] = S[0]+256*S[1];
31019261079SEd Maste         S += 2;
31119261079SEd Maste         M2[i/2] = (((m+255)>>8)+255)>>8;
31219261079SEd Maste       } else if (m >= 16384) {
31319261079SEd Maste         bottomt[i/2] = 256;
31419261079SEd Maste         bottomr[i/2] = S[0];
31519261079SEd Maste         S += 1;
31619261079SEd Maste         M2[i/2] = (m+255)>>8;
31719261079SEd Maste       } else {
31819261079SEd Maste         bottomt[i/2] = 1;
31919261079SEd Maste         bottomr[i/2] = 0;
32019261079SEd Maste         M2[i/2] = m;
32119261079SEd Maste       }
32219261079SEd Maste     }
32319261079SEd Maste     if (i < len)
32419261079SEd Maste       M2[i/2] = M[i];
32519261079SEd Maste     Decode(R2,S,M2,(len+1)/2);
32619261079SEd Maste     for (i = 0;i < len-1;i += 2) {
32719261079SEd Maste       uint32 r = bottomr[i/2];
32819261079SEd Maste       uint32 r1;
32919261079SEd Maste       uint16 r0;
33019261079SEd Maste       r += bottomt[i/2]*R2[i/2];
33119261079SEd Maste       uint32_divmod_uint14(&r1,&r0,r,M[i]);
33219261079SEd Maste       r1 = uint32_mod_uint14(r1,M[i+1]); /* only needed for invalid inputs */
33319261079SEd Maste       *out++ = r0;
33419261079SEd Maste       *out++ = r1;
33519261079SEd Maste     }
33619261079SEd Maste     if (i < len)
33719261079SEd Maste       *out++ = R2[i/2];
33819261079SEd Maste   }
33919261079SEd Maste }
34019261079SEd Maste 
34119261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.h */
34219261079SEd Maste #ifndef Encode_H
34319261079SEd Maste #define Encode_H
34419261079SEd Maste 
34519261079SEd Maste 
34619261079SEd Maste /* Encode(s,R,M,len) */
34719261079SEd Maste /* assumes 0 <= R[i] < M[i] < 16384 */
34819261079SEd Maste 
34919261079SEd Maste #endif
35019261079SEd Maste 
35119261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.c */
35219261079SEd Maste 
35319261079SEd Maste /* 0 <= R[i] < M[i] < 16384 */
Encode(unsigned char * out,const uint16 * R,const uint16 * M,long long len)35419261079SEd Maste static void Encode(unsigned char *out,const uint16 *R,const uint16 *M,long long len)
35519261079SEd Maste {
35619261079SEd Maste   if (len == 1) {
35719261079SEd Maste     uint16 r = R[0];
35819261079SEd Maste     uint16 m = M[0];
35919261079SEd Maste     while (m > 1) {
36019261079SEd Maste       *out++ = r;
36119261079SEd Maste       r >>= 8;
36219261079SEd Maste       m = (m+255)>>8;
36319261079SEd Maste     }
36419261079SEd Maste   }
36519261079SEd Maste   if (len > 1) {
36619261079SEd Maste     uint16 R2[(len+1)/2];
36719261079SEd Maste     uint16 M2[(len+1)/2];
36819261079SEd Maste     long long i;
36919261079SEd Maste     for (i = 0;i < len-1;i += 2) {
37019261079SEd Maste       uint32 m0 = M[i];
37119261079SEd Maste       uint32 r = R[i]+R[i+1]*m0;
37219261079SEd Maste       uint32 m = M[i+1]*m0;
37319261079SEd Maste       while (m >= 16384) {
37419261079SEd Maste         *out++ = r;
37519261079SEd Maste         r >>= 8;
37619261079SEd Maste         m = (m+255)>>8;
37719261079SEd Maste       }
37819261079SEd Maste       R2[i/2] = r;
37919261079SEd Maste       M2[i/2] = m;
38019261079SEd Maste     }
38119261079SEd Maste     if (i < len) {
38219261079SEd Maste       R2[i/2] = R[i];
38319261079SEd Maste       M2[i/2] = M[i];
38419261079SEd Maste     }
38519261079SEd Maste     Encode(out,R2,M2,(len+1)/2);
38619261079SEd Maste   }
38719261079SEd Maste }
38819261079SEd Maste 
38919261079SEd Maste /* from supercop-20201130/crypto_kem/sntrup761/ref/kem.c */
39019261079SEd Maste 
39119261079SEd Maste #ifdef LPR
39219261079SEd Maste #endif
39319261079SEd Maste 
39419261079SEd Maste 
39519261079SEd Maste /* ----- masks */
39619261079SEd Maste 
39719261079SEd Maste #ifndef LPR
39819261079SEd Maste 
39919261079SEd Maste /* return -1 if x!=0; else return 0 */
int16_nonzero_mask(int16 x)40019261079SEd Maste static int int16_nonzero_mask(int16 x)
40119261079SEd Maste {
40219261079SEd Maste   uint16 u = x; /* 0, else 1...65535 */
40319261079SEd Maste   uint32 v = u; /* 0, else 1...65535 */
40419261079SEd Maste   v = -v; /* 0, else 2^32-65535...2^32-1 */
40519261079SEd Maste   v >>= 31; /* 0, else 1 */
40619261079SEd Maste   return -v; /* 0, else -1 */
40719261079SEd Maste }
40819261079SEd Maste 
40919261079SEd Maste #endif
41019261079SEd Maste 
41119261079SEd Maste /* return -1 if x<0; otherwise return 0 */
int16_negative_mask(int16 x)41219261079SEd Maste static int int16_negative_mask(int16 x)
41319261079SEd Maste {
41419261079SEd Maste   uint16 u = x;
41519261079SEd Maste   u >>= 15;
41619261079SEd Maste   return -(int) u;
41719261079SEd Maste   /* alternative with gcc -fwrapv: */
41819261079SEd Maste   /* x>>15 compiles to CPU's arithmetic right shift */
41919261079SEd Maste }
42019261079SEd Maste 
42119261079SEd Maste /* ----- arithmetic mod 3 */
42219261079SEd Maste 
42319261079SEd Maste typedef int8 small;
42419261079SEd Maste 
42519261079SEd Maste /* F3 is always represented as -1,0,1 */
42619261079SEd Maste /* so ZZ_fromF3 is a no-op */
42719261079SEd Maste 
42819261079SEd Maste /* x must not be close to top int16 */
F3_freeze(int16 x)42919261079SEd Maste static small F3_freeze(int16 x)
43019261079SEd Maste {
43119261079SEd Maste   return int32_mod_uint14(x+1,3)-1;
43219261079SEd Maste }
43319261079SEd Maste 
43419261079SEd Maste /* ----- arithmetic mod q */
43519261079SEd Maste 
43619261079SEd Maste #define q12 ((q-1)/2)
43719261079SEd Maste typedef int16 Fq;
43819261079SEd Maste /* always represented as -q12...q12 */
43919261079SEd Maste /* so ZZ_fromFq is a no-op */
44019261079SEd Maste 
44119261079SEd Maste /* x must not be close to top int32 */
Fq_freeze(int32 x)44219261079SEd Maste static Fq Fq_freeze(int32 x)
44319261079SEd Maste {
44419261079SEd Maste   return int32_mod_uint14(x+q12,q)-q12;
44519261079SEd Maste }
44619261079SEd Maste 
44719261079SEd Maste #ifndef LPR
44819261079SEd Maste 
Fq_recip(Fq a1)44919261079SEd Maste static Fq Fq_recip(Fq a1)
45019261079SEd Maste {
45119261079SEd Maste   int i = 1;
45219261079SEd Maste   Fq ai = a1;
45319261079SEd Maste 
45419261079SEd Maste   while (i < q-2) {
45519261079SEd Maste     ai = Fq_freeze(a1*(int32)ai);
45619261079SEd Maste     i += 1;
45719261079SEd Maste   }
45819261079SEd Maste   return ai;
45919261079SEd Maste }
46019261079SEd Maste 
46119261079SEd Maste #endif
46219261079SEd Maste 
46319261079SEd Maste /* ----- Top and Right */
46419261079SEd Maste 
46519261079SEd Maste #ifdef LPR
46619261079SEd Maste #define tau 16
46719261079SEd Maste 
Top(Fq C)46819261079SEd Maste static int8 Top(Fq C)
46919261079SEd Maste {
47019261079SEd Maste   return (tau1*(int32)(C+tau0)+16384)>>15;
47119261079SEd Maste }
47219261079SEd Maste 
Right(int8 T)47319261079SEd Maste static Fq Right(int8 T)
47419261079SEd Maste {
47519261079SEd Maste   return Fq_freeze(tau3*(int32)T-tau2);
47619261079SEd Maste }
47719261079SEd Maste #endif
47819261079SEd Maste 
47919261079SEd Maste /* ----- small polynomials */
48019261079SEd Maste 
48119261079SEd Maste #ifndef LPR
48219261079SEd Maste 
48319261079SEd Maste /* 0 if Weightw_is(r), else -1 */
Weightw_mask(small * r)48419261079SEd Maste static int Weightw_mask(small *r)
48519261079SEd Maste {
48619261079SEd Maste   int weight = 0;
48719261079SEd Maste   int i;
48819261079SEd Maste 
48919261079SEd Maste   for (i = 0;i < p;++i) weight += r[i]&1;
49019261079SEd Maste   return int16_nonzero_mask(weight-w);
49119261079SEd Maste }
49219261079SEd Maste 
49319261079SEd Maste /* R3_fromR(R_fromRq(r)) */
R3_fromRq(small * out,const Fq * r)49419261079SEd Maste static void R3_fromRq(small *out,const Fq *r)
49519261079SEd Maste {
49619261079SEd Maste   int i;
49719261079SEd Maste   for (i = 0;i < p;++i) out[i] = F3_freeze(r[i]);
49819261079SEd Maste }
49919261079SEd Maste 
50019261079SEd Maste /* h = f*g in the ring R3 */
R3_mult(small * h,const small * f,const small * g)50119261079SEd Maste static void R3_mult(small *h,const small *f,const small *g)
50219261079SEd Maste {
50319261079SEd Maste   small fg[p+p-1];
50419261079SEd Maste   small result;
50519261079SEd Maste   int i,j;
50619261079SEd Maste 
50719261079SEd Maste   for (i = 0;i < p;++i) {
50819261079SEd Maste     result = 0;
50919261079SEd Maste     for (j = 0;j <= i;++j) result = F3_freeze(result+f[j]*g[i-j]);
51019261079SEd Maste     fg[i] = result;
51119261079SEd Maste   }
51219261079SEd Maste   for (i = p;i < p+p-1;++i) {
51319261079SEd Maste     result = 0;
51419261079SEd Maste     for (j = i-p+1;j < p;++j) result = F3_freeze(result+f[j]*g[i-j]);
51519261079SEd Maste     fg[i] = result;
51619261079SEd Maste   }
51719261079SEd Maste 
51819261079SEd Maste   for (i = p+p-2;i >= p;--i) {
51919261079SEd Maste     fg[i-p] = F3_freeze(fg[i-p]+fg[i]);
52019261079SEd Maste     fg[i-p+1] = F3_freeze(fg[i-p+1]+fg[i]);
52119261079SEd Maste   }
52219261079SEd Maste 
52319261079SEd Maste   for (i = 0;i < p;++i) h[i] = fg[i];
52419261079SEd Maste }
52519261079SEd Maste 
52619261079SEd Maste /* returns 0 if recip succeeded; else -1 */
R3_recip(small * out,const small * in)52719261079SEd Maste static int R3_recip(small *out,const small *in)
52819261079SEd Maste {
52919261079SEd Maste   small f[p+1],g[p+1],v[p+1],r[p+1];
53019261079SEd Maste   int i,loop,delta;
53119261079SEd Maste   int sign,swap,t;
53219261079SEd Maste 
53319261079SEd Maste   for (i = 0;i < p+1;++i) v[i] = 0;
53419261079SEd Maste   for (i = 0;i < p+1;++i) r[i] = 0;
53519261079SEd Maste   r[0] = 1;
53619261079SEd Maste   for (i = 0;i < p;++i) f[i] = 0;
53719261079SEd Maste   f[0] = 1; f[p-1] = f[p] = -1;
53819261079SEd Maste   for (i = 0;i < p;++i) g[p-1-i] = in[i];
53919261079SEd Maste   g[p] = 0;
54019261079SEd Maste 
54119261079SEd Maste   delta = 1;
54219261079SEd Maste 
54319261079SEd Maste   for (loop = 0;loop < 2*p-1;++loop) {
54419261079SEd Maste     for (i = p;i > 0;--i) v[i] = v[i-1];
54519261079SEd Maste     v[0] = 0;
54619261079SEd Maste 
54719261079SEd Maste     sign = -g[0]*f[0];
54819261079SEd Maste     swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]);
54919261079SEd Maste     delta ^= swap&(delta^-delta);
55019261079SEd Maste     delta += 1;
55119261079SEd Maste 
55219261079SEd Maste     for (i = 0;i < p+1;++i) {
55319261079SEd Maste       t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t;
55419261079SEd Maste       t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t;
55519261079SEd Maste     }
55619261079SEd Maste 
55719261079SEd Maste     for (i = 0;i < p+1;++i) g[i] = F3_freeze(g[i]+sign*f[i]);
55819261079SEd Maste     for (i = 0;i < p+1;++i) r[i] = F3_freeze(r[i]+sign*v[i]);
55919261079SEd Maste 
56019261079SEd Maste     for (i = 0;i < p;++i) g[i] = g[i+1];
56119261079SEd Maste     g[p] = 0;
56219261079SEd Maste   }
56319261079SEd Maste 
56419261079SEd Maste   sign = f[0];
56519261079SEd Maste   for (i = 0;i < p;++i) out[i] = sign*v[p-1-i];
56619261079SEd Maste 
56719261079SEd Maste   return int16_nonzero_mask(delta);
56819261079SEd Maste }
56919261079SEd Maste 
57019261079SEd Maste #endif
57119261079SEd Maste 
57219261079SEd Maste /* ----- polynomials mod q */
57319261079SEd Maste 
57419261079SEd Maste /* h = f*g in the ring Rq */
Rq_mult_small(Fq * h,const Fq * f,const small * g)57519261079SEd Maste static void Rq_mult_small(Fq *h,const Fq *f,const small *g)
57619261079SEd Maste {
57719261079SEd Maste   Fq fg[p+p-1];
57819261079SEd Maste   Fq result;
57919261079SEd Maste   int i,j;
58019261079SEd Maste 
58119261079SEd Maste   for (i = 0;i < p;++i) {
58219261079SEd Maste     result = 0;
58319261079SEd Maste     for (j = 0;j <= i;++j) result = Fq_freeze(result+f[j]*(int32)g[i-j]);
58419261079SEd Maste     fg[i] = result;
58519261079SEd Maste   }
58619261079SEd Maste   for (i = p;i < p+p-1;++i) {
58719261079SEd Maste     result = 0;
58819261079SEd Maste     for (j = i-p+1;j < p;++j) result = Fq_freeze(result+f[j]*(int32)g[i-j]);
58919261079SEd Maste     fg[i] = result;
59019261079SEd Maste   }
59119261079SEd Maste 
59219261079SEd Maste   for (i = p+p-2;i >= p;--i) {
59319261079SEd Maste     fg[i-p] = Fq_freeze(fg[i-p]+fg[i]);
59419261079SEd Maste     fg[i-p+1] = Fq_freeze(fg[i-p+1]+fg[i]);
59519261079SEd Maste   }
59619261079SEd Maste 
59719261079SEd Maste   for (i = 0;i < p;++i) h[i] = fg[i];
59819261079SEd Maste }
59919261079SEd Maste 
60019261079SEd Maste #ifndef LPR
60119261079SEd Maste 
60219261079SEd Maste /* h = 3f in Rq */
Rq_mult3(Fq * h,const Fq * f)60319261079SEd Maste static void Rq_mult3(Fq *h,const Fq *f)
60419261079SEd Maste {
60519261079SEd Maste   int i;
60619261079SEd Maste 
60719261079SEd Maste   for (i = 0;i < p;++i) h[i] = Fq_freeze(3*f[i]);
60819261079SEd Maste }
60919261079SEd Maste 
61019261079SEd Maste /* out = 1/(3*in) in Rq */
61119261079SEd Maste /* returns 0 if recip succeeded; else -1 */
Rq_recip3(Fq * out,const small * in)61219261079SEd Maste static int Rq_recip3(Fq *out,const small *in)
61319261079SEd Maste {
61419261079SEd Maste   Fq f[p+1],g[p+1],v[p+1],r[p+1];
61519261079SEd Maste   int i,loop,delta;
61619261079SEd Maste   int swap,t;
61719261079SEd Maste   int32 f0,g0;
61819261079SEd Maste   Fq scale;
61919261079SEd Maste 
62019261079SEd Maste   for (i = 0;i < p+1;++i) v[i] = 0;
62119261079SEd Maste   for (i = 0;i < p+1;++i) r[i] = 0;
62219261079SEd Maste   r[0] = Fq_recip(3);
62319261079SEd Maste   for (i = 0;i < p;++i) f[i] = 0;
62419261079SEd Maste   f[0] = 1; f[p-1] = f[p] = -1;
62519261079SEd Maste   for (i = 0;i < p;++i) g[p-1-i] = in[i];
62619261079SEd Maste   g[p] = 0;
62719261079SEd Maste 
62819261079SEd Maste   delta = 1;
62919261079SEd Maste 
63019261079SEd Maste   for (loop = 0;loop < 2*p-1;++loop) {
63119261079SEd Maste     for (i = p;i > 0;--i) v[i] = v[i-1];
63219261079SEd Maste     v[0] = 0;
63319261079SEd Maste 
63419261079SEd Maste     swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]);
63519261079SEd Maste     delta ^= swap&(delta^-delta);
63619261079SEd Maste     delta += 1;
63719261079SEd Maste 
63819261079SEd Maste     for (i = 0;i < p+1;++i) {
63919261079SEd Maste       t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t;
64019261079SEd Maste       t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t;
64119261079SEd Maste     }
64219261079SEd Maste 
64319261079SEd Maste     f0 = f[0];
64419261079SEd Maste     g0 = g[0];
64519261079SEd Maste     for (i = 0;i < p+1;++i) g[i] = Fq_freeze(f0*g[i]-g0*f[i]);
64619261079SEd Maste     for (i = 0;i < p+1;++i) r[i] = Fq_freeze(f0*r[i]-g0*v[i]);
64719261079SEd Maste 
64819261079SEd Maste     for (i = 0;i < p;++i) g[i] = g[i+1];
64919261079SEd Maste     g[p] = 0;
65019261079SEd Maste   }
65119261079SEd Maste 
65219261079SEd Maste   scale = Fq_recip(f[0]);
65319261079SEd Maste   for (i = 0;i < p;++i) out[i] = Fq_freeze(scale*(int32)v[p-1-i]);
65419261079SEd Maste 
65519261079SEd Maste   return int16_nonzero_mask(delta);
65619261079SEd Maste }
65719261079SEd Maste 
65819261079SEd Maste #endif
65919261079SEd Maste 
66019261079SEd Maste /* ----- rounded polynomials mod q */
66119261079SEd Maste 
Round(Fq * out,const Fq * a)66219261079SEd Maste static void Round(Fq *out,const Fq *a)
66319261079SEd Maste {
66419261079SEd Maste   int i;
66519261079SEd Maste   for (i = 0;i < p;++i) out[i] = a[i]-F3_freeze(a[i]);
66619261079SEd Maste }
66719261079SEd Maste 
66819261079SEd Maste /* ----- sorting to generate short polynomial */
66919261079SEd Maste 
Short_fromlist(small * out,const uint32 * in)67019261079SEd Maste static void Short_fromlist(small *out,const uint32 *in)
67119261079SEd Maste {
67219261079SEd Maste   uint32 L[p];
67319261079SEd Maste   int i;
67419261079SEd Maste 
67519261079SEd Maste   for (i = 0;i < w;++i) L[i] = in[i]&(uint32)-2;
67619261079SEd Maste   for (i = w;i < p;++i) L[i] = (in[i]&(uint32)-3)|1;
67719261079SEd Maste   crypto_sort_uint32(L,p);
67819261079SEd Maste   for (i = 0;i < p;++i) out[i] = (L[i]&3)-1;
67919261079SEd Maste }
68019261079SEd Maste 
68119261079SEd Maste /* ----- underlying hash function */
68219261079SEd Maste 
68319261079SEd Maste #define Hash_bytes 32
68419261079SEd Maste 
68519261079SEd Maste /* e.g., b = 0 means out = Hash0(in) */
Hash_prefix(unsigned char * out,int b,const unsigned char * in,int inlen)68619261079SEd Maste static void Hash_prefix(unsigned char *out,int b,const unsigned char *in,int inlen)
68719261079SEd Maste {
68819261079SEd Maste   unsigned char x[inlen+1];
68919261079SEd Maste   unsigned char h[64];
69019261079SEd Maste   int i;
69119261079SEd Maste 
69219261079SEd Maste   x[0] = b;
69319261079SEd Maste   for (i = 0;i < inlen;++i) x[i+1] = in[i];
69419261079SEd Maste   crypto_hash_sha512(h,x,inlen+1);
69519261079SEd Maste   for (i = 0;i < 32;++i) out[i] = h[i];
69619261079SEd Maste }
69719261079SEd Maste 
69819261079SEd Maste /* ----- higher-level randomness */
69919261079SEd Maste 
urandom32(void)70019261079SEd Maste static uint32 urandom32(void)
70119261079SEd Maste {
70219261079SEd Maste   unsigned char c[4];
70319261079SEd Maste   uint32 out[4];
70419261079SEd Maste 
70519261079SEd Maste   randombytes(c,4);
70619261079SEd Maste   out[0] = (uint32)c[0];
70719261079SEd Maste   out[1] = ((uint32)c[1])<<8;
70819261079SEd Maste   out[2] = ((uint32)c[2])<<16;
70919261079SEd Maste   out[3] = ((uint32)c[3])<<24;
71019261079SEd Maste   return out[0]+out[1]+out[2]+out[3];
71119261079SEd Maste }
71219261079SEd Maste 
Short_random(small * out)71319261079SEd Maste static void Short_random(small *out)
71419261079SEd Maste {
71519261079SEd Maste   uint32 L[p];
71619261079SEd Maste   int i;
71719261079SEd Maste 
71819261079SEd Maste   for (i = 0;i < p;++i) L[i] = urandom32();
71919261079SEd Maste   Short_fromlist(out,L);
72019261079SEd Maste }
72119261079SEd Maste 
72219261079SEd Maste #ifndef LPR
72319261079SEd Maste 
Small_random(small * out)72419261079SEd Maste static void Small_random(small *out)
72519261079SEd Maste {
72619261079SEd Maste   int i;
72719261079SEd Maste 
72819261079SEd Maste   for (i = 0;i < p;++i) out[i] = (((urandom32()&0x3fffffff)*3)>>30)-1;
72919261079SEd Maste }
73019261079SEd Maste 
73119261079SEd Maste #endif
73219261079SEd Maste 
73319261079SEd Maste /* ----- Streamlined NTRU Prime Core */
73419261079SEd Maste 
73519261079SEd Maste #ifndef LPR
73619261079SEd Maste 
73719261079SEd Maste /* h,(f,ginv) = KeyGen() */
KeyGen(Fq * h,small * f,small * ginv)73819261079SEd Maste static void KeyGen(Fq *h,small *f,small *ginv)
73919261079SEd Maste {
74019261079SEd Maste   small g[p];
74119261079SEd Maste   Fq finv[p];
74219261079SEd Maste 
74319261079SEd Maste   for (;;) {
74419261079SEd Maste     Small_random(g);
74519261079SEd Maste     if (R3_recip(ginv,g) == 0) break;
74619261079SEd Maste   }
74719261079SEd Maste   Short_random(f);
74819261079SEd Maste   Rq_recip3(finv,f); /* always works */
74919261079SEd Maste   Rq_mult_small(h,finv,g);
75019261079SEd Maste }
75119261079SEd Maste 
75219261079SEd Maste /* c = Encrypt(r,h) */
Encrypt(Fq * c,const small * r,const Fq * h)75319261079SEd Maste static void Encrypt(Fq *c,const small *r,const Fq *h)
75419261079SEd Maste {
75519261079SEd Maste   Fq hr[p];
75619261079SEd Maste 
75719261079SEd Maste   Rq_mult_small(hr,h,r);
75819261079SEd Maste   Round(c,hr);
75919261079SEd Maste }
76019261079SEd Maste 
76119261079SEd Maste /* r = Decrypt(c,(f,ginv)) */
Decrypt(small * r,const Fq * c,const small * f,const small * ginv)76219261079SEd Maste static void Decrypt(small *r,const Fq *c,const small *f,const small *ginv)
76319261079SEd Maste {
76419261079SEd Maste   Fq cf[p];
76519261079SEd Maste   Fq cf3[p];
76619261079SEd Maste   small e[p];
76719261079SEd Maste   small ev[p];
76819261079SEd Maste   int mask;
76919261079SEd Maste   int i;
77019261079SEd Maste 
77119261079SEd Maste   Rq_mult_small(cf,c,f);
77219261079SEd Maste   Rq_mult3(cf3,cf);
77319261079SEd Maste   R3_fromRq(e,cf3);
77419261079SEd Maste   R3_mult(ev,e,ginv);
77519261079SEd Maste 
77619261079SEd Maste   mask = Weightw_mask(ev); /* 0 if weight w, else -1 */
77719261079SEd Maste   for (i = 0;i < w;++i) r[i] = ((ev[i]^1)&~mask)^1;
77819261079SEd Maste   for (i = w;i < p;++i) r[i] = ev[i]&~mask;
77919261079SEd Maste }
78019261079SEd Maste 
78119261079SEd Maste #endif
78219261079SEd Maste 
78319261079SEd Maste /* ----- NTRU LPRime Core */
78419261079SEd Maste 
78519261079SEd Maste #ifdef LPR
78619261079SEd Maste 
78719261079SEd Maste /* (G,A),a = KeyGen(G); leaves G unchanged */
KeyGen(Fq * A,small * a,const Fq * G)78819261079SEd Maste static void KeyGen(Fq *A,small *a,const Fq *G)
78919261079SEd Maste {
79019261079SEd Maste   Fq aG[p];
79119261079SEd Maste 
79219261079SEd Maste   Short_random(a);
79319261079SEd Maste   Rq_mult_small(aG,G,a);
79419261079SEd Maste   Round(A,aG);
79519261079SEd Maste }
79619261079SEd Maste 
79719261079SEd Maste /* B,T = Encrypt(r,(G,A),b) */
Encrypt(Fq * B,int8 * T,const int8 * r,const Fq * G,const Fq * A,const small * b)79819261079SEd Maste static void Encrypt(Fq *B,int8 *T,const int8 *r,const Fq *G,const Fq *A,const small *b)
79919261079SEd Maste {
80019261079SEd Maste   Fq bG[p];
80119261079SEd Maste   Fq bA[p];
80219261079SEd Maste   int i;
80319261079SEd Maste 
80419261079SEd Maste   Rq_mult_small(bG,G,b);
80519261079SEd Maste   Round(B,bG);
80619261079SEd Maste   Rq_mult_small(bA,A,b);
80719261079SEd Maste   for (i = 0;i < I;++i) T[i] = Top(Fq_freeze(bA[i]+r[i]*q12));
80819261079SEd Maste }
80919261079SEd Maste 
81019261079SEd Maste /* r = Decrypt((B,T),a) */
Decrypt(int8 * r,const Fq * B,const int8 * T,const small * a)81119261079SEd Maste static void Decrypt(int8 *r,const Fq *B,const int8 *T,const small *a)
81219261079SEd Maste {
81319261079SEd Maste   Fq aB[p];
81419261079SEd Maste   int i;
81519261079SEd Maste 
81619261079SEd Maste   Rq_mult_small(aB,B,a);
81719261079SEd Maste   for (i = 0;i < I;++i)
81819261079SEd Maste     r[i] = -int16_negative_mask(Fq_freeze(Right(T[i])-aB[i]+4*w+1));
81919261079SEd Maste }
82019261079SEd Maste 
82119261079SEd Maste #endif
82219261079SEd Maste 
82319261079SEd Maste /* ----- encoding I-bit inputs */
82419261079SEd Maste 
82519261079SEd Maste #ifdef LPR
82619261079SEd Maste 
82719261079SEd Maste #define Inputs_bytes (I/8)
82819261079SEd Maste typedef int8 Inputs[I]; /* passed by reference */
82919261079SEd Maste 
Inputs_encode(unsigned char * s,const Inputs r)83019261079SEd Maste static void Inputs_encode(unsigned char *s,const Inputs r)
83119261079SEd Maste {
83219261079SEd Maste   int i;
83319261079SEd Maste   for (i = 0;i < Inputs_bytes;++i) s[i] = 0;
83419261079SEd Maste   for (i = 0;i < I;++i) s[i>>3] |= r[i]<<(i&7);
83519261079SEd Maste }
83619261079SEd Maste 
83719261079SEd Maste #endif
83819261079SEd Maste 
83919261079SEd Maste /* ----- Expand */
84019261079SEd Maste 
84119261079SEd Maste #ifdef LPR
84219261079SEd Maste 
84319261079SEd Maste static const unsigned char aes_nonce[16] = {0};
84419261079SEd Maste 
Expand(uint32 * L,const unsigned char * k)84519261079SEd Maste static void Expand(uint32 *L,const unsigned char *k)
84619261079SEd Maste {
84719261079SEd Maste   int i;
84819261079SEd Maste   crypto_stream_aes256ctr((unsigned char *) L,4*p,aes_nonce,k);
84919261079SEd Maste   for (i = 0;i < p;++i) {
85019261079SEd Maste     uint32 L0 = ((unsigned char *) L)[4*i];
85119261079SEd Maste     uint32 L1 = ((unsigned char *) L)[4*i+1];
85219261079SEd Maste     uint32 L2 = ((unsigned char *) L)[4*i+2];
85319261079SEd Maste     uint32 L3 = ((unsigned char *) L)[4*i+3];
85419261079SEd Maste     L[i] = L0+(L1<<8)+(L2<<16)+(L3<<24);
85519261079SEd Maste   }
85619261079SEd Maste }
85719261079SEd Maste 
85819261079SEd Maste #endif
85919261079SEd Maste 
86019261079SEd Maste /* ----- Seeds */
86119261079SEd Maste 
86219261079SEd Maste #ifdef LPR
86319261079SEd Maste 
86419261079SEd Maste #define Seeds_bytes 32
86519261079SEd Maste 
Seeds_random(unsigned char * s)86619261079SEd Maste static void Seeds_random(unsigned char *s)
86719261079SEd Maste {
86819261079SEd Maste   randombytes(s,Seeds_bytes);
86919261079SEd Maste }
87019261079SEd Maste 
87119261079SEd Maste #endif
87219261079SEd Maste 
87319261079SEd Maste /* ----- Generator, HashShort */
87419261079SEd Maste 
87519261079SEd Maste #ifdef LPR
87619261079SEd Maste 
87719261079SEd Maste /* G = Generator(k) */
Generator(Fq * G,const unsigned char * k)87819261079SEd Maste static void Generator(Fq *G,const unsigned char *k)
87919261079SEd Maste {
88019261079SEd Maste   uint32 L[p];
88119261079SEd Maste   int i;
88219261079SEd Maste 
88319261079SEd Maste   Expand(L,k);
88419261079SEd Maste   for (i = 0;i < p;++i) G[i] = uint32_mod_uint14(L[i],q)-q12;
88519261079SEd Maste }
88619261079SEd Maste 
88719261079SEd Maste /* out = HashShort(r) */
HashShort(small * out,const Inputs r)88819261079SEd Maste static void HashShort(small *out,const Inputs r)
88919261079SEd Maste {
89019261079SEd Maste   unsigned char s[Inputs_bytes];
89119261079SEd Maste   unsigned char h[Hash_bytes];
89219261079SEd Maste   uint32 L[p];
89319261079SEd Maste 
89419261079SEd Maste   Inputs_encode(s,r);
89519261079SEd Maste   Hash_prefix(h,5,s,sizeof s);
89619261079SEd Maste   Expand(L,h);
89719261079SEd Maste   Short_fromlist(out,L);
89819261079SEd Maste }
89919261079SEd Maste 
90019261079SEd Maste #endif
90119261079SEd Maste 
90219261079SEd Maste /* ----- NTRU LPRime Expand */
90319261079SEd Maste 
90419261079SEd Maste #ifdef LPR
90519261079SEd Maste 
90619261079SEd Maste /* (S,A),a = XKeyGen() */
XKeyGen(unsigned char * S,Fq * A,small * a)90719261079SEd Maste static void XKeyGen(unsigned char *S,Fq *A,small *a)
90819261079SEd Maste {
90919261079SEd Maste   Fq G[p];
91019261079SEd Maste 
91119261079SEd Maste   Seeds_random(S);
91219261079SEd Maste   Generator(G,S);
91319261079SEd Maste   KeyGen(A,a,G);
91419261079SEd Maste }
91519261079SEd Maste 
91619261079SEd Maste /* B,T = XEncrypt(r,(S,A)) */
XEncrypt(Fq * B,int8 * T,const int8 * r,const unsigned char * S,const Fq * A)91719261079SEd Maste static void XEncrypt(Fq *B,int8 *T,const int8 *r,const unsigned char *S,const Fq *A)
91819261079SEd Maste {
91919261079SEd Maste   Fq G[p];
92019261079SEd Maste   small b[p];
92119261079SEd Maste 
92219261079SEd Maste   Generator(G,S);
92319261079SEd Maste   HashShort(b,r);
92419261079SEd Maste   Encrypt(B,T,r,G,A,b);
92519261079SEd Maste }
92619261079SEd Maste 
92719261079SEd Maste #define XDecrypt Decrypt
92819261079SEd Maste 
92919261079SEd Maste #endif
93019261079SEd Maste 
93119261079SEd Maste /* ----- encoding small polynomials (including short polynomials) */
93219261079SEd Maste 
93319261079SEd Maste #define Small_bytes ((p+3)/4)
93419261079SEd Maste 
93519261079SEd Maste /* these are the only functions that rely on p mod 4 = 1 */
93619261079SEd Maste 
Small_encode(unsigned char * s,const small * f)93719261079SEd Maste static void Small_encode(unsigned char *s,const small *f)
93819261079SEd Maste {
93919261079SEd Maste   small x;
94019261079SEd Maste   int i;
94119261079SEd Maste 
94219261079SEd Maste   for (i = 0;i < p/4;++i) {
94319261079SEd Maste     x = *f++ + 1;
94419261079SEd Maste     x += (*f++ + 1)<<2;
94519261079SEd Maste     x += (*f++ + 1)<<4;
94619261079SEd Maste     x += (*f++ + 1)<<6;
94719261079SEd Maste     *s++ = x;
94819261079SEd Maste   }
94919261079SEd Maste   x = *f++ + 1;
95019261079SEd Maste   *s++ = x;
95119261079SEd Maste }
95219261079SEd Maste 
Small_decode(small * f,const unsigned char * s)95319261079SEd Maste static void Small_decode(small *f,const unsigned char *s)
95419261079SEd Maste {
95519261079SEd Maste   unsigned char x;
95619261079SEd Maste   int i;
95719261079SEd Maste 
95819261079SEd Maste   for (i = 0;i < p/4;++i) {
95919261079SEd Maste     x = *s++;
96019261079SEd Maste     *f++ = ((small)(x&3))-1; x >>= 2;
96119261079SEd Maste     *f++ = ((small)(x&3))-1; x >>= 2;
96219261079SEd Maste     *f++ = ((small)(x&3))-1; x >>= 2;
96319261079SEd Maste     *f++ = ((small)(x&3))-1;
96419261079SEd Maste   }
96519261079SEd Maste   x = *s++;
96619261079SEd Maste   *f++ = ((small)(x&3))-1;
96719261079SEd Maste }
96819261079SEd Maste 
96919261079SEd Maste /* ----- encoding general polynomials */
97019261079SEd Maste 
97119261079SEd Maste #ifndef LPR
97219261079SEd Maste 
Rq_encode(unsigned char * s,const Fq * r)97319261079SEd Maste static void Rq_encode(unsigned char *s,const Fq *r)
97419261079SEd Maste {
97519261079SEd Maste   uint16 R[p],M[p];
97619261079SEd Maste   int i;
97719261079SEd Maste 
97819261079SEd Maste   for (i = 0;i < p;++i) R[i] = r[i]+q12;
97919261079SEd Maste   for (i = 0;i < p;++i) M[i] = q;
98019261079SEd Maste   Encode(s,R,M,p);
98119261079SEd Maste }
98219261079SEd Maste 
Rq_decode(Fq * r,const unsigned char * s)98319261079SEd Maste static void Rq_decode(Fq *r,const unsigned char *s)
98419261079SEd Maste {
98519261079SEd Maste   uint16 R[p],M[p];
98619261079SEd Maste   int i;
98719261079SEd Maste 
98819261079SEd Maste   for (i = 0;i < p;++i) M[i] = q;
98919261079SEd Maste   Decode(R,s,M,p);
99019261079SEd Maste   for (i = 0;i < p;++i) r[i] = ((Fq)R[i])-q12;
99119261079SEd Maste }
99219261079SEd Maste 
99319261079SEd Maste #endif
99419261079SEd Maste 
99519261079SEd Maste /* ----- encoding rounded polynomials */
99619261079SEd Maste 
Rounded_encode(unsigned char * s,const Fq * r)99719261079SEd Maste static void Rounded_encode(unsigned char *s,const Fq *r)
99819261079SEd Maste {
99919261079SEd Maste   uint16 R[p],M[p];
100019261079SEd Maste   int i;
100119261079SEd Maste 
100219261079SEd Maste   for (i = 0;i < p;++i) R[i] = ((r[i]+q12)*10923)>>15;
100319261079SEd Maste   for (i = 0;i < p;++i) M[i] = (q+2)/3;
100419261079SEd Maste   Encode(s,R,M,p);
100519261079SEd Maste }
100619261079SEd Maste 
Rounded_decode(Fq * r,const unsigned char * s)100719261079SEd Maste static void Rounded_decode(Fq *r,const unsigned char *s)
100819261079SEd Maste {
100919261079SEd Maste   uint16 R[p],M[p];
101019261079SEd Maste   int i;
101119261079SEd Maste 
101219261079SEd Maste   for (i = 0;i < p;++i) M[i] = (q+2)/3;
101319261079SEd Maste   Decode(R,s,M,p);
101419261079SEd Maste   for (i = 0;i < p;++i) r[i] = R[i]*3-q12;
101519261079SEd Maste }
101619261079SEd Maste 
101719261079SEd Maste /* ----- encoding top polynomials */
101819261079SEd Maste 
101919261079SEd Maste #ifdef LPR
102019261079SEd Maste 
102119261079SEd Maste #define Top_bytes (I/2)
102219261079SEd Maste 
Top_encode(unsigned char * s,const int8 * T)102319261079SEd Maste static void Top_encode(unsigned char *s,const int8 *T)
102419261079SEd Maste {
102519261079SEd Maste   int i;
102619261079SEd Maste   for (i = 0;i < Top_bytes;++i)
102719261079SEd Maste     s[i] = T[2*i]+(T[2*i+1]<<4);
102819261079SEd Maste }
102919261079SEd Maste 
Top_decode(int8 * T,const unsigned char * s)103019261079SEd Maste static void Top_decode(int8 *T,const unsigned char *s)
103119261079SEd Maste {
103219261079SEd Maste   int i;
103319261079SEd Maste   for (i = 0;i < Top_bytes;++i) {
103419261079SEd Maste     T[2*i] = s[i]&15;
103519261079SEd Maste     T[2*i+1] = s[i]>>4;
103619261079SEd Maste   }
103719261079SEd Maste }
103819261079SEd Maste 
103919261079SEd Maste #endif
104019261079SEd Maste 
104119261079SEd Maste /* ----- Streamlined NTRU Prime Core plus encoding */
104219261079SEd Maste 
104319261079SEd Maste #ifndef LPR
104419261079SEd Maste 
104519261079SEd Maste typedef small Inputs[p]; /* passed by reference */
104619261079SEd Maste #define Inputs_random Short_random
104719261079SEd Maste #define Inputs_encode Small_encode
104819261079SEd Maste #define Inputs_bytes Small_bytes
104919261079SEd Maste 
105019261079SEd Maste #define Ciphertexts_bytes Rounded_bytes
105119261079SEd Maste #define SecretKeys_bytes (2*Small_bytes)
105219261079SEd Maste #define PublicKeys_bytes Rq_bytes
105319261079SEd Maste 
105419261079SEd Maste /* pk,sk = ZKeyGen() */
ZKeyGen(unsigned char * pk,unsigned char * sk)105519261079SEd Maste static void ZKeyGen(unsigned char *pk,unsigned char *sk)
105619261079SEd Maste {
105719261079SEd Maste   Fq h[p];
105819261079SEd Maste   small f[p],v[p];
105919261079SEd Maste 
106019261079SEd Maste   KeyGen(h,f,v);
106119261079SEd Maste   Rq_encode(pk,h);
106219261079SEd Maste   Small_encode(sk,f); sk += Small_bytes;
106319261079SEd Maste   Small_encode(sk,v);
106419261079SEd Maste }
106519261079SEd Maste 
106619261079SEd Maste /* C = ZEncrypt(r,pk) */
ZEncrypt(unsigned char * C,const Inputs r,const unsigned char * pk)106719261079SEd Maste static void ZEncrypt(unsigned char *C,const Inputs r,const unsigned char *pk)
106819261079SEd Maste {
106919261079SEd Maste   Fq h[p];
107019261079SEd Maste   Fq c[p];
107119261079SEd Maste   Rq_decode(h,pk);
107219261079SEd Maste   Encrypt(c,r,h);
107319261079SEd Maste   Rounded_encode(C,c);
107419261079SEd Maste }
107519261079SEd Maste 
107619261079SEd Maste /* r = ZDecrypt(C,sk) */
ZDecrypt(Inputs r,const unsigned char * C,const unsigned char * sk)107719261079SEd Maste static void ZDecrypt(Inputs r,const unsigned char *C,const unsigned char *sk)
107819261079SEd Maste {
107919261079SEd Maste   small f[p],v[p];
108019261079SEd Maste   Fq c[p];
108119261079SEd Maste 
108219261079SEd Maste   Small_decode(f,sk); sk += Small_bytes;
108319261079SEd Maste   Small_decode(v,sk);
108419261079SEd Maste   Rounded_decode(c,C);
108519261079SEd Maste   Decrypt(r,c,f,v);
108619261079SEd Maste }
108719261079SEd Maste 
108819261079SEd Maste #endif
108919261079SEd Maste 
109019261079SEd Maste /* ----- NTRU LPRime Expand plus encoding */
109119261079SEd Maste 
109219261079SEd Maste #ifdef LPR
109319261079SEd Maste 
109419261079SEd Maste #define Ciphertexts_bytes (Rounded_bytes+Top_bytes)
109519261079SEd Maste #define SecretKeys_bytes Small_bytes
109619261079SEd Maste #define PublicKeys_bytes (Seeds_bytes+Rounded_bytes)
109719261079SEd Maste 
Inputs_random(Inputs r)109819261079SEd Maste static void Inputs_random(Inputs r)
109919261079SEd Maste {
110019261079SEd Maste   unsigned char s[Inputs_bytes];
110119261079SEd Maste   int i;
110219261079SEd Maste 
110319261079SEd Maste   randombytes(s,sizeof s);
110419261079SEd Maste   for (i = 0;i < I;++i) r[i] = 1&(s[i>>3]>>(i&7));
110519261079SEd Maste }
110619261079SEd Maste 
110719261079SEd Maste /* pk,sk = ZKeyGen() */
ZKeyGen(unsigned char * pk,unsigned char * sk)110819261079SEd Maste static void ZKeyGen(unsigned char *pk,unsigned char *sk)
110919261079SEd Maste {
111019261079SEd Maste   Fq A[p];
111119261079SEd Maste   small a[p];
111219261079SEd Maste 
111319261079SEd Maste   XKeyGen(pk,A,a); pk += Seeds_bytes;
111419261079SEd Maste   Rounded_encode(pk,A);
111519261079SEd Maste   Small_encode(sk,a);
111619261079SEd Maste }
111719261079SEd Maste 
111819261079SEd Maste /* c = ZEncrypt(r,pk) */
ZEncrypt(unsigned char * c,const Inputs r,const unsigned char * pk)111919261079SEd Maste static void ZEncrypt(unsigned char *c,const Inputs r,const unsigned char *pk)
112019261079SEd Maste {
112119261079SEd Maste   Fq A[p];
112219261079SEd Maste   Fq B[p];
112319261079SEd Maste   int8 T[I];
112419261079SEd Maste 
112519261079SEd Maste   Rounded_decode(A,pk+Seeds_bytes);
112619261079SEd Maste   XEncrypt(B,T,r,pk,A);
112719261079SEd Maste   Rounded_encode(c,B); c += Rounded_bytes;
112819261079SEd Maste   Top_encode(c,T);
112919261079SEd Maste }
113019261079SEd Maste 
113119261079SEd Maste /* r = ZDecrypt(C,sk) */
ZDecrypt(Inputs r,const unsigned char * c,const unsigned char * sk)113219261079SEd Maste static void ZDecrypt(Inputs r,const unsigned char *c,const unsigned char *sk)
113319261079SEd Maste {
113419261079SEd Maste   small a[p];
113519261079SEd Maste   Fq B[p];
113619261079SEd Maste   int8 T[I];
113719261079SEd Maste 
113819261079SEd Maste   Small_decode(a,sk);
113919261079SEd Maste   Rounded_decode(B,c);
114019261079SEd Maste   Top_decode(T,c+Rounded_bytes);
114119261079SEd Maste   XDecrypt(r,B,T,a);
114219261079SEd Maste }
114319261079SEd Maste 
114419261079SEd Maste #endif
114519261079SEd Maste 
114619261079SEd Maste /* ----- confirmation hash */
114719261079SEd Maste 
114819261079SEd Maste #define Confirm_bytes 32
114919261079SEd Maste 
115019261079SEd Maste /* h = HashConfirm(r,pk,cache); cache is Hash4(pk) */
HashConfirm(unsigned char * h,const unsigned char * r,const unsigned char * pk,const unsigned char * cache)115119261079SEd Maste static void HashConfirm(unsigned char *h,const unsigned char *r,const unsigned char *pk,const unsigned char *cache)
115219261079SEd Maste {
115319261079SEd Maste #ifndef LPR
115419261079SEd Maste   unsigned char x[Hash_bytes*2];
115519261079SEd Maste   int i;
115619261079SEd Maste 
115719261079SEd Maste   Hash_prefix(x,3,r,Inputs_bytes);
115819261079SEd Maste   for (i = 0;i < Hash_bytes;++i) x[Hash_bytes+i] = cache[i];
115919261079SEd Maste #else
116019261079SEd Maste   unsigned char x[Inputs_bytes+Hash_bytes];
116119261079SEd Maste   int i;
116219261079SEd Maste 
116319261079SEd Maste   for (i = 0;i < Inputs_bytes;++i) x[i] = r[i];
116419261079SEd Maste   for (i = 0;i < Hash_bytes;++i) x[Inputs_bytes+i] = cache[i];
116519261079SEd Maste #endif
116619261079SEd Maste   Hash_prefix(h,2,x,sizeof x);
116719261079SEd Maste }
116819261079SEd Maste 
116919261079SEd Maste /* ----- session-key hash */
117019261079SEd Maste 
117119261079SEd Maste /* k = HashSession(b,y,z) */
HashSession(unsigned char * k,int b,const unsigned char * y,const unsigned char * z)117219261079SEd Maste static void HashSession(unsigned char *k,int b,const unsigned char *y,const unsigned char *z)
117319261079SEd Maste {
117419261079SEd Maste #ifndef LPR
117519261079SEd Maste   unsigned char x[Hash_bytes+Ciphertexts_bytes+Confirm_bytes];
117619261079SEd Maste   int i;
117719261079SEd Maste 
117819261079SEd Maste   Hash_prefix(x,3,y,Inputs_bytes);
117919261079SEd Maste   for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Hash_bytes+i] = z[i];
118019261079SEd Maste #else
118119261079SEd Maste   unsigned char x[Inputs_bytes+Ciphertexts_bytes+Confirm_bytes];
118219261079SEd Maste   int i;
118319261079SEd Maste 
118419261079SEd Maste   for (i = 0;i < Inputs_bytes;++i) x[i] = y[i];
118519261079SEd Maste   for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Inputs_bytes+i] = z[i];
118619261079SEd Maste #endif
118719261079SEd Maste   Hash_prefix(k,b,x,sizeof x);
118819261079SEd Maste }
118919261079SEd Maste 
119019261079SEd Maste /* ----- Streamlined NTRU Prime and NTRU LPRime */
119119261079SEd Maste 
119219261079SEd Maste /* pk,sk = KEM_KeyGen() */
KEM_KeyGen(unsigned char * pk,unsigned char * sk)119319261079SEd Maste static void KEM_KeyGen(unsigned char *pk,unsigned char *sk)
119419261079SEd Maste {
119519261079SEd Maste   int i;
119619261079SEd Maste 
119719261079SEd Maste   ZKeyGen(pk,sk); sk += SecretKeys_bytes;
119819261079SEd Maste   for (i = 0;i < PublicKeys_bytes;++i) *sk++ = pk[i];
119919261079SEd Maste   randombytes(sk,Inputs_bytes); sk += Inputs_bytes;
120019261079SEd Maste   Hash_prefix(sk,4,pk,PublicKeys_bytes);
120119261079SEd Maste }
120219261079SEd Maste 
120319261079SEd Maste /* c,r_enc = Hide(r,pk,cache); cache is Hash4(pk) */
Hide(unsigned char * c,unsigned char * r_enc,const Inputs r,const unsigned char * pk,const unsigned char * cache)120419261079SEd Maste static void Hide(unsigned char *c,unsigned char *r_enc,const Inputs r,const unsigned char *pk,const unsigned char *cache)
120519261079SEd Maste {
120619261079SEd Maste   Inputs_encode(r_enc,r);
120719261079SEd Maste   ZEncrypt(c,r,pk); c += Ciphertexts_bytes;
120819261079SEd Maste   HashConfirm(c,r_enc,pk,cache);
120919261079SEd Maste }
121019261079SEd Maste 
121119261079SEd Maste /* c,k = Encap(pk) */
Encap(unsigned char * c,unsigned char * k,const unsigned char * pk)121219261079SEd Maste static void Encap(unsigned char *c,unsigned char *k,const unsigned char *pk)
121319261079SEd Maste {
121419261079SEd Maste   Inputs r;
121519261079SEd Maste   unsigned char r_enc[Inputs_bytes];
121619261079SEd Maste   unsigned char cache[Hash_bytes];
121719261079SEd Maste 
121819261079SEd Maste   Hash_prefix(cache,4,pk,PublicKeys_bytes);
121919261079SEd Maste   Inputs_random(r);
122019261079SEd Maste   Hide(c,r_enc,r,pk,cache);
122119261079SEd Maste   HashSession(k,1,r_enc,c);
122219261079SEd Maste }
122319261079SEd Maste 
122419261079SEd Maste /* 0 if matching ciphertext+confirm, else -1 */
Ciphertexts_diff_mask(const unsigned char * c,const unsigned char * c2)122519261079SEd Maste static int Ciphertexts_diff_mask(const unsigned char *c,const unsigned char *c2)
122619261079SEd Maste {
122719261079SEd Maste   uint16 differentbits = 0;
122819261079SEd Maste   int len = Ciphertexts_bytes+Confirm_bytes;
122919261079SEd Maste 
123019261079SEd Maste   while (len-- > 0) differentbits |= (*c++)^(*c2++);
123119261079SEd Maste   return (1&((differentbits-1)>>8))-1;
123219261079SEd Maste }
123319261079SEd Maste 
123419261079SEd Maste /* k = Decap(c,sk) */
Decap(unsigned char * k,const unsigned char * c,const unsigned char * sk)123519261079SEd Maste static void Decap(unsigned char *k,const unsigned char *c,const unsigned char *sk)
123619261079SEd Maste {
123719261079SEd Maste   const unsigned char *pk = sk + SecretKeys_bytes;
123819261079SEd Maste   const unsigned char *rho = pk + PublicKeys_bytes;
123919261079SEd Maste   const unsigned char *cache = rho + Inputs_bytes;
124019261079SEd Maste   Inputs r;
124119261079SEd Maste   unsigned char r_enc[Inputs_bytes];
124219261079SEd Maste   unsigned char cnew[Ciphertexts_bytes+Confirm_bytes];
124319261079SEd Maste   int mask;
124419261079SEd Maste   int i;
124519261079SEd Maste 
124619261079SEd Maste   ZDecrypt(r,c,sk);
124719261079SEd Maste   Hide(cnew,r_enc,r,pk,cache);
124819261079SEd Maste   mask = Ciphertexts_diff_mask(c,cnew);
124919261079SEd Maste   for (i = 0;i < Inputs_bytes;++i) r_enc[i] ^= mask&(r_enc[i]^rho[i]);
125019261079SEd Maste   HashSession(k,1+mask,r_enc,c);
125119261079SEd Maste }
125219261079SEd Maste 
125319261079SEd Maste /* ----- crypto_kem API */
125419261079SEd Maste 
125519261079SEd Maste 
crypto_kem_sntrup761_keypair(unsigned char * pk,unsigned char * sk)125619261079SEd Maste int crypto_kem_sntrup761_keypair(unsigned char *pk,unsigned char *sk)
125719261079SEd Maste {
125819261079SEd Maste   KEM_KeyGen(pk,sk);
125919261079SEd Maste   return 0;
126019261079SEd Maste }
126119261079SEd Maste 
crypto_kem_sntrup761_enc(unsigned char * c,unsigned char * k,const unsigned char * pk)126219261079SEd Maste int crypto_kem_sntrup761_enc(unsigned char *c,unsigned char *k,const unsigned char *pk)
126319261079SEd Maste {
126419261079SEd Maste   Encap(c,k,pk);
126519261079SEd Maste   return 0;
126619261079SEd Maste }
126719261079SEd Maste 
crypto_kem_sntrup761_dec(unsigned char * k,const unsigned char * c,const unsigned char * sk)126819261079SEd Maste int crypto_kem_sntrup761_dec(unsigned char *k,const unsigned char *c,const unsigned char *sk)
126919261079SEd Maste {
127019261079SEd Maste   Decap(k,c,sk);
127119261079SEd Maste   return 0;
127219261079SEd Maste }
127319261079SEd Maste #endif /* USE_SNTRUP761X25519 */
1274