Patch bug60632_new_parameter_for_iv_ciphers.patch for OpenSSL related Bug #60632
Patch version 2013-11-10 21:18 UTC
Return to Bug #60632 |
Download this patch
Patch Revisions:
Developer: jorrit@wafel.org
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 7cf637c..24002b9 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -348,6 +348,8 @@ ZEND_BEGIN_ARG_INFO(arginfo_openssl_seal, 0)
ZEND_ARG_INFO(1, sealdata)
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)
@@ -355,6 +357,8 @@ 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, method)
+ ZEND_ARG_INFO(0, iv)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_get_md_methods, 0, 0, 0)
@@ -4731,19 +4735,21 @@ PHP_FUNCTION(openssl_verify)
PHP_FUNCTION(openssl_seal)
{
zval *pubkeys, **pubkey, *sealdata, *ekeys;
+ zval *iv = NULL;
HashTable *pubkeysht;
HashPosition pos;
EVP_PKEY **pkeys;
long * key_resources; /* so we know what to cleanup */
- int i, len1, len2, *eksl, nkeys;
+ int i, len1, len2, *eksl, nkeys, max_iv_len;
unsigned char *buf = NULL, **eks;
char * data; int data_len;
char *method =NULL;
+ unsigned char *ivbuf = NULL;
int method_len = 0;
const EVP_CIPHER *cipher;
EVP_CIPHER_CTX ctx;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|sz/", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len, &iv) == FAILURE) {
return;
}
@@ -4764,6 +4770,17 @@ PHP_FUNCTION(openssl_seal)
cipher = EVP_rc4();
}
+ max_iv_len = EVP_CIPHER_iv_length(cipher);
+
+ if (max_iv_len > 0) {
+ if (iv == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cipher uses an IV that must be returned, while no IV parameter is specified.");
+ RETURN_FALSE;
+ }
+
+ ivbuf = emalloc(max_iv_len + 1);
+ }
+
pkeys = safe_emalloc(nkeys, sizeof(*pkeys), 0);
eksl = safe_emalloc(nkeys, sizeof(*eksl), 0);
eks = safe_emalloc(nkeys, sizeof(*eks), 0);
@@ -4792,15 +4809,10 @@ 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));
- if (!EVP_SealInit(&ctx, cipher, eks, eksl, NULL, pkeys, nkeys) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {
+ if (!EVP_SealInit(&ctx, cipher, eks, eksl, ivbuf, pkeys, nkeys) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {
RETVAL_FALSE;
efree(buf);
goto clean_exit;
@@ -4821,16 +4833,18 @@ PHP_FUNCTION(openssl_seal)
add_next_index_stringl(ekeys, erealloc(eks[i], eksl[i] + 1), eksl[i], 0);
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, erealloc(iv, ivlen + 1), ivlen, 0);
- } else {
- ZVAL_EMPTY_STRING(*ivec);
+
+ if (iv) {
+ zval_dtor(iv);
+
+ if (max_iv_len > 0) {
+ ivbuf[max_iv_len] = '\0';
+ ZVAL_STRINGL(iv, (char *)ivbuf, max_iv_len, 0);
+ ivbuf = NULL;
+ } else {
+ ZVAL_EMPTY_STRING(iv);
+ }
}
-#endif
} else {
efree(buf);
}
@@ -4845,6 +4859,10 @@ clean_exit:
efree(eks[i]);
}
}
+
+ if (ivbuf) {
+ efree(ivbuf);
+ }
efree(eks);
efree(eksl);
efree(pkeys);
@@ -4866,9 +4884,11 @@ PHP_FUNCTION(openssl_open)
char * ekey; int ekey_len;
char *method =NULL;
int method_len = 0;
+ char *iv = NULL;
+ int iv_len, max_iv_len;
const EVP_CIPHER *cipher;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szsZ|s", &data, &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szsZ|ss", &data, &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len, &iv, &iv_len) == FAILURE) {
return;
}
@@ -4888,9 +4908,24 @@ PHP_FUNCTION(openssl_open)
cipher = EVP_rc4();
}
+ max_iv_len = EVP_CIPHER_iv_length(cipher);
+
+ if (max_iv_len > 0) {
+ if (iv == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cipher requires an IV, while no IV parameter is specified.");
+ RETURN_FALSE;
+ }
+ if (iv_len != max_iv_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IV length.");
+ RETURN_FALSE;
+ }
+ } else {
+ iv = NULL;
+ }
+
buf = emalloc(data_len + 1);
- if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {
+ if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, iv, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {
if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) {
efree(buf);
if (keyresource == -1) {
diff --git a/ext/openssl/tests/bug60632.phpt b/ext/openssl/tests/bug60632.phpt
index e69de29..63a8d86 100644
--- a/ext/openssl/tests/bug60632.phpt
+++ b/ext/openssl/tests/bug60632.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #60632: openssl_seal fails with AES
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) print "skip";
+if (!in_array('AES128', openssl_get_cipher_methods(true))) print "skip";
+?>
+--FILE--
+<?php
+$data = "openssl_seal() test";
+$cipher = 'AES128';
+$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 uses an IV that must be returned, while no IV parameter is specified. in %s on line %d
+
+Warning: openssl_seal(): Unknown signature algorithm. in %s on line %d
+openssl_seal() test
|