Back to index

php5  5.3.10
mcrypt.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Sascha Schumann <sascha@schumann.cx>                        |
00016    |          Derick Rethans <derick@derickrethans.nl>                    |
00017    +----------------------------------------------------------------------+
00018  */
00019 /* $Id: mcrypt.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 
00025 #include "php.h"
00026 
00027 #if HAVE_LIBMCRYPT
00028 
00029 #if PHP_WIN32
00030 # include "win32/winutil.h"
00031 #endif
00032 
00033 #include "php_mcrypt.h"
00034 #include "fcntl.h"
00035 
00036 #define NON_FREE
00037 #define MCRYPT2
00038 #include "mcrypt.h"
00039 #include "php_ini.h"
00040 #include "php_globals.h"
00041 #include "ext/standard/info.h"
00042 #include "ext/standard/php_rand.h"
00043 #include "php_mcrypt_filter.h"
00044 
00045 static int le_mcrypt;
00046 
00047 typedef struct _php_mcrypt { 
00048        MCRYPT td;
00049        zend_bool init;
00050 } php_mcrypt;
00051 
00052 /* {{{ arginfo */
00053 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_open, 0, 0, 4)
00054        ZEND_ARG_INFO(0, cipher)
00055        ZEND_ARG_INFO(0, cipher_directory)
00056        ZEND_ARG_INFO(0, mode)
00057        ZEND_ARG_INFO(0, mode_directory)
00058 ZEND_END_ARG_INFO()
00059 
00060 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic_init, 0, 0, 3)
00061        ZEND_ARG_INFO(0, td)
00062        ZEND_ARG_INFO(0, key)
00063        ZEND_ARG_INFO(0, iv)
00064 ZEND_END_ARG_INFO()
00065 
00066 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic, 0, 0, 2)
00067        ZEND_ARG_INFO(0, td)
00068        ZEND_ARG_INFO(0, data)
00069 ZEND_END_ARG_INFO()
00070 
00071 ZEND_BEGIN_ARG_INFO_EX(arginfo_mdecrypt_generic, 0, 0, 2)
00072        ZEND_ARG_INFO(0, td)
00073        ZEND_ARG_INFO(0, data)
00074 ZEND_END_ARG_INFO()
00075 
00076 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_supported_key_sizes, 0, 0, 1)
00077        ZEND_ARG_INFO(0, td)
00078 ZEND_END_ARG_INFO()
00079 
00080 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_self_test, 0, 0, 1)
00081        ZEND_ARG_INFO(0, td)
00082 ZEND_END_ARG_INFO()
00083 
00084 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_close, 0, 0, 1)
00085        ZEND_ARG_INFO(0, td)
00086 ZEND_END_ARG_INFO()
00087 
00088 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_generic_deinit, 0, 0, 1)
00089        ZEND_ARG_INFO(0, td)
00090 ZEND_END_ARG_INFO()
00091 
00092 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_algorithm_mode, 0, 0, 1)
00093        ZEND_ARG_INFO(0, td)
00094 ZEND_END_ARG_INFO()
00095 
00096 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_algorithm, 0, 0, 1)
00097        ZEND_ARG_INFO(0, td)
00098 ZEND_END_ARG_INFO()
00099 
00100 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_is_block_mode, 0, 0, 1)
00101        ZEND_ARG_INFO(0, td)
00102 ZEND_END_ARG_INFO()
00103 
00104 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_block_size, 0, 0, 1)
00105        ZEND_ARG_INFO(0, td)
00106 ZEND_END_ARG_INFO()
00107 
00108 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_key_size, 0, 0, 1)
00109        ZEND_ARG_INFO(0, td)
00110 ZEND_END_ARG_INFO()
00111 
00112 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_iv_size, 0, 0, 1)
00113        ZEND_ARG_INFO(0, td)
00114 ZEND_END_ARG_INFO()
00115 
00116 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_algorithms_name, 0, 0, 1)
00117        ZEND_ARG_INFO(0, td)
00118 ZEND_END_ARG_INFO()
00119 
00120 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_enc_get_modes_name, 0, 0, 1)
00121        ZEND_ARG_INFO(0, td)
00122 ZEND_END_ARG_INFO()
00123 
00124 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_self_test, 0, 0, 1)
00125        ZEND_ARG_INFO(0, algorithm)
00126        ZEND_ARG_INFO(0, lib_dir)
00127 ZEND_END_ARG_INFO()
00128 
00129 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_is_block_algorithm_mode, 0, 0, 1)
00130        ZEND_ARG_INFO(0, mode)
00131        ZEND_ARG_INFO(0, lib_dir)
00132 ZEND_END_ARG_INFO()
00133 
00134 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_is_block_algorithm, 0, 0, 1)
00135        ZEND_ARG_INFO(0, algorithm)
00136        ZEND_ARG_INFO(0, lib_dir)
00137 ZEND_END_ARG_INFO()
00138 
00139 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_is_block_mode, 0, 0, 1)
00140        ZEND_ARG_INFO(0, mode)
00141        ZEND_ARG_INFO(0, lib_dir)
00142 ZEND_END_ARG_INFO()
00143 
00144 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_get_algo_block_size, 0, 0, 1)
00145        ZEND_ARG_INFO(0, algorithm)
00146        ZEND_ARG_INFO(0, lib_dir)
00147 ZEND_END_ARG_INFO()
00148 
00149 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_get_algo_key_size, 0, 0, 1)
00150        ZEND_ARG_INFO(0, algorithm)
00151        ZEND_ARG_INFO(0, lib_dir)
00152 ZEND_END_ARG_INFO()
00153 
00154 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_module_get_supported_key_sizes, 0, 0, 1)
00155        ZEND_ARG_INFO(0, algorithm)
00156        ZEND_ARG_INFO(0, lib_dir)
00157 ZEND_END_ARG_INFO()
00158 
00159 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_list_algorithms, 0, 0, 0)
00160        ZEND_ARG_INFO(0, lib_dir)
00161 ZEND_END_ARG_INFO()
00162 
00163 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_list_modes, 0, 0, 0)
00164        ZEND_ARG_INFO(0, lib_dir)
00165 ZEND_END_ARG_INFO()
00166 
00167 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_key_size, 0, 0, 2)
00168        ZEND_ARG_INFO(0, cipher)
00169        ZEND_ARG_INFO(0, module)
00170 ZEND_END_ARG_INFO()
00171 
00172 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_block_size, 0, 0, 2)
00173        ZEND_ARG_INFO(0, cipher)
00174        ZEND_ARG_INFO(0, module)
00175 ZEND_END_ARG_INFO()
00176 
00177 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_iv_size, 0, 0, 2)
00178        ZEND_ARG_INFO(0, cipher)
00179        ZEND_ARG_INFO(0, module)
00180 ZEND_END_ARG_INFO()
00181 
00182 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_get_cipher_name, 0, 0, 1)
00183        ZEND_ARG_INFO(0, cipher)
00184 ZEND_END_ARG_INFO()
00185 
00186 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_encrypt, 0, 0, 5)
00187        ZEND_ARG_INFO(0, cipher)
00188        ZEND_ARG_INFO(0, key)
00189        ZEND_ARG_INFO(0, data)
00190        ZEND_ARG_INFO(0, mode)
00191        ZEND_ARG_INFO(0, iv)
00192 ZEND_END_ARG_INFO()
00193 
00194 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_decrypt, 0, 0, 5)
00195        ZEND_ARG_INFO(0, cipher)
00196        ZEND_ARG_INFO(0, key)
00197        ZEND_ARG_INFO(0, data)
00198        ZEND_ARG_INFO(0, mode)
00199        ZEND_ARG_INFO(0, iv)
00200 ZEND_END_ARG_INFO()
00201 
00202 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_ecb, 0, 0, 5)
00203        ZEND_ARG_INFO(0, cipher)
00204        ZEND_ARG_INFO(0, key)
00205        ZEND_ARG_INFO(0, data)
00206        ZEND_ARG_INFO(0, mode)
00207        ZEND_ARG_INFO(0, iv)
00208 ZEND_END_ARG_INFO()
00209 
00210 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_cbc, 0, 0, 5)
00211        ZEND_ARG_INFO(0, cipher)
00212        ZEND_ARG_INFO(0, key)
00213        ZEND_ARG_INFO(0, data)
00214        ZEND_ARG_INFO(0, mode)
00215        ZEND_ARG_INFO(0, iv)
00216 ZEND_END_ARG_INFO()
00217 
00218 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_cfb, 0, 0, 5)
00219        ZEND_ARG_INFO(0, cipher)
00220        ZEND_ARG_INFO(0, key)
00221        ZEND_ARG_INFO(0, data)
00222        ZEND_ARG_INFO(0, mode)
00223        ZEND_ARG_INFO(0, iv)
00224 ZEND_END_ARG_INFO()
00225 
00226 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_ofb, 0, 0, 5)
00227        ZEND_ARG_INFO(0, cipher)
00228        ZEND_ARG_INFO(0, key)
00229        ZEND_ARG_INFO(0, data)
00230        ZEND_ARG_INFO(0, mode)
00231        ZEND_ARG_INFO(0, iv)
00232 ZEND_END_ARG_INFO()
00233 
00234 ZEND_BEGIN_ARG_INFO_EX(arginfo_mcrypt_create_iv, 0, 0, 2)
00235        ZEND_ARG_INFO(0, size)
00236        ZEND_ARG_INFO(0, source)
00237 ZEND_END_ARG_INFO()
00238 /* }}} */
00239 
00240 const zend_function_entry mcrypt_functions[] = { /* {{{ */
00241        PHP_FE(mcrypt_ecb,                        arginfo_mcrypt_ecb)
00242        PHP_FE(mcrypt_cbc,                        arginfo_mcrypt_cbc)
00243        PHP_FE(mcrypt_cfb,                        arginfo_mcrypt_cfb)
00244        PHP_FE(mcrypt_ofb,                        arginfo_mcrypt_ofb)
00245        PHP_FE(mcrypt_get_key_size,        arginfo_mcrypt_get_key_size)
00246        PHP_FE(mcrypt_get_block_size,      arginfo_mcrypt_get_block_size)
00247        PHP_FE(mcrypt_get_cipher_name,     arginfo_mcrypt_get_cipher_name)
00248        PHP_FE(mcrypt_create_iv,           arginfo_mcrypt_create_iv)
00249 
00250        PHP_FE(mcrypt_list_algorithms,     arginfo_mcrypt_list_algorithms)
00251        PHP_FE(mcrypt_list_modes,          arginfo_mcrypt_list_modes)
00252        PHP_FE(mcrypt_get_iv_size,         arginfo_mcrypt_get_iv_size)
00253        PHP_FE(mcrypt_encrypt,                    arginfo_mcrypt_encrypt)
00254        PHP_FE(mcrypt_decrypt,                    arginfo_mcrypt_decrypt)
00255 
00256        PHP_FE(mcrypt_module_open,         arginfo_mcrypt_module_open)
00257        PHP_FE(mcrypt_generic_init,        arginfo_mcrypt_generic_init)
00258        PHP_FE(mcrypt_generic,                    arginfo_mcrypt_generic)
00259        PHP_FE(mdecrypt_generic,           arginfo_mdecrypt_generic)
00260        PHP_DEP_FALIAS(mcrypt_generic_end, mcrypt_generic_deinit, arginfo_mcrypt_generic_deinit)
00261        PHP_FE(mcrypt_generic_deinit,      arginfo_mcrypt_generic_deinit)
00262 
00263        PHP_FE(mcrypt_enc_self_test,       arginfo_mcrypt_enc_self_test)
00264        PHP_FE(mcrypt_enc_is_block_algorithm_mode, arginfo_mcrypt_enc_is_block_algorithm_mode)
00265        PHP_FE(mcrypt_enc_is_block_algorithm,     arginfo_mcrypt_enc_is_block_algorithm)
00266        PHP_FE(mcrypt_enc_is_block_mode,          arginfo_mcrypt_enc_is_block_mode)
00267        PHP_FE(mcrypt_enc_get_block_size,         arginfo_mcrypt_enc_get_block_size)
00268        PHP_FE(mcrypt_enc_get_key_size,           arginfo_mcrypt_enc_get_key_size)
00269        PHP_FE(mcrypt_enc_get_supported_key_sizes, arginfo_mcrypt_enc_get_supported_key_sizes)
00270        PHP_FE(mcrypt_enc_get_iv_size,                   arginfo_mcrypt_enc_get_iv_size)
00271        PHP_FE(mcrypt_enc_get_algorithms_name,    arginfo_mcrypt_enc_get_algorithms_name)
00272        PHP_FE(mcrypt_enc_get_modes_name,         arginfo_mcrypt_enc_get_modes_name)
00273        PHP_FE(mcrypt_module_self_test,           arginfo_mcrypt_module_self_test)
00274 
00275        PHP_FE(mcrypt_module_is_block_algorithm_mode,    arginfo_mcrypt_module_is_block_algorithm_mode)
00276        PHP_FE(mcrypt_module_is_block_algorithm,         arginfo_mcrypt_module_is_block_algorithm)
00277        PHP_FE(mcrypt_module_is_block_mode,                     arginfo_mcrypt_module_is_block_mode)
00278        PHP_FE(mcrypt_module_get_algo_block_size,               arginfo_mcrypt_module_get_algo_block_size)
00279        PHP_FE(mcrypt_module_get_algo_key_size,          arginfo_mcrypt_module_get_algo_key_size)
00280        PHP_FE(mcrypt_module_get_supported_key_sizes,    arginfo_mcrypt_module_get_supported_key_sizes)
00281 
00282        PHP_FE(mcrypt_module_close,                                    arginfo_mcrypt_module_close)
00283        PHP_FE_END
00284 };
00285 /* }}} */
00286 
00287 static PHP_MINFO_FUNCTION(mcrypt);
00288 static PHP_MINIT_FUNCTION(mcrypt);
00289 static PHP_MSHUTDOWN_FUNCTION(mcrypt);
00290 
00291 ZEND_DECLARE_MODULE_GLOBALS(mcrypt)
00292 
00293 zend_module_entry mcrypt_module_entry = {
00294        STANDARD_MODULE_HEADER,
00295        "mcrypt", 
00296        mcrypt_functions,
00297        PHP_MINIT(mcrypt), PHP_MSHUTDOWN(mcrypt),
00298        NULL, NULL,
00299        PHP_MINFO(mcrypt),
00300        NO_VERSION_YET,
00301        PHP_MODULE_GLOBALS(mcrypt),
00302        NULL,
00303        NULL,
00304        NULL,
00305        STANDARD_MODULE_PROPERTIES_EX
00306 };
00307 
00308 #ifdef COMPILE_DL_MCRYPT
00309 ZEND_GET_MODULE(mcrypt)
00310 #endif
00311 
00312 #define MCRYPT_ARGS2                                                                              \
00313        zval **cipher, **data, **key, **mode;                                        \
00314        int td;                                                                                           \
00315        char *ndata;                                                                               \
00316        size_t bsize;                                                                                     \
00317        size_t nr;                                                                                        \
00318        size_t nsize
00319 
00320 #define MCRYPT_ARGS                                                                        \
00321        MCRYPT_ARGS2;                                                                                     \
00322        zval **iv
00323 
00324 #define MCRYPT_SIZE                                                                 \
00325        bsize = mcrypt_get_block_size(Z_LVAL_PP(cipher));              \
00326        nr = (Z_STRLEN_PP(data) + bsize - 1) / bsize;                  \
00327        nsize = nr * bsize
00328 
00329 #define MCRYPT_CHECK_TD_CPY                                                                \
00330        if (td < 0) {                                                                                     \
00331               php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_FAILED);                                \
00332               RETURN_FALSE;                                                                              \
00333        }                                                                                                        \
00334        ndata = ecalloc(nr, bsize);                                                         \
00335        memcpy(ndata, Z_STRVAL_PP(data), Z_STRLEN_PP(data))
00336 
00337 #define MCRYPT_CHECK_IV                                                                    \
00338        convert_to_string_ex(iv);                                                           \
00339        if (Z_STRLEN_PP(iv) != bsize) {                                              \
00340               php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_IV_WRONG_SIZE);                  \
00341               RETURN_FALSE;                                                                              \
00342        }
00343 
00344 #define MCRYPT_ACTION(x)                                                                   \
00345        if (Z_LVAL_PP(mode) == 0) {                                                         \
00346               mcrypt_##x(td, ndata, nsize);                                                \
00347        } else {                                                                                          \
00348               mdecrypt_##x(td, ndata, nsize);                                       \
00349        }                                                                                                        \
00350        end_mcrypt_##x(td)
00351 
00352 #define MCRYPT_IV_WRONG_SIZE "The IV parameter must be as long as the blocksize"
00353 
00354 #define MCRYPT_ENCRYPT 0
00355 #define MCRYPT_DECRYPT 1
00356 
00357 #define MCRYPT_GET_INI                                                                            \
00358        cipher_dir_string = MCG(algorithms_dir);                              \
00359        module_dir_string = MCG(modes_dir);
00360 
00361 /*
00362  * #warning is not ANSI C
00363  * #warning Invalidate resource if the param count is wrong, or other problems
00364  * #warning occurred during functions.
00365  */
00366 
00367 #define MCRYPT_GET_CRYPT_ARGS                                                                     \
00368        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssZ|s",        \
00369               &cipher, &cipher_len, &key, &key_len, &data, &data_len, &mode, &iv, &iv_len) == FAILURE) { \
00370               return;              \
00371        }
00372 
00373 #define MCRYPT_GET_TD_ARG                                                                  \
00374        zval *mcryptind;                                                                           \
00375        php_mcrypt *pm;                                                                                          \
00376        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mcryptind) == FAILURE) {               \
00377               return;                                                                                                                \
00378        }                                                                                                                                                         \
00379        ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);                      
00380 
00381 #define MCRYPT_GET_MODE_DIR_ARGS(DIRECTORY)                                                       \
00382        char *dir = NULL;                                                   \
00383        int   dir_len;                                                      \
00384        char *module;                                                       \
00385        int   module_len;                                                   \
00386        if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC,               \
00387               "s|s", &module, &module_len, &dir, &dir_len) == FAILURE) {      \
00388               return;                                                         \
00389        }
00390 
00391 #define MCRYPT_OPEN_MODULE_FAILED "Module initialization failed"
00392 
00393 #define MCRYPT_ENTRY2_2_4(a,b) REGISTER_STRING_CONSTANT("MCRYPT_" #a, b, CONST_PERSISTENT)
00394 #define MCRYPT_ENTRY2_4(a) MCRYPT_ENTRY_NAMED(a, a)
00395 
00396 #define PHP_MCRYPT_INIT_CHECK      \
00397        if (!pm->init) {     \
00398               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Operation disallowed prior to mcrypt_generic_init().");     \
00399               RETURN_FALSE; \
00400        }      \
00401 
00402 PHP_INI_BEGIN()
00403        STD_PHP_INI_ENTRY("mcrypt.algorithms_dir", NULL, PHP_INI_ALL, OnUpdateString, algorithms_dir, zend_mcrypt_globals, mcrypt_globals)
00404        STD_PHP_INI_ENTRY("mcrypt.modes_dir",      NULL, PHP_INI_ALL, OnUpdateString, modes_dir, zend_mcrypt_globals, mcrypt_globals)
00405 PHP_INI_END()
00406 
00407 static void php_mcrypt_module_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
00408 {
00409        php_mcrypt *pm = (php_mcrypt *) rsrc->ptr;
00410        if (pm) {     
00411               mcrypt_generic_deinit(pm->td);
00412               mcrypt_module_close(pm->td);
00413               efree(pm);
00414               pm = NULL;
00415        }
00416 }
00417 /* }}} */
00418     
00419 static PHP_MINIT_FUNCTION(mcrypt) /* {{{ */
00420 {
00421        le_mcrypt = zend_register_list_destructors_ex(php_mcrypt_module_dtor, NULL, "mcrypt", module_number);
00422 
00423        /* modes for mcrypt_??? routines */
00424        REGISTER_LONG_CONSTANT("MCRYPT_ENCRYPT", 0, CONST_PERSISTENT);
00425        REGISTER_LONG_CONSTANT("MCRYPT_DECRYPT", 1, CONST_PERSISTENT);
00426 
00427        /* sources for mcrypt_create_iv */
00428        REGISTER_LONG_CONSTANT("MCRYPT_DEV_RANDOM", 0, CONST_PERSISTENT);
00429        REGISTER_LONG_CONSTANT("MCRYPT_DEV_URANDOM", 1, CONST_PERSISTENT);
00430        REGISTER_LONG_CONSTANT("MCRYPT_RAND", 2, CONST_PERSISTENT);
00431 
00432        /* ciphers */
00433        MCRYPT_ENTRY2_2_4(3DES, "tripledes");
00434        MCRYPT_ENTRY2_2_4(ARCFOUR_IV, "arcfour-iv");
00435        MCRYPT_ENTRY2_2_4(ARCFOUR, "arcfour");
00436        MCRYPT_ENTRY2_2_4(BLOWFISH, "blowfish");
00437        MCRYPT_ENTRY2_2_4(BLOWFISH_COMPAT, "blowfish-compat");
00438        MCRYPT_ENTRY2_2_4(CAST_128, "cast-128");
00439        MCRYPT_ENTRY2_2_4(CAST_256, "cast-256");
00440        MCRYPT_ENTRY2_2_4(CRYPT, "crypt");
00441        MCRYPT_ENTRY2_2_4(DES, "des");
00442        MCRYPT_ENTRY2_2_4(ENIGNA, "crypt");
00443        MCRYPT_ENTRY2_2_4(GOST, "gost");
00444        MCRYPT_ENTRY2_2_4(LOKI97, "loki97");
00445        MCRYPT_ENTRY2_2_4(PANAMA, "panama");
00446        MCRYPT_ENTRY2_2_4(RC2, "rc2");
00447        MCRYPT_ENTRY2_2_4(RIJNDAEL_128, "rijndael-128");
00448        MCRYPT_ENTRY2_2_4(RIJNDAEL_192, "rijndael-192");
00449        MCRYPT_ENTRY2_2_4(RIJNDAEL_256, "rijndael-256");
00450        MCRYPT_ENTRY2_2_4(SAFER64, "safer-sk64");
00451        MCRYPT_ENTRY2_2_4(SAFER128, "safer-sk128");
00452        MCRYPT_ENTRY2_2_4(SAFERPLUS, "saferplus");
00453        MCRYPT_ENTRY2_2_4(SERPENT, "serpent");
00454        MCRYPT_ENTRY2_2_4(THREEWAY, "threeway");
00455        MCRYPT_ENTRY2_2_4(TRIPLEDES, "tripledes");
00456        MCRYPT_ENTRY2_2_4(TWOFISH, "twofish");
00457        MCRYPT_ENTRY2_2_4(WAKE, "wake");
00458        MCRYPT_ENTRY2_2_4(XTEA, "xtea");
00459 
00460        MCRYPT_ENTRY2_2_4(IDEA, "idea");
00461        MCRYPT_ENTRY2_2_4(MARS, "mars");
00462        MCRYPT_ENTRY2_2_4(RC6, "rc6");
00463        MCRYPT_ENTRY2_2_4(SKIPJACK, "skipjack");
00464 /* modes */
00465        MCRYPT_ENTRY2_2_4(MODE_CBC, "cbc");
00466        MCRYPT_ENTRY2_2_4(MODE_CFB, "cfb");
00467        MCRYPT_ENTRY2_2_4(MODE_ECB, "ecb");
00468        MCRYPT_ENTRY2_2_4(MODE_NOFB, "nofb");
00469        MCRYPT_ENTRY2_2_4(MODE_OFB, "ofb");
00470        MCRYPT_ENTRY2_2_4(MODE_STREAM, "stream");
00471        REGISTER_INI_ENTRIES();
00472 
00473        php_stream_filter_register_factory("mcrypt.*", &php_mcrypt_filter_factory TSRMLS_CC);
00474        php_stream_filter_register_factory("mdecrypt.*", &php_mcrypt_filter_factory TSRMLS_CC);
00475 
00476        return SUCCESS;
00477 }
00478 /* }}} */
00479 
00480 static PHP_MSHUTDOWN_FUNCTION(mcrypt) /* {{{ */
00481 {
00482        php_stream_filter_unregister_factory("mcrypt.*" TSRMLS_CC);
00483        php_stream_filter_unregister_factory("mdecrypt.*" TSRMLS_CC);
00484 
00485        UNREGISTER_INI_ENTRIES();
00486        return SUCCESS;
00487 }
00488 /* }}} */
00489 
00490 #include "ext/standard/php_smart_str.h"
00491 
00492 PHP_MINFO_FUNCTION(mcrypt) /* {{{ */
00493 {
00494        char **modules;
00495        char mcrypt_api_no[16];
00496        int i, count;
00497        smart_str tmp1 = {0};
00498        smart_str tmp2 = {0};
00499 
00500        modules = mcrypt_list_algorithms(MCG(algorithms_dir), &count);
00501        if (count == 0) {
00502               smart_str_appends(&tmp1, "none");
00503        }
00504        for (i = 0; i < count; i++) {
00505               smart_str_appends(&tmp1, modules[i]);
00506               smart_str_appendc(&tmp1, ' ');
00507        }
00508        smart_str_0(&tmp1);
00509        mcrypt_free_p(modules, count);
00510 
00511        modules = mcrypt_list_modes(MCG(modes_dir), &count);
00512        if (count == 0) {
00513               smart_str_appends(&tmp2, "none");
00514        }
00515        for (i = 0; i < count; i++) {
00516               smart_str_appends(&tmp2, modules[i]);
00517               smart_str_appendc(&tmp2, ' ');
00518        }
00519        smart_str_0 (&tmp2);
00520        mcrypt_free_p (modules, count);
00521 
00522        snprintf (mcrypt_api_no, 16, "%d", MCRYPT_API_VERSION);
00523 
00524        php_info_print_table_start();
00525        php_info_print_table_header(2, "mcrypt support", "enabled");
00526        php_info_print_table_header(2, "mcrypt_filter support", "enabled");
00527        php_info_print_table_row(2, "Version", LIBMCRYPT_VERSION);
00528        php_info_print_table_row(2, "Api No", mcrypt_api_no);
00529        php_info_print_table_row(2, "Supported ciphers", tmp1.c);
00530        php_info_print_table_row(2, "Supported modes", tmp2.c);
00531        smart_str_free(&tmp1);
00532        smart_str_free(&tmp2);
00533        php_info_print_table_end();
00534        
00535        DISPLAY_INI_ENTRIES();
00536 }
00537 /* }}} */
00538 
00539 typedef enum {
00540        RANDOM = 0,
00541        URANDOM,
00542        RAND
00543 } iv_source;
00544 
00545 /* {{{ proto resource mcrypt_module_open(string cipher, string cipher_directory, string mode, string mode_directory)
00546    Opens the module of the algorithm and the mode to be used */
00547 PHP_FUNCTION(mcrypt_module_open)
00548 {
00549        char *cipher, *cipher_dir;
00550        char *mode,   *mode_dir;
00551        int   cipher_len, cipher_dir_len;
00552        int   mode_len,   mode_dir_len;
00553        MCRYPT td;
00554        php_mcrypt *pm;
00555    
00556        if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ssss",
00557               &cipher, &cipher_len, &cipher_dir, &cipher_dir_len,
00558               &mode,   &mode_len,   &mode_dir,   &mode_dir_len)) {
00559               return;
00560        }
00561        
00562        td = mcrypt_module_open (
00563               cipher,
00564               cipher_dir_len > 0 ? cipher_dir : MCG(algorithms_dir),
00565               mode, 
00566               mode_dir_len > 0 ? mode_dir : MCG(modes_dir)
00567        );
00568 
00569        if (td == MCRYPT_FAILED) {
00570               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open encryption module");
00571               RETURN_FALSE;
00572        } else {
00573               pm = emalloc(sizeof(php_mcrypt));
00574               pm->td = td;
00575               pm->init = 0;
00576               ZEND_REGISTER_RESOURCE(return_value, pm, le_mcrypt);
00577        }
00578 }
00579 /* }}} */
00580 
00581 /* {{{ proto int mcrypt_generic_init(resource td, string key, string iv)
00582    This function initializes all buffers for the specific module */
00583 PHP_FUNCTION(mcrypt_generic_init)
00584 {
00585        char *key, *iv;
00586        int key_len, iv_len;
00587        zval *mcryptind;
00588        unsigned char *key_s, *iv_s;
00589        int max_key_size, key_size, iv_size;
00590        php_mcrypt *pm;
00591        int result = 0;
00592        
00593        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &mcryptind, &key, &key_len, &iv, &iv_len) == FAILURE) {
00594               return;
00595        }
00596 
00597        ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);
00598 
00599        max_key_size = mcrypt_enc_get_key_size(pm->td);
00600        iv_size = mcrypt_enc_get_iv_size(pm->td);
00601 
00602        if (key_len == 0) {
00603               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key size is 0");
00604        }
00605 
00606        key_s = emalloc(key_len);
00607        memset(key_s, 0, key_len);
00608 
00609        iv_s = emalloc(iv_size + 1);
00610        memset(iv_s, 0, iv_size + 1);
00611 
00612        if (key_len > max_key_size) {
00613               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key size too large; supplied length: %d, max: %d", key_len, max_key_size);
00614               key_size = max_key_size;
00615        } else {
00616               key_size = key_len;
00617        }
00618        memcpy(key_s, key, key_len);
00619 
00620        if (iv_len != iv_size) {
00621               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Iv size incorrect; supplied length: %d, needed: %d", iv_len, iv_size);
00622        }
00623        memcpy(iv_s, iv, iv_size);
00624 
00625        mcrypt_generic_deinit(pm->td);
00626        result = mcrypt_generic_init(pm->td, key_s, key_size, iv_s);
00627 
00628        /* If this function fails, close the mcrypt module to prevent crashes
00629         * when further functions want to access this resource */
00630        if (result < 0) {
00631               zend_list_delete(Z_LVAL_P(mcryptind));
00632               switch (result) {
00633                      case -3:
00634                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key length incorrect");
00635                             break;
00636                      case -4:
00637                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memory allocation error");
00638                             break;
00639                      case -1:
00640                      default:
00641                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error");
00642                             break;
00643               }
00644        }
00645        pm->init = 1;
00646        RETVAL_LONG(result);
00647 
00648        efree(iv_s);
00649        efree(key_s);
00650 }
00651 /* }}} */
00652 
00653 /* {{{ proto string mcrypt_generic(resource td, string data)
00654    This function encrypts the plaintext */
00655 PHP_FUNCTION(mcrypt_generic)
00656 {
00657        zval *mcryptind;
00658        char *data;
00659        int data_len;
00660        php_mcrypt *pm;
00661        unsigned char* data_s;
00662        int block_size, data_size;
00663 
00664        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) {
00665               return;
00666        }
00667        
00668        ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);
00669        PHP_MCRYPT_INIT_CHECK
00670 
00671        if (data_len == 0) {
00672               php_error_docref(NULL TSRMLS_CC, E_WARNING, "An empty string was passed");
00673               RETURN_FALSE
00674        }
00675 
00676        /* Check blocksize */
00677        if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
00678               block_size = mcrypt_enc_get_block_size(pm->td);
00679               data_size = (((data_len - 1) / block_size) + 1) * block_size;
00680               data_s = emalloc(data_size + 1);
00681               memset(data_s, 0, data_size);
00682               memcpy(data_s, data, data_len);
00683        } else { /* It's not a block algorithm */
00684               data_size = data_len;
00685               data_s = emalloc(data_size + 1);
00686               memset(data_s, 0, data_size);
00687               memcpy(data_s, data, data_len);
00688        }
00689        
00690        mcrypt_generic(pm->td, data_s, data_size);
00691        data_s[data_size] = '\0';
00692 
00693        RETVAL_STRINGL(data_s, data_size, 1);
00694        efree(data_s);
00695 }
00696 /* }}} */
00697 
00698 /* {{{ proto string mdecrypt_generic(resource td, string data)
00699    This function decrypts the plaintext */
00700 PHP_FUNCTION(mdecrypt_generic)
00701 {
00702        zval *mcryptind;
00703        char *data;
00704        int data_len;
00705        php_mcrypt *pm;
00706        char* data_s;
00707        int block_size, data_size;
00708        
00709        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) {
00710               return;
00711        }
00712        
00713        ZEND_FETCH_RESOURCE(pm, php_mcrypt * , &mcryptind, -1, "MCrypt", le_mcrypt);
00714        PHP_MCRYPT_INIT_CHECK
00715 
00716        if (data_len == 0) {
00717               php_error_docref(NULL TSRMLS_CC, E_WARNING, "An empty string was passed");
00718               RETURN_FALSE
00719        }
00720 
00721        /* Check blocksize */
00722        if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
00723               block_size = mcrypt_enc_get_block_size(pm->td);
00724               data_size = (((data_len - 1) / block_size) + 1) * block_size;
00725               data_s = emalloc(data_size + 1);
00726               memset(data_s, 0, data_size);
00727               memcpy(data_s, data, data_len);
00728        } else { /* It's not a block algorithm */
00729               data_size = data_len;
00730               data_s = emalloc(data_size + 1);
00731               memset(data_s, 0, data_size);
00732               memcpy(data_s, data, data_len);
00733        }
00734        
00735        mdecrypt_generic(pm->td, data_s, data_size);
00736 
00737        RETVAL_STRINGL(data_s, data_size, 1);
00738        efree(data_s);
00739 }
00740 /* }}} */
00741 
00742 /* {{{ proto array mcrypt_enc_get_supported_key_sizes(resource td)
00743    This function decrypts the crypttext */
00744 PHP_FUNCTION(mcrypt_enc_get_supported_key_sizes)
00745 {
00746        int i, count = 0;
00747        int *key_sizes;
00748        
00749        MCRYPT_GET_TD_ARG
00750        array_init(return_value);
00751 
00752        key_sizes = mcrypt_enc_get_supported_key_sizes(pm->td, &count);
00753 
00754        for (i = 0; i < count; i++) {
00755               add_index_long(return_value, i, key_sizes[i]);
00756        }
00757 
00758        mcrypt_free(key_sizes);
00759 }
00760 /* }}} */
00761 
00762 /* {{{ proto int mcrypt_enc_self_test(resource td)
00763    This function runs the self test on the algorithm specified by the descriptor td */
00764 PHP_FUNCTION(mcrypt_enc_self_test)
00765 {
00766        MCRYPT_GET_TD_ARG
00767        RETURN_LONG(mcrypt_enc_self_test(pm->td));
00768 }
00769 /* }}} */
00770 
00771 /* {{{ proto bool mcrypt_module_close(resource td)
00772    Free the descriptor td */
00773 PHP_FUNCTION(mcrypt_module_close)
00774 {
00775        MCRYPT_GET_TD_ARG
00776        zend_list_delete(Z_LVAL_P(mcryptind));
00777        RETURN_TRUE;
00778 }
00779 /* }}} */
00780 
00781 /* {{{ proto bool mcrypt_generic_deinit(resource td)
00782    This function terminates encrypt specified by the descriptor td */
00783 PHP_FUNCTION(mcrypt_generic_deinit)
00784 {
00785        MCRYPT_GET_TD_ARG
00786 
00787        if (mcrypt_generic_deinit(pm->td) < 0) {
00788               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not terminate encryption specifier");
00789               RETURN_FALSE
00790        }
00791        pm->init = 0;
00792        RETURN_TRUE
00793 }
00794 /* }}} */
00795 
00796 /* {{{ proto bool mcrypt_enc_is_block_algorithm_mode(resource td)
00797    Returns TRUE if the mode is for use with block algorithms */
00798 PHP_FUNCTION(mcrypt_enc_is_block_algorithm_mode)
00799 {
00800        MCRYPT_GET_TD_ARG
00801 
00802        if (mcrypt_enc_is_block_algorithm_mode(pm->td) == 1) {
00803               RETURN_TRUE
00804        } else {
00805               RETURN_FALSE
00806        }
00807 }
00808 /* }}} */
00809 
00810 /* {{{ proto bool mcrypt_enc_is_block_algorithm(resource td)
00811    Returns TRUE if the alrogithm is a block algorithms */
00812 PHP_FUNCTION(mcrypt_enc_is_block_algorithm)
00813 {
00814        MCRYPT_GET_TD_ARG
00815 
00816        if (mcrypt_enc_is_block_algorithm(pm->td) == 1) {
00817               RETURN_TRUE 
00818        } else {
00819               RETURN_FALSE
00820        }
00821 }
00822 /* }}} */
00823 
00824 /* {{{ proto bool mcrypt_enc_is_block_mode(resource td)
00825    Returns TRUE if the mode outputs blocks */
00826 PHP_FUNCTION(mcrypt_enc_is_block_mode)
00827 {
00828        MCRYPT_GET_TD_ARG
00829 
00830        if (mcrypt_enc_is_block_mode(pm->td) == 1) {
00831               RETURN_TRUE
00832        } else {
00833               RETURN_FALSE
00834        }
00835 }
00836 /* }}} */
00837 
00838 /* {{{ proto int mcrypt_enc_get_block_size(resource td)
00839    Returns the block size of the cipher specified by the descriptor td */
00840 PHP_FUNCTION(mcrypt_enc_get_block_size)
00841 {
00842        MCRYPT_GET_TD_ARG
00843        RETURN_LONG(mcrypt_enc_get_block_size(pm->td));
00844 }
00845 /* }}} */
00846 
00847 /* {{{ proto int mcrypt_enc_get_key_size(resource td)
00848    Returns the maximum supported key size in bytes of the algorithm specified by the descriptor td */
00849 PHP_FUNCTION(mcrypt_enc_get_key_size)
00850 {
00851        MCRYPT_GET_TD_ARG
00852        RETURN_LONG(mcrypt_enc_get_key_size(pm->td));
00853 }
00854 /* }}} */
00855 
00856 /* {{{ proto int mcrypt_enc_get_iv_size(resource td)
00857    Returns the size of the IV in bytes of the algorithm specified by the descriptor td */
00858 PHP_FUNCTION(mcrypt_enc_get_iv_size)
00859 {
00860        MCRYPT_GET_TD_ARG
00861        RETURN_LONG(mcrypt_enc_get_iv_size(pm->td));
00862 }
00863 /* }}} */
00864 
00865 /* {{{ proto string mcrypt_enc_get_algorithms_name(resource td)
00866    Returns the name of the algorithm specified by the descriptor td */
00867 PHP_FUNCTION(mcrypt_enc_get_algorithms_name)
00868 {
00869        char *name;
00870        MCRYPT_GET_TD_ARG
00871 
00872        name = mcrypt_enc_get_algorithms_name(pm->td);
00873        RETVAL_STRING(name, 1);
00874        mcrypt_free(name);
00875 }
00876 /* }}} */
00877 
00878 /* {{{ proto string mcrypt_enc_get_modes_name(resource td)
00879    Returns the name of the mode specified by the descriptor td */
00880 PHP_FUNCTION(mcrypt_enc_get_modes_name)
00881 {
00882        char *name;
00883        MCRYPT_GET_TD_ARG
00884 
00885        name = mcrypt_enc_get_modes_name(pm->td);
00886        RETVAL_STRING(name, 1);
00887        mcrypt_free(name);
00888 }
00889 /* }}} */
00890 
00891 /* {{{ proto bool mcrypt_module_self_test(string algorithm [, string lib_dir])
00892    Does a self test of the module "module" */
00893 PHP_FUNCTION(mcrypt_module_self_test)
00894 {
00895        MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);
00896        
00897        if (mcrypt_module_self_test(module, dir) == 0) {
00898               RETURN_TRUE;
00899        } else {
00900               RETURN_FALSE;
00901        }
00902 }
00903 /* }}} */
00904 
00905 /* {{{ proto bool mcrypt_module_is_block_algorithm_mode(string mode [, string lib_dir])
00906    Returns TRUE if the mode is for use with block algorithms */
00907 PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode)
00908 {
00909        MCRYPT_GET_MODE_DIR_ARGS(modes_dir)
00910        
00911        if (mcrypt_module_is_block_algorithm_mode(module, dir) == 1) {
00912               RETURN_TRUE;
00913        } else {
00914               RETURN_FALSE;
00915        }
00916 }
00917 /* }}} */
00918 
00919 /* {{{ proto bool mcrypt_module_is_block_algorithm(string algorithm [, string lib_dir])
00920    Returns TRUE if the algorithm is a block algorithm */
00921 PHP_FUNCTION(mcrypt_module_is_block_algorithm)
00922 {
00923        MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
00924        
00925        if (mcrypt_module_is_block_algorithm(module, dir) == 1) {
00926               RETURN_TRUE;
00927        } else {
00928               RETURN_FALSE;
00929        }
00930 }
00931 /* }}} */
00932 
00933 /* {{{ proto bool mcrypt_module_is_block_mode(string mode [, string lib_dir])
00934    Returns TRUE if the mode outputs blocks of bytes */
00935 PHP_FUNCTION(mcrypt_module_is_block_mode)
00936 {
00937        MCRYPT_GET_MODE_DIR_ARGS(modes_dir)
00938        
00939        if (mcrypt_module_is_block_mode(module, dir) == 1) {
00940               RETURN_TRUE;
00941        } else {
00942               RETURN_FALSE;
00943        }
00944 }
00945 /* }}} */
00946 
00947 /* {{{ proto int mcrypt_module_get_algo_block_size(string algorithm [, string lib_dir])
00948    Returns the block size of the algorithm */
00949 PHP_FUNCTION(mcrypt_module_get_algo_block_size)
00950 {
00951        MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
00952        
00953        RETURN_LONG(mcrypt_module_get_algo_block_size(module, dir));
00954 }
00955 /* }}} */
00956 
00957 /* {{{ proto int mcrypt_module_get_algo_key_size(string algorithm [, string lib_dir])
00958    Returns the maximum supported key size of the algorithm */
00959 PHP_FUNCTION(mcrypt_module_get_algo_key_size)
00960 {
00961        MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);
00962        
00963        RETURN_LONG(mcrypt_module_get_algo_key_size(module, dir));
00964 }
00965 /* }}} */
00966 
00967 /* {{{ proto array mcrypt_module_get_supported_key_sizes(string algorithm [, string lib_dir])
00968    This function decrypts the crypttext */
00969 PHP_FUNCTION(mcrypt_module_get_supported_key_sizes)
00970 {
00971        int i, count = 0;
00972        int *key_sizes;
00973        
00974        MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
00975        array_init(return_value);
00976 
00977        key_sizes = mcrypt_module_get_algo_supported_key_sizes(module, dir, &count);
00978 
00979        for (i = 0; i < count; i++) {
00980               add_index_long(return_value, i, key_sizes[i]);
00981        }
00982        mcrypt_free(key_sizes);
00983 }
00984 /* }}} */
00985 
00986 /* {{{ proto array mcrypt_list_algorithms([string lib_dir])
00987    List all algorithms in "module_dir" */
00988 PHP_FUNCTION(mcrypt_list_algorithms)
00989 {
00990        char **modules;
00991        char *lib_dir = MCG(algorithms_dir);
00992        int   lib_dir_len;
00993        int   i, count;
00994 
00995        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
00996               &lib_dir, &lib_dir_len) == FAILURE) {
00997               return;
00998        }
00999        
01000        array_init(return_value);
01001        modules = mcrypt_list_algorithms(lib_dir, &count);
01002 
01003        if (count == 0) {
01004               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No algorithms found in module dir");
01005        }
01006        for (i = 0; i < count; i++) {
01007               add_index_string(return_value, i, modules[i], 1);
01008        }
01009        mcrypt_free_p(modules, count);
01010 }
01011 /* }}} */
01012 
01013 /* {{{ proto array mcrypt_list_modes([string lib_dir])
01014    List all modes "module_dir" */
01015 PHP_FUNCTION(mcrypt_list_modes)
01016 {
01017        char **modules;
01018        char *lib_dir = MCG(modes_dir);
01019        int   lib_dir_len;
01020        int   i, count;
01021 
01022        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
01023               &lib_dir, &lib_dir_len) == FAILURE) {
01024               return;
01025        }
01026 
01027        array_init(return_value);
01028        modules = mcrypt_list_modes(lib_dir, &count);
01029 
01030        if (count == 0) {
01031               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No modes found in module dir");
01032        }
01033        for (i = 0; i < count; i++) {
01034               add_index_string(return_value, i, modules[i], 1);
01035        }
01036        mcrypt_free_p(modules, count);
01037 }
01038 /* }}} */
01039 
01040 /* {{{ proto int mcrypt_get_key_size(string cipher, string module)
01041    Get the key size of cipher */
01042 PHP_FUNCTION(mcrypt_get_key_size)
01043 {
01044        char *cipher;
01045        char *module;
01046        int   cipher_len, module_len; 
01047        char *cipher_dir_string;
01048        char *module_dir_string;
01049        MCRYPT td;
01050 
01051        MCRYPT_GET_INI
01052 
01053        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
01054               &cipher, &cipher_len, &module, &module_len) == FAILURE) {
01055               return;
01056        }
01057        
01058        td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
01059        if (td != MCRYPT_FAILED) {
01060               RETVAL_LONG(mcrypt_enc_get_key_size(td));
01061               mcrypt_module_close(td);
01062        } else {
01063               php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED);
01064               RETURN_FALSE;
01065        }
01066 }
01067 /* }}} */
01068 
01069 /* {{{ proto int mcrypt_get_block_size(string cipher, string module)
01070    Get the key size of cipher */
01071 PHP_FUNCTION(mcrypt_get_block_size)
01072 {
01073        char *cipher;
01074        char *module;
01075        int   cipher_len, module_len; 
01076        char *cipher_dir_string;
01077        char *module_dir_string;
01078        MCRYPT td;
01079 
01080        MCRYPT_GET_INI
01081 
01082        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
01083               &cipher, &cipher_len, &module, &module_len) == FAILURE) {
01084               return;
01085        }
01086        
01087        td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
01088        if (td != MCRYPT_FAILED) {
01089               RETVAL_LONG(mcrypt_enc_get_block_size(td));
01090               mcrypt_module_close(td);
01091        } else {
01092               php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED);
01093               RETURN_FALSE;
01094        }
01095 }
01096 /* }}} */
01097 
01098 /* {{{ proto int mcrypt_get_iv_size(string cipher, string module)
01099    Get the IV size of cipher (Usually the same as the blocksize) */
01100 PHP_FUNCTION(mcrypt_get_iv_size)
01101 {
01102        char *cipher;
01103        char *module;
01104        int   cipher_len, module_len; 
01105        char *cipher_dir_string;
01106        char *module_dir_string;
01107        MCRYPT td;
01108 
01109        MCRYPT_GET_INI
01110 
01111        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
01112               &cipher, &cipher_len, &module, &module_len) == FAILURE) {
01113               return;
01114        }
01115        
01116        td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
01117        if (td != MCRYPT_FAILED) {
01118               RETVAL_LONG(mcrypt_enc_get_iv_size(td));
01119               mcrypt_module_close(td);
01120        } else {
01121               php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED);
01122               RETURN_FALSE;
01123        }
01124 }
01125 /* }}} */
01126 
01127 /* {{{ proto string mcrypt_get_cipher_name(string cipher)
01128    Get the key size of cipher */
01129 PHP_FUNCTION(mcrypt_get_cipher_name)
01130 {
01131        char *cipher_dir_string;
01132        char *module_dir_string;
01133        char *cipher_name;
01134        char *cipher;
01135        int   cipher_len;
01136        MCRYPT td;
01137 
01138        MCRYPT_GET_INI
01139 
01140        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
01141               &cipher, &cipher_len) == FAILURE) {
01142               return;
01143        }
01144 
01145        /* The code below is actually not very nice, but I didn't see a better
01146         * method */
01147        td = mcrypt_module_open(cipher, cipher_dir_string, "ecb", module_dir_string);
01148        if (td != MCRYPT_FAILED) {
01149               cipher_name = mcrypt_enc_get_algorithms_name(td);
01150               mcrypt_module_close(td);
01151               RETVAL_STRING(cipher_name,1);
01152               mcrypt_free(cipher_name);
01153        } else {
01154               td = mcrypt_module_open(cipher, cipher_dir_string, "stream", module_dir_string);
01155               if (td != MCRYPT_FAILED) {
01156                      cipher_name = mcrypt_enc_get_algorithms_name(td);
01157                      mcrypt_module_close(td);
01158                      RETVAL_STRING(cipher_name,1);
01159                      mcrypt_free(cipher_name);
01160               } else {
01161                      php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED);
01162                      RETURN_FALSE;
01163               }
01164        }
01165 }
01166 /* }}} */
01167 
01168 static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, const char *data, int data_len, char *mode, const char *iv, int iv_len, int argc, int dencrypt, zval* return_value TSRMLS_DC) /* {{{ */
01169 {
01170        char *cipher_dir_string;
01171        char *module_dir_string;
01172        int block_size, max_key_length, use_key_length, i, count, iv_size;
01173        unsigned long int data_size;
01174        int *key_length_sizes;
01175        char *key_s = NULL, *iv_s;
01176        char *data_s;
01177        MCRYPT td;
01178 
01179        MCRYPT_GET_INI
01180 
01181        td = mcrypt_module_open(cipher, cipher_dir_string, mode, module_dir_string);
01182        if (td == MCRYPT_FAILED) {
01183               php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_OPEN_MODULE_FAILED);
01184               RETURN_FALSE;
01185        }
01186        /* Checking for key-length */
01187        max_key_length = mcrypt_enc_get_key_size(td);
01188        if (key_len > max_key_length) {
01189               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size of key is too large for this algorithm");
01190        }
01191        key_length_sizes = mcrypt_enc_get_supported_key_sizes(td, &count);
01192        if (count == 0 && key_length_sizes == NULL) { /* all lengths 1 - k_l_s = OK */
01193               use_key_length = key_len;
01194               key_s = emalloc(use_key_length);
01195               memset(key_s, 0, use_key_length);
01196               memcpy(key_s, key, use_key_length);
01197        } else if (count == 1) {  /* only m_k_l = OK */
01198               key_s = emalloc(key_length_sizes[0]);
01199               memset(key_s, 0, key_length_sizes[0]);
01200               memcpy(key_s, key, MIN(key_len, key_length_sizes[0]));
01201               use_key_length = key_length_sizes[0];
01202        } else { /* dertermine smallest supported key > length of requested key */
01203               use_key_length = max_key_length; /* start with max key length */
01204               for (i = 0; i < count; i++) {
01205                      if (key_length_sizes[i] >= key_len && 
01206                             key_length_sizes[i] < use_key_length)
01207                      {
01208                             use_key_length = key_length_sizes[i];
01209                      }
01210               }
01211               key_s = emalloc(use_key_length);
01212               memset(key_s, 0, use_key_length);
01213               memcpy(key_s, key, MIN(key_len, use_key_length));
01214        }
01215        mcrypt_free (key_length_sizes);
01216        
01217        /* Check IV */
01218        iv_s = NULL;
01219        iv_size = mcrypt_enc_get_iv_size (td);
01220        
01221        /* IV is required */
01222        if (mcrypt_enc_mode_has_iv(td) == 1) {
01223               if (argc == 5) {
01224                      if (iv_size != iv_len) {
01225                             php_error_docref(NULL TSRMLS_CC, E_WARNING, MCRYPT_IV_WRONG_SIZE);
01226                      } else {
01227                             iv_s = emalloc(iv_size + 1);
01228                             memcpy(iv_s, iv, iv_size);
01229                      }
01230               } else if (argc == 4) {
01231                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to use an empty IV, which is NOT recommend");
01232                      iv_s = emalloc(iv_size + 1);
01233                      memset(iv_s, 0, iv_size + 1);
01234               }
01235        }
01236 
01237        /* Check blocksize */
01238        if (mcrypt_enc_is_block_mode(td) == 1) { /* It's a block algorithm */
01239               block_size = mcrypt_enc_get_block_size(td);
01240               data_size = (((data_len - 1) / block_size) + 1) * block_size;
01241               data_s = emalloc(data_size);
01242               memset(data_s, 0, data_size);
01243               memcpy(data_s, data, data_len);
01244        } else { /* It's not a block algorithm */
01245               data_size = data_len;
01246               data_s = emalloc(data_size);
01247               memset(data_s, 0, data_size);
01248               memcpy(data_s, data, data_len);
01249        }
01250 
01251        if (mcrypt_generic_init(td, key_s, use_key_length, iv_s) < 0) {
01252               php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Mcrypt initialisation failed");
01253               RETURN_FALSE;
01254        }
01255        if (dencrypt == MCRYPT_ENCRYPT) {
01256               mcrypt_generic(td, data_s, data_size);
01257        } else {
01258               mdecrypt_generic(td, data_s, data_size);
01259        }
01260        
01261        RETVAL_STRINGL(data_s, data_size, 1);
01262 
01263        /* freeing vars */
01264        mcrypt_generic_end(td);
01265        if (key_s != NULL) {
01266               efree (key_s);
01267        }
01268        if (iv_s != NULL) {
01269               efree (iv_s);
01270        }
01271        efree (data_s);
01272 }
01273 /* }}} */
01274 
01275 /* {{{ proto string mcrypt_encrypt(string cipher, string key, string data, string mode, string iv)
01276    OFB crypt/decrypt data using key key with cipher cipher starting with iv */
01277 PHP_FUNCTION(mcrypt_encrypt)
01278 {
01279        zval **mode;
01280        char *cipher, *key, *data, *iv = NULL;
01281        int cipher_len, key_len, data_len, iv_len = 0;
01282        
01283        MCRYPT_GET_CRYPT_ARGS
01284        
01285        convert_to_string_ex(mode);
01286 
01287        php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_ENCRYPT, return_value TSRMLS_CC);
01288 }
01289 /* }}} */
01290 
01291 /* {{{ proto string mcrypt_decrypt(string cipher, string key, string data, string mode, string iv)
01292    OFB crypt/decrypt data using key key with cipher cipher starting with iv */
01293 PHP_FUNCTION(mcrypt_decrypt)
01294 {
01295        zval **mode;
01296        char *cipher, *key, *data, *iv = NULL;
01297        int cipher_len, key_len, data_len, iv_len = 0;
01298 
01299        MCRYPT_GET_CRYPT_ARGS
01300        
01301        convert_to_string_ex(mode);
01302 
01303        php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_DECRYPT, return_value TSRMLS_CC);
01304 }
01305 /* }}} */
01306 
01307 /* {{{ proto string mcrypt_ecb(int cipher, string key, string data, int mode, string iv)
01308    ECB crypt/decrypt data using key key with cipher cipher starting with iv */
01309 PHP_FUNCTION(mcrypt_ecb)
01310 {
01311        zval **mode;
01312        char *cipher, *key, *data, *iv = NULL;
01313        int cipher_len, key_len, data_len, iv_len = 0;
01314        
01315        MCRYPT_GET_CRYPT_ARGS
01316 
01317        convert_to_long_ex(mode);
01318 
01319        php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ecb", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
01320 }
01321 /* }}} */
01322 
01323 /* {{{ proto string mcrypt_cbc(int cipher, string key, string data, int mode, string iv)
01324    CBC crypt/decrypt data using key key with cipher cipher starting with iv */
01325 PHP_FUNCTION(mcrypt_cbc)
01326 {
01327        zval **mode;
01328        char *cipher, *key, *data, *iv = NULL;
01329        int cipher_len, key_len, data_len, iv_len = 0;
01330 
01331        MCRYPT_GET_CRYPT_ARGS
01332 
01333        convert_to_long_ex(mode);
01334 
01335        php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cbc", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
01336 }
01337 /* }}} */
01338 
01339 /* {{{ proto string mcrypt_cfb(int cipher, string key, string data, int mode, string iv)
01340    CFB crypt/decrypt data using key key with cipher cipher starting with iv */
01341 PHP_FUNCTION(mcrypt_cfb)
01342 {
01343        zval **mode;
01344        char *cipher, *key, *data, *iv = NULL;
01345        int cipher_len, key_len, data_len, iv_len = 0;
01346        
01347        MCRYPT_GET_CRYPT_ARGS
01348 
01349        convert_to_long_ex(mode);
01350 
01351        php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cfb", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
01352 }
01353 /* }}} */
01354 
01355 /* {{{ proto string mcrypt_ofb(int cipher, string key, string data, int mode, string iv)
01356    OFB crypt/decrypt data using key key with cipher cipher starting with iv */
01357 PHP_FUNCTION(mcrypt_ofb)
01358 {
01359        zval **mode;
01360        char *cipher, *key, *data, *iv = NULL;
01361        int cipher_len, key_len, data_len, iv_len = 0;
01362        
01363        MCRYPT_GET_CRYPT_ARGS
01364 
01365        convert_to_long_ex(mode);
01366 
01367        php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ofb", iv, iv_len, ZEND_NUM_ARGS(), Z_LVAL_PP(mode), return_value TSRMLS_CC);
01368 }
01369 /* }}} */
01370 
01371 /* {{{ proto string mcrypt_create_iv(int size, int source)
01372    Create an initialization vector (IV) */
01373 PHP_FUNCTION(mcrypt_create_iv)
01374 {
01375        char *iv;
01376        long source = RANDOM;
01377        long size;
01378        int n = 0;
01379 
01380        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &size, &source) == FAILURE) {
01381               return;
01382        }
01383 
01384        if (size <= 0 || size >= INT_MAX) {
01385               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);
01386               RETURN_FALSE;
01387        }
01388        
01389        iv = ecalloc(size + 1, 1);
01390        
01391        if (source == RANDOM || source == URANDOM) {
01392 #if PHP_WIN32
01393               /* random/urandom equivalent on Windows */
01394               BYTE *iv_b = (BYTE *) iv;
01395               if (php_win32_get_random_bytes(iv_b, (size_t) size) == FAILURE){
01396                      efree(iv);
01397                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not gather sufficient random data");
01398                      RETURN_FALSE;
01399               }
01400               n = size;
01401 #else
01402               int    fd;
01403               size_t read_bytes = 0;
01404 
01405               fd = open(source == RANDOM ? "/dev/random" : "/dev/urandom", O_RDONLY);
01406               if (fd < 0) {
01407                      efree(iv);
01408                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open source device");
01409                      RETURN_FALSE;
01410               }
01411               while (read_bytes < size) {
01412                      n = read(fd, iv + read_bytes, size - read_bytes);
01413                      if (n < 0) {
01414                             break;
01415                      }
01416                      read_bytes += n;
01417               }
01418               n = read_bytes;
01419               close(fd);
01420               if (n < size) {
01421                      efree(iv);
01422                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not gather sufficient random data");
01423                      RETURN_FALSE;
01424               }
01425 #endif
01426        } else {
01427               n = size;
01428               while (size) {
01429                      iv[--size] = (char) (255.0 * php_rand(TSRMLS_C) / RAND_MAX);
01430               }
01431        }
01432        RETURN_STRINGL(iv, n, 0);
01433 }
01434 /* }}} */
01435 
01436 #endif
01437 
01438 /*
01439  * Local variables:
01440  * tab-width: 4
01441  * c-basic-offset: 4
01442  * End:
01443  * vim600: sw=4 ts=4 fdm=marker
01444  * vim<600: sw=4 ts=4
01445  */