chiark / gitweb /
@@ -1,6 +1,7 @@
[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 "mech.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   md= xmalloc(sizeof(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));
57
58 #define MSGSIZE_IN                                                    \
59   msgsize= buf->size;                                                 \
60   if (msgsize & ~BLOWFISH_BLOCKBYTES) return "not multiple of block size"
61
62 #define FOREACH_BLOCK(func,inptr,outptr)                              \
63  {                                                                    \
64    unsigned char *ptr;                                                \
65    ptr= buf->start;                                                   \
66    while (ptr < buf->start + msgsize)                                 \
67      func(&md->cbc,inptr,outptr);                                     \
68  }
69
70 static void menc_blowfish(struct mechdata *md, struct buffer *buf) {
71   unsigned long msgsize;
72   MSGSIZE_OUT;
73   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,ptr);
74 }
75
76 static const char *mdec_blowfish(struct mechdata *md, struct buffer *buf) {
77   unsigned long msgsize;
78   MSGSIZE_IN;
79   FOREACH_BLOCK(blowfish_cbc_decrypt,ptr,ptr);
80   return 0;
81 }
82
83 static void menc_bfmac(struct mechdata *md, struct buffer *buf) {
84   unsigned long msgsize;
85   unsigned char outblock[BLOWFISH_BLOCKBYTES];
86   
87   MSGSIZE_OUT;
88   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
89   memcpy(buf_prepend(buf,BLOWFISH_BLOCKBYTES), outblock, BLOWFISH_BLOCKBYTES);
90 }
91
92 static const char *mdec_bfmac(struct mechdata *md, struct buffer *buf) {
93   unsigned long msgsize;
94   unsigned char outblock[BLOWFISH_BLOCKBYTES];
95   unsigned char *checkblock;
96
97   BUF_UNPREPEND(checkblock,buf,BLOWFISH_BLOCKBYTES);
98   MSGSIZE_IN;
99   FOREACH_BLOCK(blowfish_cbc_encrypt,ptr,outblock);
100   if (memcmp(checkblock,outblock,BLOWFISH_BLOCKBYTES)) return "verify failed";
101   return 0;
102 }
103
104 const struct mechanism mechlist_blowfish[]= {
105   STANDARD_MECHANISM("blowfish-cbcmac", bfmac)
106   STANDARD_MECHANISM("blowfish-cbc",    blowfish)
107   { 0 }
108 };