chiark / gitweb /
New encrypting tunnel seems to work !
[userv-utils.git] / ipif / mech-blowfish.c
1 /*
2  * Blowfish
3  *
4  * arguments: key size in bits (must be multiple of 8)
5  *
6  * key values: 8 byte random IV and n byte random key
7  *
8  * encoding:         do CBC encryption overwriting message
9  * encoding for MAC: do CBC and prepend last ciphertext block
10  */
11
12 #include "forwarder.h"
13 #include "blowfish.h"
14
15 struct mechdata {
16   unsigned char iv[BLOWFISH_BLOCKBYTES];
17   struct blowfish_cbc_state cbc;
18 };
19
20 static void mds_blowfish(struct mechdata **md_r) {
21   struct mechdata *md;
22   unsigned long keysize;
23   unsigned char key[BLOWFISH_MAXKEYBYTES];
24
25   XMALLOC(md);
26
27   keysize= getarg_ulong();
28   arg_assert(!(keysize & 7));
29   keysize >>= 3;
30   arg_assert(keysize > 0 && keysize <= BLOWFISH_MAXKEYBYTES);
31
32   random_key(md->iv,sizeof(md->iv));
33   random_key(key,keysize);
34
35   blowfish_loadkey(&md->cbc.ek, key,keysize);
36   *md_r= md;
37 }
38
39 static void mes_blowfish(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
40   mds_blowfish(md_r);
41 }
42
43 static void mds_bfmac(struct mechdata **md_r) {
44   mds_blowfish(md_r);
45 }
46
47 static void mes_bfmac(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
48   mds_blowfish(md_r);
49   *maxprefix_io += BLOWFISH_BLOCKBYTES;
50 }
51
52 #define MSGSIZE_OUT                                                   \
53   msgsize= buf->size;                                                 \
54   arg_assert(!(msgsize & (BLOWFISH_BLOCKBYTES-1)));
55
56 #define MSGSIZE_IN                                                    \
57   msgsize= buf->size;                                                 \
58   if (msgsize & (BLOWFISH_BLOCKBYTES-1)) return "not multiple of block size"
59
60 #define FOREACH_BLOCK(func,inptr,outptr)                              \
61  {                                                                    \
62    unsigned char *ptr;                                                \
63    blowfish_cbc_setiv(&md->cbc, md->iv);                              \
64    for (ptr= buf->start;                                              \
65         ptr < buf->start + msgsize;                                   \
66         ptr += BLOWFISH_BLOCKBYTES) {                                 \
67      func(&md->cbc,inptr,outptr);                                     \
68    }                                                                  \
69  }
70
71 static void menc_blowfish(struct mechdata *md, struct buffer *buf) {
72   unsigned long msgsize;
73   MSGSIZE_OUT;
74   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,ptr);
75 }
76
77 static const char *mdec_blowfish(struct mechdata *md, struct buffer *buf) {
78   unsigned long msgsize;
79   MSGSIZE_IN;
80   FOREACH_BLOCK(blowfish_cbc_decrypt,ptr,ptr);
81   return 0;
82 }
83
84 static void menc_bfmac(struct mechdata *md, struct buffer *buf) {
85   unsigned long msgsize;
86   unsigned char outblock[BLOWFISH_BLOCKBYTES];
87   
88   MSGSIZE_OUT;
89   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
90   memcpy(buf_prepend(buf,BLOWFISH_BLOCKBYTES), outblock, BLOWFISH_BLOCKBYTES);
91 }
92
93 static const char *mdec_bfmac(struct mechdata *md, struct buffer *buf) {
94   unsigned long msgsize;
95   unsigned char outblock[BLOWFISH_BLOCKBYTES];
96   unsigned char *checkblock;
97
98   BUF_UNPREPEND(checkblock,buf,BLOWFISH_BLOCKBYTES);
99   MSGSIZE_IN;
100   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
101   if (memcmp(checkblock,outblock,BLOWFISH_BLOCKBYTES)) return "verify failed";
102   return 0;
103 }
104
105 const struct mechanism mechlist_blowfish[]= {
106   STANDARD_MECHANISM("blowfish-cbcmac", bfmac)
107   STANDARD_MECHANISM("blowfish-cbc",    blowfish)
108   { 0 }
109 };