/*************************************************************************
* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
* by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: crypt.c,v 1.2 2011/04/19 20:00:31 misho Exp $
*
*************************************************************************/
#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;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>