chiark / gitweb /
@@ -1,3 +1,9 @@
[userv-utils.git] / ipif / mech-blowfish.c
1 /*
2  * Blowfish mechanism for udp tunnel
3  *
4  * mechanisms: blowfish-cbc, blowfish-cbcmac
5  * arguments: key size in bits (must be multiple of 8)
6  *
7  * key values: 8 byte random IV and n byte random key
8  *
9  * restrictions: plaintext length must be multiple of block size (8 bytes)
10  * encoding:         do CBC encryption overwriting message
11  * encoding for MAC: do CBC and prepend last ciphertext block
12  */
13 /*
14  * Copyright (C) 2000 Ian Jackson
15  *
16  * This is free software; you can redistribute it and/or modify it
17  * under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with userv-utils; if not, write to the Free Software
28  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29  */
30
31 #include "forwarder.h"
32 #include "blowfish.h"
33
34 struct mechdata {
35   unsigned char iv[BLOWFISH_BLOCKBYTES];
36   struct blowfish_cbc_state cbc;
37 };
38
39 static void mds_blowfish(struct mechdata **md_r) {
40   struct mechdata *md;
41   unsigned long keysize;
42   unsigned char key[BLOWFISH_MAXKEYBYTES];
43
44   XMALLOC(md);
45
46   keysize= getarg_ulong();
47   arg_assert(!(keysize & 7));
48   keysize >>= 3;
49   arg_assert(keysize > 0 && keysize <= BLOWFISH_MAXKEYBYTES);
50
51   random_key(md->iv,sizeof(md->iv));
52   random_key(key,keysize);
53
54   blowfish_loadkey(&md->cbc.ek, key,keysize);
55   *md_r= md;
56 }
57
58 static void mes_blowfish(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
59   mds_blowfish(md_r);
60 }
61
62 static void mds_bfmac(struct mechdata **md_r) {
63   mds_blowfish(md_r);
64 }
65
66 static void mes_bfmac(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
67   mds_blowfish(md_r);
68   *maxprefix_io += BLOWFISH_BLOCKBYTES;
69 }
70
71 #define MSGSIZE_OUT                                                   \
72   msgsize= buf->size;                                                 \
73   arg_assert(!(msgsize & (BLOWFISH_BLOCKBYTES-1)));
74
75 #define MSGSIZE_IN                                                    \
76   msgsize= buf->size;                                                 \
77   if (msgsize & (BLOWFISH_BLOCKBYTES-1)) return "not multiple of block size"
78
79 #define FOREACH_BLOCK(func,inptr,outptr)                              \
80  {                                                                    \
81    unsigned char *ptr;                                                \
82    blowfish_cbc_setiv(&md->cbc, md->iv);                              \
83    for (ptr= buf->start;                                              \
84         ptr < buf->start + msgsize;                                   \
85         ptr += BLOWFISH_BLOCKBYTES) {                                 \
86      func(&md->cbc,inptr,outptr);                                     \
87    }                                                                  \
88  }
89
90 static void menc_blowfish(struct mechdata *md, struct buffer *buf) {
91   unsigned long msgsize;
92   MSGSIZE_OUT;
93   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,ptr);
94 }
95
96 static const char *mdec_blowfish(struct mechdata *md, struct buffer *buf) {
97   unsigned long msgsize;
98   MSGSIZE_IN;
99   FOREACH_BLOCK(blowfish_cbc_decrypt,ptr,ptr);
100   return 0;
101 }
102
103 static void menc_bfmac(struct mechdata *md, struct buffer *buf) {
104   unsigned long msgsize;
105   unsigned char outblock[BLOWFISH_BLOCKBYTES];
106   
107   MSGSIZE_OUT;
108   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
109   memcpy(buf_prepend(buf,BLOWFISH_BLOCKBYTES), outblock, BLOWFISH_BLOCKBYTES);
110 }
111
112 static const char *mdec_bfmac(struct mechdata *md, struct buffer *buf) {
113   unsigned long msgsize;
114   unsigned char outblock[BLOWFISH_BLOCKBYTES];
115   unsigned char *checkblock;
116
117   BUF_UNPREPEND(checkblock,buf,BLOWFISH_BLOCKBYTES);
118   MSGSIZE_IN;
119   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
120   if (memcmp(checkblock,outblock,BLOWFISH_BLOCKBYTES)) return "verify failed";
121   return 0;
122 }
123
124 const struct mechanism mechlist_blowfish[]= {
125   STANDARD_MECHANISM("blowfish-cbcmac", bfmac)
126   STANDARD_MECHANISM("blowfish-cbc",    blowfish)
127   { 0 }
128 };