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