summaryrefslogtreecommitdiff
path: root/ipif/mech-blowfish.c
blob: 69122221fd1f860038e8291e4ee4c15b42c62a3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * 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 <ijackson@chiark.greenend.org.uk>
 * Copyright 1998 David Damerell <damerell@chiark.greenend.org.uk>
 * Copyright 1999,2003
 *    Chancellor Masters and Scholars of the University of Cambridge
 * Copyright 2010 Tony Finch <fanf@dotat.at>
 *
 * 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 }
};