Skip to content

Commit 23bd7bc

Browse files
committed
refactor php_win32_get_random_bytes()
- avoid locking - initialize only once - the process will fail, if no init failed
1 parent 02991f7 commit 23bd7bc

File tree

3 files changed

+35
-63
lines changed

3 files changed

+35
-63
lines changed

main/main.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2095,7 +2095,10 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
20952095
#endif
20962096

20972097
#ifdef PHP_WIN32
2098-
php_win32_init_rng_lock();
2098+
if (!php_win32_init_random_bytes()) {
2099+
php_printf("\ncrypto service provider failed\n");
2100+
return FAILURE;
2101+
}
20992102
#endif
21002103

21012104
module_shutdown = 0;
@@ -2409,7 +2412,7 @@ void php_module_shutdown(void)
24092412
#endif
24102413

24112414
#ifdef PHP_WIN32
2412-
php_win32_free_rng_lock();
2415+
(void)php_win32_shutdown_random_bytes();
24132416
#endif
24142417

24152418
sapi_flush();

win32/winutil.c

Lines changed: 27 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -51,77 +51,50 @@ int php_win32_check_trailing_space(const char * path, const int path_len) {
5151
}
5252
}
5353

54-
HCRYPTPROV hCryptProv;
55-
unsigned int has_crypto_ctx = 0;
54+
static HCRYPTPROV hCryptProv;
55+
static BOOL has_crypto_ctx = 0;
5656

57-
#ifdef ZTS
58-
MUTEX_T php_lock_win32_cryptoctx;
59-
void php_win32_init_rng_lock()
57+
#ifdef PHP_EXPORTS
58+
BOOL php_win32_init_random_bytes(void)
6059
{
61-
php_lock_win32_cryptoctx = tsrm_mutex_alloc();
60+
int err;
61+
62+
/* CRYPT_VERIFYCONTEXT > only hashing&co-like use, no need to acces prv keys */
63+
has_crypto_ctx = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_VERIFYCONTEXT);
64+
err = GetLastError();
65+
if (!has_crypto_ctx) {
66+
/* Could mean that the key container does not exist, let try
67+
again by asking for a new one. If it fails here, it surely means that the user running
68+
this process does not have the permission(s) to use this container.
69+
*/
70+
if (NTE_BAD_KEYSET == err) {
71+
has_crypto_ctx = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT);
72+
}
73+
}
74+
75+
return has_crypto_ctx;
6276
}
6377

64-
void php_win32_free_rng_lock()
78+
BOOL php_win32_shutdown_random_bytes(void)
6579
{
66-
tsrm_mutex_lock(php_lock_win32_cryptoctx);
67-
if (has_crypto_ctx == 1) {
68-
CryptReleaseContext(hCryptProv, 0);
69-
has_crypto_ctx = 0;
80+
BOOL ret = TRUE;
81+
82+
if (has_crypto_ctx) {
83+
ret = CryptReleaseContext(hCryptProv, 0);
7084
}
71-
tsrm_mutex_unlock(php_lock_win32_cryptoctx);
72-
tsrm_mutex_free(php_lock_win32_cryptoctx);
7385

86+
return ret;
7487
}
75-
#else
76-
#define php_win32_init_rng_lock();
77-
#define php_win32_free_rng_lock();
7888
#endif
7989

80-
81-
8290
PHP_WINUTIL_API int php_win32_get_random_bytes(unsigned char *buf, size_t size) { /* {{{ */
8391

8492
BOOL ret;
8593

86-
#ifdef ZTS
87-
tsrm_mutex_lock(php_lock_win32_cryptoctx);
88-
#endif
89-
90-
if (has_crypto_ctx == 0) {
91-
/* CRYPT_VERIFYCONTEXT > only hashing&co-like use, no need to acces prv keys */
92-
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_VERIFYCONTEXT )) {
93-
/* Could mean that the key container does not exist, let try
94-
again by asking for a new one. If it fails here, it surely means that the user running
95-
this process does not have the permission(s) to use this container.
96-
*/
97-
if (GetLastError() == NTE_BAD_KEYSET) {
98-
if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT )) {
99-
has_crypto_ctx = 1;
100-
} else {
101-
has_crypto_ctx = 0;
102-
}
103-
}
104-
} else {
105-
has_crypto_ctx = 1;
106-
}
107-
}
108-
109-
#ifdef ZTS
110-
tsrm_mutex_unlock(php_lock_win32_cryptoctx);
111-
#endif
112-
113-
if (has_crypto_ctx == 0) {
114-
return FAILURE;
115-
}
116-
11794
/* XXX should go in the loop if size exceeds UINT_MAX */
11895
ret = CryptGenRandom(hCryptProv, (DWORD)size, buf);
11996

120-
if (ret) {
121-
return SUCCESS;
122-
} else {
123-
return FAILURE;
124-
}
97+
return ret ? SUCCESS : FAILURE;
12598
}
12699
/* }}} */
127100

win32/winutil.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,9 @@ PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error);
2727
#define php_win_err() php_win32_error_to_msg(GetLastError())
2828
int php_win32_check_trailing_space(const char * path, const int path_len);
2929
PHP_WINUTIL_API int php_win32_get_random_bytes(unsigned char *buf, size_t size);
30-
31-
#ifdef ZTS
32-
void php_win32_init_rng_lock();
33-
void php_win32_free_rng_lock();
34-
#else
35-
#define php_win32_init_rng_lock();
36-
#define php_win32_free_rng_lock();
30+
#ifdef PHP_EXPORTS
31+
BOOL php_win32_init_random_bytes(void);
32+
BOOL php_win32_shutdown_random_bytes(void);
3733
#endif
3834

3935
#if !defined(ECURDIR)

0 commit comments

Comments
 (0)