PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mcrypt - mcrypt.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 409 468 87.4 %
Date: 2015-05-21 Functions: 41 41 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:58:58 +0000 (6 days ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.