angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

State.php (12912B)


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