From ca28176eaf9d2311f0c563977bf723ca657a1118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 19 Mar 2024 19:56:27 +0100 Subject: [PATCH] random: Simplify implementation of php_random_generate_fallback_seed() As all the input bits and pieces are mixed with SHA-1, cross-architecture compatibility is not required and we can just mix in whatever they may look like in memory, instead of going through the `write_*()` helpers that were created for a previous in-development version that first filled a buffer that was then hashed (allowing for easy inspection of the input data, but making it harder to safely add values without checking for buffer overflows all the time). This change should also fix a build error on macOS ZTS: The thread ID is an opaque type and not guaranteed to be arithmetic as per IEEE Std 1003.1-2017. And indeed macOS defines it as a pointer to a structure, failing due to the implicit pointer to integer conversion. --- ext/random/random.c | 66 +++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/ext/random/random.c b/ext/random/random.c index eb0c7286169c..8acf3ee17ef7 100644 --- a/ext/random/random.c +++ b/ext/random/random.c @@ -614,30 +614,12 @@ 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); - } +static inline void fallback_seed_add(PHP_SHA1_CTX *c, void *p, size_t l){ + /* Wrapper around PHP_SHA1Update allowing to pass + * arbitrary pointers without (unsigned char*) casts + * everywhere. + */ + PHP_SHA1Update(c, p, l); } uint64_t php_random_generate_fallback_seed(void) @@ -650,47 +632,55 @@ uint64_t php_random_generate_fallback_seed(void) */ PHP_SHA1_CTX c; struct timeval tv; + void *pointer; + pid_t pid; +#ifdef ZTS + THREAD_T tid; +#endif 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); + fallback_seed_add(&c, &tv, sizeof(tv)); /* Various PIDs. */ - write_32(&c, getpid()); + pid = getpid(); + fallback_seed_add(&c, &pid, sizeof(pid)); #ifndef WIN32 - write_32(&c, getppid()); + pid = getppid(); + fallback_seed_add(&c, &pid, sizeof(pid)); #endif #ifdef ZTS - write_32(&c, tsrm_thread_id()); + tid = tsrm_thread_id(); + fallback_seed_add(&c, &tid, sizeof(tid)); #endif /* Pointer values to benefit from ASLR. */ - write_p(&c, (uintptr_t)&RANDOM_G(fallback_seed_initialized)); - write_p(&c, (uintptr_t)&c); + pointer = &RANDOM_G(fallback_seed_initialized); + fallback_seed_add(&c, &pointer, sizeof(pointer)); + pointer = &c; + fallback_seed_add(&c, &pointer, sizeof(pointer)); /* Updated time. */ gettimeofday(&tv, NULL); - write_32(&c, tv.tv_usec); + fallback_seed_add(&c, &tv, sizeof(tv)); /* Hostname. */ memset(buf, 0, sizeof(buf)); if (gethostname(buf, sizeof(buf) - 1) == 0) { - PHP_SHA1Update(&c, (unsigned char*)buf, strlen(buf)); + fallback_seed_add(&c, buf, strlen(buf)); } /* CSPRNG. */ if (php_random_bytes_silent(buf, 16) == SUCCESS) { - PHP_SHA1Update(&c, (unsigned char*)buf, 16); + fallback_seed_add(&c, buf, 16); } /* Updated time. */ gettimeofday(&tv, NULL); - write_32(&c, tv.tv_usec); + fallback_seed_add(&c, &tv, sizeof(tv)); } else { /* Current time. */ gettimeofday(&tv, NULL); - write_32(&c, tv.tv_sec); - write_32(&c, tv.tv_usec); + fallback_seed_add(&c, &tv, sizeof(tv)); /* Previous state. */ - PHP_SHA1Update(&c, RANDOM_G(fallback_seed), 20); + fallback_seed_add(&c, RANDOM_G(fallback_seed), 20); } PHP_SHA1Final(RANDOM_G(fallback_seed), &c); RANDOM_G(fallback_seed_initialized) = true;