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
  44. PHP_FUNCTION
  45. PHP_FUNCTION
  46. PHP_FUNCTION
  47. PHP_FUNCTION

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

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