Skip to content

Commit b938a5c

Browse files
Merge pull request #203 from paragonie/v1.x-pr202
Backport Fixes from v2 ro v1.x branch
2 parents a4d611b + d7be83f commit b938a5c

11 files changed

Lines changed: 104 additions & 53 deletions

File tree

‎src/Compat.php‎

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,6 @@ public static function base642bin(
207207

208208
/** @var string $encoded */
209209
$encoded = (string) $encoded;
210-
if (ParagonIE_Sodium_Core_Util::strlen($encoded) === 0) {
211-
return '';
212-
}
213210

214211
// Just strip before decoding
215212
if (!empty($ignore)) {
@@ -233,7 +230,7 @@ public static function base642bin(
233230
if ($ex instanceof SodiumException) {
234231
throw $ex;
235232
}
236-
throw new SodiumException('invalid base64 string');
233+
throw new SodiumException('invalid base64 string', 0, $ex);
237234
}
238235
}
239236

@@ -359,7 +356,7 @@ public static function crypto_aead_aegis128l_decrypt(
359356

360357
/* Input validation: */
361358
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS128L_NPUBBYTES) {
362-
throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS_128L_NPUBBYTES long');
359+
throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_NPUBBYTES long');
363360
}
364361
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS128L_KEYBYTES) {
365362
throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long');
@@ -413,7 +410,7 @@ public static function crypto_aead_aegis128l_encrypt(
413410

414411
/* Input validation: */
415412
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS128L_NPUBBYTES) {
416-
throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long');
413+
throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_NPUBBYTES long');
417414
}
418415
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS128L_KEYBYTES) {
419416
throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long');
@@ -522,10 +519,10 @@ public static function crypto_aead_aegis256_encrypt(
522519

523520
/* Input validation: */
524521
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS256_NPUBBYTES) {
525-
throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long');
522+
throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS256_NPUBBYTES long');
526523
}
527524
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS256_KEYBYTES) {
528-
throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long');
525+
throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS256_KEYBYTES long');
529526
}
530527

531528
list($ct, $tag) = ParagonIE_Sodium_Core_AEGIS256::encrypt($plaintext, $assocData, $key, $nonce);
@@ -565,6 +562,9 @@ public static function crypto_aead_aes256gcm_is_available()
565562
// OpenSSL doesn't support AEAD before 7.1.0
566563
return false;
567564
}
565+
if (!extension_loaded('openssl')) {
566+
return false;
567+
}
568568
if (!is_callable('openssl_encrypt') || !is_callable('openssl_decrypt')) {
569569
// OpenSSL isn't installed
570570
return false;
@@ -618,6 +618,9 @@ public static function crypto_aead_aes256gcm_decrypt(
618618
if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_AES256GCM_ABYTES) {
619619
throw new SodiumException('Message must be at least CRYPTO_AEAD_AES256GCM_ABYTES long');
620620
}
621+
if (!extension_loaded('openssl')) {
622+
throw new SodiumException('The OpenSSL extension is not installed');
623+
}
621624
if (!is_callable('openssl_decrypt')) {
622625
throw new SodiumException('The OpenSSL extension is not installed, or openssl_decrypt() is not available');
623626
}
@@ -678,6 +681,9 @@ public static function crypto_aead_aes256gcm_encrypt(
678681
throw new SodiumException('Key must be CRYPTO_AEAD_AES256GCM_KEYBYTES long');
679682
}
680683

684+
if (!extension_loaded('openssl')) {
685+
throw new SodiumException('The OpenSSL extension is not installed');
686+
}
681687
if (!is_callable('openssl_encrypt')) {
682688
throw new SodiumException('The OpenSSL extension is not installed, or openssl_encrypt() is not available');
683689
}
@@ -826,10 +832,10 @@ public static function crypto_aead_chacha20poly1305_encrypt(
826832

827833
/* Input validation: */
828834
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES) {
829-
throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES long');
835+
throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long');
830836
}
831837
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) {
832-
throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long');
838+
throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES long');
833839
}
834840

835841
if (self::useNewSodiumAPI()) {
@@ -904,10 +910,10 @@ public static function crypto_aead_chacha20poly1305_ietf_decrypt(
904910
throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long');
905911
}
906912
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) {
907-
throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long');
913+
throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES long');
908914
}
909915
if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES) {
910-
throw new SodiumException('Message must be at least CRYPTO_AEAD_CHACHA20POLY1305_ABYTES long');
916+
throw new SodiumException('Message must be at least CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES long');
911917
}
912918

913919
if (self::useNewSodiumAPI()) {
@@ -2784,6 +2790,9 @@ public static function crypto_secretbox_xchacha20poly1305_open(
27842790
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) {
27852791
throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.');
27862792
}
2793+
if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_SECRETBOX_MACBYTES) {
2794+
throw new SodiumException("Ciphertext must be at least CRYPTO_SECRETBOX_MACBYTES long");
2795+
}
27872796

