Annotation of embedaddon/strongswan/src/libstrongswan/plugins/ccm/ccm_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 "ccm_aead.h"
17:
18: #include <crypto/iv/iv_gen_seq.h>
19:
20: #define BLOCK_SIZE 16
21: #define SALT_SIZE 3
22: #define IV_SIZE 8
23: #define NONCE_SIZE (SALT_SIZE + IV_SIZE) /* 11 */
24: #define Q_SIZE (BLOCK_SIZE - NONCE_SIZE - 1) /* 4 */
25:
26: typedef struct private_ccm_aead_t private_ccm_aead_t;
27:
28: /**
29: * Private data of an ccm_aead_t object.
30: */
31: struct private_ccm_aead_t {
32:
33: /**
34: * Public ccm_aead_t interface.
35: */
36: ccm_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: * Length of the integrity check value
50: */
51: size_t icv_size;
52:
53: /**
54: * salt to add to nonce
55: */
56: u_char salt[SALT_SIZE];
57: };
58:
59: /**
60: * First block with control information
61: */
62: typedef struct __attribute__((packed)) {
63: BITFIELD4(uint8_t,
64: /* size of p length field q, as q-1 */
65: q_len: 3,
66: /* size of our ICV t, as (t-2)/2 */
67: t_len: 3,
68: /* do we have associated data */
69: assoc: 1,
70: reserved: 1,
71: ) flags;
72: /* nonce value */
73: struct __attribute__((packed)) {
74: u_char salt[SALT_SIZE];
75: u_char iv[IV_SIZE];
76: } nonce;
77: /* length of plain text, q */
78: u_char q[Q_SIZE];
79: } b0_t;
80:
81: /**
82: * Counter block
83: */
84: typedef struct __attribute__((packed)) {
85: BITFIELD3(uint8_t,
86: /* size of p length field q, as q-1 */
87: q_len: 3,
88: zero: 3,
89: reserved: 2,
90: ) flags;
91: /* nonce value */
92: struct __attribute__((packed)) {
93: u_char salt[SALT_SIZE];
94: u_char iv[IV_SIZE];
95: } nonce;
96: /* counter value */
97: u_char i[Q_SIZE];
98: } ctr_t;
99:
100: /**
101: * Build the first block B0
102: */
103: static void build_b0(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
104: chunk_t iv, char *out)
105: {
106: b0_t *block = (b0_t*)out;
107:
108: block->flags.reserved = 0;
109: block->flags.assoc = assoc.len ? 1 : 0;
110: block->flags.t_len = (this->icv_size - 2) / 2;
111: block->flags.q_len = Q_SIZE - 1;
112: memcpy(block->nonce.salt, this->salt, SALT_SIZE);
113: memcpy(block->nonce.iv, iv.ptr, IV_SIZE);
114: htoun32(block->q, plain.len);
115: }
116:
117: /**
118: * Build a counter block for counter i
119: */
120: static void build_ctr(private_ccm_aead_t *this, uint32_t i, chunk_t iv,
121: char *out)
122: {
123: ctr_t *ctr = (ctr_t*)out;
124:
125: ctr->flags.reserved = 0;
126: ctr->flags.zero = 0;
127: ctr->flags.q_len = Q_SIZE - 1;
128: memcpy(ctr->nonce.salt, this->salt, SALT_SIZE);
129: memcpy(ctr->nonce.iv, iv.ptr, IV_SIZE);
130: htoun32(ctr->i, i);
131: }
132:
133: /**
134: * En-/Decrypt data
135: */
136: static bool crypt_data(private_ccm_aead_t *this, chunk_t iv,
137: chunk_t in, chunk_t out)
138: {
139: char ctr[BLOCK_SIZE];
140: char zero[BLOCK_SIZE];
141: char block[BLOCK_SIZE];
142:
143: build_ctr(this, 1, iv, ctr);
144: memset(zero, 0, BLOCK_SIZE);
145:
146: while (in.len > 0)
147: {
148: memcpy(block, ctr, BLOCK_SIZE);
149: if (!this->crypter->encrypt(this->crypter, chunk_from_thing(block),
150: chunk_from_thing(zero), NULL))
151: {
152: return FALSE;
153: }
154: chunk_increment(chunk_from_thing(ctr));
155:
156: if (in.ptr != out.ptr)
157: {
158: memcpy(out.ptr, in.ptr, min(in.len, BLOCK_SIZE));
159: }
160: memxor(out.ptr, block, min(in.len, BLOCK_SIZE));
161: in = chunk_skip(in, BLOCK_SIZE);
162: out = chunk_skip(out, BLOCK_SIZE);
163: }
164: return TRUE;
165: }
166:
167: /**
168: * En-/Decrypt the ICV
169: */
170: static bool crypt_icv(private_ccm_aead_t *this, chunk_t iv, char *icv)
171: {
172: char ctr[BLOCK_SIZE];
173: char zero[BLOCK_SIZE];
174:
175: build_ctr(this, 0, iv, ctr);
176: memset(zero, 0, BLOCK_SIZE);
177:
178: if (!this->crypter->encrypt(this->crypter, chunk_from_thing(ctr),
179: chunk_from_thing(zero), NULL))
180: {
181: return FALSE;
182: }
183: memxor(icv, ctr, this->icv_size);
184: return TRUE;
185: }
186:
187: /**
188: * Create the ICV
189: */
190: static bool create_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
191: chunk_t iv, char *icv)
192: {
193: char zero[BLOCK_SIZE];
194: chunk_t chunk;
195: char *pos;
196: int r, len;
197:
198: memset(zero, 0, BLOCK_SIZE);
199:
200: /* calculate number of blocks, including b0 */
201: r = 1;
202: if (assoc.len)
203: { /* assoc gets a 2 byte length header, gets padded to BLOCK_SIZE */
204: r += (2 + assoc.len + BLOCK_SIZE - 1) / BLOCK_SIZE;
205: }
206: /* plain text gets padded to BLOCK_SIZE */
207: r += (plain.len + BLOCK_SIZE - 1) / BLOCK_SIZE;
208:
209: /* concatenate data to a new chunk */
210: chunk = chunk_alloc(r * BLOCK_SIZE);
211: /* write control block */
212: build_b0(this, plain, assoc, iv, chunk.ptr);
213: pos = chunk.ptr + BLOCK_SIZE;
214: /* append associated data, with length header */
215: if (assoc.len)
216: {
217: /* currently we support two byte headers only (up to 2^16-2^8 bytes) */
218: htoun16(pos, assoc.len);
219: memcpy(pos + 2, assoc.ptr, assoc.len);
220: pos += 2 + assoc.len;
221: /* padding */
222: len = (BLOCK_SIZE - ((2 + assoc.len) % BLOCK_SIZE)) % BLOCK_SIZE;
223: memset(pos, 0, len);
224: pos += len;
225: }
226: /* write plain data */
227: memcpy(pos, plain.ptr, plain.len);
228: pos += plain.len;
229: /* padding */
230: len = (BLOCK_SIZE - (plain.len % BLOCK_SIZE)) % BLOCK_SIZE;
231:
232: memset(pos, 0, len);
233:
234: /* encrypt inline with CBC, zero IV */
235: if (!this->crypter->encrypt(this->crypter, chunk,
236: chunk_from_thing(zero), NULL))
237: {
238: free(chunk.ptr);
239: return FALSE;
240: }
241: /* copy last icv_size bytes as ICV to output */
242: memcpy(icv, chunk.ptr + chunk.len - BLOCK_SIZE, this->icv_size);
243:
244: free(chunk.ptr);
245:
246: /* encrypt the ICV value */
247: return crypt_icv(this, iv, icv);
248: }
249:
250: /**
251: * Verify the ICV
252: */
253: static bool verify_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
254: chunk_t iv, char *icv)
255: {
256: char buf[this->icv_size];
257:
258: return create_icv(this, plain, assoc, iv, buf) &&
259: memeq_const(buf, icv, this->icv_size);
260: }
261:
262: METHOD(aead_t, encrypt, bool,
263: private_ccm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
264: chunk_t *encrypted)
265: {
266: if (encrypted)
267: {
268: *encrypted = chunk_alloc(plain.len + this->icv_size);
269: return create_icv(this, plain, assoc, iv, encrypted->ptr + plain.len) &&
270: crypt_data(this, iv, plain, *encrypted);
271: }
272: return create_icv(this, plain, assoc, iv, plain.ptr + plain.len) &&
273: crypt_data(this, iv, plain, plain);
274: }
275:
276: METHOD(aead_t, decrypt, bool,
277: private_ccm_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
278: chunk_t *plain)
279: {
280: if (encrypted.len < this->icv_size)
281: {
282: return FALSE;
283: }
284: encrypted.len -= this->icv_size;
285: if (plain)
286: {
287: *plain = chunk_alloc(encrypted.len);
288: return crypt_data(this, iv, encrypted, *plain) &&
289: verify_icv(this, *plain, assoc, iv,
290: encrypted.ptr + encrypted.len);
291: }
292: return crypt_data(this, iv, encrypted, encrypted) &&
293: verify_icv(this, encrypted, assoc, iv,
294: encrypted.ptr + encrypted.len);
295: }
296:
297: METHOD(aead_t, get_block_size, size_t,
298: private_ccm_aead_t *this)
299: {
300: return 1;
301: }
302:
303: METHOD(aead_t, get_icv_size, size_t,
304: private_ccm_aead_t *this)
305: {
306: return this->icv_size;
307: }
308:
309: METHOD(aead_t, get_iv_size, size_t,
310: private_ccm_aead_t *this)
311: {
312: return IV_SIZE;
313: }
314:
315: METHOD(aead_t, get_iv_gen, iv_gen_t*,
316: private_ccm_aead_t *this)
317: {
318: return this->iv_gen;
319: }
320:
321: METHOD(aead_t, get_key_size, size_t,
322: private_ccm_aead_t *this)
323: {
324: return this->crypter->get_key_size(this->crypter) + SALT_SIZE;
325: }
326:
327: METHOD(aead_t, set_key, bool,
328: private_ccm_aead_t *this, chunk_t key)
329: {
330: memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
331: key.len -= SALT_SIZE;
332: return this->crypter->set_key(this->crypter, key);
333: }
334:
335: METHOD(aead_t, destroy, void,
336: private_ccm_aead_t *this)
337: {
338: this->crypter->destroy(this->crypter);
339: this->iv_gen->destroy(this->iv_gen);
340: free(this);
341: }
342:
343: /**
344: * See header
345: */
346: ccm_aead_t *ccm_aead_create(encryption_algorithm_t algo,
347: size_t key_size, size_t salt_size)
348: {
349: private_ccm_aead_t *this;
350: size_t icv_size;
351:
352: switch (key_size)
353: {
354: case 0:
355: key_size = 16;
356: break;
357: case 16:
358: case 24:
359: case 32:
360: break;
361: default:
362: return NULL;
363: }
364: if (salt_size && salt_size != SALT_SIZE)
365: {
366: /* currently not supported */
367: return NULL;
368: }
369: switch (algo)
370: {
371: case ENCR_AES_CCM_ICV8:
372: algo = ENCR_AES_CBC;
373: icv_size = 8;
374: break;
375: case ENCR_AES_CCM_ICV12:
376: algo = ENCR_AES_CBC;
377: icv_size = 12;
378: break;
379: case ENCR_AES_CCM_ICV16:
380: algo = ENCR_AES_CBC;
381: icv_size = 16;
382: break;
383: case ENCR_CAMELLIA_CCM_ICV8:
384: algo = ENCR_CAMELLIA_CBC;
385: icv_size = 8;
386: break;
387: case ENCR_CAMELLIA_CCM_ICV12:
388: algo = ENCR_CAMELLIA_CBC;
389: icv_size = 12;
390: break;
391: case ENCR_CAMELLIA_CCM_ICV16:
392: algo = ENCR_CAMELLIA_CBC;
393: icv_size = 16;
394: break;
395: default:
396: return NULL;
397: }
398:
399: INIT(this,
400: .public = {
401: .aead = {
402: .encrypt = _encrypt,
403: .decrypt = _decrypt,
404: .get_block_size = _get_block_size,
405: .get_icv_size = _get_icv_size,
406: .get_iv_size = _get_iv_size,
407: .get_iv_gen = _get_iv_gen,
408: .get_key_size = _get_key_size,
409: .set_key = _set_key,
410: .destroy = _destroy,
411: },
412: },
413: .crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size),
414: .iv_gen = iv_gen_seq_create(),
415: .icv_size = icv_size,
416: );
417:
418: if (!this->crypter)
419: {
420: free(this);
421: return NULL;
422: }
423:
424: return &this->public;
425: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>