version 1.1, 2011/03/16 16:59:33
|
version 1.2, 2011/04/19 20:00:31
|
Line 0
|
Line 1
|
|
/************************************************************************* |
|
* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com> |
|
* by Michael Pounov <misho@openbsd-bg.org> |
|
* |
|
* $Author$ |
|
* $Id$ |
|
* |
|
*************************************************************************/ |
|
#include "global.h" |
|
|
|
|
|
/* |
|
* ioCipher() Cipher wrapper for all supported crypto algorythms |
|
* @pInput = input buffer |
|
* @inLen = input buffer len |
|
* @ppOutput = output allocated buffe, must be free after use |
|
* @Cipher = cipher engine, like EVP_bf_cbc() or etc... |
|
* @pKey = key |
|
* @pIV = IV, salt (8 bytes) |
|
* @nMode = Mode 0 - decrypting or 1 - encrypting |
|
* return: 0 not present data or error!; >0 number of processed and returned bytes into ppOutput |
|
*/ |
|
int |
|
ioCipher(u_char *pInput, int inLen, u_char **ppOutput, const EVP_CIPHER *Cipher, |
|
u_char *pKey, u_char *pIV, int nMode) |
|
{ |
|
EVP_CIPHER_CTX ctx; |
|
int chunk, buflen, outlen = 0; |
|
u_char *pos, *buf = NULL; |
|
|
|
if (!pInput || !inLen || !ppOutput || nMode & 0xFFFFFFFE) |
|
return 0; |
|
buf = malloc(inLen + EVP_MAX_BLOCK_LENGTH); |
|
if (!buf) { |
|
LOGERR; |
|
goto end; |
|
} else |
|
memset(buf, 0, inLen + EVP_MAX_BLOCK_LENGTH); |
|
|
|
EVP_CIPHER_CTX_init(&ctx); |
|
EVP_CipherInit_ex(&ctx, Cipher, NULL, pKey, pIV, nMode); |
|
|
|
for (outlen = 0, buflen = -1, pos = pInput; inLen; outlen += buflen) { |
|
chunk = inLen > 7 ? 8 : inLen; |
|
|
|
if (!EVP_CipherUpdate(&ctx, buf + outlen, &buflen, pos, chunk)) { |
|
EVP_CIPHER_CTX_cleanup(&ctx); |
|
outlen = 0; |
|
free(buf); |
|
buf = NULL; |
|
goto end; |
|
} else { |
|
if (nMode && !buflen) |
|
break; |
|
|
|
pos += chunk; |
|
inLen -= chunk; |
|
} |
|
} |
|
if (!EVP_CipherFinal_ex(&ctx, buf + outlen, &buflen)) { |
|
outlen = 0; |
|
free(buf); |
|
buf = NULL; |
|
} else |
|
outlen += buflen; |
|
|
|
EVP_CIPHER_CTX_cleanup(&ctx); |
|
end: |
|
*ppOutput = buf; |
|
return outlen; |
|
} |
|
|
|
/* |
|
* io_Blowfish() Blowfish cipher algorythm, work with ASCII hex strings |
|
* @pInput = input buffer |
|
* @inLen = input buffer len |
|
* @ppOutput = output allocated buffe, must be free after use |
|
* @pKey = key |
|
* @pIV = IV, salt (8 bytes) |
|
* @nMode = Mode 0 - decrypting or 1 - encrypting |
|
* return: 0 not present data or error!; >0 number of processed and returned bytes into ppOutput |
|
*/ |
|
int |
|
io_Blowfish(u_char *pInput, int inLen, u_char **ppOutput, u_char *pKey, u_char *pIV, int nMode) |
|
{ |
|
int len, ret; |
|
register int i; |
|
char bufCH[3], *str = NULL; |
|
u_char *buf = NULL; |
|
|
|
if (!pInput || !inLen || !ppOutput || nMode & 0xFFFFFFFE) |
|
return 0; |
|
|
|
if (nMode) { |
|
len = strlen((char*) pInput); |
|
str = strdup((char*) pInput); |
|
} else { |
|
len = strlen((char*) pInput) / 2; |
|
str = malloc(len + 1); |
|
if (!str) { |
|
LOGERR; |
|
return 0; |
|
} else |
|
memset(str, 0, len + 1); |
|
|
|
for (i = 0; i < len * 2; i += 2) { |
|
strlcpy(bufCH, (char*) &pInput[i], 3); |
|
str[i / 2] = (u_char) strtol(bufCH, NULL, 16); |
|
} |
|
} |
|
|
|
ret = len = ioCipher((u_char*) str, len, &buf, EVP_bf_cbc(), pKey, pIV, nMode); |
|
free(str); |
|
|
|
if (nMode) { |
|
ret *= 2; |
|
*ppOutput = malloc(ret + 1); |
|
if (!*ppOutput) { |
|
LOGERR; |
|
return 0; |
|
} else |
|
memset(*ppOutput, 0, ret + 1); |
|
|
|
for (i = 0; i < len; i++) { |
|
memset(bufCH, 0, 3); |
|
snprintf(bufCH, 3, "%02x", buf[i]); |
|
strlcat((char*) *ppOutput, bufCH, ret + 1); |
|
} |
|
} else |
|
if (ret && buf) |
|
*ppOutput = (u_char*) strdup((char*) buf); |
|
|
|
return ret; |
|
} |