summaryrefslogtreecommitdiff
path: root/ext/openssl/openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/openssl/openssl.c')
-rw-r--r--ext/openssl/openssl.c113
1 files changed, 93 insertions, 20 deletions
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 49a5f53caf..b462d0e66c 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -907,10 +907,16 @@ static int add_oid_section(struct php_x509_request * req) /* {{{ */
req->config_filename, req->var, req->req_config) == FAILURE) return FAILURE
#define SET_OPTIONAL_STRING_ARG(key, varname, defval) \
- if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), key, sizeof(key)-1)) != NULL && Z_TYPE_P(item) == IS_STRING) \
- varname = Z_STRVAL_P(item); \
- else \
- varname = defval
+ do { \
+ if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), key, sizeof(key)-1)) != NULL && Z_TYPE_P(item) == IS_STRING) { \
+ varname = Z_STRVAL_P(item); \
+ } else { \
+ varname = defval; \
+ if (varname == NULL) { \
+ php_openssl_store_errors(); \
+ } \
+ } \
+ } while(0)
#define SET_OPTIONAL_LONG_ARG(key, varname, defval) \
if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), key, sizeof(key)-1)) != NULL && Z_TYPE_P(item) == IS_LONG) \
@@ -988,9 +994,8 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
str = CONF_get_string(req->req_config, req->section_name, "encrypt_rsa_key");
if (str == NULL) {
str = CONF_get_string(req->req_config, req->section_name, "encrypt_key");
- if (str == NULL) {
- php_openssl_store_errors();
- }
+ /* it is sure that there are some errrors as str was NULL for encrypt_rsa_key */
+ php_openssl_store_errors();
}
if (str != NULL && strcmp(str, "no") == 0) {
req->priv_key_encrypt = 0;
@@ -1063,6 +1068,22 @@ static void php_openssl_dispose_config(struct php_x509_request * req) /* {{{ */
}
/* }}} */
+#ifdef PHP_WIN32
+#define PHP_OPENSSL_RAND_ADD_TIME() ((void) 0)
+#else
+#define PHP_OPENSSL_RAND_ADD_TIME() php_openssl_rand_add_timeval()
+
+static inline void php_openssl_rand_add_timeval() /* {{{ */
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ RAND_add(&tv, sizeof(tv), 0.0);
+}
+/* }}} */
+
+#endif
+
static int php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded) /* {{{ */
{
char buffer[MAXPATHLEN];
@@ -1106,6 +1127,7 @@ static int php_openssl_write_rand_file(const char * file, int egdsocket, int see
if (file == NULL) {
file = RAND_file_name(buffer, sizeof(buffer));
}
+ PHP_OPENSSL_RAND_ADD_TIME();
if (file == NULL || !RAND_write_file(file)) {
php_openssl_store_errors();
php_error_docref(NULL, E_WARNING, "unable to write random state");
@@ -1404,6 +1426,9 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
EVP_cleanup();
#if OPENSSL_VERSION_NUMBER >= 0x00090805f
+ /* prevent accessing locking callback from unloaded extension */
+ CRYPTO_set_locking_callback(NULL);
+ /* free allocated error strings */
ERR_free_strings();
#endif
@@ -2927,6 +2952,11 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(attribs), strindex, item) {
int nid;
+ if (NULL == strindex) {
+ php_error_docref(NULL, E_WARNING, "dn: numeric fild names are not supported");
+ continue;
+ }
+
convert_to_string_ex(item);
nid = OBJ_txt2nid(ZSTR_VAL(strindex));
@@ -3619,6 +3649,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
RSA* rsaparam;
#if OPENSSL_VERSION_NUMBER < 0x10002000L
/* OpenSSL 1.0.2 deprecates RSA_generate_key */
+ PHP_OPENSSL_RAND_ADD_TIME();
rsaparam = (RSA*)RSA_generate_key(req->priv_key_bits, RSA_F4, NULL, NULL);
#else
{
@@ -3629,6 +3660,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
return NULL;
}
rsaparam = RSA_new();
+ PHP_OPENSSL_RAND_ADD_TIME();
if (rsaparam == NULL || !RSA_generate_key_ex(rsaparam, req->priv_key_bits, bne, NULL)) {
php_openssl_store_errors();
}
@@ -3644,6 +3676,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
break;
#if !defined(NO_DSA)
case OPENSSL_KEYTYPE_DSA:
+ PHP_OPENSSL_RAND_ADD_TIME();
{
DSA *dsaparam = NULL;
#if OPENSSL_VERSION_NUMBER < 0x10002000L
@@ -3671,6 +3704,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
#endif
#if !defined(NO_DH)
case OPENSSL_KEYTYPE_DH:
+ PHP_OPENSSL_RAND_ADD_TIME();
{
int codes = 0;
DH *dhparam = NULL;
@@ -3791,6 +3825,48 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey)
} \
} while (0);
+/* {{{ php_openssl_pkey_init_dsa */
+zend_bool php_openssl_pkey_init_dsa(DSA *dsa)
+{
+ if (!dsa->p || !dsa->q || !dsa->g) {
+ return 0;
+ }
+ if (dsa->priv_key || dsa->pub_key) {
+ return 1;
+ }
+ PHP_OPENSSL_RAND_ADD_TIME();
+ if (!DSA_generate_key(dsa)) {
+ php_openssl_store_errors();
+ return 0;
+ }
+ /* if BN_mod_exp return -1, then DSA_generate_key succeed for failed key
+ * so we need to double check that public key is created */
+ if (!dsa->pub_key || BN_is_zero(dsa->pub_key)) {
+ return 0;
+ }
+ /* all good */
+ return 1;
+}
+/* }}} */
+
+/* {{{ php_openssl_pkey_init_dh */
+zend_bool php_openssl_pkey_init_dh(DH *dh)
+{
+ if (!dh->p || !dh->g) {
+ return 0;
+ }
+ if (dh->pub_key) {
+ return 1;
+ }
+ PHP_OPENSSL_RAND_ADD_TIME();
+ if (!DH_generate_key(dh)) {
+ php_openssl_store_errors();
+ return 0;
+ }
+ /* all good */
+ return 1;
+}
+/* }}} */
/* {{{ proto resource openssl_pkey_new([array configargs])
Generates a new private key */
@@ -3849,10 +3925,7 @@ PHP_FUNCTION(openssl_pkey_new)
OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, g);
OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, priv_key);
OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, pub_key);
- if (dsa->p && dsa->q && dsa->g) {
- if (!dsa->priv_key && !dsa->pub_key && !DSA_generate_key(dsa)) {
- php_openssl_store_errors();
- }
+ if (php_openssl_pkey_init_dsa(dsa)) {
if (EVP_PKEY_assign_DSA(pkey, dsa)) {
RETURN_RES(zend_register_resource(pkey, le_key));
} else {
@@ -3877,14 +3950,14 @@ PHP_FUNCTION(openssl_pkey_new)
OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, p);
OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, g);
OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, priv_key);
- OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, pub_key);
- if (dh->p && dh->g &&
- (dh->pub_key || DH_generate_key(dh)) &&
- EVP_PKEY_assign_DH(pkey, dh)) {
- ZVAL_COPY_VALUE(return_value, zend_list_insert(pkey, le_key));
- return;
- } else {
- php_openssl_store_errors();
+ OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, pub_key);php_openssl_store_errors();
+ if (php_openssl_pkey_init_dh(dh)) {
+ if (EVP_PKEY_assign_DH(pkey, dh)) {
+ ZVAL_COPY_VALUE(return_value, zend_list_insert(pkey, le_key));
+ return;
+ } else {
+ php_openssl_store_errors();
+ }
}
DH_free(dh);
} else {
@@ -5990,7 +6063,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
#else
PHP_OPENSSL_CHECK_LONG_TO_INT(buffer_length, length);
-
+ PHP_OPENSSL_RAND_ADD_TIME();
if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), (int)buffer_length) <= 0) {
zend_string_release(buffer);
if (zstrong_result_returned) {