#ifndef _CBC_GENERIC_H #define _CBC_GENERIC_H /* * CBC macro helpers * * Author: JuanJo Ciarlante * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Heavily inspired in loop_AES */ #define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \ int name(ctx_type * ctx, const u_int8_t * in, u_int8_t * out, int ilen, \ const u_int8_t * iv, int encrypt) { \ int ret = ilen, pos; \ const u_int32_t *iv_i; \ if ((ilen) % 16) \ return 0; \ if (encrypt) { \ pos = 0; \ while (pos < ilen) { \ if (pos == 0) \ iv_i = (const u_int32_t*) iv; \ else \ iv_i = (const u_int32_t*) (out - 16); \ *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ \ *((const u_int32_t \ *)(&in[ 0])); \ *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ \ *((const u_int32_t \ *)(&in[ 4])); \ *((u_int32_t *)(&out[ 8])) = iv_i[2] ^ \ *((const u_int32_t \ *)(&in[ 8])); \ *((u_int32_t *)(&out[12])) = iv_i[3] ^ \ *((const u_int32_t \ *)(&in[12])); \ enc_func(ctx, (addr_type) out, \ (addr_type) out); \ in += 16; \ out += 16; \ pos += 16; \ } \ } else { \ pos = ilen - 16; \ in += pos; \ out += pos; \ while (pos >= 0) { \ dec_func(ctx, (const addr_type) in, \ (addr_type) out); \ if (pos == 0) \ iv_i = (const u_int32_t*) (iv); \ else \ iv_i = (const u_int32_t*) (in - 16); \ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \ *((u_int32_t *)(&out[12])) ^= iv_i[3]; \ in -= 16; \ out -= 16; \ pos -= 16; \ } \ } \ return ret; \ } #define CBC_IMPL_BLK8(name, ctx_type, addr_type, enc_func, dec_func) \ int name(ctx_type * ctx, u_int8_t * in, u_int8_t * out, int ilen, \ const u_int8_t * iv, int encrypt) { \ int ret = ilen, pos; \ const u_int32_t *iv_i; \ if ((ilen) % 8) \ return 0; \ if (encrypt) { \ pos = 0; \ while (pos < ilen) { \ if (pos == 0) \ iv_i = (const u_int32_t*) iv; \ else \ iv_i = (const u_int32_t*) (out - 8); \ *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ \ *((const u_int32_t \ *)(&in[ 0])); \ *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ \ *((const u_int32_t \ *)(&in[ 4])); \ enc_func(ctx, (addr_type)out, (addr_type)out); \ in += 8; \ out += 8; \ pos += 8; \ } \ } else { \ pos = ilen - 8; \ in += pos; \ out += pos; \ while (pos >= 0) { \ dec_func(ctx, (const addr_type)in, \ (addr_type)out); \ if (pos == 0) \ iv_i = (const u_int32_t*) (iv); \ else \ iv_i = (const u_int32_t*) (in - 8); \ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ in -= 8; \ out -= 8; \ pos -= 8; \ } \ } \ return ret; \ } #define CBC_DECL(name, ctx_type) \ int name(ctx_type * ctx, u_int8_t * in, u_int8_t * out, int ilen, \ const u_int8_t * iv, int encrypt) /* Eg.: CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); CBC_DECL(AES_cbc_encrypt, aes_context); */ #endif /* _CBC_GENERIC_H */