Skip to content

Commit a6558b2

Browse files
committed
ext/openssl: avoid redundant input/output copies.
Switch the PKCS12/PKCS7/CMS readers to BIO_new_mem_buf so the parsers work on the PHP string directly. Also adds a missing NULL check in pkcs12_read. openssl_seal/openssl_open write straight into a zend_string instead of an emalloc buffer that gets copied via zend_string_init.
1 parent e27667b commit a6558b2

1 file changed

Lines changed: 23 additions & 27 deletions

File tree

ext/openssl/openssl.c

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,9 +1807,9 @@ PHP_FUNCTION(openssl_pkcs12_read)
18071807

18081808
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(zp12_len, pkcs12, 1);
18091809

1810-
bio_in = BIO_new(BIO_s_mem());
1810+
bio_in = BIO_new_mem_buf(zp12, (int)zp12_len);
18111811

1812-
if (0 >= BIO_write(bio_in, zp12, (int)zp12_len)) {
1812+
if (bio_in == NULL) {
18131813
php_openssl_store_errors();
18141814
goto cleanup;
18151815
}
@@ -3103,12 +3103,8 @@ PHP_FUNCTION(openssl_pkcs7_read)
31033103

31043104
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(p7b_len, p7b, 1);
31053105

3106-
bio_in = BIO_new(BIO_s_mem());
3106+
bio_in = BIO_new_mem_buf(p7b, (int)p7b_len);
31073107
if (bio_in == NULL) {
3108-
goto clean_exit;
3109-
}
3110-
3111-
if (0 >= BIO_write(bio_in, p7b, (int)p7b_len)) {
31123108
php_openssl_store_errors();
31133109
goto clean_exit;
31143110
}
@@ -3785,12 +3781,8 @@ PHP_FUNCTION(openssl_cms_read)
37853781

37863782
PHP_OPENSSL_CHECK_SIZE_T_TO_INT(p7b_len, p7b, 1);
37873783

3788-
bio_in = BIO_new(BIO_s_mem());
3784+
bio_in = BIO_new_mem_buf(p7b, (int)p7b_len);
37893785
if (bio_in == NULL) {
3790-
goto clean_exit;
3791-
}
3792-
3793-
if (0 >= BIO_write(bio_in, p7b, (int)p7b_len)) {
37943786
php_openssl_store_errors();
37953787
goto clean_exit;
37963788
}
@@ -4575,8 +4567,9 @@ PHP_FUNCTION(openssl_seal)
45754567
zval *pubkeys, *pubkey, *sealdata, *ekeys, *iv = NULL;
45764568
HashTable *pubkeysht;
45774569
EVP_PKEY **pkeys;
4570+
zend_string *buf;
45784571
int i, len1, len2, *eksl, nkeys, iv_len;
4579-
unsigned char iv_buf[EVP_MAX_IV_LENGTH + 1], *buf = NULL, **eks;
4572+
unsigned char iv_buf[EVP_MAX_IV_LENGTH + 1], **eks;
45804573
char * data;
45814574
size_t data_len;
45824575
char *method;
@@ -4640,22 +4633,23 @@ PHP_FUNCTION(openssl_seal)
46404633
}
46414634

46424635
/* allocate one byte extra to make room for \0 */
4643-
buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(ctx));
4636+
buf = zend_string_alloc(data_len + EVP_CIPHER_CTX_block_size(ctx), false);
46444637
EVP_CIPHER_CTX_reset(ctx);
46454638

46464639
if (EVP_SealInit(ctx, cipher, eks, eksl, &iv_buf[0], pkeys, nkeys) <= 0 ||
4647-
!EVP_SealUpdate(ctx, buf, &len1, (unsigned char *)data, (int)data_len) ||
4648-
!EVP_SealFinal(ctx, buf + len1, &len2)) {
4649-
efree(buf);
4640+
!EVP_SealUpdate(ctx, (unsigned char *)ZSTR_VAL(buf), &len1, (unsigned char *)data, (int)data_len) ||
4641+
!EVP_SealFinal(ctx, (unsigned char *)ZSTR_VAL(buf) + len1, &len2)) {
4642+
zend_string_release(buf);
46504643
EVP_CIPHER_CTX_free(ctx);
46514644
php_openssl_store_errors();
46524645
RETVAL_FALSE;
46534646
goto clean_exit;
46544647
}
46554648

