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