Skip to content

Commit 384ad6e

Browse files
committed
Use EVP_PKEY APIs for openssl_private_encrypt/public_decrypt
Use high level APIs instead of deprecated low level APIs.
1 parent 0233afa commit 384ad6e

File tree

2 files changed

+45
-76
lines changed

2 files changed

+45
-76
lines changed

ext/openssl/openssl.c

Lines changed: 44 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -6137,10 +6137,6 @@ PHP_FUNCTION(openssl_cms_decrypt)
61376137
PHP_FUNCTION(openssl_private_encrypt)
61386138
{
61396139
zval *key, *crypted;
6140-
EVP_PKEY *pkey;
6141-
int cryptedlen;
6142-
zend_string *cryptedbuf = NULL;
6143-
int successful = 0;
61446140
char * data;
61456141
size_t data_len;
61466142
zend_long padding = RSA_PKCS1_PADDING;
@@ -6149,46 +6145,39 @@ PHP_FUNCTION(openssl_private_encrypt)
61496145
RETURN_THROWS();
61506146
}
61516147

6152-
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(data_len, data, 1);
6153-
6154-
RETVAL_FALSE;
6155-
6156-
pkey = php_openssl_pkey_from_zval(key, 0, "", 0);
6157-
6148+
EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 0, "", 0);
61586149
if (pkey == NULL) {
61596150
if (!EG(exception)) {
61606151
php_error_docref(NULL, E_WARNING, "key param is not a valid private key");
61616152
}
61626153
RETURN_FALSE;
61636154
}
61646155

6165-
cryptedlen = EVP_PKEY_size(pkey);
6166-
cryptedbuf = zend_string_alloc(cryptedlen, 0);
6167-
6168-
switch (EVP_PKEY_id(pkey)) {
6169-
case EVP_PKEY_RSA:
6170-
case EVP_PKEY_RSA2:
6171-
successful = (RSA_private_encrypt((int)data_len,
6172-
(unsigned char *)data,
6173-
(unsigned char *)ZSTR_VAL(cryptedbuf),
6174-
EVP_PKEY_get0_RSA(pkey),
6175-
(int)padding) == cryptedlen);
6176-
break;
6177-
default:
6178-
php_error_docref(NULL, E_WARNING, "key type not supported in this PHP build!");
6156+
size_t out_len = 0;
6157+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
6158+
if (!ctx || EVP_PKEY_sign_init(ctx) <= 0 ||
6159+
EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
6160+
EVP_PKEY_sign(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
6161+
php_openssl_store_errors();
6162+
RETVAL_FALSE;
6163+
goto cleanup;
61796164
}
61806165

6181-
if (successful) {
6182-
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
6183-
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, cryptedbuf);
6184-
cryptedbuf = NULL;
6185-
RETVAL_TRUE;
6186-
} else {
6166+
zend_string *out = zend_string_alloc(out_len, 0);
6167+
if (EVP_PKEY_sign(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
6168+
(unsigned char *) data, data_len) <= 0) {
6169+
zend_string_release(out);
61876170
php_openssl_store_errors();
6171+
RETVAL_FALSE;
6172+
goto cleanup;
61886173
}
6189-
if (cryptedbuf) {
6190-
zend_string_release_ex(cryptedbuf, 0);
6191-
}
6174+
6175+
ZSTR_VAL(out)[out_len] = '\0';
6176+
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
6177+
RETVAL_TRUE;
6178+
6179+
cleanup:
6180+
EVP_PKEY_CTX_free(ctx);
61926181
EVP_PKEY_free(pkey);
61936182
}
61946183
/* }}} */
@@ -6296,11 +6285,6 @@ PHP_FUNCTION(openssl_public_encrypt)
62966285
PHP_FUNCTION(openssl_public_decrypt)
62976286
{
62986287
zval *key, *crypted;
6299-
EVP_PKEY *pkey;
6300-
int cryptedlen;
6301-
zend_string *cryptedbuf = NULL;
6302-
unsigned char *crypttemp;
6303-
int successful = 0;
63046288
zend_long padding = RSA_PKCS1_PADDING;
63056289
char * data;
63066290
size_t data_len;
@@ -6309,55 +6293,40 @@ PHP_FUNCTION(openssl_public_decrypt)
63096293
RETURN_THROWS();
63106294
}
63116295

6312-
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(data_len, data, 1);
6313-
6314-
RETVAL_FALSE;
6315-
6316-
pkey = php_openssl_pkey_from_zval(key, 1, NULL, 0);
6296+
EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 1, NULL, 0);
63176297
if (pkey == NULL) {
63186298
if (!EG(exception)) {
63196299
php_error_docref(NULL, E_WARNING, "key parameter is not a valid public key");
63206300
}
63216301
RETURN_FALSE;
63226302
}
63236303

