ed25519-donna-impl-base.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. #include <assert.h>
  2. #include "ed25519-donna.h"
  3. #include "../memzero.h"
  4. /* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */
  5. /* d = -121665 / 121666 */
  6. #if !defined(NDEBUG)
  7. static const bignum25519 ALIGN(16) fe_d = {
  8. 0x35978a3, 0x0d37284, 0x3156ebd, 0x06a0a0e, 0x001c029, 0x179e898, 0x3a03cbb, 0x1ce7198, 0x2e2b6ff, 0x1480db3}; /* d */
  9. #endif
  10. static const bignum25519 ALIGN(16) fe_sqrtm1 = {
  11. 0x20ea0b0, 0x186c9d2, 0x08f189d, 0x035697f, 0x0bd0c60, 0x1fbd7a7, 0x2804c9e, 0x1e16569, 0x004fc1d, 0x0ae0c92}; /* sqrt(-1) */
  12. //static const bignum25519 ALIGN(16) fe_d2 = {
  13. // 0x2b2f159, 0x1a6e509, 0x22add7a, 0x0d4141d, 0x0038052, 0x0f3d130, 0x3407977, 0x19ce331, 0x1c56dff, 0x0901b67}; /* 2 * d */
  14. /* A = 2 * (1 - d) / (1 + d) = 486662 */
  15. static const bignum25519 ALIGN(16) fe_ma2 = {
  16. 0x33de3c9, 0x1fff236, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff}; /* -A^2 */
  17. static const bignum25519 ALIGN(16) fe_ma = {
  18. 0x3f892e7, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff}; /* -A */
  19. static const bignum25519 ALIGN(16) fe_fffb1 = {
  20. 0x1e3bdff, 0x025a2b3, 0x18e5bab, 0x0ba36ac, 0x0b9afed, 0x004e61c, 0x31d645f, 0x09d1bea, 0x102529e, 0x0063810}; /* sqrt(-2 * A * (A + 2)) */
  21. static const bignum25519 ALIGN(16) fe_fffb2 = {
  22. 0x383650d, 0x066df27, 0x10405a4, 0x1cfdd48, 0x2b887f2, 0x1e9a041, 0x1d7241f, 0x0612dc5, 0x35fba5d, 0x0cbe787}; /* sqrt(2 * A * (A + 2)) */
  23. static const bignum25519 ALIGN(16) fe_fffb3 = {
  24. 0x0cfd387, 0x1209e3a, 0x3bad4fc, 0x18ad34d, 0x2ff6c02, 0x0f25d12, 0x15cdfe0, 0x0e208ed, 0x32eb3df, 0x062d7bb}; /* sqrt(-sqrt(-1) * A * (A + 2)) */
  25. static const bignum25519 ALIGN(16) fe_fffb4 = {
  26. 0x2b39186, 0x14640ed, 0x14930a7, 0x04509fa, 0x3b91bf0, 0x0f7432e, 0x07a443f, 0x17f24d8, 0x031067d, 0x0690fcc}; /* sqrt(sqrt(-1) * A * (A + 2)) */
  27. /*
  28. Timing safe memory compare
  29. */
  30. int ed25519_verify(const unsigned char *x, const unsigned char *y, size_t len) {
  31. size_t differentbits = 0;
  32. while (len--)
  33. differentbits |= (*x++ ^ *y++);
  34. return (int) (1 & ((differentbits - 1) >> 8));
  35. }
  36. /*
  37. conversions
  38. */
  39. void ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) {
  40. curve25519_mul(r->x, p->x, p->t);
  41. curve25519_mul(r->y, p->y, p->z);
  42. curve25519_mul(r->z, p->z, p->t);
  43. }
  44. void ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) {
  45. curve25519_mul(r->x, p->x, p->t);
  46. curve25519_mul(r->y, p->y, p->z);
  47. curve25519_mul(r->z, p->z, p->t);
  48. curve25519_mul(r->t, p->x, p->y);
  49. }
  50. void ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) {
  51. curve25519_sub(p->ysubx, r->y, r->x);
  52. curve25519_add(p->xaddy, r->y, r->x);
  53. curve25519_copy(p->z, r->z);
  54. curve25519_mul(p->t2d, r->t, ge25519_ec2d);
  55. }
  56. /*
  57. adding & doubling
  58. */
  59. void ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) {
  60. bignum25519 a = {0}, b = {0}, c = {0};
  61. curve25519_square(a, p->x);
  62. curve25519_square(b, p->y);
  63. curve25519_square(c, p->z);
  64. curve25519_add_reduce(c, c, c);
  65. curve25519_add(r->x, p->x, p->y);
  66. curve25519_square(r->x, r->x);
  67. curve25519_add(r->y, b, a);
  68. curve25519_sub(r->z, b, a);
  69. curve25519_sub_after_basic(r->x, r->x, r->y);
  70. curve25519_sub_after_basic(r->t, c, r->z);
  71. }
  72. #ifndef ED25519_NO_PRECOMP
  73. void ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, unsigned char signbit) {
  74. const bignum25519 *qb = (const bignum25519 *)q;
  75. bignum25519 *rb = (bignum25519 *)r;
  76. bignum25519 a = {0}, b = {0}, c = {0};
  77. curve25519_sub(a, p->y, p->x);
  78. curve25519_add(b, p->y, p->x);
  79. curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */
  80. curve25519_mul(r->x, b, qb[signbit^1]); /* y for +, x for - */
  81. curve25519_add(r->y, r->x, a);
  82. curve25519_sub(r->x, r->x, a);
  83. curve25519_mul(c, p->t, q->t2d);
  84. curve25519_add_reduce(r->t, p->z, p->z);
  85. curve25519_copy(r->z, r->t);
  86. curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
  87. curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
  88. }
  89. #endif
  90. void ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, unsigned char signbit) {
  91. const bignum25519 *qb = (const bignum25519 *)q;
  92. bignum25519 *rb = (bignum25519 *)r;
  93. bignum25519 a = {0}, b = {0}, c = {0};
  94. curve25519_sub(a, p->y, p->x);
  95. curve25519_add(b, p->y, p->x);
  96. curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */
  97. curve25519_mul(r->x, b, qb[signbit^1]); /* xaddy for +, ysubx for - */
  98. curve25519_add(r->y, r->x, a);
  99. curve25519_sub(r->x, r->x, a);
  100. curve25519_mul(c, p->t, q->t2d);
  101. curve25519_mul(r->t, p->z, q->z);
  102. curve25519_add_reduce(r->t, r->t, r->t);
  103. curve25519_copy(r->z, r->t);
  104. curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
  105. curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
  106. }
  107. void ge25519_double_partial(ge25519 *r, const ge25519 *p) {
  108. ge25519_p1p1 t = {0};
  109. ge25519_double_p1p1(&t, p);
  110. ge25519_p1p1_to_partial(r, &t);
  111. }
  112. void ge25519_double(ge25519 *r, const ge25519 *p) {
  113. ge25519_p1p1 t = {0};
  114. ge25519_double_p1p1(&t, p);
  115. ge25519_p1p1_to_full(r, &t);
  116. }
  117. void ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) {
  118. bignum25519 a = {0}, b = {0}, c = {0}, e = {0}, f = {0}, g = {0}, h = {0};
  119. curve25519_sub(a, r->y, r->x);
  120. curve25519_add(b, r->y, r->x);
  121. curve25519_mul(a, a, q->ysubx);
  122. curve25519_mul(e, b, q->xaddy);
  123. curve25519_add(h, e, a);
  124. curve25519_sub(e, e, a);
  125. curve25519_mul(c, r->t, q->t2d);
  126. curve25519_add(f, r->z, r->z);
  127. curve25519_add_after_basic(g, f, c);
  128. curve25519_sub_after_basic(f, f, c);
  129. curve25519_mul(r->x, e, f);
  130. curve25519_mul(r->y, h, g);
  131. curve25519_mul(r->z, g, f);
  132. curve25519_mul(r->t, e, h);
  133. }
  134. void ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) {
  135. bignum25519 a = {0}, b = {0}, c = {0}, x = {0}, y = {0}, z = {0}, t = {0};
  136. curve25519_sub(a, p->y, p->x);
  137. curve25519_add(b, p->y, p->x);
  138. curve25519_mul(a, a, q->ysubx);
  139. curve25519_mul(x, b, q->xaddy);
  140. curve25519_add(y, x, a);
  141. curve25519_sub(x, x, a);
  142. curve25519_mul(c, p->t, q->t2d);
  143. curve25519_mul(t, p->z, q->z);
  144. curve25519_add(t, t, t);
  145. curve25519_add_after_basic(z, t, c);
  146. curve25519_sub_after_basic(t, t, c);
  147. curve25519_mul(r->xaddy, x, t);
  148. curve25519_mul(r->ysubx, y, z);
  149. curve25519_mul(r->z, z, t);
  150. curve25519_mul(r->t2d, x, y);
  151. curve25519_copy(y, r->ysubx);
  152. curve25519_sub(r->ysubx, r->ysubx, r->xaddy);
  153. curve25519_add(r->xaddy, r->xaddy, y);
  154. curve25519_mul(r->t2d, r->t2d, ge25519_ec2d);
  155. }
  156. /*
  157. pack & unpack
  158. */
  159. void ge25519_pack(unsigned char r[32], const ge25519 *p) {
  160. bignum25519 tx = {0}, ty = {0}, zi = {0};
  161. unsigned char parity[32] = {0};
  162. curve25519_recip(zi, p->z);
  163. curve25519_mul(tx, p->x, zi);
  164. curve25519_mul(ty, p->y, zi);
  165. curve25519_contract(r, ty);
  166. curve25519_contract(parity, tx);
  167. r[31] ^= ((parity[0] & 1) << 7);
  168. }
  169. int ge25519_unpack_negative_vartime(ge25519 *r, const unsigned char p[32]) {
  170. const unsigned char zero[32] = {0};
  171. const bignum25519 one = {1};
  172. unsigned char parity = p[31] >> 7;
  173. unsigned char check[32] = {0};
  174. bignum25519 t = {0}, root = {0}, num = {0}, den = {0}, d3 = {0};
  175. curve25519_expand(r->y, p);
  176. curve25519_copy(r->z, one);
  177. curve25519_square(num, r->y); /* x = y^2 */
  178. curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */
  179. curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */
  180. curve25519_add(den, den, r->z); /* den = dy^2 + 1 */
  181. /* Computation of sqrt(num/den) */
  182. /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */
  183. curve25519_square(t, den);
  184. curve25519_mul(d3, t, den);
  185. curve25519_square(r->x, d3);
  186. curve25519_mul(r->x, r->x, den);
  187. curve25519_mul(r->x, r->x, num);
  188. curve25519_pow_two252m3(r->x, r->x);
  189. /* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */
  190. curve25519_mul(r->x, r->x, d3);
  191. curve25519_mul(r->x, r->x, num);
  192. /* 3. Check if either of the roots works: */
  193. curve25519_square(t, r->x);
  194. curve25519_mul(t, t, den);
  195. curve25519_sub_reduce(root, t, num);
  196. curve25519_contract(check, root);
  197. if (!ed25519_verify(check, zero, 32)) {
  198. curve25519_add_reduce(t, t, num);
  199. curve25519_contract(check, t);
  200. if (!ed25519_verify(check, zero, 32))
  201. return 0;
  202. curve25519_mul(r->x, r->x, ge25519_sqrtneg1);
  203. }
  204. curve25519_contract(check, r->x);
  205. if ((check[0] & 1) == parity) {
  206. curve25519_copy(t, r->x);
  207. curve25519_neg(r->x, t);
  208. }
  209. curve25519_mul(r->t, r->x, r->y);
  210. return 1;
  211. }
  212. /*
  213. scalarmults
  214. */
  215. void ge25519_set_neutral(ge25519 *r)
  216. {
  217. memzero(r, sizeof(ge25519));
  218. r->y[0] = 1;
  219. r->z[0] = 1;
  220. }
  221. #define S1_SWINDOWSIZE 5
  222. #define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2))
  223. #ifdef ED25519_NO_PRECOMP
  224. #define S2_SWINDOWSIZE 5
  225. #else
  226. #define S2_SWINDOWSIZE 7
  227. #endif
  228. #define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2))
  229. /* computes [s1]p1 + [s2]base */
  230. void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) {
  231. signed char slide1[256] = {0}, slide2[256] = {0};
  232. ge25519_pniels pre1[S1_TABLE_SIZE] = {0};
  233. #ifdef ED25519_NO_PRECOMP
  234. ge25519_pniels pre2[S2_TABLE_SIZE] = {0};
  235. #endif
  236. ge25519 dp = {0};
  237. ge25519_p1p1 t = {0};
  238. int32_t i = 0;
  239. memzero(&t, sizeof(ge25519_p1p1));
  240. contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE);
  241. contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE);
  242. ge25519_double(&dp, p1);
  243. ge25519_full_to_pniels(pre1, p1);
  244. for (i = 0; i < S1_TABLE_SIZE - 1; i++)
  245. ge25519_pnielsadd(&pre1[i+1], &dp, &pre1[i]);
  246. #ifdef ED25519_NO_PRECOMP
  247. ge25519_double(&dp, &ge25519_basepoint);
  248. ge25519_full_to_pniels(pre2, &ge25519_basepoint);
  249. for (i = 0; i < S2_TABLE_SIZE - 1; i++)
  250. ge25519_pnielsadd(&pre2[i+1], &dp, &pre2[i]);
  251. #endif
  252. ge25519_set_neutral(r);
  253. i = 255;
  254. while ((i >= 0) && !(slide1[i] | slide2[i]))
  255. i--;
  256. for (; i >= 0; i--) {
  257. ge25519_double_p1p1(&t, r);
  258. if (slide1[i]) {
  259. ge25519_p1p1_to_full(r, &t);
  260. ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7);
  261. }
  262. if (slide2[i]) {
  263. ge25519_p1p1_to_full(r, &t);
  264. #ifdef ED25519_NO_PRECOMP
  265. ge25519_pnielsadd_p1p1(&t, r, &pre2[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
  266. #else
  267. ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
  268. #endif
  269. }
  270. ge25519_p1p1_to_partial(r, &t);
  271. }
  272. curve25519_mul(r->t, t.x, t.y);
  273. memzero(slide1, sizeof(slide1));
  274. memzero(slide2, sizeof(slide2));
  275. }
  276. /* computes [s1]p1 + [s2]p2 */
  277. #if USE_MONERO
  278. void ge25519_double_scalarmult_vartime2(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const ge25519 *p2, const bignum256modm s2) {
  279. signed char slide1[256] = {0}, slide2[256] = {0};
  280. ge25519_pniels pre1[S1_TABLE_SIZE] = {0};
  281. ge25519_pniels pre2[S1_TABLE_SIZE] = {0};
  282. ge25519 dp = {0};
  283. ge25519_p1p1 t = {0};
  284. int32_t i = 0;
  285. memzero(&t, sizeof(ge25519_p1p1));
  286. contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE);
  287. contract256_slidingwindow_modm(slide2, s2, S1_SWINDOWSIZE);
  288. ge25519_double(&dp, p1);
  289. ge25519_full_to_pniels(pre1, p1);
  290. for (i = 0; i < S1_TABLE_SIZE - 1; i++)
  291. ge25519_pnielsadd(&pre1[i+1], &dp, &pre1[i]);
  292. ge25519_double(&dp, p2);
  293. ge25519_full_to_pniels(pre2, p2);
  294. for (i = 0; i < S1_TABLE_SIZE - 1; i++)
  295. ge25519_pnielsadd(&pre2[i+1], &dp, &pre2[i]);
  296. ge25519_set_neutral(r);
  297. i = 255;
  298. while ((i >= 0) && !(slide1[i] | slide2[i]))
  299. i--;
  300. for (; i >= 0; i--) {
  301. ge25519_double_p1p1(&t, r);
  302. if (slide1[i]) {
  303. ge25519_p1p1_to_full(r, &t);
  304. ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7);
  305. }
  306. if (slide2[i]) {
  307. ge25519_p1p1_to_full(r, &t);
  308. ge25519_pnielsadd_p1p1(&t, r, &pre2[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
  309. }
  310. ge25519_p1p1_to_partial(r, &t);
  311. }
  312. curve25519_mul(r->t, t.x, t.y);
  313. memzero(slide1, sizeof(slide1));
  314. memzero(slide2, sizeof(slide2));
  315. }
  316. #endif
  317. /*
  318. * The following conditional move stuff uses conditional moves.
  319. * I will check on which compilers this works, and provide suitable
  320. * workarounds for those where it doesn't.
  321. *
  322. * This works on gcc 4.x and above with -O3. Don't use -O2, this will
  323. * cause the code to not generate conditional moves. Don't use any -march=
  324. * with less than i686 on x86
  325. */
  326. static void ge25519_cmove_stride4(long * r, long * p, long * pos, long * n, int stride) {
  327. long x0=r[0], x1=r[1], x2=r[2], x3=r[3], y0 = 0, y1 = 0, y2 = 0, y3 = 0;
  328. for(; p<n; p+=stride) {
  329. volatile int flag=(p==pos);
  330. y0 = p[0];
  331. y1 = p[1];
  332. y2 = p[2];
  333. y3 = p[3];
  334. x0 = flag ? y0 : x0;
  335. x1 = flag ? y1 : x1;
  336. x2 = flag ? y2 : x2;
  337. x3 = flag ? y3 : x3;
  338. }
  339. r[0] = x0;
  340. r[1] = x1;
  341. r[2] = x2;
  342. r[3] = x3;
  343. }
  344. #define HAS_CMOVE_STRIDE4
  345. static void ge25519_cmove_stride4b(long * r, long * p, long * pos, long * n, int stride) {
  346. long x0=p[0], x1=p[1], x2=p[2], x3=p[3], y0 = 0, y1 = 0, y2 = 0, y3 = 0;
  347. for(p+=stride; p<n; p+=stride) {
  348. volatile int flag=(p==pos);
  349. y0 = p[0];
  350. y1 = p[1];
  351. y2 = p[2];
  352. y3 = p[3];
  353. x0 = flag ? y0 : x0;
  354. x1 = flag ? y1 : x1;
  355. x2 = flag ? y2 : x2;
  356. x3 = flag ? y3 : x3;
  357. }
  358. r[0] = x0;
  359. r[1] = x1;
  360. r[2] = x2;
  361. r[3] = x3;
  362. }
  363. #define HAS_CMOVE_STRIDE4B
  364. void ge25519_move_conditional_pniels_array(ge25519_pniels * r, const ge25519_pniels * p, int pos, int n) {
  365. #ifdef HAS_CMOVE_STRIDE4B
  366. size_t i = 0;
  367. for(i=0; i<sizeof(ge25519_pniels)/sizeof(long); i+=4) {
  368. ge25519_cmove_stride4b(((long*)r)+i,
  369. ((long*)p)+i,
  370. ((long*)(p+pos))+i,
  371. ((long*)(p+n))+i,
  372. sizeof(ge25519_pniels)/sizeof(long));
  373. }
  374. #else
  375. size_t i = 0;
  376. for(i=0; i<n; i++) {
  377. ge25519_move_conditional_pniels(r, p+i, pos==i);
  378. }
  379. #endif
  380. }
  381. void ge25519_move_conditional_niels_array(ge25519_niels * r, const uint8_t p[8][96], int pos, int n) {
  382. size_t i = 0;
  383. for(i=0; i<96/sizeof(long); i+=4) {
  384. ge25519_cmove_stride4(((long*)r)+i,
  385. ((long*)p)+i,
  386. ((long*)(p+pos))+i,
  387. ((long*)(p+n))+i,
  388. 96/sizeof(long));
  389. }
  390. }
  391. /* computes [s1]p1, constant time */
  392. void ge25519_scalarmult(ge25519 *r, const ge25519 *p1, const bignum256modm s1) {
  393. signed char slide1[64] = {0};
  394. ge25519_pniels pre1[9] = {0};
  395. ge25519_pniels pre = {0};
  396. ge25519 d1 = {0};
  397. ge25519_p1p1 t = {0};
  398. int32_t i = 0;
  399. contract256_window4_modm(slide1, s1);
  400. ge25519_full_to_pniels(pre1+1, p1);
  401. ge25519_double(&d1, p1);
  402. ge25519_set_neutral(r);
  403. ge25519_full_to_pniels(pre1, r);
  404. ge25519_full_to_pniels(pre1+2, &d1);
  405. for (i = 1; i < 7; i++) {
  406. ge25519_pnielsadd(&pre1[i+2], &d1, &pre1[i]);
  407. }
  408. for (i = 63; i >= 0; i--) {
  409. int k=abs(slide1[i]);
  410. ge25519_double_partial(r, r);
  411. ge25519_double_partial(r, r);
  412. ge25519_double_partial(r, r);
  413. ge25519_double_p1p1(&t, r);
  414. ge25519_move_conditional_pniels_array(&pre, pre1, k, 9);
  415. ge25519_p1p1_to_full(r, &t);
  416. ge25519_pnielsadd_p1p1(&t, r, &pre, (unsigned char)slide1[i] >> 7);
  417. ge25519_p1p1_to_partial(r, &t);
  418. }
  419. curve25519_mul(r->t, t.x, t.y);
  420. memzero(slide1, sizeof(slide1));
  421. }
  422. void ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) {
  423. bignum25519 neg = {0};
  424. uint32_t sign = (uint32_t)((unsigned char)b >> 7);
  425. uint32_t mask = ~(sign - 1);
  426. uint32_t u = (b + mask) ^ mask;
  427. /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */
  428. uint8_t packed[96] = {0};
  429. packed[0] = 1;
  430. packed[32] = 1;
  431. ge25519_move_conditional_niels_array((ge25519_niels *)packed, &table[pos*8], u-1, 8);
  432. /* expand in to t */
  433. curve25519_expand(t->ysubx, packed + 0);
  434. curve25519_expand(t->xaddy, packed + 32);
  435. curve25519_expand(t->t2d , packed + 64);
  436. /* adjust for sign */
  437. curve25519_swap_conditional(t->ysubx, t->xaddy, sign);
  438. curve25519_neg(neg, t->t2d);
  439. curve25519_swap_conditional(t->t2d, neg, sign);
  440. }
  441. /* computes [s]basepoint */
  442. void ge25519_scalarmult_base_niels(ge25519 *r, const uint8_t basepoint_table[256][96], const bignum256modm s) {
  443. signed char b[64] = {0};
  444. uint32_t i = 0;
  445. ge25519_niels t = {0};
  446. contract256_window4_modm(b, s);
  447. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]);
  448. curve25519_sub_reduce(r->x, t.xaddy, t.ysubx);
  449. curve25519_add_reduce(r->y, t.xaddy, t.ysubx);
  450. memzero(r->z, sizeof(bignum25519));
  451. curve25519_copy(r->t, t.t2d);
  452. r->z[0] = 2;
  453. for (i = 3; i < 64; i += 2) {
  454. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
  455. ge25519_nielsadd2(r, &t);
  456. }
  457. ge25519_double_partial(r, r);
  458. ge25519_double_partial(r, r);
  459. ge25519_double_partial(r, r);
  460. ge25519_double(r, r);
  461. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]);
  462. curve25519_mul(t.t2d, t.t2d, ge25519_ecd);
  463. ge25519_nielsadd2(r, &t);
  464. for(i = 2; i < 64; i += 2) {
  465. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
  466. ge25519_nielsadd2(r, &t);
  467. }
  468. }
  469. int ge25519_check(const ge25519 *r){
  470. /* return (z % q != 0 and
  471. x * y % q == z * t % q and
  472. (y * y - x * x - z * z - ed25519.d * t * t) % q == 0)
  473. */
  474. bignum25519 z={0}, lhs={0}, rhs={0}, tmp={0}, res={0};
  475. curve25519_reduce(z, r->z);
  476. curve25519_mul(lhs, r->x, r->y);
  477. curve25519_mul(rhs, r->z, r->t);
  478. curve25519_sub_reduce(lhs, lhs, rhs);
  479. curve25519_square(res, r->y);
  480. curve25519_square(tmp, r->x);
  481. curve25519_sub_reduce(res, res, tmp);
  482. curve25519_square(tmp, r->z);
  483. curve25519_sub_reduce(res, res, tmp);
  484. curve25519_square(tmp, r->t);
  485. curve25519_mul(tmp, tmp, ge25519_ecd);
  486. curve25519_sub_reduce(res, res, tmp);
  487. const int c1 = curve25519_isnonzero(z);
  488. const int c2 = curve25519_isnonzero(lhs);
  489. const int c3 = curve25519_isnonzero(res);
  490. return c1 & (c2^0x1) & (c3^0x1);
  491. }
  492. int ge25519_eq(const ge25519 *a, const ge25519 *b){
  493. int eq = 1;
  494. bignum25519 t1={0}, t2={0};
  495. eq &= ge25519_check(a);
  496. eq &= ge25519_check(b);
  497. curve25519_mul(t1, a->x, b->z);
  498. curve25519_mul(t2, b->x, a->z);
  499. curve25519_sub_reduce(t1, t1, t2);
  500. eq &= curve25519_isnonzero(t1) ^ 1;
  501. curve25519_mul(t1, a->y, b->z);
  502. curve25519_mul(t2, b->y, a->z);
  503. curve25519_sub_reduce(t1, t1, t2);
  504. eq &= curve25519_isnonzero(t1) ^ 1;
  505. return eq;
  506. }
  507. void ge25519_copy(ge25519 *dst, const ge25519 *src){
  508. curve25519_copy(dst->x, src->x);
  509. curve25519_copy(dst->y, src->y);
  510. curve25519_copy(dst->z, src->z);
  511. curve25519_copy(dst->t, src->t);
  512. }
  513. void ge25519_set_base(ge25519 *r){
  514. ge25519_copy(r, &ge25519_basepoint);
  515. }
  516. void ge25519_mul8(ge25519 *r, const ge25519 *t) {
  517. ge25519_double_partial(r, t);
  518. ge25519_double_partial(r, r);
  519. ge25519_double(r, r);
  520. }
  521. void ge25519_neg_partial(ge25519 *r){
  522. curve25519_neg(r->x, r->x);
  523. }
  524. void ge25519_neg_full(ge25519 *r){
  525. curve25519_neg(r->x, r->x);
  526. curve25519_neg(r->t, r->t);
  527. }
  528. void ge25519_reduce(ge25519 *r, const ge25519 *t){
  529. curve25519_reduce(r->x, t->x);
  530. curve25519_reduce(r->y, t->y);
  531. curve25519_reduce(r->z, t->z);
  532. curve25519_reduce(r->t, t->t);
  533. }
  534. void ge25519_norm(ge25519 *r, const ge25519 * t){
  535. bignum25519 zinv = {0};
  536. curve25519_recip(zinv, t->z);
  537. curve25519_mul(r->x, t->x, zinv);
  538. curve25519_mul(r->y, t->y, zinv);
  539. curve25519_mul(r->t, r->x, r->y);
  540. curve25519_set(r->z, 1);
  541. }
  542. void ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q, unsigned char signbit) {
  543. ge25519_pniels P_ni = {0};
  544. ge25519_p1p1 P_11 = {0};
  545. ge25519_full_to_pniels(&P_ni, q);
  546. ge25519_pnielsadd_p1p1(&P_11, p, &P_ni, signbit);
  547. ge25519_p1p1_to_full(r, &P_11);
  548. }
  549. void ge25519_fromfe_frombytes_vartime(ge25519 *r, const unsigned char *s){
  550. bignum25519 u={0}, v={0}, w={0}, x={0}, y={0}, z={0};
  551. unsigned char sign = 0;
  552. curve25519_expand_reduce(u, s);
  553. curve25519_square(v, u);
  554. curve25519_add_reduce(v, v, v); /* 2 * u^2 */
  555. curve25519_set(w, 1);
  556. curve25519_add_reduce(w, v, w); /* w = 2 * u^2 + 1 */
  557. curve25519_square(x, w); /* w^2 */
  558. curve25519_mul(y, fe_ma2, v); /* -2 * A^2 * u^2 */
  559. curve25519_add_reduce(x, x, y); /* x = w^2 - 2 * A^2 * u^2 */
  560. curve25519_divpowm1(r->x, w, x); /* (w / x)^(m + 1) */
  561. curve25519_square(y, r->x);
  562. curve25519_mul(x, y, x);
  563. curve25519_sub_reduce(y, w, x);
  564. curve25519_copy(z, fe_ma);
  565. if (curve25519_isnonzero(y)) {
  566. curve25519_add_reduce(y, w, x);
  567. if (curve25519_isnonzero(y)) {
  568. goto negative;
  569. } else {
  570. curve25519_mul(r->x, r->x, fe_fffb1);
  571. }
  572. } else {
  573. curve25519_mul(r->x, r->x, fe_fffb2);
  574. }
  575. curve25519_mul(r->x, r->x, u); /* u * sqrt(2 * A * (A + 2) * w / x) */
  576. curve25519_mul(z, z, v); /* -2 * A * u^2 */
  577. sign = 0;
  578. goto setsign;
  579. negative:
  580. curve25519_mul(x, x, fe_sqrtm1);
  581. curve25519_sub_reduce(y, w, x);
  582. if (curve25519_isnonzero(y)) {
  583. assert((curve25519_add_reduce(y, w, x), !curve25519_isnonzero(y)));
  584. curve25519_mul(r->x, r->x, fe_fffb3);
  585. } else {
  586. curve25519_mul(r->x, r->x, fe_fffb4);
  587. }
  588. /* r->x = sqrt(A * (A + 2) * w / x) */
  589. /* z = -A */
  590. sign = 1;
  591. setsign:
  592. if (curve25519_isnegative(r->x) != sign) {
  593. assert(curve25519_isnonzero(r->x));
  594. curve25519_neg(r->x, r->x);
  595. }
  596. curve25519_add_reduce(r->z, z, w);
  597. curve25519_sub_reduce(r->y, z, w);
  598. curve25519_mul(r->x, r->x, r->z);
  599. // Partial form, saving from T coord computation .
  600. // Later is mul8 discarding T anyway.
  601. // rt = ((rx * ry % q) * inv(rz)) % q
  602. // curve25519_mul(x, r->x, r->y);
  603. // curve25519_recip(z, r->z);
  604. // curve25519_mul(r->t, x, z);
  605. #if !defined(NDEBUG)
  606. {
  607. bignum25519 check_x={0}, check_y={0}, check_iz={0}, check_v={0};
  608. curve25519_recip(check_iz, r->z);
  609. curve25519_mul(check_x, r->x, check_iz);
  610. curve25519_mul(check_y, r->y, check_iz);
  611. curve25519_square(check_x, check_x);
  612. curve25519_square(check_y, check_y);
  613. curve25519_mul(check_v, check_x, check_y);
  614. curve25519_mul(check_v, fe_d, check_v);
  615. curve25519_add_reduce(check_v, check_v, check_x);
  616. curve25519_sub_reduce(check_v, check_v, check_y);
  617. curve25519_set(check_x, 1);
  618. curve25519_add_reduce(check_v, check_v, check_x);
  619. assert(!curve25519_isnonzero(check_v));
  620. }
  621. #endif
  622. }
  623. int ge25519_unpack_vartime(ge25519 *r, const unsigned char *s){
  624. int res = ge25519_unpack_negative_vartime(r, s);
  625. ge25519_neg_full(r);
  626. return res;
  627. }
  628. void ge25519_scalarmult_base_wrapper(ge25519 *r, const bignum256modm s){
  629. ge25519_scalarmult_base_niels(r, ge25519_niels_base_multiples, s);
  630. }