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
4546static int le_mcrypt ;
@@ -309,48 +310,6 @@ zend_module_entry mcrypt_module_entry = {
309310ZEND_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)
658617char * data ;
659618int data_len ;
660619php_mcrypt * pm ;
661- unsigned char * data_s ;
620+ char * data_s ;
662621int block_size , data_size ;
663622
664623if (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{
11701238char * cipher_dir_string ;
11711239char * module_dir_string ;
1172- int block_size , max_key_length , use_key_length , i , count , iv_size ;
11731240unsigned long int data_size ;
1174- int * key_length_sizes ;
1175- char * key_s = NULL , * iv_s ;
11761241char * data_s ;
11771242MCRYPT td ;
11781243
@@ -1183,124 +1248,79 @@ static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons
11831248php_error_docref (NULL TSRMLS_CC , E_WARNING , MCRYPT_OPEN_MODULE_FAILED );
11841249RETURN_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 */
12381263if (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 );
12401265data_size = (((data_len - 1 ) / block_size ) + 1 ) * block_size ;
1241- data_s = emalloc (data_size );
1266+ data_s = emalloc (data_size + 1 );
12421267memset (data_s , 0 , data_size );
12431268memcpy (data_s , data , data_len );
12441269} else { /* It's not a block algorithm */
12451270data_size = data_len ;
1246- data_s = emalloc (data_size );
1247- memset (data_s , 0 , data_size );
1271+ data_s = emalloc (data_size + 1 );
12481272memcpy (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 ) {
12521276php_error_docref (NULL TSRMLS_CC , E_RECOVERABLE_ERROR , "Mcrypt initialisation failed ");
1277+ mcrypt_module_close (td );
12531278RETURN_FALSE ;
12541279}
1280+
12551281if (dencrypt == MCRYPT_ENCRYPT ) {
12561282mcrypt_generic (td , data_s , data_size );
12571283} else {
12581284mdecrypt_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 */
12641291mcrypt_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 */
12771297PHP_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 */
12931313PHP_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
13171337convert_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
13331353convert_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
13491369convert_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
13651385convert_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