Annotation of embedaddon/php/ext/hash/hash.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 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: | Author: Sara Golemon <pollita@php.net> |
16: | Scott MacVicar <scottmac@php.net> |
17: +----------------------------------------------------------------------+
18: */
19:
1.1.1.2 misho 20: /* $Id$ */
1.1 misho 21:
22: #ifdef HAVE_CONFIG_H
23: #include "config.h"
24: #endif
25:
26: #include "php_hash.h"
27: #include "ext/standard/info.h"
28: #include "ext/standard/file.h"
29:
30: static int php_hash_le_hash;
31: HashTable php_hash_hashtable;
32:
33: #if (PHP_MAJOR_VERSION >= 5)
34: # define DEFAULT_CONTEXT FG(default_context)
35: #else
36: # define DEFAULT_CONTEXT NULL
37: #endif
38:
39: #ifdef PHP_MHASH_BC
40: struct mhash_bc_entry {
41: char *mhash_name;
42: char *hash_name;
43: int value;
44: };
45:
1.1.1.2 misho 46: #define MHASH_NUM_ALGOS 34
1.1 misho 47:
48: static struct mhash_bc_entry mhash_to_hash[MHASH_NUM_ALGOS] = {
49: {"CRC32", "crc32", 0},
50: {"MD5", "md5", 1},
51: {"SHA1", "sha1", 2},
52: {"HAVAL256", "haval256,3", 3},
53: {NULL, NULL, 4},
54: {"RIPEMD160", "ripemd160", 5},
55: {NULL, NULL, 6},
56: {"TIGER", "tiger192,3", 7},
57: {"GOST", "gost", 8},
58: {"CRC32B", "crc32b", 9},
59: {"HAVAL224", "haval224,3", 10},
60: {"HAVAL192", "haval192,3", 11},
61: {"HAVAL160", "haval160,3", 12},
62: {"HAVAL128", "haval128,3", 13},
63: {"TIGER128", "tiger128,3", 14},
64: {"TIGER160", "tiger160,3", 15},
65: {"MD4", "md4", 16},
66: {"SHA256", "sha256", 17},
67: {"ADLER32", "adler32", 18},
68: {"SHA224", "sha224", 19},
69: {"SHA512", "sha512", 20},
70: {"SHA384", "sha384", 21},
71: {"WHIRLPOOL", "whirlpool", 22},
72: {"RIPEMD128", "ripemd128", 23},
73: {"RIPEMD256", "ripemd256", 24},
74: {"RIPEMD320", "ripemd320", 25},
75: {NULL, NULL, 26}, /* support needs to be added for snefru 128 */
76: {"SNEFRU256", "snefru256", 27},
1.1.1.2 misho 77: {"MD2", "md2", 28},
78: {"FNV132", "fnv132", 29},
79: {"FNV1A32", "fnv1a32", 30},
80: {"FNV164", "fnv164", 31},
81: {"FNV1A64", "fnv1a64", 32},
82: {"JOAAT", "joaat", 33},
1.1 misho 83: };
84: #endif
85:
86: /* Hash Registry Access */
87:
88: PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(const char *algo, int algo_len) /* {{{ */
89: {
90: php_hash_ops *ops;
91: char *lower = estrndup(algo, algo_len);
92:
93: zend_str_tolower(lower, algo_len);
94: if (SUCCESS != zend_hash_find(&php_hash_hashtable, lower, algo_len + 1, (void*)&ops)) {
95: ops = NULL;
96: }
97: efree(lower);
98:
99: return ops;
100: }
101: /* }}} */
102:
103: PHP_HASH_API void php_hash_register_algo(const char *algo, const php_hash_ops *ops) /* {{{ */
104: {
105: int algo_len = strlen(algo);
106: char *lower = estrndup(algo, algo_len);
107:
108: zend_str_tolower(lower, algo_len);
109: zend_hash_add(&php_hash_hashtable, lower, algo_len + 1, (void*)ops, sizeof(php_hash_ops), NULL);
110: efree(lower);
111: }
112: /* }}} */
113:
114: PHP_HASH_API int php_hash_copy(const void *ops, void *orig_context, void *dest_context) /* {{{ */
115: {
116: php_hash_ops *hash_ops = (php_hash_ops *)ops;
117:
118: memcpy(dest_context, orig_context, hash_ops->context_size);
119: return SUCCESS;
120: }
121: /* }}} */
122:
123: /* Userspace */
124:
125: static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */
126: {
127: char *algo, *data, *digest;
128: int algo_len, data_len;
129: zend_bool raw_output = raw_output_default;
130: const php_hash_ops *ops;
131: void *context;
132: php_stream *stream = NULL;
133:
134: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &algo, &algo_len, &data, &data_len, &raw_output) == FAILURE) {
135: return;
136: }
137:
138: ops = php_hash_fetch_ops(algo, algo_len);
139: if (!ops) {
140: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown hashing algorithm: %s", algo);
141: RETURN_FALSE;
142: }
143: if (isfilename) {
1.1.1.2 misho 144: if (CHECK_NULL_PATH(data, data_len)) {
145: RETURN_FALSE;
146: }
147: stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT);
1.1 misho 148: if (!stream) {
149: /* Stream will report errors opening file */
150: RETURN_FALSE;
151: }
152: }
153:
154: context = emalloc(ops->context_size);
155: ops->hash_init(context);
156:
157: if (isfilename) {
158: char buf[1024];
159: int n;
160:
161: while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
162: ops->hash_update(context, (unsigned char *) buf, n);
163: }
164: php_stream_close(stream);
165: } else {
166: ops->hash_update(context, (unsigned char *) data, data_len);
167: }
168:
169: digest = emalloc(ops->digest_size + 1);
170: ops->hash_final((unsigned char *) digest, context);
171: efree(context);
172:
173: if (raw_output) {
174: digest[ops->digest_size] = 0;
175: RETURN_STRINGL(digest, ops->digest_size, 0);
176: } else {
177: char *hex_digest = safe_emalloc(ops->digest_size, 2, 1);
178:
179: php_hash_bin2hex(hex_digest, (unsigned char *) digest, ops->digest_size);
180: hex_digest[2 * ops->digest_size] = 0;
181: efree(digest);
182: RETURN_STRINGL(hex_digest, 2 * ops->digest_size, 0);
183: }
184: }
185: /* }}} */
186:
187: /* {{{ proto string hash(string algo, string data[, bool raw_output = false])
188: Generate a hash of a given input string
189: Returns lowercase hexits by default */
190: PHP_FUNCTION(hash)
191: {
192: php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
193: }
194: /* }}} */
195:
196: /* {{{ proto string hash_file(string algo, string filename[, bool raw_output = false])
197: Generate a hash of a given file
198: Returns lowercase hexits by default */
199: PHP_FUNCTION(hash_file)
200: {
201: php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
202: }
203: /* }}} */
204:
205: static void php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */
206: {
207: char *algo, *data, *digest, *key, *K;
208: int algo_len, data_len, key_len, i;
209: zend_bool raw_output = raw_output_default;
210: const php_hash_ops *ops;
211: void *context;
212: php_stream *stream = NULL;
213:
214: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|b", &algo, &algo_len, &data, &data_len,
215: &key, &key_len, &raw_output) == FAILURE) {
216: return;
217: }
218:
219: ops = php_hash_fetch_ops(algo, algo_len);
220: if (!ops) {
221: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown hashing algorithm: %s", algo);
222: RETURN_FALSE;
223: }
224: if (isfilename) {
1.1.1.2 misho 225: stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT);
1.1 misho 226: if (!stream) {
227: /* Stream will report errors opening file */
228: RETURN_FALSE;
229: }
230: }
231:
232: context = emalloc(ops->context_size);
233: ops->hash_init(context);
234:
235: K = emalloc(ops->block_size);
236: memset(K, 0, ops->block_size);
237:
238: if (key_len > ops->block_size) {
239: /* Reduce the key first */
240: ops->hash_update(context, (unsigned char *) key, key_len);
241: ops->hash_final((unsigned char *) K, context);
242: /* Make the context ready to start over */
243: ops->hash_init(context);
244: } else {
245: memcpy(K, key, key_len);
246: }
247:
248: /* XOR ipad */
249: for(i=0; i < ops->block_size; i++) {
250: K[i] ^= 0x36;
251: }
252: ops->hash_update(context, (unsigned char *) K, ops->block_size);
253:
254: if (isfilename) {
255: char buf[1024];
256: int n;
257:
258: while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
259: ops->hash_update(context, (unsigned char *) buf, n);
260: }
261: php_stream_close(stream);
262: } else {
263: ops->hash_update(context, (unsigned char *) data, data_len);
264: }
265:
266: digest = emalloc(ops->digest_size + 1);
267: ops->hash_final((unsigned char *) digest, context);
268:
269: /* Convert K to opad -- 0x6A = 0x36 ^ 0x5C */
270: for(i=0; i < ops->block_size; i++) {
271: K[i] ^= 0x6A;
272: }
273:
274: /* Feed this result into the outter hash */
275: ops->hash_init(context);
276: ops->hash_update(context, (unsigned char *) K, ops->block_size);
277: ops->hash_update(context, (unsigned char *) digest, ops->digest_size);
278: ops->hash_final((unsigned char *) digest, context);
279:
280: /* Zero the key */
281: memset(K, 0, ops->block_size);
282: efree(K);
283: efree(context);
284:
285: if (raw_output) {
286: digest[ops->digest_size] = 0;
287: RETURN_STRINGL(digest, ops->digest_size, 0);
288: } else {
289: char *hex_digest = safe_emalloc(ops->digest_size, 2, 1);
290:
291: php_hash_bin2hex(hex_digest, (unsigned char *) digest, ops->digest_size);
292: hex_digest[2 * ops->digest_size] = 0;
293: efree(digest);
294: RETURN_STRINGL(hex_digest, 2 * ops->digest_size, 0);
295: }
296: }
297: /* }}} */
298:
299: /* {{{ proto string hash_hmac(string algo, string data, string key[, bool raw_output = false])
300: Generate a hash of a given input string with a key using HMAC
301: Returns lowercase hexits by default */
302: PHP_FUNCTION(hash_hmac)
303: {
304: php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
305: }
306: /* }}} */
307:
308: /* {{{ proto string hash_hmac_file(string algo, string filename, string key[, bool raw_output = false])
309: Generate a hash of a given file with a key using HMAC
310: Returns lowercase hexits by default */
311: PHP_FUNCTION(hash_hmac_file)
312: {
313: php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
314: }
315: /* }}} */
316:
317:
318: /* {{{ proto resource hash_init(string algo[, int options, string key])
319: Initialize a hashing context */
320: PHP_FUNCTION(hash_init)
321: {
322: char *algo, *key = NULL;
323: int algo_len, key_len = 0, argc = ZEND_NUM_ARGS();
324: long options = 0;
325: void *context;
326: const php_hash_ops *ops;
327: php_hash_data *hash;
328:
329: if (zend_parse_parameters(argc TSRMLS_CC, "s|ls", &algo, &algo_len, &options, &key, &key_len) == FAILURE) {
330: return;
331: }
332:
333: ops = php_hash_fetch_ops(algo, algo_len);
334: if (!ops) {
335: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown hashing algorithm: %s", algo);
336: RETURN_FALSE;
337: }
338:
339: if (options & PHP_HASH_HMAC &&
340: key_len <= 0) {
341: /* Note: a zero length key is no key at all */
342: php_error_docref(NULL TSRMLS_CC, E_WARNING, "HMAC requested without a key");
343: RETURN_FALSE;
344: }
345:
346: context = emalloc(ops->context_size);
347: ops->hash_init(context);
348:
349: hash = emalloc(sizeof(php_hash_data));
350: hash->ops = ops;
351: hash->context = context;
352: hash->options = options;
353: hash->key = NULL;
354:
355: if (options & PHP_HASH_HMAC) {
356: char *K = emalloc(ops->block_size);
357: int i;
358:
359: memset(K, 0, ops->block_size);
360:
361: if (key_len > ops->block_size) {
362: /* Reduce the key first */
363: ops->hash_update(context, (unsigned char *) key, key_len);
364: ops->hash_final((unsigned char *) K, context);
365: /* Make the context ready to start over */
366: ops->hash_init(context);
367: } else {
368: memcpy(K, key, key_len);
369: }
370:
371: /* XOR ipad */
372: for(i=0; i < ops->block_size; i++) {
373: K[i] ^= 0x36;
374: }
375: ops->hash_update(context, (unsigned char *) K, ops->block_size);
376: hash->key = (unsigned char *) K;
377: }
378:
379: ZEND_REGISTER_RESOURCE(return_value, hash, php_hash_le_hash);
380: }
381: /* }}} */
382:
383: /* {{{ proto bool hash_update(resource context, string data)
384: Pump data into the hashing algorithm */
385: PHP_FUNCTION(hash_update)
386: {
387: zval *zhash;
388: php_hash_data *hash;
389: char *data;
390: int data_len;
391:
392: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zhash, &data, &data_len) == FAILURE) {
393: return;
394: }
395:
396: ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
397:
398: hash->ops->hash_update(hash->context, (unsigned char *) data, data_len);
399:
400: RETURN_TRUE;
401: }
402: /* }}} */
403:
404: /* {{{ proto int hash_update_stream(resource context, resource handle[, integer length])
405: Pump data into the hashing algorithm from an open stream */
406: PHP_FUNCTION(hash_update_stream)
407: {
408: zval *zhash, *zstream;
409: php_hash_data *hash;
410: php_stream *stream = NULL;
411: long length = -1, didread = 0;
412:
413: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|l", &zhash, &zstream, &length) == FAILURE) {
414: return;
415: }
416:
417: ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
418: php_stream_from_zval(stream, &zstream);
419:
420: while (length) {
421: char buf[1024];
422: long n, toread = 1024;
423:
424: if (length > 0 && toread > length) {
425: toread = length;
426: }
427:
428: if ((n = php_stream_read(stream, buf, toread)) <= 0) {
429: /* Nada mas */
430: RETURN_LONG(didread);
431: }
432: hash->ops->hash_update(hash->context, (unsigned char *) buf, n);
433: length -= n;
434: didread += n;
435: }
436:
437: RETURN_LONG(didread);
438: }
439: /* }}} */
440:
441: /* {{{ proto bool hash_update_file(resource context, string filename[, resource context])
442: Pump data into the hashing algorithm from a file */
443: PHP_FUNCTION(hash_update_file)
444: {
445: zval *zhash, *zcontext = NULL;
446: php_hash_data *hash;
447: php_stream_context *context;
448: php_stream *stream;
449: char *filename, buf[1024];
450: int filename_len, n;
451:
452: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|r", &zhash, &filename, &filename_len, &zcontext) == FAILURE) {
453: return;
454: }
455:
456: ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
457: context = php_stream_context_from_zval(zcontext, 0);
458:
1.1.1.2 misho 459: stream = php_stream_open_wrapper_ex(filename, "rb", REPORT_ERRORS, NULL, context);
1.1 misho 460: if (!stream) {
461: /* Stream will report errors opening file */
462: RETURN_FALSE;
463: }
464:
465: while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
466: hash->ops->hash_update(hash->context, (unsigned char *) buf, n);
467: }
468: php_stream_close(stream);
469:
470: RETURN_TRUE;
471: }
472: /* }}} */
473:
474: /* {{{ proto string hash_final(resource context[, bool raw_output=false])
475: Output resulting digest */
476: PHP_FUNCTION(hash_final)
477: {
478: zval *zhash;
479: php_hash_data *hash;
480: zend_bool raw_output = 0;
481: zend_rsrc_list_entry *le;
482: char *digest;
483: int digest_len;
484:
485: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zhash, &raw_output) == FAILURE) {
486: return;
487: }
488:
489: ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
490:
491: digest_len = hash->ops->digest_size;
492: digest = emalloc(digest_len + 1);
493: hash->ops->hash_final((unsigned char *) digest, hash->context);
494: if (hash->options & PHP_HASH_HMAC) {
495: int i;
496:
497: /* Convert K to opad -- 0x6A = 0x36 ^ 0x5C */
498: for(i=0; i < hash->ops->block_size; i++) {
499: hash->key[i] ^= 0x6A;
500: }
501:
502: /* Feed this result into the outter hash */
503: hash->ops->hash_init(hash->context);
504: hash->ops->hash_update(hash->context, (unsigned char *) hash->key, hash->ops->block_size);
505: hash->ops->hash_update(hash->context, (unsigned char *) digest, hash->ops->digest_size);
506: hash->ops->hash_final((unsigned char *) digest, hash->context);
507:
508: /* Zero the key */
509: memset(hash->key, 0, hash->ops->block_size);
510: efree(hash->key);
511: hash->key = NULL;
512: }
513: digest[digest_len] = 0;
514: efree(hash->context);
515: hash->context = NULL;
516:
517: /* zend_list_REAL_delete() */
518: if (zend_hash_index_find(&EG(regular_list), Z_RESVAL_P(zhash), (void *) &le)==SUCCESS) {
519: /* This is a hack to avoid letting the resource hide elsewhere (like in separated vars)
520: FETCH_RESOURCE is intelligent enough to handle dealing with any issues this causes */
521: le->refcount = 1;
522: } /* FAILURE is not an option */
523: zend_list_delete(Z_RESVAL_P(zhash));
524:
525: if (raw_output) {
526: RETURN_STRINGL(digest, digest_len, 0);
527: } else {
528: char *hex_digest = safe_emalloc(digest_len,2,1);
529:
530: php_hash_bin2hex(hex_digest, (unsigned char *) digest, digest_len);
531: hex_digest[2 * digest_len] = 0;
532: efree(digest);
533: RETURN_STRINGL(hex_digest, 2 * digest_len, 0);
534: }
535: }
536: /* }}} */
537:
538: /* {{{ proto resource hash_copy(resource context)
539: Copy hash resource */
540: PHP_FUNCTION(hash_copy)
541: {
542: zval *zhash;
543: php_hash_data *hash, *copy_hash;
544: void *context;
545: int res;
546:
547: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zhash) == FAILURE) {
548: return;
549: }
550:
551: ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
552:
553:
554: context = emalloc(hash->ops->context_size);
555: hash->ops->hash_init(context);
556:
557: res = hash->ops->hash_copy(hash->ops, hash->context, context);
558: if (res != SUCCESS) {
559: efree(context);
560: RETURN_FALSE;
561: }
562:
563: copy_hash = emalloc(sizeof(php_hash_data));
564: copy_hash->ops = hash->ops;
565: copy_hash->context = context;
566: copy_hash->options = hash->options;
567: copy_hash->key = ecalloc(1, hash->ops->block_size);
568: if (hash->key) {
569: memcpy(copy_hash->key, hash->key, hash->ops->block_size);
570: }
571: ZEND_REGISTER_RESOURCE(return_value, copy_hash, php_hash_le_hash);
572: }
573: /* }}} */
574:
575: /* {{{ proto array hash_algos(void)
576: Return a list of registered hashing algorithms */
577: PHP_FUNCTION(hash_algos)
578: {
579: HashPosition pos;
580: char *str;
581: uint str_len;
582: long type;
583: ulong idx;
584:
585: array_init(return_value);
586: for(zend_hash_internal_pointer_reset_ex(&php_hash_hashtable, &pos);
587: (type = zend_hash_get_current_key_ex(&php_hash_hashtable, &str, &str_len, &idx, 0, &pos)) != HASH_KEY_NON_EXISTANT;
588: zend_hash_move_forward_ex(&php_hash_hashtable, &pos)) {
589: add_next_index_stringl(return_value, str, str_len-1, 1);
590: }
591: }
592: /* }}} */
593:
594: /* Module Housekeeping */
595:
596: static void php_hash_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
597: {
598: php_hash_data *hash = (php_hash_data*)rsrc->ptr;
599:
600: /* Just in case the algo has internally allocated resources */
601: if (hash->context) {
602: unsigned char *dummy = emalloc(hash->ops->digest_size);
603: hash->ops->hash_final(dummy, hash->context);
604: efree(dummy);
605: efree(hash->context);
606: }
607:
608: if (hash->key) {
609: memset(hash->key, 0, hash->ops->block_size);
610: efree(hash->key);
611: }
612: efree(hash);
613: }
614: /* }}} */
615:
616: #define PHP_HASH_HAVAL_REGISTER(p,b) php_hash_register_algo("haval" #b "," #p , &php_hash_##p##haval##b##_ops);
617:
618: #ifdef PHP_MHASH_BC
619:
620: PHP_MINFO_FUNCTION(mhash)
621: {
622: php_info_print_table_start();
623: php_info_print_table_row(2, "MHASH support", "Enabled");
624: php_info_print_table_row(2, "MHASH API Version", "Emulated Support");
625: php_info_print_table_end();
626: }
627:
628: zend_module_entry mhash_module_entry = {
629: STANDARD_MODULE_HEADER,
630: "mhash",
631: NULL,
632: NULL,
633: NULL,
634: NULL,
635: NULL,
636: PHP_MINFO(mhash),
637: NO_VERSION_YET,
638: STANDARD_MODULE_PROPERTIES,
639: };
640:
641: static void mhash_init(INIT_FUNC_ARGS)
642: {
643: char buf[128];
644: int len;
645: int algo_number = 0;
646:
647: for (algo_number = 0; algo_number < MHASH_NUM_ALGOS; algo_number++) {
648: struct mhash_bc_entry algorithm = mhash_to_hash[algo_number];
649: if (algorithm.mhash_name == NULL) {
650: continue;
651: }
652:
653: len = slprintf(buf, 127, "MHASH_%s", algorithm.mhash_name, strlen(algorithm.mhash_name));
654: zend_register_long_constant(buf, len + 1, algorithm.value, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
655: }
656: zend_register_internal_module(&mhash_module_entry TSRMLS_CC);
657: }
658:
659: /* {{{ proto string mhash(int hash, string data [, string key])
660: Hash data with hash */
661: PHP_FUNCTION(mhash)
662: {
663: zval **z_algorithm;
664: long algorithm;
665:
666: if (zend_parse_parameters(1 TSRMLS_CC, "Z", &z_algorithm) == FAILURE) {
667: return;
668: }
669:
670: SEPARATE_ZVAL(z_algorithm);
671: convert_to_long_ex(z_algorithm);
672: algorithm = Z_LVAL_PP(z_algorithm);
673:
674: /* need to convert the first parameter from int constant to string algorithm name */
675: if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) {
676: struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
677: if (algorithm_lookup.hash_name) {
678: ZVAL_STRING(*z_algorithm, algorithm_lookup.hash_name, 1);
679: }
680: }
681:
682: if (ZEND_NUM_ARGS() == 3) {
683: php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
684: } else if (ZEND_NUM_ARGS() == 2) {
685: php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
686: } else {
687: WRONG_PARAM_COUNT;
688: }
689: }
690: /* }}} */
691:
692: /* {{{ proto string mhash_get_hash_name(int hash)
693: Gets the name of hash */
694: PHP_FUNCTION(mhash_get_hash_name)
695: {
696: long algorithm;
697:
698: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &algorithm) == FAILURE) {
699: return;
700: }
701:
702: if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) {
703: struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
704: if (algorithm_lookup.mhash_name) {
705: RETURN_STRING(algorithm_lookup.mhash_name, 1);
706: }
707: }
708: RETURN_FALSE;
709: }
710: /* }}} */
711:
712: /* {{{ proto int mhash_count(void)
713: Gets the number of available hashes */
714: PHP_FUNCTION(mhash_count)
715: {
716: if (zend_parse_parameters_none() == FAILURE) {
717: return;
718: }
719: RETURN_LONG(MHASH_NUM_ALGOS - 1);
720: }
721: /* }}} */
722:
723: /* {{{ proto int mhash_get_block_size(int hash)
724: Gets the block size of hash */
725: PHP_FUNCTION(mhash_get_block_size)
726: {
727: long algorithm;
728:
729: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &algorithm) == FAILURE) {
730: return;
731: }
732: RETVAL_FALSE;
733:
734: if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) {
735: struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
736: if (algorithm_lookup.mhash_name) {
737: const php_hash_ops *ops = php_hash_fetch_ops(algorithm_lookup.hash_name, strlen(algorithm_lookup.hash_name));
738: if (ops) {
739: RETVAL_LONG(ops->digest_size);
740: }
741: }
742: }
743: }
744: /* }}} */
745:
746: #define SALT_SIZE 8
747:
748: /* {{{ proto string mhash_keygen_s2k(int hash, string input_password, string salt, int bytes)
749: Generates a key using hash functions */
750: PHP_FUNCTION(mhash_keygen_s2k)
751: {
752: long algorithm, l_bytes;
753: int bytes;
754: char *password, *salt;
755: int password_len, salt_len;
756: char padded_salt[SALT_SIZE];
757:
758: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lssl", &algorithm, &password, &password_len, &salt, &salt_len, &l_bytes) == FAILURE) {
759: return;
760: }
761:
762: bytes = (int)l_bytes;
763: if (bytes <= 0){
764: php_error_docref(NULL TSRMLS_CC, E_WARNING, "the byte parameter must be greater than 0");
765: RETURN_FALSE;
766: }
767:
768: salt_len = MIN(salt_len, SALT_SIZE);
769:
770: memcpy(padded_salt, salt, salt_len);
771: if (salt_len < SALT_SIZE) {
772: memset(padded_salt + salt_len, 0, SALT_SIZE - salt_len);
773: }
774: salt_len = SALT_SIZE;
775:
776: RETVAL_FALSE;
777: if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) {
778: struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
779: if (algorithm_lookup.mhash_name) {
780: const php_hash_ops *ops = php_hash_fetch_ops(algorithm_lookup.hash_name, strlen(algorithm_lookup.hash_name));
781: if (ops) {
782: unsigned char null = '\0';
783: void *context;
784: char *key, *digest;
785: int i = 0, j = 0;
786: int block_size = ops->digest_size;
787: int times = bytes / block_size;
788: if (bytes % block_size != 0) times++;
789:
790: context = emalloc(ops->context_size);
791: ops->hash_init(context);
792:
793: key = ecalloc(1, times * block_size);
794: digest = emalloc(ops->digest_size + 1);
795:
796: for (i = 0; i < times; i++) {
797: ops->hash_init(context);
798:
799: for (j=0;j<i;j++) {
800: ops->hash_update(context, &null, 1);
801: }
802: ops->hash_update(context, (unsigned char *)padded_salt, salt_len);
803: ops->hash_update(context, (unsigned char *)password, password_len);
804: ops->hash_final((unsigned char *)digest, context);
805: memcpy( &key[i*block_size], digest, block_size);
806: }
807:
808: RETVAL_STRINGL(key, bytes, 1);
809: memset(key, 0, bytes);
810: efree(digest);
811: efree(context);
812: efree(key);
813: }
814: }
815: }
816: }
817: /* }}} */
818:
819: #endif
820:
821: /* {{{ PHP_MINIT_FUNCTION
822: */
823: PHP_MINIT_FUNCTION(hash)
824: {
825: php_hash_le_hash = zend_register_list_destructors_ex(php_hash_dtor, NULL, PHP_HASH_RESNAME, module_number);
826:
827: zend_hash_init(&php_hash_hashtable, 35, NULL, NULL, 1);
828:
829: php_hash_register_algo("md2", &php_hash_md2_ops);
830: php_hash_register_algo("md4", &php_hash_md4_ops);
831: php_hash_register_algo("md5", &php_hash_md5_ops);
832: php_hash_register_algo("sha1", &php_hash_sha1_ops);
833: php_hash_register_algo("sha224", &php_hash_sha224_ops);
834: php_hash_register_algo("sha256", &php_hash_sha256_ops);
835: php_hash_register_algo("sha384", &php_hash_sha384_ops);
836: php_hash_register_algo("sha512", &php_hash_sha512_ops);
837: php_hash_register_algo("ripemd128", &php_hash_ripemd128_ops);
838: php_hash_register_algo("ripemd160", &php_hash_ripemd160_ops);
839: php_hash_register_algo("ripemd256", &php_hash_ripemd256_ops);
840: php_hash_register_algo("ripemd320", &php_hash_ripemd320_ops);
841: php_hash_register_algo("whirlpool", &php_hash_whirlpool_ops);
842: php_hash_register_algo("tiger128,3", &php_hash_3tiger128_ops);
843: php_hash_register_algo("tiger160,3", &php_hash_3tiger160_ops);
844: php_hash_register_algo("tiger192,3", &php_hash_3tiger192_ops);
845: php_hash_register_algo("tiger128,4", &php_hash_4tiger128_ops);
846: php_hash_register_algo("tiger160,4", &php_hash_4tiger160_ops);
847: php_hash_register_algo("tiger192,4", &php_hash_4tiger192_ops);
848: php_hash_register_algo("snefru", &php_hash_snefru_ops);
849: php_hash_register_algo("snefru256", &php_hash_snefru_ops);
850: php_hash_register_algo("gost", &php_hash_gost_ops);
851: php_hash_register_algo("adler32", &php_hash_adler32_ops);
852: php_hash_register_algo("crc32", &php_hash_crc32_ops);
853: php_hash_register_algo("crc32b", &php_hash_crc32b_ops);
1.1.1.2 misho 854: php_hash_register_algo("fnv132", &php_hash_fnv132_ops);
855: php_hash_register_algo("fnv164", &php_hash_fnv164_ops);
856: php_hash_register_algo("joaat", &php_hash_joaat_ops);
1.1 misho 857:
858: PHP_HASH_HAVAL_REGISTER(3,128);
859: PHP_HASH_HAVAL_REGISTER(3,160);
860: PHP_HASH_HAVAL_REGISTER(3,192);
861: PHP_HASH_HAVAL_REGISTER(3,224);
862: PHP_HASH_HAVAL_REGISTER(3,256);
863:
864: PHP_HASH_HAVAL_REGISTER(4,128);
865: PHP_HASH_HAVAL_REGISTER(4,160);
866: PHP_HASH_HAVAL_REGISTER(4,192);
867: PHP_HASH_HAVAL_REGISTER(4,224);
868: PHP_HASH_HAVAL_REGISTER(4,256);
869:
870: PHP_HASH_HAVAL_REGISTER(5,128);
871: PHP_HASH_HAVAL_REGISTER(5,160);
872: PHP_HASH_HAVAL_REGISTER(5,192);
873: PHP_HASH_HAVAL_REGISTER(5,224);
874: PHP_HASH_HAVAL_REGISTER(5,256);
875:
876: REGISTER_LONG_CONSTANT("HASH_HMAC", PHP_HASH_HMAC, CONST_CS | CONST_PERSISTENT);
877:
878: #ifdef PHP_MHASH_BC
879: mhash_init(INIT_FUNC_ARGS_PASSTHRU);
880: #endif
881:
882: return SUCCESS;
883: }
884: /* }}} */
885:
886: /* {{{ PHP_MSHUTDOWN_FUNCTION
887: */
888: PHP_MSHUTDOWN_FUNCTION(hash)
889: {
890: zend_hash_destroy(&php_hash_hashtable);
891:
892: return SUCCESS;
893: }
894: /* }}} */
895:
896: /* {{{ PHP_MINFO_FUNCTION
897: */
898: PHP_MINFO_FUNCTION(hash)
899: {
900: HashPosition pos;
901: char buffer[2048];
902: char *s = buffer, *e = s + sizeof(buffer), *str;
903: ulong idx;
904: long type;
905:
906: for(zend_hash_internal_pointer_reset_ex(&php_hash_hashtable, &pos);
907: (type = zend_hash_get_current_key_ex(&php_hash_hashtable, &str, NULL, &idx, 0, &pos)) != HASH_KEY_NON_EXISTANT;
908: zend_hash_move_forward_ex(&php_hash_hashtable, &pos)) {
909: s += slprintf(s, e - s, "%s ", str);
910: }
911: *s = 0;
912:
913: php_info_print_table_start();
914: php_info_print_table_row(2, "hash support", "enabled");
915: php_info_print_table_row(2, "Hashing Engines", buffer);
916: php_info_print_table_end();
917: }
918: /* }}} */
919:
920: /* {{{ arginfo */
921: #ifdef PHP_HASH_MD5_NOT_IN_CORE
922: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_md5, 0, 0, 1)
923: ZEND_ARG_INFO(0, str)
924: ZEND_ARG_INFO(0, raw_output)
925: ZEND_END_ARG_INFO()
926:
927: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_md5_file, 0, 0, 1)
928: ZEND_ARG_INFO(0, filename)
929: ZEND_ARG_INFO(0, raw_output)
930: ZEND_END_ARG_INFO()
931: #endif
932:
933: #ifdef PHP_HASH_SHA1_NOT_IN_CORE
934: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_sha1, 0, 0, 1)
935: ZEND_ARG_INFO(0, str)
936: ZEND_ARG_INFO(0, raw_output)
937: ZEND_END_ARG_INFO()
938:
939: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_sha1_file, 0, 0, 1)
940: ZEND_ARG_INFO(0, filename)
941: ZEND_ARG_INFO(0, raw_output)
942: ZEND_END_ARG_INFO()
943: #endif
944:
945: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash, 0, 0, 2)
946: ZEND_ARG_INFO(0, algo)
947: ZEND_ARG_INFO(0, data)
948: ZEND_ARG_INFO(0, raw_output)
949: ZEND_END_ARG_INFO()
950:
951: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_file, 0, 0, 2)
952: ZEND_ARG_INFO(0, algo)
953: ZEND_ARG_INFO(0, filename)
954: ZEND_ARG_INFO(0, raw_output)
955: ZEND_END_ARG_INFO()
956:
957: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_hmac, 0, 0, 3)
958: ZEND_ARG_INFO(0, algo)
959: ZEND_ARG_INFO(0, data)
960: ZEND_ARG_INFO(0, key)
961: ZEND_ARG_INFO(0, raw_output)
962: ZEND_END_ARG_INFO()
963:
964: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_hmac_file, 0, 0, 3)
965: ZEND_ARG_INFO(0, algo)
966: ZEND_ARG_INFO(0, filename)
967: ZEND_ARG_INFO(0, key)
968: ZEND_ARG_INFO(0, raw_output)
969: ZEND_END_ARG_INFO()
970:
971: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_init, 0, 0, 1)
972: ZEND_ARG_INFO(0, algo)
973: ZEND_ARG_INFO(0, options)
974: ZEND_ARG_INFO(0, key)
975: ZEND_END_ARG_INFO()
976:
977: ZEND_BEGIN_ARG_INFO(arginfo_hash_update, 0)
978: ZEND_ARG_INFO(0, context)
979: ZEND_ARG_INFO(0, data)
980: ZEND_END_ARG_INFO()
981:
982: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_update_stream, 0, 0, 2)
983: ZEND_ARG_INFO(0, context)
984: ZEND_ARG_INFO(0, handle)
985: ZEND_ARG_INFO(0, length)
986: ZEND_END_ARG_INFO()
987:
988: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_update_file, 0, 0, 2)
989: ZEND_ARG_INFO(0, context)
990: ZEND_ARG_INFO(0, filename)
991: ZEND_ARG_INFO(0, context)
992: ZEND_END_ARG_INFO()
993:
994: ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_final, 0, 0, 1)
995: ZEND_ARG_INFO(0, context)
996: ZEND_ARG_INFO(0, raw_output)
997: ZEND_END_ARG_INFO()
998:
999: ZEND_BEGIN_ARG_INFO(arginfo_hash_copy, 0)
1000: ZEND_ARG_INFO(0, context)
1001: ZEND_END_ARG_INFO()
1002:
1003: ZEND_BEGIN_ARG_INFO(arginfo_hash_algos, 0)
1004: ZEND_END_ARG_INFO()
1005:
1006: /* BC Land */
1007: #ifdef PHP_MHASH_BC
1008: ZEND_BEGIN_ARG_INFO(arginfo_mhash_get_block_size, 0)
1009: ZEND_ARG_INFO(0, hash)
1010: ZEND_END_ARG_INFO()
1011:
1012: ZEND_BEGIN_ARG_INFO(arginfo_mhash_get_hash_name, 0)
1013: ZEND_ARG_INFO(0, hash)
1014: ZEND_END_ARG_INFO()
1015:
1016: ZEND_BEGIN_ARG_INFO(arginfo_mhash_keygen_s2k, 0)
1017: ZEND_ARG_INFO(0, hash)
1018: ZEND_ARG_INFO(0, input_password)
1019: ZEND_ARG_INFO(0, salt)
1020: ZEND_ARG_INFO(0, bytes)
1021: ZEND_END_ARG_INFO()
1022:
1023: ZEND_BEGIN_ARG_INFO(arginfo_mhash_count, 0)
1024: ZEND_END_ARG_INFO()
1025:
1026: ZEND_BEGIN_ARG_INFO_EX(arginfo_mhash, 0, 0, 2)
1027: ZEND_ARG_INFO(0, hash)
1028: ZEND_ARG_INFO(0, data)
1029: ZEND_ARG_INFO(0, key)
1030: ZEND_END_ARG_INFO()
1031: #endif
1032:
1033: /* }}} */
1034:
1035: /* {{{ hash_functions[]
1036: */
1037: const zend_function_entry hash_functions[] = {
1038: PHP_FE(hash, arginfo_hash)
1039: PHP_FE(hash_file, arginfo_hash_file)
1040:
1041: PHP_FE(hash_hmac, arginfo_hash_hmac)
1042: PHP_FE(hash_hmac_file, arginfo_hash_hmac_file)
1043:
1044: PHP_FE(hash_init, arginfo_hash_init)
1045: PHP_FE(hash_update, arginfo_hash_update)
1046: PHP_FE(hash_update_stream, arginfo_hash_update_stream)
1047: PHP_FE(hash_update_file, arginfo_hash_update_file)
1048: PHP_FE(hash_final, arginfo_hash_final)
1049: PHP_FE(hash_copy, arginfo_hash_copy)
1050:
1051: PHP_FE(hash_algos, arginfo_hash_algos)
1052:
1053: /* BC Land */
1054: #ifdef PHP_HASH_MD5_NOT_IN_CORE
1055: PHP_NAMED_FE(md5, php_if_md5, arginfo_hash_md5)
1056: PHP_NAMED_FE(md5_file, php_if_md5_file, arginfo_hash_md5_file)
1057: #endif /* PHP_HASH_MD5_NOT_IN_CORE */
1058:
1059: #ifdef PHP_HASH_SHA1_NOT_IN_CORE
1060: PHP_NAMED_FE(sha1, php_if_sha1, arginfo_hash_sha1)
1061: PHP_NAMED_FE(sha1_file, php_if_sha1_file, arginfo_hash_sha1_file)
1062: #endif /* PHP_HASH_SHA1_NOT_IN_CORE */
1063:
1064: #ifdef PHP_MHASH_BC
1065: PHP_FE(mhash_keygen_s2k, arginfo_mhash_keygen_s2k)
1066: PHP_FE(mhash_get_block_size, arginfo_mhash_get_block_size)
1067: PHP_FE(mhash_get_hash_name, arginfo_mhash_get_hash_name)
1068: PHP_FE(mhash_count, arginfo_mhash_count)
1069: PHP_FE(mhash, arginfo_mhash)
1070: #endif
1071:
1072: PHP_FE_END
1073: };
1074: /* }}} */
1075:
1076: /* {{{ hash_module_entry
1077: */
1078: zend_module_entry hash_module_entry = {
1079: #if ZEND_MODULE_API_NO >= 20010901
1080: STANDARD_MODULE_HEADER,
1081: #endif
1082: PHP_HASH_EXTNAME,
1083: hash_functions,
1084: PHP_MINIT(hash),
1085: PHP_MSHUTDOWN(hash),
1086: NULL, /* RINIT */
1087: NULL, /* RSHUTDOWN */
1088: PHP_MINFO(hash),
1089: #if ZEND_MODULE_API_NO >= 20010901
1090: PHP_HASH_EXTVER, /* Replace with version number for your extension */
1091: #endif
1092: STANDARD_MODULE_PROPERTIES
1093: };
1094: /* }}} */
1095:
1096: #ifdef COMPILE_DL_HASH
1097: ZEND_GET_MODULE(hash)
1098: #endif
1099:
1100: /*
1101: * Local variables:
1102: * tab-width: 4
1103: * c-basic-offset: 4
1104: * End:
1105: * vim600: noet sw=4 ts=4 fdm=marker
1106: * vim<600: noet sw=4 ts=4
1107: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>