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