27882797
if (PHP_INT_SIZE === 4) {
27892798
return ParagonIE_Sodium_Crypto32::secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key);
@@ -3714,6 +3723,9 @@ public static function increment(
37143723
}
37153724

37163725
$len = ParagonIE_Sodium_Core_Util::strlen($var);
3726+
if ($len < 1) {
3727+
throw new SodiumException('Argument 1 cannot be empty');
3728+
}
37173729
$c = 1;
37183730
$copy = '';
37193731
for ($i = 0; $i < $len; ++$i) {

‎src/Core/ChaCha20.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public static function encryptBytes(
329329
* @throws SodiumException
330330
* @throws TypeError
331331
*/
332-
public static function stream($len = 64, $nonce = '', $key = '')
332+
public static function stream($len, $nonce, $key)
333333
{
334334
return self::encryptBytes(
335335
new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce),
@@ -347,7 +347,7 @@ public static function stream($len = 64, $nonce = '', $key = '')
347347
* @throws SodiumException
348348
* @throws TypeError
349349
*/
350-
public static function ietfStream($len, $nonce = '', $key = '')
350+
public static function ietfStream($len, $nonce, $key)
351351
{
352352
return self::encryptBytes(
353353
new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce),
@@ -366,7 +366,7 @@ public static function ietfStream($len, $nonce = '', $key = '')
366366
* @throws SodiumException
367367
* @throws TypeError
368368
*/
369-
public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '')
369+
public static function ietfStreamXorIc($message, $nonce, $key, $ic = '')
370370
{
371371
return self::encryptBytes(
372372
new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce, $ic),
@@ -385,7 +385,7 @@ public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '
385385
* @throws SodiumException
386386
* @throws TypeError
387387
*/
388-
public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
388+
public static function streamXorIc($message, $nonce, $key, $ic = '')
389389
{
390390
return self::encryptBytes(
391391
new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce, $ic),

‎src/Core/Ed25519.php‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static function keypair()
4646
public static function seed_keypair(&$pk, &$sk, $seed)
4747
{
4848
if (self::strlen($seed) !== self::SEED_BYTES) {
49-
throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
49+
throw new SodiumException('crypto_sign keypair seed must be 32 bytes long');
5050
}
5151

5252
/** @var string $pk */
@@ -65,7 +65,7 @@ public static function seed_keypair(&$pk, &$sk, $seed)
6565
public static function secretkey($keypair)
6666
{
6767
if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
68-
throw new RangeException('crypto_sign keypair must be 96 bytes long');
68+
throw new SodiumException('crypto_sign keypair must be 96 bytes long');
6969
}
7070
return self::substr($keypair, 0, 64);
7171
}
@@ -80,7 +80,7 @@ public static function secretkey($keypair)
8080
public static function publickey($keypair)
8181
{
8282
if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
83-
throw new RangeException('crypto_sign keypair must be 96 bytes long');
83+
throw new SodiumException('crypto_sign keypair must be 96 bytes long');
8484
}
8585
return self::substr($keypair, 64, 32);
8686
}
@@ -212,6 +212,9 @@ public static function sign_open($message, $pk)
212212
*/
213213
public static function sign_detached($message, $sk)
214214
{
215+
if (self::strlen($sk) !== 64) {
216+
throw new SodiumException('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long');
217+
}
215218
# crypto_hash_sha512(az, sk, 32);
216219
$az = hash('sha512', self::substr($sk, 0, 32), true);
217220

@@ -277,8 +280,11 @@ public static function sign_detached($message, $sk)
277280
*/
278281
public static function verify_detached($sig, $message, $pk)
279282
{
280-
if (self::strlen($sig) < 64) {
281-
throw new SodiumException('Signature is too short');
283+
if (self::strlen($sig) !== 64) {
284+
throw new SodiumException('Argument 1 must be CRYPTO_SIGN_BYTES long');
285+
}
286+
if (self::strlen($pk) !== 32) {
287+
throw new SodiumException('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES long');
282288
}
283289
if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) {
284290
throw new SodiumException('S < L - Invalid signature');

‎src/Core/HChaCha20.php‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,18 @@ class ParagonIE_Sodium_Core_HChaCha20 extends ParagonIE_Sodium_Core_ChaCha20
1414
* @param string $key
1515
* @param string|null $c
1616
* @return string
17+
*
18+
* @throws SodiumException
1719
* @throws TypeError
1820
*/
19-
public static function hChaCha20($in = '', $key = '', $c = null)
21+
public static function hChaCha20($in, $key, $c = null)
2022
{
23+
if (self::strlen($in) !== 16) {
24+
throw new SodiumException('Argument 1 must be 16 bytes');
25+
}
26+
if (self::strlen($key) !== 32) {
27+
throw new SodiumException('Argument 2 must be 32 bytes');
28+
}
2129
$ctx = array();
2230

2331
if ($c === null) {

‎src/Core/Poly1305.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ abstract class ParagonIE_Sodium_Core_Poly1305 extends ParagonIE_Sodium_Core_Util
2222
*/
2323
public static function onetimeauth($m, $key)
2424
{
25-
if (self::strlen($key) < 32) {
25+
if (self::strlen($key) !== 32) {
2626
throw new InvalidArgumentException(
2727
'Key must be 32 bytes long.'
2828
);

‎src/Core/Util.php‎

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ protected static function hash_update(&$hs, $data)
338338
* @param string $ignore
339339
* @param bool $strictPadding
340340
* @return string (raw binary)
341-
* @throws RangeException
341+
*
342+
* @throws SodiumException
342343
* @throws TypeError
343344
*/
344345
public static function hex2bin($hexString, $ignore = '', $strictPadding = false)
@@ -356,16 +357,6 @@ public static function hex2bin($hexString, $ignore = '', $strictPadding = false)
356357
$c_acc = 0;
357358
$hex_len = self::strlen($hexString);
358359
$state = 0;
359-
if (($hex_len & 1) !== 0) {
360-
if ($strictPadding) {
361-
throw new RangeException(
362-
'Expected an even number of hexadecimal characters'
363-
);
364-
} else {
365-
$hexString = '0' . $hexString;
366-
++$hex_len;
367-
}
368-
}
369360

370361
$chunk = unpack('C*', $hexString);
371362
while ($hex_pos < $hex_len) {
@@ -392,6 +383,11 @@ public static function hex2bin($hexString, $ignore = '', $strictPadding = false)
392383
}
393384
$state ^= 1;
394385
}
386+
if ($strictPadding && $state !== 0) {
387+
throw new SodiumException(
388+
'Expected an even number of hexadecimal characters'
389+
);
390+
}
395391
return $bin;
396392
}
397393

@@ -536,10 +532,8 @@ public static function load64_le($string)
536532
*/
537533
public static function memcmp($left, $right)
538534
{
539-
if (self::hashEquals($left, $right)) {
540-
return 0;
541-
}
542-
return -1;
535+
$e = (int) !self::hashEquals($left, $right);
536+
return 0 - $e;
543537
}
544538

545539
/**

‎src/Core/XChaCha20.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ParagonIE_Sodium_Core_XChaCha20 extends ParagonIE_Sodium_Core_HChaCha20
1919
* @throws SodiumException
2020
* @throws TypeError
2121
*/
22-
public static function stream($len = 64, $nonce = '', $key = '')
22+
public static function stream($len, $nonce, $key)
2323
{
2424
if (self::strlen($nonce) !== 24) {
2525
throw new SodiumException('Nonce must be 24 bytes long');
@@ -46,7 +46,7 @@ public static function stream($len = 64, $nonce = '', $key = '')
4646
* @throws SodiumException
4747
* @throws TypeError
4848
*/
49-
public static function ietfStream($len = 64, $nonce = '', $key = '')
49+
public static function ietfStream($len, $nonce, $key)
5050
{
5151
if (self::strlen($nonce) !== 24) {
5252
throw new SodiumException('Nonce must be 24 bytes long');
@@ -74,7 +74,7 @@ public static function ietfStream($len = 64, $nonce = '', $key = '')
7474
* @throws SodiumException
7575
* @throws TypeError
7676
*/
77-
public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
77+
public static function streamXorIc($message, $nonce, $key, $ic = '')
7878
{
7979
if (self::strlen($nonce) !== 24) {
8080
throw new SodiumException('Nonce must be 24 bytes long');
@@ -100,7 +100,7 @@ public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
100100
* @throws SodiumException
101101
* @throws TypeError
102102
*/
103-
public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '')
103+
public static function ietfStreamXorIc($message, $nonce, $key, $ic = '')
104104
{
105105
if (self::strlen($nonce) !== 24) {
106106
throw new SodiumException('Nonce must be 24 bytes long');

‎src/Crypto.php‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,10 @@ public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $ke
11881188
$clen = ParagonIE_Sodium_Core_Util::strlen($c);
11891189

11901190
/** @var string $subkey */
1191-
$subkey = ParagonIE_Sodium_Core_HChaCha20::hchacha20($nonce, $key);
1191+
$subkey = ParagonIE_Sodium_Core_HChaCha20::hchacha20(
1192+
ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
1193+
$key
1194+
);
11921195

11931196
/** @var string $block0 */
11941197
$block0 = ParagonIE_Sodium_Core_ChaCha20::stream(
@@ -1244,7 +1247,10 @@ public static function secretstream_xchacha20poly1305_init_push($key)
12441247
$out = random_bytes(24);
12451248

12461249
# crypto_core_hchacha20(state->k, out, k, NULL);
1247-
$subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20($out, $key);
1250+
$subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
1251+
ParagonIE_Sodium_Core_Util::substr($out, 0, 16),
1252+
$key
1253+
);
12481254
$state = new ParagonIE_Sodium_Core_SecretStream_State(
12491255
$subkey,
12501256
ParagonIE_Sodium_Core_Util::substr($out, 16, 8) . str_repeat("\0", 4)

0 commit comments

Comments
 (0)