1<?php
2
3if (class_exists('ParagonIE_Sodium_Core_AES_KeySchedule', false)) {
4 return;
5}
6
7/**
8 * @internal This should only be used by sodium_compat
9 */
10class ParagonIE_Sodium_Core_AES_KeySchedule
11{
12 /** @var array<int, int> $skey -- has size 120 */
13 protected $skey;
14
15 /** @var bool $expanded */
16 protected $expanded = false;
17
18 /** @var int $numRounds */
19 private $numRounds;
20
21 /**
22 * @param array $skey
23 * @param int $numRounds
24 */
25 public function __construct(array $skey, $numRounds = 10)
26 {
27 $this->skey = $skey;
28 $this->numRounds = $numRounds;
29 }
30
31 /**
32 * Get a value at an arbitrary index. Mostly used for unit testing.
33 *
34 * @param int $i
35 * @return int
36 */
37 public function get($i)
38 {
39 return $this->skey[$i];
40 }
41
42 /**
43 * @return int
44 */
45 public function getNumRounds()
46 {
47 return $this->numRounds;
48 }
49
50 /**
51 * @param int $offset
52 * @return ParagonIE_Sodium_Core_AES_Block
53 */
54 public function getRoundKey($offset)
55 {
56 return ParagonIE_Sodium_Core_AES_Block::fromArray(
57 array_slice($this->skey, $offset, 8)
58 );
59 }
60
61 /**
62 * Return an expanded key schedule
63 *
64 * @return ParagonIE_Sodium_Core_AES_Expanded
65 */
66 public function expand()
67 {
68 $exp = new ParagonIE_Sodium_Core_AES_Expanded(
69 array_fill(0, 120, 0),
70 $this->numRounds
71 );
72 $n = ($exp->numRounds + 1) << 2;
73 for ($u = 0, $v = 0; $u < $n; ++$u, $v += 2) {
74 $x = $y = $this->skey[$u];
75 $x &= 0x55555555;
76 $exp->skey[$v] = ($x | ($x << 1)) & ParagonIE_Sodium_Core_Util::U32_MAX;
77 $y &= 0xAAAAAAAA;
78 $exp->skey[$v + 1] = ($y | ($y >> 1)) & ParagonIE_Sodium_Core_Util::U32_MAX;
79 }
80 return $exp;
81 }
82}
83