Add a return value to aead_t.encrypt()
[strongswan.git] / src / libstrongswan / plugins / gcm / gcm_aead.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "gcm_aead.h"
17
18 #include <limits.h>
19
20 #define BLOCK_SIZE 16
21 #define NONCE_SIZE 12
22 #define IV_SIZE 8
23 #define SALT_SIZE (NONCE_SIZE - IV_SIZE)
24
25 typedef struct private_gcm_aead_t private_gcm_aead_t;
26
27 /**
28 * Private data of an gcm_aead_t object.
29 */
30 struct private_gcm_aead_t {
31
32 /**
33 * Public gcm_aead_t interface.
34 */
35 gcm_aead_t public;
36
37 /**
38 * Underlying CBC crypter.
39 */
40 crypter_t *crypter;
41
42 /**
43 * Size of the integrity check value
44 */
45 size_t icv_size;
46
47 /**
48 * Salt value
49 */
50 char salt[SALT_SIZE];
51
52 /**
53 * GHASH subkey H
54 */
55 char h[BLOCK_SIZE];
56 };
57
58 /**
59 * Find a suiteable word size and network order conversion functions
60 */
61 #if ULONG_MAX == 18446744073709551615UL && defined(htobe64)
62 # define htobeword htobe64
63 # define bewordtoh be64toh
64 # define SHIFT_WORD_TYPE u_int64_t
65 #else
66 # define htobeword htonl
67 # define bewordtoh ntohl
68 # define SHIFT_WORD_TYPE u_int32_t
69 #endif
70
71 /**
72 * Bitshift a block right by one bit
73 */
74 static void sr_block(char *block)
75 {
76 int i;
77 SHIFT_WORD_TYPE *word = (SHIFT_WORD_TYPE*)block;
78
79 for (i = 0; i < BLOCK_SIZE / sizeof(*word); i++)
80 {
81 word[i] = bewordtoh(word[i]);
82 }
83 for (i = BLOCK_SIZE / sizeof(*word) - 1; i >= 0; i--)
84 {
85 word[i] >>= 1;
86 if (i != 0)
87 {
88 word[i] |= word[i - 1] << (sizeof(*word) * 8 - 1);
89 }
90 }
91 for (i = 0; i < BLOCK_SIZE / sizeof(*word); i++)
92 {
93 word[i] = htobeword(word[i]);
94 }
95 }
96
97 /**
98 * Naive implementation of block multiplication in GF128, no tables
99 */
100 static void mult_block(char *x, char *y, char *res)
101 {
102 char z[BLOCK_SIZE], v[BLOCK_SIZE], r;
103 int bit, byte;
104
105 r = 0xE1;
106 memset(z, 0, BLOCK_SIZE);
107 memcpy(v, y, BLOCK_SIZE);
108
109 for (byte = 0; byte < BLOCK_SIZE; byte++)
110 {
111 for (bit = 7; bit >= 0; bit--)
112 {
113 if (x[byte] & (1 << bit))
114 {
115 memxor(z, v, BLOCK_SIZE);
116 }
117 if (v[BLOCK_SIZE - 1] & 0x01)
118 {
119 sr_block(v);
120 v[0] ^= r;
121 }
122 else
123 {
124 sr_block(v);
125 }
126 }
127 }
128 memcpy(res, z, BLOCK_SIZE);
129 }
130
131 /**
132 * GHASH function
133 */
134 static void ghash(private_gcm_aead_t *this, chunk_t x, char *res)
135 {
136 char y[BLOCK_SIZE];
137
138 memset(y, 0, BLOCK_SIZE);
139
140 while (x.len)
141 {
142 memxor(y, x.ptr, BLOCK_SIZE);
143 mult_block(y, this->h, y);
144 x = chunk_skip(x, BLOCK_SIZE);
145 }
146 memcpy(res, y, BLOCK_SIZE);
147 }
148
149 /**
150 * GCTR function, en-/decrypts x inline
151 */
152 static void gctr(private_gcm_aead_t *this, char *icb, chunk_t x)
153 {
154 char cb[BLOCK_SIZE], iv[BLOCK_SIZE], tmp[BLOCK_SIZE];
155
156 memset(iv, 0, BLOCK_SIZE);
157 memcpy(cb, icb, BLOCK_SIZE);
158
159 while (x.len)
160 {
161 memcpy(tmp, cb, BLOCK_SIZE);
162 this->crypter->encrypt(this->crypter, chunk_from_thing(tmp),
163 chunk_from_thing(iv), NULL);
164 memxor(x.ptr, tmp, min(BLOCK_SIZE, x.len));
165 chunk_increment(chunk_from_thing(cb));
166 x = chunk_skip(x, BLOCK_SIZE);
167 }
168 }
169
170 /**
171 * Generate the block J0
172 */
173 static void create_j(private_gcm_aead_t *this, char *iv, char *j)
174 {
175 memcpy(j, this->salt, SALT_SIZE);
176 memcpy(j + SALT_SIZE, iv, IV_SIZE);
177 htoun32(j + SALT_SIZE + IV_SIZE, 1);
178 }
179
180 /**
181 * Create GHASH subkey H
182 */
183 static void create_h(private_gcm_aead_t *this, char *h)
184 {
185 char zero[BLOCK_SIZE];
186
187 memset(zero, 0, BLOCK_SIZE);
188 memset(h, 0, BLOCK_SIZE);
189
190 this->crypter->encrypt(this->crypter, chunk_create(h, BLOCK_SIZE),
191 chunk_from_thing(zero), NULL);
192 }
193
194 /**
195 * Encrypt/decrypt
196 */
197 static void crypt(private_gcm_aead_t *this, char *j, chunk_t in, chunk_t out)
198 {
199 char icb[BLOCK_SIZE];
200
201 memcpy(icb, j, BLOCK_SIZE);
202 chunk_increment(chunk_from_thing(icb));
203
204 out.len = in.len;
205 if (in.ptr != out.ptr)
206 {
207 memcpy(out.ptr, in.ptr, in.len);
208 }
209 gctr(this, icb, out);
210 }
211
212 /**
213 * Create ICV
214 */
215 static void create_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
216 char *j, char *icv)
217 {
218 size_t assoc_pad, crypt_pad;
219 chunk_t chunk;
220 char s[BLOCK_SIZE], *pos;
221
222 assoc_pad = (BLOCK_SIZE - (assoc.len % BLOCK_SIZE)) % BLOCK_SIZE;
223 crypt_pad = (BLOCK_SIZE - (crypt.len % BLOCK_SIZE)) % BLOCK_SIZE;
224
225 /* concatenate data to a new chunk */
226 chunk = chunk_alloc(assoc.len + assoc_pad +
227 crypt.len + crypt_pad + BLOCK_SIZE);
228 pos = chunk.ptr;
229 /* add associated data */
230 memcpy(pos, assoc.ptr, assoc.len);
231 pos += assoc.len;
232 memset(pos, 0, assoc_pad);
233 pos += assoc_pad;
234 /* add encrypted data */
235 memcpy(pos, crypt.ptr, crypt.len);
236 pos += crypt.len;
237 memset(pos, 0, crypt_pad);
238 pos += crypt_pad;
239 /* write associated len */
240 memset(pos, 0, 4);
241 pos += 4;
242 htoun32(pos, assoc.len * 8);
243 pos += 4;
244 /* write encrypted length */
245 memset(pos, 0, 4);
246 pos += 4;
247 htoun32(pos, crypt.len * 8);
248 pos += 4;
249
250 ghash(this, chunk, s);
251 free(chunk.ptr);
252 gctr(this, j, chunk_from_thing(s));
253
254 memcpy(icv, s, this->icv_size);
255 }
256
257 /**
258 * Verify the ICV value
259 */
260 static bool verify_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
261 char *j, char *icv)
262 {
263 char tmp[this->icv_size];
264
265 create_icv(this, assoc, crypt, j, tmp);
266
267 return memeq(tmp, icv, this->icv_size);
268 }
269
270 METHOD(aead_t, encrypt, bool,
271 private_gcm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
272 chunk_t *encrypted)
273 {
274 char j[BLOCK_SIZE];
275
276 create_j(this, iv.ptr, j);
277
278 if (encrypted)
279 {
280 *encrypted = chunk_alloc(plain.len + this->icv_size);
281 crypt(this, j, plain, *encrypted);
282 create_icv(this, assoc,
283 chunk_create(encrypted->ptr, encrypted->len - this->icv_size),
284 j, encrypted->ptr + encrypted->len - this->icv_size);
285 }
286 else
287 {
288 crypt(this, j, plain, plain);
289 create_icv(this, assoc, plain, j, plain.ptr + plain.len);
290 }
291 return TRUE;
292 }
293
294 METHOD(aead_t, decrypt, bool,
295 private_gcm_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
296 chunk_t *plain)
297 {
298 char j[BLOCK_SIZE];
299
300 if (encrypted.len < this->icv_size)
301 {
302 return FALSE;
303 }
304
305 create_j(this, iv.ptr, j);
306
307 encrypted.len -= this->icv_size;
308 if (!verify_icv(this, assoc, encrypted, j, encrypted.ptr + encrypted.len))
309 {
310 return FALSE;
311 }
312 if (plain)
313 {
314 *plain = chunk_alloc(encrypted.len);
315 crypt(this, j, encrypted, *plain);
316 }
317 else
318 {
319 crypt(this, j, encrypted, encrypted);
320 }
321 return TRUE;
322 }
323
324 METHOD(aead_t, get_block_size, size_t,
325 private_gcm_aead_t *this)
326 {
327 return 1;
328 }
329
330 METHOD(aead_t, get_icv_size, size_t,
331 private_gcm_aead_t *this)
332 {
333 return this->icv_size;
334 }
335
336 METHOD(aead_t, get_iv_size, size_t,
337 private_gcm_aead_t *this)
338 {
339 return IV_SIZE;
340 }
341
342 METHOD(aead_t, get_key_size, size_t,
343 private_gcm_aead_t *this)
344 {
345 return this->crypter->get_key_size(this->crypter) + SALT_SIZE;
346 }
347
348 METHOD(aead_t, set_key, void,
349 private_gcm_aead_t *this, chunk_t key)
350 {
351 memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
352 key.len -= SALT_SIZE;
353 this->crypter->set_key(this->crypter, key);
354 create_h(this, this->h);
355 }
356
357 METHOD(aead_t, destroy, void,
358 private_gcm_aead_t *this)
359 {
360 this->crypter->destroy(this->crypter);
361 free(this);
362 }
363
364 /**
365 * See header
366 */
367 gcm_aead_t *gcm_aead_create(encryption_algorithm_t algo, size_t key_size)
368 {
369 private_gcm_aead_t *this;
370 size_t icv_size;
371
372 switch (key_size)
373 {
374 case 0:
375 key_size = 16;
376 break;
377 case 16:
378 case 24:
379 case 32:
380 break;
381 default:
382 return NULL;
383 }
384 switch (algo)
385 {
386 case ENCR_AES_GCM_ICV8:
387 algo = ENCR_AES_CBC;
388 icv_size = 8;
389 break;
390 case ENCR_AES_GCM_ICV12:
391 algo = ENCR_AES_CBC;
392 icv_size = 12;
393 break;
394 case ENCR_AES_GCM_ICV16:
395 algo = ENCR_AES_CBC;
396 icv_size = 16;
397 break;
398 default:
399 return NULL;
400 }
401
402 INIT(this,
403 .public = {
404 .aead = {
405 .encrypt = _encrypt,
406 .decrypt = _decrypt,
407 .get_block_size = _get_block_size,
408 .get_icv_size = _get_icv_size,
409 .get_iv_size = _get_iv_size,
410 .get_key_size = _get_key_size,
411 .set_key = _set_key,
412 .destroy = _destroy,
413 },
414 },
415 .crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size),
416 .icv_size = icv_size,
417 );
418
419 if (!this->crypter)
420 {
421 free(this);
422 return NULL;
423 }
424
425 return &this->public;
426 }