1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 The PHP Group | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 3.01 of the PHP license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.php.net/license/3_01.txt | 11 | If you did not receive a copy of the PHP license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@php.net so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Authors: Sascha Schumann <sascha@schumann.cx> | 16 | Derick Rethans <derick@derickrethans.nl> | 17 +----------------------------------------------------------------------+ 18 */ 19/* $Id$ */ 20 21#ifdef HAVE_CONFIG_H 22#include "config.h" 23#endif 24 25#include "php.h" 26 27#if HAVE_LIBMCRYPT 28 29#if PHP_WIN32 30# include "win32/winutil.h" 31#endif 32 33#include "php_mcrypt.h" 34#include "fcntl.h" 35 36#define NON_FREE 37#define MCRYPT2 38#include "mcrypt.h" 39#include "php_ini.h" 40#include "php_globals.h" 41#include "ext/standard/info.h" 42#include "ext/standard/php_rand.h" 43#include "php_mcrypt_filter.h" 44 45static int le_mcrypt; 46 47typedef struct _php_mcrypt { 48 MCRYPT td; 49 zend_bool init; 50} php_mcrypt; 51 52/* {{{ arginfo */ 53ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_open, 0, 0, 4) 54 ZEND_ARG_INFO(0, cipher) 55 ZEND_ARG_INFO(0, cipher_directory) 56 ZEND_ARG_INFO(0, mode) 57 ZEND_ARG_INFO(0, mode_directory) 58ZEND_END_ARG_INFO() 59 60ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic_init, 0, 0, 3) 61 ZEND_ARG_INFO(0, td) 62 ZEND_ARG_INFO(0, key) 63 ZEND_ARG_INFO(0, iv) 64ZEND_END_ARG_INFO() 65 66ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic, 0, 0, 2) 67 ZEND_ARG_INFO(0, td) 68 ZEND_ARG_INFO(0, data) 69ZEND_END_ARG_INFO() 70 71ZEND_BEGIN_ARG_INFO_EX(arginfo_mdecrypt_generic, 0, 0, 2) 72 ZEND_ARG_INFO(0, td) 73 ZEND_ARG_INFO(0, data) 74ZEND_END_ARG_INFO() 75 76ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_supported_key_sizes, 0, 0, 1) 77 ZEND_ARG_INFO(0, td) 78ZEND_END_ARG_INFO() 79 80ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_self_test, 0, 0, 1) 81 ZEND_ARG_INFO(0, td) 82ZEND_END_ARG_INFO() 83 84ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_close, 0, 0, 1) 85 ZEND_ARG_INFO(0, td) 86ZEND_END_ARG_INFO() 87 88ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic_deinit, 0, 0, 1) 89 ZEND_ARG_INFO(0, td) 90ZEND_END_ARG_INFO() 91 92ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_algorithm_mode, 0, 0, 1) 93 ZEND_ARG_INFO(0, td) 94ZEND_END_ARG_INFO() 95 96ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_algorithm, 0, 0, 1) 97 ZEND_ARG_INFO(0, td) 98ZEND_END_ARG_INFO() 99 100ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_mode, 0, 0, 1) 101 ZEND_ARG_INFO(0, td) 102ZEND_END_ARG_INFO() 103 104ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_block_size, 0, 0, 1) 105 ZEND_ARG_INFO(0, td) 106ZEND_END_ARG_INFO() 107 108ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_key_size, 0, 0, 1) 109 ZEND_ARG_INFO(0, td) 110ZEND_END_ARG_INFO() 111 112ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_iv_size, 0, 0, 1) 113 ZEND_ARG_INFO(0, td) 114ZEND_END_ARG_INFO() 115 116ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_algorithms_name, 0, 0, 1) 117 ZEND_ARG_INFO(0, td) 118ZEND_END_ARG_INFO() 119 120ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_modes_name, 0, 0, 1) 121 ZEND_ARG_INFO(0, td) 122ZEND_END_ARG_INFO() 123 124ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_self_test, 0, 0, 1) 125 ZEND_ARG_INFO(0, algorithm) 126 ZEND_ARG_INFO(0, lib_dir) 127ZEND_END_ARG_INFO() 128 129ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_is_block_algorithm_mode, 0, 0, 1) 130 ZEND_ARG_INFO(0, mode) 131 ZEND_ARG_INFO(0, lib_dir) 132ZEND_END_ARG_INFO() 133 134ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_is_block_algorithm, 0, 0, 1) 135 ZEND_ARG_INFO(0, algorithm) 136 ZEND_ARG_INFO(0, lib_dir) 137ZEND_END_ARG_INFO() 138 139ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_is_block_mode, 0, 0, 1) 140 ZEND_ARG_INFO(0, mode) 141 ZEND_ARG_INFO(0, lib_dir) 142ZEND_END_ARG_INFO() 143 144ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_get_algo_block_size, 0, 0, 1) 145 ZEND_ARG_INFO(0, algorithm) 146 ZEND_ARG_INFO(0, lib_dir) 147ZEND_END_ARG_INFO() 148 149ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_get_algo_key_size, 0, 0, 1) 150 ZEND_ARG_INFO(0, algorithm) 151 ZEND_ARG_INFO(0, lib_dir) 152ZEND_END_ARG_INFO() 153 154ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_get_supported_key_sizes, 0, 0, 1) 155 ZEND_ARG_INFO(0, algorithm) 156 ZEND_ARG_INFO(0, lib_dir) 157ZEND_END_ARG_INFO() 158 159ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_list_algorithms, 0, 0, 0) 160 ZEND_ARG_INFO(0, lib_dir) 161ZEND_END_ARG_INFO() 162 163ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_list_modes, 0, 0, 0) 164 ZEND_ARG_INFO(0, lib_dir) 165ZEND_END_ARG_INFO() 166 167ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_key_size, 0, 0, 2) 168 ZEND_ARG_INFO(0, cipher) 169 ZEND_ARG_INFO(0, module) 170ZEND_END_ARG_INFO() 171 172ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_block_size, 0, 0, 2) 173 ZEND_ARG_INFO(0, cipher) 174 ZEND_ARG_INFO(0, module) 175ZEND_END_ARG_INFO() 176 177ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_iv_size, 0, 0, 2) 178 ZEND_ARG_INFO(0, cipher) 179 ZEND_ARG_INFO(0, module) 180ZEND_END_ARG_INFO() 181 182ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_cipher_name, 0, 0, 1) 183 ZEND_ARG_INFO(0, cipher) 184ZEND_END_ARG_INFO() 185 186ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_encrypt, 0, 0, 5) 187 ZEND_ARG_INFO(0, cipher) 188 ZEND_ARG_INFO(0, key) 189 ZEND_ARG_INFO(0, data) 190 ZEND_ARG_INFO(0, mode) 191 ZEND_ARG_INFO(0, iv) 192ZEND_END_ARG_INFO() 193 194ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_decrypt, 0, 0, 5) 195 ZEND_ARG_INFO(0, cipher) 196 ZEND_ARG_INFO(0, key) 197 ZEND_ARG_INFO(0, data) 198 ZEND_ARG_INFO(0, mode) 199 ZEND_ARG_INFO(0, iv) 200ZEND_END_ARG_INFO() 201 202ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_ecb, 0, 0, 5) 203 ZEND_ARG_INFO(0, cipher) 204 ZEND_ARG_INFO(0, key) 205 ZEND_ARG_INFO(0, data) 206 ZEND_ARG_INFO(0, mode) 207 ZEND_ARG_INFO(0, iv) 208ZEND_END_ARG_INFO() 209 210ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_cbc, 0, 0, 5) 211 ZEND_ARG_INFO(0, cipher) 212 ZEND_ARG_INFO(0, key) 213 ZEND_ARG_INFO(0, data) 214 ZEND_ARG_INFO(0, mode) 215 ZEND_ARG_INFO(0, iv) 216ZEND_END_ARG_INFO() 217 218ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_cfb, 0, 0, 5) 219 ZEND_ARG_INFO(0, cipher) 220 ZEND_ARG_INFO(0, key) 221 ZEND_ARG_INFO(0, data) 222 ZEND_ARG_INFO(0, mode) 223 ZEND_ARG_INFO(0, iv) 224ZEND_END_ARG_INFO() 225 226ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_ofb, 0, 0, 5) 227 ZEND_ARG_INFO(0, cipher) 228 ZEND_ARG_INFO(0, key) 229 ZEND_ARG_INFO(0, data) 230 ZEND_ARG_INFO(0, mode) 231 ZEND_ARG_INFO(0, iv) 232ZEND_END_ARG_INFO() 233 234ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_create_iv, 0, 0, 2) 235 ZEND_ARG_INFO(0, size) 236 ZEND_ARG_INFO(0, source) 237ZEND_END_ARG_INFO() 238/* }}} */ 239 240const zend_function_entry mcrypt_functions[] = { /* {{{ */ 241 PHP_DEP_FE(mcrypt_ecb, arginfo_mcrypt_ecb) 242 PHP_DEP_FE(mcrypt_cbc, arginfo_mcrypt_cbc) 243 PHP_DEP_FE(mcrypt_cfb, arginfo_mcrypt_cfb) 244 PHP_DEP_FE(mcrypt_ofb, arginfo_mcrypt_ofb) 245 PHP_FE(mcrypt_get_key_size, arginfo_mcrypt_get_key_size) 246 PHP_FE(mcrypt_get_block_size, arginfo_mcrypt_get_block_size) 247 PHP_FE(mcrypt_get_cipher_name, arginfo_mcrypt_get_cipher_name) 248 PHP_FE(mcrypt_create_iv, arginfo_mcrypt_create_iv) 249 250 PHP_FE(mcrypt_list_algorithms, arginfo_mcrypt_list_algorithms) 251 PHP_FE(mcrypt_list_modes, arginfo_mcrypt_list_modes) 252 PHP_FE(mcrypt_get_iv_size, arginfo_mcrypt_get_iv_size) 253 PHP_FE(mcrypt_encrypt, arginfo_mcrypt_encrypt) 254 PHP_FE(mcrypt_decrypt, arginfo_mcrypt_decrypt) 255 256 PHP_FE(mcrypt_module_open, arginfo_mcrypt_module_open) 257 PHP_FE(mcrypt_generic_init, arginfo_mcrypt_generic_init) 258 PHP_FE(mcrypt_generic, arginfo_mcrypt_generic) 259 PHP_FE(mdecrypt_generic, arginfo_mdecrypt_generic) 260 PHP_DEP_FALIAS(mcrypt_generic_end, mcrypt_generic_deinit, arginfo_mcrypt_generic_deinit) 261 PHP_FE(mcrypt_generic_deinit, arginfo_mcrypt_generic_deinit) 262 263 PHP_FE(mcrypt_enc_self_test, arginfo_mcrypt_enc_self_test) 264 PHP_FE(mcrypt_enc_is_block_algorithm_mode, arginfo_mcrypt_enc_is_block_algorithm_mode) 265 PHP_FE(mcrypt_enc_is_block_algorithm, arginfo_mcrypt_enc_is_block_algorithm) 266 PHP_FE(mcrypt_enc_is_block_mode, arginfo_mcrypt_enc_is_block_mode) 267 PHP_FE(mcrypt_enc_get_block_size, arginfo_mcrypt_enc_get_block_size) 268 PHP_FE(mcrypt_enc_get_key_size, arginfo_mcrypt_enc_get_key_size) 269 PHP_FE(mcrypt_enc_get_supported_key_sizes, arginfo_mcrypt_enc_get_supported_key_sizes) 270 PHP_FE(mcrypt_enc_get_iv_size, arginfo_mcrypt_enc_get_iv_size) 271 PHP_FE(mcrypt_enc_get_algorithms_name, arginfo_mcrypt_enc_get_algorithms_name) 272 PHP_FE(mcrypt_enc_get_modes_name, arginfo_mcrypt_enc_get_modes_name) 273 PHP_FE(mcrypt_module_self_test, arginfo_mcrypt_module_self_test) 274 275 PHP_FE(mcrypt_module_is_block_algorithm_mode, arginfo_mcrypt_module_is_block_algorithm_mode) 276 PHP_FE(mcrypt_module_is_block_algorithm, arginfo_mcrypt_module_is_block_algorithm) 277 PHP_FE(mcrypt_module_is_block_mode, arginfo_mcrypt_module_is_block_mode) 278 PHP_FE(mcrypt_module_get_algo_block_size, arginfo_mcrypt_module_get_algo_block_size) 279 PHP_FE(mcrypt_module_get_algo_key_size, arginfo_mcrypt_module_get_algo_key_size) 280 PHP_FE(mcrypt_module_get_supported_key_sizes, arginfo_mcrypt_module_get_supported_key_sizes) 281 282 PHP_FE(mcrypt_module_close, arginfo_mcrypt_module_close) 283 PHP_FE_END 284}; 285/* }}} */ 286 287static PHP_MINFO_FUNCTION(mcrypt); 288static PHP_MINIT_FUNCTION(mcrypt); 289static PHP_MSHUTDOWN_FUNCTION(mcrypt); 290 291ZEND_DECLARE_MODULE_GLOBALS(mcrypt) 292 293zend_module_entry mcrypt_module_entry = { 294 STANDARD_MODULE_HEADER, 295 "mcrypt", 296 mcrypt_functions, 297 PHP_MINIT(mcrypt), PHP_MSHUTDOWN(mcrypt), 298 NULL, NULL, 299 PHP_MINFO(mcrypt), 300 NO_VERSION_YET, 301 PHP_MODULE_GLOBALS(mcrypt), 302 NULL, 303 NULL, 304 NULL, 305 STANDARD_MODULE_PROPERTIES_EX 306}; 307 308#ifdef COMPILE_DL_MCRYPT 309ZEND_GET_MODULE(mcrypt) 310#endif 311 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 354#define MCRYPT_ENCRYPT 0 355#define MCRYPT_DECRYPT 1 356 357#define MCRYPT_GET_INI \ 358 cipher_dir_string = MCG(algorithms_dir); \ 359 module_dir_string = MCG(modes_dir); 360 361/* 362 * #warning is not ANSI C 363 * #warning Invalidate resource if the param count is wrong, or other problems 364 * #warning occurred during functions. 365 */ 366 367#define MCRYPT_GET_CRYPT_ARGS \ 368 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssZ|s", \ 369 &cipher, &cipher_len, &key, &key_len, &data, &data_len, &mode, &iv, &iv_len) == FAILURE) { \ 370 return; \ 371 } 372 373#define MCRYPT_GET_TD_ARG \ 374 zval *mcryptind; \ 375 php_mcrypt *pm; \ 376 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mcryptind) == FAILURE) { \ 377 return; \ 378 } \ 379 ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); 380 381#define MCRYPT_GET_MODE_DIR_ARGS(DIRECTORY) \ 382 char *dir = NULL; \ 383 int dir_len; \ 384 char *module; \ 385 int module_len; \ 386 if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, \ 387 "s|s", &module, &module_len, &dir, &dir_len) == FAILURE) { \ 388 return; \ 389 } 390 391#define MCRYPT_OPEN_MODULE_FAILED "Module initialization failed" 392 393#define MCRYPT_ENTRY2_2_4(a,b) REGISTER_STRING_CONSTANT("MCRYPT_" #a, b, CONST_PERSISTENT) 394#define MCRYPT_ENTRY2_4(a) MCRYPT_ENTRY_NAMED(a, a) 395 396#define PHP_MCRYPT_INIT_CHECK \ 397 if (!pm->init) { \ 398 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Operation disallowed prior to mcrypt_generic_init()."); \ 399 RETURN_FALSE; \ 400 } \ 401 402PHP_INI_BEGIN() 403 STD_PHP_INI_ENTRY("mcrypt.algorithms_dir", NULL, PHP_INI_ALL, OnUpdateString, algorithms_dir, zend_mcrypt_globals, mcrypt_globals) 404 STD_PHP_INI_ENTRY("mcrypt.modes_dir", NULL, PHP_INI_ALL, OnUpdateString, modes_dir, zend_mcrypt_globals, mcrypt_globals) 405PHP_INI_END() 406 407static void php_mcrypt_module_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ 408{ 409 php_mcrypt *pm = (php_mcrypt *) rsrc->ptr; 410 if (pm) { 411 mcrypt_generic_deinit(pm->td); 412 mcrypt_module_close(pm->td); 413 efree(pm); 414 pm = NULL; 415 } 416} 417/* }}} */ 418 419static PHP_MINIT_FUNCTION(mcrypt) /* {{{ */ 420{ 421 le_mcrypt = zend_register_list_destructors_ex(php_mcrypt_module_dtor, NULL, "mcrypt", module_number); 422 423 /* modes for mcrypt_??? routines */ 424 REGISTER_LONG_CONSTANT("MCRYPT_ENCRYPT", 0, CONST_PERSISTENT); 425 REGISTER_LONG_CONSTANT("MCRYPT_DECRYPT", 1, CONST_PERSISTENT); 426 427 /* sources for mcrypt_create_iv */ 428 REGISTER_LONG_CONSTANT("MCRYPT_DEV_RANDOM", 0, CONST_PERSISTENT); 429 REGISTER_LONG_CONSTANT("MCRYPT_DEV_URANDOM", 1, CONST_PERSISTENT); 430 REGISTER_LONG_CONSTANT("MCRYPT_RAND", 2, CONST_PERSISTENT); 431 432 /* ciphers */ 433 MCRYPT_ENTRY2_2_4(3DES, "tripledes"); 434 MCRYPT_ENTRY2_2_4(ARCFOUR_IV, "arcfour-iv"); 435 MCRYPT_ENTRY2_2_4(ARCFOUR, "arcfour"); 436 MCRYPT_ENTRY2_2_4(BLOWFISH, "blowfish"); 437 MCRYPT_ENTRY2_2_4(BLOWFISH_COMPAT, "blowfish-compat"); 438 MCRYPT_ENTRY2_2_4(CAST_128, "cast-128"); 439 MCRYPT_ENTRY2_2_4(CAST_256, "cast-256"); 440 MCRYPT_ENTRY2_2_4(CRYPT, "crypt"); 441 MCRYPT_ENTRY2_2_4(DES, "des"); 442 MCRYPT_ENTRY2_2_4(ENIGNA, "crypt"); 443 MCRYPT_ENTRY2_2_4(GOST, "gost"); 444 MCRYPT_ENTRY2_2_4(LOKI97, "loki97"); 445 MCRYPT_ENTRY2_2_4(PANAMA, "panama"); 446 MCRYPT_ENTRY2_2_4(RC2, "rc2"); 447 MCRYPT_ENTRY2_2_4(RIJNDAEL_128, "rijndael-128"); 448 MCRYPT_ENTRY2_2_4(RIJNDAEL_192, "rijndael-192"); 449 MCRYPT_ENTRY2_2_4(RIJNDAEL_256, "rijndael-256"); 450 MCRYPT_ENTRY2_2_4(SAFER64, "safer-sk64"); 451 MCRYPT_ENTRY2_2_4(SAFER128, "safer-sk128"); 452 MCRYPT_ENTRY2_2_4(SAFERPLUS, "saferplus"); 453 MCRYPT_ENTRY2_2_4(SERPENT, "serpent"); 454 MCRYPT_ENTRY2_2_4(THREEWAY, "threeway"); 455 MCRYPT_ENTRY2_2_4(TRIPLEDES, "tripledes"); 456 MCRYPT_ENTRY2_2_4(TWOFISH, "twofish"); 457 MCRYPT_ENTRY2_2_4(WAKE, "wake"); 458 MCRYPT_ENTRY2_2_4(XTEA, "xtea"); 459 460 MCRYPT_ENTRY2_2_4(IDEA, "idea"); 461 MCRYPT_ENTRY2_2_4(MARS, "mars"); 462 MCRYPT_ENTRY2_2_4(RC6, "rc6"); 463 MCRYPT_ENTRY2_2_4(SKIPJACK, "skipjack"); 464/* modes */ 465 MCRYPT_ENTRY2_2_4(MODE_CBC, "cbc"); 466 MCRYPT_ENTRY2_2_4(MODE_CFB, "cfb"); 467 MCRYPT_ENTRY2_2_4(MODE_ECB, "ecb"); 468 MCRYPT_ENTRY2_2_4(MODE_NOFB, "nofb"); 469 MCRYPT_ENTRY2_2_4(MODE_OFB, "ofb"); 470 MCRYPT_ENTRY2_2_4(MODE_STREAM, "stream"); 471 REGISTER_INI_ENTRIES(); 472 473 php_stream_filter_register_factory("mcrypt.*", &php_mcrypt_filter_factory TSRMLS_CC); 474 php_stream_filter_register_factory("mdecrypt.*", &php_mcrypt_filter_factory TSRMLS_CC); 475 476 return SUCCESS; 477} 478/* }}} */ 479 480static PHP_MSHUTDOWN_FUNCTION(mcrypt) /* {{{ */ 481{ 482 php_stream_filter_unregister_factory("mcrypt.*" TSRMLS_CC); 483 php_stream_filter_unregister_factory("mdecrypt.*" TSRMLS_CC); 484 485 UNREGISTER_INI_ENTRIES(); 486 return SUCCESS; 487} 488/* }}} */ 489 490#include "ext/standard/php_smart_str.h" 491 492PHP_MINFO_FUNCTION(mcrypt) /* {{{ */ 493{ 494 char **modules; 495 char mcrypt_api_no[16]; 496 int i, count; 497 smart_str tmp1 = {0}; 498 smart_str tmp2 = {0}; 499 500 modules = mcrypt_list_algorithms(MCG(algorithms_dir), &count); 501 if (count == 0) { 502 smart_str_appends(&tmp1, "none"); 503 } 504 for (i = 0; i < count; i++) { 505 smart_str_appends(&tmp1, modules[i]); 506 smart_str_appendc(&tmp1, ' '); 507 } 508 smart_str_0(&tmp1); 509 mcrypt_free_p(modules, count); 510 511 modules = mcrypt_list_modes(MCG(modes_dir), &count); 512 if (count == 0) { 513 smart_str_appends(&tmp2, "none"); 514 } 515 for (i = 0; i < count; i++) { 516 smart_str_appends(&tmp2, modules[i]); 517 smart_str_appendc(&tmp2, ' '); 518 } 519 smart_str_0 (&tmp2); 520 mcrypt_free_p (modules, count); 521 522 snprintf (mcrypt_api_no, 16, "%d", MCRYPT_API_VERSION); 523 524 php_info_print_table_start(); 525 php_info_print_table_header(2, "mcrypt support", "enabled"); 526 php_info_print_table_header(2, "mcrypt_filter support", "enabled"); 527 php_info_print_table_row(2, "Version", LIBMCRYPT_VERSION); 528 php_info_print_table_row(2, "Api No", mcrypt_api_no); 529 php_info_print_table_row(2, "Supported ciphers", tmp1.c); 530 php_info_print_table_row(2, "Supported modes", tmp2.c); 531 smart_str_free(&tmp1); 532 smart_str_free(&tmp2); 533 php_info_print_table_end(); 534 535 DISPLAY_INI_ENTRIES(); 536} 537/* }}} */ 538 539typedef enum { 540 RANDOM = 0, 541 URANDOM, 542 RAND 543} iv_source; 544 545/* {{{ proto resource mcrypt_module_open(string cipher, string cipher_directory, string mode, string mode_directory) 546 Opens the module of the algorithm and the mode to be used */ 547PHP_FUNCTION(mcrypt_module_open) 548{ 549 char *cipher, *cipher_dir; 550 char *mode, *mode_dir; 551 int cipher_len, cipher_dir_len; 552 int mode_len, mode_dir_len; 553 MCRYPT td; 554 php_mcrypt *pm; 555 556 if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ssss", 557 &cipher, &cipher_len, &cipher_dir, &cipher_dir_len, 558 &mode, &mode_len, &mode_dir, &mode_dir_len)) { 559 return; 560 } 561 562 td = mcrypt_module_open ( 563 cipher, 564 cipher_dir_len > 0 ? cipher_dir : MCG(algorithms_dir), 565 mode, 566 mode_dir_len > 0 ? mode_dir : MCG(modes_dir) 567 ); 568 569 if (td == MCRYPT_FAILED) { 570 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open encryption module"); 571 RETURN_FALSE; 572 } else { 573 pm = emalloc(sizeof(php_mcrypt)); 574 pm->td = td; 575 pm->init = 0; 576 ZEND_REGISTER_RESOURCE(return_value, pm, le_mcrypt); 577 } 578} 579/* }}} */ 580 581/* {{{ proto int mcrypt_generic_init(resource td, string key, string iv) 582 This function initializes all buffers for the specific module */ 583PHP_FUNCTION(mcrypt_generic_init) 584{ 585 char *key, *iv; 586 int key_len, iv_len; 587 zval *mcryptind; 588 unsigned char *key_s, *iv_s; 589 int max_key_size, key_size, iv_size; 590 php_mcrypt *pm; 591 int result = 0; 592 593 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &mcryptind, &key, &key_len, &iv, &iv_len) == FAILURE) { 594 return; 595 } 596 597 ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); 598 599 max_key_size = mcrypt_enc_get_key_size(pm->td); 600 iv_size = mcrypt_enc_get_iv_size(pm->td); 601 602 if (key_len == 0) { 603 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key size is 0"); 604 } 605 606 key_s = emalloc(key_len); 607 memset(key_s, 0, key_len); 608 609 iv_s = emalloc(iv_size + 1); 610 memset(iv_s, 0, iv_size + 1); 611 612 if (key_len > max_key_size) { 613 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key size too large; supplied length: %d, max: %d", key_len, max_key_size); 614 key_size = max_key_size; 615 } else { 616 key_size = key_len; 617 } 618 memcpy(key_s, key, key_len); 619 620 if (iv_len != iv_size) { 621 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Iv size incorrect; supplied length: %d, needed: %d", iv_len, iv_size); 622 } 623 memcpy(iv_s, iv, iv_size); 624 625 mcrypt_generic_deinit(pm->td); 626 result = mcrypt_generic_init(pm->td, key_s, key_size, iv_s); 627 628 /* If this function fails, close the mcrypt module to prevent crashes 629 * when further functions want to access this resource */ 630 if (result < 0) { 631 zend_list_delete(Z_LVAL_P(mcryptind)); 632 switch (result) { 633 case -3: 634 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key length incorrect"); 635 break; 636 case -4: 637 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memory allocation error"); 638 break; 639 case -1: 640 default: 641 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error"); 642 break; 643 } 644 } 645 pm->init = 1; 646 RETVAL_LONG(result); 647 648 efree(iv_s); 649 efree(key_s); 650} 651/* }}} */ 652 653/* {{{ proto string mcrypt_generic(resource td, string data) 654 This function encrypts the plaintext */ 655PHP_FUNCTION(mcrypt_generic) 656{ 657 zval *mcryptind; 658 char *data; 659 int data_len; 660 php_mcrypt *pm; 661 unsigned char* data_s; 662 int block_size, data_size; 663 664 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { 665 return; 666 } 667 668 ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); 669 PHP_MCRYPT_INIT_CHECK 670 671 if (data_len == 0) { 672 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An empty string was passed"); 673 RETURN_FALSE 674 } 675 676 /* Check blocksize */ 677 if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ 678 block_size = mcrypt_enc_get_block_size(pm->td); 679 data_size = (((data_len - 1) / block_size) + 1) * block_size; 680 data_s = emalloc(data_size + 1); 681 memset(data_s, 0, data_size); 682 memcpy(data_s, data, data_len); 683 } else { /* It's not a block algorithm */ 684 data_size = data_len; 685 data_s = emalloc(data_size + 1); 686 memset(data_s, 0, data_size); 687 memcpy(data_s, data, data_len); 688 } 689 690 mcrypt_generic(pm->td, data_s, data_size); 691 data_s[data_size] = '\0'; 692 693 RETVAL_STRINGL(data_s, data_size, 1); 694 efree(data_s); 695} 696/* }}} */ 697 698/* {{{ proto string mdecrypt_generic(resource td, string data) 699 This function decrypts the plaintext */ 700PHP_FUNCTION(mdecrypt_generic) 701{ 702 zval *mcryptind; 703 char *data; 704 int data_len; 705 php_mcrypt *pm; 706 char* data_s; 707 int block_size, data_size; 708 709 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { 710 return; 711 } 712 713 ZEND_FETCH_RESOURCE(pm, php_mcrypt * , &mcryptind, -1, "MCrypt", le_mcrypt); 714 PHP_MCRYPT_INIT_CHECK 715 716 if (data_len == 0) { 717 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An empty string was passed"); 718 RETURN_FALSE 719 } 720 721 /* Check blocksize */ 722 if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ 723 block_size = mcrypt_enc_get_block_size(pm->td); 724 data_size = (((data_len - 1) / block_size) + 1) * block_size; 725 data_s = emalloc(data_size + 1); 726 memset(data_s, 0, data_size); 727 memcpy(data_s, data, data_len); 728 } else { /* It's not a block algorithm */ 729 data_size = data_len; 730 data_s = emalloc(data_size + 1); 731 memset(data_s, 0, data_size); 732 memcpy(data_s, data, data_len); 733 } 734 735 mdecrypt_generic(pm->td, data_s, data_size); 736 737 RETVAL_STRINGL(data_s, data_size, 1); 738 efree(data_s); 739} 740/* }}} */ 741 742/* {{{ proto array mcrypt_enc_get_supported_key_sizes(resource td) 743 This function decrypts the crypttext */ 744PHP_FUNCTION(mcrypt_enc_get_supported_key_sizes) 745{ 746 int i, count = 0; 747 int *key_sizes; 748 749 MCRYPT_GET_TD_ARG 750 array_init(return_value); 751 752 key_sizes = mcrypt_enc_get_supported_key_sizes(pm->td, &count); 753 754 for (i = 0; i < count; i++) { 755 add_index_long(return_value, i, key_sizes[i]); 756 } 757 758 mcrypt_free(key_sizes); 759} 760/* }}} */ 761 762/* {{{ proto int mcrypt_enc_self_test(resource td) 763 This function runs the self test on the algorithm specified by the descriptor td */ 764PHP_FUNCTION(mcrypt_enc_self_test) 765{ 766 MCRYPT_GET_TD_ARG 767 RETURN_LONG(mcrypt_enc_self_test(pm->td)); 768} 769/* }}} */ 770 771/* {{{ proto bool mcrypt_module_close(resource td) 772 Free the descriptor td */ 773PHP_FUNCTION(mcrypt_module_close) 774{ 775 MCRYPT_GET_TD_ARG 776 zend_list_delete(Z_LVAL_P(mcryptind)); 777 RETURN_TRUE; 778} 779/* }}} */ 780 781/* {{{ proto bool mcrypt_generic_deinit(resource td) 782 This function terminates encrypt specified by the descriptor td */ 783PHP_FUNCTION(mcrypt_generic_deinit) 784{ 785 MCRYPT_GET_TD_ARG 786 787 if (mcrypt_generic_deinit(pm->td) < 0) { 788 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not terminate encryption specifier"); 789 RETURN_FALSE 790 } 791 pm->init = 0; 792 RETURN_TRUE 793} 794/* }}} */ 795 796/* {{{ proto bool mcrypt_enc_is_block_algorithm_mode(resource td) 797 Returns TRUE if the mode is for use with block algorithms */ 798PHP_FUNCTION(mcrypt_enc_is_block_algorithm_mode) 799{ 800 MCRYPT_GET_TD_ARG 801 802 if (mcrypt_enc_is_block_algorithm_mode(pm->td) == 1) { 803 RETURN_TRUE 804 } else { 805 RETURN_FALSE 806 } 807} 808/* }}} */ 809 810/* {{{ proto bool mcrypt_enc_is_block_algorithm(resource td) 811 Returns TRUE if the alrogithm is a block algorithms */ 812PHP_FUNCTION(mcrypt_enc_is_block_algorithm) 813{ 814 MCRYPT_GET_TD_ARG 815 816 if (mcrypt_enc_is_block_algorithm(pm->td) == 1) { 817 RETURN_TRUE 818 } else { 819 RETURN_FALSE 820 } 821} 822/* }}} */ 823 824/* {{{ proto bool mcrypt_enc_is_block_mode(resource td) 825 Returns TRUE if the mode outputs blocks */ 826PHP_FUNCTION(mcrypt_enc_is_block_mode) 827{ 828 MCRYPT_GET_TD_ARG 829 830 if (mcrypt_enc_is_block_mode(pm->td) == 1) { 831 RETURN_TRUE 832 } else { 833 RETURN_FALSE 834 } 835} 836/* }}} */ 837 838/* {{{ proto int mcrypt_enc_get_block_size(resource td) 839 Returns the block size of the cipher specified by the descriptor td */ 840PHP_FUNCTION(mcrypt_enc_get_block_size) 841{ 842 MCRYPT_GET_TD_ARG 843 RETURN_LONG(mcrypt_enc_get_block_size(pm->td)); 844} 845/* }}} */ 846 847/* {{{ proto int mcrypt_enc_get_key_size(resource td) 848 Returns the maximum supported key size in bytes of the algorithm specified by the descriptor td */ 849PHP_FUNCTION(mcrypt_enc_get_key_size) 850{ 851 MCRYPT_GET_TD_ARG 852 RETURN_LONG(mcrypt_enc_get_key_size(pm->td)); 853} 854/* }}} */ 855 856/* {{{ proto int mcrypt_enc_get_iv_size(resource td) 857 Returns the size of the IV in bytes of the algorithm specified by the descriptor td */ 858PHP_FUNCTION(mcrypt_enc_get_iv_size) 859{ 860 MCRYPT_GET_TD_ARG 861 RETURN_LONG(mcrypt_enc_get_iv_size(pm->td)); 862} 863/* }}} */ 864 865/* {{{ proto string mcrypt_enc_get_algorithms_name(resource td) 866 Returns the name of the algorithm specified by the descriptor td */ 867PHP_FUNCTION(mcrypt_enc_get_algorithms_name) 868{ 869 char *name; 870 MCRYPT_GET_TD_ARG 871 872 name = mcrypt_enc_get_algorithms_name(pm->td); 873 RETVAL_STRING(name, 1); 874 mcrypt_free(name); 875} 876/* }}} */ 877 878/* {{{ proto string mcrypt_enc_get_modes_name(resource td) 879 Returns the name of the mode specified by the descriptor td */ 880PHP_FUNCTION(mcrypt_enc_get_modes_name) 881{ 882 char *name; 883 MCRYPT_GET_TD_ARG 884 885 name = mcrypt_enc_get_modes_name(pm->td); 886 RETVAL_STRING(name, 1); 887 mcrypt_free(name); 888} 889/* }}} */ 890 891/* {{{ proto bool mcrypt_module_self_test(string algorithm [, string lib_dir]) 892 Does a self test of the module "module" */ 893PHP_FUNCTION(mcrypt_module_self_test) 894{ 895 MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir); 896 897 if (mcrypt_module_self_test(module, dir) == 0) { 898 RETURN_TRUE; 899 } else { 900 RETURN_FALSE; 901 } 902} 903/* }}} */ 904 905/* {{{ proto bool mcrypt_module_is_block_algorithm_mode(string mode [, string lib_dir]) 906 Returns TRUE if the mode is for use with block algorithms */ 907PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode) 908{ 909 MCRYPT_GET_MODE_DIR_ARGS(modes_dir) 910 911 if (mcrypt_module_is_block_algorithm_mode(module, dir) == 1) { 912 RETURN_TRUE; 913 } else { 914 RETURN_FALSE; 915 } 916} 917/* }}} */ 918 919/* {{{ proto bool mcrypt_module_is_block_algorithm(string algorithm [, string lib_dir]) 920 Returns TRUE if the algorithm is a block algorithm */ 921PHP_FUNCTION(mcrypt_module_is_block_algorithm) 922{ 923 MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) 924 925 if (mcrypt_module_is_block_algorithm(module, dir) == 1) { 926 RETURN_TRUE; 927 } else { 928 RETURN_FALSE; 929 } 930} 931/* }}} */ 932 933/* {{{ proto bool mcrypt_module_is_block_mode(string mode [, string lib_dir]) 934 Returns TRUE if the mode outputs blocks of bytes */ 935PHP_FUNCTION(mcrypt_module_is_block_mode) 936{ 937 MCRYPT_GET_MODE_DIR_ARGS(modes_dir) 938 939 if (mcrypt_module_is_block_mode(module, dir) == 1) { 940 RETURN_TRUE; 941 } else { 942 RETURN_FALSE; 943 } 944} 945/* }}} */ 946 947/* {{{ proto int mcrypt_module_get_algo_block_size(string algorithm [, string lib_dir]) 948 Returns the block size of the algorithm */ 949PHP_FUNCTION(mcrypt_module_get_algo_block_size) 950{ 951 MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) 952 953 RETURN_LONG(mcrypt_module_get_algo_block_size(module, dir)); 954} 955/* }}} */ 956 957/* {{{ proto int mcrypt_module_get_algo_key_size(string algorithm [, string lib_dir]) 958 Returns the maximum supported key size of the algorithm */ 959PHP_FUNCTION(mcrypt_module_get_algo_key_size) 960{ 961 MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir); 962 963 RETURN_LONG(mcrypt_module_get_algo_key_size(module, dir)); 964} 965/* }}} */ 966 967/* {{{ proto array mcrypt_module_get_supported_key_sizes(string algorithm [, string lib_dir]) 968 This function decrypts the crypttext */ 969PHP_FUNCTION(mcrypt_module_get_supported_key_sizes) 970{ 971 int i, count = 0; 972 int *key_sizes; 973 974 MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) 975 array_init(return_value); 976 977 key_sizes = mcrypt_module_get_algo_supported_key_sizes(module, dir, &count); 978 979 for (i = 0; i < count; i++) { 980 add_index_long(return_value, i, key_sizes[i]); 981 } 982 mcrypt_free(key_sizes); 983} 984/* }}} */ 985 986/* {{{ proto array mcrypt_list_algorithms([string lib_dir]) 987 List all algorithms in "module_dir" */ 988PHP_FUNCTION(mcrypt_list_algorithms) 989{ 990 char **modules; 991 char *lib_dir = MCG(algorithms_dir); 992 int lib_dir_len; 993 int i, count; 994 995 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", 996 &lib_dir, &lib_dir_len) == FAILURE) { 997 return; 998 } 999 1000 array_init(return_value); 1001 modules = mcrypt_list_algorithms(lib_dir, &count); 1002 1003 if (count == 0) { 1004 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No algorithms found in module dir"); 1005 } 1006 for (i = 0; i < count; i++) { 1007 add_index_string(return_value, i, modules[i], 1); 1008 } 1009 mcrypt_free_p(modules, count); 1010} 1011/* }}} */ 1012 1013/* {{{ proto array mcrypt_list_modes([string lib_dir]) 1014 List all modes "module_dir" */ 1015PHP_FUNCTION(mcrypt_list_modes) 1016{ 1017 char **modules; 1018 char *lib_dir = MCG(modes_dir); 1019 int lib_dir_len; 1020 int i, count; 1021 1022 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", 1023 &lib_dir, &lib_dir_len) == FAILURE) { 1024 return; 1025 } 1026 1027 array_init(return_value); 1028 modules = mcrypt_list_modes(lib_dir, &count); 1029 1030 if (count == 0) { 1031 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No modes found in module dir"); 1032 } 1033 for (i = 0; i < count; i++) { 1034 add_index_string(return_value, i, modules[i], 1); 1035 } 1036 mcrypt_free_p(modules, count); 1037} 1038/* }}} */ 1039 1040/* {{{ proto int mcrypt_get_key_size(string cipher, string module) 1041 Get the key size of cipher */ 1042PHP_FUNCTION(mcrypt_get_key_size) 1043{ 1044 char *cipher; 1045 char *module; 1046 int cipher_len, module_len; 1047 char *cipher_dir_string; 1048 char *module_dir_string; 1049 MCRYPT td; 1050 1051 MCRYPT_GET_INI 1052 1053 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", 1054 &cipher, &cipher_len, &module, &module_len) == FAILURE) { 1055 return; 1056 } 1057 1058 td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 1059 if (td != MCRYPT_FAILED) { 1060 RETVAL_LONG(mcrypt_enc_get_key_size(td)); 1061 mcrypt_module_close(td); 1062 } else { 1063 php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED); 1064 RETURN_FALSE; 1065 } 1066} 1067/* }}} */ 1068 1069/* {{{ proto int mcrypt_get_block_size(string cipher, string module) 1070 Get the key size of cipher */ 1071PHP_FUNCTION(mcrypt_get_block_size) 1072{ 1073 char *cipher; 1074 char *module; 1075 int cipher_len, module_len; 1076 char *cipher_dir_string; 1077 char *module_dir_string; 1078 MCRYPT td; 1079 1080 MCRYPT_GET_INI 1081 1082 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", 1083 &cipher, &cipher_len, &module, &module_len) == FAILURE) { 1084 return; 1085 } 1086 1087 td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 1088 if (td != MCRYPT_FAILED) { 1089 RETVAL_LONG(mcrypt_enc_get_block_size(td)); 1090 mcrypt_module_close(td); 1091 } else { 1092 php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED); 1093 RETURN_FALSE; 1094 } 1095} 1096/* }}} */ 1097 1098/* {{{ proto int mcrypt_get_iv_size(string cipher, string module) 1099 Get the IV size of cipher (Usually the same as the blocksize) */ 1100PHP_FUNCTION(mcrypt_get_iv_size) 1101{ 1102 char *cipher; 1103 char *module; 1104 int cipher_len, module_len; 1105 char *cipher_dir_string; 1106 char *module_dir_string; 1107 MCRYPT td; 1108 1109 MCRYPT_GET_INI 1110 1111 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", 1112 &cipher, &cipher_len, &module, &module_len) == FAILURE) { 1113 return; 1114 } 1115 1116 td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 1117 if (td != MCRYPT_FAILED) { 1118 RETVAL_LONG(mcrypt_enc_get_iv_size(td)); 1119 mcrypt_module_close(td); 1120 } else { 1121 php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED); 1122 RETURN_FALSE; 1123 } 1124} 1125/* }}} */ 1126 1127/* {{{ proto string mcrypt_get_cipher_name(string cipher) 1128 Get the key size of cipher */ 1129PHP_FUNCTION(mcrypt_get_cipher_name) 1130{ 1131 char *cipher_dir_string; 1132 char *module_dir_string; 1133 char *cipher_name; 1134 char *cipher; 1135 int cipher_len; 1136 MCRYPT td; 1137 1138 MCRYPT_GET_INI 1139 1140 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", 1141 &cipher, &cipher_len) == FAILURE) { 1142 return; 1143 } 1144 1145 /* The code below is actually not very nice, but I didn't see a better 1146 * method */ 1147 td = mcrypt_module_open(cipher, cipher_dir_string, "ecb", module_dir_string); 1148 if (td != MCRYPT_FAILED) { 1149 cipher_name = mcrypt_enc_get_algorithms_name(td); 1150 mcrypt_module_close(td); 1151 RETVAL_STRING(cipher_name,1); 1152 mcrypt_free(cipher_name); 1153 } else { 1154 td = mcrypt_module_open(cipher, cipher_dir_string, "stream", module_dir_string); 1155 if (td != MCRYPT_FAILED) { 1156 cipher_name = mcrypt_enc_get_algorithms_name(td); 1157 mcrypt_module_close(td); 1158 RETVAL_STRING(cipher_name,1); 1159 mcrypt_free(cipher_name); 1160 } else { 1161 php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED); 1162 RETURN_FALSE; 1163 } 1164 } 1165} 1166/* }}} */ 1167 1168static 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) /* {{{ */ 1169{ 1170 char *cipher_dir_string; 1171 char *module_dir_string; 1172 int block_size, max_key_length, use_key_length, i, count, iv_size; 1173 unsigned long int data_size; 1174 int *key_length_sizes; 1175 char *key_s = NULL, *iv_s; 1176 char *data_s; 1177 MCRYPT td; 1178 1179 MCRYPT_GET_INI 1180 1181 td = mcrypt_module_open(cipher, cipher_dir_string, mode, module_dir_string); 1182 if (td == MCRYPT_FAILED) { 1183 php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED); 1184 RETURN_FALSE; 1185 } 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)); 1214 } 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 } 1235 } 1236 1237 /* Check blocksize */ 1238 if (mcrypt_enc_is_block_mode(td) == 1) { /* It's a block algorithm */ 1239 block_size = mcrypt_enc_get_block_size(td); 1240 data_size = (((data_len - 1) / block_size) + 1) * block_size; 1241 data_s = emalloc(data_size); 1242 memset(data_s, 0, data_size); 1243 memcpy(data_s, data, data_len); 1244 } else { /* It's not a block algorithm */ 1245 data_size = data_len; 1246 data_s = emalloc(data_size); 1247 memset(data_s, 0, data_size); 1248 memcpy(data_s, data, data_len); 1249 } 1250 1251 if (mcrypt_generic_init(td, key_s, use_key_length, iv_s) < 0) { 1252 php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Mcrypt initialisation failed"); 1253 RETURN_FALSE; 1254 } 1255 if (dencrypt == MCRYPT_ENCRYPT) { 1256 mcrypt_generic(td, data_s, data_size); 1257 } else { 1258 mdecrypt_generic(td, data_s, data_size); 1259 } 1260 1261 RETVAL_STRINGL(data_s, data_size, 1); 1262 1263 /* freeing vars */ 1264 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); 1272} 1273/* }}} */ 1274 1275/* {{{ proto string mcrypt_encrypt(string cipher, string key, string data, string mode, string iv) 1276 OFB crypt/decrypt data using key key with cipher cipher starting with iv */ 1277PHP_FUNCTION(mcrypt_encrypt) 1278{ 1279 zval **mode; 1280 char *cipher, *key, *data, *iv = NULL; 1281 int cipher_len, key_len, data_len, iv_len = 0; 1282 1283 MCRYPT_GET_CRYPT_ARGS 1284 1285 convert_to_string_ex(mode); 1286 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); 1288} 1289/* }}} */ 1290 1291/* {{{ proto string mcrypt_decrypt(string cipher, string key, string data, string mode, string iv) 1292 OFB crypt/decrypt data using key key with cipher cipher starting with iv */ 1293PHP_FUNCTION(mcrypt_decrypt) 1294{ 1295 zval **mode; 1296 char *cipher, *key, *data, *iv = NULL; 1297 int cipher_len, key_len, data_len, iv_len = 0; 1298 1299 MCRYPT_GET_CRYPT_ARGS 1300 1301 convert_to_string_ex(mode); 1302 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); 1304} 1305/* }}} */ 1306 1307/* {{{ proto string mcrypt_ecb(int cipher, string key, string data, int mode, string iv) 1308 ECB crypt/decrypt data using key key with cipher cipher starting with iv */ 1309PHP_FUNCTION(mcrypt_ecb) 1310{ 1311 zval **mode; 1312 char *cipher, *key, *data, *iv = NULL; 1313 int cipher_len, key_len, data_len, iv_len = 0; 1314 1315 MCRYPT_GET_CRYPT_ARGS 1316 1317 convert_to_long_ex(mode); 1318 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); 1320} 1321/* }}} */ 1322 1323/* {{{ proto string mcrypt_cbc(int cipher, string key, string data, int mode, string iv) 1324 CBC crypt/decrypt data using key key with cipher cipher starting with iv */ 1325PHP_FUNCTION(mcrypt_cbc) 1326{ 1327 zval **mode; 1328 char *cipher, *key, *data, *iv = NULL; 1329 int cipher_len, key_len, data_len, iv_len = 0; 1330 1331 MCRYPT_GET_CRYPT_ARGS 1332 1333 convert_to_long_ex(mode); 1334 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); 1336} 1337/* }}} */ 1338 1339/* {{{ proto string mcrypt_cfb(int cipher, string key, string data, int mode, string iv) 1340 CFB crypt/decrypt data using key key with cipher cipher starting with iv */ 1341PHP_FUNCTION(mcrypt_cfb) 1342{ 1343 zval **mode; 1344 char *cipher, *key, *data, *iv = NULL; 1345 int cipher_len, key_len, data_len, iv_len = 0; 1346 1347 MCRYPT_GET_CRYPT_ARGS 1348 1349 convert_to_long_ex(mode); 1350 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); 1352} 1353/* }}} */ 1354 1355/* {{{ proto string mcrypt_ofb(int cipher, string key, string data, int mode, string iv) 1356 OFB crypt/decrypt data using key key with cipher cipher starting with iv */ 1357PHP_FUNCTION(mcrypt_ofb) 1358{ 1359 zval **mode; 1360 char *cipher, *key, *data, *iv = NULL; 1361 int cipher_len, key_len, data_len, iv_len = 0; 1362 1363 MCRYPT_GET_CRYPT_ARGS 1364 1365 convert_to_long_ex(mode); 1366 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); 1368} 1369/* }}} */ 1370 1371/* {{{ proto string mcrypt_create_iv(int size, int source) 1372 Create an initialization vector (IV) */ 1373PHP_FUNCTION(mcrypt_create_iv) 1374{ 1375 char *iv; 1376 long source = RANDOM; 1377 long size; 1378 int n = 0; 1379 1380 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &size, &source) == FAILURE) { 1381 return; 1382 } 1383 1384 if (size <= 0 || size >= INT_MAX) { 1385 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create an IV with a size of less than 1 or greater than %d", INT_MAX); 1386 RETURN_FALSE; 1387 } 1388 1389 iv = ecalloc(size + 1, 1); 1390 1391 if (source == RANDOM || source == URANDOM) { 1392#if PHP_WIN32 1393 /* random/urandom equivalent on Windows */ 1394 BYTE *iv_b = (BYTE *) iv; 1395 if (php_win32_get_random_bytes(iv_b, (size_t) size) == FAILURE){ 1396 efree(iv); 1397 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not gather sufficient random data"); 1398 RETURN_FALSE; 1399 } 1400 n = size; 1401#else 1402 int fd; 1403 size_t read_bytes = 0; 1404 1405 fd = open(source == RANDOM ? "/dev/random" : "/dev/urandom", O_RDONLY); 1406 if (fd < 0) { 1407 efree(iv); 1408 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open source device"); 1409 RETURN_FALSE; 1410 } 1411 while (read_bytes < size) { 1412 n = read(fd, iv + read_bytes, size - read_bytes); 1413 if (n < 0) { 1414 break; 1415 } 1416 read_bytes += n; 1417 } 1418 n = read_bytes; 1419 close(fd); 1420 if (n < size) { 1421 efree(iv); 1422 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not gather sufficient random data"); 1423 RETURN_FALSE; 1424 } 1425#endif 1426 } else { 1427 n = size; 1428 while (size) { 1429 iv[--size] = (char) (255.0 * php_rand(TSRMLS_C) / RAND_MAX); 1430 } 1431 } 1432 RETURN_STRINGL(iv, n, 0); 1433} 1434/* }}} */ 1435 1436#endif 1437 1438/* 1439 * Local variables: 1440 * tab-width: 4 1441 * c-basic-offset: 4 1442 * End: 1443 * vim600: sw=4 ts=4 fdm=marker 1444 * vim<600: sw=4 ts=4 1445 */ 1446