Annotation of embedaddon/strongswan/src/libstrongswan/plugins/xcbc/xcbc.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012 Tobias Brunner
3: * Copyright (C) 2008 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include <string.h>
18:
19: #include "xcbc.h"
20:
21: #include <utils/debug.h>
22: #include <crypto/mac.h>
23: #include <crypto/prfs/mac_prf.h>
24: #include <crypto/signers/mac_signer.h>
25:
26: typedef struct private_mac_t private_mac_t;
27:
28: /**
29: * Private data of a mac_t object.
30: *
31: * The variable names are the same as in the RFC.
32: */
33: struct private_mac_t {
34:
35: /**
36: * Public mac_t interface.
37: */
38: mac_t public;
39:
40: /**
41: * Block size, in bytes
42: */
43: uint8_t b;
44:
45: /**
46: * crypter using k1
47: */
48: crypter_t *k1;
49:
50: /**
51: * k2
52: */
53: uint8_t *k2;
54:
55: /**
56: * k3
57: */
58: uint8_t *k3;
59:
60: /**
61: * E
62: */
63: uint8_t *e;
64:
65: /**
66: * remaining, unprocessed bytes in append mode
67: */
68: uint8_t *remaining;
69:
70: /**
71: * number of bytes in remaining
72: */
73: int remaining_bytes;
74:
75: /**
76: * TRUE if we have zero bytes to xcbc in final()
77: */
78: bool zero;
79: };
80:
81: /**
82: * xcbc supplied data, but do not run final operation
83: */
84: static bool update(private_mac_t *this, chunk_t data)
85: {
86: chunk_t iv;
87:
88: if (data.len)
89: {
90: this->zero = FALSE;
91: }
92:
93: if (this->remaining_bytes + data.len <= this->b)
94: { /* no complete block, just copy into remaining */
95: memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
96: this->remaining_bytes += data.len;
97: return TRUE;
98: }
99:
100: iv = chunk_alloca(this->b);
101: memset(iv.ptr, 0, iv.len);
102:
103: /* (3) For each block M[i], where i = 1 ... n-1:
104: * XOR M[i] with E[i-1], then encrypt the result with Key K1,
105: * yielding E[i].
106: */
107:
108: /* append data to remaining bytes, process block M[1] */
109: memcpy(this->remaining + this->remaining_bytes, data.ptr,
110: this->b - this->remaining_bytes);
111: data = chunk_skip(data, this->b - this->remaining_bytes);
112: memxor(this->e, this->remaining, this->b);
113: if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL))
114: {
115: return FALSE;
116: }
117:
118: /* process blocks M[2] ... M[n-1] */
119: while (data.len > this->b)
120: {
121: memcpy(this->remaining, data.ptr, this->b);
122: data = chunk_skip(data, this->b);
123: memxor(this->e, this->remaining, this->b);
124: if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b),
125: iv, NULL))
126: {
127: return FALSE;
128: }
129: }
130:
131: /* store remaining bytes of block M[n] */
132: memcpy(this->remaining, data.ptr, data.len);
133: this->remaining_bytes = data.len;
134:
135: return TRUE;
136: }
137:
138: /**
139: * run last round, data is in this->e
140: */
141: static bool final(private_mac_t *this, uint8_t *out)
142: {
143: chunk_t iv;
144:
145: iv = chunk_alloca(this->b);
146: memset(iv.ptr, 0, iv.len);
147:
148: /* (4) For block M[n]: */
149: if (this->remaining_bytes == this->b && !this->zero)
150: {
151: /* a) If the blocksize of M[n] is 128 bits:
152: * XOR M[n] with E[n-1] and Key K2, then encrypt the result with
153: * Key K1, yielding E[n].
154: */
155: memxor(this->e, this->remaining, this->b);
156: memxor(this->e, this->k2, this->b);
157: }
158: else
159: {
160: /* b) If the blocksize of M[n] is less than 128 bits:
161: *
162: * i) Pad M[n] with a single "1" bit, followed by the number of
163: * "0" bits (possibly none) required to increase M[n]'s
164: * blocksize to 128 bits.
165: */
166: if (this->remaining_bytes < this->b)
167: {
168: this->remaining[this->remaining_bytes] = 0x80;
169: while (++this->remaining_bytes < this->b)
170: {
171: this->remaining[this->remaining_bytes] = 0x00;
172: }
173: }
174: /* ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result
175: * with Key K1, yielding E[n].
176: */
177: memxor(this->e, this->remaining, this->b);
178: memxor(this->e, this->k3, this->b);
179: }
180: if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL))
181: {
182: return FALSE;
183: }
184:
185: memcpy(out, this->e, this->b);
186:
187: /* (2) Define E[0] = 0x00000000000000000000000000000000 */
188: memset(this->e, 0, this->b);
189: this->remaining_bytes = 0;
190: this->zero = TRUE;
191:
192: return TRUE;
193: }
194:
195: METHOD(mac_t, get_mac, bool,
196: private_mac_t *this, chunk_t data, uint8_t *out)
197: {
198: /* update E, do not process last block */
199: if (!update(this, data))
200: {
201: return FALSE;
202: }
203:
204: if (out)
205: { /* if not in append mode, process last block and output result */
206: return final(this, out);
207: }
208: return TRUE;
209: }
210:
211: METHOD(mac_t, get_mac_size, size_t,
212: private_mac_t *this)
213: {
214: return this->b;
215: }
216:
217: METHOD(mac_t, set_key, bool,
218: private_mac_t *this, chunk_t key)
219: {
220: chunk_t iv, k1, lengthened;
221:
222: memset(this->e, 0, this->b);
223: this->remaining_bytes = 0;
224: this->zero = TRUE;
225:
226: /* we support variable keys from RFC4434 */
227: if (key.len == this->b)
228: {
229: lengthened = key;
230: }
231: else if (key.len < this->b)
232: { /* pad short keys */
233: lengthened = chunk_alloca(this->b);
234: memset(lengthened.ptr, 0, lengthened.len);
235: memcpy(lengthened.ptr, key.ptr, key.len);
236: }
237: else
238: { /* shorten key using xcbc */
239: lengthened = chunk_alloca(this->b);
240: memset(lengthened.ptr, 0, lengthened.len);
241: if (!set_key(this, lengthened) ||
242: !get_mac(this, key, lengthened.ptr))
243: {
244: return FALSE;
245: }
246: }
247:
248: k1 = chunk_alloca(this->b);
249: iv = chunk_alloca(this->b);
250: memset(iv.ptr, 0, iv.len);
251:
252: /*
253: * (1) Derive 3 128-bit keys (K1, K2 and K3) from the 128-bit secret
254: * key K, as follows:
255: * K1 = 0x01010101010101010101010101010101 encrypted with Key K
256: * K2 = 0x02020202020202020202020202020202 encrypted with Key K
257: * K3 = 0x03030303030303030303030303030303 encrypted with Key K
258: */
259:
260: memset(k1.ptr, 0x01, this->b);
261: memset(this->k2, 0x02, this->b);
262: memset(this->k3, 0x03, this->b);
263:
264: if (!this->k1->set_key(this->k1, lengthened) ||
265: !this->k1->encrypt(this->k1, chunk_create(this->k2, this->b), iv, NULL) ||
266: !this->k1->encrypt(this->k1, chunk_create(this->k3, this->b), iv, NULL) ||
267: !this->k1->encrypt(this->k1, k1, iv, NULL) ||
268: !this->k1->set_key(this->k1, k1))
269: {
270: memwipe(k1.ptr, k1.len);
271: return FALSE;
272: }
273: memwipe(k1.ptr, k1.len);
274: return TRUE;
275: }
276:
277: METHOD(mac_t, destroy, void,
278: private_mac_t *this)
279: {
280: this->k1->destroy(this->k1);
281: memwipe(this->k2, this->b);
282: free(this->k2);
283: memwipe(this->k3, this->b);
284: free(this->k3);
285: free(this->e);
286: free(this->remaining);
287: free(this);
288: }
289:
290: /*
291: * Described in header
292: */
293: static mac_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
294: {
295: private_mac_t *this;
296: crypter_t *crypter;
297: uint8_t b;
298:
299: crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size);
300: if (!crypter)
301: {
302: return NULL;
303: }
304: b = crypter->get_block_size(crypter);
305: /* input and output of crypter must be equal for xcbc */
306: if (b != key_size)
307: {
308: crypter->destroy(crypter);
309: return NULL;
310: }
311:
312: INIT(this,
313: .public = {
314: .get_mac = _get_mac,
315: .get_mac_size = _get_mac_size,
316: .set_key = _set_key,
317: .destroy = _destroy,
318: },
319: .b = b,
320: .k1 = crypter,
321: .k2 = malloc(b),
322: .k3 = malloc(b),
323: .e = malloc(b),
324: .remaining = malloc(b),
325: .zero = TRUE,
326: );
327: memset(this->e, 0, b);
328:
329: return &this->public;
330: }
331:
332: /*
333: * Described in header.
334: */
335: prf_t *xcbc_prf_create(pseudo_random_function_t algo)
336: {
337: mac_t *xcbc;
338:
339: switch (algo)
340: {
341: case PRF_AES128_XCBC:
342: xcbc = xcbc_create(ENCR_AES_CBC, 16);
343: break;
344: case PRF_CAMELLIA128_XCBC:
345: xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
346: break;
347: default:
348: return NULL;
349: }
350: if (xcbc)
351: {
352: return mac_prf_create(xcbc);
353: }
354: return NULL;
355: }
356:
357: /*
358: * Described in header
359: */
360: signer_t *xcbc_signer_create(integrity_algorithm_t algo)
361: {
362: size_t trunc;
363: mac_t *xcbc;
364:
365: switch (algo)
366: {
367: case AUTH_AES_XCBC_96:
368: xcbc = xcbc_create(ENCR_AES_CBC, 16);
369: trunc = 12;
370: break;
371: case AUTH_CAMELLIA_XCBC_96:
372: xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
373: trunc = 12;
374: break;
375: default:
376: return NULL;
377: }
378: if (xcbc)
379: {
380: return mac_signer_create(xcbc, trunc);
381: }
382: return NULL;
383: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>