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"
31 uint8_t key_zero_data
[16] = { 0x00 };
32 uint8_t key_ones_data
[16] = { 0x01 };
33 uint8_t key_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
34 uint8_t key_picc_data
[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
36 static int CmdHelp(const char *Cmd
);
37 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
);
38 static int32_t le24toh (uint8_t data
[3]);
41 int CmdHF14ADesWb(const char *Cmd
)
43 /* uint8_t blockNo = 0;
45 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
46 uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
51 PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
52 PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
56 blockNo = param_get8(Cmd, 0);
57 cmdp = param_getchar(Cmd, 1);
59 PrintAndLog("Key type must be A or B");
62 if (cmdp != 'A' && cmdp != 'a') keyType = 1;
63 if (param_gethex(Cmd, 2, key, 12)) {
64 PrintAndLog("Key must include 12 HEX symbols");
67 if (param_gethex(Cmd, 3, bldata, 32)) {
68 PrintAndLog("Block data must include 32 HEX symbols");
71 PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
72 PrintAndLog("--data: %s", sprint_hex(bldata, 16));
74 UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
75 memcpy(c.d.asBytes, key, 6);
76 memcpy(c.d.asBytes + 10, bldata, 16);
80 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
81 uint8_t isOK = resp.arg[0] & 0xff;
82 PrintAndLog("isOk:%02x", isOK);
84 PrintAndLog("Command execute timeout");
90 int CmdHF14ADesRb(const char *Cmd
)
92 // uint8_t blockNo = 0;
93 // uint8_t keyType = 0;
94 // uint8_t key[6] = {0, 0, 0, 0, 0, 0};
99 // if (strlen(Cmd)<3) {
100 // PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
101 // PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
105 // blockNo = param_get8(Cmd, 0);
106 // cmdp = param_getchar(Cmd, 1);
107 // if (cmdp == 0x00) {
108 // PrintAndLog("Key type must be A or B");
111 // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
112 // if (param_gethex(Cmd, 2, key, 12)) {
113 // PrintAndLog("Key must include 12 HEX symbols");
116 // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
118 // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
119 // memcpy(c.d.asBytes, key, 6);
123 // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
124 // uint8_t isOK = resp.arg[0] & 0xff;
125 // uint8_t * data = resp.d.asBytes;
128 // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
130 // PrintAndLog("isOk:%02x", isOK);
132 // PrintAndLog("Command execute timeout");
138 int CmdHF14ADesInfo(const char *Cmd
){
140 UsbCommand c
= {CMD_MIFARE_DESFIRE_INFO
};
144 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
145 PrintAndLog("Command execute timeout");
148 uint8_t isOK
= resp
.arg
[0] & 0xff;
150 PrintAndLog("Command unsuccessful");
154 PrintAndLog("-- Desfire Information --------------------------------------");
155 PrintAndLog("-------------------------------------------------------------");
156 PrintAndLog(" UID : %s",sprint_hex(resp
.d
.asBytes
, 7));
157 PrintAndLog(" Batch number : %s",sprint_hex(resp
.d
.asBytes
+28,5));
158 PrintAndLog(" Production date : week %02x, 20%02x",resp
.d
.asBytes
[33], resp
.d
.asBytes
[34]);
159 PrintAndLog(" -----------------------------------------------------------");
160 PrintAndLog(" Hardware Information");
161 PrintAndLog(" Vendor Id : %s", GetVendorStr(resp
.d
.asBytes
[7]));
162 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[8]);
163 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[9]);
164 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[10], resp
.d
.asBytes
[11]);
165 PrintAndLog(" Storage size : %s",GetCardSizeStr(resp
.d
.asBytes
[12]));
166 PrintAndLog(" Protocol : %s",GetProtocolStr(resp
.d
.asBytes
[13]));
167 PrintAndLog(" -----------------------------------------------------------");
168 PrintAndLog(" Software Information");
169 PrintAndLog(" Vendor Id : %s",GetVendorStr(resp
.d
.asBytes
[14]));
170 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[15]);
171 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[16]);
172 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[17], resp
.d
.asBytes
[18]);
173 PrintAndLog(" storage size : %s", GetCardSizeStr(resp
.d
.asBytes
[19]));
174 PrintAndLog(" Protocol : %s", GetProtocolStr(resp
.d
.asBytes
[20]));
175 PrintAndLog("-------------------------------------------------------------");
177 // Master Key settings
178 GetKeySettings(NULL
);
180 // Free memory on card
181 c
.cmd
= CMD_MIFARE_DESFIRE
;
182 c
.arg
[0] = (INIT
| DISCONNECT
);
184 c
.d
.asBytes
[0] = GET_FREE_MEMORY
;
186 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
191 memcpy(tmp
, resp
.d
.asBytes
+3,3);
193 PrintAndLog(" Available free memory on card : %d bytes", le24toh( tmp
));
194 PrintAndLog("-------------------------------------------------------------");
197 Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
198 Application Master Key (AMK) 0x00 AID != 00 00 00
199 Application keys (APK) 0x01-0x0D
200 Application free 0x0E
201 Application never 0x0F
214 char * GetVendorStr( uint8_t id
){
219 sprintf(retStr
, "0x%02X (NXP)",id
);
221 sprintf(retStr
,"0x%02X (Unknown)",id
);
226 The 7 MSBits (= n) code the storage size itself based on 2^n,
227 the LSBit is set to '0' if the size is exactly 2^n
228 and set to '1' if the storage size is between 2^n and 2^(n+1).
229 For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
231 char * GetCardSizeStr( uint8_t fsize
){
236 uint16_t usize
= 1 << ((fsize
>>1) + 1);
237 uint16_t lsize
= 1 << (fsize
>>1);
241 sprintf(retStr
, "0x%02X (%d - %d bytes)",fsize
, usize
, lsize
);
243 sprintf(retStr
, "0x%02X (%d bytes)", fsize
, lsize
);
247 char * GetProtocolStr(uint8_t id
){
253 sprintf(retStr
,"0x%02X (ISO 14443-3, 14443-4)", id
);
255 sprintf(retStr
,"0x%02X (Unknown)", id
);
259 void GetKeySettings( uint8_t *aid
){
261 char messStr
[512] = {0x00};
264 uint32_t options
= NONE
;
268 //memset(messStr, 0x00, 512);
270 c
.cmd
= CMD_MIFARE_DESFIRE
;
273 PrintAndLog(" CMK - PICC, Card Master Key settings ");
275 c
.arg
[CMDPOS
] = (INIT
| DISCONNECT
);
276 c
.arg
[LENPOS
] = 0x01;
277 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
279 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
280 isOK
= resp
.arg
[0] & 0xff;
282 PrintAndLog(" Can't select master application");
286 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
287 PrintAndLog(" [0x08] Configuration changeable : %s", str
);
288 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
289 PrintAndLog(" [0x04] CMK required for create/delete : %s",str
);
290 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
291 PrintAndLog(" [0x02] Directory list access with CMK : %s",str
);
292 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
293 PrintAndLog(" [0x01] CMK is changeable : %s", str
);
295 c
.arg
[LENPOS
] = 0x02; //LEN
296 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
297 c
.d
.asBytes
[1] = 0x00;
299 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {
302 isOK
= resp
.arg
[0] & 0xff;
304 PrintAndLog(" Can't read key-version");
308 PrintAndLog(" Max number of keys : %d", resp
.d
.asBytes
[4]);
309 PrintAndLog(" Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
310 PrintAndLog(" ----------------------------------------------------------");
312 c
.arg
[LENPOS
] = 0x02; //LEN
313 c
.d
.asBytes
[0] = AUTHENTICATE
; //0x0A
314 c
.d
.asBytes
[1] = 0x00; // KEY 0
316 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
317 isOK
= resp
.d
.asBytes
[2] & 0xff;
318 PrintAndLog(" [0x0A] Authenticate : %s", ( isOK
==0xAE ) ? "NO":"YES");
320 c
.d
.asBytes
[0] = AUTHENTICATE_ISO
; //0x1A
322 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
323 isOK
= resp
.d
.asBytes
[2] & 0xff;
324 PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK
==0xAE ) ? "NO":"YES");
326 c
.d
.asBytes
[0] = AUTHENTICATE_AES
; //0xAA
328 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
329 isOK
= resp
.d
.asBytes
[2] & 0xff;
330 PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK
==0xAE ) ? "NO":"YES");
332 PrintAndLog(" ----------------------------------------------------------");
335 PrintAndLog(" AMK - Application Master Key settings");
338 c
.arg
[0] = (INIT
| CLEARTRACE
);
339 c
.arg
[LENPOS
] = 0x04;
340 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
341 memcpy(c
.d
.asBytes
+1, aid
, 3);
344 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
345 PrintAndLog(" Timed-out");
348 isOK
= resp
.arg
[0] & 0xff;
350 PrintAndLog(" Can't select AID: %s",sprint_hex(aid
,3));
357 c
.arg
[LENPOS
] = 0x01;
358 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
360 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
363 isOK
= resp
.arg
[0] & 0xff;
365 PrintAndLog(" Can't read Application Master key settings");
368 uint8_t rights
= (resp
.d
.asBytes
[3] >> 4 && 0xff);
371 str
= "AMK authentication is necessary to change any key (default)";
374 str
= "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
377 str
= "All keys (except AMK,see Bit0) within this application are frozen";
380 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.";
383 PrintAndLog("Changekey Access rights");
384 PrintAndLog("-- %s",str
);
387 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
388 PrintAndLog(" 0x08 Configuration changeable : %s", str
);
389 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
390 PrintAndLog(" 0x04 AMK required for create/delete : %s",str
);
391 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
392 PrintAndLog(" 0x02 Directory list access with AMK : %s",str
);
393 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
394 PrintAndLog(" 0x01 AMK is changeable : %s", str
);
399 c
.arg
[LENPOS
] = 0x02;
400 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
401 c
.d
.asBytes
[1] = 0x00;
403 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
404 PrintAndLog(" Timed-out");
410 isOK
= resp
.arg
[0] & 0xff;
412 PrintAndLog(" Can't read Application Master key version. Trying all keys");
413 numOfKeys
= MAX_NUM_KEYS
;
416 numOfKeys
= resp
.d
.asBytes
[4];
418 PrintAndLog(" Max number of keys : %d", numOfKeys
);
419 PrintAndLog(" Application Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
420 PrintAndLog("-------------------------------------------------------------");
423 // LOOP over numOfKeys that we got before.
424 // From 0x01 to numOfKeys. We already got 0x00. (AMK)
425 for(int i
=0x01; i
<=0x0f; ++i
){
433 int CmdHF14ADesEnumApplications(const char *Cmd
){
437 uint32_t options
= (INIT
| DISCONNECT
);
439 UsbCommand c
= {CMD_MIFARE_DESFIRE
, {options
, 0x01 }};
440 c
.d
.asBytes
[0] = GET_APPLICATION_IDS
; //0x6a
445 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
448 isOK
= resp
.arg
[0] & 0xff;
450 PrintAndLog("Command unsuccessful");
454 PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
455 PrintAndLog("-------------------------------------------------------------");
458 UsbCommand respFiles
;
461 int max
= resp
.arg
[1] -3 -2;
463 for(int i
=3; i
<=max
; i
+=3){
464 PrintAndLog(" Aid %d : %02X %02X %02X ",num
,resp
.d
.asBytes
[i
],resp
.d
.asBytes
[i
+1],resp
.d
.asBytes
[i
+2]);
467 aid
[0] = resp
.d
.asBytes
[i
];
468 aid
[1] = resp
.d
.asBytes
[i
+1];
469 aid
[2] = resp
.d
.asBytes
[i
+2];
472 // Select Application
473 c
.arg
[CMDPOS
] = INIT
;
474 c
.arg
[LENPOS
] = 0x04;
475 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
476 c
.d
.asBytes
[1] = resp
.d
.asBytes
[i
];
477 c
.d
.asBytes
[2] = resp
.d
.asBytes
[i
+1];
478 c
.d
.asBytes
[3] = resp
.d
.asBytes
[i
+2];
481 if (!WaitForResponseTimeout(CMD_ACK
,&respAid
,1500) ) {
482 PrintAndLog(" Timed-out");
485 isOK
= respAid
.d
.asBytes
[2] & 0xff;
487 PrintAndLog(" Can't select AID: %s",sprint_hex(resp
.d
.asBytes
+i
,3));
492 c
.arg
[CMDPOS
] = NONE
;
493 c
.arg
[LENPOS
] = 0x01;
494 c
.d
.asBytes
[0] = GET_FILE_IDS
; // 0x6f
497 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
498 PrintAndLog(" Timed-out");
501 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
503 PrintAndLog(" Can't get file ids ");
505 int respfileLen
= resp
.arg
[1]-3-2;
506 for (int j
=0; j
< respfileLen
; ++j
){
507 PrintAndLog(" Fileid %d :", resp
.d
.asBytes
[j
+3]);
513 c
.arg
[CMDPOS
] = DISCONNECT
;
514 c
.arg
[LENPOS
] = 0x01;
515 c
.d
.asBytes
[0] = GET_ISOFILE_IDS
; // 0x61
518 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
519 PrintAndLog(" Timed-out");
522 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
524 PrintAndLog(" Can't get ISO file ids ");
526 int respfileLen
= resp
.arg
[1]-3-2;
527 for (int j
=0; j
< respfileLen
; ++j
){
528 PrintAndLog(" ISO Fileid %d :", resp
.d
.asBytes
[j
+3]);
535 PrintAndLog("-------------------------------------------------------------");
541 // MIAFRE DesFire Authentication
544 int CmdHF14ADesAuth(const char *Cmd
){
547 // ------------------------
553 uint8_t keylength
= 8;
554 unsigned char key
[24];
557 PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
558 PrintAndLog(" Auth modes");
559 PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
560 PrintAndLog(" Crypto");
561 PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
563 PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
564 PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
567 uint8_t cmdAuthMode
= param_get8(Cmd
,0);
568 uint8_t cmdAuthAlgo
= param_get8(Cmd
,1);
569 uint8_t cmdKeyNo
= param_get8(Cmd
,2);
574 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2) {
575 PrintAndLog("Crypto algo not valid for the auth mode");
580 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2 && cmdAuthAlgo
!= 3) {
581 PrintAndLog("Crypto algo not valid for the auth mode");
586 if ( cmdAuthAlgo
!= 4) {
587 PrintAndLog("Crypto algo not valid for the auth mode");
592 PrintAndLog("Wrong Auth mode");
597 switch (cmdAuthAlgo
){
600 PrintAndLog("3DES selected");
604 PrintAndLog("3 key 3DES selected");
608 PrintAndLog("AES selected");
613 PrintAndLog("DES selected");
618 if (param_gethex(Cmd
, 3, key
, keylength
*2)) {
619 PrintAndLog("Key must include %d HEX symbols", keylength
);
622 // algo, nyckellängd,
623 UsbCommand c
= {CMD_MIFARE_DESFIRE_AUTH1
, { cmdAuthMode
, cmdAuthAlgo
, cmdKeyNo
}};
625 c
.d
.asBytes
[0] = keylength
;
626 memcpy(c
.d
.asBytes
+1, key
, keylength
);
631 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) {
632 PrintAndLog("Client command execute timeout");
636 uint8_t isOK
= resp
.arg
[0] & 0xff;
638 uint8_t * data
= resp
.d
.asBytes
;
640 PrintAndLog(" Key :%s",sprint_hex(key
, keylength
));
641 PrintAndLog(" SESSION :%s",sprint_hex(data
, keylength
));
642 PrintAndLog("-------------------------------------------------------------");
643 //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
645 PrintAndLog("Client command failed.");
647 PrintAndLog("-------------------------------------------------------------");
652 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
) {
653 for( ; len
> 0; len
--,dst
++,src
++)
657 static int32_t le24toh (uint8_t data
[3]) {
658 return (data
[2] << 16) | (data
[1] << 8) | data
[0];
661 static command_t CommandTable
[] =
663 {"help", CmdHelp
, 1, "This help"},
664 {"auth", CmdHF14ADesAuth
, 0, "Tries a MIFARE DesFire Authentication"},
665 {"rb", CmdHF14ADesRb
, 0, "Read MIFARE DesFire block"},
666 {"wb", CmdHF14ADesWb
, 0, "write MIFARE DesFire block"},
667 {"info", CmdHF14ADesInfo
, 0, "Get MIFARE DesFire information"},
668 {"enum", CmdHF14ADesEnumApplications
,0, "Tries enumerate all applications"},
669 {NULL
, NULL
, 0, NULL
}
672 int CmdHFMFDes(const char *Cmd
)
675 WaitForResponseTimeout(CMD_ACK
,NULL
,100);
676 CmdsParse(CommandTable
, Cmd
);
680 int CmdHelp(const char *Cmd
)
682 CmdsHelp(CommandTable
);