44 if (MacEnum::MAC_CMAC() != $macAlgorithm) {
45 throw new \InvalidArgumentException(
'Unsupported algorithm');
48 if (!($innerAlgorithm instanceof
CipherEnum)) {
49 throw new \InvalidArgumentException(
'A cipher was expected for the inner algorithm');
52 $cipher = Registry::buildCipher($innerAlgorithm, ModeEnum::MODE_ECB(),
new None, $key, 0,
true);
53 $blockSize = $cipher->getBlockSize();
54 if (!isset(self::$polynomials[$blockSize << 3])) {
55 throw new \InvalidArgumentException(
'Unsupported cipher');
58 $null = str_repeat(
"\x00", $blockSize);
59 $polynomial = str_pad(self::$polynomials[$blockSize << 3], $blockSize,
"\x00", STR_PAD_LEFT);
60 $k0 = $cipher->encrypt(
'', $null);
62 if ((ord($k0[0]) & 0x80) === 0) {
63 $k1 = self::mul2mod($k0, $blockSize);
65 $k1 = self::mul2mod($k0, $blockSize) ^ $polynomial;
68 if ((ord($k1[0]) & 0x80) === 0) {
69 $k2 = self::mul2mod($k1, $blockSize);
71 $k2 = self::mul2mod($k1, $blockSize) ^ $polynomial;
77 $this->cipher = $cipher;
80 private static function mul2mod($n, $l)
83 for ($i = $l - 1; $i >= 0; $i--) {
84 $t = (ord($n[$i]) << 1) + $c;
92 protected function internalUpdate($data)
97 protected function internalFinalize()
99 $blockSize = $this->cipher->getBlockSize();
100 $m = str_split($this->data, $blockSize);
101 $last = count($m) - 1;
102 $mk1 = $m[$last] ^ $this->k1;
103 $mk2 = $this->k2 ^ str_pad($m[$last] .
"\x80", $blockSize,
"\x00", STR_PAD_RIGHT);
105 if (strlen($m[$last]) === $blockSize) {
111 $c = str_repeat(
"\x00", $blockSize);
112 for ($i = 0, $max = count($m); $i < $max; $i++) {
113 $c = $this->cipher->encrypt(
'', $c ^ $m[$i]);
__construct(MacEnum $macAlgorithm, SubAlgorithmAbstractEnum $innerAlgorithm, $key, $nonce= '')