/* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Sascha Schumann | +----------------------------------------------------------------------+ */ #include "php.h" #if HAVE_LIBMCRYPT #include "php_mcrypt.h" #include "fcntl.h" #define NON_FREE #define MCRYPT2 #include "mcrypt.h" function_entry mcrypt_functions[] = { PHP_FE(mcrypt_ecb, NULL) PHP_FE(mcrypt_cbc, NULL) PHP_FE(mcrypt_cfb, NULL) PHP_FE(mcrypt_ofb, NULL) PHP_FE(mcrypt_get_cipher_name, NULL) PHP_FE(mcrypt_get_block_size, NULL) PHP_FE(mcrypt_get_key_size, NULL) PHP_FE(mcrypt_create_iv, NULL) {0}, }; static PHP_MINIT_FUNCTION(mcrypt); zend_module_entry mcrypt_module_entry = { "mcrypt", mcrypt_functions, PHP_MINIT(mcrypt), NULL, NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES, }; #if 0 typedef struct mcrypt_global_struct { int le_h; } mcrypt_global_struct; static mcrypt_global_struct mcryptg; #define MCRYPTG(x) mcryptg.x #endif #define MCRYPT_ARGS2 \ pval *cipher, *data, *key, *mode; \ int td; \ char *ndata; \ size_t bsize; \ size_t nr; \ size_t nsize #define MCRYPT_ARGS MCRYPT_ARGS2; pval *iv #define MCRYPT_CONVERT \ convert_to_long(cipher); \ convert_to_long(mode); \ convert_to_string(data); \ convert_to_string(key) #define MCRYPT_SIZE \ bsize = get_block_size(cipher->value.lval); \ nr = (data->value.str.len + bsize - 1) / bsize; \ nsize = nr * bsize #define MCRYPT_CHECK_TD_CPY \ if(td == -1) { \ php_error(E_WARNING, MCRYPT_FAILED); \ RETURN_FALSE; \ } \ ndata = ecalloc(nr, bsize); \ memcpy(ndata, data->value.str.val, data->value.str.len) #define MCRYPT_CHECK_IV \ convert_to_string(iv); \ if(iv->value.str.len != bsize) { \ php_error(E_WARNING, MCRYPT_IV_WRONG_SIZE); \ RETURN_FALSE; \ } #define MCRYPT_ACTION(x) \ if(mode->value.lval == 0) \ mcrypt_##x(td, ndata, nsize); \ else \ mdecrypt_##x(td, ndata, nsize); \ end_mcrypt_##x(td) #define MCRYPT_IV_WRONG_SIZE "The IV paramater must be as long as the blocksize" #define MCRYPT_FAILED "mcrypt initialization failed" #define MCRYPT_ENTRY(a) REGISTER_LONG_CONSTANT("MCRYPT_" #a, a, CONST_PERSISTENT) static PHP_MINIT_FUNCTION(mcrypt) { /* modes for mcrypt_??? routines */ REGISTER_LONG_CONSTANT("MCRYPT_ENCRYPT", 0, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MCRYPT_DECRYPT", 1, CONST_PERSISTENT); /* sources for mcrypt_create_iv */ REGISTER_LONG_CONSTANT("MCRYPT_DEV_RANDOM", 0, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MCRYPT_DEV_URANDOM", 1, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MCRYPT_RAND", 2, CONST_PERSISTENT); /* ciphers */ MCRYPT_ENTRY(BLOWFISH); MCRYPT_ENTRY(DES); MCRYPT_ENTRY(TripleDES); MCRYPT_ENTRY(ThreeWAY); MCRYPT_ENTRY(GOST); #ifdef CRYPT MCRYPT_ENTRY(CRYPT); #endif #ifdef DES_COMPAT MCRYPT_ENTRY(DES_COMPAT); #endif MCRYPT_ENTRY(SAFER64); MCRYPT_ENTRY(SAFER128); MCRYPT_ENTRY(CAST128); MCRYPT_ENTRY(TEAN); MCRYPT_ENTRY(RC2); #ifdef TWOFISH MCRYPT_ENTRY(TWOFISH); #elif defined(TWOFISH128) MCRYPT_ENTRY(TWOFISH128); MCRYPT_ENTRY(TWOFISH192); MCRYPT_ENTRY(TWOFISH256); #endif #ifdef RC6 MCRYPT_ENTRY(RC6); #endif #ifdef IDEA MCRYPT_ENTRY(IDEA); #endif return SUCCESS; } typedef enum { RANDOM = 0, URANDOM, RAND } iv_source; /* proto mcrypt_create_iv(int size, int source) create an initializing vector (IV) */ PHP_FUNCTION(mcrypt_create_iv) { pval *size, *psource; char *iv; iv_source source; int i; if(ARG_COUNT(ht) != 2 || getParameters(ht, 2, &size, &psource) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(size); convert_to_long(psource); source = psource->value.lval; i = size->value.lval; if(i <= 0) { php_error(E_WARNING, "illegal size input parameter"); RETURN_FALSE; } iv = ecalloc(i, 1); if(source == RANDOM || source == URANDOM) { int fd; fd = open(source == RANDOM ? "/dev/random" : "/dev/urandom", O_RDONLY); if(fd < 0) { efree(iv); php_error(E_WARNING, "cannot open source device"); RETURN_FALSE; } read(fd, iv, i); close(fd); } else { while(i) { iv[--i] = rand(); } } RETURN_STRINGL(iv, size->value.lval, 0); } /* proto mcrypt_get_cipher_name(int cipher) get the name of cipher */ PHP_FUNCTION(mcrypt_get_cipher_name) { pval *cipher; char *str, *nstr; if(ARG_COUNT(ht) != 1 || getParameters(ht, 1, &cipher) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(cipher); str = get_algorithms_name(cipher->value.lval); nstr = estrdup(str); free(str); RETURN_STRING(nstr, 0); } /* proto mcrypt_get_key_size(int cipher) get the key size of cipher */ PHP_FUNCTION(mcrypt_get_key_size) { pval *cipher; if(ARG_COUNT(ht) != 1 || getParameters(ht, 1, &cipher) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(cipher); RETURN_LONG(get_key_size(cipher->value.lval)); } /* proto mcrypt_get_block_size(int cipher) get the block size of cipher */ PHP_FUNCTION(mcrypt_get_block_size) { pval *cipher; if(ARG_COUNT(ht) != 1 || getParameters(ht, 1, &cipher) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long(cipher); RETURN_LONG(get_block_size(cipher->value.lval)); } /* proto mcrypt_ofb(int cipher, string key, string data, int mode, string iv) OFB crypt/decrypt data using key key with cipher cipher starting with iv */ PHP_FUNCTION(mcrypt_ofb) { MCRYPT_ARGS; if(ARG_COUNT(ht) != 5 || getParameters(ht, 5, &cipher, &key, &data, &mode, &iv) == FAILURE) { WRONG_PARAM_COUNT; } MCRYPT_CONVERT; MCRYPT_SIZE; MCRYPT_CHECK_IV; td = init_mcrypt_ofb(cipher->value.lval, key->value.str.val, key->value.str.len, iv->value.str.val); MCRYPT_CHECK_TD_CPY; MCRYPT_ACTION(ofb); RETURN_STRINGL(ndata, nsize, 0); } /* proto mcrypt_cfb(int cipher, string key, string data, int mode, string iv) CFB crypt/decrypt data using key key with cipher cipher starting with iv */ PHP_FUNCTION(mcrypt_cfb) { MCRYPT_ARGS; if(ARG_COUNT(ht) != 5 || getParameters(ht, 5, &cipher, &key, &data, &mode, &iv) == FAILURE) { WRONG_PARAM_COUNT; } MCRYPT_CONVERT; MCRYPT_SIZE; MCRYPT_CHECK_IV; td = init_mcrypt_cfb(cipher->value.lval, key->value.str.val, key->value.str.len, iv->value.str.val); MCRYPT_CHECK_TD_CPY; MCRYPT_ACTION(cfb); RETURN_STRINGL(ndata, nsize, 0); } /* proto mcrypt_cbc(int cipher, string key, string data, int mode [,string iv]) CBC crypt/decrypt data using key key with cipher cipher using optional iv */ PHP_FUNCTION(mcrypt_cbc) { MCRYPT_ARGS; int ac = ARG_COUNT(ht); if(ac < 4 || ac > 5 || getParameters(ht, ac, &cipher, &key, &data, &mode, &iv) == FAILURE) { WRONG_PARAM_COUNT; } MCRYPT_CONVERT; MCRYPT_SIZE; if(ac > 4) { MCRYPT_CHECK_IV; } td = init_mcrypt_cbc(cipher->value.lval, key->value.str.val, key->value.str.len); MCRYPT_CHECK_TD_CPY; if(ac > 4) { mcrypt(td, iv->value.str.val); } MCRYPT_ACTION(cbc); RETURN_STRINGL(ndata, nsize, 0); } /* proto mcrypt_ecb(int cipher, string key, string data, int mode) ECB crypt/decrypt data using key key with cipher cipher */ PHP_FUNCTION(mcrypt_ecb) { MCRYPT_ARGS2; if(ARG_COUNT(ht) != 4 || getParameters(ht, 4, &cipher, &key, &data, &mode) == FAILURE) { WRONG_PARAM_COUNT; } MCRYPT_CONVERT; MCRYPT_SIZE; td = init_mcrypt_ecb(cipher->value.lval, key->value.str.val, key->value.str.len); MCRYPT_CHECK_TD_CPY; MCRYPT_ACTION(ecb); RETURN_STRINGL(ndata, nsize, 0); } #endif