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 <openssl/des.h>
16 #include "loclass/des.h"
18 #include "proxmark3.h"
19 #include "../include/common.h"
20 #include "../include/mifare.h"
21 #include "../common/iso14443crc.h"
24 #include "cmdparser.h"
26 #include "cmdhfmfdes.h"
33 uint8_t key_zero_data
[16] = { 0x00 };
34 uint8_t key_ones_data
[16] = { 0x01 };
35 uint8_t key_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
36 uint8_t key_picc_data
[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
38 static int CmdHelp(const char *Cmd
);
39 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
);
40 static int32_t le24toh (uint8_t data
[3]);
43 int CmdHF14ADesWb(const char *Cmd
)
45 /* uint8_t blockNo = 0;
47 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
48 uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
53 PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
54 PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
58 blockNo = param_get8(Cmd, 0);
59 cmdp = param_getchar(Cmd, 1);
61 PrintAndLog("Key type must be A or B");
64 if (cmdp != 'A' && cmdp != 'a') keyType = 1;
65 if (param_gethex(Cmd, 2, key, 12)) {
66 PrintAndLog("Key must include 12 HEX symbols");
69 if (param_gethex(Cmd, 3, bldata, 32)) {
70 PrintAndLog("Block data must include 32 HEX symbols");
73 PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
74 PrintAndLog("--data: %s", sprint_hex(bldata, 16));
76 UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
77 memcpy(c.d.asBytes, key, 6);
78 memcpy(c.d.asBytes + 10, bldata, 16);
82 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
83 uint8_t isOK = resp.arg[0] & 0xff;
84 PrintAndLog("isOk:%02x", isOK);
86 PrintAndLog("Command execute timeout");
92 int CmdHF14ADesRb(const char *Cmd
)
94 // uint8_t blockNo = 0;
95 // uint8_t keyType = 0;
96 // uint8_t key[6] = {0, 0, 0, 0, 0, 0};
101 // if (strlen(Cmd)<3) {
102 // PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
103 // PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
107 // blockNo = param_get8(Cmd, 0);
108 // cmdp = param_getchar(Cmd, 1);
109 // if (cmdp == 0x00) {
110 // PrintAndLog("Key type must be A or B");
113 // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
114 // if (param_gethex(Cmd, 2, key, 12)) {
115 // PrintAndLog("Key must include 12 HEX symbols");
118 // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
120 // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
121 // memcpy(c.d.asBytes, key, 6);
125 // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
126 // uint8_t isOK = resp.arg[0] & 0xff;
127 // uint8_t * data = resp.d.asBytes;
130 // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
132 // PrintAndLog("isOk:%02x", isOK);
134 // PrintAndLog("Command execute timeout");
140 int CmdHF14ADesInfo(const char *Cmd
){
142 UsbCommand c
= {CMD_MIFARE_DESFIRE_INFO
};
146 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
147 PrintAndLog("Command execute timeout");
150 uint8_t isOK
= resp
.arg
[0] & 0xff;
152 PrintAndLog("Command unsuccessful");
156 PrintAndLog("-- Desfire Information --------------------------------------");
157 PrintAndLog("-------------------------------------------------------------");
158 PrintAndLog(" UID : %s",sprint_hex(resp
.d
.asBytes
, 7));
159 PrintAndLog(" Batch number : %s",sprint_hex(resp
.d
.asBytes
+28,5));
160 PrintAndLog(" Production date : week %02x, 20%02x",resp
.d
.asBytes
[33], resp
.d
.asBytes
[34]);
161 PrintAndLog(" -----------------------------------------------------------");
162 PrintAndLog(" Hardware Information");
163 PrintAndLog(" Vendor Id : %s", getTagInfo(resp
.d
.asBytes
[7]));
164 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[8]);
165 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[9]);
166 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[10], resp
.d
.asBytes
[11]);
167 PrintAndLog(" Storage size : %s",GetCardSizeStr(resp
.d
.asBytes
[12]));
168 PrintAndLog(" Protocol : %s",GetProtocolStr(resp
.d
.asBytes
[13]));
169 PrintAndLog(" -----------------------------------------------------------");
170 PrintAndLog(" Software Information");
171 PrintAndLog(" Vendor Id : %s", getTagInfo(resp
.d
.asBytes
[14]));
172 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[15]);
173 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[16]);
174 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[17], resp
.d
.asBytes
[18]);
175 PrintAndLog(" storage size : %s", GetCardSizeStr(resp
.d
.asBytes
[19]));
176 PrintAndLog(" Protocol : %s", GetProtocolStr(resp
.d
.asBytes
[20]));
177 PrintAndLog("-------------------------------------------------------------");
179 // Master Key settings
180 GetKeySettings(NULL
);
182 // Free memory on card
183 c
.cmd
= CMD_MIFARE_DESFIRE
;
184 c
.arg
[0] = (INIT
| DISCONNECT
);
186 c
.d
.asBytes
[0] = GET_FREE_MEMORY
;
188 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
193 memcpy(tmp
, resp
.d
.asBytes
+3,3);
195 PrintAndLog(" Available free memory on card : %d bytes", le24toh( tmp
));
196 PrintAndLog("-------------------------------------------------------------");
199 Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
200 Application Master Key (AMK) 0x00 AID != 00 00 00
201 Application keys (APK) 0x01-0x0D
202 Application free 0x0E
203 Application never 0x0F
217 The 7 MSBits (= n) code the storage size itself based on 2^n,
218 the LSBit is set to '0' if the size is exactly 2^n
219 and set to '1' if the storage size is between 2^n and 2^(n+1).
220 For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
222 char * GetCardSizeStr( uint8_t fsize
){
227 uint16_t usize
= 1 << ((fsize
>>1) + 1);
228 uint16_t lsize
= 1 << (fsize
>>1);
232 sprintf(retStr
, "0x%02X (%d - %d bytes)",fsize
, usize
, lsize
);
234 sprintf(retStr
, "0x%02X (%d bytes)", fsize
, lsize
);
238 char * GetProtocolStr(uint8_t id
){
244 sprintf(retStr
,"0x%02X (ISO 14443-3, 14443-4)", id
);
246 sprintf(retStr
,"0x%02X (Unknown)", id
);
250 void GetKeySettings( uint8_t *aid
){
252 char messStr
[512] = {0x00};
255 uint32_t options
= NONE
;
259 //memset(messStr, 0x00, 512);
261 c
.cmd
= CMD_MIFARE_DESFIRE
;
264 PrintAndLog(" CMK - PICC, Card Master Key settings ");
266 c
.arg
[CMDPOS
] = (INIT
| DISCONNECT
);
267 c
.arg
[LENPOS
] = 0x01;
268 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
270 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
271 isOK
= resp
.arg
[0] & 0xff;
273 PrintAndLog(" Can't select master application");
277 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
278 PrintAndLog(" [0x08] Configuration changeable : %s", str
);
279 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
280 PrintAndLog(" [0x04] CMK required for create/delete : %s",str
);
281 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
282 PrintAndLog(" [0x02] Directory list access with CMK : %s",str
);
283 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
284 PrintAndLog(" [0x01] CMK is changeable : %s", str
);
286 c
.arg
[LENPOS
] = 0x02; //LEN
287 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
288 c
.d
.asBytes
[1] = 0x00;
290 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {
293 isOK
= resp
.arg
[0] & 0xff;
295 PrintAndLog(" Can't read key-version");
299 PrintAndLog(" Max number of keys : %d", resp
.d
.asBytes
[4]);
300 PrintAndLog(" Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
301 PrintAndLog(" ----------------------------------------------------------");
303 c
.arg
[LENPOS
] = 0x02; //LEN
304 c
.d
.asBytes
[0] = AUTHENTICATE
; //0x0A
305 c
.d
.asBytes
[1] = 0x00; // KEY 0
307 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
308 isOK
= resp
.d
.asBytes
[2] & 0xff;
309 PrintAndLog(" [0x0A] Authenticate : %s", ( isOK
==0xAE ) ? "NO":"YES");
311 c
.d
.asBytes
[0] = AUTHENTICATE_ISO
; //0x1A
313 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
314 isOK
= resp
.d
.asBytes
[2] & 0xff;
315 PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK
==0xAE ) ? "NO":"YES");
317 c
.d
.asBytes
[0] = AUTHENTICATE_AES
; //0xAA
319 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
320 isOK
= resp
.d
.asBytes
[2] & 0xff;
321 PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK
==0xAE ) ? "NO":"YES");
323 PrintAndLog(" ----------------------------------------------------------");
326 PrintAndLog(" AMK - Application Master Key settings");
329 c
.arg
[0] = (INIT
| CLEARTRACE
);
330 c
.arg
[LENPOS
] = 0x04;
331 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
332 memcpy(c
.d
.asBytes
+1, aid
, 3);
335 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
336 PrintAndLog(" Timed-out");
339 isOK
= resp
.arg
[0] & 0xff;
341 PrintAndLog(" Can't select AID: %s",sprint_hex(aid
,3));
348 c
.arg
[LENPOS
] = 0x01;
349 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
351 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
354 isOK
= resp
.arg
[0] & 0xff;
356 PrintAndLog(" Can't read Application Master key settings");
359 uint8_t rights
= (resp
.d
.asBytes
[3] >> 4 && 0xff);
362 str
= "AMK authentication is necessary to change any key (default)";
365 str
= "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
368 str
= "All keys (except AMK,see Bit0) within this application are frozen";
371 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.";
374 PrintAndLog("Changekey Access rights");
375 PrintAndLog("-- %s",str
);
378 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
379 PrintAndLog(" 0x08 Configuration changeable : %s", str
);
380 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
381 PrintAndLog(" 0x04 AMK required for create/delete : %s",str
);
382 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
383 PrintAndLog(" 0x02 Directory list access with AMK : %s",str
);
384 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
385 PrintAndLog(" 0x01 AMK is changeable : %s", str
);
390 c
.arg
[LENPOS
] = 0x02;
391 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
392 c
.d
.asBytes
[1] = 0x00;
394 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
395 PrintAndLog(" Timed-out");
401 isOK
= resp
.arg
[0] & 0xff;
403 PrintAndLog(" Can't read Application Master key version. Trying all keys");
404 numOfKeys
= MAX_NUM_KEYS
;
407 numOfKeys
= resp
.d
.asBytes
[4];
409 PrintAndLog(" Max number of keys : %d", numOfKeys
);
410 PrintAndLog(" Application Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
411 PrintAndLog("-------------------------------------------------------------");
414 // LOOP over numOfKeys that we got before.
415 // From 0x01 to numOfKeys. We already got 0x00. (AMK)
416 for(int i
=0x01; i
<=0x0f; ++i
){
424 int CmdHF14ADesEnumApplications(const char *Cmd
){
428 uint32_t options
= (INIT
| DISCONNECT
);
430 UsbCommand c
= {CMD_MIFARE_DESFIRE
, {options
, 0x01 }};
431 c
.d
.asBytes
[0] = GET_APPLICATION_IDS
; //0x6a
436 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
439 isOK
= resp
.arg
[0] & 0xff;
441 PrintAndLog("Command unsuccessful");
445 PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
446 PrintAndLog("-------------------------------------------------------------");
449 UsbCommand respFiles
;
452 int max
= resp
.arg
[1] -3 -2;
454 for(int i
=3; i
<=max
; i
+=3){
455 PrintAndLog(" Aid %d : %02X %02X %02X ",num
,resp
.d
.asBytes
[i
],resp
.d
.asBytes
[i
+1],resp
.d
.asBytes
[i
+2]);
458 aid
[0] = resp
.d
.asBytes
[i
];
459 aid
[1] = resp
.d
.asBytes
[i
+1];
460 aid
[2] = resp
.d
.asBytes
[i
+2];
463 // Select Application
464 c
.arg
[CMDPOS
] = INIT
;
465 c
.arg
[LENPOS
] = 0x04;
466 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
467 c
.d
.asBytes
[1] = resp
.d
.asBytes
[i
];
468 c
.d
.asBytes
[2] = resp
.d
.asBytes
[i
+1];
469 c
.d
.asBytes
[3] = resp
.d
.asBytes
[i
+2];
472 if (!WaitForResponseTimeout(CMD_ACK
,&respAid
,1500) ) {
473 PrintAndLog(" Timed-out");
476 isOK
= respAid
.d
.asBytes
[2] & 0xff;
478 PrintAndLog(" Can't select AID: %s",sprint_hex(resp
.d
.asBytes
+i
,3));
483 c
.arg
[CMDPOS
] = NONE
;
484 c
.arg
[LENPOS
] = 0x01;
485 c
.d
.asBytes
[0] = GET_FILE_IDS
; // 0x6f
488 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
489 PrintAndLog(" Timed-out");
492 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
494 PrintAndLog(" Can't get file ids ");
496 int respfileLen
= resp
.arg
[1]-3-2;
497 for (int j
=0; j
< respfileLen
; ++j
){
498 PrintAndLog(" Fileid %d :", resp
.d
.asBytes
[j
+3]);
504 c
.arg
[CMDPOS
] = DISCONNECT
;
505 c
.arg
[LENPOS
] = 0x01;
506 c
.d
.asBytes
[0] = GET_ISOFILE_IDS
; // 0x61
509 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
510 PrintAndLog(" Timed-out");
513 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
515 PrintAndLog(" Can't get ISO file ids ");
517 int respfileLen
= resp
.arg
[1]-3-2;
518 for (int j
=0; j
< respfileLen
; ++j
){
519 PrintAndLog(" ISO Fileid %d :", resp
.d
.asBytes
[j
+3]);
526 PrintAndLog("-------------------------------------------------------------");
532 // MIAFRE DesFire Authentication
535 int CmdHF14ADesAuth(const char *Cmd
){
538 // ------------------------
544 uint8_t keylength
= 8;
545 unsigned char key
[24];
548 PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
549 PrintAndLog(" Auth modes");
550 PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
551 PrintAndLog(" Crypto");
552 PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
554 PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
555 PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
558 uint8_t cmdAuthMode
= param_get8(Cmd
,0);
559 uint8_t cmdAuthAlgo
= param_get8(Cmd
,1);
560 uint8_t cmdKeyNo
= param_get8(Cmd
,2);
565 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2) {
566 PrintAndLog("Crypto algo not valid for the auth mode");
571 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2 && cmdAuthAlgo
!= 3) {
572 PrintAndLog("Crypto algo not valid for the auth mode");
577 if ( cmdAuthAlgo
!= 4) {
578 PrintAndLog("Crypto algo not valid for the auth mode");
583 PrintAndLog("Wrong Auth mode");
588 switch (cmdAuthAlgo
){
591 PrintAndLog("3DES selected");
595 PrintAndLog("3 key 3DES selected");
599 PrintAndLog("AES selected");
604 PrintAndLog("DES selected");
609 if (param_gethex(Cmd
, 3, key
, keylength
*2)) {
610 PrintAndLog("Key must include %d HEX symbols", keylength
);
613 // algo, nyckellängd,
614 UsbCommand c
= {CMD_MIFARE_DESFIRE_AUTH1
, { cmdAuthMode
, cmdAuthAlgo
, cmdKeyNo
}};
616 c
.d
.asBytes
[0] = keylength
;
617 memcpy(c
.d
.asBytes
+1, key
, keylength
);
622 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) {
623 PrintAndLog("Client command execute timeout");
627 uint8_t isOK
= resp
.arg
[0] & 0xff;
629 uint8_t * data
= resp
.d
.asBytes
;
631 PrintAndLog(" Key :%s",sprint_hex(key
, keylength
));
632 PrintAndLog(" SESSION :%s",sprint_hex(data
, keylength
));
633 PrintAndLog("-------------------------------------------------------------");
634 //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
636 PrintAndLog("Client command failed.");
638 PrintAndLog("-------------------------------------------------------------");
643 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
) {
644 for( ; len
> 0; len
--,dst
++,src
++)
648 static int32_t le24toh (uint8_t data
[3]) {
649 return (data
[2] << 16) | (data
[1] << 8) | data
[0];
652 static command_t CommandTable
[] =
654 {"help", CmdHelp
, 1, "This help"},
655 {"auth", CmdHF14ADesAuth
, 0, "Tries a MIFARE DesFire Authentication"},
656 {"rb", CmdHF14ADesRb
, 0, "Read MIFARE DesFire block"},
657 {"wb", CmdHF14ADesWb
, 0, "write MIFARE DesFire block"},
658 {"info", CmdHF14ADesInfo
, 0, "Get MIFARE DesFire information"},
659 {"enum", CmdHF14ADesEnumApplications
,0, "Tries enumerate all applications"},
660 {NULL
, NULL
, 0, NULL
}
663 int CmdHFMFDes(const char *Cmd
)
666 WaitForResponseTimeout(CMD_ACK
,NULL
,100);
667 CmdsParse(CommandTable
, Cmd
);
671 int CmdHelp(const char *Cmd
)
673 CmdsHelp(CommandTable
);