diff --git a/src/Compat.php b/src/Compat.php index 907f33c4..5b9db5c3 100644 --- a/src/Compat.php +++ b/src/Compat.php @@ -242,7 +242,9 @@ public static function crypto_aead_aes256gcm_decrypt( throw new SodiumException('The OpenSSL extension is not installed, or openssl_decrypt() is not available'); } + /** @var string $ctext */ $ctext = ParagonIE_Sodium_Core_Util::substr($ciphertext, 0, -self::CRYPTO_AEAD_AES256GCM_ABYTES); + /** @var string $authTag */ $authTag = ParagonIE_Sodium_Core_Util::substr($ciphertext, -self::CRYPTO_AEAD_AES256GCM_ABYTES, 16); return openssl_decrypt( $ctext, diff --git a/src/Core32/Curve25519.php b/src/Core32/Curve25519.php index 808e2c70..6e427007 100644 --- a/src/Core32/Curve25519.php +++ b/src/Core32/Curve25519.php @@ -715,7 +715,7 @@ public static function fe_mul( $h8 = $h8->subInt64($carry8->shiftLeft(26)); $carry9 = $h9->addInt(1 << 24)->shiftRight(25); - $h0 = $h0->addInt64($carry9->mulInt(19)); + $h0 = $h0->addInt64($carry9->mulInt(19, 5)); $h9 = $h9->subInt64($carry9->shiftLeft(25)); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); @@ -940,7 +940,7 @@ public static function fe_sq(ParagonIE_Sodium_Core32_Curve25519_Fe $f) $h8 = $h8->subInt64($carry8->shiftLeft(26)); $carry9 = $h9->addInt(1 << 24)->shiftRight(25); - $h0 = $h0->addInt64($carry9->mulInt(19)); + $h0 = $h0->addInt64($carry9->mulInt(19, 5)); $h9 = $h9->subInt64($carry9->shiftLeft(25)); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); @@ -1144,7 +1144,7 @@ public static function fe_sq2(ParagonIE_Sodium_Core32_Curve25519_Fe $f) $h8 = $h8->subInt64($carry8->shiftLeft(26)); $carry9 = $h9->addInt(1 << 24)->shiftRight(25); - $h0 = $h0->addInt64($carry9->mulInt(19)); + $h0 = $h0->addInt64($carry9->mulInt(19, 5)); $h9 = $h9->subInt64($carry9->shiftLeft(25)); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); diff --git a/src/Core32/Int32.php b/src/Core32/Int32.php index 8dc7d49d..9a9862e5 100644 --- a/src/Core32/Int32.php +++ b/src/Core32/Int32.php @@ -168,12 +168,36 @@ public function mulInt($int = 0, $size = 0) $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + + /** @var int $size */ + /** @var int $i */ for ($i = $size; $i >= 0; --$i) { $m = (int) (-($int & 1)); - $return = $return->addInt32($a->mask($m)); - $a = $a->shiftLeft(1); + $x0 = $a0 & $m; + $x1 = $a1 & $m; + + $ret1 += $x1; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + + $a1 = ($a1 << 1); + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; $int >>= 1; } + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; return $return; } @@ -197,13 +221,46 @@ public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0) $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + $b0 = $b->limbs[0]; + $b1 = $b->limbs[1]; + + /** @var int $size */ /** @var int $i */ for ($i = $size; $i >= 0; --$i) { - $m = (int) (-($b->limbs[1] & 1)); - $return = $return->addInt32($a->mask($m)); - $a = $a->shiftLeft(1); - $b = $b->shiftRight(1); + $m = (int) (-($b1 & 1)); + $x0 = $a0 & $m; + $x1 = $a1 & $m; + + $ret1 += $x1; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + + $a1 = ($a1 << 1); + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; + + $x0 = ($b0 & 1) << 16; + $b0 = ($b0 >> 1); + $b1 = (($b1 | $x0) >> 1); + + $b0 &= 0xffff; + $b1 &= 0xffff; + } + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; + return $return; } diff --git a/src/Core32/Int64.php b/src/Core32/Int64.php index 6f791ea0..b9108fee 100644 --- a/src/Core32/Int64.php +++ b/src/Core32/Int64.php @@ -197,15 +197,58 @@ public function mulInt($int = 0, $size = 0) $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $ret2 = 0; + $ret3 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + $a2 = $a->limbs[2]; + $a3 = $a->limbs[3]; + + /** @var int $size */ + /** @var int $i */ for ($i = $size; $i >= 0; --$i) { - $return = $return->addInt64( - $a->mask64( - (int) (-($int & 1)), - (int) (-($int & 1)) - ) - ); - $a = $a->shiftLeft(1); + $mask = -($int & 1); + $x0 = $a0 & $mask; + $x1 = $a1 & $mask; + $x2 = $a2 & $mask; + $x3 = $a3 & $mask; + + $ret3 += $x3; + $c = $ret3 >> 16; + + $ret2 += $x2 + $c; + $c = $ret2 >> 16; + + $ret1 += $x1 + $c; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + $ret2 &= 0xffff; + $ret3 &= 0xffff; + + $a3 = $a3 << 1; + $x3 = $a3 >> 16; + $a2 = ($a2 << 1) | $x3; + $x2 = $a2 >> 16; + $a1 = ($a1 << 1) | $x2; + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; + $a2 &= 0xffff; + $a3 &= 0xffff; + $int >>= 1; + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; + $return->limbs[2] = $ret2; + $return->limbs[3] = $ret3; } return $return; } @@ -270,18 +313,77 @@ public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0) $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; + // Initialize: + $ret0 = 0; + $ret1 = 0; + $ret2 = 0; + $ret3 = 0; + $a0 = $a->limbs[0]; + $a1 = $a->limbs[1]; + $a2 = $a->limbs[2]; + $a3 = $a->limbs[3]; + $b0 = $b->limbs[0]; + $b1 = $b->limbs[1]; + $b2 = $b->limbs[2]; + $b3 = $b->limbs[3]; + /** @var int $size */ /** @var int $i */ for ($i = (int) $size; $i >= 0; --$i) { - $return = $return->addInt64( - $a->mask64( - (int) (-($b->limbs[3] & 1)), - (int) (-($b->limbs[3] & 1)) - ) - ); - $a = $a->shiftLeft(1); - $b = $b->shiftRight(1); + $mask = -($b3 & 1); + $x0 = $a0 & $mask; + $x1 = $a1 & $mask; + $x2 = $a2 & $mask; + $x3 = $a3 & $mask; + + $ret3 += $x3; + $c = $ret3 >> 16; + + $ret2 += $x2 + $c; + $c = $ret2 >> 16; + + $ret1 += $x1 + $c; + $c = $ret1 >> 16; + + $ret0 += $x0 + $c; + + $ret0 &= 0xffff; + $ret1 &= 0xffff; + $ret2 &= 0xffff; + $ret3 &= 0xffff; + + $a3 = $a3 << 1; + $x3 = $a3 >> 16; + $a2 = ($a2 << 1) | $x3; + $x2 = $a2 >> 16; + $a1 = ($a1 << 1) | $x2; + $x1 = $a1 >> 16; + $a0 = ($a0 << 1) | $x1; + $a0 &= 0xffff; + $a1 &= 0xffff; + $a2 &= 0xffff; + $a3 &= 0xffff; + + $x0 = ($b0 & 1) << 16; + $x1 = ($b1 & 1) << 16; + $x2 = ($b2 & 1) << 16; + + $b0 = ($b0 >> 1); + $b1 = (($b1 | $x0) >> 1); + $b2 = (($b2 | $x1) >> 1); + $b3 = (($b3 | $x2) >> 1); + + $b0 &= 0xffff; + $b1 &= 0xffff; + $b2 &= 0xffff; + $b3 &= 0xffff; + } + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; + $return->limbs[2] = $ret2; + $return->limbs[3] = $ret3; + return $return; }