diff options
author | Jakub Zelenka <bukka@php.net> | 2016-06-12 18:39:32 +0100 |
---|---|---|
committer | Jakub Zelenka <bukka@php.net> | 2016-06-12 18:39:32 +0100 |
commit | a2f4c32eb14221de79009aadaa3da9c3349e3526 (patch) | |
tree | d48f38421c636dd2c6d0ba346a92e68f239fdaa7 | |
parent | 5d57e255790fe32ac3a7e01ce51184fc217eb061 (diff) | |
parent | 0e2447cd11f4b72257e5d2609f923177e9736c3c (diff) | |
download | php-git-a2f4c32eb14221de79009aadaa3da9c3349e3526.tar.gz |
Merge branch 'PHP-5.6' into PHP-7.0
-rw-r--r-- | ext/openssl/openssl.c | 78 | ||||
-rw-r--r-- | ext/openssl/tests/bug72336.phpt | 24 | ||||
-rw-r--r-- | ext/openssl/tests/openssl_error_string_basic.phpt | 163 |
3 files changed, 166 insertions, 99 deletions
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 2e8aa9a60d..e2f9fafacf 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1006,6 +1006,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]; @@ -1048,6 +1064,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_error_docref(NULL, E_WARNING, "unable to write random state"); return FAILURE; @@ -3414,6 +3431,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 { @@ -3424,6 +3442,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req return NULL; } rsaparam = RSA_new(); + PHP_OPENSSL_RAND_ADD_TIME(); RSA_generate_key_ex(rsaparam, req->priv_key_bits, bne, NULL); BN_free(bne); } @@ -3435,6 +3454,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 @@ -3457,6 +3477,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; @@ -3570,6 +3591,46 @@ 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)) { + 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)) { + return 0; + } + /* all good */ + return 1; +} +/* }}} */ /* {{{ proto resource openssl_pkey_new([array configargs]) Generates a new private key */ @@ -3622,10 +3683,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); - } + if (php_openssl_pkey_init_dsa(dsa)) { if (EVP_PKEY_assign_DSA(pkey, dsa)) { RETURN_RES(zend_register_resource(pkey, le_key)); } @@ -3645,11 +3703,11 @@ PHP_FUNCTION(openssl_pkey_new) 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; + 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; + } } DH_free(dh); } @@ -5511,7 +5569,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) { diff --git a/ext/openssl/tests/bug72336.phpt b/ext/openssl/tests/bug72336.phpt new file mode 100644 index 0000000000..893b51838d --- /dev/null +++ b/ext/openssl/tests/bug72336.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #72336 (openssl_pkey_new does not fail for invalid DSA params) +--SKIPIF-- +<?php if (!extension_loaded("openssl")) print "skip"; ?> +--FILE-- +<?php +$p = '00f8000ae45b2dacb47dd977d58b719d097bdf07cb2c17660ad898518c08' . + '1a61659a16daadfaa406a0a994c743df5eda07e36bd0adcad921b77432ff' . + '24ccc31e782d647e66768122b578857e9293df78387dc8b44af2a4a3f305' . + '1f236b1000a3e31da489c6681b0031f7ec37c2e1091bdb698e7660f135b6' . + '996def90090303b7ad'; + +$q = '009b3734fc9f7a4a9d6437ec314e0a78c2889af64b'; + +$g = '00b320300a0bc55b8f0ec6edc218e2185250f38fbb8291db8a89227f6e41' . + '00d47d6ccb9c7d42fc43280ecc2ed386e81ff65bc5d6a2ae78db7372f5dc' . + 'f780f4558e7ed3dd0c96a1b40727ac56c5165aed700a3b63997893a1fb21' . + '4e882221f0dd9604820dc34e2725dd6901c93e0ca56f6d76d495c332edc5' . + 'b81747c4c447a941f3'; + +var_dump(openssl_pkey_new(array('dsa' => array('p' => $p, 'q' => $q, 'g' => $g)))); +?> +--EXPECT-- +bool(false) diff --git a/ext/openssl/tests/openssl_error_string_basic.phpt b/ext/openssl/tests/openssl_error_string_basic.phpt index 7f39f70621..76bc2d570a 100644 --- a/ext/openssl/tests/openssl_error_string_basic.phpt +++ b/ext/openssl/tests/openssl_error_string_basic.phpt @@ -1,16 +1,37 @@ --TEST-- openssl_error_string() tests --SKIPIF-- -<?php -if (!extension_loaded("openssl")) print "skip"; -//if (OPENSSL_VERSION_NUMBER < 0x10001001) die("skip OpenSSLv1.0.1 required"); -?> ---XFAIL-- -ot ready baked yet, fails different ways on different envs +<?php if (!extension_loaded("openssl")) print "skip"; ?> --FILE-- <?php -// helper function to dump openssl errors -function dump_openssl_errors() { +// helper function to check openssl errors +function expect_openssl_errors($name, $expected_error_codes) { + $expected_errors = array_fill_keys($expected_error_codes, false); + while (($error_string = openssl_error_string()) !== false) { + if (strlen($error_string) > 14) { + $error_code = substr($error_string, 6, 8); + if (isset($expected_errors[$error_code])) { + $expected_errors[$error_code] = true; + } + } + } + + $fail = false; + foreach ($expected_errors as $error_code => $error_code_found) { + if (!$error_code_found) { + $fail = true; + echo "$name: no error code $error_code\n"; + } + } + + if (!$fail) { + echo "$name: ok\n"; + } +} + +// helper for debugging errors +function dump_openssl_errors($name) { + echo "\n$name\n"; while (($error_string = openssl_error_string()) !== false) { var_dump($error_string); } @@ -56,61 +77,59 @@ while (($enc_error_new = openssl_error_string()) !== false) { ++$error_queue_size; } var_dump($error_queue_size); +echo "\n"; // PKEY echo "PKEY errors\n"; // file for pkey (file:///) fails when opennig (BIO_new_file) -openssl_pkey_export_to_file("file://" . $invalid_file_for_read, $output_file); -dump_openssl_errors(); +@openssl_pkey_export_to_file("file://" . $invalid_file_for_read, $output_file); +expect_openssl_errors('openssl_pkey_export_to_file opening', ['02001002', '2006D080']); // file or private pkey is not correct PEM - failing PEM_read_bio_PrivateKey -openssl_pkey_export_to_file($csr_file, $output_file); -dump_openssl_errors(); +@openssl_pkey_export_to_file($csr_file, $output_file); +expect_openssl_errors('openssl_pkey_export_to_file pem', ['0906D06C']); // file to export cannot be written -openssl_pkey_export_to_file($private_key_file, $invalid_file_for_write); -dump_openssl_errors(); +@openssl_pkey_export_to_file($private_key_file, $invalid_file_for_write); +expect_openssl_errors('openssl_pkey_export_to_file write', ['2006D002', '09072007']); // succesful export -openssl_pkey_export($private_key_file_with_pass, $out, 'wrong pwd'); -dump_openssl_errors(); +@openssl_pkey_export($private_key_file_with_pass, $out, 'wrong pwd'); +expect_openssl_errors('openssl_pkey_export', ['06065064', '0906A065']); // invalid x509 for getting public key -openssl_pkey_get_public($private_key_file); -dump_openssl_errors(); +@openssl_pkey_get_public($private_key_file); +expect_openssl_errors('openssl_pkey_get_public', ['0906D06C']); // private encrypt with unknown padding -openssl_private_encrypt("data", $crypted, $private_key_file, 1000); -dump_openssl_errors(); +@openssl_private_encrypt("data", $crypted, $private_key_file, 1000); +expect_openssl_errors('openssl_private_encrypt', ['04066076']); // private decrypt with failed padding check -openssl_private_decrypt("data", $crypted, $private_key_file); -dump_openssl_errors(); +@openssl_private_decrypt("data", $crypted, $private_key_file); +expect_openssl_errors('openssl_private_decrypt', ['04065072']); // public encrypt and decrypt with failed padding check and padding -openssl_public_encrypt("data", $crypted, $public_key_file, 1000); -openssl_public_decrypt("data", $crypted, $public_key_file); -dump_openssl_errors(); +@openssl_public_encrypt("data", $crypted, $public_key_file, 1000); +@openssl_public_decrypt("data", $crypted, $public_key_file); +expect_openssl_errors('openssl_private_(en|de)crypt padding', ['0906D06C', '04068076', '0407006A', '04067072']); // X509 echo "X509 errors\n"; // file for x509 (file:///) fails when opennig (BIO_new_file) -openssl_x509_export_to_file("file://" . $invalid_file_for_read, $output_file); -dump_openssl_errors(); +@openssl_x509_export_to_file("file://" . $invalid_file_for_read, $output_file); +expect_openssl_errors('openssl_x509_export_to_file open', ['02001002']); // file or str cert is not correct PEM - failing PEM_read_bio_X509 or PEM_ASN1_read_bio -openssl_x509_export_to_file($csr_file, $output_file); -dump_openssl_errors(); +@openssl_x509_export_to_file($csr_file, $output_file); +expect_openssl_errors('openssl_x509_export_to_file pem', ['0906D06C']); // file to export cannot be written -openssl_x509_export_to_file($crt_file, $invalid_file_for_write); -dump_openssl_errors(); +@openssl_x509_export_to_file($crt_file, $invalid_file_for_write); +expect_openssl_errors('openssl_x509_export_to_file write', ['2006D002']); // checking purpose fails because there is no such purpose 1000 -openssl_x509_checkpurpose($crt_file, 1000); -dump_openssl_errors(); -// make sure that X509_STORE_add_lookup will not emmit any error (just PHP warning) -openssl_x509_checkpurpose($crt_file, X509_PURPOSE_SSL_CLIENT, array( __DIR__ . "/cert.csr")); -dump_openssl_errors(); +@openssl_x509_checkpurpose($crt_file, 1000); +expect_openssl_errors('openssl_x509_checkpurpose purpose', ['0B086079']); // CSR echo "CSR errors\n"; // file for csr (file:///) fails when opennig (BIO_new_file) -openssl_csr_get_subject("file://" . $invalid_file_for_read); -dump_openssl_errors(); +@openssl_csr_get_subject("file://" . $invalid_file_for_read); +expect_openssl_errors('openssl_csr_get_subject open', ['02001002', '2006D080', '20068079', '0906D06C']); // file or str csr is not correct PEM - failing PEM_read_bio_X509_REQ openssl_csr_get_subject($crt_file); -dump_openssl_errors(); +@expect_openssl_errors('openssl_csr_get_subjec pem', ['0906D06C']); // other possible cuases that are difficult to catch: // - ASN1_STRING_to_UTF8 fails in add_assoc_name_entry @@ -124,59 +143,25 @@ if (is_file($output_file)) { unlink($output_file); } ?> ---EXPECTF-- +--EXPECT-- string(89) "error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length" bool(false) int(15) -PKEY errors - -Warning: openssl_pkey_export_to_file(): cannot get key from parameter 1 in %s on line %d -string(61) "error:02001002:system library:fopen:No such file or directory" -string(53) "error:2006D080:BIO routines:BIO_new_file:no such file" -Warning: openssl_pkey_export_to_file(): cannot get key from parameter 1 in %s on line %d -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" -string(68) "error:0E06D06C:configuration file routines:NCONF_get_string:no value" -string(68) "error:0E06D06C:configuration file routines:NCONF_get_string:no value" -string(68) "error:0E06D06C:configuration file routines:NCONF_get_string:no value" -string(68) "error:0E06D06C:configuration file routines:NCONF_get_string:no value" -string(68) "error:0E06D06C:configuration file routines:NCONF_get_string:no value" -string(68) "error:0E06D06C:configuration file routines:NCONF_get_string:no value" -string(50) "error:02001015:system library:fopen:Is a directory" -string(51) "error:2006D002:BIO routines:BIO_new_file:system lib" -string(49) "error:09072007:PEM routines:PEM_write_bio:BUF lib" - -Warning: openssl_pkey_export(): cannot get key from parameter 1 in %s on line %d -string(72) "error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt" -string(53) "error:0906A065:PEM routines:PEM_do_header:bad decrypt" -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" -string(72) "error:04066076:rsa routines:RSA_EAY_PRIVATE_ENCRYPT:unknown padding type" -string(78) "error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error" -string(72) "error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed" -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" -string(71) "error:04068076:rsa routines:RSA_EAY_PUBLIC_ENCRYPT:unknown padding type" -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" -string(79) "error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01" -string(71) "error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed" +PKEY errors +openssl_pkey_export_to_file opening: ok +openssl_pkey_export_to_file pem: ok +openssl_pkey_export_to_file write: ok +openssl_pkey_export: ok +openssl_pkey_get_public: ok +openssl_private_encrypt: ok +openssl_private_decrypt: ok +openssl_private_(en|de)crypt padding: ok X509 errors - -Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d -string(61) "error:02001002:system library:fopen:No such file or directory" -string(53) "error:2006D080:BIO routines:BIO_new_file:no such file" - -Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" - -Warning: openssl_x509_export_to_file(): error opening file %s in %s on line %d -string(50) "error:02001015:system library:fopen:Is a directory" -string(51) "error:2006D002:BIO routines:BIO_new_file:system lib" -string(90) "error:0B086079:x509 certificate routines:X509_STORE_CTX_purpose_inherit:unknown purpose id" - -Warning: openssl_x509_checkpurpose(): error loading file %s in %s on line %d +openssl_x509_export_to_file open: ok +openssl_x509_export_to_file pem: ok +openssl_x509_export_to_file write: ok +openssl_x509_checkpurpose purpose: ok CSR errors -string(61) "error:02001002:system library:fopen:No such file or directory" -string(53) "error:2006D080:BIO routines:BIO_new_file:no such file" -string(55) "error:20068079:BIO routines:BIO_gets:unsupported method" -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" -string(54) "error:0906D06C:PEM routines:PEM_read_bio:no start line" +openssl_csr_get_subject open: ok +openssl_csr_get_subjec pem: ok |