/htdocs/wp-includes/sodium_compat/src/Core32/Poly1305/State.php

https://gitlab.com/VTTE/sitios-vtte · PHP · 451 lines · 289 code · 48 blank · 114 comment · 15 complexity · b4b644fa35dbc824c3bd0a09e0277130 MD5 · raw file

  1. <?php
  2. if (class_exists('ParagonIE_Sodium_Core32_Poly1305_State', false)) {
  3. return;
  4. }
  5. /**
  6. * Class ParagonIE_Sodium_Core32_Poly1305_State
  7. */
  8. class ParagonIE_Sodium_Core32_Poly1305_State extends ParagonIE_Sodium_Core32_Util
  9. {
  10. /**
  11. * @var array<int, int>
  12. */
  13. protected $buffer = array();
  14. /**
  15. * @var bool
  16. */
  17. protected $final = false;
  18. /**
  19. * @var array<int, ParagonIE_Sodium_Core32_Int32>
  20. */
  21. public $h;
  22. /**
  23. * @var int
  24. */
  25. protected $leftover = 0;
  26. /**
  27. * @var array<int, ParagonIE_Sodium_Core32_Int32>
  28. */
  29. public $r;
  30. /**
  31. * @var array<int, ParagonIE_Sodium_Core32_Int64>
  32. */
  33. public $pad;
  34. /**
  35. * ParagonIE_Sodium_Core32_Poly1305_State constructor.
  36. *
  37. * @internal You should not use this directly from another application
  38. *
  39. * @param string $key
  40. * @throws InvalidArgumentException
  41. * @throws SodiumException
  42. * @throws TypeError
  43. */
  44. public function __construct($key = '')
  45. {
  46. if (self::strlen($key) < 32) {
  47. throw new InvalidArgumentException(
  48. 'Poly1305 requires a 32-byte key'
  49. );
  50. }
  51. /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
  52. $this->r = array(
  53. // st->r[0] = ...
  54. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4))
  55. ->setUnsignedInt(true)
  56. ->mask(0x3ffffff),
  57. // st->r[1] = ...
  58. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 3, 4))
  59. ->setUnsignedInt(true)
  60. ->shiftRight(2)
  61. ->mask(0x3ffff03),
  62. // st->r[2] = ...
  63. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 6, 4))
  64. ->setUnsignedInt(true)
  65. ->shiftRight(4)
  66. ->mask(0x3ffc0ff),
  67. // st->r[3] = ...
  68. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 9, 4))
  69. ->setUnsignedInt(true)
  70. ->shiftRight(6)
  71. ->mask(0x3f03fff),
  72. // st->r[4] = ...
  73. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4))
  74. ->setUnsignedInt(true)
  75. ->shiftRight(8)
  76. ->mask(0x00fffff)
  77. );
  78. /* h = 0 */
  79. $this->h = array(
  80. new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
  81. new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
  82. new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
  83. new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
  84. new ParagonIE_Sodium_Core32_Int32(array(0, 0), true)
  85. );
  86. /* save pad for later */
  87. $this->pad = array(
  88. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4))
  89. ->setUnsignedInt(true)->toInt64(),
  90. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4))
  91. ->setUnsignedInt(true)->toInt64(),
  92. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4))
  93. ->setUnsignedInt(true)->toInt64(),
  94. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4))
  95. ->setUnsignedInt(true)->toInt64(),
  96. );
  97. $this->leftover = 0;
  98. $this->final = false;
  99. }
  100. /**
  101. * @internal You should not use this directly from another application
  102. *
  103. * @param string $message
  104. * @return self
  105. * @throws SodiumException
  106. * @throws TypeError
  107. */
  108. public function update($message = '')
  109. {
  110. $bytes = self::strlen($message);
  111. /* handle leftover */
  112. if ($this->leftover) {
  113. /** @var int $want */
  114. $want = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - $this->leftover;
  115. if ($want > $bytes) {
  116. $want = $bytes;
  117. }
  118. for ($i = 0; $i < $want; ++$i) {
  119. $mi = self::chrToInt($message[$i]);
  120. $this->buffer[$this->leftover + $i] = $mi;
  121. }
  122. // We snip off the leftmost bytes.
  123. $message = self::substr($message, $want);
  124. $bytes = self::strlen($message);
  125. $this->leftover += $want;
  126. if ($this->leftover < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
  127. // We still don't have enough to run $this->blocks()
  128. return $this;
  129. }
  130. $this->blocks(
  131. self::intArrayToString($this->buffer),
  132. ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
  133. );
  134. $this->leftover = 0;
  135. }
  136. /* process full blocks */
  137. if ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
  138. /** @var int $want */
  139. $want = $bytes & ~(ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - 1);
  140. if ($want >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
  141. /** @var string $block */
  142. $block = self::substr($message, 0, $want);
  143. if (self::strlen($block) >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
  144. $this->blocks($block, $want);
  145. $message = self::substr($message, $want);
  146. $bytes = self::strlen($message);
  147. }
  148. }
  149. }
  150. /* store leftover */
  151. if ($bytes) {
  152. for ($i = 0; $i < $bytes; ++$i) {
  153. $mi = self::chrToInt($message[$i]);
  154. $this->buffer[$this->leftover + $i] = $mi;
  155. }
  156. $this->leftover = (int) $this->leftover + $bytes;
  157. }
  158. return $this;
  159. }
  160. /**
  161. * @internal You should not use this directly from another application
  162. *
  163. * @param string $message
  164. * @param int $bytes
  165. * @return self
  166. * @throws SodiumException
  167. * @throws TypeError
  168. */
  169. public function blocks($message, $bytes)
  170. {
  171. if (self::strlen($message) < 16) {
  172. $message = str_pad($message, 16, "\x00", STR_PAD_RIGHT);
  173. }
  174. $hibit = ParagonIE_Sodium_Core32_Int32::fromInt((int) ($this->final ? 0 : 1 << 24)); /* 1 << 128 */
  175. $hibit->setUnsignedInt(true);
  176. $zero = new ParagonIE_Sodium_Core32_Int64(array(0, 0, 0, 0), true);
  177. /**
  178. * @var ParagonIE_Sodium_Core32_Int64 $d0
  179. * @var ParagonIE_Sodium_Core32_Int64 $d1
  180. * @var ParagonIE_Sodium_Core32_Int64 $d2
  181. * @var ParagonIE_Sodium_Core32_Int64 $d3
  182. * @var ParagonIE_Sodium_Core32_Int64 $d4
  183. * @var ParagonIE_Sodium_Core32_Int64 $r0
  184. * @var ParagonIE_Sodium_Core32_Int64 $r1
  185. * @var ParagonIE_Sodium_Core32_Int64 $r2
  186. * @var ParagonIE_Sodium_Core32_Int64 $r3
  187. * @var ParagonIE_Sodium_Core32_Int64 $r4
  188. *
  189. * @var ParagonIE_Sodium_Core32_Int32 $h0
  190. * @var ParagonIE_Sodium_Core32_Int32 $h1
  191. * @var ParagonIE_Sodium_Core32_Int32 $h2
  192. * @var ParagonIE_Sodium_Core32_Int32 $h3
  193. * @var ParagonIE_Sodium_Core32_Int32 $h4
  194. */
  195. $r0 = $this->r[0]->toInt64();
  196. $r1 = $this->r[1]->toInt64();
  197. $r2 = $this->r[2]->toInt64();
  198. $r3 = $this->r[3]->toInt64();
  199. $r4 = $this->r[4]->toInt64();
  200. $s1 = $r1->toInt64()->mulInt(5, 3);
  201. $s2 = $r2->toInt64()->mulInt(5, 3);
  202. $s3 = $r3->toInt64()->mulInt(5, 3);
  203. $s4 = $r4->toInt64()->mulInt(5, 3);
  204. $h0 = $this->h[0];
  205. $h1 = $this->h[1];
  206. $h2 = $this->h[2];
  207. $h3 = $this->h[3];
  208. $h4 = $this->h[4];
  209. while ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
  210. /* h += m[i] */
  211. $h0 = $h0->addInt32(
  212. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4))
  213. ->mask(0x3ffffff)
  214. )->toInt64();
  215. $h1 = $h1->addInt32(
  216. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 3, 4))
  217. ->shiftRight(2)
  218. ->mask(0x3ffffff)
  219. )->toInt64();
  220. $h2 = $h2->addInt32(
  221. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 6, 4))
  222. ->shiftRight(4)
  223. ->mask(0x3ffffff)
  224. )->toInt64();
  225. $h3 = $h3->addInt32(
  226. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 9, 4))
  227. ->shiftRight(6)
  228. ->mask(0x3ffffff)
  229. )->toInt64();
  230. $h4 = $h4->addInt32(
  231. ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4))
  232. ->shiftRight(8)
  233. ->orInt32($hibit)
  234. )->toInt64();
  235. /* h *= r */
  236. $d0 = $zero
  237. ->addInt64($h0->mulInt64($r0, 25))
  238. ->addInt64($s4->mulInt64($h1, 26))
  239. ->addInt64($s3->mulInt64($h2, 26))
  240. ->addInt64($s2->mulInt64($h3, 26))
  241. ->addInt64($s1->mulInt64($h4, 26));
  242. $d1 = $zero
  243. ->addInt64($h0->mulInt64($r1, 25))
  244. ->addInt64($h1->mulInt64($r0, 25))
  245. ->addInt64($s4->mulInt64($h2, 26))
  246. ->addInt64($s3->mulInt64($h3, 26))
  247. ->addInt64($s2->mulInt64($h4, 26));
  248. $d2 = $zero
  249. ->addInt64($h0->mulInt64($r2, 25))
  250. ->addInt64($h1->mulInt64($r1, 25))
  251. ->addInt64($h2->mulInt64($r0, 25))
  252. ->addInt64($s4->mulInt64($h3, 26))
  253. ->addInt64($s3->mulInt64($h4, 26));
  254. $d3 = $zero
  255. ->addInt64($h0->mulInt64($r3, 25))
  256. ->addInt64($h1->mulInt64($r2, 25))
  257. ->addInt64($h2->mulInt64($r1, 25))
  258. ->addInt64($h3->mulInt64($r0, 25))
  259. ->addInt64($s4->mulInt64($h4, 26));
  260. $d4 = $zero
  261. ->addInt64($h0->mulInt64($r4, 25))
  262. ->addInt64($h1->mulInt64($r3, 25))
  263. ->addInt64($h2->mulInt64($r2, 25))
  264. ->addInt64($h3->mulInt64($r1, 25))
  265. ->addInt64($h4->mulInt64($r0, 25));
  266. /* (partial) h %= p */
  267. $c = $d0->shiftRight(26);
  268. $h0 = $d0->toInt32()->mask(0x3ffffff);
  269. $d1 = $d1->addInt64($c);
  270. $c = $d1->shiftRight(26);
  271. $h1 = $d1->toInt32()->mask(0x3ffffff);
  272. $d2 = $d2->addInt64($c);
  273. $c = $d2->shiftRight(26);
  274. $h2 = $d2->toInt32()->mask(0x3ffffff);
  275. $d3 = $d3->addInt64($c);
  276. $c = $d3->shiftRight(26);
  277. $h3 = $d3->toInt32()->mask(0x3ffffff);
  278. $d4 = $d4->addInt64($c);
  279. $c = $d4->shiftRight(26);
  280. $h4 = $d4->toInt32()->mask(0x3ffffff);
  281. $h0 = $h0->addInt32($c->toInt32()->mulInt(5, 3));
  282. $c = $h0->shiftRight(26);
  283. $h0 = $h0->mask(0x3ffffff);
  284. $h1 = $h1->addInt32($c);
  285. // Chop off the left 32 bytes.
  286. $message = self::substr(
  287. $message,
  288. ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
  289. );
  290. $bytes -= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE;
  291. }
  292. /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
  293. $this->h = array($h0, $h1, $h2, $h3, $h4);
  294. return $this;
  295. }
  296. /**
  297. * @internal You should not use this directly from another application
  298. *
  299. * @return string
  300. * @throws SodiumException
  301. * @throws TypeError
  302. */
  303. public function finish()
  304. {
  305. /* process the remaining block */
  306. if ($this->leftover) {
  307. $i = $this->leftover;
  308. $this->buffer[$i++] = 1;
  309. for (; $i < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE; ++$i) {
  310. $this->buffer[$i] = 0;
  311. }
  312. $this->final = true;
  313. $this->blocks(
  314. self::substr(
  315. self::intArrayToString($this->buffer),
  316. 0,
  317. ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
  318. ),
  319. $b = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
  320. );
  321. }
  322. /**
  323. * @var ParagonIE_Sodium_Core32_Int32 $f
  324. * @var ParagonIE_Sodium_Core32_Int32 $g0
  325. * @var ParagonIE_Sodium_Core32_Int32 $g1
  326. * @var ParagonIE_Sodium_Core32_Int32 $g2
  327. * @var ParagonIE_Sodium_Core32_Int32 $g3
  328. * @var ParagonIE_Sodium_Core32_Int32 $g4
  329. * @var ParagonIE_Sodium_Core32_Int32 $h0
  330. * @var ParagonIE_Sodium_Core32_Int32 $h1
  331. * @var ParagonIE_Sodium_Core32_Int32 $h2
  332. * @var ParagonIE_Sodium_Core32_Int32 $h3
  333. * @var ParagonIE_Sodium_Core32_Int32 $h4
  334. */
  335. $h0 = $this->h[0];
  336. $h1 = $this->h[1];
  337. $h2 = $this->h[2];
  338. $h3 = $this->h[3];
  339. $h4 = $this->h[4];
  340. $c = $h1->shiftRight(26); # $c = $h1 >> 26;
  341. $h1 = $h1->mask(0x3ffffff); # $h1 &= 0x3ffffff;
  342. $h2 = $h2->addInt32($c); # $h2 += $c;
  343. $c = $h2->shiftRight(26); # $c = $h2 >> 26;
  344. $h2 = $h2->mask(0x3ffffff); # $h2 &= 0x3ffffff;
  345. $h3 = $h3->addInt32($c); # $h3 += $c;
  346. $c = $h3->shiftRight(26); # $c = $h3 >> 26;
  347. $h3 = $h3->mask(0x3ffffff); # $h3 &= 0x3ffffff;
  348. $h4 = $h4->addInt32($c); # $h4 += $c;
  349. $c = $h4->shiftRight(26); # $c = $h4 >> 26;
  350. $h4 = $h4->mask(0x3ffffff); # $h4 &= 0x3ffffff;
  351. $h0 = $h0->addInt32($c->mulInt(5, 3)); # $h0 += self::mul($c, 5);
  352. $c = $h0->shiftRight(26); # $c = $h0 >> 26;
  353. $h0 = $h0->mask(0x3ffffff); # $h0 &= 0x3ffffff;
  354. $h1 = $h1->addInt32($c); # $h1 += $c;
  355. /* compute h + -p */
  356. $g0 = $h0->addInt(5);
  357. $c = $g0->shiftRight(26);
  358. $g0 = $g0->mask(0x3ffffff);
  359. $g1 = $h1->addInt32($c);
  360. $c = $g1->shiftRight(26);
  361. $g1 = $g1->mask(0x3ffffff);
  362. $g2 = $h2->addInt32($c);
  363. $c = $g2->shiftRight(26);
  364. $g2 = $g2->mask(0x3ffffff);
  365. $g3 = $h3->addInt32($c);
  366. $c = $g3->shiftRight(26);
  367. $g3 = $g3->mask(0x3ffffff);
  368. $g4 = $h4->addInt32($c)->subInt(1 << 26);
  369. # $mask = ($g4 >> 31) - 1;
  370. /* select h if h < p, or h + -p if h >= p */
  371. $mask = (int) (($g4->toInt() >> 31) + 1);
  372. $g0 = $g0->mask($mask);
  373. $g1 = $g1->mask($mask);
  374. $g2 = $g2->mask($mask);
  375. $g3 = $g3->mask($mask);
  376. $g4 = $g4->mask($mask);
  377. /** @var int $mask */
  378. $mask = (~$mask) & 0xffffffff;
  379. $h0 = $h0->mask($mask)->orInt32($g0);
  380. $h1 = $h1->mask($mask)->orInt32($g1);
  381. $h2 = $h2->mask($mask)->orInt32($g2);
  382. $h3 = $h3->mask($mask)->orInt32($g3);
  383. $h4 = $h4->mask($mask)->orInt32($g4);
  384. /* h = h % (2^128) */
  385. $h0 = $h0->orInt32($h1->shiftLeft(26));
  386. $h1 = $h1->shiftRight(6)->orInt32($h2->shiftLeft(20));
  387. $h2 = $h2->shiftRight(12)->orInt32($h3->shiftLeft(14));
  388. $h3 = $h3->shiftRight(18)->orInt32($h4->shiftLeft(8));
  389. /* mac = (h + pad) % (2^128) */
  390. $f = $h0->toInt64()->addInt64($this->pad[0]);
  391. $h0 = $f->toInt32();
  392. $f = $h1->toInt64()->addInt64($this->pad[1])->addInt($h0->overflow);
  393. $h1 = $f->toInt32();
  394. $f = $h2->toInt64()->addInt64($this->pad[2])->addInt($h1->overflow);
  395. $h2 = $f->toInt32();
  396. $f = $h3->toInt64()->addInt64($this->pad[3])->addInt($h2->overflow);
  397. $h3 = $f->toInt32();
  398. return $h0->toReverseString() .
  399. $h1->toReverseString() .
  400. $h2->toReverseString() .
  401. $h3->toReverseString();
  402. }
  403. }