mirror of
https://github.com/php/php-src.git
synced 2024-11-27 20:03:40 +08:00
Fix bug #73833 (null character not allowed in openssl_pkey_get_private)
This commit is contained in:
parent
f7b8322b14
commit
9fa347997a
2
NEWS
2
NEWS
@ -38,6 +38,8 @@ PHP NEWS
|
||||
loss). (Yussuf Khalil)
|
||||
|
||||
- OpenSSL:
|
||||
. Fixed bug #73833 (null character not allowed in openssl_pkey_get_private).
|
||||
(Jakub Zelenka)
|
||||
. Fixed bug #73711 (Segfault in openssl_pkey_new when generating DSA or DH
|
||||
key). (Jakub Zelenka)
|
||||
. Fixed bug #74341 (openssl_x509_parse fails to parse ASN.1 UTCTime without
|
||||
|
@ -784,7 +784,9 @@ struct php_x509_request { /* {{{ */
|
||||
/* }}} */
|
||||
|
||||
static X509 * php_openssl_x509_from_zval(zval * val, int makeresource, zend_resource **resourceval);
|
||||
static EVP_PKEY * php_openssl_evp_from_zval(zval * val, int public_key, char * passphrase, int makeresource, zend_resource **resourceval);
|
||||
static EVP_PKEY * php_openssl_evp_from_zval(
|
||||
zval * val, int public_key, char *passphrase, size_t passphrase_len,
|
||||
int makeresource, zend_resource **resourceval);
|
||||
static int php_openssl_is_private_key(EVP_PKEY* pkey);
|
||||
static X509_STORE * setup_verify(zval * calist);
|
||||
static STACK_OF(X509) * load_all_certs_from_file(char *certfile);
|
||||
@ -1696,7 +1698,8 @@ PHP_FUNCTION(openssl_spki_new)
|
||||
}
|
||||
RETVAL_FALSE;
|
||||
|
||||
pkey = php_openssl_evp_from_zval(zpkey, 0, challenge, 1, &keyresource);
|
||||
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(challenge_len, challenge);
|
||||
pkey = php_openssl_evp_from_zval(zpkey, 0, challenge, challenge_len, 1, &keyresource);
|
||||
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to use supplied private key");
|
||||
@ -2069,7 +2072,7 @@ PHP_FUNCTION(openssl_x509_check_private_key)
|
||||
if (cert == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
key = php_openssl_evp_from_zval(zkey, 0, "", 1, &keyresource);
|
||||
key = php_openssl_evp_from_zval(zkey, 0, "", 0, 1, &keyresource);
|
||||
if (key) {
|
||||
RETVAL_BOOL(X509_check_private_key(cert, key));
|
||||
}
|
||||
@ -2635,7 +2638,7 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
|
||||
php_error_docref(NULL, E_WARNING, "cannot get cert from parameter 1");
|
||||
return;
|
||||
}
|
||||
priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 1, &keyresource);
|
||||
priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 0, 1, &keyresource);
|
||||
if (priv_key == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "cannot get private key from parameter 3");
|
||||
goto cleanup;
|
||||
@ -2716,7 +2719,7 @@ PHP_FUNCTION(openssl_pkcs12_export)
|
||||
php_error_docref(NULL, E_WARNING, "cannot get cert from parameter 1");
|
||||
return;
|
||||
}
|
||||
priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 1, &keyresource);
|
||||
priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 0, 1, &keyresource);
|
||||
if (priv_key == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "cannot get private key from parameter 3");
|
||||
goto cleanup;
|
||||
@ -3191,7 +3194,7 @@ PHP_FUNCTION(openssl_csr_sign)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 1, &keyresource);
|
||||
priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 0, 1, &keyresource);
|
||||
if (priv_key == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "cannot get private key from parameter 3");
|
||||
goto cleanup;
|
||||
@ -3315,7 +3318,7 @@ PHP_FUNCTION(openssl_csr_new)
|
||||
if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
|
||||
/* Generate or use a private key */
|
||||
if (Z_TYPE_P(out_pkey) != IS_NULL) {
|
||||
req.priv_key = php_openssl_evp_from_zval(out_pkey, 0, NULL, 0, &key_resource);
|
||||
req.priv_key = php_openssl_evp_from_zval(out_pkey, 0, NULL, 0, 0, &key_resource);
|
||||
if (req.priv_key != NULL) {
|
||||
we_made_the_key = 0;
|
||||
}
|
||||
@ -3452,6 +3455,27 @@ PHP_FUNCTION(openssl_csr_get_public_key)
|
||||
|
||||
/* {{{ EVP Public/Private key functions */
|
||||
|
||||
struct php_openssl_pem_password {
|
||||
char *key;
|
||||
int len;
|
||||
};
|
||||
|
||||
/* {{{ php_openssl_pem_password_cb */
|
||||
static int php_openssl_pem_password_cb(char *buf, int size, int rwflag, void *userdata)
|
||||
{
|
||||
struct php_openssl_pem_password *password = userdata;
|
||||
|
||||
if (password == NULL || password->key == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = (password->len > size) ? size : password->len;
|
||||
memcpy(buf, password->key, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_openssl_evp_from_zval
|
||||
Given a zval, coerce it into a EVP_PKEY object.
|
||||
It can be:
|
||||
@ -3465,7 +3489,9 @@ PHP_FUNCTION(openssl_csr_get_public_key)
|
||||
empty string rather than NULL for the passphrase - NULL causes a passphrase prompt to be emitted in
|
||||
the Apache error log!
|
||||
*/
|
||||
static EVP_PKEY * php_openssl_evp_from_zval(zval * val, int public_key, char * passphrase, int makeresource, zend_resource **resourceval)
|
||||
static EVP_PKEY * php_openssl_evp_from_zval(
|
||||
zval * val, int public_key, char *passphrase, size_t passphrase_len,
|
||||
int makeresource, zend_resource **resourceval)
|
||||
{
|
||||
EVP_PKEY * key = NULL;
|
||||
X509 * cert = NULL;
|
||||
@ -3497,10 +3523,12 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval * val, int public_key, char * p
|
||||
|
||||
if (Z_TYPE_P(zphrase) == IS_STRING) {
|
||||
passphrase = Z_STRVAL_P(zphrase);
|
||||
passphrase_len = Z_STRLEN_P(zphrase);
|
||||
} else {
|
||||
ZVAL_COPY(&tmp, zphrase);
|
||||
convert_to_string(&tmp);
|
||||
passphrase = Z_STRVAL(tmp);
|
||||
passphrase_len = Z_STRLEN(tmp);
|
||||
}
|
||||
|
||||
/* now set val to be the key param and continue */
|
||||
@ -3599,7 +3627,14 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval * val, int public_key, char * p
|
||||
if (in == NULL) {
|
||||
TMP_CLEAN;
|
||||
}
|
||||
key = PEM_read_bio_PrivateKey(in, NULL,NULL, passphrase);
|
||||
if (passphrase == NULL) {
|
||||
key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
|
||||
} else {
|
||||
struct php_openssl_pem_password password;
|
||||
password.key = passphrase;
|
||||
password.len = passphrase_len;
|
||||
key = PEM_read_bio_PrivateKey(in, NULL, php_openssl_pem_password_cb, &password);
|
||||
}
|
||||
BIO_free(in);
|
||||
}
|
||||
}
|
||||
@ -4072,8 +4107,7 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
|
||||
RETVAL_FALSE;
|
||||
|
||||
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(passphrase_len, passphrase);
|
||||
|
||||
key = php_openssl_evp_from_zval(zpkey, 0, passphrase, 0, &key_resource);
|
||||
key = php_openssl_evp_from_zval(zpkey, 0, passphrase, passphrase_len, 0, &key_resource);
|
||||
|
||||
if (key == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "cannot get key from parameter 1");
|
||||
@ -4146,8 +4180,7 @@ PHP_FUNCTION(openssl_pkey_export)
|
||||
RETVAL_FALSE;
|
||||
|
||||
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(passphrase_len, passphrase);
|
||||
|
||||
key = php_openssl_evp_from_zval(zpkey, 0, passphrase, 0, &key_resource);
|
||||
key = php_openssl_evp_from_zval(zpkey, 0, passphrase, passphrase_len, 0, &key_resource);
|
||||
|
||||
if (key == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "cannot get key from parameter 1");
|
||||
@ -4215,7 +4248,7 @@ PHP_FUNCTION(openssl_pkey_get_public)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &cert) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
pkey = php_openssl_evp_from_zval(cert, 1, NULL, 1, &res);
|
||||
pkey = php_openssl_evp_from_zval(cert, 1, NULL, 0, 1, &res);
|
||||
if (pkey == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@ -4254,7 +4287,9 @@ PHP_FUNCTION(openssl_pkey_get_private)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|s", &cert, &passphrase, &passphrase_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
pkey = php_openssl_evp_from_zval(cert, 0, passphrase, 1, &res);
|
||||
|
||||
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(passphrase_len, passphrase);
|
||||
pkey = php_openssl_evp_from_zval(cert, 0, passphrase, passphrase_len, 1, &res);
|
||||
|
||||
if (pkey == NULL) {
|
||||
RETURN_FALSE;
|
||||
@ -4756,7 +4791,7 @@ PHP_FUNCTION(openssl_pkcs7_sign)
|
||||
}
|
||||
}
|
||||
|
||||
privkey = php_openssl_evp_from_zval(zprivkey, 0, "", 0, &keyresource);
|
||||
privkey = php_openssl_evp_from_zval(zprivkey, 0, "", 0, 0, &keyresource);
|
||||
if (privkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "error getting private key");
|
||||
goto clean_exit;
|
||||
@ -4854,7 +4889,7 @@ PHP_FUNCTION(openssl_pkcs7_decrypt)
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
key = php_openssl_evp_from_zval(recipkey ? recipkey : recipcert, 0, "", 0, &keyresval);
|
||||
key = php_openssl_evp_from_zval(recipkey ? recipkey : recipcert, 0, "", 0, 0, &keyresval);
|
||||
if (key == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "unable to get private key");
|
||||
goto clean_exit;
|
||||
@ -4916,7 +4951,7 @@ PHP_FUNCTION(openssl_private_encrypt)
|
||||
}
|
||||
RETVAL_FALSE;
|
||||
|
||||
pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource);
|
||||
pkey = php_openssl_evp_from_zval(key, 0, "", 0, 0, &keyresource);
|
||||
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "key param is not a valid private key");
|
||||
@ -4977,7 +5012,7 @@ PHP_FUNCTION(openssl_private_decrypt)
|
||||
}
|
||||
RETVAL_FALSE;
|
||||
|
||||
pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource);
|
||||
pkey = php_openssl_evp_from_zval(key, 0, "", 0, 0, &keyresource);
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "key parameter is not a valid private key");
|
||||
RETURN_FALSE;
|
||||
@ -5043,7 +5078,7 @@ PHP_FUNCTION(openssl_public_encrypt)
|
||||
return;
|
||||
RETVAL_FALSE;
|
||||
|
||||
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource);
|
||||
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, 0, &keyresource);
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "key parameter is not a valid public key");
|
||||
RETURN_FALSE;
|
||||
@ -5104,7 +5139,7 @@ PHP_FUNCTION(openssl_public_decrypt)
|
||||
}
|
||||
RETVAL_FALSE;
|
||||
|
||||
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource);
|
||||
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, 0, &keyresource);
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "key parameter is not a valid public key");
|
||||
RETURN_FALSE;
|
||||
@ -5193,7 +5228,7 @@ PHP_FUNCTION(openssl_sign)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z|z", &data, &data_len, &signature, &key, &method) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource);
|
||||
pkey = php_openssl_evp_from_zval(key, 0, "", 0, 0, &keyresource);
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "supplied key param cannot be coerced into a private key");
|
||||
RETURN_FALSE;
|
||||
@ -5278,7 +5313,7 @@ PHP_FUNCTION(openssl_verify)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource);
|
||||
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, 0, &keyresource);
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "supplied key param cannot be coerced into a public key");
|
||||
RETURN_FALSE;
|
||||
@ -5357,7 +5392,7 @@ PHP_FUNCTION(openssl_seal)
|
||||
/* get the public keys we are using to seal this data */
|
||||
i = 0;
|
||||
ZEND_HASH_FOREACH_VAL(pubkeysht, pubkey) {
|
||||
pkeys[i] = php_openssl_evp_from_zval(pubkey, 1, NULL, 0, &key_resources[i]);
|
||||
pkeys[i] = php_openssl_evp_from_zval(pubkey, 1, NULL, 0, 0, &key_resources[i]);
|
||||
if (pkeys[i] == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "not a public key (%dth member of pubkeys)", i+1);
|
||||
RETVAL_FALSE;
|
||||
@ -5451,7 +5486,7 @@ PHP_FUNCTION(openssl_open)
|
||||
return;
|
||||
}
|
||||
|
||||
pkey = php_openssl_evp_from_zval(privkey, 0, "", 0, &keyresource);
|
||||
pkey = php_openssl_evp_from_zval(privkey, 0, "", 0, 0, &keyresource);
|
||||
if (pkey == NULL) {
|
||||
php_error_docref(NULL, E_WARNING, "unable to coerce parameter 4 into a private key");
|
||||
RETURN_FALSE;
|
||||
|
30
ext/openssl/tests/bug73833.phpt
Normal file
30
ext/openssl/tests/bug73833.phpt
Normal file
@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
Bug #73833: null character not allowed in openssl_pkey_get_private
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("openssl")) die("skip openssl not loaded");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$passwords = ["abc\x00defghijkl", "abcdefghikjl"];
|
||||
|
||||
foreach($passwords as $password) {
|
||||
$key = openssl_pkey_new();
|
||||
|
||||
if (openssl_pkey_export($key, $privatePEM, $password) === false) {
|
||||
echo "Failed to encrypt.\n";
|
||||
} else {
|
||||
echo "Encrypted!\n";
|
||||
}
|
||||
if (openssl_pkey_get_private($privatePEM, $password) === false) {
|
||||
echo "Failed to decrypt.\n";
|
||||
} else {
|
||||
echo "Decrypted!\n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Encrypted!
|
||||
Decrypted!
|
||||
Encrypted!
|
||||
Decrypted!
|
Loading…
Reference in New Issue
Block a user