Return to mcrypt.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / mcrypt |
1.1 ! misho 1: /* ! 2: +----------------------------------------------------------------------+ ! 3: | PHP Version 5 | ! 4: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 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: mcrypt.c 321634 2012-01-01 13:15:04Z felipe $ */ ! 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: ! 45: static int le_mcrypt; ! 46: ! 47: typedef struct _php_mcrypt { ! 48: MCRYPT td; ! 49: zend_bool init; ! 50: } php_mcrypt; ! 51: ! 52: /* {{{ arginfo */ ! 53: ZEND_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) ! 58: ZEND_END_ARG_INFO() ! 59: ! 60: ZEND_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) ! 64: ZEND_END_ARG_INFO() ! 65: ! 66: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic, 0, 0, 2) ! 67: ZEND_ARG_INFO(0, td) ! 68: ZEND_ARG_INFO(0, data) ! 69: ZEND_END_ARG_INFO() ! 70: ! 71: ZEND_BEGIN_ARG_INFO_EX(arginfo_mdecrypt_generic, 0, 0, 2) ! 72: ZEND_ARG_INFO(0, td) ! 73: ZEND_ARG_INFO(0, data) ! 74: ZEND_END_ARG_INFO() ! 75: ! 76: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_supported_key_sizes, 0, 0, 1) ! 77: ZEND_ARG_INFO(0, td) ! 78: ZEND_END_ARG_INFO() ! 79: ! 80: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_self_test, 0, 0, 1) ! 81: ZEND_ARG_INFO(0, td) ! 82: ZEND_END_ARG_INFO() ! 83: ! 84: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_close, 0, 0, 1) ! 85: ZEND_ARG_INFO(0, td) ! 86: ZEND_END_ARG_INFO() ! 87: ! 88: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic_deinit, 0, 0, 1) ! 89: ZEND_ARG_INFO(0, td) ! 90: ZEND_END_ARG_INFO() ! 91: ! 92: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_algorithm_mode, 0, 0, 1) ! 93: ZEND_ARG_INFO(0, td) ! 94: ZEND_END_ARG_INFO() ! 95: ! 96: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_algorithm, 0, 0, 1) ! 97: ZEND_ARG_INFO(0, td) ! 98: ZEND_END_ARG_INFO() ! 99: ! 100: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_mode, 0, 0, 1) ! 101: ZEND_ARG_INFO(0, td) ! 102: ZEND_END_ARG_INFO() ! 103: ! 104: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_block_size, 0, 0, 1) ! 105: ZEND_ARG_INFO(0, td) ! 106: ZEND_END_ARG_INFO() ! 107: ! 108: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_key_size, 0, 0, 1) ! 109: ZEND_ARG_INFO(0, td) ! 110: ZEND_END_ARG_INFO() ! 111: ! 112: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_iv_size, 0, 0, 1) ! 113: ZEND_ARG_INFO(0, td) ! 114: ZEND_END_ARG_INFO() ! 115: ! 116: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_algorithms_name, 0, 0, 1) ! 117: ZEND_ARG_INFO(0, td) ! 118: ZEND_END_ARG_INFO() ! 119: ! 120: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_modes_name, 0, 0, 1) ! 121: ZEND_ARG_INFO(0, td) ! 122: ZEND_END_ARG_INFO() ! 123: ! 124: ZEND_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) ! 127: ZEND_END_ARG_INFO() ! 128: ! 129: ZEND_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) ! 132: ZEND_END_ARG_INFO() ! 133: ! 134: ZEND_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) ! 137: ZEND_END_ARG_INFO() ! 138: ! 139: ZEND_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) ! 142: ZEND_END_ARG_INFO() ! 143: ! 144: ZEND_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) ! 147: ZEND_END_ARG_INFO() ! 148: ! 149: ZEND_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) ! 152: ZEND_END_ARG_INFO() ! 153: ! 154: ZEND_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) ! 157: ZEND_END_ARG_INFO() ! 158: ! 159: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_list_algorithms, 0, 0, 0) ! 160: ZEND_ARG_INFO(0, lib_dir) ! 161: ZEND_END_ARG_INFO() ! 162: ! 163: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_list_modes, 0, 0, 0) ! 164: ZEND_ARG_INFO(0, lib_dir) ! 165: ZEND_END_ARG_INFO() ! 166: ! 167: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_key_size, 0, 0, 2) ! 168: ZEND_ARG_INFO(0, cipher) ! 169: ZEND_ARG_INFO(0, module) ! 170: ZEND_END_ARG_INFO() ! 171: ! 172: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_block_size, 0, 0, 2) ! 173: ZEND_ARG_INFO(0, cipher) ! 174: ZEND_ARG_INFO(0, module) ! 175: ZEND_END_ARG_INFO() ! 176: ! 177: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_iv_size, 0, 0, 2) ! 178: ZEND_ARG_INFO(0, cipher) ! 179: ZEND_ARG_INFO(0, module) ! 180: ZEND_END_ARG_INFO() ! 181: ! 182: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_cipher_name, 0, 0, 1) ! 183: ZEND_ARG_INFO(0, cipher) ! 184: ZEND_END_ARG_INFO() ! 185: ! 186: ZEND_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) ! 192: ZEND_END_ARG_INFO() ! 193: ! 194: ZEND_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) ! 200: ZEND_END_ARG_INFO() ! 201: ! 202: ZEND_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) ! 208: ZEND_END_ARG_INFO() ! 209: ! 210: ZEND_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) ! 216: ZEND_END_ARG_INFO() ! 217: ! 218: ZEND_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) ! 224: ZEND_END_ARG_INFO() ! 225: ! 226: ZEND_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) ! 232: ZEND_END_ARG_INFO() ! 233: ! 234: ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_create_iv, 0, 0, 2) ! 235: ZEND_ARG_INFO(0, size) ! 236: ZEND_ARG_INFO(0, source) ! 237: ZEND_END_ARG_INFO() ! 238: /* }}} */ ! 239: ! 240: const zend_function_entry mcrypt_functions[] = { /* {{{ */ ! 241: PHP_FE(mcrypt_ecb, arginfo_mcrypt_ecb) ! 242: PHP_FE(mcrypt_cbc, arginfo_mcrypt_cbc) ! 243: PHP_FE(mcrypt_cfb, arginfo_mcrypt_cfb) ! 244: PHP_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: ! 287: static PHP_MINFO_FUNCTION(mcrypt); ! 288: static PHP_MINIT_FUNCTION(mcrypt); ! 289: static PHP_MSHUTDOWN_FUNCTION(mcrypt); ! 290: ! 291: ZEND_DECLARE_MODULE_GLOBALS(mcrypt) ! 292: ! 293: zend_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 ! 309: ZEND_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: ! 402: PHP_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) ! 405: PHP_INI_END() ! 406: ! 407: static 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: ! 419: static 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: ! 480: static 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: ! 492: PHP_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: ! 539: typedef 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 */ ! 547: PHP_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 */ ! 583: PHP_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 */ ! 655: PHP_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 */ ! 700: PHP_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 */ ! 744: PHP_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 */ ! 764: PHP_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 */ ! 773: PHP_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 */ ! 783: PHP_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 */ ! 798: PHP_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 */ ! 812: PHP_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 */ ! 826: PHP_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 */ ! 840: PHP_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 */ ! 849: PHP_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 */ ! 858: PHP_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 */ ! 867: PHP_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 */ ! 880: PHP_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" */ ! 893: PHP_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 */ ! 907: PHP_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 */ ! 921: PHP_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 */ ! 935: PHP_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 */ ! 949: PHP_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 */ ! 959: PHP_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 */ ! 969: PHP_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" */ ! 988: PHP_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" */ ! 1015: PHP_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 */ ! 1042: PHP_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 */ ! 1071: PHP_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) */ ! 1100: PHP_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 */ ! 1129: PHP_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: ! 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) /* {{{ */ ! 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 */ ! 1277: PHP_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 */ ! 1293: PHP_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 */ ! 1309: PHP_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 */ ! 1325: PHP_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 */ ! 1341: PHP_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 */ ! 1357: PHP_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) */ ! 1373: PHP_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: */