php-src/ext/mcrypt/mcrypt.c

388 lines
9.5 KiB
C
Raw Normal View History

1999-04-25 17:04:56 +00:00
/*
+----------------------------------------------------------------------+
1999-07-16 13:13:16 +00:00
| PHP version 4.0 |
1999-04-25 17:04:56 +00:00
+----------------------------------------------------------------------+
| Copyright (c) 1997, 1998, 1999, 2000 The PHP Group |
1999-04-25 17:04:56 +00:00
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
1999-07-16 13:13:16 +00:00
| 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_02.txt. |
1999-07-16 13:13:16 +00:00
| 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. |
1999-04-25 17:04:56 +00:00
+----------------------------------------------------------------------+
2000-07-10 10:09:15 +00:00
| Authors: Sascha Schumann <sascha@schumann.cx> |
1999-04-25 17:04:56 +00:00
+----------------------------------------------------------------------+
*/
1999-04-25 16:50:40 +00:00
#include "php.h"
#if HAVE_LIBMCRYPT
#include "php_mcrypt.h"
#include "fcntl.h"
1999-04-25 16:50:40 +00:00
#define NON_FREE
#define MCRYPT2
#include "mcrypt.h"
1999-04-25 16:50:40 +00:00
function_entry mcrypt_functions[] = {
PHP_FE(mcrypt_ecb, NULL)
1999-04-25 17:04:56 +00:00
PHP_FE(mcrypt_cbc, NULL)
PHP_FE(mcrypt_cfb, NULL)
1999-04-25 21:11:29 +00:00
PHP_FE(mcrypt_ofb, NULL)
PHP_FE(mcrypt_get_cipher_name, NULL)
1999-04-25 20:32:15 +00:00
PHP_FE(mcrypt_get_block_size, NULL)
PHP_FE(mcrypt_get_key_size, NULL)
1999-04-25 21:09:07 +00:00
PHP_FE(mcrypt_create_iv, NULL)
1999-04-25 16:50:40 +00:00
{0},
};
1999-08-02 15:02:52 +00:00
static PHP_MINIT_FUNCTION(mcrypt);
1999-04-25 16:50:40 +00:00
zend_module_entry mcrypt_module_entry = {
"mcrypt",
mcrypt_functions,
1999-08-02 15:02:52 +00:00
PHP_MINIT(mcrypt), NULL,
1999-04-25 16:50:40 +00:00
NULL, NULL,
NULL,
STANDARD_MODULE_PROPERTIES,
};
2000-05-02 03:29:28 +00:00
#ifdef COMPILE_DL_MCRYPT
ZEND_GET_MODULE(mcrypt)
#endif
1999-04-25 16:50:40 +00:00
#if 0
typedef struct mcrypt_global_struct {
int le_h;
} mcrypt_global_struct;
static mcrypt_global_struct mcryptg;
#define MCRYPTG(x) mcryptg.x
#endif
1999-09-17 09:40:51 +00:00
#define MCRYPT_ARGS2 \
pval **cipher, **data, **key, **mode; \
int td; \
char *ndata; \
size_t bsize; \
size_t nr; \
1999-04-25 21:32:52 +00:00
size_t nsize
1999-09-17 09:40:51 +00:00
#define MCRYPT_ARGS \
MCRYPT_ARGS2; \
pval **iv
1999-04-25 21:32:52 +00:00
1999-09-17 09:40:51 +00:00
#define MCRYPT_CONVERT \
convert_to_long_ex(cipher); \
convert_to_long_ex(mode); \
convert_to_string_ex(data); \
convert_to_string_ex(key)
1999-04-25 21:32:52 +00:00
1999-09-17 09:40:51 +00:00
#define MCRYPT_SIZE \
bsize = mcrypt_get_block_size((*cipher)->value.lval); \
1999-09-17 09:40:51 +00:00
nr = ((*data)->value.str.len + bsize - 1) / bsize; \
1999-04-25 21:24:07 +00:00
nsize = nr * bsize
1999-09-17 09:40:51 +00:00
#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_ex(iv); \
if((*iv)->value.str.len != bsize) { \
php_error(E_WARNING, MCRYPT_IV_WRONG_SIZE); \
RETURN_FALSE; \
1999-04-25 21:24:07 +00:00
}
1999-09-17 09:40:51 +00:00
#define MCRYPT_ACTION(x) \
if((*mode)->value.lval == 0) \
mcrypt_##x(td, ndata, nsize); \
else \
mdecrypt_##x(td, ndata, nsize); \
1999-04-25 21:24:07 +00:00
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_NAMED(a,b) REGISTER_LONG_CONSTANT("MCRYPT_" #a, b, CONST_PERSISTENT)
#define MCRYPT_ENTRY2(a) MCRYPT_ENTRY_NAMED(a, MCRYPT_##a)
#define MCRYPT_ENTRY(a) MCRYPT_ENTRY_NAMED(a, a)
1999-04-25 16:50:40 +00:00
1999-08-02 15:02:52 +00:00
static PHP_MINIT_FUNCTION(mcrypt)
1999-04-25 16:50:40 +00:00
{
1999-04-25 21:09:07 +00:00
/* modes for mcrypt_??? routines */
1999-06-27 21:46:34 +00:00
REGISTER_LONG_CONSTANT("MCRYPT_ENCRYPT", 0, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MCRYPT_DECRYPT", 1, CONST_PERSISTENT);
1999-04-25 21:09:07 +00:00
/* sources for mcrypt_create_iv */
1999-06-27 21:46:34 +00:00
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);
1999-04-25 21:09:07 +00:00
/* ciphers */
#if defined(MCRYPT_API_VERSION) && MCRYPT_API_VERSION >= 19991015
MCRYPT_ENTRY2(BLOWFISH_448);
MCRYPT_ENTRY2(DES);
MCRYPT_ENTRY2(3DES);
MCRYPT_ENTRY2(3WAY);
MCRYPT_ENTRY2(GOST);
MCRYPT_ENTRY2(SAFER_64);
MCRYPT_ENTRY2(SAFER_128);
MCRYPT_ENTRY2(CAST_128);
MCRYPT_ENTRY2(XTEA);
MCRYPT_ENTRY2(RC2_1024);
MCRYPT_ENTRY2(TWOFISH_128);
MCRYPT_ENTRY2(TWOFISH_192);
MCRYPT_ENTRY2(TWOFISH_256);
MCRYPT_ENTRY2(BLOWFISH_128);
MCRYPT_ENTRY2(BLOWFISH_192);
MCRYPT_ENTRY2(BLOWFISH_256);
MCRYPT_ENTRY2(CAST_256);
MCRYPT_ENTRY2(SAFERPLUS);
MCRYPT_ENTRY2(LOKI97);
MCRYPT_ENTRY2(SERPENT_128);
MCRYPT_ENTRY2(SERPENT_192);
MCRYPT_ENTRY2(SERPENT_256);
MCRYPT_ENTRY2(RIJNDAEL_128);
MCRYPT_ENTRY2(RIJNDAEL_192);
MCRYPT_ENTRY2(RIJNDAEL_256);
MCRYPT_ENTRY2(RC2_256);
MCRYPT_ENTRY2(RC2_128);
MCRYPT_ENTRY2(RC6_256);
MCRYPT_ENTRY2(IDEA);
MCRYPT_ENTRY2(RC6_128);
MCRYPT_ENTRY2(RC6_192);
MCRYPT_ENTRY2(RC4);
#else
#error Please update your mcrypt library
1999-04-25 16:50:40 +00:00
#endif
1999-04-25 16:50:40 +00:00
return SUCCESS;
}
1999-04-25 20:32:15 +00:00
1999-04-25 21:09:07 +00:00
typedef enum {
RANDOM = 0,
URANDOM,
RAND
} iv_source;
2000-05-26 17:20:36 +00:00
/* {{{ proto string mcrypt_create_iv(int size, int source)
Create an initializing vector (IV) */
1999-04-25 21:09:07 +00:00
PHP_FUNCTION(mcrypt_create_iv)
{
1999-09-17 09:40:51 +00:00
pval **size, **psource;
1999-04-25 21:09:07 +00:00
char *iv;
iv_source source;
int i;
1999-09-17 09:40:51 +00:00
int n = 0;
1999-04-25 21:09:07 +00:00
if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &size, &psource) == FAILURE) {
1999-04-25 21:09:07 +00:00
WRONG_PARAM_COUNT;
}
1999-09-17 09:40:51 +00:00
convert_to_long_ex(size);
convert_to_long_ex(psource);
source = (*psource)->value.lval;
i = (*size)->value.lval;
if(i <= 0) {
php_error(E_WARNING, "illegal size input parameter");
RETURN_FALSE;
}
1999-04-25 21:09:07 +00:00
iv = ecalloc(i, 1);
if(source == RANDOM || source == URANDOM) {
int fd;
size_t read_bytes = 0;
1999-04-25 21:09:07 +00:00
fd = open(source == RANDOM ? "/dev/random" : "/dev/urandom",
O_RDONLY);
if(fd < 0) {
efree(iv);
php_error(E_WARNING, "cannot open source device");
1999-04-25 21:09:07 +00:00
RETURN_FALSE;
}
while (read_bytes < i) {
n = read(fd, iv + read_bytes, i - read_bytes);
if (n < 0)
break;
read_bytes += n;
}
n = read_bytes;
1999-04-25 21:09:07 +00:00
close(fd);
} else {
1999-04-25 21:50:24 +00:00
while(i) {
1999-09-17 09:40:51 +00:00
iv[--i] = 255.0 * rand() / RAND_MAX;
1999-04-25 21:09:07 +00:00
}
1999-09-17 09:40:51 +00:00
n = (*size)->value.lval;
1999-04-25 21:09:07 +00:00
}
1999-09-17 09:40:51 +00:00
RETURN_STRINGL(iv, n, 0);
1999-04-25 21:09:07 +00:00
}
2000-05-26 17:20:36 +00:00
/* }}} */
1999-04-25 21:09:07 +00:00
2000-05-26 17:20:36 +00:00
/* {{{ proto string mcrypt_get_cipher_name(int cipher)
2000-06-18 19:18:30 +00:00
Get the name of cipher */
PHP_FUNCTION(mcrypt_get_cipher_name)
{
1999-09-17 09:40:51 +00:00
pval **cipher;
char *str, *nstr;
if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &cipher) == FAILURE) {
WRONG_PARAM_COUNT;
}
1999-09-17 09:40:51 +00:00
convert_to_long_ex(cipher);
str = mcrypt_get_algorithms_name((*cipher)->value.lval);
if (str) {
nstr = estrdup(str);
free(str);
RETURN_STRING(nstr, 0);
}
RETURN_FALSE;
}
2000-05-26 17:20:36 +00:00
/* }}} */
2000-05-26 17:20:36 +00:00
/* {{{ proto int mcrypt_get_key_size(int cipher)
2000-06-18 19:18:30 +00:00
Get the key size of cipher */
1999-04-25 20:32:15 +00:00
PHP_FUNCTION(mcrypt_get_key_size)
{
1999-09-17 09:40:51 +00:00
pval **cipher;
1999-04-25 20:32:15 +00:00
if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &cipher) == FAILURE) {
1999-04-25 20:32:15 +00:00
WRONG_PARAM_COUNT;
}
1999-09-17 09:40:51 +00:00
convert_to_long_ex(cipher);
1999-04-25 20:32:15 +00:00
RETURN_LONG(mcrypt_get_key_size((*cipher)->value.lval));
1999-04-25 20:32:15 +00:00
}
2000-05-26 17:20:36 +00:00
/* }}} */
1999-04-25 20:32:15 +00:00
2000-05-26 17:20:36 +00:00
/* {{{ proto int mcrypt_get_block_size(int cipher)
2000-06-18 19:18:30 +00:00
Get the block size of cipher */
1999-04-25 20:32:15 +00:00
PHP_FUNCTION(mcrypt_get_block_size)
{
1999-09-17 09:40:51 +00:00
pval **cipher;
1999-04-25 20:32:15 +00:00
if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &cipher) == FAILURE) {
1999-04-25 20:32:15 +00:00
WRONG_PARAM_COUNT;
}
1999-09-17 09:40:51 +00:00
convert_to_long_ex(cipher);
1999-04-25 20:32:15 +00:00
RETURN_LONG(mcrypt_get_block_size((*cipher)->value.lval));
1999-04-25 20:32:15 +00:00
}
2000-05-26 17:20:36 +00:00
/* }}} */
1999-04-25 16:50:40 +00:00
2000-05-26 17:20:36 +00:00
/* {{{ proto string 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 */
1999-04-25 21:11:29 +00:00
PHP_FUNCTION(mcrypt_ofb)
{
1999-04-25 21:32:52 +00:00
MCRYPT_ARGS;
if(ZEND_NUM_ARGS() != 5 ||
1999-12-18 22:40:35 +00:00
zend_get_parameters_ex(5, &cipher, &key, &data, &mode, &iv) == FAILURE) {
1999-04-25 21:11:29 +00:00
WRONG_PARAM_COUNT;
}
1999-04-25 21:32:52 +00:00
MCRYPT_CONVERT;
1999-04-25 21:24:07 +00:00
MCRYPT_SIZE;
MCRYPT_CHECK_IV;
1999-04-25 21:11:29 +00:00
1999-09-17 09:40:51 +00:00
td = init_mcrypt_ofb((*cipher)->value.lval, (*key)->value.str.val, (*key)->value.str.len, (*iv)->value.str.val);
1999-04-25 21:24:07 +00:00
MCRYPT_CHECK_TD_CPY;
MCRYPT_ACTION(ofb);
1999-04-25 21:11:29 +00:00
RETURN_STRINGL(ndata, nsize, 0);
}
2000-05-26 17:20:36 +00:00
/* }}} */
1999-04-25 21:11:29 +00:00
2000-05-26 17:20:36 +00:00
/* {{{ proto string 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)
1999-04-25 17:04:56 +00:00
{
1999-04-25 21:32:52 +00:00
MCRYPT_ARGS;
1999-04-25 17:04:56 +00:00
if(ZEND_NUM_ARGS() != 5 ||
1999-12-18 22:40:35 +00:00
zend_get_parameters_ex(5, &cipher, &key, &data, &mode, &iv) == FAILURE) {
1999-04-25 17:04:56 +00:00
WRONG_PARAM_COUNT;
}
1999-04-25 21:32:52 +00:00
MCRYPT_CONVERT;
1999-04-25 21:24:07 +00:00
MCRYPT_SIZE;
MCRYPT_CHECK_IV;
1999-04-25 17:04:56 +00:00
1999-09-17 09:40:51 +00:00
td = init_mcrypt_cfb((*cipher)->value.lval, (*key)->value.str.val, (*key)->value.str.len, (*iv)->value.str.val);
1999-04-25 21:24:07 +00:00
MCRYPT_CHECK_TD_CPY;
MCRYPT_ACTION(cfb);
RETURN_STRINGL(ndata, nsize, 0);
}
2000-05-26 17:20:36 +00:00
/* }}} */
1999-04-25 21:24:07 +00:00
2000-06-18 19:18:30 +00:00
/* {{{ proto string 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)
{
1999-04-25 21:32:52 +00:00
MCRYPT_ARGS;
int ac = ZEND_NUM_ARGS();
if(ac < 4 || ac > 5 ||
1999-12-18 22:40:35 +00:00
zend_get_parameters_ex(ac, &cipher, &key, &data, &mode, &iv) == FAILURE) {
WRONG_PARAM_COUNT;
}
1999-04-25 21:32:52 +00:00
MCRYPT_CONVERT;
1999-04-25 21:24:07 +00:00
MCRYPT_SIZE;
if(ac > 4) {
1999-04-25 21:24:07 +00:00
MCRYPT_CHECK_IV;
1999-04-25 17:04:56 +00:00
}
1999-09-17 09:40:51 +00:00
td = init_mcrypt_cbc((*cipher)->value.lval, (*key)->value.str.val, (*key)->value.str.len);
1999-04-25 21:24:07 +00:00
MCRYPT_CHECK_TD_CPY;
1999-04-25 17:04:56 +00:00
if(ac > 4) {
1999-09-17 09:40:51 +00:00
mcrypt(td, (*iv)->value.str.val);
}
1999-04-25 21:24:07 +00:00
MCRYPT_ACTION(cbc);
1999-04-25 17:04:56 +00:00
RETURN_STRINGL(ndata, nsize, 0);
}
2000-05-26 17:20:36 +00:00
/* }}} */
1999-04-25 17:04:56 +00:00
2000-05-26 17:20:36 +00:00
/* {{{ proto string mcrypt_ecb(int cipher, string key, string data, int mode)
1999-04-25 17:04:56 +00:00
ECB crypt/decrypt data using key key with cipher cipher */
1999-04-25 16:50:40 +00:00
PHP_FUNCTION(mcrypt_ecb)
{
1999-04-25 21:32:52 +00:00
MCRYPT_ARGS2;
1999-04-25 16:50:40 +00:00
if(ZEND_NUM_ARGS() != 4 ||
1999-12-18 22:40:35 +00:00
zend_get_parameters_ex(4, &cipher, &key, &data, &mode) == FAILURE) {
1999-04-25 16:50:40 +00:00
WRONG_PARAM_COUNT;
}
1999-04-25 21:32:52 +00:00
MCRYPT_CONVERT;
1999-04-25 21:24:07 +00:00
MCRYPT_SIZE;
1999-04-25 16:50:40 +00:00
1999-09-17 09:40:51 +00:00
td = init_mcrypt_ecb((*cipher)->value.lval, (*key)->value.str.val, (*key)->value.str.len);
1999-04-25 21:24:07 +00:00
MCRYPT_CHECK_TD_CPY;
MCRYPT_ACTION(ecb);
1999-04-25 16:50:40 +00:00
RETURN_STRINGL(ndata, nsize, 0);
}
2000-05-26 17:20:36 +00:00
/* }}} */
1999-04-25 16:50:40 +00:00
#endif