Improve openssl_random_pseudo_bytes()

CSPRNG implementations should always fail closed. Now
openssl_random_pseudo_bytes() will fail closed by throwing an
`\Exception` in fail conditions.

RFC: https://wiki.php.net/rfc/improve-openssl-random-pseudo-bytes
This commit is contained in:
Sammy Kaye Powers 2018-11-19 18:14:53 -05:00 committed by Nikita Popov
parent 894e78b494
commit 74c0e580ef
5 changed files with 34 additions and 7 deletions

2
NEWS
View file

@ -42,6 +42,8 @@ PHP NEWS
- OpenSSL: - OpenSSL:
. Added openssl_x509_verify function. (Ben Scholzen) . Added openssl_x509_verify function. (Ben Scholzen)
. openssl_random_pseudo_bytes() now throws in error conditions.
(Sammy Kaye Powers)
- PDO_OCI: - PDO_OCI:
. Implemented FR #76908 (PDO_OCI getColumnMeta() not implemented). . Implemented FR #76908 (PDO_OCI getColumnMeta() not implemented).

View file

@ -37,6 +37,15 @@ PHP 7.4 UPGRADE NOTES
. The default parameter value of idn_to_ascii() and idn_to_utf8() is now . The default parameter value of idn_to_ascii() and idn_to_utf8() is now
INTL_IDNA_VARIANT_UTS46 instead of the deprecated INTL_IDNA_VARIANT_2003. INTL_IDNA_VARIANT_UTS46 instead of the deprecated INTL_IDNA_VARIANT_2003.
- Openssl:
. The openssl_random_pseudo_bytes() function will now throw an exception in
error situations, similar to random_bytes(). In particular, an Error is
thrown if the number of requested bytes is smaller *or equal* than zero,
and an Exception is thrown is sufficient randomness cannot be gathered.
The $crypto_strong output argument is guaranteed to always be true if the
function does not throw, so explicitly checking it is not necessary.
RFC: http://php.net/manual/de/function.openssl-random-pseudo-bytes.php
- PDO: - PDO:
. Attempting to serialize a PDO or PDOStatement instance will now generate . Attempting to serialize a PDO or PDOStatement instance will now generate
an Exception rather than a PDOException, consistent with other internal an Exception rather than a PDOException, consistent with other internal

View file

@ -28,6 +28,7 @@
#include "php.h" #include "php.h"
#include "php_ini.h" #include "php_ini.h"
#include "php_openssl.h" #include "php_openssl.h"
#include "zend_exceptions.h"
/* PHP Includes */ /* PHP Includes */
#include "ext/standard/file.h" #include "ext/standard/file.h"
@ -6861,7 +6862,8 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
|| ZEND_LONG_INT_OVFL(buffer_length) || ZEND_LONG_INT_OVFL(buffer_length)
#endif #endif
) { ) {
RETURN_FALSE; zend_throw_exception(zend_ce_error, "Length must be greater than 0", 0);
return;
} }
buffer = zend_string_alloc(buffer_length, 0); buffer = zend_string_alloc(buffer_length, 0);
@ -6872,7 +6874,8 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
if (zstrong_result_returned) { if (zstrong_result_returned) {
ZVAL_FALSE(zstrong_result_returned); ZVAL_FALSE(zstrong_result_returned);
} }
RETURN_FALSE; zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
return;
} }
#else #else
@ -6884,7 +6887,8 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
if (zstrong_result_returned) { if (zstrong_result_returned) {
ZVAL_FALSE(zstrong_result_returned); ZVAL_FALSE(zstrong_result_returned);
} }
RETURN_FALSE; zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
return;
} else { } else {
php_openssl_store_errors(); php_openssl_store_errors();
} }

View file

@ -4,13 +4,11 @@ openssl_random_pseudo_bytes() tests
<?php if (!extension_loaded("openssl")) print "skip"; ?> <?php if (!extension_loaded("openssl")) print "skip"; ?>
--FILE-- --FILE--
<?php <?php
for ($i = 0; $i < 10; $i++) { for ($i = 1; $i < 10; $i++) {
var_dump(bin2hex(openssl_random_pseudo_bytes($i, $strong))); var_dump(bin2hex(openssl_random_pseudo_bytes($i)));
} }
?> ?>
--EXPECTF-- --EXPECTF--
string(0) ""
string(2) "%s" string(2) "%s"
string(4) "%s" string(4) "%s"
string(6) "%s" string(6) "%s"

View file

@ -0,0 +1,14 @@
--TEST--
Test error operation of openssl_random_pseudo_bytes()
--SKIPIF--
<?php if (!extension_loaded("openssl")) print "skip"; ?>
--FILE--
<?php
try {
openssl_random_pseudo_bytes(0);
} catch (Error $e) {
echo $e->getMessage().PHP_EOL;
}
?>
--EXPECTF--
Length must be greater than 0