| 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 | |
| 30 | static void xor (const uint8_t *ivect, uint8_t *data, const size_t len); |
| 31 | |
| 32 | static size_t key_macing_length (desfirekey_t key); |
| 33 | |
| 34 | static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) { |
| 35 | for (size_t i = 0; i < len; i++) { |
| 36 | data[i] ^= ivect[i]; |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | void cmac_generate_subkeys ( desfirekey_t key) { |
| 41 | int kbs = key_block_size (key); |
| 42 | const uint8_t R = (kbs == 8) ? 0x1B : 0x87; |
| 43 | |
| 44 | uint8_t l[kbs]; |
| 45 | memset (l, 0, kbs); |
| 46 | |
| 47 | uint8_t ivect[kbs]; |
| 48 | memset (ivect, 0, kbs); |
| 49 | |
| 50 | mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER); |
| 51 | |
| 52 | bool xor = false; |
| 53 | |
| 54 | // Used to compute CMAC on complete blocks |
| 55 | memcpy (key->cmac_sk1, l, kbs); |
| 56 | xor = l[0] & 0x80; |
| 57 | lsl (key->cmac_sk1, kbs); |
| 58 | if (xor) |
| 59 | key->cmac_sk1[kbs-1] ^= R; |
| 60 | |
| 61 | // Used to compute CMAC on the last block if non-complete |
| 62 | memcpy (key->cmac_sk2, key->cmac_sk1, kbs); |
| 63 | xor = key->cmac_sk1[0] & 0x80; |
| 64 | lsl (key->cmac_sk2, kbs); |
| 65 | if (xor) |
| 66 | key->cmac_sk2[kbs-1] ^= R; |
| 67 | } |
| 68 | |
| 69 | void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) { |
| 70 | int kbs = key_block_size (key); |
| 71 | uint8_t *buffer = malloc (padded_data_length (len, kbs)); |
| 72 | |
| 73 | memcpy (buffer, data, len); |
| 74 | |
| 75 | if ((!len) || (len % kbs)) { |
| 76 | buffer[len++] = 0x80; |
| 77 | while (len % kbs) { |
| 78 | buffer[len++] = 0x00; |
| 79 | } |
| 80 | xor (key->cmac_sk2, buffer + len - kbs, kbs); |
| 81 | } else { |
| 82 | xor (key->cmac_sk1, buffer + len - kbs, kbs); |
| 83 | } |
| 84 | |
| 85 | mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); |
| 86 | |
| 87 | memcpy (cmac, ivect, kbs); |
| 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) { |
| 229 | maced_data_length (key, *nbytes); |
| 230 | |
| 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 |
| 324 | Dbprintf ("No room for MAC!"); |
| 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 |
| 339 | Dbprintf ("MACing not verified"); |
| 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 |
| 369 | Dbprintf ("CMAC NOT verified :-("); |
| 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 | } |