Skip to content

Commit 9c6838d

Browse files
committed
ext/gmp: Add gmp_powm_sec()
1 parent e9ee4c0 commit 9c6838d

9 files changed

Lines changed: 113 additions & 1 deletion

File tree

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ PHP NEWS
1414
declares a default value for the attribute). (iliaal)
1515

1616
- GMP:
17+
. Added gmp_powm_sec(). (Weilin Du)
1718
. Fixed GMP power and shift operators to reject GMP right operands outside
1819
the unsigned long range instead of silently truncating them. (Weilin Du)
1920
. Fixed GMP integer string parsing to reject strings containing NUL bytes

UPGRADING

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ PHP 8.6 UPGRADE NOTES
265265
- Fileinfo:
266266
. finfo_file() now works with remote streams.
267267

268+
- GMP:
269+
. Added gmp_powm_sec() for side-channel quiet modular exponentiation.
270+
Requires GNU MP 5.0.0 or later.
271+
268272
- Intl:
269273
. Added Locale::getDisplayKeyword() and Locale::getDisplayKeywordValue(),
270274
with the alias of locale_get_display_keyword() and
@@ -410,6 +414,9 @@ PHP 8.6 UPGRADE NOTES
410414
6. New Functions
411415
========================================
412416

417+
- GMP:
418+
. gmp_powm_sec()
419+
413420
- Intl:
414421
. grapheme_strrev()
415422
RFC: https://wiki.php.net/rfc/grapheme_strrev

ext/gmp/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ if test "$PHP_GMP" != "no"; then
2222
LIBS="$LIBS $GMP_LIBS"
2323
gmp_check=no
2424
AC_CHECK_HEADER([gmp.h], [AC_CHECK_FUNC([__gmpz_rootrem], [gmp_check=yes])])
25+
AC_CHECK_FUNCS([__gmpz_powm_sec])
2526
CFLAGS=$CFLAGS_SAVED
2627
LIBS=$LIBS_SAVED
2728

ext/gmp/config.w32

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ ARG_WITH("gmp", "Include GNU MP support.", "no");
55
if (PHP_GMP != "no") {
66
if (CHECK_LIB("mpir_a.lib", "gmp", PHP_GMP) &&
77
CHECK_HEADER("gmp.h", "CFLAGS_GMP", PHP_GMP + ";" + PHP_PHP_BUILD + "\\include\\mpir")) {
8+
if (GREP_HEADER("gmp.h", "mpz_powm_sec", PHP_GMP + ";" + PHP_PHP_BUILD + "\\include\\mpir")) {
9+
AC_DEFINE('HAVE___GMPZ_POWM_SEC', 1, "Define to 1 if GMP has the 'mpz_powm_sec' function.");
10+
}
811
EXTENSION("gmp", "gmp.c", null, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
912
PHP_INSTALL_HEADERS("ext/gmp", "php_gmp_int.h");
1013
AC_DEFINE('HAVE_GMP', 1, "Define to 1 if the PHP extension 'gmp' is available.");

ext/gmp/gmp.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,39 @@ ZEND_FUNCTION(gmp_powm)
11891189
}
11901190
/* }}} */
11911191

1192+
#ifdef HAVE___GMPZ_POWM_SEC
1193+
/* {{{ Raise base to power exp and take result modulo mod using a side-channel quiet algorithm */
1194+
ZEND_FUNCTION(gmp_powm_sec)
1195+
{
1196+
mpz_ptr gmpnum_base, gmpnum_exp, gmpnum_mod, gmpnum_result;
1197+
1198+
ZEND_PARSE_PARAMETERS_START(3, 3)
1199+
GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_base)
1200+
GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_exp)
1201+
GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_mod)
1202+
ZEND_PARSE_PARAMETERS_END();
1203+
1204+
if (mpz_sgn(gmpnum_exp) <= 0) {
1205+
zend_argument_value_error(2, "must be greater than 0");
1206+
RETURN_THROWS();
1207+
}
1208+
1209+
if (!mpz_cmp_ui(gmpnum_mod, 0)) {
1210+
zend_argument_error(zend_ce_division_by_zero_error, 3, "Modulo by zero");
1211+
RETURN_THROWS();
1212+
}
1213+
1214+
if (!mpz_odd_p(gmpnum_mod)) {
1215+
zend_argument_value_error(3, "must be odd");
1216+
RETURN_THROWS();
1217+
}
1218+
1219+
INIT_GMP_RETVAL(gmpnum_result);
1220+
mpz_powm_sec(gmpnum_result, gmpnum_base, gmpnum_exp, gmpnum_mod);
1221+
}
1222+
/* }}} */
1223+
#endif
1224+
11921225
/* {{{ Takes integer part of square root of a */
11931226
ZEND_FUNCTION(gmp_sqrt)
11941227
{

ext/gmp/gmp.stub.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ function gmp_pow(GMP|int|string $num, int $exponent): GMP {}
125125

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

128+
#ifdef HAVE___GMPZ_POWM_SEC
129+
function gmp_powm_sec(GMP|int|string $num, GMP|int|string $exponent, GMP|int|string $modulus): GMP {}
130+
#endif
131+
128132
function gmp_perfect_square(GMP|int|string $num): bool {}
129133

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

ext/gmp/gmp_arginfo.h

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/gmp/tests/bug80560.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ $functions2 = [
6060
$functions3 = [
6161
'gmp_powm',
6262
];
63+
if (function_exists('gmp_powm_sec')) {
64+
$functions3[] = 'gmp_powm_sec';
65+
}
6366

6467
echo 'Explicit base with gmp_init:', \PHP_EOL;
6568
echo 'Hexadecimal', \PHP_EOL;

ext/gmp/tests/gmp_powm_sec.phpt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
gmp_powm_sec()
3+
--EXTENSIONS--
4+
gmp
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists('gmp_powm_sec')) {
8+
die('skip gmp_powm_sec() is not available');
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
14+
var_dump(gmp_strval(gmp_powm_sec(4, 13, 497)));
15+
var_dump(gmp_strval(gmp_powm_sec(gmp_init(7), gmp_init(3), gmp_init(13))));
16+
17+
foreach ([0, -1] as $exp) {
18+
try {
19+
var_dump(gmp_powm_sec(4, $exp, 497));
20+
} catch (\ValueError $e) {
21+
echo $e::class, ": ", $e->getMessage(), \PHP_EOL;
22+
}
23+
}
24+
25+
try {
26+
var_dump(gmp_powm_sec(4, 13, 0));
27+
} catch (\DivisionByZeroError $e) {
28+
echo $e::class, ": ", $e->getMessage(), \PHP_EOL;
29+
}
30+
31+
try {
32+
var_dump(gmp_powm_sec(4, 13, 496));
33+
} catch (\ValueError $e) {
34+
echo $e::class, ": ", $e->getMessage(), \PHP_EOL;
35+
}
36+
37+
echo "Done\n";
38+
?>
39+
--EXPECT--
40+
string(3) "445"
41+
string(1) "5"
42+
ValueError: gmp_powm_sec(): Argument #2 ($exponent) must be greater than 0
43+
ValueError: gmp_powm_sec(): Argument #2 ($exponent) must be greater than 0
44+
DivisionByZeroError: gmp_powm_sec(): Argument #3 ($modulus) Modulo by zero
45+
ValueError: gmp_powm_sec(): Argument #3 ($modulus) must be odd
46+
Done

0 commit comments

Comments
 (0)