Skip to content

Commit 0233afa

Browse files
committed
Use EVP_PKEY API for openssl_public_encrypt/private_decrypt
Use the high level API instead of the deprecated low level API.
1 parent 503146a commit 0233afa

File tree

2 files changed

+45
-74
lines changed

2 files changed

+45
-74
lines changed

ext/openssl/openssl.c

Lines changed: 44 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6197,11 +6197,6 @@ PHP_FUNCTION(openssl_private_encrypt)
61976197
PHP_FUNCTION(openssl_private_decrypt)
61986198
{
61996199
zval *key, *crypted;
6200-
EVP_PKEY *pkey;
6201-
int cryptedlen;
6202-
zend_string *cryptedbuf = NULL;
6203-
unsigned char *crypttemp;
6204-
int successful = 0;
62056200
zend_long padding = RSA_PKCS1_PADDING;
62066201
char * data;
62076202
size_t data_len;
@@ -6210,65 +6205,48 @@ PHP_FUNCTION(openssl_private_decrypt)
62106205
RETURN_THROWS();
62116206
}
62126207

6213-
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(data_len, data, 1);
6214-
6215-
RETVAL_FALSE;
6216-
6217-
pkey = php_openssl_pkey_from_zval(key, 0, "", 0);
6208+
EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 0, "", 0);
62186209
if (pkey == NULL) {
62196210
if (!EG(exception)) {
62206211
php_error_docref(NULL, E_WARNING, "key parameter is not a valid private key");
62216212
}
62226213
RETURN_FALSE;
62236214
}
62246215

6225-
cryptedlen = EVP_PKEY_size(pkey);
6226-
crypttemp = emalloc(cryptedlen + 1);
6227-
6228-
switch (EVP_PKEY_id(pkey)) {
6229-
case EVP_PKEY_RSA:
6230-
case EVP_PKEY_RSA2:
6231-
cryptedlen = RSA_private_decrypt((int)data_len,
6232-
(unsigned char *)data,
6233-
crypttemp,
6234-
EVP_PKEY_get0_RSA(pkey),
6235-
(int)padding);
6236-
if (cryptedlen != -1) {
6237-
cryptedbuf = zend_string_alloc(cryptedlen, 0);
6238-
memcpy(ZSTR_VAL(cryptedbuf), crypttemp, cryptedlen);
6239-
successful = 1;
6240-
}
6241-
break;
6242-
default:
6243-
php_error_docref(NULL, E_WARNING, "key type not supported in this PHP build!");
6216+
size_t out_len = 0;
6217+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
6218+
if (!ctx || EVP_PKEY_decrypt_init(ctx) <= 0 ||
6219+
EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
6220+
EVP_PKEY_decrypt(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
6221+
php_openssl_store_errors();
6222+
RETVAL_FALSE;
6223+
goto cleanup;
62446224
}
62456225

6246-
efree(crypttemp);
6247-
6248-
if (successful) {
6249-
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
6250-
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, cryptedbuf);
6251-
cryptedbuf = NULL;
6252-
RETVAL_TRUE;
6253-
} else {
6226+
zend_string *out = zend_string_alloc(out_len, 0);
6227+
if (EVP_PKEY_decrypt(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
6228+
(unsigned char *) data, data_len) <= 0) {
6229+
zend_string_release(out);
62546230
php_openssl_store_errors();
6231+
RETVAL_FALSE;
6232+
goto cleanup;
62556233
}
62566234

6235+
out = zend_string_truncate(out, out_len, 0);
6236+
ZSTR_VAL(out)[out_len] = '\0';
6237+
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
6238+
RETVAL_TRUE;
6239+
6240+
cleanup:
6241+
EVP_PKEY_CTX_free(ctx);
62576242
EVP_PKEY_free(pkey);
6258-
if (cryptedbuf) {
6259-
zend_string_release_ex(cryptedbuf, 0);
6260-
}
62616243
}
62626244
/* }}} */
62636245

62646246
/* {{{ Encrypts data with public key */
62656247
PHP_FUNCTION(openssl_public_encrypt)
62666248
{
62676249
zval *key, *crypted;
6268-
EVP_PKEY *pkey;
6269-
int cryptedlen;
6270-
zend_string *cryptedbuf;
6271-
int successful = 0;
62726250
zend_long padding = RSA_PKCS1_PADDING;
62736251
char * data;
62746252
size_t data_len;
@@ -6277,47 +6255,40 @@ PHP_FUNCTION(openssl_public_encrypt)
62776255
RETURN_THROWS();
62786256
}
62796257

6280-
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(data_len, data, 1);
6281-
6282-
RETVAL_FALSE;
6283-
6284-
pkey = php_openssl_pkey_from_zval(key, 1, NULL, 0);
6258+
EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 1, NULL, 0);
62856259
if (pkey == NULL) {
62866260
if (!EG(exception)) {
62876261
php_error_docref(NULL, E_WARNING, "key parameter is not a valid public key");
62886262
}
62896263
RETURN_FALSE;
62906264
}
62916265

6292-
cryptedlen = EVP_PKEY_size(pkey);
6293-
cryptedbuf = zend_string_alloc(cryptedlen, 0);
6294-
6295-
switch (EVP_PKEY_id(pkey)) {
6296-
case EVP_PKEY_RSA:
6297-
case EVP_PKEY_RSA2:
6298-
successful = (RSA_public_encrypt((int)data_len,
6299-
(unsigned char *)data,
6300-
(unsigned char *)ZSTR_VAL(cryptedbuf),
6301-
EVP_PKEY_get0_RSA(pkey),
6302-
(int)padding) == cryptedlen);
6303-
break;
6304-
default:
6305-
php_error_docref(NULL, E_WARNING, "key type not supported in this PHP build!");
6306-
6266+
size_t out_len = 0;
6267+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
6268+
if (!ctx || EVP_PKEY_encrypt_init(ctx) <= 0 ||
6269+
EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
6270+
EVP_PKEY_encrypt(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
6271+
php_openssl_store_errors();
6272+
RETVAL_FALSE;
6273+
goto cleanup;
63076274
}
63086275

6309-
if (successful) {
6310-
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
6311-
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, cryptedbuf);
6312-
cryptedbuf = NULL;
6313-
RETVAL_TRUE;
6314-
} else {
6276+
zend_string *out = zend_string_alloc(out_len, 0);
6277+
if (EVP_PKEY_encrypt(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
6278+
(unsigned char *) data, data_len) <= 0) {
6279+
zend_string_release(out);
63156280
php_openssl_store_errors();
6281+
RETVAL_FALSE;
6282+
goto cleanup;
63166283
}
6284+
6285+
ZSTR_VAL(out)[out_len] = '\0';
6286+
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
6287+
RETVAL_TRUE;
6288+
6289+
cleanup:
6290+
EVP_PKEY_CTX_free(ctx);
63176291
EVP_PKEY_free(pkey);
6318-
if (cryptedbuf) {
6319-
zend_string_release_ex(cryptedbuf, 0);
6320-
}
63216292
}
63226293
/* }}} */
63236294

ext/openssl/tests/openssl_error_string_basic.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ expect_openssl_errors('openssl_private_decrypt', ['04065072']);
119119
// public encrypt and decrypt with failed padding check and padding
120120
@openssl_public_encrypt("data", $crypted, $public_key_file, 1000);
121121
@openssl_public_decrypt("data", $crypted, $public_key_file);
122-
expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '04068076', '04067072']);
122+
expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '0408F090', '04067072']);
123123

124124
// X509
125125
echo "X509 errors\n";

0 commit comments

Comments
 (0)