1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 #include "mifaredesfire.h"
19 #include "proxmark3_arm.h"
22 #include "mifareutil.h"
23 #include "desfire_crypto.h"
26 #include "fpgaloader.h"
27 #include "iso14443a.h"
29 #include "commonutil.h"
33 #include "protocols.h"
35 #define MAX_APPLICATION_COUNT 28
36 #define MAX_FILE_COUNT 16
37 #define MAX_DESFIRE_FRAME_SIZE 60
38 #define NOT_YET_AUTHENTICATED 255
39 #define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
40 #define RECEIVE_SIZE 64
42 // the block number for the ISO14443-4 PCB
43 static uint8_t pcb_blocknum
= 0;
44 // Deselect card by sending a s-block. the crc is precalced for speed
45 static uint8_t deselect_cmd
[] = {0xc2, 0xe0, 0xb4};
47 //static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
48 /* PCB CID CMD PAYLOAD */
49 //static uint8_t __res[MAX_FRAME_SIZE];
51 static struct desfire_key skey
= {0};
52 static desfirekey_t sessionkey
= &skey
;
54 bool InitDesfireCard(void) {
58 iso14a_card_select_t card
;
60 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN
);
63 if (!iso14443a_select_card(NULL
, &card
, NULL
, true, 0, false)) {
64 if (g_dbglevel
>= DBG_ERROR
) DbpString("Can't select card");
73 uint8_t data
[RECEIVE_SIZE
];
76 void MifareSendCommand(uint8_t *datain
) {
80 uint8_t datain
[FRAME_PAYLOAD_SIZE
];
82 struct p
*payload
= (struct p
*) datain
;
84 uint8_t resp
[RECEIVE_SIZE
];
85 memset(resp
, 0, sizeof(resp
));
87 if (g_dbglevel
>= DBG_EXTENDED
) {
88 Dbprintf(" flags : %02X", payload
->flags
);
89 Dbprintf(" len : %02X", payload
->datalen
);
90 print_result(" RX : ", payload
->datain
, payload
->datalen
);
93 if (payload
->flags
& CLEARTRACE
)
96 if (payload
->flags
& INIT
) {
97 if (!InitDesfireCard()) {
102 int len
= DesfireAPDU(payload
->datain
, payload
->datalen
, resp
);
103 if (g_dbglevel
>= DBG_EXTENDED
)
104 print_result("RESP <--: ", resp
, len
);
111 if (payload
->flags
& DISCONNECT
)
114 //reply_mix(CMD_ACK, 1, len, 0, resp, len);
120 memcpy(rpayload
.data
, resp
, rpayload
.len
);
121 reply_ng(CMD_HF_DESFIRE_COMMAND
, PM3_SUCCESS
, (uint8_t *)&rpayload
, sizeof(rpayload
));
125 void MifareDesfireGetInformation(void) {
130 iso14a_card_select_t card
;
131 uint8_t resp
[PM3_CMD_DATA_SIZE
] = {0x00};
137 uint8_t versionHW
[7];
138 uint8_t versionSW
[7];
142 memset(&payload
, 0x00, sizeof(payload
));
146 3 = desfire command 3
149 PCB == 0x0A because sending CID byte.
150 CID == 0x00 first card?
154 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN
);
156 // reset the pcb_blocknum,
159 // card select - information
160 if (!iso14443a_select_card(NULL
, &card
, NULL
, true, 0, false)) {
161 if (g_dbglevel
>= DBG_ERROR
) {
162 DbpString("Can't select card");
164 payload
.isOK
= 1; // 2 == can not select
165 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_ESOFT
, (uint8_t *)&payload
, sizeof(payload
));
171 memcpy(payload
.uid
, card
.uid
, card
.uidlen
);
172 payload
.uidlen
= card
.uidlen
;
175 uint8_t cmd
[] = {0x90, MFDES_GET_VERSION
, 0x00, 0x00, 0x00};
176 size_t cmd_len
= sizeof(cmd
);
178 len
= DesfireAPDU(cmd
, cmd_len
, resp
);
180 print_result("ERROR <--: ", resp
, len
);
181 payload
.isOK
= 3; // 3 == DOESN'T ANSWER TO GET_VERSION
182 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_ESOFT
, (uint8_t *)&payload
, sizeof(payload
));
187 if (len
< sizeof(payload
.versionHW
) + 1) {
188 payload
.isOK
= 3; // 3 == DOESN'T ANSWER TO GET_VERSION
189 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_ESOFT
, (uint8_t *)&payload
, sizeof(payload
));
191 if (g_dbglevel
>= DBG_ERROR
) {
192 Dbprintf("Tag answer to MFDES_GET_VERSION was too short: data in Hardware Information is probably invalid.");
193 print_result("Answer", resp
, len
);
198 memcpy(payload
.versionHW
, resp
+ 1, sizeof(payload
.versionHW
));
201 cmd
[1] = MFDES_ADDITIONAL_FRAME
;
202 len
= DesfireAPDU(cmd
, cmd_len
, resp
);
204 payload
.isOK
= 3; // 3 == DOESN'T ANSWER TO GET_VERSION
205 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_ESOFT
, (uint8_t *)&payload
, sizeof(payload
));
210 if (len
< sizeof(payload
.versionSW
) + 1) {
211 payload
.isOK
= 3; // 3 == DOESN'T ANSWER TO GET_VERSION
212 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_ESOFT
, (uint8_t *)&payload
, sizeof(payload
));
214 if (g_dbglevel
>= DBG_ERROR
) {
215 Dbprintf("Tag answer to MFDES_ADDITIONAL_FRAME 1 was too short: data in Software Information is probably invalid.");
216 print_result("Answer", resp
, len
);
221 memcpy(payload
.versionSW
, resp
+ 1, sizeof(payload
.versionSW
));
224 len
= DesfireAPDU(cmd
, cmd_len
, resp
);
226 payload
.isOK
= 3; // 3 == DOESN'T ANSWER TO GET_VERSION
227 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_ESOFT
, (uint8_t *)&payload
, sizeof(payload
));
232 if (len
< sizeof(payload
.details
) + 1) {
233 payload
.isOK
= 3; // 3 == DOESN'T ANSWER TO GET_VERSION
234 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_ESOFT
, (uint8_t *)&payload
, sizeof(payload
));
236 if (g_dbglevel
>= DBG_ERROR
) {
237 Dbprintf("Tag answer to MFDES_ADDITIONAL_FRAME 2 was too short: data in Batch number and Production date is probably invalid");
238 print_result("Answer", resp
, len
);
243 memcpy(payload
.details
, resp
+ 1, sizeof(payload
.details
));
245 reply_ng(CMD_HF_DESFIRE_INFO
, PM3_SUCCESS
, (uint8_t *)&payload
, sizeof(payload
));
247 // reset the pcb_blocknum,
253 uint8_t sessionkeylen
;
254 uint8_t sessionkey
[24];
257 void MifareDES_Auth1(uint8_t *datain
) {
266 struct p
*payload
= (struct p
*) datain
;
268 // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
269 // 4 different crypto arg1 DES, 3DES, 3K3DES, AES
270 // 3 different communication modes, PLAIN,MAC,CRYPTO
272 mbedtls_aes_context ctx
;
274 uint8_t keybytes
[24];
275 uint8_t resp
[256] = {0x00};
276 uint8_t cmd
[40] = {0x00};
279 uint8_t IV
[16] = {0x00};
280 uint8_t RndA
[16] = {0x00};
281 uint8_t RndB
[16] = {0x00};
282 uint8_t encRndB
[16] = {0x00};
283 uint8_t rotRndB
[16] = {0x00}; //RndB'
284 uint8_t both
[32] = {0x00}; // ek/dk_keyNo(RndA+RndB')
286 // Generate Random Value
287 uint32_t value
= prng_successor(GetTickCount(), 32);
288 num_to_bytes(value
, 4, &RndA
[0]);
289 value
= prng_successor(GetTickCount(), 32);
290 num_to_bytes(value
, 4, &RndA
[4]);
291 value
= prng_successor(GetTickCount(), 32);
292 num_to_bytes(value
, 4, &RndA
[8]);
293 value
= prng_successor(GetTickCount(), 32);
294 num_to_bytes(value
, 4, &RndA
[12]);
297 uint8_t PICC_MASTER_KEY8
[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
298 uint8_t PICC_MASTER_KEY16
[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 uint8_t PICC_MASTER_KEY24
[24] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
304 //uint8_t null_key_data16[16] = {0x00};
305 //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
306 //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
317 if (payload
->keylen
== 0) {
318 if (payload
->algo
== MFDES_AUTH_DES
) {
319 memcpy(keybytes
, PICC_MASTER_KEY8
, 8);
320 } else if (payload
->algo
== MFDES_ALGO_AES
|| payload
->algo
== MFDES_ALGO_3DES
) {
321 memcpy(keybytes
, PICC_MASTER_KEY16
, 16);
322 } else if (payload
->algo
== MFDES_ALGO_3K3DES
) {
323 memcpy(keybytes
, PICC_MASTER_KEY24
, 24);
326 memcpy(keybytes
, payload
->key
, payload
->keylen
);
330 struct desfire_key defaultkey
= {0};
331 desfirekey_t key
= &defaultkey
;
333 if (payload
->algo
== MFDES_ALGO_AES
) {
334 mbedtls_aes_init(&ctx
);
335 Desfire_aes_key_new(keybytes
, key
);
336 } else if (payload
->algo
== MFDES_ALGO_3DES
) {
337 Desfire_3des_key_new_with_version(keybytes
, key
);
338 } else if (payload
->algo
== MFDES_ALGO_DES
) {
339 Desfire_des_key_new(keybytes
, key
);
340 } else if (payload
->algo
== MFDES_ALGO_3K3DES
) {
341 Desfire_3k3des_key_new_with_version(keybytes
, key
);
344 uint8_t subcommand
= MFDES_AUTHENTICATE
;
346 if (payload
->mode
== MFDES_AUTH_AES
) {
347 subcommand
= MFDES_AUTHENTICATE_AES
;
348 } else if (payload
->mode
== MFDES_AUTH_ISO
) {
349 subcommand
= MFDES_AUTHENTICATE_ISO
;
352 if (payload
->mode
!= MFDES_AUTH_PICC
) {
353 // Let's send our auth command
359 cmd
[5] = payload
->keyno
;
361 len
= DesfireAPDU(cmd
, 7, resp
);
363 cmd
[0] = MFDES_AUTHENTICATE
;
364 cmd
[1] = payload
->keyno
;
365 len
= DesfireAPDU(cmd
, 2, resp
);
369 if (g_dbglevel
>= DBG_ERROR
) {
370 DbpString("Authentication failed. Card timeout.");
372 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 3);
376 if (resp
[2] == (uint8_t)MFDES_ADDITIONAL_FRAME
) {
377 DbpString("Authentication failed. Invalid key number.");
378 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 3);
383 int expectedlen
= 1 + 8 + 2 + 2;
384 if (payload
->algo
== MFDES_ALGO_AES
|| payload
->algo
== MFDES_ALGO_3K3DES
) {
385 expectedlen
= 1 + 16 + 2 + 2;
389 if (payload
->mode
== MFDES_AUTH_PICC
) {
390 expectedlen
= 1 + 1 + 8 + 2;
394 if (len
!= expectedlen
) {
395 if (g_dbglevel
>= DBG_ERROR
) {
396 DbpString("Authentication failed. Length of answer doesn't match algo.");
397 print_result("Res-Buffer: ", resp
, len
);
399 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 3);
404 if (payload
->mode
!= MFDES_AUTH_PICC
) {
405 memcpy(encRndB
, resp
+ 1, rndlen
);
407 memcpy(encRndB
, resp
+ 2, rndlen
);
411 if (payload
->algo
== MFDES_ALGO_AES
) {
413 if (mbedtls_aes_setkey_dec(&ctx
, key
->data
, 128) != 0) {
414 if (g_dbglevel
>= DBG_EXTENDED
) {
415 DbpString("mbedtls_aes_setkey_dec failed");
417 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 7);
420 mbedtls_aes_crypt_cbc(&ctx
, MBEDTLS_AES_DECRYPT
, 16, IV
, encRndB
, RndB
);
422 } else if (payload
->algo
== MFDES_ALGO_DES
) {
423 des_decrypt(RndB
, encRndB
, key
->data
);
424 } else if (payload
->algo
== MFDES_ALGO_3DES
) {
425 tdes_nxp_receive(encRndB
, RndB
, rndlen
, key
->data
, IV
, 2);
426 } else if (payload
->algo
== MFDES_ALGO_3K3DES
) {
427 tdes_nxp_receive(encRndB
, RndB
, rndlen
, key
->data
, IV
, 3);
430 // - Rotate RndB by 8 bits
431 memcpy(rotRndB
, RndB
, rndlen
);
432 rol(rotRndB
, rndlen
);
434 uint8_t encRndA
[16] = {0x00};
436 // - Encrypt our response
437 if (payload
->mode
== MFDES_AUTH_DES
|| payload
->mode
== MFDES_AUTH_PICC
) {
439 des_decrypt(encRndA
, RndA
, key
->data
);
440 memcpy(both
, encRndA
, rndlen
);
442 for (int x
= 0; x
< rndlen
; x
++) {
443 rotRndB
[x
] = rotRndB
[x
] ^ encRndA
[x
];
446 des_decrypt(encRndB
, rotRndB
, key
->data
);
447 memcpy(both
+ 8, encRndB
, rndlen
);
449 } else if (payload
->mode
== MFDES_AUTH_ISO
) {
451 if (payload
->algo
== MFDES_ALGO_3DES
) {
452 uint8_t tmp
[16] = {0x00};
453 memcpy(tmp
, RndA
, rndlen
);
454 memcpy(tmp
+ rndlen
, rotRndB
, rndlen
);
455 tdes_nxp_send(tmp
, both
, 16, key
->data
, IV
, 2);
456 } else if (payload
->algo
== MFDES_ALGO_3K3DES
) {
457 uint8_t tmp
[32] = {0x00};
458 memcpy(tmp
, RndA
, rndlen
);
459 memcpy(tmp
+ rndlen
, rotRndB
, rndlen
);
460 tdes_nxp_send(tmp
, both
, 32, key
->data
, IV
, 3);
463 } else if (payload
->mode
== MFDES_AUTH_AES
) {
465 uint8_t tmp
[32] = {0x00};
466 memcpy(tmp
, RndA
, rndlen
);
467 memcpy(tmp
+ 16, rotRndB
, rndlen
);
469 if (payload
->algo
== MFDES_ALGO_AES
) {
471 if (mbedtls_aes_setkey_enc(&ctx
, key
->data
, 128) != 0) {
472 if (g_dbglevel
>= DBG_EXTENDED
) {
473 DbpString("mbedtls_aes_setkey_enc failed");
475 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 7);
478 mbedtls_aes_crypt_cbc(&ctx
, MBEDTLS_AES_ENCRYPT
, 32, IV
, tmp
, both
);
483 if (payload
->algo
== MFDES_ALGO_AES
|| payload
->algo
== MFDES_ALGO_3K3DES
) {
487 if (payload
->mode
!= MFDES_AUTH_PICC
) {
489 cmd
[1] = MFDES_ADDITIONAL_FRAME
;
493 memcpy(cmd
+ 5, both
, bothlen
);
494 cmd
[bothlen
+ 5] = 0x0;
495 len
= DesfireAPDU(cmd
, 5 + bothlen
+ 1, resp
);
497 cmd
[0] = MFDES_ADDITIONAL_FRAME
;
498 memcpy(cmd
+ 1, both
, bothlen
);
499 len
= DesfireAPDU(cmd
, 1 + bothlen
, resp
);
503 if (g_dbglevel
>= DBG_ERROR
) {
504 DbpString("Authentication failed. Card timeout.");
506 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 3);
510 if (payload
->mode
!= MFDES_AUTH_PICC
) {
512 if ((resp
[len
- 4] != 0x91) || (resp
[len
- 3] != 0x00)) {
513 DbpString("Authentication failed.");
514 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 6);
520 if (resp
[1] != 0x00) {
521 DbpString("Authentication failed.");
522 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 6);
530 Desfire_session_key_new(RndA
, RndB
, key
, sessionkey
);
532 if (g_dbglevel
>= DBG_EXTENDED
) {
533 print_result("SESSIONKEY : ", sessionkey
->data
, payload
->keylen
);
536 if (payload
->mode
!= MFDES_AUTH_PICC
) {
537 memcpy(encRndA
, resp
+ 1, rndlen
);
539 memcpy(encRndA
, resp
+ 2, rndlen
);
542 if (payload
->mode
== MFDES_AUTH_DES
|| payload
->mode
== MFDES_AUTH_PICC
) {
544 if (payload
->algo
== MFDES_ALGO_DES
) {
545 des_decrypt(encRndA
, encRndA
, key
->data
);
546 } else if (payload
->algo
== MFDES_ALGO_3DES
) {
547 tdes_nxp_receive(encRndA
, encRndA
, rndlen
, key
->data
, IV
, 2);
548 } else if (payload
->algo
== MFDES_ALGO_3K3DES
) {
549 tdes_nxp_receive(encRndA
, encRndA
, rndlen
, key
->data
, IV
, 3);
552 } else if (payload
->mode
== MFDES_AUTH_AES
) {
554 if (mbedtls_aes_setkey_dec(&ctx
, key
->data
, 128) != 0) {
555 if (g_dbglevel
>= DBG_EXTENDED
) {
556 DbpString("mbedtls_aes_setkey_dec failed");
558 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 7);
561 mbedtls_aes_crypt_cbc(&ctx
, MBEDTLS_AES_DECRYPT
, 16, IV
, encRndA
, encRndA
);
565 if (g_dbglevel
>= DBG_EXTENDED
) {
566 print_result("RndA : ", RndA
, rndlen
);
567 print_result("RndB: ", RndB
, rndlen
);
568 print_result("encRndA : ", encRndA
, rndlen
);
571 for (int x
= 0; x
< rndlen
; x
++) {
572 if (RndA
[x
] != encRndA
[x
]) {
573 DbpString("Authentication failed. Cannot verify Session Key.");
574 OnErrorNG(CMD_HF_DESFIRE_AUTH1
, 4);
578 //Change the selected key to a new value.
581 // Current key is a 3DES key, change it to a DES key
582 if (payload->algo == 2) {
585 cmd[2] = payload->keyno;
587 uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
589 uint8_t first, second;
590 uint8_t buff1[8] = {0x00};
591 uint8_t buff2[8] = {0x00};
592 uint8_t buff3[8] = {0x00};
594 memcpy(buff1,newKey, 8);
595 memcpy(buff2,newKey + 8, 8);
597 compute_crc(CRC_14443_A, newKey, 16, &first, &second);
598 memcpy(buff3, &first, 1);
599 memcpy(buff3 + 1, &second, 1);
601 tdes_dec(&buff1, &buff1, skey->data);
602 memcpy(cmd+2,buff1,8);
604 for (int x = 0; x < 8; x++) {
605 buff2[x] = buff2[x] ^ buff1[x];
607 tdes_dec(&buff2, &buff2, skey->data);
608 memcpy(cmd+10,buff2,8);
610 for (int x = 0; x < 8; x++) {
611 buff3[x] = buff3[x] ^ buff2[x];
613 tdes_dec(&buff3, &buff3, skey->data);
614 memcpy(cmd+19,buff3,8);
616 // The command always times out on the first attempt, this will retry until a response
620 len = DesfireAPDU(cmd,27,resp);
624 // Current key is a DES key, change it to a 3DES key
625 if (payload->algo == 1) {
628 cmd[2] = payload->keyno;
630 uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
632 uint8_t first, second;
633 uint8_t buff1[8] = {0x00};
634 uint8_t buff2[8] = {0x00};
635 uint8_t buff3[8] = {0x00};
637 memcpy(buff1,newKey, 8);
638 memcpy(buff2,newKey + 8, 8);
640 compute_crc(CRC_14443_A, newKey, 16, &first, &second);
641 memcpy(buff3, &first, 1);
642 memcpy(buff3 + 1, &second, 1);
644 des_dec(&buff1, &buff1, skey->data);
645 memcpy(cmd+3,buff1,8);
647 for (int x = 0; x < 8; x++) {
648 buff2[x] = buff2[x] ^ buff1[x];
650 des_dec(&buff2, &buff2, skey->data);
651 memcpy(cmd+11,buff2,8);
653 for (int x = 0; x < 8; x++) {
654 buff3[x] = buff3[x] ^ buff2[x];
656 des_dec(&buff3, &buff3, skey->data);
657 memcpy(cmd+19,buff3,8);
659 // The command always times out on the first attempt, this will retry until a response
663 len = DesfireAPDU(cmd,27,resp);
672 rpayload
.sessionkeylen
= payload
->keylen
;
673 memcpy(rpayload
.sessionkey
, sessionkey
->data
, rpayload
.sessionkeylen
);
674 reply_ng(CMD_HF_DESFIRE_AUTH1
, PM3_SUCCESS
, (uint8_t *)&rpayload
, sizeof(rpayload
));
678 // 3 different ISO ways to send data to a DESFIRE (direct, capsuled, capsuled ISO)
679 // cmd = cmd bytes to send
680 // cmd_len = length of cmd
681 // dataout = pointer to response data array
682 int DesfireAPDU(uint8_t *cmd
, size_t cmd_len
, uint8_t *dataout
) {
685 size_t wrappedLen
= 0;
686 uint8_t wCmd
[PM3_CMD_DATA_SIZE
] = {0x00};
687 uint8_t resp
[MAX_FRAME_SIZE
];
688 uint8_t par
[MAX_PARITY_SIZE
];
690 wrappedLen
= CreateAPDU(cmd
, cmd_len
, wCmd
);
692 if (g_dbglevel
>= DBG_EXTENDED
) {
693 print_result("WCMD <--: ", wCmd
, wrappedLen
);
696 ReaderTransmit(wCmd
, wrappedLen
, NULL
);
698 len
= ReaderReceive(resp
, sizeof(resp
), par
);
700 if (g_dbglevel
>= DBG_EXTENDED
) Dbprintf("fukked");
701 return false; //DATA LINK ERROR
704 // if we received an I- or R(ACK)-Block with a block number equal to the
705 // current block number, toggle the current block number
706 if (len
>= 4 // PCB+CID+CRC = 4 bytes
707 && ((resp
[0] & 0xC0) == 0 // I-Block
708 || (resp
[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
709 && (resp
[0] & 0x01) == pcb_blocknum
) { // equal block numbers
710 pcb_blocknum
^= 1; //toggle next block
713 memcpy(dataout
, resp
, len
);
718 size_t CreateAPDU(uint8_t *datain
, size_t len
, uint8_t *dataout
) {
720 size_t cmdlen
= MIN(len
+ 3, PM3_CMD_DATA_SIZE
- 1);
723 memset(cmd
, 0, cmdlen
);
725 cmd
[0] = 0x02; // 0x0A = send cid, 0x02 = no cid.
726 cmd
[0] |= pcb_blocknum
; // OR the block number into the PCB
728 if (g_dbglevel
>= DBG_EXTENDED
) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum
, cmd
[0]);
730 //cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards
732 memcpy(cmd
+ 1, datain
, len
);
733 AddCrc14A(cmd
, len
+ 1);
736 hf 14a apdu -sk 90 60 00 00 00
737 hf 14a apdu -k 90 AF 00 00 00
738 hf 14a apdu 90AF000000
740 memcpy(dataout
, cmd
, cmdlen
);
744 // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
745 // crc_update(&desfire_crc32, addr, addr_sz);
746 // crc_update(&desfire_crc32, byte, 8);
747 // uint32_t crc = crc_finish(&desfire_crc32);
749 void OnSuccess(void) {
751 ReaderTransmit(deselect_cmd
, 3, NULL
);
752 if (mifare_ultra_halt()) {
753 if (g_dbglevel
>= DBG_ERROR
) Dbprintf("Halt error");
758 void OnError(uint8_t reason
) {
759 reply_mix(CMD_ACK
, 0, reason
, 0, 0, 0);
763 void OnErrorNG(uint16_t cmd
, uint8_t reason
) {
764 reply_ng(cmd
, reason
, NULL
, 0);