File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / crypt.c
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Tue Apr 19 20:00:31 2011 UTC (13 years, 2 months ago) by misho
Branches: MAIN
CVS tags: io1_7, IO1_6, HEAD
release 1.6

/*************************************************************************
* (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>