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