Skip to content

Commit 94e308d

Browse files
committed
Merge branch 'PHP-5.6'
2 parents 1a94fca + d595502 commit 94e308d

33 files changed

+643
-498
lines changed

ext/mcrypt/mcrypt.c

Lines changed: 146 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "php_globals.h"
4141
#include "ext/standard/info.h"
4242
#include "ext/standard/php_rand.h"
43+
#include "ext/standard/php_smart_str.h"
4344
#include "php_mcrypt_filter.h"
4445

4546
static int le_mcrypt;
@@ -309,48 +310,6 @@ zend_module_entry mcrypt_module_entry = {
309310
ZEND_GET_MODULE(mcrypt)
310311
#endif
311312

312-
#define MCRYPT_ARGS2 \
313-
zval **cipher, **data, **key, **mode; \
314-
int td; \
315-
char *ndata; \
316-
size_t bsize; \
317-
size_t nr; \
318-
size_t nsize
319-
320-
#define MCRYPT_ARGS \
321-
MCRYPT_ARGS2; \
322-
zval **iv
323-
324-
#define MCRYPT_SIZE \
325-
bsize = mcrypt_get_block_size(Z_LVAL_PP(cipher)); \
326-
nr = (Z_STRLEN_PP(data) + bsize - 1) / bsize; \
327-
nsize = nr * bsize
328-
329-
#define MCRYPT_CHECK_TD_CPY \
330-
if (td < 0) { \
331-
php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_FAILED); \
332-
RETURN_FALSE; \
333-
} \
334-
ndata = ecalloc(nr, bsize); \
335-
memcpy(ndata, Z_STRVAL_PP(data), Z_STRLEN_PP(data))
336-
337-
#define MCRYPT_CHECK_IV \
338-
convert_to_string_ex(iv); \
339-
if (Z_STRLEN_PP(iv) != bsize) { \
340-
php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_IV_WRONG_SIZE); \
341-
RETURN_FALSE; \
342-
}
343-
344-
#define MCRYPT_ACTION(x) \
345-
if (Z_LVAL_PP(mode) == 0) { \
346-
mcrypt_##x(td, ndata, nsize); \
347-
} else { \
348-
mdecrypt_##x(td, ndata, nsize); \
349-
} \
350-
end_mcrypt_##x(td)
351-
352-
#define MCRYPT_IV_WRONG_SIZE "The IV parameter must be as long as the blocksize"
353-
354313
#define MCRYPT_ENCRYPT 0
355314
#define MCRYPT_DECRYPT 1
356315

@@ -658,7 +617,7 @@ PHP_FUNCTION(mcrypt_generic)
658617
char *data;
659618
int data_len;
660619
php_mcrypt *pm;
661-
unsigned char* data_s;
620+
char* data_s;
662621
int block_size, data_size;
663622

664623
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) {
@@ -1165,14 +1124,120 @@ PHP_FUNCTION(mcrypt_get_cipher_name)
11651124
}
11661125
/* }}} */
11671126

