1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2014 Iceman
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // High frequency MIFARE Desfire commands
9 //-----------------------------------------------------------------------------
15 #include "loclass/des.h"
17 #include "proxmark3.h"
18 #include "../include/common.h"
19 #include "../include/mifare.h"
20 #include "../common/iso14443crc.h"
23 #include "cmdparser.h"
25 #include "cmdhfmfdes.h"
32 uint8_t key_zero_data
[16] = { 0x00 };
33 uint8_t key_ones_data
[16] = { 0x01 };
34 uint8_t key_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
35 uint8_t key_picc_data
[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
37 static int CmdHelp(const char *Cmd
);
39 int CmdHF14ADesWb(const char *Cmd
)
41 /* uint8_t blockNo = 0;
43 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
44 uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
49 PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
50 PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
54 blockNo = param_get8(Cmd, 0);
55 cmdp = param_getchar(Cmd, 1);
57 PrintAndLog("Key type must be A or B");
60 if (cmdp != 'A' && cmdp != 'a') keyType = 1;
61 if (param_gethex(Cmd, 2, key, 12)) {
62 PrintAndLog("Key must include 12 HEX symbols");
65 if (param_gethex(Cmd, 3, bldata, 32)) {
66 PrintAndLog("Block data must include 32 HEX symbols");
69 PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
70 PrintAndLog("--data: %s", sprint_hex(bldata, 16));
72 UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
73 memcpy(c.d.asBytes, key, 6);
74 memcpy(c.d.asBytes + 10, bldata, 16);
78 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
79 uint8_t isOK = resp.arg[0] & 0xff;
80 PrintAndLog("isOk:%02x", isOK);
82 PrintAndLog("Command execute timeout");
88 int CmdHF14ADesRb(const char *Cmd
)
90 // uint8_t blockNo = 0;
91 // uint8_t keyType = 0;
92 // uint8_t key[6] = {0, 0, 0, 0, 0, 0};
97 // if (strlen(Cmd)<3) {
98 // PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
99 // PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
103 // blockNo = param_get8(Cmd, 0);
104 // cmdp = param_getchar(Cmd, 1);
105 // if (cmdp == 0x00) {
106 // PrintAndLog("Key type must be A or B");
109 // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
110 // if (param_gethex(Cmd, 2, key, 12)) {
111 // PrintAndLog("Key must include 12 HEX symbols");
114 // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
116 // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
117 // memcpy(c.d.asBytes, key, 6);
121 // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
122 // uint8_t isOK = resp.arg[0] & 0xff;
123 // uint8_t * data = resp.d.asBytes;
126 // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
128 // PrintAndLog("isOk:%02x", isOK);
130 // PrintAndLog("Command execute timeout");
136 int CmdHF14ADesInfo(const char *Cmd
){
138 UsbCommand c
= {CMD_MIFARE_DESFIRE_INFO
};
142 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
143 PrintAndLog("Command execute timeout");
146 uint8_t isOK
= resp
.arg
[0] & 0xff;
148 PrintAndLog("Command unsuccessful");
152 PrintAndLog("-- Desfire Information --------------------------------------");
153 PrintAndLog("-------------------------------------------------------------");
154 PrintAndLog(" UID : %s",sprint_hex(resp
.d
.asBytes
, 7));
155 PrintAndLog(" Batch number : %s",sprint_hex(resp
.d
.asBytes
+28,5));
156 PrintAndLog(" Production date : week %02x, 20%02x",resp
.d
.asBytes
[33], resp
.d
.asBytes
[34]);
157 PrintAndLog(" -----------------------------------------------------------");
158 PrintAndLog(" Hardware Information");
159 PrintAndLog(" Vendor Id : %s", getTagInfo(resp
.d
.asBytes
[7]));
160 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[8]);
161 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[9]);
162 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[10], resp
.d
.asBytes
[11]);
163 PrintAndLog(" Storage size : %s",GetCardSizeStr(resp
.d
.asBytes
[12]));
164 PrintAndLog(" Protocol : %s",GetProtocolStr(resp
.d
.asBytes
[13]));
165 PrintAndLog(" -----------------------------------------------------------");
166 PrintAndLog(" Software Information");
167 PrintAndLog(" Vendor Id : %s", getTagInfo(resp
.d
.asBytes
[14]));
168 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[15]);
169 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[16]);
170 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[17], resp
.d
.asBytes
[18]);
171 PrintAndLog(" storage size : %s", GetCardSizeStr(resp
.d
.asBytes
[19]));
172 PrintAndLog(" Protocol : %s", GetProtocolStr(resp
.d
.asBytes
[20]));
173 PrintAndLog("-------------------------------------------------------------");
175 // Master Key settings
176 GetKeySettings(NULL
);
178 // Free memory on card
179 c
.cmd
= CMD_MIFARE_DESFIRE
;
180 c
.arg
[0] = (INIT
| DISCONNECT
);
182 c
.d
.asBytes
[0] = GET_FREE_MEMORY
;
184 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
189 memcpy(tmp
, resp
.d
.asBytes
+3,3);
191 PrintAndLog(" Available free memory on card : %d bytes", le24toh( tmp
));
192 PrintAndLog("-------------------------------------------------------------");
195 Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
196 Application Master Key (AMK) 0x00 AID != 00 00 00
197 Application keys (APK) 0x01-0x0D
198 Application free 0x0E
199 Application never 0x0F
213 The 7 MSBits (= n) code the storage size itself based on 2^n,
214 the LSBit is set to '0' if the size is exactly 2^n
215 and set to '1' if the storage size is between 2^n and 2^(n+1).
216 For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
218 char * GetCardSizeStr( uint8_t fsize
){
223 uint16_t usize
= 1 << ((fsize
>>1) + 1);
224 uint16_t lsize
= 1 << (fsize
>>1);
228 sprintf(retStr
, "0x%02X (%d - %d bytes)",fsize
, usize
, lsize
);
230 sprintf(retStr
, "0x%02X (%d bytes)", fsize
, lsize
);
234 char * GetProtocolStr(uint8_t id
){
240 sprintf(retStr
,"0x%02X (ISO 14443-3, 14443-4)", id
);
242 sprintf(retStr
,"0x%02X (Unknown)", id
);
246 void GetKeySettings( uint8_t *aid
){
248 char messStr
[512] = {0x00};
251 uint32_t options
= NONE
;
255 //memset(messStr, 0x00, 512);
257 c
.cmd
= CMD_MIFARE_DESFIRE
;
260 PrintAndLog(" CMK - PICC, Card Master Key settings ");
262 c
.arg
[CMDPOS
] = (INIT
| DISCONNECT
);
263 c
.arg
[LENPOS
] = 0x01;
264 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
266 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
267 isOK
= resp
.arg
[0] & 0xff;
269 PrintAndLog(" Can't select master application");
273 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
274 PrintAndLog(" [0x08] Configuration changeable : %s", str
);
275 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
276 PrintAndLog(" [0x04] CMK required for create/delete : %s",str
);
277 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
278 PrintAndLog(" [0x02] Directory list access with CMK : %s",str
);
279 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
280 PrintAndLog(" [0x01] CMK is changeable : %s", str
);
282 c
.arg
[LENPOS
] = 0x02; //LEN
283 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
284 c
.d
.asBytes
[1] = 0x00;
286 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {
289 isOK
= resp
.arg
[0] & 0xff;
291 PrintAndLog(" Can't read key-version");
295 PrintAndLog(" Max number of keys : %d", resp
.d
.asBytes
[4]);
296 PrintAndLog(" Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
297 PrintAndLog(" ----------------------------------------------------------");
299 c
.arg
[LENPOS
] = 0x02; //LEN
300 c
.d
.asBytes
[0] = AUTHENTICATE
; //0x0A
301 c
.d
.asBytes
[1] = 0x00; // KEY 0
303 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
304 isOK
= resp
.d
.asBytes
[2] & 0xff;
305 PrintAndLog(" [0x0A] Authenticate : %s", ( isOK
==0xAE ) ? "NO":"YES");
307 c
.d
.asBytes
[0] = AUTHENTICATE_ISO
; //0x1A
309 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
310 isOK
= resp
.d
.asBytes
[2] & 0xff;
311 PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK
==0xAE ) ? "NO":"YES");
313 c
.d
.asBytes
[0] = AUTHENTICATE_AES
; //0xAA
315 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
316 isOK
= resp
.d
.asBytes
[2] & 0xff;
317 PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK
==0xAE ) ? "NO":"YES");
319 PrintAndLog(" ----------------------------------------------------------");
322 PrintAndLog(" AMK - Application Master Key settings");
325 c
.arg
[0] = (INIT
| CLEARTRACE
);
326 c
.arg
[LENPOS
] = 0x04;
327 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
328 memcpy(c
.d
.asBytes
+1, aid
, 3);
331 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
332 PrintAndLog(" Timed-out");
335 isOK
= resp
.arg
[0] & 0xff;
337 PrintAndLog(" Can't select AID: %s",sprint_hex(aid
,3));
344 c
.arg
[LENPOS
] = 0x01;
345 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
347 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
350 isOK
= resp
.arg
[0] & 0xff;
352 PrintAndLog(" Can't read Application Master key settings");
355 uint8_t rights
= (resp
.d
.asBytes
[3] >> 4 & 0xff);
358 str
= "AMK authentication is necessary to change any key (default)";
361 str
= "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
364 str
= "All keys (except AMK,see Bit0) within this application are frozen";
367 str
= "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed.";
370 PrintAndLog("Changekey Access rights");
371 PrintAndLog("-- %s",str
);
374 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
375 PrintAndLog(" 0x08 Configuration changeable : %s", str
);
376 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
377 PrintAndLog(" 0x04 AMK required for create/delete : %s",str
);
378 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
379 PrintAndLog(" 0x02 Directory list access with AMK : %s",str
);
380 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
381 PrintAndLog(" 0x01 AMK is changeable : %s", str
);
386 c
.arg
[LENPOS
] = 0x02;
387 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
388 c
.d
.asBytes
[1] = 0x00;
390 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
391 PrintAndLog(" Timed-out");
397 isOK
= resp
.arg
[0] & 0xff;
399 PrintAndLog(" Can't read Application Master key version. Trying all keys");
400 numOfKeys
= MAX_NUM_KEYS
;
403 numOfKeys
= resp
.d
.asBytes
[4];
405 PrintAndLog(" Max number of keys : %d", numOfKeys
);
406 PrintAndLog(" Application Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
407 PrintAndLog("-------------------------------------------------------------");
410 // LOOP over numOfKeys that we got before.
411 // From 0x01 to numOfKeys. We already got 0x00. (AMK)
412 for(int i
=0x01; i
<=0x0f; ++i
){
420 int CmdHF14ADesEnumApplications(const char *Cmd
){
424 uint32_t options
= (INIT
| DISCONNECT
);
426 UsbCommand c
= {CMD_MIFARE_DESFIRE
, {options
, 0x01 }};
427 c
.d
.asBytes
[0] = GET_APPLICATION_IDS
; //0x6a
432 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
435 isOK
= resp
.arg
[0] & 0xff;
437 PrintAndLog("Command unsuccessful");
441 PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
442 PrintAndLog("-------------------------------------------------------------");
445 UsbCommand respFiles
;
448 int max
= resp
.arg
[1] -3 -2;
450 for(int i
=3; i
<=max
; i
+=3){
451 PrintAndLog(" Aid %d : %02X %02X %02X ",num
,resp
.d
.asBytes
[i
],resp
.d
.asBytes
[i
+1],resp
.d
.asBytes
[i
+2]);
454 aid
[0] = resp
.d
.asBytes
[i
];
455 aid
[1] = resp
.d
.asBytes
[i
+1];
456 aid
[2] = resp
.d
.asBytes
[i
+2];
459 // Select Application
460 c
.arg
[CMDPOS
] = INIT
;
461 c
.arg
[LENPOS
] = 0x04;
462 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
463 c
.d
.asBytes
[1] = resp
.d
.asBytes
[i
];
464 c
.d
.asBytes
[2] = resp
.d
.asBytes
[i
+1];
465 c
.d
.asBytes
[3] = resp
.d
.asBytes
[i
+2];
468 if (!WaitForResponseTimeout(CMD_ACK
,&respAid
,1500) ) {
469 PrintAndLog(" Timed-out");
472 isOK
= respAid
.d
.asBytes
[2] & 0xff;
474 PrintAndLog(" Can't select AID: %s",sprint_hex(resp
.d
.asBytes
+i
,3));
479 c
.arg
[CMDPOS
] = NONE
;
480 c
.arg
[LENPOS
] = 0x01;
481 c
.d
.asBytes
[0] = GET_FILE_IDS
; // 0x6f
484 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
485 PrintAndLog(" Timed-out");
488 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
490 PrintAndLog(" Can't get file ids ");
492 int respfileLen
= resp
.arg
[1]-3-2;
493 for (int j
=0; j
< respfileLen
; ++j
){
494 PrintAndLog(" Fileid %d :", resp
.d
.asBytes
[j
+3]);
500 c
.arg
[CMDPOS
] = DISCONNECT
;
501 c
.arg
[LENPOS
] = 0x01;
502 c
.d
.asBytes
[0] = GET_ISOFILE_IDS
; // 0x61
505 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
506 PrintAndLog(" Timed-out");
509 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
511 PrintAndLog(" Can't get ISO file ids ");
513 int respfileLen
= resp
.arg
[1]-3-2;
514 for (int j
=0; j
< respfileLen
; ++j
){
515 PrintAndLog(" ISO Fileid %d :", resp
.d
.asBytes
[j
+3]);
522 PrintAndLog("-------------------------------------------------------------");
528 // MIAFRE DesFire Authentication
531 int CmdHF14ADesAuth(const char *Cmd
){
534 // ------------------------
540 uint8_t keylength
= 8;
541 unsigned char key
[24];
544 PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
545 PrintAndLog(" Auth modes");
546 PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
547 PrintAndLog(" Crypto");
548 PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
550 PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
551 PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
554 uint8_t cmdAuthMode
= param_get8(Cmd
,0);
555 uint8_t cmdAuthAlgo
= param_get8(Cmd
,1);
556 uint8_t cmdKeyNo
= param_get8(Cmd
,2);
561 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2) {
562 PrintAndLog("Crypto algo not valid for the auth mode");
567 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2 && cmdAuthAlgo
!= 3) {
568 PrintAndLog("Crypto algo not valid for the auth mode");
573 if ( cmdAuthAlgo
!= 4) {
574 PrintAndLog("Crypto algo not valid for the auth mode");
579 PrintAndLog("Wrong Auth mode");
584 switch (cmdAuthAlgo
){
587 PrintAndLog("3DES selected");
591 PrintAndLog("3 key 3DES selected");
595 PrintAndLog("AES selected");
600 PrintAndLog("DES selected");
605 if (param_gethex(Cmd
, 3, key
, keylength
*2)) {
606 PrintAndLog("Key must include %d HEX symbols", keylength
);
609 // algo, nyckellängd,
610 UsbCommand c
= {CMD_MIFARE_DESFIRE_AUTH1
, { cmdAuthMode
, cmdAuthAlgo
, cmdKeyNo
}};
612 c
.d
.asBytes
[0] = keylength
;
613 memcpy(c
.d
.asBytes
+1, key
, keylength
);
614 clearCommandBuffer();
618 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) {
619 PrintAndLog("Client command execute timeout");
623 uint8_t isOK
= resp
.arg
[0] & 0xff;
625 uint8_t * data
= resp
.d
.asBytes
;
627 PrintAndLog(" Key :%s",sprint_hex(key
, keylength
));
628 PrintAndLog(" SESSION :%s",sprint_hex(data
, keylength
));
629 PrintAndLog("-------------------------------------------------------------");
630 //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
632 PrintAndLog("Client command failed.");
634 PrintAndLog("-------------------------------------------------------------");
639 static command_t CommandTable
[] = {
640 {"help", CmdHelp
, 1, "This help"},
641 {"info", CmdHF14ADesInfo
, 0, "Get MIFARE DesFire information"},
642 {"enum", CmdHF14ADesEnumApplications
,0, "Tries enumerate all applications"},
643 {"auth", CmdHF14ADesAuth
, 0, "Tries a MIFARE DesFire Authentication"},
644 {"rdbl", CmdHF14ADesRb
, 0, "Read MIFARE DesFire block"},
645 {"wrbl", CmdHF14ADesWb
, 0, "write MIFARE DesFire block"},
646 {NULL
, NULL
, 0, NULL
}
649 int CmdHFMFDes(const char *Cmd
) {
651 clearCommandBuffer();
652 //WaitForResponseTimeout(CMD_ACK,NULL,100);
653 CmdsParse(CommandTable
, Cmd
);
657 int CmdHelp(const char *Cmd
) {
658 CmdsHelp(CommandTable
);