ed25519_ref10_fe_51.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #include <string.h>
  2. #include "private/common.h"
  3. #include "utils.h"
  4. /*
  5. h = 0
  6. */
  7. static inline void
  8. fe25519_0(fe25519 h)
  9. {
  10. memset(&h[0], 0, 5 * sizeof h[0]);
  11. }
  12. /*
  13. h = 1
  14. */
  15. static inline void
  16. fe25519_1(fe25519 h)
  17. {
  18. h[0] = 1;
  19. memset(&h[1], 0, 4 * sizeof h[0]);
  20. }
  21. /*
  22. h = f + g
  23. Can overlap h with f or g.
  24. */
  25. static inline void
  26. fe25519_add(fe25519 h, const fe25519 f, const fe25519 g)
  27. {
  28. uint64_t h0 = f[0] + g[0];
  29. uint64_t h1 = f[1] + g[1];
  30. uint64_t h2 = f[2] + g[2];
  31. uint64_t h3 = f[3] + g[3];
  32. uint64_t h4 = f[4] + g[4];
  33. h[0] = h0;
  34. h[1] = h1;
  35. h[2] = h2;
  36. h[3] = h3;
  37. h[4] = h4;
  38. }
  39. /*
  40. h = f - g
  41. */
  42. static void
  43. fe25519_sub(fe25519 h, const fe25519 f, const fe25519 g)
  44. {
  45. const uint64_t mask = 0x7ffffffffffffULL;
  46. uint64_t h0, h1, h2, h3, h4;
  47. h0 = g[0];
  48. h1 = g[1];
  49. h2 = g[2];
  50. h3 = g[3];
  51. h4 = g[4];
  52. h1 += h0 >> 51;
  53. h0 &= mask;
  54. h2 += h1 >> 51;
  55. h1 &= mask;
  56. h3 += h2 >> 51;
  57. h2 &= mask;
  58. h4 += h3 >> 51;
  59. h3 &= mask;
  60. h0 += 19ULL * (h4 >> 51);
  61. h4 &= mask;
  62. h0 = (f[0] + 0xfffffffffffdaULL) - h0;
  63. h1 = (f[1] + 0xffffffffffffeULL) - h1;
  64. h2 = (f[2] + 0xffffffffffffeULL) - h2;
  65. h3 = (f[3] + 0xffffffffffffeULL) - h3;
  66. h4 = (f[4] + 0xffffffffffffeULL) - h4;
  67. h[0] = h0;
  68. h[1] = h1;
  69. h[2] = h2;
  70. h[3] = h3;
  71. h[4] = h4;
  72. }
  73. /*
  74. h = -f
  75. */
  76. static inline void
  77. fe25519_neg(fe25519 h, const fe25519 f)
  78. {
  79. fe25519 zero;
  80. fe25519_0(zero);
  81. fe25519_sub(h, zero, f);
  82. }
  83. /*
  84. Replace (f,g) with (g,g) if b == 1;
  85. replace (f,g) with (f,g) if b == 0.
  86. *
  87. Preconditions: b in {0,1}.
  88. */
  89. static void
  90. fe25519_cmov(fe25519 f, const fe25519 g, unsigned int b)
  91. {
  92. const uint64_t mask = (uint64_t) (-(int64_t) b);
  93. uint64_t f0 = f[0];
  94. uint64_t f1 = f[1];
  95. uint64_t f2 = f[2];
  96. uint64_t f3 = f[3];
  97. uint64_t f4 = f[4];
  98. uint64_t x0 = f0 ^ g[0];
  99. uint64_t x1 = f1 ^ g[1];
  100. uint64_t x2 = f2 ^ g[2];
  101. uint64_t x3 = f3 ^ g[3];
  102. uint64_t x4 = f4 ^ g[4];
  103. x0 &= mask;
  104. x1 &= mask;
  105. x2 &= mask;
  106. x3 &= mask;
  107. x4 &= mask;
  108. f[0] = f0 ^ x0;
  109. f[1] = f1 ^ x1;
  110. f[2] = f2 ^ x2;
  111. f[3] = f3 ^ x3;
  112. f[4] = f4 ^ x4;
  113. }
  114. /*
  115. Replace (f,g) with (g,f) if b == 1;
  116. replace (f,g) with (f,g) if b == 0.
  117. Preconditions: b in {0,1}.
  118. */
  119. static void
  120. fe25519_cswap(fe25519 f, fe25519 g, unsigned int b)
  121. {
  122. const uint64_t mask = (uint64_t) (-(int64_t) b);
  123. uint64_t f0 = f[0];
  124. uint64_t f1 = f[1];
  125. uint64_t f2 = f[2];
  126. uint64_t f3 = f[3];
  127. uint64_t f4 = f[4];
  128. uint64_t g0 = g[0];
  129. uint64_t g1 = g[1];
  130. uint64_t g2 = g[2];
  131. uint64_t g3 = g[3];
  132. uint64_t g4 = g[4];
  133. uint64_t x0 = f0 ^ g0;
  134. uint64_t x1 = f1 ^ g1;
  135. uint64_t x2 = f2 ^ g2;
  136. uint64_t x3 = f3 ^ g3;
  137. uint64_t x4 = f4 ^ g4;
  138. x0 &= mask;
  139. x1 &= mask;
  140. x2 &= mask;
  141. x3 &= mask;
  142. x4 &= mask;
  143. f[0] = f0 ^ x0;
  144. f[1] = f1 ^ x1;
  145. f[2] = f2 ^ x2;
  146. f[3] = f3 ^ x3;
  147. f[4] = f4 ^ x4;
  148. g[0] = g0 ^ x0;
  149. g[1] = g1 ^ x1;
  150. g[2] = g2 ^ x2;
  151. g[3] = g3 ^ x3;
  152. g[4] = g4 ^ x4;
  153. }
  154. /*
  155. h = f
  156. */
  157. static inline void
  158. fe25519_copy(fe25519 h, const fe25519 f)
  159. {
  160. uint64_t f0 = f[0];
  161. uint64_t f1 = f[1];
  162. uint64_t f2 = f[2];
  163. uint64_t f3 = f[3];
  164. uint64_t f4 = f[4];
  165. h[0] = f0;
  166. h[1] = f1;
  167. h[2] = f2;
  168. h[3] = f3;
  169. h[4] = f4;
  170. }
  171. /*
  172. return 1 if f is in {1,3,5,...,q-2}
  173. return 0 if f is in {0,2,4,...,q-1}
  174. */
  175. static inline int
  176. fe25519_isnegative(const fe25519 f)
  177. {
  178. unsigned char s[32];
  179. fe25519_tobytes(s, f);
  180. return s[0] & 1;
  181. }
  182. /*
  183. return 1 if f == 0
  184. return 0 if f != 0
  185. */
  186. static inline int
  187. fe25519_iszero(const fe25519 f)
  188. {
  189. unsigned char s[32];
  190. fe25519_tobytes(s, f);
  191. return sodium_is_zero(s, 32);
  192. }
  193. /*
  194. h = f * g
  195. Can overlap h with f or g.
  196. */
  197. static void
  198. fe25519_mul(fe25519 h, const fe25519 f, const fe25519 g)
  199. {
  200. const uint64_t mask = 0x7ffffffffffffULL;
  201. uint128_t r0, r1, r2, r3, r4, carry;
  202. uint64_t f0, f1, f2, f3, f4;
  203. uint64_t f1_19, f2_19, f3_19, f4_19;
  204. uint64_t g0, g1, g2, g3, g4;
  205. uint64_t r00, r01, r02, r03, r04;
  206. f0 = f[0];
  207. f1 = f[1];
  208. f2 = f[2];
  209. f3 = f[3];
  210. f4 = f[4];
  211. g0 = g[0];
  212. g1 = g[1];
  213. g2 = g[2];
  214. g3 = g[3];
  215. g4 = g[4];
  216. f1_19 = 19ULL * f1;
  217. f2_19 = 19ULL * f2;
  218. f3_19 = 19ULL * f3;
  219. f4_19 = 19ULL * f4;
  220. r0 = ((uint128_t) f0 ) * ((uint128_t) g0);
  221. r0 += ((uint128_t) f1_19) * ((uint128_t) g4);
  222. r0 += ((uint128_t) f2_19) * ((uint128_t) g3);
  223. r0 += ((uint128_t) f3_19) * ((uint128_t) g2);
  224. r0 += ((uint128_t) f4_19) * ((uint128_t) g1);
  225. r1 = ((uint128_t) f0 ) * ((uint128_t) g1);
  226. r1 += ((uint128_t) f1 ) * ((uint128_t) g0);
  227. r1 += ((uint128_t) f2_19) * ((uint128_t) g4);
  228. r1 += ((uint128_t) f3_19) * ((uint128_t) g3);
  229. r1 += ((uint128_t) f4_19) * ((uint128_t) g2);
  230. r2 = ((uint128_t) f0 ) * ((uint128_t) g2);
  231. r2 += ((uint128_t) f1 ) * ((uint128_t) g1);
  232. r2 += ((uint128_t) f2 ) * ((uint128_t) g0);
  233. r2 += ((uint128_t) f3_19) * ((uint128_t) g4);
  234. r2 += ((uint128_t) f4_19) * ((uint128_t) g3);
  235. r3 = ((uint128_t) f0 ) * ((uint128_t) g3);
  236. r3 += ((uint128_t) f1 ) * ((uint128_t) g2);
  237. r3 += ((uint128_t) f2 ) * ((uint128_t) g1);
  238. r3 += ((uint128_t) f3 ) * ((uint128_t) g0);
  239. r3 += ((uint128_t) f4_19) * ((uint128_t) g4);
  240. r4 = ((uint128_t) f0 ) * ((uint128_t) g4);
  241. r4 += ((uint128_t) f1 ) * ((uint128_t) g3);
  242. r4 += ((uint128_t) f2 ) * ((uint128_t) g2);
  243. r4 += ((uint128_t) f3 ) * ((uint128_t) g1);
  244. r4 += ((uint128_t) f4 ) * ((uint128_t) g0);
  245. r00 = ((uint64_t) r0) & mask;
  246. carry = r0 >> 51;
  247. r1 += carry;
  248. r01 = ((uint64_t) r1) & mask;
  249. carry = r1 >> 51;
  250. r2 += carry;
  251. r02 = ((uint64_t) r2) & mask;
  252. carry = r2 >> 51;
  253. r3 += carry;
  254. r03 = ((uint64_t) r3) & mask;
  255. carry = r3 >> 51;
  256. r4 += carry;
  257. r04 = ((uint64_t) r4) & mask;
  258. carry = r4 >> 51;
  259. r00 += 19ULL * (uint64_t) carry;
  260. carry = r00 >> 51;
  261. r00 &= mask;
  262. r01 += (uint64_t) carry;
  263. carry = r01 >> 51;
  264. r01 &= mask;
  265. r02 += (uint64_t) carry;
  266. h[0] = r00;
  267. h[1] = r01;
  268. h[2] = r02;
  269. h[3] = r03;
  270. h[4] = r04;
  271. }
  272. /*
  273. h = f * f
  274. Can overlap h with f.
  275. */
  276. static void
  277. fe25519_sq(fe25519 h, const fe25519 f)
  278. {
  279. const uint64_t mask = 0x7ffffffffffffULL;
  280. uint128_t r0, r1, r2, r3, r4, carry;
  281. uint64_t f0, f1, f2, f3, f4;
  282. uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
  283. uint64_t r00, r01, r02, r03, r04;
  284. f0 = f[0];
  285. f1 = f[1];
  286. f2 = f[2];
  287. f3 = f[3];
  288. f4 = f[4];
  289. f0_2 = f0 << 1;
  290. f1_2 = f1 << 1;
  291. f1_38 = 38ULL * f1;
  292. f2_38 = 38ULL * f2;
  293. f3_38 = 38ULL * f3;
  294. f3_19 = 19ULL * f3;
  295. f4_19 = 19ULL * f4;
  296. r0 = ((uint128_t) f0 ) * ((uint128_t) f0);
  297. r0 += ((uint128_t) f1_38) * ((uint128_t) f4);
  298. r0 += ((uint128_t) f2_38) * ((uint128_t) f3);
  299. r1 = ((uint128_t) f0_2 ) * ((uint128_t) f1);
  300. r1 += ((uint128_t) f2_38) * ((uint128_t) f4);
  301. r1 += ((uint128_t) f3_19) * ((uint128_t) f3);
  302. r2 = ((uint128_t) f0_2 ) * ((uint128_t) f2);
  303. r2 += ((uint128_t) f1 ) * ((uint128_t) f1);
  304. r2 += ((uint128_t) f3_38) * ((uint128_t) f4);
  305. r3 = ((uint128_t) f0_2 ) * ((uint128_t) f3);
  306. r3 += ((uint128_t) f1_2 ) * ((uint128_t) f2);
  307. r3 += ((uint128_t) f4_19) * ((uint128_t) f4);
  308. r4 = ((uint128_t) f0_2 ) * ((uint128_t) f4);
  309. r4 += ((uint128_t) f1_2 ) * ((uint128_t) f3);
  310. r4 += ((uint128_t) f2 ) * ((uint128_t) f2);
  311. r00 = ((uint64_t) r0) & mask;
  312. carry = r0 >> 51;
  313. r1 += carry;
  314. r01 = ((uint64_t) r1) & mask;
  315. carry = r1 >> 51;
  316. r2 += carry;
  317. r02 = ((uint64_t) r2) & mask;
  318. carry = r2 >> 51;
  319. r3 += carry;
  320. r03 = ((uint64_t) r3) & mask;
  321. carry = r3 >> 51;
  322. r4 += carry;
  323. r04 = ((uint64_t) r4) & mask;
  324. carry = r4 >> 51;
  325. r00 += 19ULL * (uint64_t) carry;
  326. carry = r00 >> 51;
  327. r00 &= mask;
  328. r01 += (uint64_t) carry;
  329. carry = r01 >> 51;
  330. r01 &= mask;
  331. r02 += (uint64_t) carry;
  332. h[0] = r00;
  333. h[1] = r01;
  334. h[2] = r02;
  335. h[3] = r03;
  336. h[4] = r04;
  337. }
  338. /*
  339. h = 2 * f * f
  340. Can overlap h with f.
  341. */
  342. static void
  343. fe25519_sq2(fe25519 h, const fe25519 f)
  344. {
  345. const uint64_t mask = 0x7ffffffffffffULL;
  346. uint128_t r0, r1, r2, r3, r4, carry;
  347. uint64_t f0, f1, f2, f3, f4;
  348. uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
  349. uint64_t r00, r01, r02, r03, r04;
  350. f0 = f[0];
  351. f1 = f[1];
  352. f2 = f[2];
  353. f3 = f[3];
  354. f4 = f[4];
  355. f0_2 = f0 << 1;
  356. f1_2 = f1 << 1;
  357. f1_38 = 38ULL * f1;
  358. f2_38 = 38ULL * f2;
  359. f3_38 = 38ULL * f3;
  360. f3_19 = 19ULL * f3;
  361. f4_19 = 19ULL * f4;
  362. r0 = ((uint128_t) f0 ) * ((uint128_t) f0);
  363. r0 += ((uint128_t) f1_38) * ((uint128_t) f4);
  364. r0 += ((uint128_t) f2_38) * ((uint128_t) f3);
  365. r1 = ((uint128_t) f0_2 ) * ((uint128_t) f1);
  366. r1 += ((uint128_t) f2_38) * ((uint128_t) f4);
  367. r1 += ((uint128_t) f3_19) * ((uint128_t) f3);
  368. r2 = ((uint128_t) f0_2 ) * ((uint128_t) f2);
  369. r2 += ((uint128_t) f1 ) * ((uint128_t) f1);
  370. r2 += ((uint128_t) f3_38) * ((uint128_t) f4);
  371. r3 = ((uint128_t) f0_2 ) * ((uint128_t) f3);
  372. r3 += ((uint128_t) f1_2 ) * ((uint128_t) f2);
  373. r3 += ((uint128_t) f4_19) * ((uint128_t) f4);
  374. r4 = ((uint128_t) f0_2 ) * ((uint128_t) f4);
  375. r4 += ((uint128_t) f1_2 ) * ((uint128_t) f3);
  376. r4 += ((uint128_t) f2 ) * ((uint128_t) f2);
  377. r0 <<= 1;
  378. r1 <<= 1;
  379. r2 <<= 1;
  380. r3 <<= 1;
  381. r4 <<= 1;
  382. r00 = ((uint64_t) r0) & mask;
  383. carry = r0 >> 51;
  384. r1 += carry;
  385. r01 = ((uint64_t) r1) & mask;
  386. carry = r1 >> 51;
  387. r2 += carry;
  388. r02 = ((uint64_t) r2) & mask;
  389. carry = r2 >> 51;
  390. r3 += carry;
  391. r03 = ((uint64_t) r3) & mask;
  392. carry = r3 >> 51;
  393. r4 += carry;
  394. r04 = ((uint64_t) r4) & mask;
  395. carry = r4 >> 51;
  396. r00 += 19ULL * (uint64_t) carry;
  397. carry = r00 >> 51;
  398. r00 &= mask;
  399. r01 += (uint64_t) carry;
  400. carry = r01 >> 51;
  401. r01 &= mask;
  402. r02 += (uint64_t) carry;
  403. h[0] = r00;
  404. h[1] = r01;
  405. h[2] = r02;
  406. h[3] = r03;
  407. h[4] = r04;
  408. }
  409. static void
  410. fe25519_scalar_product(fe25519 h, const fe25519 f, uint32_t n)
  411. {
  412. const uint64_t mask = 0x7ffffffffffffULL;
  413. uint128_t a;
  414. uint128_t sn = (uint128_t) n;
  415. uint64_t h0, h1, h2, h3, h4;
  416. a = f[0] * sn;
  417. h0 = ((uint64_t) a) & mask;
  418. a = f[1] * sn + ((uint64_t) (a >> 51));
  419. h1 = ((uint64_t) a) & mask;
  420. a = f[2] * sn + ((uint64_t) (a >> 51));
  421. h2 = ((uint64_t) a) & mask;
  422. a = f[3] * sn + ((uint64_t) (a >> 51));
  423. h3 = ((uint64_t) a) & mask;
  424. a = f[4] * sn + ((uint64_t) (a >> 51));
  425. h4 = ((uint64_t) a) & mask;
  426. h0 += (a >> 51) * 19ULL;
  427. h[0] = h0;
  428. h[1] = h1;
  429. h[2] = h2;
  430. h[3] = h3;
  431. h[4] = h4;
  432. }