summaryrefslogtreecommitdiff
path: root/ext/openssl/openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/openssl/openssl.c')
-rw-r--r--ext/openssl/openssl.c75
1 files changed, 45 insertions, 30 deletions
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;