7c0a2ba23ac206dc092fc7e4e2024433c33c1b4c
[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 <debug.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 * Bitshift a block right by one bit
60 */
61 static void sr_block(u_char *block)
62 {
63 int i;
64
65 for (i = BLOCK_SIZE - 1; i >= 0; i--)
66 {
67 block[i] = block[i] >> 1;
68 if (i != 0)
69 {
70 block[i] |= block[i - 1] << 7;
71 }
72 }
73 }
74
75 /**
76 * Naive implementation of block multiplication in GF128, no tables
77 */
78 static void mult_block(char *x, char *y, char *res)
79 {
80 char z[BLOCK_SIZE], v[BLOCK_SIZE], r;
81 int bit, byte;
82
83 r = 0xE1;
84 memset(z, 0, BLOCK_SIZE);
85 memcpy(v, y, BLOCK_SIZE);
86
87 for (byte = 0; byte < BLOCK_SIZE; byte++)
88 {
89 for (bit = 7; bit >= 0; bit--)
90 {
91 if (x[byte] & (1 << bit))
92 {
93 memxor(z, v, BLOCK_SIZE);
94 }
95 if (v[BLOCK_SIZE - 1] & 0x01)
96 {
97 sr_block(v);
98 v[0] ^= r;
99 }
100 else
101 {
102 sr_block(v);
103 }
104 }
105 }
106 memcpy(res, z, BLOCK_SIZE);
107 }
108
109 /**
110 * GHASH function
111 */
112 static void ghash(private_gcm_aead_t *this, chunk_t x, char *res)
113 {
114 char y[BLOCK_SIZE];
115
116 memset(y, 0, BLOCK_SIZE);
117
118 while (x.len)
119 {
120 memxor(y, x.ptr, BLOCK_SIZE);
121 mult_block(y, this->h, y);
122 x = chunk_skip(x, BLOCK_SIZE);
123 }
124 memcpy(res, y, BLOCK_SIZE);
125 }
126
127 /**
128 * GCTR function, en-/decrypts x inline
129 */
130 static void gctr(private_gcm_aead_t *this, char *icb, chunk_t x)
131 {
132 char cb[BLOCK_SIZE], iv[BLOCK_SIZE], tmp[BLOCK_SIZE];
133
134 memset(iv, 0, BLOCK_SIZE);
135 memcpy(cb, icb, BLOCK_SIZE);
136
137 while (x.len)
138 {
139 memcpy(tmp, cb, BLOCK_SIZE);
140 this->crypter->encrypt(this->crypter, chunk_from_thing(tmp),
141 chunk_from_thing(iv), NULL);
142 memxor(x.ptr, tmp, min(BLOCK_SIZE, x.len));
143 chunk_increment(chunk_from_thing(cb));
144 x = chunk_skip(x, BLOCK_SIZE);
145 }
146 }
147
148 /**
149 * Generate the block J0
150 */
151 static void create_j(private_gcm_aead_t *this, char *iv, char *j)
152 {
153 memcpy(j, this->salt, SALT_SIZE);
154 memcpy(j + SALT_SIZE, iv, IV_SIZE);
155 htoun32(j + SALT_SIZE + IV_SIZE, 1);
156 }
157
158 /**
159 * Create GHASH subkey H
160 */
161 static void create_h(private_gcm_aead_t *this, char *h)
162 {
163 char zero[BLOCK_SIZE];
164
165 memset(zero, 0, BLOCK_SIZE);
166 memset(h, 0, BLOCK_SIZE);
167
168 this->crypter->encrypt(this->crypter, chunk_create(h, BLOCK_SIZE),
169 chunk_from_thing(zero), NULL);
170 }
171
172 /**
173 * Encrypt/decrypt
174 */
175 static void crypt(private_gcm_aead_t *this, char *j, chunk_t in, chunk_t out)
176 {
177 char icb[BLOCK_SIZE];
178
179 memcpy(icb, j, BLOCK_SIZE);
180 chunk_increment(chunk_from_thing(icb));
181
182 out.len = in.len;
183 if (in.ptr != out.ptr)
184 {
185 memcpy(out.ptr, in.ptr, in.len);
186 }
187 gctr(this, icb, out);
188 }
189
190 /**
191 * Create ICV
192 */
193 static void create_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
194 char *j, char *icv)
195 {
196 size_t assoc_pad, crypt_pad;
197 chunk_t chunk;
198 char s[BLOCK_SIZE], *pos;
199
200 assoc_pad = (BLOCK_SIZE - (assoc.len % BLOCK_SIZE)) % BLOCK_SIZE;
201 crypt_pad = (BLOCK_SIZE - (crypt.len % BLOCK_SIZE)) % BLOCK_SIZE;
202
203 /* concatenate data to a new chunk */
204 chunk = chunk_alloc(assoc.len + assoc_pad +
205 crypt.len + crypt_pad + BLOCK_SIZE);
206 pos = chunk.ptr;
207 /* add associated data */
208 memcpy(pos, assoc.ptr, assoc.len);
209 pos += assoc.len;
210 memset(pos, 0, assoc_pad);
211 pos += assoc_pad;
212 /* add encrypted data */
213 memcpy(pos, crypt.ptr, crypt.len);
214 pos += crypt.len;
215 memset(pos, 0, crypt_pad);
216 pos += crypt_pad;
217 /* write associated len */
218 memset(pos, 0, 4);
219 pos += 4;
220 htoun32(pos, assoc.len * 8);
221 pos += 4;
222 /* write encrypted length */
223 memset(pos, 0, 4);
224 pos += 4;
225 htoun32(pos, crypt.len * 8);
226 pos += 4;
227
228 ghash(this, chunk, s);
229 free(chunk.ptr);
230 gctr(this, j, chunk_from_thing(s));
231
232 memcpy(icv, s, this->icv_size);
233 }
234
235 /**
236 * Verify the ICV value
237 */
238 static bool verify_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
239 char *j, char *icv)
240 {
241 char tmp[this->icv_size];
242
243 create_icv(this, assoc, crypt, j, tmp);
244
245 return memeq(tmp, icv, this->icv_size);
246 }
247
248 METHOD(aead_t, encrypt, void,
249 private_gcm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
250 chunk_t *encrypted)
251 {
252 char j[BLOCK_SIZE];
253
254 create_j(this, iv.ptr, j);
255
256 if (encrypted)
257 {
258 *encrypted = chunk_alloc(plain.len + this->icv_size);
259 crypt(this, j, plain, *encrypted);
260 create_icv(this, assoc,
261 chunk_create(encrypted->ptr, encrypted->len - this->icv_size),
262 j, encrypted->ptr + encrypted->len - this->icv_size);
263 }
264 else
265 {
266 crypt(this, j, plain, plain);
267 create_icv(this, assoc, plain, j, plain.ptr + plain.len);
268 }
269 }
270
271 METHOD(aead_t, decrypt, bool,
272 private_gcm_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
273 chunk_t *plain)
274 {
275 char j[BLOCK_SIZE];
276
277 if (encrypted.len < this->icv_size)
278 {
279 return FALSE;
280 }
281
282 create_j(this, iv.ptr, j);
283
284 encrypted.len -= this->icv_size;
285 if (!verify_icv(this, assoc, encrypted, j, encrypted.ptr + encrypted.len))
286 {
287 return FALSE;
288 }
289 if (plain)
290 {
291 *plain = chunk_alloc(encrypted.len);
292 crypt(this, j, encrypted, *plain);
293 }
294 else
295 {
296 crypt(this, j, encrypted, encrypted);
297 }
298 return TRUE;
299 }
300
301 METHOD(aead_t, get_block_size, size_t,
302 private_gcm_aead_t *this)
303 {
304 return 1;
305 }
306
307 METHOD(aead_t, get_icv_size, size_t,
308 private_gcm_aead_t *this)
309 {
310 return this->icv_size;
311 }
312
313 METHOD(aead_t, get_iv_size, size_t,
314 private_gcm_aead_t *this)
315 {
316 return IV_SIZE;
317 }
318
319 METHOD(aead_t, get_key_size, size_t,
320 private_gcm_aead_t *this)
321 {
322 return this->crypter->get_key_size(this->crypter) + SALT_SIZE;
323 }
324
325 METHOD(aead_t, set_key, void,
326 private_gcm_aead_t *this, chunk_t key)
327 {
328 memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
329 key.len -= SALT_SIZE;
330 this->crypter->set_key(this->crypter, key);
331 create_h(this, this->h);
332 }
333
334 METHOD(aead_t, destroy, void,
335 private_gcm_aead_t *this)
336 {
337 this->crypter->destroy(this->crypter);
338 free(this);
339 }
340
341 /**
342 * See header
343 */
344 gcm_aead_t *gcm_aead_create(encryption_algorithm_t algo, size_t key_size)
345 {
346 private_gcm_aead_t *this;
347 size_t icv_size;
348
349 switch (key_size)
350 {
351 case 0:
352 key_size = 16;
353 break;
354 case 16:
355 case 24:
356 case 32:
357 break;
358 default:
359 return NULL;
360 }
361 switch (algo)
362 {
363 case ENCR_AES_GCM_ICV8:
364 algo = ENCR_AES_CBC;
365 icv_size = 8;
366 break;
367 case ENCR_AES_GCM_ICV12:
368 algo = ENCR_AES_CBC;
369 icv_size = 12;
370 break;
371 case ENCR_AES_GCM_ICV16:
372 algo = ENCR_AES_CBC;
373 icv_size = 16;
374 break;
375 default:
376 return NULL;
377 }
378
379 INIT(this,
380 .public = {
381 .aead = {
382 .encrypt = _encrypt,
383 .decrypt = _decrypt,
384 .get_block_size = _get_block_size,
385 .get_icv_size = _get_icv_size,
386 .get_iv_size = _get_iv_size,
387 .get_key_size = _get_key_size,
388 .set_key = _set_key,
389 .destroy = _destroy,
390 },
391 },
392 .crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size),
393 .icv_size = icv_size,
394 );
395
396 if (!this->crypter)
397 {
398 free(this);
399 return NULL;
400 }
401
402 return &this->public;
403 }