ed25519_donna_impl_base.c 24 KB

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