Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 24d561e

Browse files
Add zend_general_random_bytes function
1 parent ddf18e3 commit 24d561e

File tree

7 files changed

+117
-108
lines changed

7 files changed

+117
-108
lines changed

‎Zend/zend.c‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ ZEND_API zend_string *(*zend_resolve_path)(zend_string *filename);
9595
ZEND_API zend_result (*zend_post_startup_cb)(void) = NULL;
9696
ZEND_API void (*zend_post_shutdown_cb)(void) = NULL;
9797
ZEND_API zend_result (*zend_os_csprng_random_bytes)(void *bytes, size_t size, char *errstr, size_t errstr_size) = NULL;
98+
ZEND_API zend_result (*zend_general_random_bytes)(zend_utility_general_random_state *state, void *bytes, size_t size) = NULL;
9899

99100
/* This callback must be signal handler safe! */
100101
void (*zend_on_timeout)(int seconds);
@@ -914,8 +915,9 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */
914915
#endif
915916

916917
/* Set up early utility functions. zend_mm depends on
917-
* zend_os_csprng_random_bytes */
918-
zend_os_csprng_random_bytes = utility_functions->os_csprng_randomn_bytes_function;
918+
* zend_general_random_bytes */
919+
zend_os_csprng_random_bytes = utility_functions->os_csprng_random_bytes_function;
920+
zend_general_random_bytes = utility_functions->general_random_bytes_function;
919921

920922
start_memory_manager();
921923

‎Zend/zend.h‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ struct _zend_class_entry {
234234
} info;
235235
};
236236

