--- libaitio/src/crypt.c 2011/03/16 16:59:33 1.1 +++ libaitio/src/crypt.c 2011/04/19 20:00:31 1.2 @@ -0,0 +1,134 @@ +/************************************************************************* +* (C) 2010 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov +* +* $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; +}