Skip to content

Commit df7fd97

Browse files
committed
Throw on below-minimum opslimit/memlimit in sodium pwhash
The four sodium pwhash functions queued a zend_argument_error for an opslimit or memlimit below the documented minimum but fell through to the KDF instead of returning. When libsodium rejects the value the precise argument error is clobbered by a generic "internal error"; when it accepts the value the full KDF runs before the queued error surfaces, defeating the minimum-cost gate. Add the missing RETURN_THROWS() so each lower-bound check returns like its sibling upper-bound branches. Closes GH-22383
1 parent ca4561c commit df7fd97

2 files changed

Lines changed: 34 additions & 0 deletions

File tree

ext/sodium/libsodium.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,6 +1473,7 @@ PHP_FUNCTION(sodium_crypto_pwhash)
14731473
}
14741474
if (memlimit < crypto_pwhash_MEMLIMIT_MIN) {
14751475
zend_argument_error(sodium_exception_ce, 5, "must be greater than or equal to %d", crypto_pwhash_MEMLIMIT_MIN);
1476+
RETURN_THROWS();
14761477
}
14771478
hash = zend_string_alloc((size_t) hash_len, 0);
14781479
ret = -1;
@@ -1532,9 +1533,11 @@ PHP_FUNCTION(sodium_crypto_pwhash_str)
15321533
}
15331534
if (opslimit < crypto_pwhash_OPSLIMIT_MIN) {
15341535
zend_argument_error(sodium_exception_ce, 2, "must be greater than or equal to %d", crypto_pwhash_OPSLIMIT_MIN);
1536+
RETURN_THROWS();
15351537
}
15361538
if (memlimit < crypto_pwhash_MEMLIMIT_MIN) {
15371539
zend_argument_error(sodium_exception_ce, 3, "must be greater than or equal to %d", crypto_pwhash_MEMLIMIT_MIN);
1540+
RETURN_THROWS();
15381541
}
15391542
hash_str = zend_string_alloc(crypto_pwhash_STRBYTES - 1, 0);
15401543
if (crypto_pwhash_str
@@ -1640,9 +1643,11 @@ PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256)
16401643
}
16411644
if (opslimit < crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE) {
16421645
zend_argument_error(sodium_exception_ce, 4, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
1646+
RETURN_THROWS();
16431647
}
16441648
if (memlimit < crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) {
16451649
zend_argument_error(sodium_exception_ce, 5, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
1650+
RETURN_THROWS();
16461651
}
16471652
hash = zend_string_alloc((size_t) hash_len, 0);
16481653
if (crypto_pwhash_scryptsalsa208sha256
@@ -1685,9 +1690,11 @@ PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256_str)
16851690
}
16861691
if (opslimit < crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE) {
16871692
zend_argument_error(sodium_exception_ce, 2, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
1693+
RETURN_THROWS();
16881694
}
16891695
if (memlimit < crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) {
16901696
zend_argument_error(sodium_exception_ce, 3, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
1697+
RETURN_THROWS();
16911698
}
16921699
hash_str = zend_string_alloc
16931700
(crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1, 0);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
sodium_crypto_pwhash(): a below-minimum memlimit reports a precise argument error
3+
--EXTENSIONS--
4+
sodium
5+
--SKIPIF--
6+
<?php
7+
if (!defined('SODIUM_CRYPTO_PWHASH_SALTBYTES')) print "skip libsodium without argon2";
8+
?>
9+
--FILE--
10+
<?php
11+
$salt = str_repeat("a", SODIUM_CRYPTO_PWHASH_SALTBYTES);
12+
13+
try {
14+
sodium_crypto_pwhash(32, "password", $salt, SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, 1);
15+
} catch (SodiumException $e) {
16+
echo $e->getMessage(), "\n";
17+
}
18+
19+
try {
20+
sodium_crypto_pwhash_str("password", SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, 1);
21+
} catch (SodiumException $e) {
22+
echo $e->getMessage(), "\n";
23+
}
24+
?>
25+
--EXPECTF--
26+
sodium_crypto_pwhash(): Argument #5 ($memlimit) must be greater than or equal to %d
27+
sodium_crypto_pwhash_str(): Argument #3 ($memlimit) must be greater than or equal to %d

0 commit comments

Comments
 (0)