]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhfmfu.c
1 //-----------------------------------------------------------------------------
2 // Ultralight Code (c) 2013,2014 Midnitesnake & Andy Davies of Pentura
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 ULTRALIGHT (C) commands
9 //-----------------------------------------------------------------------------
10 #include <openssl/des.h>
16 #define MAX_ULTRA_BLOCKS 0x0f
17 #define MAX_ULTRAC_BLOCKS 0x2f
18 //#define MAX_ULTRAC_BLOCKS 0x2c
19 uint8_t key1_blnk_data
[16] = { 0x00 };
20 uint8_t key2_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
21 uint8_t key3_3des_data
[16] = { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 };
22 uint8_t key4_nfc_data
[16] = { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 };
23 uint8_t key5_ones_data
[16] = { 0x01 };
25 static int CmdHelp(const char *Cmd
);
27 int CmdHF14AMfUInfo(const char *Cmd
){
29 uint8_t datatemp
[7] = {0x00};
33 UsbCommand c
= {CMD_MIFAREU_READCARD
, {0, 4}};
37 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
38 isOK
= resp
.arg
[0] & 0xff;
39 data
= resp
.d
.asBytes
;
42 PrintAndLog("Error reading from tag");
46 PrintAndLog("Command execute timed out");
51 PrintAndLog("-- Mifare Ultralight / Ultralight-C Tag Information ---------");
52 PrintAndLog("-------------------------------------------------------------");
55 memcpy( datatemp
, data
, 3);
56 memcpy( datatemp
+3, data
+4, 4);
58 PrintAndLog("MANUFACTURER : %s", getTagInfo(datatemp
[0]));
59 PrintAndLog(" UID : %s ", sprint_hex(datatemp
, 7));
61 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
62 int crc0
= 0x88 ^ data
[0] ^ data
[1] ^data
[2];
63 if ( data
[3] == crc0
)
64 PrintAndLog(" BCC0 : %02x - Ok", data
[3]);
66 PrintAndLog(" BCC0 : %02x - crc should be %02x", data
[3], crc0
);
68 int crc1
= data
[4] ^ data
[5] ^ data
[6] ^data
[7];
69 if ( data
[8] == crc1
)
70 PrintAndLog(" BCC1 : %02x - Ok", data
[8]);
72 PrintAndLog(" BCC1 : %02x - crc should be %02x", data
[8], crc1
);
74 PrintAndLog(" Internal : %s ", sprint_hex(data
+ 9, 1));
76 memcpy(datatemp
, data
+10, 2);
77 PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp
, 2),printBits( 2, &datatemp
) );
78 PrintAndLog(" OneTimePad : %s ", sprint_hex(data
+ 3*4, 4));
81 int len
= CmdHF14AMfucAuth("K 0");
82 // PrintAndLog("CODE: %d",len);
84 PrintAndLog("Seems to be a Ultralight %s", (len
==0) ? "-C" :"");
89 // Mifare Ultralight Write Single Block
91 int CmdHF14AMfUWrBl(const char *Cmd
){
93 bool chinese_card
= FALSE
;
94 uint8_t bldata
[16] = {0x00};
97 char cmdp
= param_getchar(Cmd
, 0);
98 if (strlen(Cmd
) < 3 || cmdp
== 'h' || cmdp
== 'H') {
99 PrintAndLog("Usage: hf mfu wrbl <block number> <block data (8 hex symbols)> [w]");
100 PrintAndLog(" [block number]");
101 PrintAndLog(" [block data] - (8 hex symbols)");
102 PrintAndLog(" [w] - Chinese magic ultralight tag");
104 PrintAndLog(" sample: hf mfu wrbl 0 01020304");
109 blockNo
= param_get8(Cmd
, 0);
111 if (blockNo
> MAX_ULTRA_BLOCKS
){
112 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
116 if (param_gethex(Cmd
, 1, bldata
, 8)) {
117 PrintAndLog("Block data must include 8 HEX symbols");
121 if (strchr(Cmd
,'w') != 0 || strchr(Cmd
,'W') != 0 ) {
127 PrintAndLog("Access Denied");
129 PrintAndLog("--specialblock no:%02x", blockNo
);
130 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
131 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
132 memcpy(d
.d
.asBytes
,bldata
, 4);
134 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
135 uint8_t isOK
= resp
.arg
[0] & 0xff;
136 PrintAndLog("isOk:%02x", isOK
);
138 PrintAndLog("Command execute timeout");
142 PrintAndLog("--block no:%02x", blockNo
);
143 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
144 UsbCommand e
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
145 memcpy(e
.d
.asBytes
,bldata
, 4);
147 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
148 uint8_t isOK
= resp
.arg
[0] & 0xff;
149 PrintAndLog("isOk:%02x", isOK
);
151 PrintAndLog("Command execute timeout");
158 // Mifare Ultralight Read Single Block
160 int CmdHF14AMfURdBl(const char *Cmd
){
162 uint8_t blockNo
= -1;
164 char cmdp
= param_getchar(Cmd
, 0);
166 if (strlen(Cmd
) < 1 || cmdp
== 'h' || cmdp
== 'H') {
167 PrintAndLog("Usage: hf mfu rdbl <block number>");
168 PrintAndLog(" sample: hfu mfu rdbl 0");
172 blockNo
= param_get8(Cmd
, 0);
174 if (blockNo
> MAX_ULTRA_BLOCKS
){
175 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
179 PrintAndLog("--block no:0x%02X (%d)", (int)blockNo
, blockNo
);
180 UsbCommand c
= {CMD_MIFAREU_READBL
, {blockNo
}};
184 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
185 uint8_t isOK
= resp
.arg
[0] & 0xff;
186 uint8_t * data
= resp
.d
.asBytes
;
188 PrintAndLog("isOk: %02x", isOK
);
191 PrintAndLog("Data: %s", sprint_hex(data
, 4));
193 PrintAndLog("Command execute timeout");
199 // Mifare Ultralight / Ultralight-C; Read and Dump Card Contents
201 int CmdHF14AMfUDump(const char *Cmd
){
204 char filename
[FILE_PATH_SIZE
] = {0x00};
205 char * fnameptr
= filename
;
207 uint8_t *lockbytes_t
= NULL
;
208 uint8_t lockbytes
[2] = {0x00};
210 uint8_t *lockbytes_t2
= NULL
;
211 uint8_t lockbytes2
[2] = {0x00};
213 bool bit
[16] = {0x00};
214 bool bit2
[16] = {0x00};
220 bool tmplockbit
= false;
222 uint8_t *data
= NULL
;
224 char cmdp
= param_getchar(Cmd
, 0);
226 if (cmdp
== 'h' || cmdp
== 'H') {
227 PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag.");
228 PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`");
229 PrintAndLog("Usage: hf mfu dump <c> <filename w/o .bin>");
230 PrintAndLog(" <c> optional cardtype c == Ultralight-C, if not defaults to Ultralight");
231 PrintAndLog(" sample: hf mfu dump");
232 PrintAndLog(" : hf mfu dump myfile");
233 PrintAndLog(" : hf mfu dump c myfile");
238 Pages
= (cmdp
== 'c' || cmdp
== 'C') ? 44 : 16;
240 PrintAndLog("Dumping Ultralight%s Card Data...", (Pages
==16)?"":"-C");
242 UsbCommand c
= {CMD_MIFAREU_READCARD
, {BlockNo
,Pages
}};
246 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
247 isOK
= resp
.arg
[0] & 0xff;
249 PrintAndLog("Command error");
252 data
= resp
.d
.asBytes
;
254 PrintAndLog("Command execute timeout");
261 lockbytes_t
= data
+ 8;
262 lockbytes
[0] = lockbytes_t
[2];
263 lockbytes
[1] = lockbytes_t
[3];
264 for(j
= 0; j
< 16; j
++){
265 bit
[j
] = lockbytes
[j
/8] & ( 1 <<(7-j
%8));
268 // Load bottom lockbytes if available
271 lockbytes_t2
= data
+ (40*4);
272 lockbytes2
[0] = lockbytes_t2
[2];
273 lockbytes2
[1] = lockbytes_t2
[3];
274 for (j
= 0; j
< 16; j
++) {
275 bit2
[j
] = lockbytes2
[j
/8] & ( 1 <<(7-j
%8));
279 for (i
= 0; i
< Pages
; ++i
) {
282 PrintAndLog("Block %02x:%s ", i
,sprint_hex(data
+ i
* 4, 4));
287 case 3: tmplockbit
= bit
[4]; break;
288 case 4: tmplockbit
= bit
[3]; break;
289 case 5: tmplockbit
= bit
[2]; break;
290 case 6: tmplockbit
= bit
[1]; break;
291 case 7: tmplockbit
= bit
[0]; break;
292 case 8: tmplockbit
= bit
[15]; break;
293 case 9: tmplockbit
= bit
[14]; break;
294 case 10: tmplockbit
= bit
[13]; break;
295 case 11: tmplockbit
= bit
[12]; break;
296 case 12: tmplockbit
= bit
[11]; break;
297 case 13: tmplockbit
= bit
[10]; break;
298 case 14: tmplockbit
= bit
[9]; break;
299 case 15: tmplockbit
= bit
[8]; break;
303 case 19: tmplockbit
= bit2
[6]; break;
307 case 23: tmplockbit
= bit2
[5]; break;
311 case 27: tmplockbit
= bit2
[4]; break;
315 case 31: tmplockbit
= bit2
[2]; break;
319 case 35: tmplockbit
= bit2
[1]; break;
323 case 39: tmplockbit
= bit2
[0]; break;
324 case 40: tmplockbit
= bit2
[12]; break;
325 case 41: tmplockbit
= bit2
[11]; break;
326 case 42: tmplockbit
= bit2
[10]; break; //auth0
327 case 43: tmplockbit
= bit2
[9]; break; //auth1
330 PrintAndLog("Block %02x:%s [%d]", i
,sprint_hex(data
+ i
* 4, 4),tmplockbit
);
335 len
= param_getstr(Cmd
,0,filename
);
337 len
= param_getstr(Cmd
,1,filename
);
339 if (len
> FILE_PATH_SIZE
) len
= FILE_PATH_SIZE
;
341 // user supplied filename?
344 // UID = data 0-1-2 4-5-6-7 (skips a beat)
345 sprintf(fnameptr
, "%02X", data
[0]);
347 sprintf(fnameptr
, "%02X", data
[1]);
349 sprintf(fnameptr
, "%02X", data
[2]);
351 sprintf(fnameptr
, "%02X", data
[4]);
353 sprintf(fnameptr
, "%02X", data
[5]);
355 sprintf(fnameptr
, "%02X", data
[6]);
357 sprintf(fnameptr
, "%02X", data
[7]);
364 // add file extension
365 sprintf(fnameptr
, ".bin");
367 if ((fout
= fopen(filename
,"wb")) == NULL
) {
368 PrintAndLog("Could not create file name %s", filename
);
371 fwrite( data
, 1, Pages
*4, fout
);
374 PrintAndLog("Dumped %d pages, wrote %d bytes to %s", Pages
, Pages
*4, filename
);
378 // Needed to Authenticate to Ultralight C tags
379 void rol (uint8_t *data
, const size_t len
){
380 uint8_t first
= data
[0];
381 for (size_t i
= 0; i
< len
-1; i
++) {
387 //-------------------------------------------------------------------------------
388 // Ultralight C Methods
389 //-------------------------------------------------------------------------------
392 // Ultralight C Authentication Demo {currently uses hard-coded key}
394 int CmdHF14AMfucAuth(const char *Cmd
){
396 uint8_t blockNo
= 0, keyNo
= 0;
397 uint8_t e_RndB
[8] = {0x00};
399 unsigned char RndARndB
[16] = {0x00};
400 uint8_t key
[16] = {0x00};
401 DES_cblock RndA
, RndB
;
403 DES_key_schedule ks1
,ks2
;
404 DES_cblock key1
,key2
;
406 char cmdp
= param_getchar(Cmd
, 0);
410 if (cmdp
== 'h' || cmdp
== 'H') {
411 PrintAndLog("Usage: hf mfu cauth k <key number>");
412 PrintAndLog(" 1 = all zeros key");
413 PrintAndLog(" 2 = 0x00-0x0F key");
414 PrintAndLog(" 3 = nfc key");
415 PrintAndLog(" 4 = all ones key");
416 PrintAndLog(" defaults to 3DES standard key");
417 PrintAndLog(" sample : hf mfu cauth k");
418 PrintAndLog(" : hf mfu cauth k 3");
422 //Change key to user defined one
423 if (cmdp
== 'k' || cmdp
== 'K'){
425 keyNo
= param_get8(Cmd
, 1);
429 memcpy(key
,key1_blnk_data
,16);
432 memcpy(key
,key2_defa_data
,16);
435 memcpy(key
,key4_nfc_data
,16);
438 memcpy(key
,key5_ones_data
,16);
441 memcpy(key
,key3_3des_data
,16);
445 memcpy(key
,key3_3des_data
,16);
449 memcpy(key2
,key
+8,8);
450 DES_set_key((DES_cblock
*)key1
,&ks1
);
451 DES_set_key((DES_cblock
*)key2
,&ks2
);
454 UsbCommand c
= {CMD_MIFAREUC_AUTH1
, {blockNo
}};
457 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
458 uint8_t isOK
= resp
.arg
[0] & 0xff;
460 uint8_t * data
= resp
.d
.asBytes
;
463 PrintAndLog("enc(RndB):%s", sprint_hex(data
+1, 8));
464 memcpy(e_RndB
,data
+1,8);
466 return 2; // auth failed.
469 PrintAndLog("Command execute timeout");
474 DES_random_key(&RndA
);
475 DES_ede2_cbc_encrypt(e_RndB
,RndB
,sizeof(e_RndB
),&ks1
,&ks2
,&iv
,0);
476 PrintAndLog(" RndB:%s",sprint_hex(RndB
, 8));
477 PrintAndLog(" RndA:%s",sprint_hex(RndA
, 8));
479 memcpy(RndARndB
,RndA
,8);
480 memcpy(RndARndB
+8,RndB
,8);
481 PrintAndLog(" RA+B:%s",sprint_hex(RndARndB
, 16));
482 DES_ede2_cbc_encrypt(RndARndB
,RndARndB
,sizeof(RndARndB
),&ks1
,&ks2
,&e_RndB
,1);
483 PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB
, 16));
486 UsbCommand d
= {CMD_MIFAREUC_AUTH2
, {cuid
}};
487 memcpy(d
.d
.asBytes
,RndARndB
, 16);
491 if (WaitForResponseTimeout(CMD_ACK
,&respb
,1500)) {
492 uint8_t isOK
= respb
.arg
[0] & 0xff;
493 uint8_t * data2
= respb
.d
.asBytes
;
496 PrintAndLog("enc(RndA'):%s", sprint_hex(data2
+1, 8));
502 PrintAndLog("Command execute timeout");
509 // Ultralight C Read Single Block
511 int CmdHF14AMfUCRdBl(const char *Cmd
)
513 uint8_t blockNo
= -1;
514 char cmdp
= param_getchar(Cmd
, 0);
516 if (strlen(Cmd
) < 1 || cmdp
== 'h' || cmdp
== 'H') {
517 PrintAndLog("Usage: hf mfu crdbl <block number>");
518 PrintAndLog(" sample: hf mfu crdbl 0");
522 blockNo
= param_get8(Cmd
, 0);
524 PrintAndLog("Wrong block number");
528 if (blockNo
> MAX_ULTRAC_BLOCKS
){
529 PrintAndLog("Error: Maximum number of readable blocks is 47 for Ultralight-C Cards!");
533 PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo
, blockNo
);
536 UsbCommand e
= {CMD_MIFAREU_READBL
, {blockNo
}};
539 if (WaitForResponseTimeout(CMD_ACK
,&resp_c
,1500)) {
540 uint8_t isOK
= resp_c
.arg
[0] & 0xff;
541 uint8_t *data
= resp_c
.d
.asBytes
;
543 PrintAndLog("isOk: %02x", isOK
);
545 PrintAndLog("Data: %s", sprint_hex(data
, 4));
548 PrintAndLog("Command execute timeout");
554 // Mifare Ultralight C Write Single Block
556 int CmdHF14AMfUCWrBl(const char *Cmd
){
558 uint8_t blockNo
= -1;
559 bool chinese_card
= FALSE
;
560 uint8_t bldata
[16] = {0x00};
563 char cmdp
= param_getchar(Cmd
, 0);
565 if (strlen(Cmd
) < 3 || cmdp
== 'h' || cmdp
== 'H') {
566 PrintAndLog("Usage: hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]");
567 PrintAndLog(" [block number]");
568 PrintAndLog(" [block data] - (8 hex symbols)");
569 PrintAndLog(" [w] - Chinese magic ultralight tag");
571 PrintAndLog(" sample: hf mfu cwrbl 0 01020304");
576 blockNo
= param_get8(Cmd
, 0);
577 if (blockNo
> MAX_ULTRAC_BLOCKS
){
578 PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!");
582 if (param_gethex(Cmd
, 1, bldata
, 8)) {
583 PrintAndLog("Block data must include 8 HEX symbols");
587 if (strchr(Cmd
,'w') != 0 || strchr(Cmd
,'W') != 0 ) {
591 if ( blockNo
<= 3 ) {
593 PrintAndLog("Access Denied");
595 PrintAndLog("--Special block no: 0x%02x", blockNo
);
596 PrintAndLog("--Data: %s", sprint_hex(bldata
, 4));
597 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
598 memcpy(d
.d
.asBytes
,bldata
, 4);
600 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
601 uint8_t isOK
= resp
.arg
[0] & 0xff;
602 PrintAndLog("isOk:%02x", isOK
);
604 PrintAndLog("Command execute timeout");
608 PrintAndLog("--Block no : 0x%02x", blockNo
);
609 PrintAndLog("--Data: %s", sprint_hex(bldata
, 4));
610 UsbCommand e
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
611 memcpy(e
.d
.asBytes
,bldata
, 4);
613 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
614 uint8_t isOK
= resp
.arg
[0] & 0xff;
615 PrintAndLog("isOk : %02x", isOK
);
617 PrintAndLog("Command execute timeout");
623 //------------------------------------
625 //------------------------------------
626 static command_t CommandTable
[] =
628 {"help", CmdHelp
, 1,"This help"},
629 {"dbg", CmdHF14AMfDbg
, 0,"Set default debug mode"},
630 {"info", CmdHF14AMfUInfo
, 0,"Taginfo"},
631 {"dump", CmdHF14AMfUDump
, 0,"Dump MIFARE Ultralight / Ultralight-C tag to binary file"},
632 {"rdbl", CmdHF14AMfURdBl
, 0,"Read block - MIFARE Ultralight"},
633 {"wrbl", CmdHF14AMfUWrBl
, 0,"Write block - MIFARE Ultralight"},
634 {"crdbl", CmdHF14AMfUCRdBl
, 0,"Read block - MIFARE Ultralight C"},
635 {"cwrbl", CmdHF14AMfUCWrBl
, 0,"Write MIFARE Ultralight C block"},
636 {"cauth", CmdHF14AMfucAuth
, 0,"try a Ultralight C Authentication"},
637 {NULL
, NULL
, 0, NULL
}
640 int CmdHFMFUltra(const char *Cmd
){
641 WaitForResponseTimeout(CMD_ACK
,NULL
,100);
642 CmdsParse(CommandTable
, Cmd
);
646 int CmdHelp(const char *Cmd
){
647 CmdsHelp(CommandTable
);