237+
typedef union {
238+
zend_max_align_t align;
239+
uint64_t opaque[5];
240+
} zend_utility_general_random_state;
241+
237242
typedef struct _zend_utility_functions {
238243
void (*error_function)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message);
239244
size_t (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
@@ -248,7 +253,8 @@ typedef struct _zend_utility_functions {
248253
void (*printf_to_smart_str_function)(smart_str *buf, const char *format, va_list ap);
249254
char *(*getenv_function)(const char *name, size_t name_len);
250255
zend_string *(*resolve_path_function)(zend_string *filename);
251-
zend_result (*os_csprng_randomn_bytes_function)(void *bytes, size_t size, char *errstr, size_t errstr_size);
256+
zend_result (*os_csprng_random_bytes_function)(void *bytes, size_t size, char *errstr, size_t errstr_size);
257+
zend_result (*general_random_bytes_function)(zend_utility_general_random_state *state, void *bytes, size_t size);
252258
} zend_utility_functions;
253259

254260
typedef struct _zend_utility_values {
@@ -342,6 +348,7 @@ extern void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_l
342348
extern ZEND_API char *(*zend_getenv)(const char *name, size_t name_len);
343349
extern ZEND_API zend_string *(*zend_resolve_path)(zend_string *filename);
344350
extern ZEND_API zend_result (*zend_os_csprng_random_bytes)(void *bytes, size_t size, char *errstr, size_t errstr_size);
351+
extern ZEND_API zend_result (*zend_general_random_bytes)(zend_utility_general_random_state *state, void *bytes, size_t size);
345352

346353
/* These two callbacks are especially for opcache */
347354
extern ZEND_API zend_result (*zend_post_startup_cb)(void);

‎Zend/zend_alloc.c‎

Lines changed: 3 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,6 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list;
263263

264264
static bool zend_mm_use_huge_pages = false;
265265

266-
typedef struct _zend_mm_rand_state {
267-
uint32_t state[4];
268-
} zend_mm_rand_state;
269-
270266
/*
271267
* Memory is retrieved from OS by chunks of fixed size 2MB.
272268
* Inside chunk it's managed by pages of fixed size 4096B.
@@ -342,7 +338,7 @@ struct _zend_mm_heap {
342338
HashTable *tracked_allocs;
343339
#endif
344340
pid_t pid;
345-
zend_mm_rand_state rand_state;
341+
zend_utility_general_random_state rand_state;
346342
};
347343

348344
struct _zend_mm_chunk {
@@ -2043,105 +2039,18 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
20432039
#endif
20442040
}
20452041

2046-
/********/
2047-
/* Rand */
2048-
/********/
2049-
2050-
/* Xoshiro256** PRNG based on implementation from Go Kudo in
2051-
* ext/random/engine_xoshiro256starstar.c, based on code from David Blackman,
2052-
* Sebastiano Vigna. */
2053-
2054-
static inline uint64_t splitmix64(uint64_t *seed)
2055-
{
2056-
uint64_t r;
2057-
2058-
r = (*seed += 0x9e3779b97f4a7c15ULL);
2059-
r = (r ^ (r >> 30)) * 0xbf58476d1ce4e5b9ULL;
2060-
r = (r ^ (r >> 27)) * 0x94d049bb133111ebULL;
2061-
return (r ^ (r >> 31));
2062-
}
2063-
2064-
ZEND_ATTRIBUTE_CONST static inline uint64_t rotl(const uint64_t x, int k)
2065-
{
2066-
return (x << k) | (x >> (64 - k));
2067-
}
2068-
2069-
static inline uint64_t zend_mm_rand_generate(zend_mm_rand_state *s)
2070-
{
2071-
const uint64_t r = rotl(s->state[1] * 5, 7) * 9;
2072-
const uint64_t t = s->state[1] << 17;
2073-
2074-
s->state[2] ^= s->state[0];
2075-
s->state[3] ^= s->state[1];
2076-
s->state[1] ^= s->state[2];
2077-
s->state[0] ^= s->state[3];
2078-
2079-
s->state[2] ^= t;
2080-
2081-
s->state[3] = rotl(s->state[3], 45);
2082-
2083-
return r;
2084-
}
2085-
2086-
static inline void zend_mm_rand_seed256(zend_mm_rand_state *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3)
2087-
{
2088-
state->state[0] = s0;
2089-
state->state[1] = s1;
2090-
state->state[2] = s2;
2091-
state->state[3] = s3;
2092-
}
2093-
2094-
static inline void zend_mm_rand_seed64(zend_mm_rand_state *state, uint64_t seed)
2095-
{
2096-
uint64_t s[4];
2097-
2098-
s[0] = splitmix64(&seed);
2099-
s[1] = splitmix64(&seed);
2100-
s[2] = splitmix64(&seed);
2101-
s[3] = splitmix64(&seed);
2102-
2103-
zend_mm_rand_seed256(state, s[0], s[1], s[2], s[3]);
2104-
}
2105-
21062042
/******************/
21072043
/* Initialization */
21082044
/******************/
21092045

21102046
static zend_result zend_mm_refresh_key(zend_mm_heap *heap)
21112047
{
2112-
heap->shadow_key = (uintptr_t) zend_mm_rand_generate(&heap->rand_state);
2113-
2114-
return SUCCESS;
2048+
return zend_general_random_bytes(&heap->rand_state, &heap->shadow_key, sizeof(heap->shadow_key));
21152049
}
21162050

21172051
static zend_result zend_mm_init_key(zend_mm_heap *heap)
21182052
{
2119-
uint64_t seed[4];
2120-
char errstr[128];
2121-
if (zend_os_csprng_random_bytes(&seed, sizeof(seed), errstr, sizeof(errstr)) == SUCCESS) {
2122-
zend_mm_rand_seed256(&heap->rand_state,
2123-
seed[0], seed[1], seed[2], seed[3]);
2124-
} else {
2125-
/* Fallback to weak seed generation */
2126-
#if ZEND_MM_ERROR
2127-
fprintf(stderr, "Could not generate secure random seed: %s\n", errstr);
2128-
#endif
2129-
zend_hrtime_t nanotime = zend_hrtime();
2130-
uint64_t v = 0;
2131-
v ^= (uint64_t) nanotime;
2132-
splitmix64(&v);
2133-
v ^= (uint64_t) getpid();
2134-
splitmix64(&v);
2135-
#ifdef ZTS
2136-
THREAD_T tid = tsrm_thread_id();
2137-
uint64_t tmp = 0;
2138-
memcpy(&tmp, &tid, MIN(sizeof(tmp), sizeof(tid)));
2139-
v ^= tmp;
2140-
splitmix64(&v);
2141-
#endif
2142-
zend_mm_rand_seed64(&heap->rand_state, v);
2143-
}
2144-
2053+
memset(&heap->rand_state, 0, sizeof(heap->rand_state));
21452054
return zend_mm_refresh_key(heap);
21462055
}
21472056

‎Zend/zend_portability.h‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,4 +791,20 @@ extern "C++" {
791791
# define ZEND_STATIC_ASSERT(c, m)
792792
#endif
793793

794+
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) /* C11 */ \
795+
|| (defined(__cplusplus) && __cplusplus >= 201103L) /* C++11 */
796+
typedef max_align_t zend_max_align_t;
797+
#else
798+
typedef union {
799+
char c;
800+
short s;
801+
int i;
802+
long l;
803+
float f;
804+
double d;
805+
void *p;
806+
void (*fun)();
807+
} zend_max_align_t;
808+
#endif
809+
794810
#endif /* ZEND_PORTABILITY_H */

‎ext/random/php_random.h‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@
3737

3838
PHPAPI double php_combined_lcg(void);
3939

40+
typedef struct _php_random_fallback_seed_state php_random_fallback_seed_state;
41+
typedef struct _php_random_state_for_zend php_random_state_for_zend;
42+
4043
PHPAPI uint64_t php_random_generate_fallback_seed(void);
44+
PHPAPI uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_state *state);
45+
PHPAPI zend_result php_general_random_bytes_for_zend(zend_utility_general_random_state *state, void *bytes, size_t size);
4146

4247
static inline zend_long GENERATE_SEED(void)
4348
{
@@ -108,6 +113,18 @@ typedef struct _php_random_algo_with_state {
108113
void *state;
109114
} php_random_algo_with_state;
110115

116+
typedef struct _php_random_fallback_seed_state {
117+
bool initialized;
118+
unsigned char seed[20];
119+
} php_random_fallback_seed_state;
120+
121+
typedef struct _php_random_state_for_zend {
122+
bool initialized;
123+
php_random_status_state_xoshiro256starstar xoshiro256starstar_state;
124+
} php_random_state_for_zend;
125+
126+
ZEND_STATIC_ASSERT(sizeof(zend_utility_general_random_state) >= sizeof(php_random_state_for_zend), "");
127+
111128
extern PHPAPI const php_random_algo php_random_algo_combinedlcg;
112129
extern PHPAPI const php_random_algo php_random_algo_mt19937;
113130
extern PHPAPI const php_random_algo php_random_algo_pcgoneseq128xslrr64;
@@ -206,8 +223,7 @@ PHP_RINIT_FUNCTION(random);
206223
ZEND_BEGIN_MODULE_GLOBALS(random)
207224
bool combined_lcg_seeded;
208225
bool mt19937_seeded;
209-
bool fallback_seed_initialized;
210-
unsigned char fallback_seed[20];
226+
php_random_fallback_seed_state fallback_seed_state;
211227
php_random_status_state_combinedlcg combined_lcg;
212228
php_random_status_state_mt19937 mt19937;
213229
ZEND_END_MODULE_GLOBALS(random)

‎ext/random/random.c‎

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ static inline void fallback_seed_add(PHP_SHA1_CTX *c, void *p, size_t l){
622622
PHP_SHA1Update(c, p, l);
623623
}
624624

625-
uint64_t php_random_generate_fallback_seed(void)
625+
uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_state*state)
626626
{
627627
/* Mix various values using SHA-1 as a PRF to obtain as
628628
* much entropy as possible, hopefully generating an
@@ -640,7 +640,7 @@ uint64_t php_random_generate_fallback_seed(void)
640640
char buf[64 + 1];
641641

642642
PHP_SHA1Init(&c);
643-
if (!RANDOM_G(fallback_seed_initialized)) {
643+
if (!state->initialized) {
644644
/* Current time. */
645645
gettimeofday(&tv, NULL);
646646
fallback_seed_add(&c, &tv, sizeof(tv));
@@ -656,7 +656,7 @@ uint64_t php_random_generate_fallback_seed(void)
656656
fallback_seed_add(&c, &tid, sizeof(tid));
657657
#endif
658658
/* Pointer values to benefit from ASLR. */
659-
pointer = &RANDOM_G(fallback_seed_initialized);
659+
pointer = state;
660660
fallback_seed_add(&c, &pointer, sizeof(pointer));
661661
pointer = &c;
662662
fallback_seed_add(&c, &pointer, sizeof(pointer));
@@ -680,24 +680,82 @@ uint64_t php_random_generate_fallback_seed(void)
680680
gettimeofday(&tv, NULL);
681681
fallback_seed_add(&c, &tv, sizeof(tv));
682682
/* Previous state. */
683-
fallback_seed_add(&c, RANDOM_G(fallback_seed), 20);
683+
fallback_seed_add(&c, state->seed, 20);
684684
}
685-
PHP_SHA1Final(RANDOM_G(fallback_seed), &c);
686-
RANDOM_G(fallback_seed_initialized) = true;
685+
PHP_SHA1Final(state->seed, &c);
686+
state->initialized = true;
687687

688688
uint64_t result = 0;
689689

690690
for (int i = 0; i < sizeof(result); i++) {
691-
result = result | (((uint64_t)RANDOM_G(fallback_seed)[i]) << (i * 8));
691+
result = result | (((uint64_t)state->seed[i]) << (i * 8));
692692
}
693693

694694
return result;
695695
}
696696

