Skip to content

Reseed the RNG on the first call to openssl_random_pseudo_bytes #1843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 65 additions & 3 deletions ext/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ enum php_openssl_cipher_type {
PHP_OPENSSL_CIPHER_DEFAULT = PHP_OPENSSL_CIPHER_RC2_40
};

ZEND_DECLARE_MODULE_GLOBALS(openssl);
static PHP_GINIT_FUNCTION(openssl);

PHP_FUNCTION(openssl_get_md_methods);
PHP_FUNCTION(openssl_get_cipher_methods);

Expand Down Expand Up @@ -519,11 +522,15 @@ zend_module_entry openssl_module_entry = {
openssl_functions,
PHP_MINIT(openssl),
PHP_MSHUTDOWN(openssl),
NULL,
PHP_RINIT(openssl),
NULL,
PHP_MINFO(openssl),
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
PHP_MODULE_GLOBALS(openssl),
PHP_GINIT(openssl),
NULL,
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */

Expand Down Expand Up @@ -624,6 +631,21 @@ static STACK_OF(X509) * load_all_certs_from_file(char *certfile);
static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC);
static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req TSRMLS_DC);

static int php_openssl_rand_seed() /* {{{ */
{
if (OPENSSL_G(rng_reseeded) != 1) {
int result = RAND_poll();

if (result != 1) {
return FAILURE;
}

OPENSSL_G(rng_reseeded) = 1;
}

return SUCCESS;
} /* }}} */

static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */
{
zval **data;
Expand Down Expand Up @@ -1107,13 +1129,28 @@ static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo) { /* {
}
/* }}} */


/* {{{ INI Settings */
PHP_INI_BEGIN()
PHP_INI_ENTRY("openssl.cafile", NULL, PHP_INI_PERDIR, NULL)
PHP_INI_ENTRY("openssl.capath", NULL, PHP_INI_PERDIR, NULL)
PHP_INI_END()
/* }}} */


/* {{{ PHP_GINIT_FUNCTION */
static PHP_GINIT_FUNCTION(openssl)
{
openssl_globals->rng_reseeded = 0;
}
/* }}} */

/* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(openssl)
{
OPENSSL_G(rng_reseeded) = 0;
}
/* }}} */

/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(openssl)
Expand Down Expand Up @@ -3083,6 +3120,12 @@ PHP_FUNCTION(openssl_csr_new)
}
RETVAL_FALSE;

// php_openssl_generate_private_key uses php_openssl_write_rand_file which uses RAND_write_file, which uses RAND_bytes
if (php_openssl_rand_seed() != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "couldn't seed the randomizer sufficiently");
RETURN_FALSE;
}

PHP_SSL_REQ_INIT(&req);

if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
Expand Down Expand Up @@ -3540,6 +3583,13 @@ PHP_FUNCTION(openssl_pkey_new)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &args) == FAILURE) {
return;
}

// php_openssl_generate_private_key uses php_openssl_write_rand_file which uses RAND_write_file, which uses RAND_bytes
if (php_openssl_rand_seed() != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "couldn't seed the randomizer sufficiently");
RETURN_FALSE;
}

RETVAL_FALSE;

if (args && Z_TYPE_P(args) == IS_ARRAY) {
Expand Down Expand Up @@ -4883,6 +4933,12 @@ PHP_FUNCTION(openssl_seal)
} else {
cipher = EVP_rc4();
}

// EVP_SealInit uses RAND_bytes
if (php_openssl_rand_seed() != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "couldn't seed the randomizer sufficiently");
RETURN_FALSE;
}

pkeys = safe_emalloc(nkeys, sizeof(*pkeys), 0);
eksl = safe_emalloc(nkeys, sizeof(*eksl), 0);
Expand Down Expand Up @@ -5178,6 +5234,7 @@ PHP_FUNCTION(openssl_encrypt)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) {
return;
}

cipher_type = EVP_get_cipherbyname(method);
if (!cipher_type) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown cipher algorithm");
Expand Down Expand Up @@ -5398,6 +5455,11 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
unsigned char *buffer = NULL;
zval *zstrong_result_returned = NULL;

if (php_openssl_rand_seed() != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "couldn't seed the randomizer sufficiently");
RETURN_FALSE;
}

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) {
return;
}
Expand Down
13 changes: 13 additions & 0 deletions ext/openssl/php_openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ PHP_MINIT_FUNCTION(openssl);
PHP_MSHUTDOWN_FUNCTION(openssl);
PHP_MINFO_FUNCTION(openssl);

PHP_RINIT_FUNCTION(openssl);

PHP_FUNCTION(openssl_pkey_get_private);
PHP_FUNCTION(openssl_pkey_get_public);
PHP_FUNCTION(openssl_pkey_free);
Expand Down Expand Up @@ -101,6 +103,17 @@ PHP_FUNCTION(openssl_spki_export);
PHP_FUNCTION(openssl_spki_export_challenge);

PHP_FUNCTION(openssl_get_cert_locations);

ZEND_BEGIN_MODULE_GLOBALS(openssl)
zend_bool rng_reseeded;
ZEND_END_MODULE_GLOBALS(openssl)

#ifdef ZTS
#define OPENSSL_G(v) TSRMG(openssl_globals_id, zend_openssl_globals *, v)
#else
#define OPENSSL_G(v) (openssl_globals.v)
#endif

#else

#define phpext_openssl_ptr NULL
Expand Down