diff options
author | Jakub Zelenka <bukka@php.net> | 2015-09-06 19:09:56 +0100 |
---|---|---|
committer | Jakub Zelenka <bukka@php.net> | 2015-09-06 19:09:56 +0100 |
commit | e235cb65fbb2b16eb6ee35c0786d9f42f1a74e2c (patch) | |
tree | 7a2d022ad0673bbe25cf71554c5f8b7f4af1dfd5 | |
parent | a49d394beb80cf0efa582559463af9a045fc0407 (diff) | |
download | php-git-e235cb65fbb2b16eb6ee35c0786d9f42f1a74e2c.tar.gz |
Fix request #70438: Add IV parameter for openssl_seal and openssl_open
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | ext/openssl/openssl.c | 75 | ||||
-rw-r--r-- | ext/openssl/tests/bug60632.phpt | 2 | ||||
-rw-r--r-- | ext/openssl/tests/bug70438.phpt | 29 |
4 files changed, 79 insertions, 31 deletions
@@ -9,6 +9,10 @@ PHP NEWS . Fixed bug #70001 (Assigning to DOMNode::textContent does additional entity encoding). (cmb) +- OpenSSL + . Implemented FR #70438 (Add IV parameter for openssl_seal and openssl_open) + (Jakub Zelenka) + - Streams: . Fixed bug #70361 (HTTP stream wrapper doesn't close keep-alive connections). (Niklas Keller) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 4ec4c4f4ed..7d3a3f03da 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -358,6 +358,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_seal, 0, 0, 4) ZEND_ARG_INFO(1, ekeys) /* arary */ ZEND_ARG_INFO(0, pubkeys) /* array */ ZEND_ARG_INFO(0, method) + ZEND_ARG_INFO(1, iv) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_openssl_open, 0) @@ -365,6 +366,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_openssl_open, 0) ZEND_ARG_INFO(1, opendata) ZEND_ARG_INFO(0, ekey) ZEND_ARG_INFO(0, privkey) + ZEND_ARG_INFO(0, iv) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_get_md_methods, 0, 0, 0) @@ -4886,12 +4888,12 @@ PHP_FUNCTION(openssl_verify) Seals data */ PHP_FUNCTION(openssl_seal) { - zval *pubkeys, *pubkey, *sealdata, *ekeys; + zval *pubkeys, *pubkey, *sealdata, *ekeys, *iv = NULL; HashTable *pubkeysht; EVP_PKEY **pkeys; zend_resource ** key_resources; /* so we know what to cleanup */ - int i, len1, len2, *eksl, nkeys; - unsigned char *buf = NULL, **eks; + int i, len1, len2, *eksl, nkeys, iv_len; + unsigned char iv_buf[EVP_MAX_IV_LENGTH + 1], *buf = NULL, **eks; char * data; size_t data_len; char *method =NULL; @@ -4899,7 +4901,8 @@ PHP_FUNCTION(openssl_seal) const EVP_CIPHER *cipher; EVP_CIPHER_CTX ctx; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z/a/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z/a/|sz/", &data, &data_len, + &sealdata, &ekeys, &pubkeys, &method, &method_len, &iv) == FAILURE) { return; } pubkeysht = HASH_OF(pubkeys); @@ -4917,14 +4920,17 @@ PHP_FUNCTION(openssl_seal) php_error_docref(NULL, E_WARNING, "Unknown signature algorithm."); RETURN_FALSE; } - if (EVP_CIPHER_iv_length(cipher) > 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ciphers with modes requiring IV are not supported"); - RETURN_FALSE; - } } else { cipher = EVP_rc4(); } + iv_len = EVP_CIPHER_iv_length(cipher); + if (!iv && iv_len > 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Cipher algorithm requires an IV to be supplied as a sixth parameter"); + RETURN_FALSE; + } + pkeys = safe_emalloc(nkeys, sizeof(*pkeys), 0); eksl = safe_emalloc(nkeys, sizeof(*eksl), 0); eks = safe_emalloc(nkeys, sizeof(*eks), 0); @@ -4951,16 +4957,12 @@ PHP_FUNCTION(openssl_seal) goto clean_exit; } -#if 0 - /* Need this if allow ciphers that require initialization vector */ - ivlen = EVP_CIPHER_CTX_iv_length(&ctx); - iv = ivlen ? emalloc(ivlen + 1) : NULL; -#endif /* allocate one byte extra to make room for \0 */ buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(&ctx)); EVP_CIPHER_CTX_cleanup(&ctx); - if (!EVP_SealInit(&ctx, cipher, eks, eksl, NULL, pkeys, nkeys) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, (int)data_len)) { + if (!EVP_SealInit(&ctx, cipher, eks, eksl, &iv_buf[0], pkeys, nkeys) || + !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, (int)data_len)) { RETVAL_FALSE; efree(buf); EVP_CIPHER_CTX_cleanup(&ctx); @@ -4983,17 +4985,12 @@ PHP_FUNCTION(openssl_seal) efree(eks[i]); eks[i] = NULL; } -#if 0 - /* If allow ciphers that need IV, we need this */ - zval_dtor(*ivec); - if (ivlen) { - iv[ivlen] = '\0'; - ZVAL_STRINGL(*ivec, iv, ivlen); - efree(iv); - } else { - ZVAL_EMPTY_STRING(*ivec); + + if (iv) { + zval_dtor(iv); + iv_buf[iv_len] = '\0'; + ZVAL_NEW_STR(iv, zend_string_init((char*)iv_buf, iv_len, 0)); } -#endif } else { efree(buf); } @@ -5022,19 +5019,20 @@ PHP_FUNCTION(openssl_open) { zval *privkey, *opendata; EVP_PKEY *pkey; - int len1, len2; - unsigned char *buf; + int len1, len2, cipher_iv_len; + unsigned char *buf, *iv_buf; zend_resource *keyresource = NULL; EVP_CIPHER_CTX ctx; char * data; size_t data_len; char * ekey; size_t ekey_len; - char *method =NULL; - size_t method_len = 0; + char *method = NULL, *iv = NULL; + size_t method_len = 0, iv_len = 0; const EVP_CIPHER *cipher; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/sz|s", &data, &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/sz|ss", &data, &data_len, &opendata, + &ekey, &ekey_len, &privkey, &method, &method_len, &iv, &iv_len) == FAILURE) { return; } @@ -5057,9 +5055,26 @@ PHP_FUNCTION(openssl_open) cipher = EVP_rc4(); } + cipher_iv_len = EVP_CIPHER_iv_length(cipher); + if (cipher_iv_len > 0) { + if (!iv) { + php_error_docref(NULL, E_WARNING, + "Cipher algorithm requires an IV to be supplied as a sixth parameter"); + RETURN_FALSE; + } + if (cipher_iv_len != iv_len) { + php_error_docref(NULL, E_WARNING, "IV length is invalid"); + RETURN_FALSE; + } + iv_buf = (unsigned char *)iv; + } else { + iv_buf = NULL; + } + buf = emalloc(data_len + 1); - if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, (int)ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, (int)data_len)) { + if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, (int)ekey_len, iv_buf, pkey) && + EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, (int)data_len)) { if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) { efree(buf); RETVAL_FALSE; diff --git a/ext/openssl/tests/bug60632.phpt b/ext/openssl/tests/bug60632.phpt index c718fed6db..972c20e3b8 100644 --- a/ext/openssl/tests/bug60632.phpt +++ b/ext/openssl/tests/bug60632.phpt @@ -21,5 +21,5 @@ $result = openssl_seal('test phrase', $encrypted, $ekeys, array($pubkey), 'AES-2 echo "Done"; ?> --EXPECTF-- -Warning: openssl_seal(): Ciphers with modes requiring IV are not supported in %s on line %d +Warning: openssl_seal(): Cipher algorithm requires an IV to be supplied as a sixth parameter in %s on line %d Done diff --git a/ext/openssl/tests/bug70438.phpt b/ext/openssl/tests/bug70438.phpt new file mode 100644 index 0000000000..de87a51a7a --- /dev/null +++ b/ext/openssl/tests/bug70438.phpt @@ -0,0 +1,29 @@ +--TEST-- +Request #70438: Add IV parameter for openssl_seal and openssl_open +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) { + print "skip"; +} +if (!in_array('AES-128-CBC', openssl_get_cipher_methods(true))) { + print "skip"; +} +?> +--FILE-- +<?php +$data = "openssl_seal() test"; +$cipher = 'AES-128-CBC'; +$pub_key = "file://" . dirname(__FILE__) . "/public.key"; +$priv_key = "file://" . dirname(__FILE__) . "/private.key"; + +openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key), $cipher); +openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key), 'sparkles', $iv); +openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key), $cipher, $iv); +openssl_open($sealed, $decrypted, $ekeys[0], $priv_key, $cipher, $iv); +echo $decrypted; +?> +--EXPECTF-- +Warning: openssl_seal(): Cipher algorithm requires an IV to be supplied as a sixth parameter in %s on line %d + +Warning: openssl_seal(): Unknown signature algorithm. in %s on line %d +openssl_seal() test |