Makefile.in: Drop dist target
[secnet] / transform-eax.c
1 /*
2 * eax-transform.c: EAX-Serpent bulk data transformation
3 */
4 /*
5 * This file is part of secnet.
6 * See README for full list of copyright holders.
7 *
8 * secnet is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * secnet is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * version 3 along with secnet; if not, see
20 * https://www.gnu.org/licenses/gpl.html.
21 */
22 /*
23 * We use EAX with the following parameters:
24 *
25 * Plaintext:
26 * Concatenation of:
27 * Data packet as supplied to us
28 * Zero or more zero bytes ignored by receiver } padding
29 * One byte padding length }
30 * This is a bit like PKCS#5. It helps disguise message lengths.
31 * It also provides a further room for future expansion. When
32 * transmitting we pad the message to the next multiple of
33 * a configurable rounding factor, 16 bytes by default.
34 *
35 * Transmitted message:
36 * Concatenation of:
37 * EAX ciphertext
38 * 32-bit sequence number (initially zero)
39 * The sequence number allows us to discard far-too-old
40 * packets.
41 *
42 * Nonce:
43 * Concatenation of:
44 * 32-bit sequence number (big endian)
45 * initial value comes from SHA-512 hash (see below)
46 * 1 byte: 0x01 if sender has setup priority, 0x00 if it doesn't
47 * (ie, the direction of data flow)
48 *
49 * Header: None
50 *
51 * Tag length:
52 * 16 bytes (128 bits) by default
53 *
54 * Key:
55 * The first 32 bytes of the SHA-512 hash of the shared secret
56 * from the DH key exchange (the latter being expressed as
57 * the shortest possible big-endian octet string).
58 *
59 * The bytes [32,40> of the hash of the shared secret are used for
60 * initial sequence numbers: [32,36> for those sent by the end without
61 * setup priority, [36,40> for those for the other end.
62 *
63 */
64
65 #include "secnet.h"
66 #include "unaligned.h"
67 #include "util.h"
68 #include "serpent.h"
69 #include "sha512.h"
70 #include "transform-common.h"
71 #include "hexdebug.h"
72
73 #define BLOCK_SIZE 16
74 #define SEQLEN 4
75
76 struct transform_params {
77 SEQNUM_PARAMS_FIELDS;
78 uint32_t tag_length, padding_mask;
79 };
80
81 struct transform {
82 closure_t cl;
83 struct transform_if ops;
84 struct transform_params p;
85 };
86
87 struct transform_inst {
88 struct transform_inst_if ops;
89 struct transform_params p;
90 /* remaining valid iff keyed */
91 unsigned direction:1;
92 SEQNUM_KEYED_FIELDS;
93 struct keyInstance key;
94 uint8_t info_b[BLOCK_SIZE], info_p[BLOCK_SIZE];
95 };
96
97 static void block_encrypt(struct transform_inst *transform_inst,
98 uint8_t dst[BLOCK_SIZE],
99 const uint8_t src[BLOCK_SIZE])
100 {
101 serpent_encrypt(&transform_inst->key, src, dst);
102 }
103
104 #define INFO struct transform_inst *transform_inst
105 #define I transform_inst
106 #define EAX_ENTRYPOINT_DECL static
107 #define BLOCK_ENCRYPT(dst,src) block_encrypt(transform_inst,dst,src)
108 #define INFO_B (transform_inst->info_b)
109 #define INFO_P (transform_inst->info_p)
110
111 #include "eax.c"
112
113 #if 0
114
115 #define TEAX_DEBUG(ary,sz) teax_debug(__func__,__LINE__,#ary,#sz,ary,sz)
116 static void teax_debug(const char *func, int line,
117 const char *aryp, const char *szp,
118 const void *ary, size_t sz)
119 {
120 fprintf(stderr,"TEAX %s:%-3d %10s %15s : ", func,line,aryp,szp);
121 hexdebug(stderr,ary,sz);
122 fprintf(stderr,"\n");
123 }
124
125 #else
126
127 #define TEAX_DEBUG(ary,sz) /* empty */
128
129 #endif
130
131 static bool_t transform_setkey(void *sst, uint8_t *key, int32_t keylen,
132 bool_t direction)
133 {
134 struct transform_inst *ti=sst;
135 struct sha512_ctx hash_ctx;
136 uint8_t hash_out[64];
137
138 TEAX_DEBUG(key,keylen);
139
140 sha512_init_ctx(&hash_ctx);
141 sha512_process_bytes(key, keylen, &hash_ctx);
142 sha512_finish_ctx(&hash_ctx, hash_out);
143
144 TEAX_DEBUG(hash_out,32);
145 TEAX_DEBUG(hash_out+32,8);
146
147 ti->direction=direction;
148 serpent_makekey(&ti->key, 32*8, hash_out);
149 eax_setup(ti);
150 SEQNUM_KEYED_INIT(get_uint32(hash_out+32+!direction*4),
151 get_uint32(hash_out+32+direction*4));
152
153 return True;
154 }
155
156 TRANSFORM_VALID;
157
158 TRANSFORM_DESTROY;
159
160 static void transform_delkey(void *sst)
161 {
162 struct transform_inst *ti=sst;
163
164 FILLZERO(ti->key);
165 FILLZERO(ti->info_b);
166 FILLZERO(ti->info_p);
167 ti->keyed=False;
168 }
169
170 static transform_apply_return transform_forward(void *sst,
171 struct buffer_if *buf, const char **errmsg)
172 {
173 struct transform_inst *ti=sst;
174
175 KEYED_CHECK;
176
177 size_t padlen = ti->p.padding_mask - buf->size;
178 padlen &= ti->p.padding_mask;
179 padlen++;
180
181 uint8_t *pad = buf_append(buf,padlen);
182 memset(pad, 0, padlen-1);
183 pad[padlen-1] = padlen;
184
185 uint8_t nonce[SEQLEN+1];
186 put_uint32(nonce,ti->sendseq);
187 nonce[SEQLEN] = ti->direction;
188
189 TEAX_DEBUG(nonce,sizeof(nonce));
190 TEAX_DEBUG(buf->start,buf->size);
191
192 assert(buf_append(buf,ti->p.tag_length));
193 eax_encrypt(ti, nonce,sizeof(nonce), 0,0,
194 buf->start,buf->size-ti->p.tag_length,
195 ti->p.tag_length, buf->start);
196
197 TEAX_DEBUG(buf->start,buf->size);
198
199 BUF_ADD_BYTES(append,buf,nonce,SEQLEN);
200
201 TEAX_DEBUG(nonce,SEQLEN);
202
203 ti->sendseq++;
204
205 return 0;
206 }
207
208 static transform_apply_return transform_reverse(void *sst,
209 struct buffer_if *buf, const char **errmsg)
210 {
211 struct transform_inst *ti=sst;
212
213 KEYED_CHECK;
214
215 TEAX_DEBUG(buf->start,buf->size);
216
217 uint8_t nonce[SEQLEN+1];
218 const uint8_t *seqp = buf_unappend(buf,SEQLEN);
219 if (!seqp) goto too_short;
220
221 TEAX_DEBUG(seqp,SEQLEN);
222
223 uint32_t seqnum = get_uint32(seqp);
224
225 memcpy(nonce,seqp,SEQLEN);
226 nonce[4] = !ti->direction;
227
228 TEAX_DEBUG(nonce,sizeof(nonce));
229 TEAX_DEBUG(buf->start,buf->size);
230
231 bool_t ok = eax_decrypt(ti, nonce,sizeof(nonce), 0,0, buf->start,buf->size,
232 ti->p.tag_length, buf->start);
233 if (!ok) {
234 TEAX_DEBUG(0,0);
235 *errmsg="EAX decryption failed";
236 return transform_apply_err;
237 }
238 assert(buf->size >= (int)ti->p.tag_length);
239 buf->size -= ti->p.tag_length;
240
241 TEAX_DEBUG(buf->start,buf->size);
242
243 const uint8_t *padp = buf_unappend(buf,1);
244 if (!padp) goto too_short;
245
246 TEAX_DEBUG(padp,1);
247
248 size_t padlen = *padp;
249 if (!buf_unappend(buf,padlen-1)) goto too_short;
250
251 SEQNUM_CHECK(seqnum, &ti->p);
252
253 TEAX_DEBUG(buf->start,buf->size);
254
255 return 0;
256
257 too_short:
258 *errmsg="ciphertext or plaintext too short";
259 return transform_apply_err;
260 }
261
262 static struct transform_inst_if *transform_create(void *sst)
263 {
264 struct transform *st=sst;
265
266 TRANSFORM_CREATE_CORE;
267
268 ti->p=st->p;
269
270 return &ti->ops;
271 }
272
273 static list_t *transform_apply(closure_t *self, struct cloc loc,
274 dict_t *context, list_t *args)
275 {
276 struct transform *st;
277 item_t *item;
278 dict_t *dict;
279
280 NEW(st);
281 st->cl.description="eax-serpent";
282 st->cl.type=CL_TRANSFORM;
283 st->cl.apply=NULL;
284 st->cl.interface=&st->ops;
285 st->ops.st=st;
286
287 /* First parameter must be a dict */
288 item=list_elem(args,0);
289 if (!item || item->type!=t_dict)
290 cfgfatal(loc,"eax-serpent","parameter must be a dictionary\n");
291 dict=item->data.dict;
292
293 SET_CAPAB_TRANSFORMNUM(CAPAB_TRANSFORMNUM_EAXSERPENT);
294
295 SEQNUM_PARAMS_INIT(dict,&st->p,"eax-serpent",loc);
296
297 st->p.tag_length=dict_read_number(dict, "tag-length-bytes",
298 False, "eax-serpent", loc, 128/8);
299 if (st->p.tag_length<1 || st->p.tag_length>BLOCK_SIZE)
300 cfgfatal(loc,"eax-serpent","tag-length-bytes out of range 0..%d\n",
301 BLOCK_SIZE);
302
303 uint32_t padding_round=dict_read_number(dict, "padding-rounding",
304 False, "eax-serpent", loc, 16);
305 if (padding_round & (padding_round-1))
306 cfgfatal(loc,"eax-serpent","padding-round not a power of two\n");
307 if (padding_round > 255)
308 cfgfatal(loc,"eax-serpent","padding-round must be 1..128\n");
309 if (padding_round == 0)
310 padding_round = 1;
311 st->p.padding_mask = padding_round-1;
312
313 update_max_start_pad(&transform_max_start_pad, 0);
314
315 st->ops.keylen=0;
316 st->ops.create=transform_create;
317
318 return new_closure(&st->cl);
319 }
320
321 void transform_eax_module(dict_t *dict)
322 {
323 add_closure(dict,"eax-serpent",transform_apply);
324 }