697+
uint64_t php_random_generate_fallback_seed(void)
698+
{
699+
return php_random_generate_fallback_seed_ex(&RANDOM_G(fallback_seed_state));
700+
}
701+
702+
static zend_result php_general_random_bytes_for_zend_initialize(php_random_state_for_zend *state)
703+
{
704+
uint64_t t[4];
705+
706+
do {
707+
char errstr[128];
708+
if (php_random_bytes_ex(&t, sizeof(t), errstr, sizeof(errstr)) == FAILURE) {
709+
#if ZEND_DEBUG
710+
fprintf(stderr, "php_random_bytes_ex: Failed to generate a random seed: %s\n", errstr);
711+
#endif
712+
return FAILURE;
713+
}
714+
} while (UNEXPECTED(t[0] == 0 && t[1] == 0 && t[2] == 0 && t[3] == 0));
715+
716+
php_random_xoshiro256starstar_seed256(&state->xoshiro256starstar_state, t[0], t[1], t[2], t[3]);
717+
718+
return SUCCESS;
719+
}
720+
721+
static void php_general_random_bytes_for_zend_initialize_fallback(php_random_state_for_zend *state)
722+
{
723+
uint64_t t;
724+
php_random_fallback_seed_state fallback_state;
725+
726+
do {
727+
t = php_random_generate_fallback_seed_ex(&fallback_state);
728+
} while (UNEXPECTED(t == 0));
729+
730+
php_random_xoshiro256starstar_seed64(&state->xoshiro256starstar_state, t);
731+
}
732+
733+
PHPAPI zend_result php_general_random_bytes_for_zend(zend_utility_general_random_state *opaque_state, void *bytes, size_t size)
734+
{
735+
php_random_state_for_zend *state = (php_random_state_for_zend*) opaque_state;
736+
737+
if (!state->initialized) {
738+
if (php_general_random_bytes_for_zend_initialize(state) == FAILURE) {
739+
php_general_random_bytes_for_zend_initialize_fallback(state);
740+
}
741+
state->initialized = true;
742+
}
743+
744+
while (size > 0) {
745+
php_random_result result = php_random_algo_xoshiro256starstar.generate(&state->xoshiro256starstar_state);
746+
size_t chunk_size = MIN(size, sizeof(result.size));
747+
memcpy(bytes, &result.result, chunk_size);
748+
size -= chunk_size;
749+
bytes += chunk_size;
750+
}
751+
752+
return SUCCESS;
753+
}
754+
697755
/* {{{ PHP_GINIT_FUNCTION */
698756
static PHP_GINIT_FUNCTION(random)
699757
{
700-
random_globals->fallback_seed_initialized = false;
758+
random_globals->fallback_seed_state.initialized = false;
701759
}
702760
/* }}} */
703761

‎main/main.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2115,7 +2115,8 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi
21152115
zuf.printf_to_smart_str_function = php_printf_to_smart_str;
21162116
zuf.getenv_function = sapi_getenv;
21172117
zuf.resolve_path_function = php_resolve_path_for_zend;
2118-
zuf.os_csprng_randomn_bytes_function = php_random_bytes_ex;
2118+
zuf.os_csprng_random_bytes_function = php_random_bytes_ex;
2119+
zuf.general_random_bytes_function = php_general_random_bytes_for_zend;
21192120
zend_startup(&zuf);
21202121
zend_reset_lc_ctype_locale();
21212122
zend_update_current_locale();

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /