/* * Blowfish mechanism for udp tunnel * * mechanisms: blowfish-cbc, blowfish-cbcmac * arguments: key size in bits (must be multiple of 8) * * key values: 8 byte random IV and n byte random key * * restrictions: plaintext length must be multiple of block size (8 bytes) * encoding: do CBC encryption overwriting message * encoding for MAC: do CBC and prepend last ciphertext block */ /* * This file is part of ipif, part of userv-utils * * Copyright 1996-2013 Ian Jackson * Copyright 1998 David Damerell * Copyright 1999,2003 * Chancellor Masters and Scholars of the University of Cambridge * Copyright 2010 Tony Finch * * This 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 3 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with userv-utils; if not, see http://www.gnu.org/licenses/. */ #include "forwarder.h" #include "blowfish.h" struct mechdata { unsigned char iv[BLOWFISH_BLOCKBYTES]; struct blowfish_cbc_state cbc; }; static void mds_blowfish(struct mechdata **md_r) { struct mechdata *md; unsigned long keysize; unsigned char key[BLOWFISH_MAXKEYBYTES]; XMALLOC(md); keysize= getarg_ulong(); arg_assert(!(keysize & 7)); keysize >>= 3; arg_assert(keysize > 0 && keysize <= BLOWFISH_MAXKEYBYTES); random_key(md->iv,sizeof(md->iv)); random_key(key,keysize); blowfish_loadkey(&md->cbc.ek, key,keysize); *md_r= md; } static void mes_blowfish(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) { mds_blowfish(md_r); } static void mds_bfmac(struct mechdata **md_r) { mds_blowfish(md_r); } static void mes_bfmac(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) { mds_blowfish(md_r); *maxprefix_io += BLOWFISH_BLOCKBYTES; } #define MSGSIZE_OUT \ msgsize= buf->size; \ arg_assert(!(msgsize & (BLOWFISH_BLOCKBYTES-1))); #define MSGSIZE_IN \ msgsize= buf->size; \ if (msgsize & (BLOWFISH_BLOCKBYTES-1)) return "not multiple of block size" #define FOREACH_BLOCK(func,inptr,outptr) \ { \ unsigned char *ptr; \ blowfish_cbc_setiv(&md->cbc, md->iv); \ for (ptr= buf->start; \ ptr < buf->start + msgsize; \ ptr += BLOWFISH_BLOCKBYTES) { \ func(&md->cbc,inptr,outptr); \ } \ } static void menc_blowfish(struct mechdata *md, struct buffer *buf) { unsigned long msgsize; MSGSIZE_OUT; FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,ptr); } static const char *mdec_blowfish(struct mechdata *md, struct buffer *buf) { unsigned long msgsize; MSGSIZE_IN; FOREACH_BLOCK(blowfish_cbc_decrypt,ptr,ptr); return 0; } static void menc_bfmac(struct mechdata *md, struct buffer *buf) { unsigned long msgsize; unsigned char outblock[BLOWFISH_BLOCKBYTES]; MSGSIZE_OUT; FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock); memcpy(buf_prepend(buf,BLOWFISH_BLOCKBYTES), outblock, BLOWFISH_BLOCKBYTES); } static const char *mdec_bfmac(struct mechdata *md, struct buffer *buf) { unsigned long msgsize; unsigned char outblock[BLOWFISH_BLOCKBYTES]; unsigned char *checkblock; BUF_UNPREPEND(checkblock,buf,BLOWFISH_BLOCKBYTES); MSGSIZE_IN; FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock); if (memcmp(checkblock,outblock,BLOWFISH_BLOCKBYTES)) return "verify failed"; return 0; } const struct mechanism mechlist_blowfish[]= { STANDARD_MECHANISM("blowfish-cbcmac", bfmac) STANDARD_MECHANISM("blowfish-cbc", blowfish) { 0 } };