1168-
static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, const char *data, int data_len, char *mode, const char *iv, int iv_len, int argc, int dencrypt, zval* return_value TSRMLS_DC) /* {{{ */
1127+
static char *php_mcrypt_get_key_size_str(
1128+
int max_key_size, const int *key_sizes, int key_size_count) /* {{{ */
1129+
{
1130+
if (key_size_count == 0) {
1131+
char *str;
1132+
spprintf(&str, 0, "Only keys of size 1 to %d supported", max_key_size);
1133+
return str;
1134+
} else if (key_size_count == 1) {
1135+
char *str;
1136+
spprintf(&str, 0, "Only keys of size %d supported", key_sizes[0]);
1137+
return str;
1138+
} else {
1139+
int i;
1140+
smart_str str = {0};
1141+
smart_str_appends(&str, "Only keys of sizes ");
1142+
1143+
for (i = 0; i < key_size_count; ++i) {
1144+
if (i == key_size_count - 1) {
1145+
smart_str_appends(&str, " or ");
1146+
} else if (i != 0) {
1147+
smart_str_appends(&str, ", ");
1148+
}
1149+
1150+
smart_str_append_long(&str, key_sizes[i]);
1151+
}
1152+
1153+
smart_str_appends(&str, " supported");
1154+
smart_str_0(&str);
1155+
return str.c;
1156+
}
1157+
}
1158+
/* }}} */
1159+
1160+
static zend_bool php_mcrypt_is_valid_key_size(
1161+
int key_size, int max_key_size, int *key_sizes, int key_size_count) /* {{{ */
1162+
{
1163+
int i;
1164+
1165+
if (key_size <= 0 || key_size > max_key_size) {
1166+
return 0;
1167+
}
1168+
1169+
if (key_size_count == 0) {
1170+
/* All key sizes are valid */
1171+
return 1;
1172+
}
1173+
1174+
for (i = 0; i < key_size_count; i++) {
1175+
if (key_sizes[i] == key_size) {
1176+
return 1;
1177+
}
1178+
}
1179+
1180+
return 0;
1181+
}
1182+
/* }}} */
1183+
1184+
static int php_mcrypt_ensure_valid_key_size(MCRYPT td, int key_size TSRMLS_DC) /* {{{ */
1185+
{
1186+
int key_size_count;
1187+
int max_key_size = mcrypt_enc_get_key_size(td);
1188+
int *key_sizes = mcrypt_enc_get_supported_key_sizes(td, &key_size_count);
1189+
1190+
zend_bool is_valid_key_size = php_mcrypt_is_valid_key_size(
1191+
key_size, max_key_size, key_sizes, key_size_count
1192+
);
1193+
if (!is_valid_key_size) {
1194+
char *key_size_str = php_mcrypt_get_key_size_str(
1195+
max_key_size, key_sizes, key_size_count
1196+
);
1197+
php_error_docref(NULL TSRMLS_CC, E_WARNING,
1198+
"Key of size %d not supported by this algorithm. %s", key_size, key_size_str
1199+
);
1200+
efree(key_size_str);
1201+
}
1202+
1203+
if (key_sizes) {
1204+
mcrypt_free(key_sizes);
1205+
}
1206+
1207+
return is_valid_key_size ? SUCCESS : FAILURE;
1208+
}
1209+
/* }}} */
1210+
1211+
static int php_mcrypt_ensure_valid_iv(MCRYPT td, const char *iv, int iv_size TSRMLS_DC) /* {{{ */
1212+
{
1213+
if (mcrypt_enc_mode_has_iv(td) == 1) {
1214+
int expected_iv_size = mcrypt_enc_get_iv_size(td);
1215+
1216+
if (!iv) {
1217+
php_error_docref(NULL TSRMLS_CC, E_WARNING,
1218+
"Encryption mode requires an initialization vector of size %d", expected_iv_size
1219+
);
1220+
return FAILURE;
1221+
}
1222+
1223+
if (iv_size != expected_iv_size) {
1224+
php_error_docref(NULL TSRMLS_CC, E_WARNING,
1225+
"Received initialization vector of size %d, but size %d is required "
1226+
"for this encryption mode", iv_size, expected_iv_size
1227+
);
1228+
return FAILURE;
1229+
}
1230+
}
1231+
1232+
return SUCCESS;
1233+
}
1234+
/* }}} */
1235+
1236+
static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, const char *data, int data_len, char *mode, const char *iv, int iv_len, int dencrypt, zval* return_value TSRMLS_DC) /* {{{ */
11691237
{
11701238
char *cipher_dir_string;
11711239
char *module_dir_string;
1172-
int block_size, max_key_length, use_key_length, i, count, iv_size;
11731240
unsigned long int data_size;
1174-
int *key_length_sizes;
1175-
char *key_s = NULL, *iv_s;
11761241
char *data_s;
11771242
MCRYPT td;
11781243

@@ -1183,124 +1248,79 @@ static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons
11831248
php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED);
11841249
RETURN_FALSE;
11851250
}
1186-
/* Checking for key-length */
1187-
max_key_length = mcrypt_enc_get_key_size(td);
1188-
if (key_len > max_key_length) {
1189-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size of key is too large for this algorithm");
1190-
}
1191-
key_length_sizes = mcrypt_enc_get_supported_key_sizes(td, &count);
1192-
if (count == 0 && key_length_sizes == NULL) { /* all lengths 1 - k_l_s = OK */
1193-
use_key_length = key_len;
1194-
key_s = emalloc(use_key_length);
1195-
memset(key_s, 0, use_key_length);
1196-
memcpy(key_s, key, use_key_length);
1197-
} else if (count == 1) { /* only m_k_l = OK */
1198-
key_s = emalloc(key_length_sizes[0]);
1199-
memset(key_s, 0, key_length_sizes[0]);
1200-
memcpy(key_s, key, MIN(key_len, key_length_sizes[0]));
1201-
use_key_length = key_length_sizes[0];
1202-
} else { /* dertermine smallest supported key > length of requested key */
1203-
use_key_length = max_key_length; /* start with max key length */
1204-
for (i = 0; i < count; i++) {
1205-
if (key_length_sizes[i] >= key_len &&
1206-
key_length_sizes[i] < use_key_length)
1207-
{
1208-
use_key_length = key_length_sizes[i];
1209-
}
1210-
}
1211-
key_s = emalloc(use_key_length);
1212-
memset(key_s, 0, use_key_length);
1213-
memcpy(key_s, key, MIN(key_len, use_key_length));
1251+
1252+
if (php_mcrypt_ensure_valid_key_size(td, key_len TSRMLS_CC) == FAILURE) {
1253+
mcrypt_module_close(td);
1254+
RETURN_FALSE;
12141255
}
1215-
mcrypt_free (key_length_sizes);
1216-
1217-
/* Check IV */
1218-
iv_s = NULL;
1219-
iv_size = mcrypt_enc_get_iv_size (td);
1220-
1221-
/* IV is required */
1222-
if (mcrypt_enc_mode_has_iv(td) == 1) {
1223-
if (argc == 5) {
1224-
if (iv_size != iv_len) {
1225-
php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_IV_WRONG_SIZE);
1226-
} else {
1227-
iv_s = emalloc(iv_size + 1);
1228-
memcpy(iv_s, iv, iv_size);
1229-
}
1230-
} else if (argc == 4) {
1231-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to use an empty IV, which is NOT recommend");
1232-
iv_s = emalloc(iv_size + 1);
1233-
memset(iv_s, 0, iv_size + 1);
1234-
}
1256+
1257+
if (php_mcrypt_ensure_valid_iv(td, iv, iv_len TSRMLS_CC) == FAILURE) {
1258+
mcrypt_module_close(td);
1259+
RETURN_FALSE;
12351260
}
12361261

12371262
/* Check blocksize */
12381263
if (mcrypt_enc_is_block_mode(td) == 1) { /* It's a block algorithm */
1239-
block_size = mcrypt_enc_get_block_size(td);
1264+
int block_size = mcrypt_enc_get_block_size(td);
12401265
data_size = (((data_len - 1) / block_size) + 1) * block_size;
1241-
data_s = emalloc(data_size);
1266+
data_s = emalloc(data_size + 1);
12421267
memset(data_s, 0, data_size);
12431268
memcpy(data_s, data, data_len);
12441269
} else { /* It's not a block algorithm */
12451270
data_size = data_len;
1246-
data_s = emalloc(data_size);
1247-
memset(data_s, 0, data_size);
1271+
data_s = emalloc(data_size + 1);
12481272
memcpy(data_s, data, data_len);
12491273
}
12501274

1251-
if (mcrypt_generic_init(td, key_s, use_key_length, iv_s) < 0) {
1275+
if (mcrypt_generic_init(td, (void *) key, key_len, (void *) iv) < 0) {
12521276
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Mcrypt initialisation failed");
1277+
mcrypt_module_close(td);
12531278
RETURN_FALSE;
12541279
}
1280+
12551281
if (dencrypt == MCRYPT_ENCRYPT) {
12561282
mcrypt_generic(td, data_s, data_size);
12571283
} else {
12581284
mdecrypt_generic(td, data_s, data_size);
12591285
}
12601286

1261-
RETVAL_STRINGL(data_s, data_size, 1);
1287+
data_s[data_size] = 0;
1288+
RETVAL_STRINGL(data_s, data_size, 0);
12621289

12631290
/* freeing vars */
12641291
mcrypt_generic_end(td);
1265-
if (key_s != NULL) {
1266-
efree (key_s);
1267-
}
1268-
if (iv_s != NULL) {
1269-
efree (iv_s);
1270-
}
1271-
efree (data_s);
12721292
}
12731293
/* }}} */
12741294

12751295
/* {{{ proto string mcrypt_encrypt(string cipher, string key, string data, string mode, string iv)
12761296
OFB crypt/decrypt data using key key with cipher cipher starting with iv */
12771297
PHP_FUNCTION(mcrypt_encrypt)
12781298
{
1279-
zval **mode;
1280-
char *cipher, *key, *data, *iv = NULL;
1281-
int cipher_len, key_len, data_len, iv_len = 0;
1299+
char *cipher, *key, *data, *mode, *iv = NULL;
1300+
int cipher_len, key_len, data_len, mode_len, iv_len = 0;
12821301

1283-
MCRYPT_GET_CRYPT_ARGS
1284-
1285-
convert_to_string_ex(mode);
1302+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssss|s", &cipher, &cipher_len,
1303+
&key, &key_len, &data, &data_len, &mode, &mode_len, &iv, &iv_len) == FAILURE) {
1304+
return;
1305+
}
12861306

