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