6324-
cryptedlen = EVP_PKEY_size(pkey);
6325-
crypttemp = emalloc(cryptedlen + 1);
6326-
6327-
switch (EVP_PKEY_id(pkey)) {
6328-
case EVP_PKEY_RSA:
6329-
case EVP_PKEY_RSA2:
6330-
cryptedlen = RSA_public_decrypt((int)data_len,
6331-
(unsigned char *)data,
6332-
crypttemp,
6333-
EVP_PKEY_get0_RSA(pkey),
6334-
(int)padding);
6335-
if (cryptedlen != -1) {
6336-
cryptedbuf = zend_string_alloc(cryptedlen, 0);
6337-
memcpy(ZSTR_VAL(cryptedbuf), crypttemp, cryptedlen);
6338-
successful = 1;
6339-
}
6340-
break;
6341-
6342-
default:
6343-
php_error_docref(NULL, E_WARNING, "key type not supported in this PHP build!");
6344-
6304+
size_t out_len = 0;
6305+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
6306+
if (!ctx || EVP_PKEY_verify_recover_init(ctx) <= 0 ||
6307+
EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
6308+
EVP_PKEY_verify_recover(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
6309+
php_openssl_store_errors();
6310+
RETVAL_FALSE;
6311+
goto cleanup;
63456312
}
63466313

6347-
efree(crypttemp);
6348-
6349-
if (successful) {
6350-
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
6351-
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, cryptedbuf);
6352-
cryptedbuf = NULL;
6353-
RETVAL_TRUE;
6354-
} else {
6314+
zend_string *out = zend_string_alloc(out_len, 0);
6315+
if (EVP_PKEY_verify_recover(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
6316+
(unsigned char *) data, data_len) <= 0) {
6317+
zend_string_release(out);
63556318
php_openssl_store_errors();
6319+
RETVAL_FALSE;
6320+
goto cleanup;
63566321
}
63576322

6358-
if (cryptedbuf) {
6359-
zend_string_release_ex(cryptedbuf, 0);
6360-
}
6323+
out = zend_string_truncate(out, out_len, 0);
6324+
ZSTR_VAL(out)[out_len] = '\0';
6325+
ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
6326+
RETVAL_TRUE;
6327+
6328+
cleanup:
6329+
EVP_PKEY_CTX_free(ctx);
63616330
EVP_PKEY_free(pkey);
63626331
}
63636332
/* }}} */

ext/openssl/tests/openssl_error_string_basic.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ expect_openssl_errors('openssl_pkey_export', ['06065064', '0906A065']);
112112
expect_openssl_errors('openssl_pkey_get_public', [$err_pem_no_start_line]);
113113
// private encrypt with unknown padding
114114
@openssl_private_encrypt("data", $crypted, $private_key_file, 1000);
115-
expect_openssl_errors('openssl_private_encrypt', ['04066076']);
115+
expect_openssl_errors('openssl_private_encrypt', ['0408F090']);
116116
// private decrypt with failed padding check
117117
@openssl_private_decrypt("data", $crypted, $private_key_file);
118118
expect_openssl_errors('openssl_private_decrypt', ['04065072']);

0 commit comments

Comments
 (0)