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