Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ PHP NEWS
declares a default value for the attribute). (iliaal)

- GMP:
. Added gmp_powm_sec(). (Weilin Du)
. Added gmp_prevprime(). (Weilin Du, David Carlier)
. Fixed GMP power and shift operators to reject GMP right operands outside
the unsigned long range instead of silently truncating them. (Weilin Du)
Expand Down
3 changes: 3 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ PHP 8.6 UPGRADE NOTES
. finfo_file() now works with remote streams.

- GMP:
. Added gmp_powm_sec() for side-channel quiet modular exponentiation.
Requires GNU MP 5.0.0 or later.
. Added gmp_prevprime() to get the largest prime smaller than the given
number. A ValueError is thrown if no such prime exists. This function is
available only when PHP is built against GNU MP 6.3.0 or later; it is not
Expand Down Expand Up @@ -428,6 +430,7 @@ PHP 8.6 UPGRADE NOTES
========================================

- GMP:
. gmp_powm_sec()
. gmp_prevprime()

- Intl:
Expand Down
2 changes: 1 addition & 1 deletion ext/gmp/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ if test "$PHP_GMP" != "no"; then
LIBS="$LIBS $GMP_LIBS"
gmp_check=no
AC_CHECK_HEADER([gmp.h], [AC_CHECK_FUNC([__gmpz_rootrem], [gmp_check=yes])])
AC_CHECK_FUNCS([__gmpz_prevprime])
AC_CHECK_FUNCS([__gmpz_powm_sec __gmpz_prevprime])
CFLAGS=$CFLAGS_SAVED
LIBS=$LIBS_SAVED

Expand Down
3 changes: 3 additions & 0 deletions ext/gmp/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ ARG_WITH("gmp", "Include GNU MP support.", "no");
if (PHP_GMP != "no") {
if (CHECK_LIB("mpir_a.lib", "gmp", PHP_GMP) &&
CHECK_HEADER("gmp.h", "CFLAGS_GMP", PHP_GMP + ";" + PHP_PHP_BUILD + "\\include\\mpir")) {
if (GREP_HEADER("gmp.h", "mpz_powm_sec", PHP_GMP + ";" + PHP_PHP_BUILD + "\\include\\mpir")) {
AC_DEFINE('HAVE___GMPZ_POWM_SEC', 1, "Define to 1 if GMP has the 'mpz_powm_sec' function.");
}
if (GREP_HEADER("gmp.h", "mpz_prevprime", PHP_GMP + ";" + PHP_PHP_BUILD + "\\include\\mpir")) {
AC_DEFINE('HAVE___GMPZ_PREVPRIME', 1, "Define to 1 if GMP has the 'mpz_prevprime' function.");
}
Expand Down
33 changes: 33 additions & 0 deletions ext/gmp/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,39 @@ ZEND_FUNCTION(gmp_powm)
}
/* }}} */

#ifdef HAVE___GMPZ_POWM_SEC
/* {{{ Raise base to power exp and take result modulo mod using a side-channel quiet algorithm */
ZEND_FUNCTION(gmp_powm_sec)
{
mpz_ptr gmpnum_base, gmpnum_exp, gmpnum_mod, gmpnum_result;

ZEND_PARSE_PARAMETERS_START(3, 3)
GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_base)
GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_exp)
GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_mod)
ZEND_PARSE_PARAMETERS_END();

if (mpz_sgn(gmpnum_exp) <= 0) {
zend_argument_value_error(2, "must be greater than 0");
RETURN_THROWS();
}

if (UNEXPECTED(!mpz_odd_p(gmpnum_mod))) {
/* Zero is an even modulus, but report it like gmp_powm() does. */
if (!mpz_cmp_ui(gmpnum_mod, 0)) {
zend_argument_error(zend_ce_division_by_zero_error, 3, "Modulo by zero");
} else {
zend_argument_value_error(3, "must be odd");
}
RETURN_THROWS();
}

INIT_GMP_RETVAL(gmpnum_result);
mpz_powm_sec(gmpnum_result, gmpnum_base, gmpnum_exp, gmpnum_mod);
}
/* }}} */
#endif

/* {{{ Takes integer part of square root of a */
ZEND_FUNCTION(gmp_sqrt)
{
Expand Down
4 changes: 4 additions & 0 deletions ext/gmp/gmp.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ function gmp_pow(GMP|int|string $num, int $exponent): GMP {}

function gmp_powm(GMP|int|string $num, GMP|int|string $exponent, GMP|int|string $modulus): GMP {}

#ifdef HAVE___GMPZ_POWM_SEC
function gmp_powm_sec(GMP|int|string $num, GMP|int|string $exponent, GMP|int|string $modulus): GMP {}
#endif

function gmp_perfect_square(GMP|int|string $num): bool {}

function gmp_perfect_power(GMP|int|string $num): bool {}
Expand Down
16 changes: 15 additions & 1 deletion ext/gmp/gmp_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions ext/gmp/tests/bug80560.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ $functions2 = [
$functions3 = [
'gmp_powm',
];
if (function_exists('gmp_powm_sec')) {
$functions3[] = 'gmp_powm_sec';
}

echo 'Explicit base with gmp_init:', \PHP_EOL;
echo 'Hexadecimal', \PHP_EOL;
Expand Down
46 changes: 46 additions & 0 deletions ext/gmp/tests/gmp_powm_sec.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
--TEST--
gmp_powm_sec()
--EXTENSIONS--
gmp
--SKIPIF--
<?php
if (!function_exists('gmp_powm_sec')) {
die('skip gmp_powm_sec() is not available');
}
?>
--FILE--
<?php

var_dump(gmp_strval(gmp_powm_sec(4, 13, 497)));
var_dump(gmp_strval(gmp_powm_sec(gmp_init(7), gmp_init(3), gmp_init(13))));

foreach ([0, -1] as $exp) {
try {
var_dump(gmp_powm_sec(4, $exp, 497));
} catch (\ValueError $e) {
echo $e::class, ": ", $e->getMessage(), \PHP_EOL;
}
}

try {
var_dump(gmp_powm_sec(4, 13, 0));
} catch (\DivisionByZeroError $e) {
echo $e::class, ": ", $e->getMessage(), \PHP_EOL;
}

try {
var_dump(gmp_powm_sec(4, 13, 496));
} catch (\ValueError $e) {
echo $e::class, ": ", $e->getMessage(), \PHP_EOL;
}

echo "Done\n";
?>
--EXPECT--
string(3) "445"
string(1) "5"
ValueError: gmp_powm_sec(): Argument #2 ($exponent) must be greater than 0
ValueError: gmp_powm_sec(): Argument #2 ($exponent) must be greater than 0
DivisionByZeroError: gmp_powm_sec(): Argument #3 ($modulus) Modulo by zero
ValueError: gmp_powm_sec(): Argument #3 ($modulus) must be odd
Done
Loading