1287-
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_ENCRYPT, return_value TSRMLS_CC);
1307+
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, mode, iv, iv_len, MCRYPT_ENCRYPT, return_value TSRMLS_CC);
12881308
}
12891309
/* }}} */
12901310

12911311
/* {{{ proto string mcrypt_decrypt(string cipher, string key, string data, string mode, string iv)
12921312
OFB crypt/decrypt data using key key with cipher cipher starting with iv */
12931313
PHP_FUNCTION(mcrypt_decrypt)
12941314
{
1295-
zval **mode;
1296-
char *cipher, *key, *data, *iv = NULL;
1297-
int cipher_len, key_len, data_len, iv_len = 0;
1315+
char *cipher, *key, *data, *mode, *iv = NULL;
1316+
int cipher_len, key_len, data_len, mode_len, iv_len = 0;
12981317

1299-
MCRYPT_GET_CRYPT_ARGS
1300-
1301-
convert_to_string_ex(mode);
1318+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssss|s", &cipher, &cipher_len,
1319+
&key, &key_len, &data, &data_len, &mode, &mode_len, &iv, &iv_len) == FAILURE) {
1320+
return;
1321+
}
13021322

1303-
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_DECRYPT, return_value TSRMLS_CC);
1323+
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, mode, iv, iv_len, MCRYPT_DECRYPT, return_value TSRMLS_CC);
13041324
}
13051325
/* }}} */
13061326

@@ -1316,7 +1336,7 @@ PHP_FUNCTION(mcrypt_ecb)
13161336

13171337
convert_to_long_ex(mode);
13181338

1319-
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ecb", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
1339+
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ecb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC);
13201340
}
13211341
/* }}} */
13221342

@@ -1332,7 +1352,7 @@ PHP_FUNCTION(mcrypt_cbc)
13321352

13331353
convert_to_long_ex(mode);
13341354

1335-
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cbc", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
1355+
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cbc", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC);
13361356
}
13371357
/* }}} */
13381358

@@ -1348,7 +1368,7 @@ PHP_FUNCTION(mcrypt_cfb)
13481368

13491369
convert_to_long_ex(mode);
13501370

1351-
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cfb", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
1371+
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cfb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC);
13521372
}
13531373
/* }}} */
13541374

@@ -1364,7 +1384,7 @@ PHP_FUNCTION(mcrypt_ofb)
13641384

13651385
convert_to_long_ex(mode);
13661386

1367-
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ofb", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
1387+
php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ofb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC);
13681388
}
13691389
/* }}} */
13701390

0 commit comments

Comments
 (0)