root/ext/mcrypt/mcrypt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHP_INI_BEGIN
  2. PHP_GINIT_FUNCTION
  3. PHP_GSHUTDOWN_FUNCTION
  4. PHP_MINIT_FUNCTION
  5. PHP_MSHUTDOWN_FUNCTION
  6. PHP_MINFO_FUNCTION
  7. PHP_FUNCTION
  8. PHP_FUNCTION
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. PHP_FUNCTION
  12. PHP_FUNCTION
  13. PHP_FUNCTION
  14. PHP_FUNCTION
  15. PHP_FUNCTION
  16. PHP_FUNCTION
  17. PHP_FUNCTION
  18. PHP_FUNCTION
  19. PHP_FUNCTION
  20. PHP_FUNCTION
  21. PHP_FUNCTION
  22. PHP_FUNCTION
  23. PHP_FUNCTION
  24. PHP_FUNCTION
  25. PHP_FUNCTION
  26. PHP_FUNCTION
  27. PHP_FUNCTION
  28. PHP_FUNCTION
  29. PHP_FUNCTION
  30. PHP_FUNCTION
  31. PHP_FUNCTION
  32. PHP_FUNCTION
  33. PHP_FUNCTION
  34. PHP_FUNCTION
  35. PHP_FUNCTION
  36. php_mcrypt_get_key_size_str
  37. php_mcrypt_is_valid_key_size
  38. php_mcrypt_ensure_valid_key_size
  39. php_mcrypt_ensure_valid_iv
  40. php_mcrypt_do_crypt
  41. PHP_FUNCTION
  42. PHP_FUNCTION
  43. PHP_FUNCTION

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

/* [<][>][^][v][top][bottom][index][help] */