]>
Commit | Line | Data |
---|---|---|
f38a1528 | 1 | /*- |
2 | * Copyright (C) 2010, Romain Tartiere. | |
3 | * | |
4 | * This program is free software: you can redistribute it and/or modify it | |
5 | * under the terms of the GNU Lesser General Public License as published by the | |
6 | * Free Software Foundation, either version 3 of the License, or (at your | |
7 | * option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/> | |
16 | * | |
17 | * $Id$ | |
18 | */ | |
19 | ||
20 | /* | |
21 | * This implementation was written based on information provided by the | |
22 | * following documents: | |
23 | * | |
24 | * NIST Special Publication 800-38B | |
25 | * Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication | |
26 | * May 2005 | |
27 | */ | |
28 | #include "desfire_crypto.h" | |
29 | ||
7838f4be | 30 | static void xor (const uint8_t *ivect, uint8_t *data, const size_t len); |
31 | static size_t key_macing_length (desfirekey_t key); | |
f38a1528 | 32 | |
33 | static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) { | |
34 | for (size_t i = 0; i < len; i++) { | |
35 | data[i] ^= ivect[i]; | |
36 | } | |
37 | } | |
38 | ||
39 | void cmac_generate_subkeys ( desfirekey_t key) { | |
40 | int kbs = key_block_size (key); | |
41 | const uint8_t R = (kbs == 8) ? 0x1B : 0x87; | |
42 | ||
43 | uint8_t l[kbs]; | |
44 | memset (l, 0, kbs); | |
45 | ||
46 | uint8_t ivect[kbs]; | |
47 | memset (ivect, 0, kbs); | |
48 | ||
49 | mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER); | |
50 | ||
51 | bool xor = false; | |
52 | ||
53 | // Used to compute CMAC on complete blocks | |
54 | memcpy (key->cmac_sk1, l, kbs); | |
55 | xor = l[0] & 0x80; | |
56 | lsl (key->cmac_sk1, kbs); | |
57 | if (xor) | |
58 | key->cmac_sk1[kbs-1] ^= R; | |
59 | ||
60 | // Used to compute CMAC on the last block if non-complete | |
61 | memcpy (key->cmac_sk2, key->cmac_sk1, kbs); | |
62 | xor = key->cmac_sk1[0] & 0x80; | |
63 | lsl (key->cmac_sk2, kbs); | |
64 | if (xor) | |
65 | key->cmac_sk2[kbs-1] ^= R; | |
66 | } | |
67 | ||
68 | void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) { | |
69 | int kbs = key_block_size (key); | |
70 | uint8_t *buffer = malloc (padded_data_length (len, kbs)); | |
71 | ||
72 | memcpy (buffer, data, len); | |
73 | ||
74 | if ((!len) || (len % kbs)) { | |
75 | buffer[len++] = 0x80; | |
76 | while (len % kbs) { | |
77 | buffer[len++] = 0x00; | |
78 | } | |
79 | xor (key->cmac_sk2, buffer + len - kbs, kbs); | |
80 | } else { | |
81 | xor (key->cmac_sk1, buffer + len - kbs, kbs); | |
82 | } | |
83 | ||
84 | mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); | |
85 | ||
86 | memcpy (cmac, ivect, kbs); | |
4a71da5a | 87 | free(buffer); |
f38a1528 | 88 | } |
89 | ||
90 | size_t key_block_size (const desfirekey_t key) { | |
91 | size_t block_size = 8; | |
92 | ||
93 | switch (key->type) { | |
94 | case T_DES: | |
95 | case T_3DES: | |
96 | case T_3K3DES: | |
97 | block_size = 8; | |
98 | break; | |
99 | case T_AES: | |
100 | block_size = 16; | |
101 | break; | |
102 | } | |
103 | ||
104 | return block_size; | |
105 | } | |
106 | ||
107 | /* | |
108 | * Size of MACing produced with the key. | |
109 | */ | |
110 | static size_t key_macing_length (const desfirekey_t key) { | |
111 | size_t mac_length = MAC_LENGTH; | |
112 | ||
113 | switch (key->type) { | |
114 | case T_DES: | |
115 | case T_3DES: | |
116 | mac_length = MAC_LENGTH; | |
117 | break; | |
118 | case T_3K3DES: | |
119 | case T_AES: | |
120 | mac_length = CMAC_LENGTH; | |
121 | break; | |
122 | } | |
123 | ||
124 | return mac_length; | |
125 | } | |
126 | ||
127 | /* | |
128 | * Size required to store nbytes of data in a buffer of size n*block_size. | |
129 | */ | |
130 | size_t padded_data_length (const size_t nbytes, const size_t block_size) { | |
131 | if ((!nbytes) || (nbytes % block_size)) | |
132 | return ((nbytes / block_size) + 1) * block_size; | |
133 | else | |
134 | return nbytes; | |
135 | } | |
136 | ||
137 | /* | |
138 | * Buffer size required to MAC nbytes of data | |
139 | */ | |
140 | size_t maced_data_length (const desfirekey_t key, const size_t nbytes) { | |
141 | return nbytes + key_macing_length (key); | |
142 | } | |
143 | /* | |
144 | * Buffer size required to encipher nbytes of data and a two bytes CRC. | |
145 | */ | |
146 | size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings) { | |
147 | size_t crc_length = 0; | |
148 | if (!(communication_settings & NO_CRC)) { | |
149 | switch (DESFIRE(tag)->authentication_scheme) { | |
150 | case AS_LEGACY: | |
151 | crc_length = 2; | |
152 | break; | |
153 | case AS_NEW: | |
154 | crc_length = 4; | |
155 | break; | |
156 | } | |
157 | } | |
158 | ||
159 | size_t block_size = DESFIRE(tag)->session_key ? key_block_size (DESFIRE(tag)->session_key) : 1; | |
160 | ||
161 | return padded_data_length (nbytes + crc_length, block_size); | |
162 | } | |
163 | ||
164 | void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings) { | |
165 | uint8_t *res = data; | |
166 | uint8_t mac[4]; | |
167 | size_t edl; | |
168 | bool append_mac = true; | |
169 | desfirekey_t key = DESFIRE(tag)->session_key; | |
170 | ||
171 | if (!key) | |
172 | return data; | |
173 | ||
174 | switch (communication_settings & MDCM_MASK) { | |
175 | case MDCM_PLAIN: | |
176 | if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) | |
177 | break; | |
178 | ||
179 | /* | |
180 | * When using new authentication methods, PLAIN data transmission from | |
181 | * the PICC to the PCD are CMACed, so we have to maintain the | |
182 | * cryptographic initialisation vector up-to-date to check data | |
183 | * integrity later. | |
184 | * | |
185 | * The only difference with CMACed data transmission is that the CMAC | |
186 | * is not apended to the data send by the PCD to the PICC. | |
187 | */ | |
188 | ||
189 | append_mac = false; | |
190 | ||
191 | /* pass through */ | |
192 | case MDCM_MACED: | |
193 | switch (DESFIRE(tag)->authentication_scheme) { | |
194 | case AS_LEGACY: | |
195 | if (!(communication_settings & MAC_COMMAND)) | |
196 | break; | |
197 | ||
198 | /* pass through */ | |
199 | edl = padded_data_length (*nbytes - offset, key_block_size (DESFIRE(tag)->session_key)) + offset; | |
200 | ||
201 | // Fill in the crypto buffer with data ... | |
202 | memcpy (res, data, *nbytes); | |
203 | // ... and 0 padding | |
204 | memset (res + *nbytes, 0, edl - *nbytes); | |
205 | ||
206 | mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER); | |
207 | ||
208 | memcpy (mac, res + edl - 8, 4); | |
209 | ||
210 | // Copy again provided data (was overwritten by mifare_cypher_blocks_chained) | |
211 | memcpy (res, data, *nbytes); | |
212 | ||
213 | if (!(communication_settings & MAC_COMMAND)) | |
214 | break; | |
215 | // Append MAC | |
216 | size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset; | |
217 | bla++; | |
218 | ||
219 | memcpy (res + *nbytes, mac, 4); | |
220 | ||
221 | *nbytes += 4; | |
222 | break; | |
223 | case AS_NEW: | |
224 | if (!(communication_settings & CMAC_COMMAND)) | |
225 | break; | |
226 | cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac); | |
227 | ||
228 | if (append_mac) { | |
da198be4 | 229 | size_t len = maced_data_length (key, *nbytes); |
230 | ++len; | |
f38a1528 | 231 | memcpy (res, data, *nbytes); |
232 | memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH); | |
233 | *nbytes += CMAC_LENGTH; | |
234 | } | |
235 | break; | |
236 | } | |
237 | ||
238 | break; | |
239 | case MDCM_ENCIPHERED: | |
240 | /* |<-------------- data -------------->| | |
241 | * |<--- offset -->| | | |
242 | * +---------------+--------------------+-----+---------+ | |
243 | * | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING | | |
244 | * +---------------+--------------------+-----+---------+ ---------------- | |
245 | * | |<~~~~v~~~~~~~~~~~~~>| ^ | | (DES / 3DES) | |
246 | * | | `---- crc16() ----' | | | |
247 | * | | | ^ | | ----- *or* ----- | |
248 | * |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>| ^ | | (3K3DES / AES) | |
249 | * | `---- crc32() ----' | | | |
250 | * | | ---- *then* ---- | |
251 | * |<---------------------------------->| | |
252 | * encypher()/decypher() | |
253 | */ | |
254 | ||
255 | if (!(communication_settings & ENC_COMMAND)) | |
256 | break; | |
257 | edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset; | |
258 | ||
259 | // Fill in the crypto buffer with data ... | |
260 | memcpy (res, data, *nbytes); | |
261 | if (!(communication_settings & NO_CRC)) { | |
262 | // ... CRC ... | |
263 | switch (DESFIRE (tag)->authentication_scheme) { | |
264 | case AS_LEGACY: | |
265 | AppendCrc14443a(res + offset, *nbytes - offset); | |
266 | *nbytes += 2; | |
267 | break; | |
268 | case AS_NEW: | |
269 | crc32_append (res, *nbytes); | |
270 | *nbytes += 4; | |
271 | break; | |
272 | } | |
273 | } | |
274 | // ... and padding | |
275 | memset (res + *nbytes, 0, edl - *nbytes); | |
276 | ||
277 | *nbytes = edl; | |
278 | ||
279 | mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER); | |
280 | break; | |
281 | default: | |
282 | ||
283 | *nbytes = -1; | |
284 | res = NULL; | |
285 | break; | |
286 | } | |
287 | ||
288 | return res; | |
289 | ||
290 | } | |
291 | ||
292 | void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings) | |
293 | { | |
294 | void *res = data; | |
295 | size_t edl; | |
296 | void *edata = NULL; | |
297 | uint8_t first_cmac_byte = 0x00; | |
298 | ||
299 | desfirekey_t key = DESFIRE(tag)->session_key; | |
300 | ||
301 | if (!key) | |
302 | return data; | |
303 | ||
304 | // Return directly if we just have a status code. | |
305 | if (1 == *nbytes) | |
306 | return res; | |
307 | ||
308 | switch (communication_settings & MDCM_MASK) { | |
309 | case MDCM_PLAIN: | |
310 | ||
311 | if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) | |
312 | break; | |
313 | ||
314 | /* pass through */ | |
315 | case MDCM_MACED: | |
316 | switch (DESFIRE (tag)->authentication_scheme) { | |
317 | case AS_LEGACY: | |
318 | if (communication_settings & MAC_VERIFY) { | |
319 | *nbytes -= key_macing_length (key); | |
320 | if (*nbytes <= 0) { | |
321 | *nbytes = -1; | |
322 | res = NULL; | |
323 | #ifdef WITH_DEBUG | |
8d0a3e87 | 324 | Dbprintf ("No room for MAC!"); |
f38a1528 | 325 | #endif |
326 | break; | |
327 | } | |
328 | ||
329 | edl = enciphered_data_length (tag, *nbytes - 1, communication_settings); | |
330 | edata = malloc (edl); | |
331 | ||
332 | memcpy (edata, data, *nbytes - 1); | |
333 | memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1); | |
334 | ||
335 | mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER); | |
336 | ||
337 | if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) { | |
338 | #ifdef WITH_DEBUG | |
8d0a3e87 | 339 | Dbprintf ("MACing not verified"); |
f38a1528 | 340 | hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0); |
341 | hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0); | |
342 | #endif | |
343 | DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; | |
344 | *nbytes = -1; | |
345 | res = NULL; | |
346 | } | |
347 | } | |
348 | break; | |
349 | case AS_NEW: | |
350 | if (!(communication_settings & CMAC_COMMAND)) | |
351 | break; | |
352 | if (communication_settings & CMAC_VERIFY) { | |
353 | if (*nbytes < 9) { | |
354 | *nbytes = -1; | |
355 | res = NULL; | |
356 | break; | |
357 | } | |
358 | first_cmac_byte = ((uint8_t *)data)[*nbytes - 9]; | |
359 | ((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1]; | |
360 | } | |
361 | ||
362 | int n = (communication_settings & CMAC_VERIFY) ? 8 : 0; | |
363 | cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac); | |
364 | ||
365 | if (communication_settings & CMAC_VERIFY) { | |
366 | ((uint8_t *)data)[*nbytes - 9] = first_cmac_byte; | |
367 | if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) { | |
368 | #ifdef WITH_DEBUG | |
8d0a3e87 | 369 | Dbprintf ("CMAC NOT verified :-("); |
f38a1528 | 370 | hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0); |
371 | hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0); | |
372 | #endif | |
373 | DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; | |
374 | *nbytes = -1; | |
375 | res = NULL; | |
376 | } else { | |
377 | *nbytes -= 8; | |
378 | } | |
379 | } | |
380 | break; | |
381 | } | |
382 | ||
383 | free (edata); | |
384 | ||
385 | break; | |
386 | case MDCM_ENCIPHERED: | |
387 | (*nbytes)--; | |
388 | bool verified = false; | |
389 | int crc_pos = 0x00; | |
390 | int end_crc_pos = 0x00; | |
391 | uint8_t x; | |
392 | ||
393 | /* | |
394 | * AS_LEGACY: | |
395 | * ,-----------------+-------------------------------+--------+ | |
396 | * \ BLOCK n-1 | BLOCK n | STATUS | | |
397 | * / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 | | |
398 | * `-----------------+-------------------------------+--------+ | |
399 | * | |
400 | * <------------ DATA ------------> | |
401 | * FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING | |
402 | * | |
403 | * AS_NEW: | |
404 | * ,-------------------------------+-----------------------------------------------+--------+ | |
405 | * \ BLOCK n-1 | BLOCK n | STATUS | | |
406 | * / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 | | |
407 | * `-------------------------------+-----------------------------------------------+--------+ | |
408 | * <----------------------------------- DATA ------------------------------------->| | |
409 | * | |
410 | * <----------------- DATA ----------------> | |
411 | * FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS | |
412 | * `------------------' | |
413 | */ | |
414 | ||
415 | mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER); | |
416 | ||
417 | /* | |
418 | * Look for the CRC and ensure it is followed by NULL padding. We | |
419 | * can't start by the end because the CRC is supposed to be 0 when | |
420 | * verified, and accumulating 0's in it should not change it. | |
421 | */ | |
422 | switch (DESFIRE (tag)->authentication_scheme) { | |
423 | case AS_LEGACY: | |
424 | crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks | |
425 | if (crc_pos < 0) { | |
426 | /* Single block */ | |
427 | crc_pos = 0; | |
428 | } | |
429 | break; | |
430 | case AS_NEW: | |
431 | /* Move status between payload and CRC */ | |
432 | res = DESFIRE (tag)->crypto_buffer; | |
433 | memcpy (res, data, *nbytes); | |
434 | ||
435 | crc_pos = (*nbytes) - 16 - 3; | |
436 | if (crc_pos < 0) { | |
437 | /* Single block */ | |
438 | crc_pos = 0; | |
439 | } | |
440 | memcpy ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos); | |
441 | ((uint8_t *)res)[crc_pos] = 0x00; | |
442 | crc_pos++; | |
443 | *nbytes += 1; | |
444 | break; | |
445 | } | |
446 | ||
447 | do { | |
448 | uint16_t crc16 =0x00; | |
449 | uint32_t crc; | |
450 | switch (DESFIRE (tag)->authentication_scheme) { | |
451 | case AS_LEGACY: | |
452 | end_crc_pos = crc_pos + 2; | |
453 | AppendCrc14443a (res, end_crc_pos); | |
454 | ||
455 | // | |
456 | ||
457 | ||
458 | crc = crc16; | |
459 | break; | |
460 | case AS_NEW: | |
461 | end_crc_pos = crc_pos + 4; | |
462 | crc32 (res, end_crc_pos, (uint8_t *)&crc); | |
463 | break; | |
464 | } | |
465 | if (!crc) { | |
466 | verified = true; | |
467 | for (int n = end_crc_pos; n < *nbytes - 1; n++) { | |
468 | uint8_t byte = ((uint8_t *)res)[n]; | |
469 | if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) )) | |
470 | verified = false; | |
471 | } | |
472 | } | |
473 | if (verified) { | |
474 | *nbytes = crc_pos; | |
475 | switch (DESFIRE (tag)->authentication_scheme) { | |
476 | case AS_LEGACY: | |
477 | ((uint8_t *)data)[(*nbytes)++] = 0x00; | |
478 | break; | |
479 | case AS_NEW: | |
480 | /* The status byte was already before the CRC */ | |
481 | break; | |
482 | } | |
483 | } else { | |
484 | switch (DESFIRE (tag)->authentication_scheme) { | |
485 | case AS_LEGACY: | |
486 | break; | |
487 | case AS_NEW: | |
488 | x = ((uint8_t *)res)[crc_pos - 1]; | |
489 | ((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos]; | |
490 | ((uint8_t *)res)[crc_pos] = x; | |
491 | break; | |
492 | } | |
493 | crc_pos++; | |
494 | } | |
495 | } while (!verified && (end_crc_pos < *nbytes)); | |
496 | ||
497 | if (!verified) { | |
498 | #ifdef WITH_DEBUG | |
499 | /* FIXME In some configurations, the file is transmitted PLAIN */ | |
500 | Dbprintf("CRC not verified in decyphered stream"); | |
501 | #endif | |
502 | DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; | |
503 | *nbytes = -1; | |
504 | res = NULL; | |
505 | } | |
506 | ||
507 | break; | |
508 | default: | |
509 | Dbprintf("Unknown communication settings"); | |
510 | *nbytes = -1; | |
511 | res = NULL; | |
512 | break; | |
513 | ||
514 | } | |
515 | return res; | |
516 | } | |
517 | ||
518 | ||
519 | void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size) | |
520 | { | |
521 | uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE]; | |
522 | ||
523 | if (direction == MCD_SEND) { | |
524 | xor (ivect, data, block_size); | |
525 | } else { | |
526 | memcpy (ovect, data, block_size); | |
527 | } | |
528 | ||
529 | uint8_t edata[MAX_CRYPTO_BLOCK_SIZE]; | |
530 | ||
531 | switch (key->type) { | |
532 | case T_DES: | |
533 | switch (operation) { | |
534 | case MCO_ENCYPHER: | |
535 | //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); | |
536 | des_enc(edata, data, key->data); | |
537 | break; | |
538 | case MCO_DECYPHER: | |
539 | //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); | |
540 | des_dec(edata, data, key->data); | |
541 | break; | |
542 | } | |
543 | break; | |
544 | case T_3DES: | |
545 | switch (operation) { | |
546 | case MCO_ENCYPHER: | |
547 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); | |
548 | // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); | |
549 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); | |
550 | tdes_enc(edata,data, key->data); | |
551 | break; | |
552 | case MCO_DECYPHER: | |
553 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); | |
554 | // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); | |
555 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); | |
556 | tdes_dec(data, edata, key->data); | |
557 | break; | |
558 | } | |
559 | break; | |
560 | case T_3K3DES: | |
561 | switch (operation) { | |
562 | case MCO_ENCYPHER: | |
563 | tdes_enc(edata,data, key->data); | |
564 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); | |
565 | // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); | |
566 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT); | |
567 | break; | |
568 | case MCO_DECYPHER: | |
569 | tdes_dec(data, edata, key->data); | |
570 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT); | |
571 | // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); | |
572 | // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); | |
573 | break; | |
574 | } | |
575 | break; | |
576 | case T_AES: | |
577 | switch (operation) | |
578 | { | |
579 | case MCO_ENCYPHER: | |
580 | { | |
581 | AesCtx ctx; | |
582 | AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); | |
583 | AesEncrypt(&ctx, data, edata, sizeof(data) ); | |
584 | break; | |
585 | } | |
586 | case MCO_DECYPHER: | |
587 | { | |
588 | AesCtx ctx; | |
589 | AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); | |
590 | AesDecrypt(&ctx, edata, data, sizeof(edata)); | |
591 | break; | |
592 | } | |
593 | } | |
594 | break; | |
595 | } | |
596 | ||
597 | memcpy (data, edata, block_size); | |
598 | ||
599 | if (direction == MCD_SEND) { | |
600 | memcpy (ivect, data, block_size); | |
601 | } else { | |
602 | xor (ivect, data, block_size); | |
603 | memcpy (ivect, ovect, block_size); | |
604 | } | |
605 | } | |
606 | ||
607 | /* | |
608 | * This function performs all CBC cyphering / deciphering. | |
609 | * | |
610 | * The tag argument may be NULL, in which case both key and ivect shall be set. | |
611 | * When using the tag session_key and ivect for processing data, these | |
612 | * arguments should be set to NULL. | |
613 | * | |
614 | * Because the tag may contain additional data, one may need to call this | |
615 | * function with tag, key and ivect defined. | |
616 | */ | |
617 | void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) { | |
618 | size_t block_size; | |
619 | ||
620 | if (tag) { | |
621 | if (!key) | |
622 | key = DESFIRE (tag)->session_key; | |
623 | if (!ivect) | |
624 | ivect = DESFIRE (tag)->ivect; | |
625 | ||
626 | switch (DESFIRE (tag)->authentication_scheme) { | |
627 | case AS_LEGACY: | |
628 | memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE); | |
629 | break; | |
630 | case AS_NEW: | |
631 | break; | |
632 | } | |
633 | } | |
634 | ||
635 | block_size = key_block_size (key); | |
636 | ||
637 | size_t offset = 0; | |
638 | while (offset < data_size) { | |
639 | mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size); | |
640 | offset += block_size; | |
641 | } | |
642 | } |