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