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>
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"
30 uint8_t key_zero_data
[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
31 uint8_t key_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
32 uint8_t key_ones_data
[16] = { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 };
33 uint8_t key_picc_data
[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
35 static int CmdHelp(const char *Cmd
);
36 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
);
37 static int32_t le24toh (uint8_t data
[3]);
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", GetVendorStr(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",GetVendorStr(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
213 char * GetVendorStr( uint8_t id
){
218 sprintf(retStr
, "0x%02X (NXP)",id
);
220 sprintf(retStr
,"0x%02X (Unknown)",id
);
225 The 7 MSBits (= n) code the storage size itself based on 2^n,
226 the LSBit is set to '0' if the size is exactly 2^n
227 and set to '1' if the storage size is between 2^n and 2^(n+1).
228 For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
230 char * GetCardSizeStr( uint8_t fsize
){
235 uint16_t usize
= 1 << ((fsize
>>1) + 1);
236 uint16_t lsize
= 1 << (fsize
>>1);
239 if ( fsize
& (1 << 0 ) )
240 sprintf(retStr
, "0x%02X (%d - %d bytes)",fsize
, usize
, lsize
);
242 sprintf(retStr
, "0x%02X (%d bytes)", fsize
, lsize
);
246 char * GetProtocolStr(uint8_t id
){
252 sprintf(retStr
,"0x%02X (ISO 14443-3, 14443-4)", id
);
254 sprintf(retStr
,"0x%02X", id
);
258 void GetKeySettings( uint8_t *aid
){
260 char messStr
[512] = {0x00};
263 uint32_t options
= NONE
;
267 //memset(messStr, 0x00, 512);
269 c
.cmd
= CMD_MIFARE_DESFIRE
;
272 PrintAndLog(" CMK - PICC, Card Master Key settings ");
274 c
.arg
[CMDPOS
] = (INIT
| DISCONNECT
);
275 c
.arg
[LENPOS
] = 0x01;
276 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
278 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
279 isOK
= resp
.arg
[0] & 0xff;
281 PrintAndLog(" Can't select master application");
285 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
286 PrintAndLog(" [0x08] Configuration changeable : %s", str
);
287 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
288 PrintAndLog(" [0x04] CMK required for create/delete : %s",str
);
289 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
290 PrintAndLog(" [0x02] Directory list access with CMK : %s",str
);
291 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
292 PrintAndLog(" [0x01] CMK is changeable : %s", str
);
294 c
.arg
[LENPOS
] = 0x02; //LEN
295 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
296 c
.d
.asBytes
[1] = 0x00;
298 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {
301 isOK
= resp
.arg
[0] & 0xff;
303 PrintAndLog(" Can't read key-version");
307 PrintAndLog(" Max number of keys : %d", resp
.d
.asBytes
[4]);
308 PrintAndLog(" Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
309 PrintAndLog(" ----------------------------------------------------------");
311 c
.arg
[LENPOS
] = 0x02; //LEN
312 c
.d
.asBytes
[0] = AUTHENTICATE
; //0x0A
313 c
.d
.asBytes
[1] = 0x00; // KEY 0
315 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
316 isOK
= resp
.d
.asBytes
[2] & 0xff;
317 PrintAndLog(" [0x0A] Authenticate : %s", ( isOK
==0xAE ) ? "NO":"YES");
319 c
.d
.asBytes
[0] = AUTHENTICATE_ISO
; //0x1A
321 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
322 isOK
= resp
.d
.asBytes
[2] & 0xff;
323 PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK
==0xAE ) ? "NO":"YES");
325 c
.d
.asBytes
[0] = AUTHENTICATE_AES
; //0xAA
327 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}
328 isOK
= resp
.d
.asBytes
[2] & 0xff;
329 PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK
==0xAE ) ? "NO":"YES");
331 PrintAndLog(" ----------------------------------------------------------");
334 PrintAndLog(" AMK - Application Master Key settings");
337 c
.arg
[0] = (INIT
| CLEARTRACE
);
338 c
.arg
[LENPOS
] = 0x04;
339 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
340 memcpy(c
.d
.asBytes
+1, aid
, 3);
343 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
344 PrintAndLog(" Timed-out");
347 isOK
= resp
.arg
[0] & 0xff;
349 PrintAndLog(" Can't select AID: %s",sprint_hex(aid
,3));
356 c
.arg
[LENPOS
] = 0x01;
357 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45
359 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
362 isOK
= resp
.arg
[0] & 0xff;
364 PrintAndLog(" Can't read Application Master key settings");
367 uint8_t rights
= (resp
.d
.asBytes
[3] >> 4 && 0xff);
370 str
= "AMK authentication is necessary to change any key (default)";
373 str
= "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
376 str
= "All keys (except AMK,see Bit0) within this application are frozen";
379 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.";
382 PrintAndLog("Changekey Access rights");
383 PrintAndLog("-- %s",str
);
386 str
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";
387 PrintAndLog(" 0x08 Configuration changeable : %s", str
);
388 str
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES";
389 PrintAndLog(" 0x04 AMK required for create/delete : %s",str
);
390 str
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES";
391 PrintAndLog(" 0x02 Directory list access with AMK : %s",str
);
392 str
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO";
393 PrintAndLog(" 0x01 AMK is changeable : %s", str
);
398 c
.arg
[LENPOS
] = 0x02;
399 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64
400 c
.d
.asBytes
[1] = 0x00;
402 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
403 PrintAndLog(" Timed-out");
409 isOK
= resp
.arg
[0] & 0xff;
411 PrintAndLog(" Can't read Application Master key version. Trying all keys");
412 numOfKeys
= MAX_NUM_KEYS
;
415 numOfKeys
= resp
.d
.asBytes
[4];
417 PrintAndLog(" Max number of keys : %d", numOfKeys
);
418 PrintAndLog(" Application Master key Version : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]);
419 PrintAndLog("-------------------------------------------------------------");
422 // LOOP over numOfKeys that we got before.
423 // From 0x01 to numOfKeys. We already got 0x00. (AMK)
424 for(int i
=0x01; i
<=0x0f; ++i
){
432 int CmdHF14ADesEnumApplications(const char *Cmd
){
436 uint32_t options
= (INIT
| DISCONNECT
);
438 UsbCommand c
= {CMD_MIFARE_DESFIRE
, {options
, 0x01 }};
439 c
.d
.asBytes
[0] = GET_APPLICATION_IDS
; //0x6a
444 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) {
447 isOK
= resp
.arg
[0] & 0xff;
449 PrintAndLog("Command unsuccessful");
453 PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
454 PrintAndLog("-------------------------------------------------------------");
457 UsbCommand respFiles
;
460 int max
= resp
.arg
[1] -3 -2;
462 for(int i
=3; i
<=max
; i
+=3){
463 PrintAndLog(" Aid %d : %02X %02X %02X ",num
,resp
.d
.asBytes
[i
],resp
.d
.asBytes
[i
+1],resp
.d
.asBytes
[i
+2]);
466 aid
[0] = resp
.d
.asBytes
[i
];
467 aid
[1] = resp
.d
.asBytes
[i
+1];
468 aid
[2] = resp
.d
.asBytes
[i
+2];
471 // Select Application
472 c
.arg
[CMDPOS
] = INIT
;
473 c
.arg
[LENPOS
] = 0x04;
474 c
.d
.asBytes
[0] = SELECT_APPLICATION
; // 0x5a
475 c
.d
.asBytes
[1] = resp
.d
.asBytes
[i
];
476 c
.d
.asBytes
[2] = resp
.d
.asBytes
[i
+1];
477 c
.d
.asBytes
[3] = resp
.d
.asBytes
[i
+2];
480 if (!WaitForResponseTimeout(CMD_ACK
,&respAid
,1500) ) {
481 PrintAndLog(" Timed-out");
484 isOK
= respAid
.d
.asBytes
[2] & 0xff;
486 PrintAndLog(" Can't select AID: %s",sprint_hex(resp
.d
.asBytes
+i
,3));
491 c
.arg
[CMDPOS
] = NONE
;
492 c
.arg
[LENPOS
] = 0x01;
493 c
.d
.asBytes
[0] = GET_FILE_IDS
; // 0x6f
496 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
497 PrintAndLog(" Timed-out");
500 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
502 PrintAndLog(" Can't get file ids ");
504 int respfileLen
= resp
.arg
[1]-3-2;
505 for (int j
=0; j
< respfileLen
; ++j
){
506 PrintAndLog(" Fileid %d :", resp
.d
.asBytes
[j
+3]);
512 c
.arg
[CMDPOS
] = DISCONNECT
;
513 c
.arg
[LENPOS
] = 0x01;
514 c
.d
.asBytes
[0] = GET_ISOFILE_IDS
; // 0x61
517 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) {
518 PrintAndLog(" Timed-out");
521 isOK
= respFiles
.d
.asBytes
[2] & 0xff;
523 PrintAndLog(" Can't get ISO file ids ");
525 int respfileLen
= resp
.arg
[1]-3-2;
526 for (int j
=0; j
< respfileLen
; ++j
){
527 PrintAndLog(" ISO Fileid %d :", resp
.d
.asBytes
[j
+3]);
534 PrintAndLog("-------------------------------------------------------------");
540 int CmdHF14ADesNonces(const char *Cmd
){
545 // MIAFRE DesFire Authentication
548 int CmdHF14ADesAuth(const char *Cmd
){
551 // ------------------------
557 uint8_t keylength
= 8;
558 unsigned char key
[24];
561 PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
562 PrintAndLog(" Auth modes");
563 PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
564 PrintAndLog(" Crypto");
565 PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
567 PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
568 PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
571 uint8_t cmdAuthMode
= param_get8(Cmd
,0);
572 uint8_t cmdAuthAlgo
= param_get8(Cmd
,1);
573 uint8_t cmdKeyNo
= param_get8(Cmd
,2);
578 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2) {
579 PrintAndLog("Crypto algo not valid for the auth mode");
584 if ( cmdAuthAlgo
!= 1 && cmdAuthAlgo
!= 2 && cmdAuthAlgo
!= 3) {
585 PrintAndLog("Crypto algo not valid for the auth mode");
590 if ( cmdAuthAlgo
!= 4) {
591 PrintAndLog("Crypto algo not valid for the auth mode");
596 PrintAndLog("Wrong Auth mode");
601 switch (cmdAuthAlgo
){
604 PrintAndLog("3DES selected");
608 PrintAndLog("3 key 3DES selected");
612 PrintAndLog("AES selected");
617 PrintAndLog("DES selected");
622 if (param_gethex(Cmd
, 3, key
, keylength
*2)) {
623 PrintAndLog("Key must include %d HEX symbols", keylength
);
626 // algo, nyckellängd,
627 UsbCommand c
= {CMD_MIFARE_DESFIRE_AUTH1
, { cmdAuthMode
, cmdAuthAlgo
, cmdKeyNo
}};
629 c
.d
.asBytes
[0] = keylength
;
630 memcpy(c
.d
.asBytes
+1, key
, keylength
);
635 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) {
636 PrintAndLog("Client command execute timeout");
640 uint8_t isOK
= resp
.arg
[0] & 0xff;
642 uint8_t * data
= resp
.d
.asBytes
;
644 PrintAndLog(" Key :%s",sprint_hex(key
, keylength
));
645 PrintAndLog(" SESSION :%s",sprint_hex(data
, keylength
));
646 PrintAndLog("-------------------------------------------------------------");
647 //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
649 PrintAndLog("Client command failed.");
651 PrintAndLog("-------------------------------------------------------------");
656 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
) {
657 for( ; len
> 0; len
--,dst
++,src
++)
661 static int32_t le24toh (uint8_t data
[3]) {
662 return (data
[2] << 16) | (data
[1] << 8) | data
[0];
665 static command_t CommandTable
[] =
667 {"help", CmdHelp
, 1, "This help"},
668 {"auth", CmdHF14ADesAuth
, 0, "Tries a MIFARE DesFire Authentication"},
669 {"rb", CmdHF14ADesRb
, 0, "Read MIFARE DesFire block"},
670 {"wb", CmdHF14ADesWb
, 0, "write MIFARE DesFire block"},
671 {"info", CmdHF14ADesInfo
, 0, "Get MIFARE DesFire information"},
672 {"enum", CmdHF14ADesEnumApplications
,0, "Tries enumerate all applications"},
673 {"nonce", CmdHF14ADesNonces
, 0, "<n> Collect n>0 nonces"},
674 {NULL
, NULL
, 0, NULL
}
677 int CmdHFMFDes(const char *Cmd
)
680 WaitForResponseTimeout(CMD_ACK
,NULL
,100);
681 CmdsParse(CommandTable
, Cmd
);
685 int CmdHelp(const char *Cmd
)
687 CmdsHelp(CommandTable
);