46564649
if (len1 + len2 > 0) {
4657-
ZEND_TRY_ASSIGN_REF_NEW_STR(sealdata, zend_string_init((char*)buf, len1 + len2, 0));
4658-
efree(buf);
4650+
ZSTR_VAL(buf)[len1 + len2] = 0;
4651+
ZSTR_LEN(buf) = len1 + len2;
4652+
ZEND_TRY_ASSIGN_REF_NEW_STR(sealdata, buf);
46594653

46604654
ekeys = zend_try_array_init(ekeys);
46614655
if (!ekeys) {
@@ -4675,7 +4669,7 @@ PHP_FUNCTION(openssl_seal)
46754669
ZEND_TRY_ASSIGN_REF_NEW_STR(iv, zend_string_init((char*)iv_buf, iv_len, 0));
46764670
}
46774671
} else {
4678-
efree(buf);
4672+
zend_string_release(buf);
46794673
}
46804674
RETVAL_LONG(len1 + len2);
46814675
EVP_CIPHER_CTX_free(ctx);
@@ -4699,9 +4693,10 @@ PHP_FUNCTION(openssl_seal)
46994693
PHP_FUNCTION(openssl_open)
47004694
{
47014695
zval *privkey, *opendata;
4696+
zend_string *buf;
47024697
EVP_PKEY *pkey;
47034698
int len1, len2, cipher_iv_len;
4704-
unsigned char *buf, *iv_buf;
4699+
unsigned char *iv_buf;
47054700
EVP_CIPHER_CTX *ctx;
47064701
char * data;
47074702
size_t data_len;
@@ -4750,21 +4745,22 @@ PHP_FUNCTION(openssl_open)
47504745
iv_buf = NULL;
47514746
}
47524747

4753-
buf = emalloc(data_len + 1);
4748+
buf = zend_string_alloc(data_len, false);
47544749

47554750
ctx = EVP_CIPHER_CTX_new();
47564751
if (ctx != NULL && EVP_OpenInit(ctx, cipher, (unsigned char *)ekey, (int)ekey_len, iv_buf, pkey) &&
4757-
EVP_OpenUpdate(ctx, buf, &len1, (unsigned char *)data, (int)data_len) &&
4758-
EVP_OpenFinal(ctx, buf + len1, &len2) && (len1 + len2 > 0)) {
4759-
buf[len1 + len2] = '\0';
4760-
ZEND_TRY_ASSIGN_REF_NEW_STR(opendata, zend_string_init((char*)buf, len1 + len2, 0));
4752+
EVP_OpenUpdate(ctx, (unsigned char *)ZSTR_VAL(buf), &len1, (unsigned char *)data, (int)data_len) &&
4753+
EVP_OpenFinal(ctx, (unsigned char *)ZSTR_VAL(buf) + len1, &len2) && (len1 + len2 > 0)) {
4754+
ZSTR_VAL(buf)[len1 + len2] = '\0';
4755+
ZSTR_LEN(buf) = len1 + len2;
4756+
ZEND_TRY_ASSIGN_REF_NEW_STR(opendata, buf);
47614757
RETVAL_TRUE;
47624758
} else {
47634759
php_openssl_store_errors();
4760+
zend_string_release(buf);
47644761
RETVAL_FALSE;
47654762
}
47664763

4767-
efree(buf);
47684764
EVP_CIPHER_CTX_free(ctx);
47694765
out_pkey:
47704766
EVP_PKEY_free(pkey);

0 commit comments

Comments
 (0)