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
);
40 int CmdHF14ADesWb(const char *Cmd
)
42 /* uint8_t blockNo = 0;
44 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
45 uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
50 PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
51 PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
55 blockNo = param_get8(Cmd, 0);
56 cmdp = param_getchar(Cmd, 1);
58 PrintAndLog("Key type must be A or B");
61 if (cmdp != 'A' && cmdp != 'a') keyType = 1;
62 if (param_gethex(Cmd, 2, key, 12)) {
63 PrintAndLog("Key must include 12 HEX symbols");
66 if (param_gethex(Cmd, 3, bldata, 32)) {
67 PrintAndLog("Block data must include 32 HEX symbols");
70 PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
71 PrintAndLog("--data: %s", sprint_hex(bldata, 16));
73 UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
74 memcpy(c.d.asBytes, key, 6);
75 memcpy(c.d.asBytes + 10, bldata, 16);
79 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
80 uint8_t isOK = resp.arg[0] & 0xff;
81 PrintAndLog("isOk:%02x", isOK);
83 PrintAndLog("Command execute timeout");
89 int CmdHF14ADesRb(const char *Cmd
)
91 // uint8_t blockNo = 0;
92 // uint8_t keyType = 0;
93 // uint8_t key[6] = {0, 0, 0, 0, 0, 0};
98 // if (strlen(Cmd)<3) {
99 // PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
100 // PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
104 // blockNo = param_get8(Cmd, 0);
105 // cmdp = param_getchar(Cmd, 1);
106 // if (cmdp == 0x00) {
107 // PrintAndLog("Key type must be A or B");
110 // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
111 // if (param_gethex(Cmd, 2, key, 12)) {
112 // PrintAndLog("Key must include 12 HEX symbols");
115 // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
117 // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
118 // memcpy(c.d.asBytes, key, 6);
122 // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
123 // uint8_t isOK = resp.arg[0] & 0xff;
124 // uint8_t * data = resp.d.asBytes;
127 // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
129 // PrintAndLog("isOk:%02x", isOK);
131 // PrintAndLog("Command execute timeout");
137 int CmdHF14ADesInfo(const char *Cmd
){
139 UsbCommand c
= {CMD_MIFARE_DESFIRE_INFO
};
143 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
144 PrintAndLog("Command execute timeout");
147 uint8_t isOK
= resp
.arg
[0] & 0xff;
149 PrintAndLog("Command unsuccessful");
153 PrintAndLog("-- Desfire Information --------------------------------------");
154 PrintAndLog("-------------------------------------------------------------");
155 PrintAndLog(" UID : %s",sprint_hex(resp
.d
.asBytes
, 7));
156 PrintAndLog(" Batch number : %s",sprint_hex(resp
.d
.asBytes
+28,5));
157 PrintAndLog(" Production date : week %02x, 20%02x",resp
.d
.asBytes
[33], resp
.d
.asBytes
[34]);
158 PrintAndLog(" -----------------------------------------------------------");
159 PrintAndLog(" Hardware Information");
160 PrintAndLog(" Vendor Id : %s", getTagInfo(resp
.d
.asBytes
[7]));
161 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[8]);
162 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[9]);
163 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[10], resp
.d
.asBytes
[11]);
164 PrintAndLog(" Storage size : %s",GetCardSizeStr(resp
.d
.asBytes
[12]));
165 PrintAndLog(" Protocol : %s",GetProtocolStr(resp
.d
.asBytes
[13]));
166 PrintAndLog(" -----------------------------------------------------------");
167 PrintAndLog(" Software Information");
168 PrintAndLog(" Vendor Id : %s", getTagInfo(resp
.d
.asBytes
[14]));
169 PrintAndLog(" Type : 0x%02X",resp
.d
.asBytes
[15]);
170 PrintAndLog(" Subtype : 0x%02X",resp
.d
.asBytes
[16]);
171 PrintAndLog(" Version : %d.%d",resp
.d
.asBytes
[17], resp
.d
.asBytes
[18]);
172 PrintAndLog(" storage size : %s", GetCardSizeStr(resp
.d
.asBytes
[19]));
173 PrintAndLog(" Protocol : %s", GetProtocolStr(resp
.d
.asBytes
[20]));
174 PrintAndLog("-------------------------------------------------------------");
176 // Master Key settings
177 GetKeySettings(NULL
);
179 // Free memory on card
180 c
.cmd
= CMD_MIFARE_DESFIRE
;
181 c
.arg
[0] = (INIT
| DISCONNECT
);
183 c
.d
.asBytes
[0] = GET_FREE_MEMORY
;
185 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
190 memcpy(tmp
, resp
.d
.asBytes
+3,3);
192 PrintAndLog(" Available free memory on card : %d bytes", le24toh( tmp
));
193 PrintAndLog("-------------------------------------------------------------");
196 Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
197 Application Master Key (AMK) 0x00 AID != 00 00 00
198 Application keys (APK) 0x01-0x0D
199 Application free 0x0E
200 Application never 0x0F
214 The 7 MSBits (= n) code the storage size itself based on 2^n,
215 the LSBit is set to '0' if the size is exactly 2^n
216 and set to '1' if the storage size is between 2^n and 2^(n+1).
217 For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
219 char * GetCardSizeStr( uint8_t fsize
){
224 uint16_t usize
= 1 << ((fsize
>>1) + 1);
225 uint16_t lsize
= 1 << (fsize
>>1);
229 sprintf(retStr
, "0x%02X (%d - %d bytes)",fsize
, usize
, lsize
);
231 sprintf(retStr
, "0x%02X (%d bytes)", fsize
, lsize
);
235 char * GetProtocolStr(uint8_t id
){
241 sprintf(retStr
,"0x%02X (ISO 14443-3, 14443-4)", id
);
243 sprintf(retStr
,"0x%02X (Unknown)", id
);
247 void GetKeySettings( uint8_t *aid
){
249 char messStr
[512] = {0x00};
252 uint32_t options
= NONE
;
256 //memset(messStr, 0x00, 512);
258 c
.cmd
= CMD_MIFARE_DESFIRE
;
261 PrintAndLog(" CMK - PICC, Card Master Key settings ");
263 c
.arg
[CMDPOS
] = (INIT
| DISCONNECT
);
264 c
.arg
[LENPOS
] = 0x01;
265 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
267 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
268 isOK
= resp
.arg
[0] & 0xff;
270 PrintAndLog(" Can't select master application");
274 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
275 PrintAndLog(" [0x08] Configuration changeable : %s", str
);
276 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
277 PrintAndLog(" [0x04] CMK required for create/delete : %s",str
);
278 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
279 PrintAndLog(" [0x02] Directory list access with CMK : %s",str
);
280 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
281 PrintAndLog(" [0x01] CMK is changeable : %s", str
);
283 c
.arg
[LENPOS
] = 0x02; //LEN
284 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
285 c
.d
.asBytes
[1] = 0x00;
287 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {
290 isOK
= resp
.arg
[0] & 0xff;
292 PrintAndLog(" Can't read key-version");
296 PrintAndLog(" Max number of keys : %d", resp
.d
.asBytes
[4]);
297 PrintAndLog(" Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
298 PrintAndLog(" ----------------------------------------------------------");
300 c
.arg
[LENPOS
] = 0x02; //LEN
301 c
.d
.asBytes
[0] = AUTHENTICATE
; //0x0A
302 c
.d
.asBytes
[1] = 0x00; // KEY 0
304 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
305 isOK
= resp
.d
.asBytes
[2] & 0xff;
306 PrintAndLog(" [0x0A] Authenticate : %s", ( isOK
==0xAE ) ? "NO":"YES");
308 c
.d
.asBytes
[0] = AUTHENTICATE_ISO
; //0x1A
310 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
311 isOK
= resp
.d
.asBytes
[2] & 0xff;
312 PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK
==0xAE ) ? "NO":"YES");
314 c
.d
.asBytes
[0] = AUTHENTICATE_AES
; //0xAA
316 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
317 isOK
= resp
.d
.asBytes
[2] & 0xff;
318 PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK
==0xAE ) ? "NO":"YES");
320 PrintAndLog(" ----------------------------------------------------------");
323 PrintAndLog(" AMK - Application Master Key settings");
326 c
.arg
[0] = (INIT
| CLEARTRACE
);
327 c
.arg
[LENPOS
] = 0x04;
328 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
329 memcpy(c
.d
.asBytes
+1, aid
, 3);
332 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
333 PrintAndLog(" Timed-out");
336 isOK
= resp
.arg
[0] & 0xff;
338 PrintAndLog(" Can't select AID: %s",sprint_hex(aid
,3));
345 c
.arg
[LENPOS
] = 0x01;
346 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
348 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
351 isOK
= resp
.arg
[0] & 0xff;
353 PrintAndLog(" Can't read Application Master key settings");
356 uint8_t rights
= (resp
.d
.asBytes
[3] >> 4 && 0xff);
359 str
= "AMK authentication is necessary to change any key (default)";
362 str
= "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
365 str
= "All keys (except AMK,see Bit0) within this application are frozen";
368 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.";
371 PrintAndLog("Changekey Access rights");
372 PrintAndLog("-- %s",str
);
375 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
376 PrintAndLog(" 0x08 Configuration changeable : %s", str
);
377 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
378 PrintAndLog(" 0x04 AMK required for create/delete : %s",str
);
379 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
380 PrintAndLog(" 0x02 Directory list access with AMK : %s",str
);
381 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
382 PrintAndLog(" 0x01 AMK is changeable : %s", str
);
387 c
.arg
[LENPOS
] = 0x02;
388 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
389 c
.d
.asBytes
[1] = 0x00;
391 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
392 PrintAndLog(" Timed-out");
398 isOK
= resp
.arg
[0] & 0xff;
400 PrintAndLog(" Can't read Application Master key version. Trying all keys");
401 numOfKeys
= MAX_NUM_KEYS
;
404 numOfKeys
= resp
.d
.asBytes
[4];
406 PrintAndLog(" Max number of keys : %d", numOfKeys
);
407 PrintAndLog(" Application Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
408 PrintAndLog("-------------------------------------------------------------");
411 // LOOP over numOfKeys that we got before.
412 // From 0x01 to numOfKeys. We already got 0x00. (AMK)
413 for(int i
=0x01; i
<=0x0f; ++i
){
421 int CmdHF14ADesEnumApplications(const char *Cmd
){
425 uint32_t options
= (INIT
| DISCONNECT
);
427 UsbCommand c
= {CMD_MIFARE_DESFIRE
, {options
, 0x01 }};
428 c
.d
.asBytes
[0] = GET_APPLICATION_IDS
; //0x6a
433 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
436 isOK
= resp
.arg
[0] & 0xff;
438 PrintAndLog("Command unsuccessful");
442 PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
443 PrintAndLog("-------------------------------------------------------------");
446 UsbCommand respFiles
;
449 int max
= resp
.arg
[1] -3 -2;
451 for(int i
=3; i
<=max
; i
+=3){
452 PrintAndLog(" Aid %d : %02X %02X %02X ",num
,resp
.d
.asBytes
[i
],resp
.d
.asBytes
[i
+1],resp
.d
.asBytes
[i
+2]);
455 aid
[0] = resp
.d
.asBytes
[i
];
456 aid
[1] = resp
.d
.asBytes
[i
+1];
457 aid
[2] = resp
.d
.asBytes
[i
+2];
460 // Select Application
461 c
.arg
[CMDPOS
] = INIT
;
462 c
.arg
[LENPOS
] = 0x04;
463 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
464 c
.d
.asBytes
[1] = resp
.d
.asBytes
[i
];
465 c
.d
.asBytes
[2] = resp
.d
.asBytes
[i
+1];
466 c
.d
.asBytes
[3] = resp
.d
.asBytes
[i
+2];
469 if (!WaitForResponseTimeout(CMD_ACK
,&respAid
,1500) ) {
470 PrintAndLog(" Timed-out");
473 isOK
= respAid
.d
.asBytes
[2] & 0xff;
475 PrintAndLog(" Can't select AID: %s",sprint_hex(resp
.d
.asBytes
+i
,3));
480 c
.arg
[CMDPOS
] = NONE
;
481 c
.arg
[LENPOS
] = 0x01;
482 c
.d
.asBytes
[0] = GET_FILE_IDS
; // 0x6f
485 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
486 PrintAndLog(" Timed-out");
489 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
491 PrintAndLog(" Can't get file ids ");
493 int respfileLen
= resp
.arg
[1]-3-2;
494 for (int j
=0; j
< respfileLen
; ++j
){
495 PrintAndLog(" Fileid %d :", resp
.d
.asBytes
[j
+3]);
501 c
.arg
[CMDPOS
] = DISCONNECT
;
502 c
.arg
[LENPOS
] = 0x01;
503 c
.d
.asBytes
[0] = GET_ISOFILE_IDS
; // 0x61
506 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
507 PrintAndLog(" Timed-out");
510 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
512 PrintAndLog(" Can't get ISO file ids ");
514 int respfileLen
= resp
.arg
[1]-3-2;
515 for (int j
=0; j
< respfileLen
; ++j
){
516 PrintAndLog(" ISO Fileid %d :", resp
.d
.asBytes
[j
+3]);
523 PrintAndLog("-------------------------------------------------------------");
529 // MIAFRE DesFire Authentication
532 int CmdHF14ADesAuth(const char *Cmd
){
535 // ------------------------
541 uint8_t keylength
= 8;
542 unsigned char key
[24];
545 PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
546 PrintAndLog(" Auth modes");
547 PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
548 PrintAndLog(" Crypto");
549 PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
551 PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
552 PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
555 uint8_t cmdAuthMode
= param_get8(Cmd
,0);
556 uint8_t cmdAuthAlgo
= param_get8(Cmd
,1);
557 uint8_t cmdKeyNo
= param_get8(Cmd
,2);
562 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2) {
563 PrintAndLog("Crypto algo not valid for the auth mode");
568 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2 && cmdAuthAlgo
!= 3) {
569 PrintAndLog("Crypto algo not valid for the auth mode");
574 if ( cmdAuthAlgo
!= 4) {
575 PrintAndLog("Crypto algo not valid for the auth mode");
580 PrintAndLog("Wrong Auth mode");
585 switch (cmdAuthAlgo
){
588 PrintAndLog("3DES selected");
592 PrintAndLog("3 key 3DES selected");
596 PrintAndLog("AES selected");
601 PrintAndLog("DES selected");
606 if (param_gethex(Cmd
, 3, key
, keylength
*2)) {
607 PrintAndLog("Key must include %d HEX symbols", keylength
);
610 // algo, nyckellängd,
611 UsbCommand c
= {CMD_MIFARE_DESFIRE_AUTH1
, { cmdAuthMode
, cmdAuthAlgo
, cmdKeyNo
}};
613 c
.d
.asBytes
[0] = keylength
;
614 memcpy(c
.d
.asBytes
+1, key
, keylength
);
619 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) {
620 PrintAndLog("Client command execute timeout");
624 uint8_t isOK
= resp
.arg
[0] & 0xff;
626 uint8_t * data
= resp
.d
.asBytes
;
628 PrintAndLog(" Key :%s",sprint_hex(key
, keylength
));
629 PrintAndLog(" SESSION :%s",sprint_hex(data
, keylength
));
630 PrintAndLog("-------------------------------------------------------------");
631 //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
633 PrintAndLog("Client command failed.");
635 PrintAndLog("-------------------------------------------------------------");
640 static command_t CommandTable
[] =
642 {"help", CmdHelp
, 1, "This help"},
643 {"info", CmdHF14ADesInfo
, 0, "Get MIFARE DesFire information"},
644 {"enum", CmdHF14ADesEnumApplications
,0, "Tries enumerate all applications"},
645 {"auth", CmdHF14ADesAuth
, 0, "Tries a MIFARE DesFire Authentication"},
646 {"rdbl", CmdHF14ADesRb
, 0, "Read MIFARE DesFire block"},
647 {"wrbl", CmdHF14ADesWb
, 0, "write MIFARE DesFire block"},
648 {NULL
, NULL
, 0, NULL
}
651 int CmdHFMFDes(const char *Cmd
)
654 WaitForResponseTimeout(CMD_ACK
,NULL
,100);
655 CmdsParse(CommandTable
, Cmd
);
659 int CmdHelp(const char *Cmd
)
661 CmdsHelp(CommandTable
);