]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhfmfu.c
716a7e661d47045e385ffca21319bd600138a8d1
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 uint8_t MAX_ULTRA_BLOCKS
= 0x0f;
17 uint8_t MAX_ULTRAC_BLOCKS
= 0x2c;
18 uint8_t key1_blnk_data
[16] = { 0x00 };
19 uint8_t key2_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
20 uint8_t key3_3des_data
[16] = { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 };
21 uint8_t key4_nfc_data
[16] = { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 };
22 uint8_t key5_ones_data
[16] = { 0x01 };
24 static int CmdHelp(const char *Cmd
);
26 int CmdHF14AMfUInfo(const char *Cmd
){
28 uint8_t datatemp
[7] = {0x00};
32 UsbCommand c
= {CMD_MIFAREU_READCARD
, {0, 4}};
36 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
37 isOK
= resp
.arg
[0] & 0xff;
38 data
= resp
.d
.asBytes
;
41 PrintAndLog("Error reading from tag");
45 PrintAndLog("Command execute timed out");
50 PrintAndLog("-- Mifare Ultralight / Ultralight-C Tag Information ---------");
51 PrintAndLog("-------------------------------------------------------------");
54 memcpy( datatemp
, data
, 3);
55 memcpy( datatemp
+3, data
+4, 4);
57 PrintAndLog("MANUFACTURER : %s", getTagInfo(datatemp
[0]));
58 PrintAndLog(" UID : %s ", sprint_hex(datatemp
, 7));
60 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
61 int crc0
= 0x88 ^ data
[0] ^ data
[1] ^data
[2];
62 if ( data
[3] == crc0
)
63 PrintAndLog(" BCC0 : %02x - Ok", data
[3]);
65 PrintAndLog(" BCC0 : %02x - crc should be %02x", data
[3], crc0
);
67 int crc1
= data
[4] ^ data
[5] ^ data
[6] ^data
[7];
68 if ( data
[8] == crc1
)
69 PrintAndLog(" BCC1 : %02x - Ok", data
[8]);
71 PrintAndLog(" BCC1 : %02x - crc should be %02x", data
[8], crc1
);
73 PrintAndLog(" Internal : %s ", sprint_hex(data
+ 9, 1));
75 memcpy(datatemp
, data
+10, 2);
76 PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp
, 2),printBits( 2, &datatemp
) );
77 PrintAndLog(" OneTimePad : %s ", sprint_hex(data
+ 3*4, 4));
80 int len
= CmdHF14AMfucAuth("K 0");
81 // PrintAndLog("CODE: %d",len);
83 PrintAndLog("Seems to be a Ultralight %s", (len
==0) ? "-C" :"");
88 // Mifare Ultralight Write Single Block
90 int CmdHF14AMfUWrBl(const char *Cmd
){
92 bool chinese_card
= FALSE
;
93 uint8_t bldata
[16] = {0x00};
96 char cmdp
= param_getchar(Cmd
, 0);
97 if (strlen(Cmd
) < 3 || cmdp
== 'h' || cmdp
== 'H') {
98 PrintAndLog("Usage: hf mfu wrbl <block number> <block data (8 hex symbols)> [w]");
99 PrintAndLog(" [block number]");
100 PrintAndLog(" [block data] - (8 hex symbols)");
101 PrintAndLog(" [w] - Chinese magic ultralight tag");
103 PrintAndLog(" sample: hf mfu wrbl 0 01020304");
108 blockNo
= param_get8(Cmd
, 0);
109 if (blockNo
> MAX_ULTRA_BLOCKS
){
110 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
114 if (param_gethex(Cmd
, 1, bldata
, 8)) {
115 PrintAndLog("Block data must include 8 HEX symbols");
119 if (strchr(Cmd
,'w') != 0 || strchr(Cmd
,'W') != 0 ) {
125 PrintAndLog("Access Denied");
127 PrintAndLog("--specialblock no:%02x", blockNo
);
128 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
129 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
130 memcpy(d
.d
.asBytes
,bldata
, 4);
132 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
133 uint8_t isOK
= resp
.arg
[0] & 0xff;
134 PrintAndLog("isOk:%02x", isOK
);
136 PrintAndLog("Command execute timeout");
140 PrintAndLog("--block no:%02x", blockNo
);
141 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
142 UsbCommand e
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
143 memcpy(e
.d
.asBytes
,bldata
, 4);
145 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
146 uint8_t isOK
= resp
.arg
[0] & 0xff;
147 PrintAndLog("isOk:%02x", isOK
);
149 PrintAndLog("Command execute timeout");
156 // Mifare Ultralight Read Single Block
158 int CmdHF14AMfURdBl(const char *Cmd
){
162 char cmdp
= param_getchar(Cmd
, 0);
164 if (strlen(Cmd
) < 1 || cmdp
== 'h' || cmdp
== 'H') {
165 PrintAndLog("Usage: hf mfu rdbl <block number>");
166 PrintAndLog(" sample: hfu mfu rdbl 0");
170 blockNo
= param_get8(Cmd
, 0);
171 // if (blockNo>MAX_ULTRA_BLOCKS){
172 // PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
175 PrintAndLog("--block no:0x%02X (%d)", (int)blockNo
, blockNo
);
176 UsbCommand c
= {CMD_MIFAREU_READBL
, {blockNo
}};
180 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
181 uint8_t isOK
= resp
.arg
[0] & 0xff;
182 uint8_t * data
= resp
.d
.asBytes
;
184 PrintAndLog("isOk: %02x", isOK
);
187 PrintAndLog("Data: %s", sprint_hex(data
, 4));
189 PrintAndLog("Command execute timeout");
195 // Mifare Ultralight / Ultralight-C; Read and Dump Card Contents
197 int CmdHF14AMfUDump(const char *Cmd
){
200 char filename
[FILE_PATH_SIZE
] = {0x00};
201 char * fnameptr
= filename
;
203 uint8_t *lockbytes_t
= NULL
;
204 uint8_t lockbytes
[2] = {0x00};
206 uint8_t *lockbytes_t2
= NULL
;
207 uint8_t lockbytes2
[2] = {0x00};
209 bool bit
[16] = {0x00};
210 bool bit2
[16] = {0x00};
216 bool tmplockbit
= false;
218 uint8_t *data
= NULL
;
220 char cmdp
= param_getchar(Cmd
, 0);
222 if (cmdp
== 'h' || cmdp
== 'H') {
223 PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag.");
224 PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`");
225 PrintAndLog("Usage: hf mfu dump <c> <filename w/o .bin>");
226 PrintAndLog(" <c> optional cardtype c == Ultralight-C, if not defaults to Ultralight");
227 PrintAndLog(" sample: hf mfu dump");
228 PrintAndLog(" : hf mfu dump myfile");
229 PrintAndLog(" : hf mfu dump c myfile");
234 Pages
= (cmdp
== 'c' || cmdp
== 'C') ? 44 : 16;
236 PrintAndLog("Dumping Ultralight%s Card Data...", (Pages
==16)?"":"-C");
238 UsbCommand c
= {CMD_MIFAREU_READCARD
, {BlockNo
,Pages
}};
242 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
243 isOK
= resp
.arg
[0] & 0xff;
245 PrintAndLog("Command error");
248 data
= resp
.d
.asBytes
;
250 PrintAndLog("Command execute timeout");
257 lockbytes_t
= data
+ 8;
258 lockbytes
[0] = lockbytes_t
[2];
259 lockbytes
[1] = lockbytes_t
[3];
260 for(j
= 0; j
< 16; j
++){
261 bit
[j
] = lockbytes
[j
/8] & ( 1 <<(7-j
%8));
264 // Load bottom lockbytes if available
267 lockbytes_t2
= data
+ (40*4);
268 lockbytes2
[0] = lockbytes_t2
[2];
269 lockbytes2
[1] = lockbytes_t2
[3];
270 for (j
= 0; j
< 16; j
++) {
271 bit2
[j
] = lockbytes2
[j
/8] & ( 1 <<(7-j
%8));
275 for (i
= 0; i
< Pages
; ++i
) {
278 PrintAndLog("Block %02x:%s ", i
,sprint_hex(data
+ i
* 4, 4));
283 case 3: tmplockbit
= bit
[4]; break;
284 case 4: tmplockbit
= bit
[3]; break;
285 case 5: tmplockbit
= bit
[2]; break;
286 case 6: tmplockbit
= bit
[1]; break;
287 case 7: tmplockbit
= bit
[0]; break;
288 case 8: tmplockbit
= bit
[15]; break;
289 case 9: tmplockbit
= bit
[14]; break;
290 case 10: tmplockbit
= bit
[13]; break;
291 case 11: tmplockbit
= bit
[12]; break;
292 case 12: tmplockbit
= bit
[11]; break;
293 case 13: tmplockbit
= bit
[10]; break;
294 case 14: tmplockbit
= bit
[9]; break;
295 case 15: tmplockbit
= bit
[8]; break;
299 case 19: tmplockbit
= bit2
[6]; break;
303 case 23: tmplockbit
= bit2
[5]; break;
307 case 27: tmplockbit
= bit2
[4]; break;
311 case 31: tmplockbit
= bit2
[2]; break;
315 case 35: tmplockbit
= bit2
[1]; break;
319 case 39: tmplockbit
= bit2
[0]; break;
320 case 40: tmplockbit
= bit2
[12]; break;
321 case 41: tmplockbit
= bit2
[11]; break;
322 case 42: tmplockbit
= bit2
[10]; break; //auth0
323 case 43: tmplockbit
= bit2
[9]; break; //auth1
326 PrintAndLog("Block %02x:%s [%d]", i
,sprint_hex(data
+ i
* 4, 4),tmplockbit
);
331 len
= param_getstr(Cmd
,0,filename
);
333 len
= param_getstr(Cmd
,1,filename
);
335 if (len
> FILE_PATH_SIZE
) len
= FILE_PATH_SIZE
;
337 // user supplied filename?
340 // UID = data 0-1-2 4-5-6-7 (skips a beat)
341 sprintf(fnameptr
, "%02X", data
[0]);
343 sprintf(fnameptr
, "%02X", data
[1]);
345 sprintf(fnameptr
, "%02X", data
[2]);
347 sprintf(fnameptr
, "%02X", data
[4]);
349 sprintf(fnameptr
, "%02X", data
[5]);
351 sprintf(fnameptr
, "%02X", data
[6]);
353 sprintf(fnameptr
, "%02X", data
[7]);
360 // add file extension
361 sprintf(fnameptr
, ".bin");
363 if ((fout
= fopen(filename
,"wb")) == NULL
) {
364 PrintAndLog("Could not create file name %s", filename
);
367 fwrite( data
, 1, Pages
*4, fout
);
370 PrintAndLog("Dumped %d pages, wrote %d bytes to %s", Pages
, Pages
*4, filename
);
374 // Needed to Authenticate to Ultralight C tags
375 void rol (uint8_t *data
, const size_t len
){
376 uint8_t first
= data
[0];
377 for (size_t i
= 0; i
< len
-1; i
++) {
383 //-------------------------------------------------------------------------------
384 // Ultralight C Methods
385 //-------------------------------------------------------------------------------
388 // Ultralight C Authentication Demo {currently uses hard-coded key}
390 int CmdHF14AMfucAuth(const char *Cmd
){
392 uint8_t blockNo
= 0, keyNo
= 0;
393 uint8_t e_RndB
[8] = {0x00};
395 unsigned char RndARndB
[16] = {0x00};
396 uint8_t key
[16] = {0x00};
397 DES_cblock RndA
, RndB
;
399 DES_key_schedule ks1
,ks2
;
400 DES_cblock key1
,key2
;
402 char cmdp
= param_getchar(Cmd
, 0);
406 if (cmdp
== 'h' || cmdp
== 'H') {
407 PrintAndLog("Usage: hf mfu cauth k <key number>");
408 PrintAndLog(" 1 = all zeros key");
409 PrintAndLog(" 2 = 0x00-0x0F key");
410 PrintAndLog(" 3 = nfc key");
411 PrintAndLog(" 4 = all ones key");
412 PrintAndLog(" defaults to 3DES standard key");
413 PrintAndLog(" sample : hf mfu cauth k");
414 PrintAndLog(" : hf mfu cauth k 3");
418 //Change key to user defined one
419 if (cmdp
== 'k' || cmdp
== 'K'){
421 keyNo
= param_get8(Cmd
, 1);
425 memcpy(key
,key1_blnk_data
,16);
428 memcpy(key
,key2_defa_data
,16);
431 memcpy(key
,key4_nfc_data
,16);
434 memcpy(key
,key5_ones_data
,16);
437 memcpy(key
,key3_3des_data
,16);
441 memcpy(key
,key3_3des_data
,16);
445 memcpy(key2
,key
+8,8);
446 DES_set_key((DES_cblock
*)key1
,&ks1
);
447 DES_set_key((DES_cblock
*)key2
,&ks2
);
450 UsbCommand c
= {CMD_MIFAREUC_AUTH1
, {blockNo
}};
453 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
454 uint8_t isOK
= resp
.arg
[0] & 0xff;
456 uint8_t * data
= resp
.d
.asBytes
;
459 PrintAndLog("enc(RndB):%s", sprint_hex(data
+1, 8));
460 memcpy(e_RndB
,data
+1,8);
462 return 2; // auth failed.
465 PrintAndLog("Command execute timeout");
470 DES_random_key(&RndA
);
471 DES_ede2_cbc_encrypt(e_RndB
,RndB
,sizeof(e_RndB
),&ks1
,&ks2
,&iv
,0);
472 PrintAndLog(" RndB:%s",sprint_hex(RndB
, 8));
473 PrintAndLog(" RndA:%s",sprint_hex(RndA
, 8));
475 memcpy(RndARndB
,RndA
,8);
476 memcpy(RndARndB
+8,RndB
,8);
477 PrintAndLog(" RA+B:%s",sprint_hex(RndARndB
, 16));
478 DES_ede2_cbc_encrypt(RndARndB
,RndARndB
,sizeof(RndARndB
),&ks1
,&ks2
,&e_RndB
,1);
479 PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB
, 16));
482 UsbCommand d
= {CMD_MIFAREUC_AUTH2
, {cuid
}};
483 memcpy(d
.d
.asBytes
,RndARndB
, 16);
487 if (WaitForResponseTimeout(CMD_ACK
,&respb
,1500)) {
488 uint8_t isOK
= respb
.arg
[0] & 0xff;
489 uint8_t * data2
= respb
.d
.asBytes
;
492 PrintAndLog("enc(RndA'):%s", sprint_hex(data2
+1, 8));
498 PrintAndLog("Command execute timeout");
505 // Ultralight C Read Single Block
507 int CmdHF14AMfUCRdBl(const char *Cmd
)
509 uint8_t blockNo
= -1;
510 char cmdp
= param_getchar(Cmd
, 0);
512 if (strlen(Cmd
) < 1 || cmdp
== 'h' || cmdp
== 'H') {
513 PrintAndLog("Usage: hf mfu crdbl <block number>");
514 PrintAndLog(" sample: hf mfu crdbl 0");
518 blockNo
= param_get8(Cmd
, 0);
520 PrintAndLog("Wrong block number");
524 if (blockNo
> (MAX_ULTRAC_BLOCKS
+4) ){
525 PrintAndLog("Error: Maximum number of readable blocks is 47 for Ultralight-C Cards!");
529 PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo
, blockNo
);
532 UsbCommand e
= {CMD_MIFAREU_READBL
, {blockNo
}};
535 if (WaitForResponseTimeout(CMD_ACK
,&resp_c
,1500)) {
536 uint8_t isOK
= resp_c
.arg
[0] & 0xff;
537 uint8_t *data
= resp_c
.d
.asBytes
;
539 PrintAndLog("isOk: %02x", isOK
);
541 PrintAndLog("Data: %s", sprint_hex(data
, 4));
544 PrintAndLog("Command execute timeout");
550 // Mifare Ultralight C Write Single Block
552 int CmdHF14AMfUCWrBl(const char *Cmd
){
555 bool chinese_card
= FALSE
;
556 uint8_t bldata
[16] = {0x00};
559 char cmdp
= param_getchar(Cmd
, 0);
561 if (strlen(Cmd
) < 3 || cmdp
== 'h' || cmdp
== 'H') {
562 PrintAndLog("Usage: hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]");
563 PrintAndLog(" [block number]");
564 PrintAndLog(" [block data] - (8 hex symbols)");
565 PrintAndLog(" [w] - Chinese magic ultralight tag");
567 PrintAndLog(" sample: hf mfu cwrbl 0 01020304");
572 blockNo
= param_get8(Cmd
, 0);
573 if (blockNo
> (MAX_ULTRAC_BLOCKS
+4) ){
574 PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!");
578 if (param_gethex(Cmd
, 1, bldata
, 8)) {
579 PrintAndLog("Block data must include 8 HEX symbols");
583 if (strchr(Cmd
,'w') != 0 || strchr(Cmd
,'W') != 0 ) {
587 if ( blockNo
<= 3 ) {
589 PrintAndLog("Access Denied");
591 PrintAndLog("--Special block no: 0x%02x", blockNo
);
592 PrintAndLog("--Data: %s", sprint_hex(bldata
, 4));
593 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
594 memcpy(d
.d
.asBytes
,bldata
, 4);
596 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
597 uint8_t isOK
= resp
.arg
[0] & 0xff;
598 PrintAndLog("isOk:%02x", isOK
);
600 PrintAndLog("Command execute timeout");
604 PrintAndLog("--Block no : 0x%02x", blockNo
);
605 PrintAndLog("--Data: %s", sprint_hex(bldata
, 4));
606 UsbCommand e
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
607 memcpy(e
.d
.asBytes
,bldata
, 4);
609 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
610 uint8_t isOK
= resp
.arg
[0] & 0xff;
611 PrintAndLog("isOk : %02x", isOK
);
613 PrintAndLog("Command execute timeout");
619 //------------------------------------
621 //------------------------------------
622 static command_t CommandTable
[] =
624 {"help", CmdHelp
, 1,"This help"},
625 {"dbg", CmdHF14AMfDbg
, 0,"Set default debug mode"},
626 {"info", CmdHF14AMfUInfo
, 0,"Taginfo"},
627 {"dump", CmdHF14AMfUDump
, 0,"Dump MIFARE Ultralight / Ultralight-C tag to binary file"},
628 {"rdbl", CmdHF14AMfURdBl
, 0,"Read block - MIFARE Ultralight"},
629 {"wrbl", CmdHF14AMfUWrBl
, 0,"Write block - MIFARE Ultralight"},
630 {"crdbl", CmdHF14AMfUCRdBl
, 0,"Read block - MIFARE Ultralight C"},
631 {"cwrbl", CmdHF14AMfUCWrBl
, 0,"Write MIFARE Ultralight C block"},
632 {"cauth", CmdHF14AMfucAuth
, 0,"try a Ultralight C Authentication"},
633 {NULL
, NULL
, 0, NULL
}
636 int CmdHFMFUltra(const char *Cmd
){
637 WaitForResponseTimeout(CMD_ACK
,NULL
,100);
638 CmdsParse(CommandTable
, Cmd
);
642 int CmdHelp(const char *Cmd
){
643 CmdsHelp(CommandTable
);