1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

random: Improve the output quality of RANDOM_SEED() (#13730)

* random: Improve the output quality of RANDOM_SEED()

Previously 4 consecutive calls to `RANDOM_SEED()` each for 4 different CLI
requests resulted in:

    $ sapi/cli/php test.php
    2c13e9fde9caa
    2c13e9fd1d6b0
    2c13e9fd4de34
    2c13e9fd1610e
    $ sapi/cli/php test.php
    2c1436764fe07
    2c14367621770
    2c143676c0bf6
    2c143676e02f5
    $ sapi/cli/php test.php
    2c144995a0626
    2c14499590fe2
    2c144995c65db
    2c14499536833
    $ sapi/cli/php test.php
    2c145cb30860b
    2c145cb3ec027
    2c145cb33b4ca
    2c145cb38ff63

Now they result in:

    $ sapi/cli/php test.php
    6796973ace1b5f3d
    1913daf5c158cb4b
    255dbf24237bc8c9
    7c3ba22e60f35196
    $ sapi/cli/php test.php
    afb7cc9ba9819cd2
    3e01a71b91ad020c
    6b718364d3ef108
    bdcd17beeb4b31d2
    $ sapi/cli/php test.php
    53d36eb9b83f8788
    4381c85e816187aa
    2e9b32ee9898e71e
    31d15c946842bddb
    $ sapi/cli/php test.php
    2037a3cba88114b4
    ba0b0d93a9bb43aa
    e13d82d2421269e2
    191de474f3292240

* tree-wide: Replace GENERATE_SEED() by php_random_generate_fallback_seed()

* random: Fix NTS build

* random: Fix Windows build
This commit is contained in:
Tim Düsterhus
2024-03-18 16:08:23 +01:00
committed by GitHub
parent 4f7a3d9053
commit 81744d6cf7
6 changed files with 111 additions and 14 deletions

View File

@@ -174,6 +174,11 @@ PHP 8.4 INTERNALS UPGRADE NOTES
- The CSPRNG API (php_random_(bytes|int)_*) is now provided by the new
and much smaller php_random_csprng.h header. The new header is included
in php_random.h for compatibility with existing users.
- A new php_random_generate_fallback_seed() function has been added as a
replacement for the generically named GENERATE_SEED(). The internal
implementation has been improved to generate better seeds, however any
users should use the opportunity to verify that seeding is first
attempted using the CSPRNG for better output size flexibility.
c. ext/xsl
- The function php_xsl_create_object() was removed as it was not used

View File

@@ -1734,9 +1734,9 @@ static void gmp_init_random(void)
/* Initialize */
gmp_randinit_mt(GMPG(rand_state));
/* Seed */
zend_long seed = 0;
if (php_random_bytes_silent(&seed, sizeof(zend_long)) == FAILURE) {
seed = GENERATE_SEED();
unsigned long int seed = 0;
if (php_random_bytes_silent(&seed, sizeof(seed)) == FAILURE) {
seed = (unsigned long int)php_random_generate_fallback_seed();
}
gmp_randseed_ui(GMPG(rand_state), seed);

View File

@@ -242,7 +242,7 @@ PHPAPI void php_random_mt19937_seed_default(php_random_status_state_mt19937 *sta
uint32_t seed = 0;
if (php_random_bytes_silent(&seed, sizeof(seed)) == FAILURE) {
seed = GENERATE_SEED();
seed = (uint32_t)php_random_generate_fallback_seed();
}
php_random_mt19937_seed32(state, seed);

View File

@@ -37,17 +37,11 @@
PHPAPI double php_combined_lcg(void);
PHPAPI uint64_t php_random_generate_fallback_seed(void);
static inline zend_long GENERATE_SEED(void)
{
zend_ulong pid;
# ifdef PHP_WIN32
pid = (zend_ulong) GetCurrentProcessId();
# else
pid = (zend_ulong) getpid();
# endif
return (((zend_long) ((zend_ulong) time(NULL) * pid)) ^ ((zend_long) (1000000.0 * php_combined_lcg())));
return (zend_long)php_random_generate_fallback_seed();
}
# define PHP_MT_RAND_MAX ((zend_long) (0x7FFFFFFF)) /* (1<<31) - 1 */
@@ -213,6 +207,8 @@ ZEND_BEGIN_MODULE_GLOBALS(random)
int random_fd;
bool combined_lcg_seeded;
bool mt19937_seeded;
bool fallback_seed_initialized;
unsigned char fallback_seed[20];
php_random_status_state_combinedlcg combined_lcg;
php_random_status_state_mt19937 mt19937;
ZEND_END_MODULE_GLOBALS(random)

View File

@@ -12,6 +12,7 @@
+----------------------------------------------------------------------+
| Authors: Sammy Kaye Powers <me@sammyk.me> |
| Go Kudo <zeriyoshi@php.net> |
| Tim Düsterhus <timwolla@php.net> |
+----------------------------------------------------------------------+
*/
@@ -31,6 +32,7 @@
#include "php_random.h"
#include "php_random_csprng.h"
#include "ext/standard/sha1.h"
#if HAVE_UNISTD_H
# include <unistd.h>
@@ -612,10 +614,101 @@ PHP_FUNCTION(random_int)
}
/* }}} */
static void write_32(PHP_SHA1_CTX *c, uint32_t u)
{
unsigned char buf[4];
unsigned char *p = buf;
*(p++) = (u >> 0) & 0xff;
*(p++) = (u >> 8) & 0xff;
*(p++) = (u >> 16) & 0xff;
*(p++) = (u >> 24) & 0xff;
PHP_SHA1Update(c, buf, sizeof(buf));
}
static void write_64(PHP_SHA1_CTX *c, uint64_t u)
{
write_32(c, u);
write_32(c, u >> 32);
}
static void write_p(PHP_SHA1_CTX *c, uintptr_t p)
{
if (sizeof(p) == 4) {
write_32(c, p);
} else {
write_64(c, p);
}
}
uint64_t php_random_generate_fallback_seed(void)
{
/* Mix various values using SHA-1 as a PRF to obtain as
* much entropy as possible, hopefully generating an
* unpredictable and independent uint64_t. Nevertheless
* the output of this function MUST NOT be treated as
* being cryptographically safe.
*/
PHP_SHA1_CTX c;
struct timeval tv;
char buf[64 + 1];
PHP_SHA1Init(&c);
if (!RANDOM_G(fallback_seed_initialized)) {
/* Current time. */
gettimeofday(&tv, NULL);
write_32(&c, tv.tv_sec);
write_32(&c, tv.tv_usec);
/* Various PIDs. */
write_32(&c, getpid());
#ifndef WIN32
write_32(&c, getppid());
#endif
#ifdef ZTS
write_32(&c, tsrm_thread_id());
#endif
/* Pointer values to benefit from ASLR. */
write_p(&c, (uintptr_t)&RANDOM_G(fallback_seed_initialized));
write_p(&c, (uintptr_t)&c);
/* Updated time. */
gettimeofday(&tv, NULL);
write_32(&c, tv.tv_usec);
/* Hostname. */
memset(buf, 0, sizeof(buf));
if (gethostname(buf, sizeof(buf) - 1) == 0) {
PHP_SHA1Update(&c, (unsigned char*)buf, strlen(buf));
}
/* CSPRNG. */
if (php_random_bytes_silent(buf, 16) == SUCCESS) {
PHP_SHA1Update(&c, (unsigned char*)buf, 16);
}
/* Updated time. */
gettimeofday(&tv, NULL);
write_32(&c, tv.tv_usec);
} else {
/* Current time. */
gettimeofday(&tv, NULL);
write_32(&c, tv.tv_sec);
write_32(&c, tv.tv_usec);
/* Previous state. */
PHP_SHA1Update(&c, RANDOM_G(fallback_seed), 20);
}
PHP_SHA1Final(RANDOM_G(fallback_seed), &c);
RANDOM_G(fallback_seed_initialized) = true;
uint64_t result = 0;
for (int i = 0; i < sizeof(result); i++) {
result = result | (((uint64_t)RANDOM_G(fallback_seed)[i]) << (i * 8));
}
return result;
}
/* {{{ PHP_GINIT_FUNCTION */
static PHP_GINIT_FUNCTION(random)
{
random_globals->random_fd = -1;
random_globals->fallback_seed_initialized = false;
}
/* }}} */

View File

@@ -2879,7 +2879,10 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */
};
php_random_uint128_t seed;
if (php_random_bytes_silent(&seed, sizeof(seed)) == FAILURE) {
seed = php_random_uint128_constant(GENERATE_SEED(), GENERATE_SEED());
seed = php_random_uint128_constant(
php_random_generate_fallback_seed(),
php_random_generate_fallback_seed()
);
}
php_random_pcgoneseq128xslrr64_seed128(ps_globals->random.state, seed);
}