Annotation of embedaddon/php/ext/mcrypt/mcrypt.c, revision 1.1
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: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>