Annotation of embedaddon/strongswan/src/libstrongswan/plugins/cmac/cmac.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
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 <string.h>
17:
18: #include "cmac.h"
19:
20: #include <utils/debug.h>
21: #include <crypto/mac.h>
22: #include <crypto/prfs/mac_prf.h>
23: #include <crypto/signers/mac_signer.h>
24:
25: typedef struct private_mac_t private_mac_t;
26:
27: /**
28: * Private data of a mac_t object.
29: *
30: * The variable names are the same as in the RFC.
31: */
32: struct private_mac_t {
33:
34: /**
35: * Public interface.
36: */
37: mac_t public;
38:
39: /**
40: * Block size, in bytes
41: */
42: uint8_t b;
43:
44: /**
45: * Crypter with key K
46: */
47: crypter_t *k;
48:
49: /**
50: * K1
51: */
52: uint8_t *k1;
53:
54: /**
55: * K2
56: */
57: uint8_t *k2;
58:
59: /**
60: * T
61: */
62: uint8_t *t;
63:
64: /**
65: * remaining, unprocessed bytes in append mode
66: */
67: uint8_t *remaining;
68:
69: /**
70: * number of bytes in remaining
71: */
72: int remaining_bytes;
73: };
74:
75: /**
76: * process supplied data, but do not run final operation
77: */
78: static bool update(private_mac_t *this, chunk_t data)
79: {
80: chunk_t iv;
81:
82: if (this->remaining_bytes + data.len <= this->b)
83: { /* no complete block (or last block), just copy into remaining */
84: memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
85: this->remaining_bytes += data.len;
86: return TRUE;
87: }
88:
89: iv = chunk_alloca(this->b);
90: memset(iv.ptr, 0, iv.len);
91:
92: /* T := 0x00000000000000000000000000000000 (initially)
93: * for each block M_i (except the last)
94: * X := T XOR M_i;
95: * T := AES-128(K, X);
96: */
97:
98: /* append data to remaining bytes, process block M_1 */
99: memcpy(this->remaining + this->remaining_bytes, data.ptr,
100: this->b - this->remaining_bytes);
101: data = chunk_skip(data, this->b - this->remaining_bytes);
102: memxor(this->t, this->remaining, this->b);
103: if (!this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL))
104: {
105: return FALSE;
106: }
107:
108: /* process blocks M_2 ... M_n-1 */
109: while (data.len > this->b)
110: {
111: memcpy(this->remaining, data.ptr, this->b);
112: data = chunk_skip(data, this->b);
113: memxor(this->t, this->remaining, this->b);
114: if (!this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL))
115: {
116: return FALSE;
117: }
118: }
119:
120: /* store remaining bytes of block M_n */
121: memcpy(this->remaining, data.ptr, data.len);
122: this->remaining_bytes = data.len;
123:
124: return TRUE;
125: }
126:
127: /**
128: * process last block M_last
129: */
130: static bool final(private_mac_t *this, uint8_t *out)
131: {
132: chunk_t iv;
133:
134: iv = chunk_alloca(this->b);
135: memset(iv.ptr, 0, iv.len);
136:
137: /* if last block is complete
138: * M_last := M_n XOR K1;
139: * else
140: * M_last := padding(M_n) XOR K2;
141: */
142: if (this->remaining_bytes == this->b)
143: {
144: memxor(this->remaining, this->k1, this->b);
145: }
146: else
147: {
148: /* padding(x) = x || 10^i where i is 128-8*r-1
149: * That is, padding(x) is the concatenation of x and a single '1',
150: * followed by the minimum number of '0's, so that the total length is
151: * equal to 128 bits.
152: */
153: if (this->remaining_bytes < this->b)
154: {
155: this->remaining[this->remaining_bytes] = 0x80;
156: while (++this->remaining_bytes < this->b)
157: {
158: this->remaining[this->remaining_bytes] = 0x00;
159: }
160: }
161: memxor(this->remaining, this->k2, this->b);
162: }
163: /* T := M_last XOR T;
164: * T := AES-128(K,T);
165: */
166: memxor(this->t, this->remaining, this->b);
167: if (!this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL))
168: {
169: return FALSE;
170: }
171:
172: memcpy(out, this->t, this->b);
173:
174: /* reset state */
175: memset(this->t, 0, this->b);
176: this->remaining_bytes = 0;
177:
178: return TRUE;
179: }
180:
181: METHOD(mac_t, get_mac, bool,
182: private_mac_t *this, chunk_t data, uint8_t *out)
183: {
184: /* update T, do not process last block */
185: if (!update(this, data))
186: {
187: return FALSE;
188: }
189:
190: if (out)
191: { /* if not in append mode, process last block and output result */
192: return final(this, out);
193: }
194: return TRUE;
195: }
196:
197: METHOD(mac_t, get_mac_size, size_t,
198: private_mac_t *this)
199: {
200: return this->b;
201: }
202:
203: /**
204: * Left-shift the given chunk by one bit.
205: */
206: static void bit_shift(chunk_t chunk)
207: {
208: size_t i;
209:
210: for (i = 0; i < chunk.len; i++)
211: {
212: chunk.ptr[i] <<= 1;
213: if (i < chunk.len - 1 && chunk.ptr[i + 1] & 0x80)
214: {
215: chunk.ptr[i] |= 0x01;
216: }
217: }
218: }
219:
220: /**
221: * Apply the following key derivation (in-place):
222: * if MSB(C) == 0
223: * C := C << 1
224: * else
225: * C := (C << 1) XOR 0x00000000000000000000000000000087
226: */
227: static void derive_key(chunk_t chunk)
228: {
229: if (chunk.ptr[0] & 0x80)
230: {
231: chunk_t rb;
232:
233: rb = chunk_alloca(chunk.len);
234: memset(rb.ptr, 0, rb.len);
235: rb.ptr[rb.len - 1] = 0x87;
236: bit_shift(chunk);
237: memxor(chunk.ptr, rb.ptr, chunk.len);
238: }
239: else
240: {
241: bit_shift(chunk);
242: }
243: }
244:
245: METHOD(mac_t, set_key, bool,
246: private_mac_t *this, chunk_t key)
247: {
248: chunk_t resized, iv, l;
249:
250: memset(this->t, 0, this->b);
251: this->remaining_bytes = 0;
252:
253: /* we support variable keys as defined in RFC 4615 */
254: if (key.len == this->b)
255: {
256: resized = key;
257: }
258: else
259: { /* use cmac recursively to resize longer or shorter keys */
260: resized = chunk_alloca(this->b);
261: memset(resized.ptr, 0, resized.len);
262: if (!set_key(this, resized) ||
263: !get_mac(this, key, resized.ptr))
264: {
265: return FALSE;
266: }
267: }
268:
269: /*
270: * Rb = 0x00000000000000000000000000000087
271: * L = 0x00000000000000000000000000000000 encrypted with K
272: * if MSB(L) == 0
273: * K1 = L << 1
274: * else
275: * K1 = (L << 1) XOR Rb
276: * if MSB(K1) == 0
277: * K2 = K1 << 1
278: * else
279: * K2 = (K1 << 1) XOR Rb
280: */
281: iv = chunk_alloca(this->b);
282: memset(iv.ptr, 0, iv.len);
283: l = chunk_alloca(this->b);
284: memset(l.ptr, 0, l.len);
285: if (!this->k->set_key(this->k, resized) ||
286: !this->k->encrypt(this->k, l, iv, NULL))
287: {
288: return FALSE;
289: }
290: derive_key(l);
291: memcpy(this->k1, l.ptr, l.len);
292: derive_key(l);
293: memcpy(this->k2, l.ptr, l.len);
294: memwipe(l.ptr, l.len);
295:
296: return TRUE;
297: }
298:
299: METHOD(mac_t, destroy, void,
300: private_mac_t *this)
301: {
302: this->k->destroy(this->k);
303: memwipe(this->k1, this->b);
304: free(this->k1);
305: memwipe(this->k2, this->b);
306: free(this->k2);
307: free(this->t);
308: free(this->remaining);
309: free(this);
310: }
311:
312: /*
313: * Described in header
314: */
315: mac_t *cmac_create(encryption_algorithm_t algo, size_t key_size)
316: {
317: private_mac_t *this;
318: crypter_t *crypter;
319: uint8_t b;
320:
321: crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size);
322: if (!crypter)
323: {
324: return NULL;
325: }
326: b = crypter->get_block_size(crypter);
327: /* input and output of crypter must be equal for cmac */
328: if (b != key_size)
329: {
330: crypter->destroy(crypter);
331: return NULL;
332: }
333:
334: INIT(this,
335: .public = {
336: .get_mac = _get_mac,
337: .get_mac_size = _get_mac_size,
338: .set_key = _set_key,
339: .destroy = _destroy,
340: },
341: .b = b,
342: .k = crypter,
343: .k1 = malloc(b),
344: .k2 = malloc(b),
345: .t = malloc(b),
346: .remaining = malloc(b),
347: );
348: memset(this->t, 0, b);
349:
350: return &this->public;
351: }
352:
353: /*
354: * Described in header.
355: */
356: prf_t *cmac_prf_create(pseudo_random_function_t algo)
357: {
358: mac_t *cmac;
359:
360: switch (algo)
361: {
362: case PRF_AES128_CMAC:
363: cmac = cmac_create(ENCR_AES_CBC, 16);
364: break;
365: default:
366: return NULL;
367: }
368: if (cmac)
369: {
370: return mac_prf_create(cmac);
371: }
372: return NULL;
373: }
374:
375: /*
376: * Described in header
377: */
378: signer_t *cmac_signer_create(integrity_algorithm_t algo)
379: {
380: size_t truncation;
381: mac_t *cmac;
382:
383: switch (algo)
384: {
385: case AUTH_AES_CMAC_96:
386: cmac = cmac_create(ENCR_AES_CBC, 16);
387: truncation = 12;
388: break;
389: default:
390: return NULL;
391: }
392: if (cmac)
393: {
394: return mac_signer_create(cmac, truncation);
395: }
396: return NULL;
397: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>