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 : %s",GetVersionStr(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
){
220 static char buf
[30] = {0x00};
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
){
236 static char buf
[30] = {0x00};
240 sprintf(retStr
,"0x%02X (ISO 14443-3, 14443-4)", id
);
242 sprintf(retStr
,"0x%02X (Unknown)", id
);
246 char * GetVersionStr(uint8_t major
, uint8_t minor
){
248 static char buf
[30] = {0x00};
252 sprintf(retStr
,"%d.%d (Desfire MF3ICD40)", major
, minor
);
253 else if ( major
== 0x01 && minor
== 0x00)
254 sprintf(retStr
,"%d.%d (Desfire EV1)", major
, minor
);
255 else if ( major
== 0x12 && minor
== 0x00)
256 sprintf(retStr
,"%d.%d (Desfire EV2)", major
, minor
);
258 sprintf(retStr
,"%d.%d (Unknown)", major
, minor
);
262 void GetKeySettings( uint8_t *aid
){
264 char messStr
[512] = {0x00};
267 uint32_t options
= NONE
;
271 //memset(messStr, 0x00, 512);
273 c
.cmd
= CMD_MIFARE_DESFIRE
;
276 PrintAndLog(" CMK - PICC, Card Master Key settings ");
278 c
.arg
[CMDPOS
] = (INIT
| DISCONNECT
);
279 c
.arg
[LENPOS
] = 0x01;
280 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
282 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
283 isOK
= resp
.arg
[0] & 0xff;
285 PrintAndLog(" Can't select master application");
289 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
290 PrintAndLog(" [0x08] Configuration changeable : %s", str
);
291 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
292 PrintAndLog(" [0x04] CMK required for create/delete : %s",str
);
293 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
294 PrintAndLog(" [0x02] Directory list access with CMK : %s",str
);
295 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
296 PrintAndLog(" [0x01] CMK is changeable : %s", str
);
298 c
.arg
[LENPOS
] = 0x02; //LEN
299 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
300 c
.d
.asBytes
[1] = 0x00;
302 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {
305 isOK
= resp
.arg
[0] & 0xff;
307 PrintAndLog(" Can't read key-version");
311 PrintAndLog(" Max number of keys : %d", resp
.d
.asBytes
[4]);
312 PrintAndLog(" Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
313 PrintAndLog(" ----------------------------------------------------------");
315 c
.arg
[LENPOS
] = 0x02; //LEN
316 c
.d
.asBytes
[0] = AUTHENTICATE
; //0x0A
317 c
.d
.asBytes
[1] = 0x00; // KEY 0
319 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
320 isOK
= resp
.d
.asBytes
[2] & 0xff;
321 PrintAndLog(" [0x0A] Authenticate : %s", ( isOK
==0xAE ) ? "NO":"YES");
323 c
.d
.asBytes
[0] = AUTHENTICATE_ISO
; //0x1A
325 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
326 isOK
= resp
.d
.asBytes
[2] & 0xff;
327 PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK
==0xAE ) ? "NO":"YES");
329 c
.d
.asBytes
[0] = AUTHENTICATE_AES
; //0xAA
331 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
332 isOK
= resp
.d
.asBytes
[2] & 0xff;
333 PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK
==0xAE ) ? "NO":"YES");
335 PrintAndLog(" ----------------------------------------------------------");
338 PrintAndLog(" AMK - Application Master Key settings");
341 c
.arg
[0] = (INIT
| CLEARTRACE
);
342 c
.arg
[LENPOS
] = 0x04;
343 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
344 memcpy(c
.d
.asBytes
+1, aid
, 3);
347 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
348 PrintAndLog(" Timed-out");
351 isOK
= resp
.arg
[0] & 0xff;
353 PrintAndLog(" Can't select AID: %s",sprint_hex(aid
,3));
360 c
.arg
[LENPOS
] = 0x01;
361 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
363 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
366 isOK
= resp
.arg
[0] & 0xff;
368 PrintAndLog(" Can't read Application Master key settings");
371 uint8_t rights
= (resp
.d
.asBytes
[3] >> 4 & 0xff);
374 str
= "AMK authentication is necessary to change any key (default)";
377 str
= "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
380 str
= "All keys (except AMK,see Bit0) within this application are frozen";
383 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.";
386 PrintAndLog("Changekey Access rights");
387 PrintAndLog("-- %s",str
);
390 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
391 PrintAndLog(" 0x08 Configuration changeable : %s", str
);
392 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
393 PrintAndLog(" 0x04 AMK required for create/delete : %s",str
);
394 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
395 PrintAndLog(" 0x02 Directory list access with AMK : %s",str
);
396 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
397 PrintAndLog(" 0x01 AMK is changeable : %s", str
);
402 c
.arg
[LENPOS
] = 0x02;
403 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
404 c
.d
.asBytes
[1] = 0x00;
406 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
407 PrintAndLog(" Timed-out");
413 isOK
= resp
.arg
[0] & 0xff;
415 PrintAndLog(" Can't read Application Master key version. Trying all keys");
416 numOfKeys
= MAX_NUM_KEYS
;
419 numOfKeys
= resp
.d
.asBytes
[4];
421 PrintAndLog(" Max number of keys : %d", numOfKeys
);
422 PrintAndLog(" Application Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
423 PrintAndLog("-------------------------------------------------------------");
426 // LOOP over numOfKeys that we got before.
427 // From 0x01 to numOfKeys. We already got 0x00. (AMK)
428 for(int i
=0x01; i
<=0x0f; ++i
){
436 int CmdHF14ADesEnumApplications(const char *Cmd
){
440 uint32_t options
= (INIT
| DISCONNECT
);
442 UsbCommand c
= {CMD_MIFARE_DESFIRE
, {options
, 0x01 }};
443 c
.d
.asBytes
[0] = GET_APPLICATION_IDS
; //0x6a
448 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
451 isOK
= resp
.arg
[0] & 0xff;
453 PrintAndLog("Command unsuccessful");
457 PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
458 PrintAndLog("-------------------------------------------------------------");
461 UsbCommand respFiles
;
464 int max
= resp
.arg
[1] -3 -2;
466 for(int i
=3; i
<=max
; i
+=3){
467 PrintAndLog(" Aid %d : %02X %02X %02X ",num
,resp
.d
.asBytes
[i
],resp
.d
.asBytes
[i
+1],resp
.d
.asBytes
[i
+2]);
470 aid
[0] = resp
.d
.asBytes
[i
];
471 aid
[1] = resp
.d
.asBytes
[i
+1];
472 aid
[2] = resp
.d
.asBytes
[i
+2];
475 // Select Application
476 c
.arg
[CMDPOS
] = INIT
;
477 c
.arg
[LENPOS
] = 0x04;
478 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
479 c
.d
.asBytes
[1] = resp
.d
.asBytes
[i
];
480 c
.d
.asBytes
[2] = resp
.d
.asBytes
[i
+1];
481 c
.d
.asBytes
[3] = resp
.d
.asBytes
[i
+2];
484 if (!WaitForResponseTimeout(CMD_ACK
,&respAid
,1500) ) {
485 PrintAndLog(" Timed-out");
488 isOK
= respAid
.d
.asBytes
[2] & 0xff;
490 PrintAndLog(" Can't select AID: %s",sprint_hex(resp
.d
.asBytes
+i
,3));
495 c
.arg
[CMDPOS
] = NONE
;
496 c
.arg
[LENPOS
] = 0x01;
497 c
.d
.asBytes
[0] = GET_FILE_IDS
; // 0x6f
500 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
501 PrintAndLog(" Timed-out");
504 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
506 PrintAndLog(" Can't get file ids ");
508 int respfileLen
= resp
.arg
[1]-3-2;
509 for (int j
=0; j
< respfileLen
; ++j
){
510 PrintAndLog(" Fileid %d :", resp
.d
.asBytes
[j
+3]);
516 c
.arg
[CMDPOS
] = DISCONNECT
;
517 c
.arg
[LENPOS
] = 0x01;
518 c
.d
.asBytes
[0] = GET_ISOFILE_IDS
; // 0x61
521 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
522 PrintAndLog(" Timed-out");
525 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
527 PrintAndLog(" Can't get ISO file ids ");
529 int respfileLen
= resp
.arg
[1]-3-2;
530 for (int j
=0; j
< respfileLen
; ++j
){
531 PrintAndLog(" ISO Fileid %d :", resp
.d
.asBytes
[j
+3]);
538 PrintAndLog("-------------------------------------------------------------");
544 // MIAFRE DesFire Authentication
547 int CmdHF14ADesAuth(const char *Cmd
){
550 // ------------------------
556 uint8_t keylength
= 8;
557 unsigned char key
[24];
560 PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
561 PrintAndLog(" Auth modes");
562 PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
563 PrintAndLog(" Crypto");
564 PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
566 PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
567 PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
570 uint8_t cmdAuthMode
= param_get8(Cmd
,0);
571 uint8_t cmdAuthAlgo
= param_get8(Cmd
,1);
572 uint8_t cmdKeyNo
= param_get8(Cmd
,2);
577 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2) {
578 PrintAndLog("Crypto algo not valid for the auth mode");
583 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2 && cmdAuthAlgo
!= 3) {
584 PrintAndLog("Crypto algo not valid for the auth mode");
589 if ( cmdAuthAlgo
!= 4) {
590 PrintAndLog("Crypto algo not valid for the auth mode");
595 PrintAndLog("Wrong Auth mode");
600 switch (cmdAuthAlgo
){
603 PrintAndLog("3DES selected");
607 PrintAndLog("3 key 3DES selected");
611 PrintAndLog("AES selected");
616 PrintAndLog("DES selected");
621 if (param_gethex(Cmd
, 3, key
, keylength
*2)) {
622 PrintAndLog("Key must include %d HEX symbols", keylength
);
625 // algo, nyckellängd,
626 UsbCommand c
= {CMD_MIFARE_DESFIRE_AUTH1
, { cmdAuthMode
, cmdAuthAlgo
, cmdKeyNo
}};
628 c
.d
.asBytes
[0] = keylength
;
629 memcpy(c
.d
.asBytes
+1, key
, keylength
);
630 clearCommandBuffer();
634 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) {
635 PrintAndLog("Client command execute timeout");
639 uint8_t isOK
= resp
.arg
[0] & 0xff;
641 uint8_t * data
= resp
.d
.asBytes
;
643 PrintAndLog(" Key :%s",sprint_hex(key
, keylength
));
644 PrintAndLog(" SESSION :%s",sprint_hex(data
, keylength
));
645 PrintAndLog("-------------------------------------------------------------");
646 //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
648 PrintAndLog("Client command failed.");
650 PrintAndLog("-------------------------------------------------------------");
655 static command_t CommandTable
[] = {
656 {"help", CmdHelp
, 1, "This help"},
657 {"info", CmdHF14ADesInfo
, 0, "Get MIFARE DesFire information"},
658 {"enum", CmdHF14ADesEnumApplications
,0, "Tries enumerate all applications"},
659 {"auth", CmdHF14ADesAuth
, 0, "Tries a MIFARE DesFire Authentication"},
660 {"rdbl", CmdHF14ADesRb
, 0, "Read MIFARE DesFire block"},
661 {"wrbl", CmdHF14ADesWb
, 0, "write MIFARE DesFire block"},
662 {NULL
, NULL
, 0, NULL
}
665 int CmdHFMFDes(const char *Cmd
) {
667 clearCommandBuffer();
668 CmdsParse(CommandTable
, Cmd
);
672 int CmdHelp(const char *Cmd
) {
673 CmdsHelp(CommandTable
);