Implemented AES-CMAC based PRF and signer.
[strongswan.git] / src / libstrongswan / plugins / cmac / cmac.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * 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 <debug.h>
21
22 typedef struct private_cmac_t private_cmac_t;
23
24 /**
25 * Private data of a cmac_t object.
26 *
27 * The variable names are the same as in the RFC.
28 */
29 struct private_cmac_t {
30
31 /**
32 * Public interface.
33 */
34 cmac_t public;
35
36 /**
37 * Block size, in bytes
38 */
39 u_int8_t b;
40
41 /**
42 * Crypter with key K
43 */
44 crypter_t *k;
45
46 /**
47 * K1
48 */
49 u_int8_t *k1;
50
51 /**
52 * K2
53 */
54 u_int8_t *k2;
55
56 /**
57 * T
58 */
59 u_int8_t *t;
60
61 /**
62 * remaining, unprocessed bytes in append mode
63 */
64 u_int8_t *remaining;
65
66 /**
67 * number of bytes in remaining
68 */
69 int remaining_bytes;
70 };
71
72 /**
73 * process supplied data, but do not run final operation
74 */
75 static void update(private_cmac_t *this, chunk_t data)
76 {
77 chunk_t iv;
78
79 if (this->remaining_bytes + data.len <= this->b)
80 { /* no complete block (or last block), just copy into remaining */
81 memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
82 this->remaining_bytes += data.len;
83 return;
84 }
85
86 iv = chunk_alloca(this->b);
87 memset(iv.ptr, 0, iv.len);
88
89 /* T := 0x00000000000000000000000000000000 (initially)
90 * for each block M_i (except the last)
91 * X := T XOR M_i;
92 * T := AES-128(K, X);
93 */
94
95 /* append data to remaining bytes, process block M_1 */
96 memcpy(this->remaining + this->remaining_bytes, data.ptr,
97 this->b - this->remaining_bytes);
98 data = chunk_skip(data, this->b - this->remaining_bytes);
99 memxor(this->t, this->remaining, this->b);
100 this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
101
102 /* process blocks M_2 ... M_n-1 */
103 while (data.len > this->b)
104 {
105 memcpy(this->remaining, data.ptr, this->b);
106 data = chunk_skip(data, this->b);
107 memxor(this->t, this->remaining, this->b);
108 this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
109 }
110
111 /* store remaining bytes of block M_n */
112 memcpy(this->remaining, data.ptr, data.len);
113 this->remaining_bytes = data.len;
114 }
115
116 /**
117 * process last block M_last
118 */
119 static void final(private_cmac_t *this, u_int8_t *out)
120 {
121 chunk_t iv;
122
123 iv = chunk_alloca(this->b);
124 memset(iv.ptr, 0, iv.len);
125
126 /* if last block is complete
127 * M_last := M_n XOR K1;
128 * else
129 * M_last := padding(M_n) XOR K2;
130 */
131 if (this->remaining_bytes == this->b)
132 {
133 memxor(this->remaining, this->k1, this->b);
134 }
135 else
136 {
137 /* padding(x) = x || 10^i where i is 128-8*r-1
138 * That is, padding(x) is the concatenation of x and a single '1',
139 * followed by the minimum number of '0's, so that the total length is
140 * equal to 128 bits.
141 */
142 if (this->remaining_bytes < this->b)
143 {
144 this->remaining[this->remaining_bytes] = 0x80;
145 while (++this->remaining_bytes < this->b)
146 {
147 this->remaining[this->remaining_bytes] = 0x00;
148 }
149 }
150 memxor(this->remaining, this->k2, this->b);
151 }
152 /* T := M_last XOR T;
153 * T := AES-128(K,T);
154 */
155 memxor(this->t, this->remaining, this->b);
156 this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
157
158 memcpy(out, this->t, this->b);
159
160 /* reset state */
161 memset(this->t, 0, this->b);
162 this->remaining_bytes = 0;
163 }
164
165 METHOD(cmac_t, get_mac, void,
166 private_cmac_t *this, chunk_t data, u_int8_t *out)
167 {
168 /* update T, do not process last block */
169 update(this, data);
170
171 if (out)
172 { /* if not in append mode, process last block and output result */
173 final(this, out);
174 }
175 }
176
177 METHOD(cmac_t, get_block_size, size_t,
178 private_cmac_t *this)
179 {
180 return this->b;
181 }
182
183 /**
184 * Left-shift the given chunk by one bit.
185 */
186 static void bit_shift(chunk_t chunk)
187 {
188 size_t i;
189
190 for (i = 0; i < chunk.len; i++)
191 {
192 chunk.ptr[i] <<= 1;
193 if (i < chunk.len - 1 && chunk.ptr[i + 1] & 0x80)
194 {
195 chunk.ptr[i] |= 0x01;
196 }
197 }
198 }
199
200 /**
201 * Apply the following key derivation (in-place):
202 * if MSB(C) == 0
203 * C := C << 1
204 * else
205 * C := (C << 1) XOR 0x00000000000000000000000000000087
206 */
207 static void derive_key(chunk_t chunk)
208 {
209 if (chunk.ptr[0] & 0x80)
210 {
211 chunk_t rb;
212
213 rb = chunk_alloca(chunk.len);
214 memset(rb.ptr, 0, rb.len);
215 rb.ptr[rb.len - 1] = 0x87;
216 bit_shift(chunk);
217 memxor(chunk.ptr, rb.ptr, chunk.len);
218 }
219 else
220 {
221 bit_shift(chunk);
222 }
223 }
224
225 METHOD(cmac_t, set_key, void,
226 private_cmac_t *this, chunk_t key)
227 {
228 chunk_t resized, iv, l;
229
230 /* we support variable keys as defined in RFC 4615 */
231 if (key.len == this->b)
232 {
233 resized = key;
234 }
235 else
236 { /* use cmac recursively to resize longer or shorter keys */
237 resized = chunk_alloca(this->b);
238 memset(resized.ptr, 0, resized.len);
239 set_key(this, resized);
240 get_mac(this, key, resized.ptr);
241 }
242
243 /*
244 * Rb = 0x00000000000000000000000000000087
245 * L = 0x00000000000000000000000000000000 encrypted with K
246 * if MSB(L) == 0
247 * K1 = L << 1
248 * else
249 * K1 = (L << 1) XOR Rb
250 * if MSB(K1) == 0
251 * K2 = K1 << 1
252 * else
253 * K2 = (K1 << 1) XOR Rb
254 */
255 iv = chunk_alloca(this->b);
256 memset(iv.ptr, 0, iv.len);
257 l = chunk_alloca(this->b);
258 memset(l.ptr, 0, l.len);
259 this->k->set_key(this->k, resized);
260 this->k->encrypt(this->k, l, iv, NULL);
261 derive_key(l);
262 memcpy(this->k1, l.ptr, l.len);
263 derive_key(l);
264 memcpy(this->k2, l.ptr, l.len);
265 memwipe(l.ptr, l.len);
266 }
267
268 METHOD(cmac_t, destroy, void,
269 private_cmac_t *this)
270 {
271 this->k->destroy(this->k);
272 memwipe(this->k1, this->b);
273 free(this->k1);
274 memwipe(this->k2, this->b);
275 free(this->k2);
276 free(this->t);
277 free(this->remaining);
278 free(this);
279 }
280
281 /*
282 * Described in header
283 */
284 cmac_t *cmac_create(encryption_algorithm_t algo, size_t key_size)
285 {
286 private_cmac_t *this;
287 crypter_t *crypter;
288 u_int8_t b;
289
290 crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size);
291 if (!crypter)
292 {
293 return NULL;
294 }
295 b = crypter->get_block_size(crypter);
296 /* input and output of crypter must be equal for cmac */
297 if (b != key_size)
298 {
299 crypter->destroy(crypter);
300 return NULL;
301 }
302
303 INIT(this,
304 .public = {
305 .get_mac = _get_mac,
306 .get_block_size = _get_block_size,
307 .set_key = _set_key,
308 .destroy = _destroy,
309 },
310 .b = b,
311 .k = crypter,
312 .k1 = malloc(b),
313 .k2 = malloc(b),
314 .t = malloc(b),
315 .remaining = malloc(b),
316 );
317 memset(this->t, 0, b);
318
319 return &this->public;
320 }
321