ed25519-donna-impl-base.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #if !defined(ED25519_SSE2)
  2. /*
  3. conversions
  4. */
  5. DONNA_INLINE static void
  6. ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) {
  7. curve25519_mul(r->x, p->x, p->t);
  8. curve25519_mul(r->y, p->y, p->z);
  9. curve25519_mul(r->z, p->z, p->t);
  10. }
  11. DONNA_INLINE static void
  12. ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) {
  13. curve25519_mul(r->x, p->x, p->t);
  14. curve25519_mul(r->y, p->y, p->z);
  15. curve25519_mul(r->z, p->z, p->t);
  16. curve25519_mul(r->t, p->x, p->y);
  17. }
  18. static void
  19. ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) {
  20. curve25519_sub(p->ysubx, r->y, r->x);
  21. curve25519_add(p->xaddy, r->y, r->x);
  22. curve25519_copy(p->z, r->z);
  23. curve25519_mul(p->t2d, r->t, ge25519_ec2d);
  24. }
  25. /*
  26. adding & doubling
  27. */
  28. static void
  29. ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519 *q) {
  30. bignum25519 a,b,c,d,t,u;
  31. curve25519_sub(a, p->y, p->x);
  32. curve25519_add(b, p->y, p->x);
  33. curve25519_sub(t, q->y, q->x);
  34. curve25519_add(u, q->y, q->x);
  35. curve25519_mul(a, a, t);
  36. curve25519_mul(b, b, u);
  37. curve25519_mul(c, p->t, q->t);
  38. curve25519_mul(c, c, ge25519_ec2d);
  39. curve25519_mul(d, p->z, q->z);
  40. curve25519_add(d, d, d);
  41. curve25519_sub(r->x, b, a);
  42. curve25519_add(r->y, b, a);
  43. curve25519_add_after_basic(r->z, d, c);
  44. curve25519_sub_after_basic(r->t, d, c);
  45. }
  46. static void
  47. ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) {
  48. bignum25519 a,b,c;
  49. curve25519_square(a, p->x);
  50. curve25519_square(b, p->y);
  51. curve25519_square(c, p->z);
  52. curve25519_add_reduce(c, c, c);
  53. curve25519_add(r->x, p->x, p->y);
  54. curve25519_square(r->x, r->x);
  55. curve25519_add(r->y, b, a);
  56. curve25519_sub(r->z, b, a);
  57. curve25519_sub_after_basic(r->x, r->x, r->y);
  58. curve25519_sub_after_basic(r->t, c, r->z);
  59. }
  60. static void
  61. ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, unsigned char signbit) {
  62. const bignum25519 *qb = (const bignum25519 *)q;
  63. bignum25519 *rb = (bignum25519 *)r;
  64. bignum25519 a,b,c;
  65. curve25519_sub(a, p->y, p->x);
  66. curve25519_add(b, p->y, p->x);
  67. curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */
  68. curve25519_mul(r->x, b, qb[signbit^1]); /* y for +, x for - */
  69. curve25519_add(r->y, r->x, a);
  70. curve25519_sub(r->x, r->x, a);
  71. curve25519_mul(c, p->t, q->t2d);
  72. curve25519_add_reduce(r->t, p->z, p->z);
  73. curve25519_copy(r->z, r->t);
  74. curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
  75. curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
  76. }
  77. static void
  78. ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, unsigned char signbit) {
  79. const bignum25519 *qb = (const bignum25519 *)q;
  80. bignum25519 *rb = (bignum25519 *)r;
  81. bignum25519 a,b,c;
  82. curve25519_sub(a, p->y, p->x);
  83. curve25519_add(b, p->y, p->x);
  84. curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */
  85. curve25519_mul(r->x, b, qb[signbit^1]); /* xaddy for +, ysubx for - */
  86. curve25519_add(r->y, r->x, a);
  87. curve25519_sub(r->x, r->x, a);
  88. curve25519_mul(c, p->t, q->t2d);
  89. curve25519_mul(r->t, p->z, q->z);
  90. curve25519_add_reduce(r->t, r->t, r->t);
  91. curve25519_copy(r->z, r->t);
  92. curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
  93. curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
  94. }
  95. static void
  96. ge25519_double_partial(ge25519 *r, const ge25519 *p) {
  97. ge25519_p1p1 t;
  98. ge25519_double_p1p1(&t, p);
  99. ge25519_p1p1_to_partial(r, &t);
  100. }
  101. static void
  102. ge25519_double(ge25519 *r, const ge25519 *p) {
  103. ge25519_p1p1 t;
  104. ge25519_double_p1p1(&t, p);
  105. ge25519_p1p1_to_full(r, &t);
  106. }
  107. static void
  108. ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q) {
  109. ge25519_p1p1 t;
  110. ge25519_add_p1p1(&t, p, q);
  111. ge25519_p1p1_to_full(r, &t);
  112. }
  113. static void
  114. ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) {
  115. bignum25519 a,b,c,e,f,g,h;
  116. curve25519_sub(a, r->y, r->x);
  117. curve25519_add(b, r->y, r->x);
  118. curve25519_mul(a, a, q->ysubx);
  119. curve25519_mul(e, b, q->xaddy);
  120. curve25519_add(h, e, a);
  121. curve25519_sub(e, e, a);
  122. curve25519_mul(c, r->t, q->t2d);
  123. curve25519_add(f, r->z, r->z);
  124. curve25519_add_after_basic(g, f, c);
  125. curve25519_sub_after_basic(f, f, c);
  126. curve25519_mul(r->x, e, f);
  127. curve25519_mul(r->y, h, g);
  128. curve25519_mul(r->z, g, f);
  129. curve25519_mul(r->t, e, h);
  130. }
  131. static void
  132. ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) {
  133. bignum25519 a,b,c,x,y,z,t;
  134. curve25519_sub(a, p->y, p->x);
  135. curve25519_add(b, p->y, p->x);
  136. curve25519_mul(a, a, q->ysubx);
  137. curve25519_mul(x, b, q->xaddy);
  138. curve25519_add(y, x, a);
  139. curve25519_sub(x, x, a);
  140. curve25519_mul(c, p->t, q->t2d);
  141. curve25519_mul(t, p->z, q->z);
  142. curve25519_add(t, t, t);
  143. curve25519_add_after_basic(z, t, c);
  144. curve25519_sub_after_basic(t, t, c);
  145. curve25519_mul(r->xaddy, x, t);
  146. curve25519_mul(r->ysubx, y, z);
  147. curve25519_mul(r->z, z, t);
  148. curve25519_mul(r->t2d, x, y);
  149. curve25519_copy(y, r->ysubx);
  150. curve25519_sub(r->ysubx, r->ysubx, r->xaddy);
  151. curve25519_add(r->xaddy, r->xaddy, y);
  152. curve25519_mul(r->t2d, r->t2d, ge25519_ec2d);
  153. }
  154. /*
  155. pack & unpack
  156. */
  157. static void
  158. ge25519_pack(unsigned char r[32], const ge25519 *p) {
  159. bignum25519 tx, ty, zi;
  160. unsigned char parity[32];
  161. curve25519_recip(zi, p->z);
  162. curve25519_mul(tx, p->x, zi);
  163. curve25519_mul(ty, p->y, zi);
  164. curve25519_contract(r, ty);
  165. curve25519_contract(parity, tx);
  166. r[31] ^= ((parity[0] & 1) << 7);
  167. }
  168. // NOTE: leaves in unfinished state
  169. static void
  170. ge25519_batchpack_destructive_1(bytes32 *out, ge25519 *in, bignum25519 *tmp, size_t num) {
  171. bignum25519 ty;
  172. curve25519_batchrecip(&in->z, &in->z, tmp, num, sizeof(ge25519));
  173. for (size_t i = 0; i < num; ++i) {
  174. curve25519_mul(ty, in[i].y, in[i].z);
  175. curve25519_contract(out[i], ty);
  176. }
  177. }
  178. static void
  179. ge25519_batchpack_destructive_finish(bytes32 out, ge25519 *unf) {
  180. bignum25519 tx;
  181. unsigned char parity[32];
  182. // z of unfinished is inverted
  183. curve25519_mul(tx, unf->x, unf->z);
  184. curve25519_contract(parity, tx);
  185. out[31] ^= ((parity[0] & 1) << 7);
  186. }
  187. static int
  188. ge25519_unpack_negative_vartime(ge25519 *r, const unsigned char p[32]) {
  189. static const unsigned char zero[32] = {0};
  190. static const bignum25519 one = {1};
  191. unsigned char parity = p[31] >> 7;
  192. unsigned char check[32];
  193. bignum25519 t, root, num, den, d3;
  194. curve25519_expand(r->y, p);
  195. curve25519_copy(r->z, one);
  196. curve25519_square(num, r->y); /* x = y^2 */
  197. curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */
  198. curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */
  199. curve25519_add(den, den, r->z); /* den = dy^2 + 1 */
  200. /* Computation of sqrt(num/den) */
  201. /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */
  202. curve25519_square(t, den);
  203. curve25519_mul(d3, t, den);
  204. curve25519_square(r->x, d3);
  205. curve25519_mul(r->x, r->x, den);
  206. curve25519_mul(r->x, r->x, num);
  207. curve25519_pow_two252m3(r->x, r->x);
  208. /* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */
  209. curve25519_mul(r->x, r->x, d3);
  210. curve25519_mul(r->x, r->x, num);
  211. /* 3. Check if either of the roots works: */
  212. curve25519_square(t, r->x);
  213. curve25519_mul(t, t, den);
  214. curve25519_sub_reduce(root, t, num);
  215. curve25519_contract(check, root);
  216. if (!ed25519_verify(check, zero, 32)) {
  217. curve25519_add_reduce(t, t, num);
  218. curve25519_contract(check, t);
  219. if (!ed25519_verify(check, zero, 32))
  220. return 0;
  221. curve25519_mul(r->x, r->x, ge25519_sqrtneg1);
  222. }
  223. curve25519_contract(check, r->x);
  224. if ((check[0] & 1) == parity) {
  225. curve25519_copy(t, r->x);
  226. curve25519_neg(r->x, t);
  227. }
  228. curve25519_mul(r->t, r->x, r->y);
  229. return 1;
  230. }
  231. /*
  232. scalarmults
  233. */
  234. #define S1_SWINDOWSIZE 5
  235. #define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2))
  236. #define S2_SWINDOWSIZE 7
  237. #define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2))
  238. /* computes [s1]p1 + [s2]basepoint */
  239. static void
  240. ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) {
  241. signed char slide1[256], slide2[256];
  242. ge25519_pniels pre1[S1_TABLE_SIZE];
  243. ge25519 d1;
  244. ge25519_p1p1 t;
  245. int32_t i;
  246. contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE);
  247. contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE);
  248. ge25519_double(&d1, p1);
  249. ge25519_full_to_pniels(pre1, p1);
  250. for (i = 0; i < S1_TABLE_SIZE - 1; i++)
  251. ge25519_pnielsadd(&pre1[i+1], &d1, &pre1[i]);
  252. /* set neutral */
  253. memset(r, 0, sizeof(ge25519));
  254. r->y[0] = 1;
  255. r->z[0] = 1;
  256. i = 255;
  257. while ((i >= 0) && !(slide1[i] | slide2[i]))
  258. i--;
  259. for (; i >= 0; i--) {
  260. ge25519_double_p1p1(&t, r);
  261. if (slide1[i]) {
  262. ge25519_p1p1_to_full(r, &t);
  263. ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7);
  264. }
  265. if (slide2[i]) {
  266. ge25519_p1p1_to_full(r, &t);
  267. ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
  268. }
  269. ge25519_p1p1_to_partial(r, &t);
  270. }
  271. }
  272. #if !defined(HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS)
  273. static uint32_t
  274. ge25519_windowb_equal(uint32_t b, uint32_t c) {
  275. return ((b ^ c) - 1) >> 31;
  276. }
  277. static void
  278. ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) {
  279. bignum25519 neg;
  280. uint32_t sign = (uint32_t)((unsigned char)b >> 7);
  281. uint32_t mask = ~(sign - 1);
  282. uint32_t u = (b + mask) ^ mask;
  283. uint32_t i;
  284. /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */
  285. uint8_t packed[96] = {0};
  286. packed[0] = 1;
  287. packed[32] = 1;
  288. for (i = 0; i < 8; i++)
  289. curve25519_move_conditional_bytes(packed, table[(pos * 8) + i], ge25519_windowb_equal(u, i + 1));
  290. /* expand in to t */
  291. curve25519_expand(t->ysubx, packed + 0);
  292. curve25519_expand(t->xaddy, packed + 32);
  293. curve25519_expand(t->t2d , packed + 64);
  294. /* adjust for sign */
  295. curve25519_swap_conditional(t->ysubx, t->xaddy, sign);
  296. curve25519_neg(neg, t->t2d);
  297. curve25519_swap_conditional(t->t2d, neg, sign);
  298. }
  299. #endif /* HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS */
  300. /* computes [s]basepoint */
  301. static void
  302. ge25519_scalarmult_base_niels(ge25519 *r, const uint8_t basepoint_table[256][96], const bignum256modm s) {
  303. signed char b[64];
  304. uint32_t i;
  305. ge25519_niels t;
  306. contract256_window4_modm(b, s);
  307. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]);
  308. curve25519_sub_reduce(r->x, t.xaddy, t.ysubx);
  309. curve25519_add_reduce(r->y, t.xaddy, t.ysubx);
  310. memset(r->z, 0, sizeof(bignum25519));
  311. curve25519_copy(r->t, t.t2d);
  312. r->z[0] = 2;
  313. for (i = 3; i < 64; i += 2) {
  314. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
  315. ge25519_nielsadd2(r, &t);
  316. }
  317. ge25519_double_partial(r, r);
  318. ge25519_double_partial(r, r);
  319. ge25519_double_partial(r, r);
  320. ge25519_double(r, r);
  321. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]);
  322. curve25519_mul(t.t2d, t.t2d, ge25519_ecd);
  323. ge25519_nielsadd2(r, &t);
  324. for(i = 2; i < 64; i += 2) {
  325. ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
  326. ge25519_nielsadd2(r, &t);
  327. }
  328. }
  329. #endif /* !defined(ED25519_SSE2) */