fe25519.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. #define WINDOWSIZE 1 /* Should be 1,2, or 4 */
  2. #define WINDOWMASK ((1<<WINDOWSIZE)-1)
  3. #include "fe25519.h"
  4. static crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
  5. {
  6. crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */
  7. x -= 1; /* 4294967295: yes; 0..65534: no */
  8. x >>= 31; /* 1: yes; 0: no */
  9. return x;
  10. }
  11. static crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
  12. {
  13. unsigned int x = a;
  14. x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */
  15. x >>= 31; /* 0: yes; 1: no */
  16. x ^= 1; /* 1: yes; 0: no */
  17. return x;
  18. }
  19. static crypto_uint32 times19(crypto_uint32 a)
  20. {
  21. return (a << 4) + (a << 1) + a;
  22. }
  23. static crypto_uint32 times38(crypto_uint32 a)
  24. {
  25. return (a << 5) + (a << 2) + (a << 1);
  26. }
  27. static void reduce_add_sub(fe25519 *r)
  28. {
  29. crypto_uint32 t;
  30. int i,rep;
  31. for(rep=0;rep<4;rep++)
  32. {
  33. t = r->v[31] >> 7;
  34. r->v[31] &= 127;
  35. t = times19(t);
  36. r->v[0] += t;
  37. for(i=0;i<31;i++)
  38. {
  39. t = r->v[i] >> 8;
  40. r->v[i+1] += t;
  41. r->v[i] &= 255;
  42. }
  43. }
  44. }
  45. static void reduce_mul(fe25519 *r)
  46. {
  47. crypto_uint32 t;
  48. int i,rep;
  49. for(rep=0;rep<2;rep++)
  50. {
  51. t = r->v[31] >> 7;
  52. r->v[31] &= 127;
  53. t = times19(t);
  54. r->v[0] += t;
  55. for(i=0;i<31;i++)
  56. {
  57. t = r->v[i] >> 8;
  58. r->v[i+1] += t;
  59. r->v[i] &= 255;
  60. }
  61. }
  62. }
  63. /* reduction modulo 2^255-19 */
  64. void fe25519_freeze(fe25519 *r)
  65. {
  66. int i;
  67. crypto_uint32 m = equal(r->v[31],127);
  68. for(i=30;i>0;i--)
  69. m &= equal(r->v[i],255);
  70. m &= ge(r->v[0],237);
  71. m = -m;
  72. r->v[31] -= m&127;
  73. for(i=30;i>0;i--)
  74. r->v[i] -= m&255;
  75. r->v[0] -= m&237;
  76. }
  77. void fe25519_unpack(fe25519 *r, const unsigned char x[32])
  78. {
  79. int i;
  80. for(i=0;i<32;i++) r->v[i] = x[i];
  81. r->v[31] &= 127;
  82. }
  83. /* Assumes input x being reduced below 2^255 */
  84. void fe25519_pack(unsigned char r[32], const fe25519 *x)
  85. {
  86. int i;
  87. fe25519 y = *x;
  88. fe25519_freeze(&y);
  89. for(i=0;i<32;i++)
  90. r[i] = y.v[i];
  91. }
  92. int fe25519_iszero(const fe25519 *x)
  93. {
  94. int i;
  95. int r;
  96. fe25519 t = *x;
  97. fe25519_freeze(&t);
  98. r = equal(t.v[0],0);
  99. for(i=1;i<32;i++)
  100. r &= equal(t.v[i],0);
  101. return r;
  102. }
  103. int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
  104. {
  105. int i;
  106. fe25519 t1 = *x;
  107. fe25519 t2 = *y;
  108. fe25519_freeze(&t1);
  109. fe25519_freeze(&t2);
  110. for(i=0;i<32;i++)
  111. if(t1.v[i] != t2.v[i]) return 0;
  112. return 1;
  113. }
  114. void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
  115. {
  116. int i;
  117. crypto_uint32 mask = b;
  118. mask = -mask;
  119. for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
  120. }
  121. unsigned char fe25519_getparity(const fe25519 *x)
  122. {
  123. fe25519 t = *x;
  124. fe25519_freeze(&t);
  125. return t.v[0] & 1;
  126. }
  127. void fe25519_setone(fe25519 *r)
  128. {
  129. int i;
  130. r->v[0] = 1;
  131. for(i=1;i<32;i++) r->v[i]=0;
  132. }
  133. void fe25519_setzero(fe25519 *r)
  134. {
  135. int i;
  136. for(i=0;i<32;i++) r->v[i]=0;
  137. }
  138. void fe25519_neg(fe25519 *r, const fe25519 *x)
  139. {
  140. fe25519 t;
  141. int i;
  142. for(i=0;i<32;i++) t.v[i]=x->v[i];
  143. fe25519_setzero(r);
  144. fe25519_sub(r, r, &t);
  145. }
  146. void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
  147. {
  148. int i;
  149. for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i];
  150. reduce_add_sub(r);
  151. }
  152. void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
  153. {
  154. int i;
  155. crypto_uint32 t[32];
  156. t[0] = x->v[0] + 0x1da;
  157. t[31] = x->v[31] + 0xfe;
  158. for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe;
  159. for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i];
  160. reduce_add_sub(r);
  161. }
  162. void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
  163. {
  164. int i,j;
  165. crypto_uint32 t[63];
  166. for(i=0;i<63;i++)t[i] = 0;
  167. for(i=0;i<32;i++)
  168. for(j=0;j<32;j++)
  169. t[i+j] += x->v[i] * y->v[j];
  170. for(i=32;i<63;i++)
  171. r->v[i-32] = t[i-32] + times38(t[i]);
  172. r->v[31] = t[31]; /* result now in r[0]...r[31] */
  173. reduce_mul(r);
  174. }
  175. void fe25519_square(fe25519 *r, const fe25519 *x)
  176. {
  177. fe25519_mul(r, x, x);
  178. }
  179. void fe25519_invert(fe25519 *r, const fe25519 *x)
  180. {
  181. fe25519 z2;
  182. fe25519 z9;
  183. fe25519 z11;
  184. fe25519 z2_5_0;
  185. fe25519 z2_10_0;
  186. fe25519 z2_20_0;
  187. fe25519 z2_50_0;
  188. fe25519 z2_100_0;
  189. fe25519 t0;
  190. fe25519 t1;
  191. int i;
  192. /* 2 */ fe25519_square(&z2,x);
  193. /* 4 */ fe25519_square(&t1,&z2);
  194. /* 8 */ fe25519_square(&t0,&t1);
  195. /* 9 */ fe25519_mul(&z9,&t0,x);
  196. /* 11 */ fe25519_mul(&z11,&z9,&z2);
  197. /* 22 */ fe25519_square(&t0,&z11);
  198. /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9);
  199. /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0);
  200. /* 2^7 - 2^2 */ fe25519_square(&t1,&t0);
  201. /* 2^8 - 2^3 */ fe25519_square(&t0,&t1);
  202. /* 2^9 - 2^4 */ fe25519_square(&t1,&t0);
  203. /* 2^10 - 2^5 */ fe25519_square(&t0,&t1);
  204. /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0);
  205. /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0);
  206. /* 2^12 - 2^2 */ fe25519_square(&t1,&t0);
  207. /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
  208. /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0);
  209. /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0);
  210. /* 2^22 - 2^2 */ fe25519_square(&t1,&t0);
  211. /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
  212. /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0);
  213. /* 2^41 - 2^1 */ fe25519_square(&t1,&t0);
  214. /* 2^42 - 2^2 */ fe25519_square(&t0,&t1);
  215. /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
  216. /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0);
  217. /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0);
  218. /* 2^52 - 2^2 */ fe25519_square(&t1,&t0);
  219. /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
  220. /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0);
  221. /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0);
  222. /* 2^102 - 2^2 */ fe25519_square(&t0,&t1);
  223. /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
  224. /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0);
  225. /* 2^201 - 2^1 */ fe25519_square(&t0,&t1);
  226. /* 2^202 - 2^2 */ fe25519_square(&t1,&t0);
  227. /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
  228. /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0);
  229. /* 2^251 - 2^1 */ fe25519_square(&t1,&t0);
  230. /* 2^252 - 2^2 */ fe25519_square(&t0,&t1);
  231. /* 2^253 - 2^3 */ fe25519_square(&t1,&t0);
  232. /* 2^254 - 2^4 */ fe25519_square(&t0,&t1);
  233. /* 2^255 - 2^5 */ fe25519_square(&t1,&t0);
  234. /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11);
  235. }
  236. void fe25519_pow2523(fe25519 *r, const fe25519 *x)
  237. {
  238. fe25519 z2;
  239. fe25519 z9;
  240. fe25519 z11;
  241. fe25519 z2_5_0;
  242. fe25519 z2_10_0;
  243. fe25519 z2_20_0;
  244. fe25519 z2_50_0;
  245. fe25519 z2_100_0;
  246. fe25519 t;
  247. int i;
  248. /* 2 */ fe25519_square(&z2,x);
  249. /* 4 */ fe25519_square(&t,&z2);
  250. /* 8 */ fe25519_square(&t,&t);
  251. /* 9 */ fe25519_mul(&z9,&t,x);
  252. /* 11 */ fe25519_mul(&z11,&z9,&z2);
  253. /* 22 */ fe25519_square(&t,&z11);
  254. /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9);
  255. /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0);
  256. /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); }
  257. /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0);
  258. /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0);
  259. /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
  260. /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0);
  261. /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0);
  262. /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); }
  263. /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0);
  264. /* 2^41 - 2^1 */ fe25519_square(&t,&t);
  265. /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
  266. /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0);
  267. /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0);
  268. /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
  269. /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0);
  270. /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0);
  271. /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); }
  272. /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0);
  273. /* 2^201 - 2^1 */ fe25519_square(&t,&t);
  274. /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
  275. /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0);
  276. /* 2^251 - 2^1 */ fe25519_square(&t,&t);
  277. /* 2^252 - 2^2 */ fe25519_square(&t,&t);
  278. /* 2^252 - 3 */ fe25519_mul(r,&t,x);
  279. }