chiark / gitweb /
crypto debugging, and several bugfixes
[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   struct blowfish_cbc_state cbc;
17 };
18
19 static void mds_blowfish(struct mechdata **md_r) {
20   struct mechdata *md;
21   unsigned long keysize;
22   unsigned char iv[BLOWFISH_BLOCKBYTES];
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(iv,sizeof(iv));
33   random_key(key,keysize);
34
35   blowfish_loadkey(&md->cbc.ek, key,keysize);
36   blowfish_cbc_setiv(&md->cbc, iv);
37
38   *md_r= md;
39 }
40
41 static void mes_blowfish(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
42   mds_blowfish(md_r);
43 }
44
45 static void mds_bfmac(struct mechdata **md_r) {
46   mds_blowfish(md_r);
47 }
48
49 static void mes_bfmac(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
50   mds_blowfish(md_r);
51   *maxprefix_io += BLOWFISH_BLOCKBYTES;
52 }
53
54 #define MSGSIZE_OUT                                                   \
55   msgsize= buf->size;                                                 \
56   arg_assert(!(msgsize & (BLOWFISH_BLOCKBYTES-1)));
57
58 #define MSGSIZE_IN                                                    \
59   msgsize= buf->size;                                                 \
60   if (msgsize & (BLOWFISH_BLOCKBYTES-1)) return "not multiple of block size"
61
62 #define FOREACH_BLOCK(func,inptr,outptr)                              \
63  {                                                                    \
64    unsigned char *ptr;                                                \
65    for (ptr= buf->start;                                              \
66         ptr < buf->start + msgsize;                                   \
67         ptr += BLOWFISH_BLOCKBYTES) {                                 \
68      func(&md->cbc,inptr,outptr);                                     \
69    }                                                                  \
70  }
71
72 static void menc_blowfish(struct mechdata *md, struct buffer *buf) {
73   unsigned long msgsize;
74   MSGSIZE_OUT;
75   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,ptr);
76 }
77
78 static const char *mdec_blowfish(struct mechdata *md, struct buffer *buf) {
79   unsigned long msgsize;
80   MSGSIZE_IN;
81   FOREACH_BLOCK(blowfish_cbc_decrypt,ptr,ptr);
82   return 0;
83 }
84
85 static void menc_bfmac(struct mechdata *md, struct buffer *buf) {
86   unsigned long msgsize;
87   unsigned char outblock[BLOWFISH_BLOCKBYTES];
88   
89   MSGSIZE_OUT;
90   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
91   memcpy(buf_prepend(buf,BLOWFISH_BLOCKBYTES), outblock, BLOWFISH_BLOCKBYTES);
92 }
93
94 static const char *mdec_bfmac(struct mechdata *md, struct buffer *buf) {
95   unsigned long msgsize;
96   unsigned char outblock[BLOWFISH_BLOCKBYTES];
97   unsigned char *checkblock;
98
99   BUF_UNPREPEND(checkblock,buf,BLOWFISH_BLOCKBYTES);
100   MSGSIZE_IN;
101   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
102   if (memcmp(checkblock,outblock,BLOWFISH_BLOCKBYTES)) return "verify failed";
103   return 0;
104 }
105
106 const struct mechanism mechlist_blowfish[]= {
107   STANDARD_MECHANISM("blowfish-cbcmac", bfmac)
108   STANDARD_MECHANISM("blowfish-cbc",    blowfish)
109   { 0 }
110 };