diff --git a/src/wp-includes/sodium_compat/src/Core/Curve25519.php b/src/wp-includes/sodium_compat/src/Core/Curve25519.php index 284871114b0ba..7dab1cd0bbd7a 100644 --- a/src/wp-includes/sodium_compat/src/Core/Curve25519.php +++ b/src/wp-includes/sodium_compat/src/Core/Curve25519.php @@ -2899,6 +2899,7 @@ public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A) # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]); } + $r = self::ge_p1p1_to_p3($t); } # ge_p1p1_to_p3(r, &t); diff --git a/src/wp-includes/sodium_compat/src/Core/Ed25519.php b/src/wp-includes/sodium_compat/src/Core/Ed25519.php index bf6b5cfbd77f4..5cae0f180c4a7 100644 --- a/src/wp-includes/sodium_compat/src/Core/Ed25519.php +++ b/src/wp-includes/sodium_compat/src/Core/Ed25519.php @@ -119,7 +119,7 @@ public static function is_on_main_subgroup(ParagonIE_Sodium_Core_Curve25519_Ge_P { $p1 = self::ge_mul_l($A); $t = self::fe_sub($p1->Y, $p1->Z); - return self::fe_isnonzero($p1->X) && self::fe_isnonzero($t); + return !self::fe_isnonzero($p1->X) && !self::fe_isnonzero($t); } /** diff --git a/src/wp-includes/sodium_compat/src/Core32/Curve25519.php b/src/wp-includes/sodium_compat/src/Core32/Curve25519.php index aafffcd132bef..5a5f0babd6dc1 100644 --- a/src/wp-includes/sodium_compat/src/Core32/Curve25519.php +++ b/src/wp-includes/sodium_compat/src/Core32/Curve25519.php @@ -3154,6 +3154,7 @@ public static function ge_mul_l(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A) # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]); } + $r = self::ge_p1p1_to_p3($t); } # ge_p1p1_to_p3(r, &t); return self::ge_p1p1_to_p3($t); diff --git a/src/wp-includes/sodium_compat/src/Core32/Ed25519.php b/src/wp-includes/sodium_compat/src/Core32/Ed25519.php index 1b86b6774282b..8a0ea8e3e25a7 100644 --- a/src/wp-includes/sodium_compat/src/Core32/Ed25519.php +++ b/src/wp-includes/sodium_compat/src/Core32/Ed25519.php @@ -106,6 +106,22 @@ public static function publickey_from_secretkey($sk) return self::sk_to_pk($sk); } + /** + * Returns TRUE if $A represents a point on the order of the Edwards25519 prime order subgroup. + * Returns FALSE if $A is on a different subgroup. + * + * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A + * @return bool + * + * @throws SodiumException + */ + public static function is_on_main_subgroup(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A) + { + $p1 = self::ge_mul_l($A); + $t = self::fe_sub($p1->Y, $p1->Z); + return !self::fe_isnonzero($p1->X) && !self::fe_isnonzero($t); + } + /** * @param string $pk * @return string @@ -118,9 +134,8 @@ public static function pk_to_curve25519($pk) throw new SodiumException('Public key is on a small order'); } $A = self::ge_frombytes_negate_vartime($pk); - $p1 = self::ge_mul_l($A); - if (!self::fe_isnonzero($p1->X)) { - throw new SodiumException('Unexpected zero result'); + if (!self::is_on_main_subgroup($A)) { + throw new SodiumException('Public key is not on a member of the main subgroup'); } # fe_1(one_minus_y); @@ -307,6 +322,9 @@ public static function verify_detached($sig, $message, $pk) /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */ $A = self::ge_frombytes_negate_vartime($pk); + if (!self::is_on_main_subgroup($A)) { + throw new SodiumException('Public key is not on a member of the main subgroup'); + } /** @var string $hDigest */ $hDigest = hash( diff --git a/src/wp-includes/sodium_compat/src/File.php b/src/wp-includes/sodium_compat/src/File.php index c132a92e25fff..658dcd973612a 100644 --- a/src/wp-includes/sodium_compat/src/File.php +++ b/src/wp-includes/sodium_compat/src/File.php @@ -1329,8 +1329,14 @@ public static function verify_core32($sig, $filePath, $publicKey) // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification. ParagonIE_Sodium_Compat::$fastMult = true; + if (ParagonIE_Sodium_Core32_Ed25519::small_order($publicKey)) { + throw new SodiumException('Public key has small order'); + } /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */ $A = ParagonIE_Sodium_Core32_Ed25519::ge_frombytes_negate_vartime($publicKey); + if (!ParagonIE_Sodium_Core32_Ed25519::is_on_main_subgroup($A)) { + throw new SodiumException('Public key is not on a member of the main subgroup'); + } $hs = hash_init('sha512'); self::hash_update($hs, self::substr($sig, 0, 32));