/htdocs/wp-includes/sodium_compat/src/Core/Curve25519.php

https://gitlab.com/VTTE/sitios-vtte · PHP · 1469 lines · 950 code · 83 blank · 436 comment · 37 complexity · 89d6bbc2c88f13bee1d52da8597985c2 MD5 · raw file

  1. <?php
  2. if (class_exists('ParagonIE_Sodium_Core_Curve25519', false)) {
  3. return;
  4. }
  5. /**
  6. * Class ParagonIE_Sodium_Core_Curve25519
  7. *
  8. * Implements Curve25519 core functions
  9. *
  10. * Based on the ref10 curve25519 code provided by libsodium
  11. *
  12. * @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
  13. */
  14. abstract class ParagonIE_Sodium_Core_Curve25519 extends ParagonIE_Sodium_Core_Curve25519_H
  15. {
  16. /**
  17. * Get a field element of size 10 with a value of 0
  18. *
  19. * @internal You should not use this directly from another application
  20. *
  21. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  22. */
  23. public static function fe_0()
  24. {
  25. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
  26. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  27. );
  28. }
  29. /**
  30. * Get a field element of size 10 with a value of 1
  31. *
  32. * @internal You should not use this directly from another application
  33. *
  34. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  35. */
  36. public static function fe_1()
  37. {
  38. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
  39. array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  40. );
  41. }
  42. /**
  43. * Add two field elements.
  44. *
  45. * @internal You should not use this directly from another application
  46. *
  47. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  48. * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
  49. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  50. * @psalm-suppress MixedAssignment
  51. * @psalm-suppress MixedOperand
  52. */
  53. public static function fe_add(
  54. ParagonIE_Sodium_Core_Curve25519_Fe $f,
  55. ParagonIE_Sodium_Core_Curve25519_Fe $g
  56. ) {
  57. /** @var array<int, int> $arr */
  58. $arr = array();
  59. for ($i = 0; $i < 10; ++$i) {
  60. $arr[$i] = (int) ($f[$i] + $g[$i]);
  61. }
  62. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($arr);
  63. }
  64. /**
  65. * Constant-time conditional move.
  66. *
  67. * @internal You should not use this directly from another application
  68. *
  69. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  70. * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
  71. * @param int $b
  72. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  73. * @psalm-suppress MixedAssignment
  74. */
  75. public static function fe_cmov(
  76. ParagonIE_Sodium_Core_Curve25519_Fe $f,
  77. ParagonIE_Sodium_Core_Curve25519_Fe $g,
  78. $b = 0
  79. ) {
  80. /** @var array<int, int> $h */
  81. $h = array();
  82. $b *= -1;
  83. for ($i = 0; $i < 10; ++$i) {
  84. /** @var int $x */
  85. $x = (($f[$i] ^ $g[$i]) & $b);
  86. $h[$i] = (int) ((int) ($f[$i]) ^ $x);
  87. }
  88. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h);
  89. }
  90. /**
  91. * Create a copy of a field element.
  92. *
  93. * @internal You should not use this directly from another application
  94. *
  95. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  96. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  97. */
  98. public static function fe_copy(ParagonIE_Sodium_Core_Curve25519_Fe $f)
  99. {
  100. $h = clone $f;
  101. return $h;
  102. }
  103. /**
  104. * Give: 32-byte string.
  105. * Receive: A field element object to use for internal calculations.
  106. *
  107. * @internal You should not use this directly from another application
  108. *
  109. * @param string $s
  110. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  111. * @throws RangeException
  112. * @throws TypeError
  113. */
  114. public static function fe_frombytes($s)
  115. {
  116. if (self::strlen($s) !== 32) {
  117. throw new RangeException('Expected a 32-byte string.');
  118. }
  119. /** @var int $h0 */
  120. $h0 = self::load_4($s);
  121. /** @var int $h1 */
  122. $h1 = self::load_3(self::substr($s, 4, 3)) << 6;
  123. /** @var int $h2 */
  124. $h2 = self::load_3(self::substr($s, 7, 3)) << 5;
  125. /** @var int $h3 */
  126. $h3 = self::load_3(self::substr($s, 10, 3)) << 3;
  127. /** @var int $h4 */
  128. $h4 = self::load_3(self::substr($s, 13, 3)) << 2;
  129. /** @var int $h5 */
  130. $h5 = self::load_4(self::substr($s, 16, 4));
  131. /** @var int $h6 */
  132. $h6 = self::load_3(self::substr($s, 20, 3)) << 7;
  133. /** @var int $h7 */
  134. $h7 = self::load_3(self::substr($s, 23, 3)) << 5;
  135. /** @var int $h8 */
  136. $h8 = self::load_3(self::substr($s, 26, 3)) << 4;
  137. /** @var int $h9 */
  138. $h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2;
  139. /** @var int $carry9 */
  140. $carry9 = ($h9 + (1 << 24)) >> 25;
  141. $h0 += self::mul($carry9, 19, 5);
  142. $h9 -= $carry9 << 25;
  143. /** @var int $carry1 */
  144. $carry1 = ($h1 + (1 << 24)) >> 25;
  145. $h2 += $carry1;
  146. $h1 -= $carry1 << 25;
  147. /** @var int $carry3 */
  148. $carry3 = ($h3 + (1 << 24)) >> 25;
  149. $h4 += $carry3;
  150. $h3 -= $carry3 << 25;
  151. /** @var int $carry5 */
  152. $carry5 = ($h5 + (1 << 24)) >> 25;
  153. $h6 += $carry5;
  154. $h5 -= $carry5 << 25;
  155. /** @var int $carry7 */
  156. $carry7 = ($h7 + (1 << 24)) >> 25;
  157. $h8 += $carry7;
  158. $h7 -= $carry7 << 25;
  159. /** @var int $carry0 */
  160. $carry0 = ($h0 + (1 << 25)) >> 26;
  161. $h1 += $carry0;
  162. $h0 -= $carry0 << 26;
  163. /** @var int $carry2 */
  164. $carry2 = ($h2 + (1 << 25)) >> 26;
  165. $h3 += $carry2;
  166. $h2 -= $carry2 << 26;
  167. /** @var int $carry4 */
  168. $carry4 = ($h4 + (1 << 25)) >> 26;
  169. $h5 += $carry4;
  170. $h4 -= $carry4 << 26;
  171. /** @var int $carry6 */
  172. $carry6 = ($h6 + (1 << 25)) >> 26;
  173. $h7 += $carry6;
  174. $h6 -= $carry6 << 26;
  175. /** @var int $carry8 */
  176. $carry8 = ($h8 + (1 << 25)) >> 26;
  177. $h9 += $carry8;
  178. $h8 -= $carry8 << 26;
  179. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
  180. array(
  181. (int) $h0,
  182. (int) $h1,
  183. (int) $h2,
  184. (int) $h3,
  185. (int) $h4,
  186. (int) $h5,
  187. (int) $h6,
  188. (int) $h7,
  189. (int) $h8,
  190. (int) $h9
  191. )
  192. );
  193. }
  194. /**
  195. * Convert a field element to a byte string.
  196. *
  197. * @internal You should not use this directly from another application
  198. *
  199. * @param ParagonIE_Sodium_Core_Curve25519_Fe $h
  200. * @return string
  201. */
  202. public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe $h)
  203. {
  204. /** @var int $h0 */
  205. $h0 = (int) $h[0];
  206. /** @var int $h1 */
  207. $h1 = (int) $h[1];
  208. /** @var int $h2 */
  209. $h2 = (int) $h[2];
  210. /** @var int $h3 */
  211. $h3 = (int) $h[3];
  212. /** @var int $h4 */
  213. $h4 = (int) $h[4];
  214. /** @var int $h5 */
  215. $h5 = (int) $h[5];
  216. /** @var int $h6 */
  217. $h6 = (int) $h[6];
  218. /** @var int $h7 */
  219. $h7 = (int) $h[7];
  220. /** @var int $h8 */
  221. $h8 = (int) $h[8];
  222. /** @var int $h9 */
  223. $h9 = (int) $h[9];
  224. /** @var int $q */
  225. $q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25;
  226. /** @var int $q */
  227. $q = ($h0 + $q) >> 26;
  228. /** @var int $q */
  229. $q = ($h1 + $q) >> 25;
  230. /** @var int $q */
  231. $q = ($h2 + $q) >> 26;
  232. /** @var int $q */
  233. $q = ($h3 + $q) >> 25;
  234. /** @var int $q */
  235. $q = ($h4 + $q) >> 26;
  236. /** @var int $q */
  237. $q = ($h5 + $q) >> 25;
  238. /** @var int $q */
  239. $q = ($h6 + $q) >> 26;
  240. /** @var int $q */
  241. $q = ($h7 + $q) >> 25;
  242. /** @var int $q */
  243. $q = ($h8 + $q) >> 26;
  244. /** @var int $q */
  245. $q = ($h9 + $q) >> 25;
  246. $h0 += self::mul($q, 19, 5);
  247. /** @var int $carry0 */
  248. $carry0 = $h0 >> 26;
  249. $h1 += $carry0;
  250. $h0 -= $carry0 << 26;
  251. /** @var int $carry1 */
  252. $carry1 = $h1 >> 25;
  253. $h2 += $carry1;
  254. $h1 -= $carry1 << 25;
  255. /** @var int $carry2 */
  256. $carry2 = $h2 >> 26;
  257. $h3 += $carry2;
  258. $h2 -= $carry2 << 26;
  259. /** @var int $carry3 */
  260. $carry3 = $h3 >> 25;
  261. $h4 += $carry3;
  262. $h3 -= $carry3 << 25;
  263. /** @var int $carry4 */
  264. $carry4 = $h4 >> 26;
  265. $h5 += $carry4;
  266. $h4 -= $carry4 << 26;
  267. /** @var int $carry5 */
  268. $carry5 = $h5 >> 25;
  269. $h6 += $carry5;
  270. $h5 -= $carry5 << 25;
  271. /** @var int $carry6 */
  272. $carry6 = $h6 >> 26;
  273. $h7 += $carry6;
  274. $h6 -= $carry6 << 26;
  275. /** @var int $carry7 */
  276. $carry7 = $h7 >> 25;
  277. $h8 += $carry7;
  278. $h7 -= $carry7 << 25;
  279. /** @var int $carry8 */
  280. $carry8 = $h8 >> 26;
  281. $h9 += $carry8;
  282. $h8 -= $carry8 << 26;
  283. /** @var int $carry9 */
  284. $carry9 = $h9 >> 25;
  285. $h9 -= $carry9 << 25;
  286. /**
  287. * @var array<int, int>
  288. */
  289. $s = array(
  290. (int) (($h0 >> 0) & 0xff),
  291. (int) (($h0 >> 8) & 0xff),
  292. (int) (($h0 >> 16) & 0xff),
  293. (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
  294. (int) (($h1 >> 6) & 0xff),
  295. (int) (($h1 >> 14) & 0xff),
  296. (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
  297. (int) (($h2 >> 5) & 0xff),
  298. (int) (($h2 >> 13) & 0xff),
  299. (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
  300. (int) (($h3 >> 3) & 0xff),
  301. (int) (($h3 >> 11) & 0xff),
  302. (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
  303. (int) (($h4 >> 2) & 0xff),
  304. (int) (($h4 >> 10) & 0xff),
  305. (int) (($h4 >> 18) & 0xff),
  306. (int) (($h5 >> 0) & 0xff),
  307. (int) (($h5 >> 8) & 0xff),
  308. (int) (($h5 >> 16) & 0xff),
  309. (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
  310. (int) (($h6 >> 7) & 0xff),
  311. (int) (($h6 >> 15) & 0xff),
  312. (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
  313. (int) (($h7 >> 5) & 0xff),
  314. (int) (($h7 >> 13) & 0xff),
  315. (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
  316. (int) (($h8 >> 4) & 0xff),
  317. (int) (($h8 >> 12) & 0xff),
  318. (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
  319. (int) (($h9 >> 2) & 0xff),
  320. (int) (($h9 >> 10) & 0xff),
  321. (int) (($h9 >> 18) & 0xff)
  322. );
  323. return self::intArrayToString($s);
  324. }
  325. /**
  326. * Is a field element negative? (1 = yes, 0 = no. Used in calculations.)
  327. *
  328. * @internal You should not use this directly from another application
  329. *
  330. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  331. * @return int
  332. * @throws SodiumException
  333. * @throws TypeError
  334. */
  335. public static function fe_isnegative(ParagonIE_Sodium_Core_Curve25519_Fe $f)
  336. {
  337. $str = self::fe_tobytes($f);
  338. return (int) (self::chrToInt($str[0]) & 1);
  339. }
  340. /**
  341. * Returns 0 if this field element results in all NUL bytes.
  342. *
  343. * @internal You should not use this directly from another application
  344. *
  345. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  346. * @return bool
  347. * @throws SodiumException
  348. * @throws TypeError
  349. */
  350. public static function fe_isnonzero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
  351. {
  352. static $zero;
  353. if ($zero === null) {
  354. $zero = str_repeat("\x00", 32);
  355. }
  356. /** @var string $zero */
  357. /** @var string $str */
  358. $str = self::fe_tobytes($f);
  359. return !self::verify_32($str, (string) $zero);
  360. }
  361. /**
  362. * Multiply two field elements
  363. *
  364. * h = f * g
  365. *
  366. * @internal You should not use this directly from another application
  367. *
  368. * @security Is multiplication a source of timing leaks? If so, can we do
  369. * anything to prevent that from happening?
  370. *
  371. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  372. * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
  373. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  374. */
  375. public static function fe_mul(
  376. ParagonIE_Sodium_Core_Curve25519_Fe $f,
  377. ParagonIE_Sodium_Core_Curve25519_Fe $g
  378. ) {
  379. /** @var int $f0 */
  380. $f0 = $f[0];
  381. /** @var int $f1 */
  382. $f1 = $f[1];
  383. /** @var int $f2 */
  384. $f2 = $f[2];
  385. /** @var int $f3 */
  386. $f3 = $f[3];
  387. /** @var int $f4 */
  388. $f4 = $f[4];
  389. /** @var int $f5 */
  390. $f5 = $f[5];
  391. /** @var int $f6 */
  392. $f6 = $f[6];
  393. /** @var int $f7 */
  394. $f7 = $f[7];
  395. /** @var int $f8 */
  396. $f8 = $f[8];
  397. /** @var int $f9 */
  398. $f9 = $f[9];
  399. /** @var int $g0 */
  400. $g0 = $g[0];
  401. /** @var int $g1 */
  402. $g1 = $g[1];
  403. /** @var int $g2 */
  404. $g2 = $g[2];
  405. /** @var int $g3 */
  406. $g3 = $g[3];
  407. /** @var int $g4 */
  408. $g4 = $g[4];
  409. /** @var int $g5 */
  410. $g5 = $g[5];
  411. /** @var int $g6 */
  412. $g6 = $g[6];
  413. /** @var int $g7 */
  414. $g7 = $g[7];
  415. /** @var int $g8 */
  416. $g8 = $g[8];
  417. /** @var int $g9 */
  418. $g9 = $g[9];
  419. $g1_19 = self::mul($g1, 19, 5);
  420. $g2_19 = self::mul($g2, 19, 5);
  421. $g3_19 = self::mul($g3, 19, 5);
  422. $g4_19 = self::mul($g4, 19, 5);
  423. $g5_19 = self::mul($g5, 19, 5);
  424. $g6_19 = self::mul($g6, 19, 5);
  425. $g7_19 = self::mul($g7, 19, 5);
  426. $g8_19 = self::mul($g8, 19, 5);
  427. $g9_19 = self::mul($g9, 19, 5);
  428. /** @var int $f1_2 */
  429. $f1_2 = $f1 << 1;
  430. /** @var int $f3_2 */
  431. $f3_2 = $f3 << 1;
  432. /** @var int $f5_2 */
  433. $f5_2 = $f5 << 1;
  434. /** @var int $f7_2 */
  435. $f7_2 = $f7 << 1;
  436. /** @var int $f9_2 */
  437. $f9_2 = $f9 << 1;
  438. $f0g0 = self::mul($f0, $g0, 26);
  439. $f0g1 = self::mul($f0, $g1, 25);
  440. $f0g2 = self::mul($f0, $g2, 26);
  441. $f0g3 = self::mul($f0, $g3, 25);
  442. $f0g4 = self::mul($f0, $g4, 26);
  443. $f0g5 = self::mul($f0, $g5, 25);
  444. $f0g6 = self::mul($f0, $g6, 26);
  445. $f0g7 = self::mul($f0, $g7, 25);
  446. $f0g8 = self::mul($f0, $g8, 26);
  447. $f0g9 = self::mul($f0, $g9, 26);
  448. $f1g0 = self::mul($f1, $g0, 26);
  449. $f1g1_2 = self::mul($f1_2, $g1, 25);
  450. $f1g2 = self::mul($f1, $g2, 26);
  451. $f1g3_2 = self::mul($f1_2, $g3, 25);
  452. $f1g4 = self::mul($f1, $g4, 26);
  453. $f1g5_2 = self::mul($f1_2, $g5, 25);
  454. $f1g6 = self::mul($f1, $g6, 26);
  455. $f1g7_2 = self::mul($f1_2, $g7, 25);
  456. $f1g8 = self::mul($f1, $g8, 26);
  457. $f1g9_38 = self::mul($g9_19, $f1_2, 26);
  458. $f2g0 = self::mul($f2, $g0, 26);
  459. $f2g1 = self::mul($f2, $g1, 25);
  460. $f2g2 = self::mul($f2, $g2, 26);
  461. $f2g3 = self::mul($f2, $g3, 25);
  462. $f2g4 = self::mul($f2, $g4, 26);
  463. $f2g5 = self::mul($f2, $g5, 25);
  464. $f2g6 = self::mul($f2, $g6, 26);
  465. $f2g7 = self::mul($f2, $g7, 25);
  466. $f2g8_19 = self::mul($g8_19, $f2, 26);
  467. $f2g9_19 = self::mul($g9_19, $f2, 26);
  468. $f3g0 = self::mul($f3, $g0, 26);
  469. $f3g1_2 = self::mul($f3_2, $g1, 25);
  470. $f3g2 = self::mul($f3, $g2, 26);
  471. $f3g3_2 = self::mul($f3_2, $g3, 25);
  472. $f3g4 = self::mul($f3, $g4, 26);
  473. $f3g5_2 = self::mul($f3_2, $g5, 25);
  474. $f3g6 = self::mul($f3, $g6, 26);
  475. $f3g7_38 = self::mul($g7_19, $f3_2, 26);
  476. $f3g8_19 = self::mul($g8_19, $f3, 25);
  477. $f3g9_38 = self::mul($g9_19, $f3_2, 26);
  478. $f4g0 = self::mul($f4, $g0, 26);
  479. $f4g1 = self::mul($f4, $g1, 25);
  480. $f4g2 = self::mul($f4, $g2, 26);
  481. $f4g3 = self::mul($f4, $g3, 25);
  482. $f4g4 = self::mul($f4, $g4, 26);
  483. $f4g5 = self::mul($f4, $g5, 25);
  484. $f4g6_19 = self::mul($g6_19, $f4, 26);
  485. $f4g7_19 = self::mul($g7_19, $f4, 26);
  486. $f4g8_19 = self::mul($g8_19, $f4, 26);
  487. $f4g9_19 = self::mul($g9_19, $f4, 26);
  488. $f5g0 = self::mul($f5, $g0, 26);
  489. $f5g1_2 = self::mul($f5_2, $g1, 25);
  490. $f5g2 = self::mul($f5, $g2, 26);
  491. $f5g3_2 = self::mul($f5_2, $g3, 25);
  492. $f5g4 = self::mul($f5, $g4, 26);
  493. $f5g5_38 = self::mul($g5_19, $f5_2, 26);
  494. $f5g6_19 = self::mul($g6_19, $f5, 25);
  495. $f5g7_38 = self::mul($g7_19, $f5_2, 26);
  496. $f5g8_19 = self::mul($g8_19, $f5, 25);
  497. $f5g9_38 = self::mul($g9_19, $f5_2, 26);
  498. $f6g0 = self::mul($f6, $g0, 26);
  499. $f6g1 = self::mul($f6, $g1, 25);
  500. $f6g2 = self::mul($f6, $g2, 26);
  501. $f6g3 = self::mul($f6, $g3, 25);
  502. $f6g4_19 = self::mul($g4_19, $f6, 26);
  503. $f6g5_19 = self::mul($g5_19, $f6, 26);
  504. $f6g6_19 = self::mul($g6_19, $f6, 26);
  505. $f6g7_19 = self::mul($g7_19, $f6, 26);
  506. $f6g8_19 = self::mul($g8_19, $f6, 26);
  507. $f6g9_19 = self::mul($g9_19, $f6, 26);
  508. $f7g0 = self::mul($f7, $g0, 26);
  509. $f7g1_2 = self::mul($f7_2, $g1, 25);
  510. $f7g2 = self::mul($f7, $g2, 26);
  511. $f7g3_38 = self::mul($g3_19, $f7_2, 26);
  512. $f7g4_19 = self::mul($g4_19, $f7, 26);
  513. $f7g5_38 = self::mul($g5_19, $f7_2, 26);
  514. $f7g6_19 = self::mul($g6_19, $f7, 25);
  515. $f7g7_38 = self::mul($g7_19, $f7_2, 26);
  516. $f7g8_19 = self::mul($g8_19, $f7, 25);
  517. $f7g9_38 = self::mul($g9_19,$f7_2, 26);
  518. $f8g0 = self::mul($f8, $g0, 26);
  519. $f8g1 = self::mul($f8, $g1, 25);
  520. $f8g2_19 = self::mul($g2_19, $f8, 26);
  521. $f8g3_19 = self::mul($g3_19, $f8, 26);
  522. $f8g4_19 = self::mul($g4_19, $f8, 26);
  523. $f8g5_19 = self::mul($g5_19, $f8, 26);
  524. $f8g6_19 = self::mul($g6_19, $f8, 26);
  525. $f8g7_19 = self::mul($g7_19, $f8, 26);
  526. $f8g8_19 = self::mul($g8_19, $f8, 26);
  527. $f8g9_19 = self::mul($g9_19, $f8, 26);
  528. $f9g0 = self::mul($f9, $g0, 26);
  529. $f9g1_38 = self::mul($g1_19, $f9_2, 26);
  530. $f9g2_19 = self::mul($g2_19, $f9, 25);
  531. $f9g3_38 = self::mul($g3_19, $f9_2, 26);
  532. $f9g4_19 = self::mul($g4_19, $f9, 25);
  533. $f9g5_38 = self::mul($g5_19, $f9_2, 26);
  534. $f9g6_19 = self::mul($g6_19, $f9, 25);
  535. $f9g7_38 = self::mul($g7_19, $f9_2, 26);
  536. $f9g8_19 = self::mul($g8_19, $f9, 25);
  537. $f9g9_38 = self::mul($g9_19, $f9_2, 26);
  538. $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
  539. $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
  540. $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
  541. $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
  542. $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
  543. $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
  544. $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38;
  545. $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19;
  546. $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38;
  547. $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ;
  548. /** @var int $carry0 */
  549. $carry0 = ($h0 + (1 << 25)) >> 26;
  550. $h1 += $carry0;
  551. $h0 -= $carry0 << 26;
  552. /** @var int $carry4 */
  553. $carry4 = ($h4 + (1 << 25)) >> 26;
  554. $h5 += $carry4;
  555. $h4 -= $carry4 << 26;
  556. /** @var int $carry1 */
  557. $carry1 = ($h1 + (1 << 24)) >> 25;
  558. $h2 += $carry1;
  559. $h1 -= $carry1 << 25;
  560. /** @var int $carry5 */
  561. $carry5 = ($h5 + (1 << 24)) >> 25;
  562. $h6 += $carry5;
  563. $h5 -= $carry5 << 25;
  564. /** @var int $carry2 */
  565. $carry2 = ($h2 + (1 << 25)) >> 26;
  566. $h3 += $carry2;
  567. $h2 -= $carry2 << 26;
  568. /** @var int $carry6 */
  569. $carry6 = ($h6 + (1 << 25)) >> 26;
  570. $h7 += $carry6;
  571. $h6 -= $carry6 << 26;
  572. /** @var int $carry3 */
  573. $carry3 = ($h3 + (1 << 24)) >> 25;
  574. $h4 += $carry3;
  575. $h3 -= $carry3 << 25;
  576. /** @var int $carry7 */
  577. $carry7 = ($h7 + (1 << 24)) >> 25;
  578. $h8 += $carry7;
  579. $h7 -= $carry7 << 25;
  580. /** @var int $carry4 */
  581. $carry4 = ($h4 + (1 << 25)) >> 26;
  582. $h5 += $carry4;
  583. $h4 -= $carry4 << 26;
  584. /** @var int $carry8 */
  585. $carry8 = ($h8 + (1 << 25)) >> 26;
  586. $h9 += $carry8;
  587. $h8 -= $carry8 << 26;
  588. /** @var int $carry9 */
  589. $carry9 = ($h9 + (1 << 24)) >> 25;
  590. $h0 += self::mul($carry9, 19, 5);
  591. $h9 -= $carry9 << 25;
  592. /** @var int $carry0 */
  593. $carry0 = ($h0 + (1 << 25)) >> 26;
  594. $h1 += $carry0;
  595. $h0 -= $carry0 << 26;
  596. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
  597. array(
  598. (int) $h0,
  599. (int) $h1,
  600. (int) $h2,
  601. (int) $h3,
  602. (int) $h4,
  603. (int) $h5,
  604. (int) $h6,
  605. (int) $h7,
  606. (int) $h8,
  607. (int) $h9
  608. )
  609. );
  610. }
  611. /**
  612. * Get the negative values for each piece of the field element.
  613. *
  614. * h = -f
  615. *
  616. * @internal You should not use this directly from another application
  617. *
  618. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  619. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  620. * @psalm-suppress MixedAssignment
  621. */
  622. public static function fe_neg(ParagonIE_Sodium_Core_Curve25519_Fe $f)
  623. {
  624. $h = new ParagonIE_Sodium_Core_Curve25519_Fe();
  625. for ($i = 0; $i < 10; ++$i) {
  626. $h[$i] = -$f[$i];
  627. }
  628. return $h;
  629. }
  630. /**
  631. * Square a field element
  632. *
  633. * h = f * f
  634. *
  635. * @internal You should not use this directly from another application
  636. *
  637. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  638. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  639. */
  640. public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f)
  641. {
  642. $f0 = (int) $f[0];
  643. $f1 = (int) $f[1];
  644. $f2 = (int) $f[2];
  645. $f3 = (int) $f[3];
  646. $f4 = (int) $f[4];
  647. $f5 = (int) $f[5];
  648. $f6 = (int) $f[6];
  649. $f7 = (int) $f[7];
  650. $f8 = (int) $f[8];
  651. $f9 = (int) $f[9];
  652. /** @var int $f0_2 */
  653. $f0_2 = $f0 << 1;
  654. /** @var int $f1_2 */
  655. $f1_2 = $f1 << 1;
  656. /** @var int $f2_2 */
  657. $f2_2 = $f2 << 1;
  658. /** @var int $f3_2 */
  659. $f3_2 = $f3 << 1;
  660. /** @var int $f4_2 */
  661. $f4_2 = $f4 << 1;
  662. /** @var int $f5_2 */
  663. $f5_2 = $f5 << 1;
  664. /** @var int $f6_2 */
  665. $f6_2 = $f6 << 1;
  666. /** @var int $f7_2 */
  667. $f7_2 = $f7 << 1;
  668. $f5_38 = self::mul($f5, 38, 6);
  669. $f6_19 = self::mul($f6, 19, 5);
  670. $f7_38 = self::mul($f7, 38, 6);
  671. $f8_19 = self::mul($f8, 19, 5);
  672. $f9_38 = self::mul($f9, 38, 6);
  673. $f0f0 = self::mul($f0, $f0, 25);
  674. $f0f1_2 = self::mul($f0_2, $f1, 24);
  675. $f0f2_2 = self::mul($f0_2, $f2, 25);
  676. $f0f3_2 = self::mul($f0_2, $f3, 24);
  677. $f0f4_2 = self::mul($f0_2, $f4, 25);
  678. $f0f5_2 = self::mul($f0_2, $f5, 25);
  679. $f0f6_2 = self::mul($f0_2, $f6, 25);
  680. $f0f7_2 = self::mul($f0_2, $f7, 24);
  681. $f0f8_2 = self::mul($f0_2, $f8, 25);
  682. $f0f9_2 = self::mul($f0_2, $f9, 25);
  683. $f1f1_2 = self::mul($f1_2, $f1, 24);
  684. $f1f2_2 = self::mul($f1_2, $f2, 25);
  685. $f1f3_4 = self::mul($f1_2, $f3_2, 25);
  686. $f1f4_2 = self::mul($f1_2, $f4, 25);
  687. $f1f5_4 = self::mul($f1_2, $f5_2, 26);
  688. $f1f6_2 = self::mul($f1_2, $f6, 25);
  689. $f1f7_4 = self::mul($f1_2, $f7_2, 25);
  690. $f1f8_2 = self::mul($f1_2, $f8, 25);
  691. $f1f9_76 = self::mul($f9_38, $f1_2, 25);
  692. $f2f2 = self::mul($f2, $f2, 25);
  693. $f2f3_2 = self::mul($f2_2, $f3, 24);
  694. $f2f4_2 = self::mul($f2_2, $f4, 25);
  695. $f2f5_2 = self::mul($f2_2, $f5, 25);
  696. $f2f6_2 = self::mul($f2_2, $f6, 25);
  697. $f2f7_2 = self::mul($f2_2, $f7, 24);
  698. $f2f8_38 = self::mul($f8_19, $f2_2, 26);
  699. $f2f9_38 = self::mul($f9_38, $f2, 25);
  700. $f3f3_2 = self::mul($f3_2, $f3, 24);
  701. $f3f4_2 = self::mul($f3_2, $f4, 25);
  702. $f3f5_4 = self::mul($f3_2, $f5_2, 26);
  703. $f3f6_2 = self::mul($f3_2, $f6, 25);
  704. $f3f7_76 = self::mul($f7_38, $f3_2, 25);
  705. $f3f8_38 = self::mul($f8_19, $f3_2, 25);
  706. $f3f9_76 = self::mul($f9_38, $f3_2, 25);
  707. $f4f4 = self::mul($f4, $f4, 25);
  708. $f4f5_2 = self::mul($f4_2, $f5, 25);
  709. $f4f6_38 = self::mul($f6_19, $f4_2, 26);
  710. $f4f7_38 = self::mul($f7_38, $f4, 25);
  711. $f4f8_38 = self::mul($f8_19, $f4_2, 26);
  712. $f4f9_38 = self::mul($f9_38, $f4, 25);
  713. $f5f5_38 = self::mul($f5_38, $f5, 25);
  714. $f5f6_38 = self::mul($f6_19, $f5_2, 26);
  715. $f5f7_76 = self::mul($f7_38, $f5_2, 26);
  716. $f5f8_38 = self::mul($f8_19, $f5_2, 26);
  717. $f5f9_76 = self::mul($f9_38, $f5_2, 26);
  718. $f6f6_19 = self::mul($f6_19, $f6, 25);
  719. $f6f7_38 = self::mul($f7_38, $f6, 25);
  720. $f6f8_38 = self::mul($f8_19, $f6_2, 26);
  721. $f6f9_38 = self::mul($f9_38, $f6, 25);
  722. $f7f7_38 = self::mul($f7_38, $f7, 24);
  723. $f7f8_38 = self::mul($f8_19, $f7_2, 25);
  724. $f7f9_76 = self::mul($f9_38, $f7_2, 25);
  725. $f8f8_19 = self::mul($f8_19, $f8, 25);
  726. $f8f9_38 = self::mul($f9_38, $f8, 25);
  727. $f9f9_38 = self::mul($f9_38, $f9, 25);
  728. $h0 = $f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38;
  729. $h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38;
  730. $h2 = $f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19;
  731. $h3 = $f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38;
  732. $h4 = $f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38;
  733. $h5 = $f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38;
  734. $h6 = $f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19;
  735. $h7 = $f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38;
  736. $h8 = $f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38;
  737. $h9 = $f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2;
  738. /** @var int $carry0 */
  739. $carry0 = ($h0 + (1 << 25)) >> 26;
  740. $h1 += $carry0;
  741. $h0 -= $carry0 << 26;
  742. /** @var int $carry4 */
  743. $carry4 = ($h4 + (1 << 25)) >> 26;
  744. $h5 += $carry4;
  745. $h4 -= $carry4 << 26;
  746. /** @var int $carry1 */
  747. $carry1 = ($h1 + (1 << 24)) >> 25;
  748. $h2 += $carry1;
  749. $h1 -= $carry1 << 25;
  750. /** @var int $carry5 */
  751. $carry5 = ($h5 + (1 << 24)) >> 25;
  752. $h6 += $carry5;
  753. $h5 -= $carry5 << 25;
  754. /** @var int $carry2 */
  755. $carry2 = ($h2 + (1 << 25)) >> 26;
  756. $h3 += $carry2;
  757. $h2 -= $carry2 << 26;
  758. /** @var int $carry6 */
  759. $carry6 = ($h6 + (1 << 25)) >> 26;
  760. $h7 += $carry6;
  761. $h6 -= $carry6 << 26;
  762. /** @var int $carry3 */
  763. $carry3 = ($h3 + (1 << 24)) >> 25;
  764. $h4 += $carry3;
  765. $h3 -= $carry3 << 25;
  766. /** @var int $carry7 */
  767. $carry7 = ($h7 + (1 << 24)) >> 25;
  768. $h8 += $carry7;
  769. $h7 -= $carry7 << 25;
  770. /** @var int $carry4 */
  771. $carry4 = ($h4 + (1 << 25)) >> 26;
  772. $h5 += $carry4;
  773. $h4 -= $carry4 << 26;
  774. /** @var int $carry8 */
  775. $carry8 = ($h8 + (1 << 25)) >> 26;
  776. $h9 += $carry8;
  777. $h8 -= $carry8 << 26;
  778. /** @var int $carry9 */
  779. $carry9 = ($h9 + (1 << 24)) >> 25;
  780. $h0 += self::mul($carry9, 19, 5);
  781. $h9 -= $carry9 << 25;
  782. /** @var int $carry0 */
  783. $carry0 = ($h0 + (1 << 25)) >> 26;
  784. $h1 += $carry0;
  785. $h0 -= $carry0 << 26;
  786. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
  787. array(
  788. (int) $h0,
  789. (int) $h1,
  790. (int) $h2,
  791. (int) $h3,
  792. (int) $h4,
  793. (int) $h5,
  794. (int) $h6,
  795. (int) $h7,
  796. (int) $h8,
  797. (int) $h9
  798. )
  799. );
  800. }
  801. /**
  802. * Square and double a field element
  803. *
  804. * h = 2 * f * f
  805. *
  806. * @internal You should not use this directly from another application
  807. *
  808. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  809. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  810. */
  811. public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f)
  812. {
  813. $f0 = (int) $f[0];
  814. $f1 = (int) $f[1];
  815. $f2 = (int) $f[2];
  816. $f3 = (int) $f[3];
  817. $f4 = (int) $f[4];
  818. $f5 = (int) $f[5];
  819. $f6 = (int) $f[6];
  820. $f7 = (int) $f[7];
  821. $f8 = (int) $f[8];
  822. $f9 = (int) $f[9];
  823. /** @var int $f0_2 */
  824. $f0_2 = $f0 << 1;
  825. /** @var int $f1_2 */
  826. $f1_2 = $f1 << 1;
  827. /** @var int $f2_2 */
  828. $f2_2 = $f2 << 1;
  829. /** @var int $f3_2 */
  830. $f3_2 = $f3 << 1;
  831. /** @var int $f4_2 */
  832. $f4_2 = $f4 << 1;
  833. /** @var int $f5_2 */
  834. $f5_2 = $f5 << 1;
  835. /** @var int $f6_2 */
  836. $f6_2 = $f6 << 1;
  837. /** @var int $f7_2 */
  838. $f7_2 = $f7 << 1;
  839. $f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */
  840. $f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */
  841. $f7_38 = self::mul($f7, 38, 6); /* 1.959375*2^30 */
  842. $f8_19 = self::mul($f8, 19, 5); /* 1.959375*2^30 */
  843. $f9_38 = self::mul($f9, 38, 6); /* 1.959375*2^30 */
  844. $f0f0 = self::mul($f0, $f0, 24);
  845. $f0f1_2 = self::mul($f0_2, $f1, 24);
  846. $f0f2_2 = self::mul($f0_2, $f2, 24);
  847. $f0f3_2 = self::mul($f0_2, $f3, 24);
  848. $f0f4_2 = self::mul($f0_2, $f4, 24);
  849. $f0f5_2 = self::mul($f0_2, $f5, 24);
  850. $f0f6_2 = self::mul($f0_2, $f6, 24);
  851. $f0f7_2 = self::mul($f0_2, $f7, 24);
  852. $f0f8_2 = self::mul($f0_2, $f8, 24);
  853. $f0f9_2 = self::mul($f0_2, $f9, 24);
  854. $f1f1_2 = self::mul($f1_2, $f1, 24);
  855. $f1f2_2 = self::mul($f1_2, $f2, 24);
  856. $f1f3_4 = self::mul($f1_2, $f3_2, 24);
  857. $f1f4_2 = self::mul($f1_2, $f4, 24);
  858. $f1f5_4 = self::mul($f1_2, $f5_2, 24);
  859. $f1f6_2 = self::mul($f1_2, $f6, 24);
  860. $f1f7_4 = self::mul($f1_2, $f7_2, 24);
  861. $f1f8_2 = self::mul($f1_2, $f8, 24);
  862. $f1f9_76 = self::mul($f9_38, $f1_2, 24);
  863. $f2f2 = self::mul($f2, $f2, 24);
  864. $f2f3_2 = self::mul($f2_2, $f3, 24);
  865. $f2f4_2 = self::mul($f2_2, $f4, 24);
  866. $f2f5_2 = self::mul($f2_2, $f5, 24);
  867. $f2f6_2 = self::mul($f2_2, $f6, 24);
  868. $f2f7_2 = self::mul($f2_2, $f7, 24);
  869. $f2f8_38 = self::mul($f8_19, $f2_2, 25);
  870. $f2f9_38 = self::mul($f9_38, $f2, 24);
  871. $f3f3_2 = self::mul($f3_2, $f3, 24);
  872. $f3f4_2 = self::mul($f3_2, $f4, 24);
  873. $f3f5_4 = self::mul($f3_2, $f5_2, 24);
  874. $f3f6_2 = self::mul($f3_2, $f6, 24);
  875. $f3f7_76 = self::mul($f7_38, $f3_2, 24);
  876. $f3f8_38 = self::mul($f8_19, $f3_2, 24);
  877. $f3f9_76 = self::mul($f9_38, $f3_2, 24);
  878. $f4f4 = self::mul($f4, $f4, 24);
  879. $f4f5_2 = self::mul($f4_2, $f5, 24);
  880. $f4f6_38 = self::mul($f6_19, $f4_2, 25);
  881. $f4f7_38 = self::mul($f7_38, $f4, 24);
  882. $f4f8_38 = self::mul($f8_19, $f4_2, 25);
  883. $f4f9_38 = self::mul($f9_38, $f4, 24);
  884. $f5f5_38 = self::mul($f5_38, $f5, 24);
  885. $f5f6_38 = self::mul($f6_19, $f5_2, 24);
  886. $f5f7_76 = self::mul($f7_38, $f5_2, 24);
  887. $f5f8_38 = self::mul($f8_19, $f5_2, 24);
  888. $f5f9_76 = self::mul($f9_38, $f5_2, 24);
  889. $f6f6_19 = self::mul($f6_19, $f6, 24);
  890. $f6f7_38 = self::mul($f7_38, $f6, 24);
  891. $f6f8_38 = self::mul($f8_19, $f6_2, 25);
  892. $f6f9_38 = self::mul($f9_38, $f6, 24);
  893. $f7f7_38 = self::mul($f7_38, $f7, 24);
  894. $f7f8_38 = self::mul($f8_19, $f7_2, 24);
  895. $f7f9_76 = self::mul($f9_38, $f7_2, 24);
  896. $f8f8_19 = self::mul($f8_19, $f8, 24);
  897. $f8f9_38 = self::mul($f9_38, $f8, 24);
  898. $f9f9_38 = self::mul($f9_38, $f9, 24);
  899. /** @var int $h0 */
  900. $h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38) << 1;
  901. /** @var int $h1 */
  902. $h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38) << 1;
  903. /** @var int $h2 */
  904. $h2 = (int) ($f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19) << 1;
  905. /** @var int $h3 */
  906. $h3 = (int) ($f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38) << 1;
  907. /** @var int $h4 */
  908. $h4 = (int) ($f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38) << 1;
  909. /** @var int $h5 */
  910. $h5 = (int) ($f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38) << 1;
  911. /** @var int $h6 */
  912. $h6 = (int) ($f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19) << 1;
  913. /** @var int $h7 */
  914. $h7 = (int) ($f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38) << 1;
  915. /** @var int $h8 */
  916. $h8 = (int) ($f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38) << 1;
  917. /** @var int $h9 */
  918. $h9 = (int) ($f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2) << 1;
  919. /** @var int $carry0 */
  920. $carry0 = ($h0 + (1 << 25)) >> 26;
  921. $h1 += $carry0;
  922. $h0 -= $carry0 << 26;
  923. /** @var int $carry4 */
  924. $carry4 = ($h4 + (1 << 25)) >> 26;
  925. $h5 += $carry4;
  926. $h4 -= $carry4 << 26;
  927. /** @var int $carry1 */
  928. $carry1 = ($h1 + (1 << 24)) >> 25;
  929. $h2 += $carry1;
  930. $h1 -= $carry1 << 25;
  931. /** @var int $carry5 */
  932. $carry5 = ($h5 + (1 << 24)) >> 25;
  933. $h6 += $carry5;
  934. $h5 -= $carry5 << 25;
  935. /** @var int $carry2 */
  936. $carry2 = ($h2 + (1 << 25)) >> 26;
  937. $h3 += $carry2;
  938. $h2 -= $carry2 << 26;
  939. /** @var int $carry6 */
  940. $carry6 = ($h6 + (1 << 25)) >> 26;
  941. $h7 += $carry6;
  942. $h6 -= $carry6 << 26;
  943. /** @var int $carry3 */
  944. $carry3 = ($h3 + (1 << 24)) >> 25;
  945. $h4 += $carry3;
  946. $h3 -= $carry3 << 25;
  947. /** @var int $carry7 */
  948. $carry7 = ($h7 + (1 << 24)) >> 25;
  949. $h8 += $carry7;
  950. $h7 -= $carry7 << 25;
  951. /** @var int $carry4 */
  952. $carry4 = ($h4 + (1 << 25)) >> 26;
  953. $h5 += $carry4;
  954. $h4 -= $carry4 << 26;
  955. /** @var int $carry8 */
  956. $carry8 = ($h8 + (1 << 25)) >> 26;
  957. $h9 += $carry8;
  958. $h8 -= $carry8 << 26;
  959. /** @var int $carry9 */
  960. $carry9 = ($h9 + (1 << 24)) >> 25;
  961. $h0 += self::mul($carry9, 19, 5);
  962. $h9 -= $carry9 << 25;
  963. /** @var int $carry0 */
  964. $carry0 = ($h0 + (1 << 25)) >> 26;
  965. $h1 += $carry0;
  966. $h0 -= $carry0 << 26;
  967. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
  968. array(
  969. (int) $h0,
  970. (int) $h1,
  971. (int) $h2,
  972. (int) $h3,
  973. (int) $h4,
  974. (int) $h5,
  975. (int) $h6,
  976. (int) $h7,
  977. (int) $h8,
  978. (int) $h9
  979. )
  980. );
  981. }
  982. /**
  983. * @internal You should not use this directly from another application
  984. *
  985. * @param ParagonIE_Sodium_Core_Curve25519_Fe $Z
  986. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  987. */
  988. public static function fe_invert(ParagonIE_Sodium_Core_Curve25519_Fe $Z)
  989. {
  990. $z = clone $Z;
  991. $t0 = self::fe_sq($z);
  992. $t1 = self::fe_sq($t0);
  993. $t1 = self::fe_sq($t1);
  994. $t1 = self::fe_mul($z, $t1);
  995. $t0 = self::fe_mul($t0, $t1);
  996. $t2 = self::fe_sq($t0);
  997. $t1 = self::fe_mul($t1, $t2);
  998. $t2 = self::fe_sq($t1);
  999. for ($i = 1; $i < 5; ++$i) {
  1000. $t2 = self::fe_sq($t2);
  1001. }
  1002. $t1 = self::fe_mul($t2, $t1);
  1003. $t2 = self::fe_sq($t1);
  1004. for ($i = 1; $i < 10; ++$i) {
  1005. $t2 = self::fe_sq($t2);
  1006. }
  1007. $t2 = self::fe_mul($t2, $t1);
  1008. $t3 = self::fe_sq($t2);
  1009. for ($i = 1; $i < 20; ++$i) {
  1010. $t3 = self::fe_sq($t3);
  1011. }
  1012. $t2 = self::fe_mul($t3, $t2);
  1013. $t2 = self::fe_sq($t2);
  1014. for ($i = 1; $i < 10; ++$i) {
  1015. $t2 = self::fe_sq($t2);
  1016. }
  1017. $t1 = self::fe_mul($t2, $t1);
  1018. $t2 = self::fe_sq($t1);
  1019. for ($i = 1; $i < 50; ++$i) {
  1020. $t2 = self::fe_sq($t2);
  1021. }
  1022. $t2 = self::fe_mul($t2, $t1);
  1023. $t3 = self::fe_sq($t2);
  1024. for ($i = 1; $i < 100; ++$i) {
  1025. $t3 = self::fe_sq($t3);
  1026. }
  1027. $t2 = self::fe_mul($t3, $t2);
  1028. $t2 = self::fe_sq($t2);
  1029. for ($i = 1; $i < 50; ++$i) {
  1030. $t2 = self::fe_sq($t2);
  1031. }
  1032. $t1 = self::fe_mul($t2, $t1);
  1033. $t1 = self::fe_sq($t1);
  1034. for ($i = 1; $i < 5; ++$i) {
  1035. $t1 = self::fe_sq($t1);
  1036. }
  1037. return self::fe_mul($t1, $t0);
  1038. }
  1039. /**
  1040. * @internal You should not use this directly from another application
  1041. *
  1042. * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
  1043. *
  1044. * @param ParagonIE_Sodium_Core_Curve25519_Fe $z
  1045. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  1046. */
  1047. public static function fe_pow22523(ParagonIE_Sodium_Core_Curve25519_Fe $z)
  1048. {
  1049. # fe_sq(t0, z);
  1050. # fe_sq(t1, t0);
  1051. # fe_sq(t1, t1);
  1052. # fe_mul(t1, z, t1);
  1053. # fe_mul(t0, t0, t1);
  1054. # fe_sq(t0, t0);
  1055. # fe_mul(t0, t1, t0);
  1056. # fe_sq(t1, t0);
  1057. $t0 = self::fe_sq($z);
  1058. $t1 = self::fe_sq($t0);
  1059. $t1 = self::fe_sq($t1);
  1060. $t1 = self::fe_mul($z, $t1);
  1061. $t0 = self::fe_mul($t0, $t1);
  1062. $t0 = self::fe_sq($t0);
  1063. $t0 = self::fe_mul($t1, $t0);
  1064. $t1 = self::fe_sq($t0);
  1065. # for (i = 1; i < 5; ++i) {
  1066. # fe_sq(t1, t1);
  1067. # }
  1068. for ($i = 1; $i < 5; ++$i) {
  1069. $t1 = self::fe_sq($t1);
  1070. }
  1071. # fe_mul(t0, t1, t0);
  1072. # fe_sq(t1, t0);
  1073. $t0 = self::fe_mul($t1, $t0);
  1074. $t1 = self::fe_sq($t0);
  1075. # for (i = 1; i < 10; ++i) {
  1076. # fe_sq(t1, t1);
  1077. # }
  1078. for ($i = 1; $i < 10; ++$i) {
  1079. $t1 = self::fe_sq($t1);
  1080. }
  1081. # fe_mul(t1, t1, t0);
  1082. # fe_sq(t2, t1);
  1083. $t1 = self::fe_mul($t1, $t0);
  1084. $t2 = self::fe_sq($t1);
  1085. # for (i = 1; i < 20; ++i) {
  1086. # fe_sq(t2, t2);
  1087. # }
  1088. for ($i = 1; $i < 20; ++$i) {
  1089. $t2 = self::fe_sq($t2);
  1090. }
  1091. # fe_mul(t1, t2, t1);
  1092. # fe_sq(t1, t1);
  1093. $t1 = self::fe_mul($t2, $t1);
  1094. $t1 = self::fe_sq($t1);
  1095. # for (i = 1; i < 10; ++i) {
  1096. # fe_sq(t1, t1);
  1097. # }
  1098. for ($i = 1; $i < 10; ++$i) {
  1099. $t1 = self::fe_sq($t1);
  1100. }
  1101. # fe_mul(t0, t1, t0);
  1102. # fe_sq(t1, t0);
  1103. $t0 = self::fe_mul($t1, $t0);
  1104. $t1 = self::fe_sq($t0);
  1105. # for (i = 1; i < 50; ++i) {
  1106. # fe_sq(t1, t1);
  1107. # }
  1108. for ($i = 1; $i < 50; ++$i) {
  1109. $t1 = self::fe_sq($t1);
  1110. }
  1111. # fe_mul(t1, t1, t0);
  1112. # fe_sq(t2, t1);
  1113. $t1 = self::fe_mul($t1, $t0);
  1114. $t2 = self::fe_sq($t1);
  1115. # for (i = 1; i < 100; ++i) {
  1116. # fe_sq(t2, t2);
  1117. # }
  1118. for ($i = 1; $i < 100; ++$i) {
  1119. $t2 = self::fe_sq($t2);
  1120. }
  1121. # fe_mul(t1, t2, t1);
  1122. # fe_sq(t1, t1);
  1123. $t1 = self::fe_mul($t2, $t1);
  1124. $t1 = self::fe_sq($t1);
  1125. # for (i = 1; i < 50; ++i) {
  1126. # fe_sq(t1, t1);
  1127. # }
  1128. for ($i = 1; $i < 50; ++$i) {
  1129. $t1 = self::fe_sq($t1);
  1130. }
  1131. # fe_mul(t0, t1, t0);
  1132. # fe_sq(t0, t0);
  1133. # fe_sq(t0, t0);
  1134. # fe_mul(out, t0, z);
  1135. $t0 = self::fe_mul($t1, $t0);
  1136. $t0 = self::fe_sq($t0);
  1137. $t0 = self::fe_sq($t0);
  1138. return self::fe_mul($t0, $z);
  1139. }
  1140. /**
  1141. * Subtract two field elements.
  1142. *
  1143. * h = f - g
  1144. *
  1145. * Preconditions:
  1146. * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
  1147. * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
  1148. *
  1149. * Postconditions:
  1150. * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
  1151. *
  1152. * @internal You should not use this directly from another application
  1153. *
  1154. * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
  1155. * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
  1156. * @return ParagonIE_Sodium_Core_Curve25519_Fe
  1157. * @psalm-suppress MixedOperand
  1158. */
  1159. public static function fe_sub(ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g)
  1160. {
  1161. return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
  1162. array(
  1163. (int) ($f[0] - $g[0]),
  1164. (int) ($f[1] - $g[1]),
  1165. (int) ($f[2] - $g[2]),
  1166. (int) ($f[3] - $g[3]),
  1167. (int) ($f[4] - $g[4]),
  1168. (int) ($f[5] - $g[5]),
  1169. (int) ($f[6] - $g[6]),
  1170. (int) ($f[7] - $g[7]),
  1171. (int) ($f[8] - $g[8]),
  1172. (int) ($f[9] - $g[9])
  1173. )
  1174. );
  1175. }
  1176. /**
  1177. * Add two group elements.
  1178. *
  1179. * r = p + q
  1180. *
  1181. * @internal You should not use this directly from another application
  1182. *
  1183. * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
  1184. * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
  1185. * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
  1186. */
  1187. public static function ge_add(
  1188. ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
  1189. ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
  1190. ) {
  1191. $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
  1192. $r->X = self::fe_add($p->Y, $p->X);
  1193. $r->Y = self::fe_sub($p->Y, $p->X);
  1194. $r->Z = self::fe_mul($r->X, $q->YplusX);
  1195. $r->Y = self::fe_mul($r->Y, $q->YminusX);
  1196. $r->T = self::fe_mul($q->T2d, $p->T);
  1197. $r->X = self::fe_mul($p->Z, $q->Z);
  1198. $t0 = self::fe_add($r->X, $r->X);
  1199. $r->X = self::fe_sub($r->Z, $r->Y);
  1200. $r->Y = self::fe_add($r->Z, $r->Y);
  1201. $r->Z = self::fe_add($t0, $r->T);
  1202. $r->T = self::fe_sub($t0, $r->T);
  1203. return $r;
  1204. }
  1205. /**
  1206. * @internal You should not use this directly from another application
  1207. *
  1208. * @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
  1209. * @param string $a
  1210. * @return array<int, mixed>
  1211. * @throws SodiumException
  1212. * @throws TypeError
  1213. */
  1214. public static function slide($a)
  1215. {
  1216. if (self::strlen($a) < 256) {
  1217. if (self::strlen($a) < 16) {
  1218. $a = str_pad($a, 256, '0', STR_PAD_RIGHT);
  1219. }
  1220. }
  1221. /** @var array<int, int> $r */
  1222. $r = array();
  1223. /** @var int $i */
  1224. for ($i = 0; $i < 256; ++$i) {
  1225. $r[$i] = (int) (
  1226. 1 & (
  1227. self::chrToInt($a[(int) ($i >> 3)])
  1228. >>
  1229. ($i & 7)
  1230. )
  1231. );
  1232. }
  1233. for ($i = 0;$i < 256;++$i) {
  1234. if ($r[$i]) {
  1235. for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
  1236. if ($r[$i + $b]) {
  1237. if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
  1238. $r[$i] += $r[$i + $b] << $b;
  1239. $r[$i + $b] = 0;
  1240. } elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) {
  1241. $r[$i] -= $r[$i + $b] << $b;
  1242. for ($k = $i + $b; $k < 256; ++$k) {
  1243. if (!$r[$k]) {
  1244. $r[$k] = 1;
  1245. break;
  1246. }
  1247. $r[$k] = 0;
  1248. }
  1249. } else {
  1250. break;
  1251. }
  1252. }
  1253. }
  1254. }
  1255. }
  1256. return $r;
  1257. }
  1258. /**
  1259. * @internal You should not use this directly from another application
  1260. *
  1261. * @param string $s
  1262. * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
  1263. * @throws SodiumException
  1264. * @throws TypeError
  1265. */
  1266. public static function ge_frombytes_negate_vartime($s)
  1267. {
  1268. static $d = null;
  1269. if (!$d) {
  1270. $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
  1271. }
  1272. # fe_frombytes(h->Y,s);
  1273. # fe_1(h->Z);
  1274. $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
  1275. self::fe_0(),
  1276. self::fe_frombytes($s),
  1277. self::fe_1()
  1278. );
  1279. # fe_sq(u,h->Y);
  1280. # fe_mul(v,u,d);
  1281. # fe_sub(u,u,h->Z); /* u = y^2-1 */
  1282. # fe_add(v,v,h->Z); /* v = dy^2+1 */
  1283. $u = self::fe_sq($h->Y);
  1284. /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d */
  1285. $v = self::fe_mul($u, $d);
  1286. $u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */
  1287. $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */
  1288. # fe_sq(v3,v);
  1289. # fe_mul(v3,v3,v); /* v3 = v^3 */
  1290. # fe_sq(h->X,v3);
  1291. # fe_mul(h->X,h->X,v);
  1292. # fe_mul(h->X,h->X,u); /* x = uv^7 */
  1293. $v3 = self::fe_sq($v);
  1294. $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
  1295. $h->X = self::fe_sq($v3);
  1296. $h->X = self::fe_mul($h->X, $v);
  1297. $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */
  1298. # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
  1299. # fe_mul(h->X,h->X,v3);
  1300. # fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
  1301. $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
  1302. $h->X = self::fe_mul($h->X, $v3);
  1303. $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */
  1304. # fe_sq(vxx,h->X);
  1305. # fe_mul(vxx,vxx,v);
  1306. # fe_sub(check,vxx,u); /* vx^2-u */
  1307. $vxx = self::fe_sq($h->X);
  1308. $vxx = self::fe_mul($vxx, $v);
  1309. $check = self::fe_sub($vxx, $u); /* vx^2 - u */
  1310. # if (fe_isnonzero(check)) {
  1311. # fe_add(check,vxx,u); /* vx^2+u */
  1312. # if (fe_isnonzero(check)) {
  1313. # return -1;
  1314. # }
  1315. # fe_mul(h->X,h->X,sqrtm1);
  1316. # }
  1317. if (self::fe_isnonzero($check)) {
  1318. $check = self::fe_add($vxx, $u); /* vx^2 + u */
  1319. if (self::fe_isnonzero($check)) {
  1320. throw new RangeException('Internal check failed.');
  1321. }
  1322. $h->X = self::fe_mul(
  1323. $h->X,
  1324. ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1)
  1325. );
  1326. }
  1327. # if (fe_isnegative(h->X) == (s[31] >> 7)) {
  1328. # fe_neg(h->X,h->X);
  1329. # }
  1330. $i = self::chrToInt($s[31]);
  1331. if (self::fe_isnegative($h->X) === ($i >> 7)) {
  1332. $h->X = self::fe_neg($h->X);
  1333. }
  1334. # fe_mul(h->T,h->X,h->Y);
  1335. $h->T = self::fe_mul($h->X, $h->Y);
  1336. return $h;
  1337. }
  1338. /**
  1339. * @internal You should not use this directly from another application
  1340. *
  1341. * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
  1342. * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
  1343. * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
  1344. * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
  1345. */
  1346. public static function ge_madd(
  1347. ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
  1348. ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
  1349. ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
  1350. ) {
  1351. $r = clone $R;
  1352. $r->X = self::fe_add($p->Y, $p->X);
  1353. $r->Y = self::fe_sub($p->Y, $p->X);
  1354. $r->Z = self::fe_mul($r->X, $q->yplusx);
  1355. $r->Y = self::fe_mul($r->Y, $q->yminusx);
  1356. $r->T = self::fe_mul($q->xy2d, $p->T);
  1357. $t0 = self::fe_add(clone $p->Z, clone $p->Z);
  1358. $r->X = self::fe_sub($r->Z, $r->Y);
  1359. $r->Y = self::fe_add($r->Z, $r->Y);
  1360. $r->Z = self::fe_add($t0, $r->T);
  1361. $r->T = self::fe_sub($t0, $r->T);
  1362. return $r;
  1363. }
  1364. /**
  1365. * @internal You should not use this directly from another application
  1366. *
  1367. * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
  1368. * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
  1369. * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
  1370. * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
  1371. */
  1372. public static function ge_msub(
  1373. ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
  1374. ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
  1375. ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
  1376. ) {
  1377. $r = clone $R;
  1378. $r->X = self::fe_add($p->Y, $p->X);
  1379. $r->Y = self::fe_sub($p->Y, $p->X);
  1380. $r->Z = self::fe_mul($r->X, $q->yminusx);
  1381. $r->Y = self::fe_mul($r->Y, $q->yplusx);
  1382. $r->T = self::fe_mul($q->xy2d, $p->T);
  1383. $t0 = self::fe_add($p->Z, $p->Z);
  1384. $r->X = self::fe_sub($r->Z, $r->Y);
  1385. $r->Y = self::fe_add($r->Z, $r->Y);
  1386. $r->Z = self