]>
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>
14 uint8_t MAX_ULTRA_BLOCKS
= 0x0f;
15 uint8_t MAX_ULTRAC_BLOCKS
= 0x2c;
16 uint8_t key1_blnk_data
[16] = { 0x00 };
17 uint8_t key2_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
18 uint8_t key3_3des_data
[16] = { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 };
19 uint8_t key4_nfc_data
[16] = { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 };
20 uint8_t key5_ones_data
[16] = { 0x01 };
22 static int CmdHelp(const char *Cmd
);
24 int CmdHF14AMfUInfo(const char *Cmd
){
26 uint8_t datatemp
[7] = {0x00};
30 UsbCommand c
= {CMD_MIFAREU_READCARD
, {0, 4}};
34 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
35 isOK
= resp
.arg
[0] & 0xff;
36 data
= resp
.d
.asBytes
;
39 PrintAndLog("Error reading from tag");
43 PrintAndLog("Command execute timed out");
48 PrintAndLog("-- Mifare Ultralight / Ultralight-C Tag Information ---------");
49 PrintAndLog("-------------------------------------------------------------");
52 memcpy( datatemp
, data
, 3);
53 memcpy( datatemp
+3, data
+4, 4);
55 PrintAndLog("MANUFACTURER : %s", getTagInfo(datatemp
[0]));
56 PrintAndLog(" UID : %s ", sprint_hex(datatemp
, 7));
58 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
59 int crc0
= 0x88 ^ data
[0] ^ data
[1] ^data
[2];
60 if ( data
[3] == crc0
)
61 PrintAndLog(" BCC0 : %02x - Ok", data
[3]);
63 PrintAndLog(" BCC0 : %02x - crc should be %02x", data
[3], crc0
);
65 int crc1
= data
[4] ^ data
[5] ^ data
[6] ^data
[7];
66 if ( data
[8] == crc1
)
67 PrintAndLog(" BCC1 : %02x - Ok", data
[8]);
69 PrintAndLog(" BCC1 : %02x - crc should be %02x", data
[8], crc1
);
71 PrintAndLog(" Internal : %s ", sprint_hex(data
+ 9, 1));
73 memcpy(datatemp
, data
+10, 2);
74 PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp
, 2),printBits( 2, &datatemp
) );
75 PrintAndLog(" OneTimePad : %s ", sprint_hex(data
+ 3*4, 4));
82 // Mifare Ultralight Write Single Block
84 int CmdHF14AMfUWrBl(const char *Cmd
){
86 bool chinese_card
= 0;
87 uint8_t bldata
[16] = {0x00};
91 PrintAndLog("Usage: hf mfu uwrbl <block number> <block data > [w]");
92 PrintAndLog(" [block number] ");
93 PrintAndLog(" [block data] - (8 hex symbols)");
94 PrintAndLog(" [w] - Chinese magic ultralight-c tag ");
96 PrintAndLog(" sample: hf mfu uwrbl 0 01020304");
99 blockNo
= param_get8(Cmd
, 0);
100 if (blockNo
>MAX_ULTRA_BLOCKS
){
101 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
104 if (param_gethex(Cmd
, 1, bldata
, 8)) {
105 PrintAndLog("Block data must include 8 HEX symbols");
108 if (strchr(Cmd
,'w') != 0) {
114 PrintAndLog("Access Denied");
116 PrintAndLog("--specialblock no:%02x", blockNo
);
117 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
118 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
119 memcpy(d
.d
.asBytes
,bldata
, 4);
121 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
122 uint8_t isOK
= resp
.arg
[0] & 0xff;
123 PrintAndLog("isOk:%02x", isOK
);
125 PrintAndLog("Command execute timeout");
131 PrintAndLog("Access Denied");
133 PrintAndLog("--specialblock no:%02x", blockNo
);
134 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
135 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
136 memcpy(d
.d
.asBytes
,bldata
, 4);
138 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
139 uint8_t isOK
= resp
.arg
[0] & 0xff;
140 PrintAndLog("isOk:%02x", isOK
);
142 PrintAndLog("Command execute timeout");
148 PrintAndLog("Access Denied");
150 PrintAndLog("--specialblock no:%02x", blockNo
);
151 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
152 UsbCommand c
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
153 memcpy(c
.d
.asBytes
, bldata
, 4);
155 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
156 uint8_t isOK
= resp
.arg
[0] & 0xff;
157 PrintAndLog("isOk:%02x", isOK
);
159 PrintAndLog("Command execute timeout");
164 PrintAndLog("--specialblock no:%02x", blockNo
);
165 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
166 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
167 memcpy(d
.d
.asBytes
,bldata
, 4);
169 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
170 uint8_t isOK
= resp
.arg
[0] & 0xff;
171 PrintAndLog("isOk:%02x", isOK
);
173 PrintAndLog("Command execute timeout");
177 PrintAndLog("--block no:%02x", blockNo
);
178 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
179 UsbCommand e
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
180 memcpy(e
.d
.asBytes
,bldata
, 4);
182 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
183 uint8_t isOK
= resp
.arg
[0] & 0xff;
184 PrintAndLog("isOk:%02x", isOK
);
186 PrintAndLog("Command execute timeout");
194 // Mifare Ultralight Read Single Block
196 int CmdHF14AMfURdBl(const char *Cmd
){
201 PrintAndLog("Usage: hf mfu urdbl <block number>");
202 PrintAndLog(" sample: hfu mfu urdbl 0");
206 blockNo
= param_get8(Cmd
, 0);
207 // if (blockNo>MAX_ULTRA_BLOCKS){
208 // PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
211 PrintAndLog("--block no:%02x", (int)blockNo
);
212 UsbCommand c
= {CMD_MIFAREU_READBL
, {blockNo
}};
216 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
217 uint8_t isOK
= resp
.arg
[0] & 0xff;
218 uint8_t * data
= resp
.d
.asBytes
;
221 PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4));
223 PrintAndLog("isOk:%02x", isOK
);
226 PrintAndLog("Command execute timeout");
232 // Mifare Ultralight / Ultralight-C; Read and Dump Card Contents
234 int CmdHF14AMfUDump(const char *Cmd
){
237 char filename
[FILE_PATH_SIZE
] = {0x00};
238 char * fnameptr
= filename
;
240 uint8_t *lockbytes_t
= NULL
;
241 uint8_t lockbytes
[2] = {0x00};
243 uint8_t *lockbytes_t2
= NULL
;
244 uint8_t lockbytes2
[2] = {0x00};
246 bool bit
[16] = {0x00};
247 bool bit2
[16] = {0x00};
253 bool tmplockbit
= false;
255 uint8_t *data
= NULL
;
257 char cmdp
= param_getchar(Cmd
, 0);
259 if (cmdp
== 'h' || cmdp
== 'H') {
260 PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag.");
261 PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`");
262 PrintAndLog("Usage: hf mfu dump <c> <filename w/o .bin>");
263 PrintAndLog(" <c> optional cardtype c == Ultralight-C, if not defaults to Ultralight");
264 PrintAndLog(" sample: hf mfu dump");
265 PrintAndLog(" : hf mfu dump myfile");
266 PrintAndLog(" : hf mfu dump c myfile");
271 Pages
= (cmdp
== 'c' || cmdp
== 'C') ? 44 : 16;
273 PrintAndLog("Dumping Ultralight%s Card Data...", (Pages
==16)?"":"-C");
275 UsbCommand c
= {CMD_MIFAREU_READCARD
, {BlockNo
,Pages
}};
279 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
280 isOK
= resp
.arg
[0] & 0xff;
282 PrintAndLog("Command error");
285 data
= resp
.d
.asBytes
;
287 PrintAndLog("Command execute timeout");
294 lockbytes_t
= data
+ 8;
295 lockbytes
[0] = lockbytes_t
[2];
296 lockbytes
[1] = lockbytes_t
[3];
297 for(j
= 0; j
< 16; j
++){
298 bit
[j
] = lockbytes
[j
/8] & ( 1 <<(7-j
%8));
301 // Load bottom lockbytes if available
304 lockbytes_t2
= data
+ (40*4);
305 lockbytes2
[0] = lockbytes_t2
[2];
306 lockbytes2
[1] = lockbytes_t2
[3];
307 for (j
= 0; j
< 16; j
++) {
308 bit2
[j
] = lockbytes2
[j
/8] & ( 1 <<(7-j
%8));
312 for (i
= 0; i
< Pages
; ++i
) {
315 PrintAndLog("Block %02x:%s ", i
,sprint_hex(data
+ i
* 4, 4));
320 case 3: tmplockbit
= bit
[4]; break;
321 case 4: tmplockbit
= bit
[3]; break;
322 case 5: tmplockbit
= bit
[2]; break;
323 case 6: tmplockbit
= bit
[1]; break;
324 case 7: tmplockbit
= bit
[0]; break;
325 case 8: tmplockbit
= bit
[15]; break;
326 case 9: tmplockbit
= bit
[14]; break;
327 case 10: tmplockbit
= bit
[13]; break;
328 case 11: tmplockbit
= bit
[12]; break;
329 case 12: tmplockbit
= bit
[11]; break;
330 case 13: tmplockbit
= bit
[10]; break;
331 case 14: tmplockbit
= bit
[9]; break;
332 case 15: tmplockbit
= bit
[8]; break;
336 case 19: tmplockbit
= bit2
[6]; break;
340 case 23: tmplockbit
= bit2
[5]; break;
344 case 27: tmplockbit
= bit2
[4]; break;
348 case 31: tmplockbit
= bit2
[2]; break;
352 case 35: tmplockbit
= bit2
[1]; break;
356 case 39: tmplockbit
= bit2
[0]; break;
357 case 40: tmplockbit
= bit2
[12]; break;
358 case 41: tmplockbit
= bit2
[11]; break;
359 case 42: tmplockbit
= bit2
[10]; break; //auth0
360 case 43: tmplockbit
= bit2
[9]; break; //auth1
363 PrintAndLog("Block %02x:%s [%d]", i
,sprint_hex(data
+ i
* 4, 4),tmplockbit
);
368 len
= param_getstr(Cmd
,0,filename
);
370 len
= param_getstr(Cmd
,1,filename
);
372 if (len
> FILE_PATH_SIZE
) len
= FILE_PATH_SIZE
;
374 // user supplied filename?
377 // UID = data 0-1-2 4-5-6-7 (skips a beat)
378 sprintf(fnameptr
, "%02X", data
[0]);
380 sprintf(fnameptr
, "%02X", data
[1]);
382 sprintf(fnameptr
, "%02X", data
[2]);
384 sprintf(fnameptr
, "%02X", data
[4]);
386 sprintf(fnameptr
, "%02X", data
[5]);
388 sprintf(fnameptr
, "%02X", data
[6]);
390 sprintf(fnameptr
, "%02X", data
[7]);
397 // add file extension
398 sprintf(fnameptr
, ".bin");
400 if ((fout
= fopen(filename
,"wb")) == NULL
) {
401 PrintAndLog("Could not create file name %s", filename
);
404 fwrite( data
, 1, Pages
*4, fout
);
407 PrintAndLog("Dumped %d pages, wrote %d bytes to %s", Pages
, Pages
*4, filename
);
411 // Needed to Authenticate to Ultralight C tags
412 void rol (uint8_t *data
, const size_t len
){
413 uint8_t first
= data
[0];
414 for (size_t i
= 0; i
< len
-1; i
++) {
420 //-------------------------------------------------------------------------------
421 // Ultralight C Methods
422 //-------------------------------------------------------------------------------
425 // Ultralight C Authentication Demo {currently uses hard-coded key}
427 int CmdHF14AMfucAuth(const char *Cmd
){
429 uint8_t blockNo
= 0, keyNo
= 0;
430 uint8_t e_RndB
[8] = {0x00};
432 unsigned char RndARndB
[16] = {0x00};
433 uint8_t key
[16] = {0x00};
434 DES_cblock RndA
, RndB
;
436 DES_key_schedule ks1
,ks2
;
437 DES_cblock key1
,key2
;
443 PrintAndLog("Usage: hf mfu auth k <key number>");
444 PrintAndLog(" sample: hf mfu auth k 0");
448 //Change key to user defined one
449 if (strchr(Cmd
,'k') != 0){
451 keyNo
= param_get8(Cmd
, 1);
454 memcpy(key
,key1_blnk_data
,16);
457 memcpy(key
,key2_defa_data
,16);
460 memcpy(key
,key4_nfc_data
,16);
463 memcpy(key
,key5_ones_data
,16);
466 memcpy(key
,key3_3des_data
,16);
470 memcpy(key
,key3_3des_data
,16);
473 memcpy(key2
,key
+8,8);
474 DES_set_key((DES_cblock
*)key1
,&ks1
);
475 DES_set_key((DES_cblock
*)key2
,&ks2
);
478 UsbCommand c
= {CMD_MIFAREUC_AUTH1
, {blockNo
}};
481 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
482 uint8_t isOK
= resp
.arg
[0] & 0xff;
484 uint8_t * data
= resp
.d
.asBytes
;
487 PrintAndLog("enc(RndB):%s", sprint_hex(data
+1, 8));
488 memcpy(e_RndB
,data
+1,8);
491 PrintAndLog("Command execute timeout");
495 DES_random_key(&RndA
);
496 DES_ede2_cbc_encrypt(e_RndB
,RndB
,sizeof(e_RndB
),&ks1
,&ks2
,&iv
,0);
497 PrintAndLog(" RndB:%s",sprint_hex(RndB
, 8));
498 PrintAndLog(" RndA:%s",sprint_hex(RndA
, 8));
500 memcpy(RndARndB
,RndA
,8);
501 memcpy(RndARndB
+8,RndB
,8);
502 PrintAndLog(" RA+B:%s",sprint_hex(RndARndB
, 16));
503 DES_ede2_cbc_encrypt(RndARndB
,RndARndB
,sizeof(RndARndB
),&ks1
,&ks2
,&e_RndB
,1);
504 PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB
, 16));
507 UsbCommand d
= {CMD_MIFAREUC_AUTH2
, {cuid
}};
508 memcpy(d
.d
.asBytes
,RndARndB
, 16);
512 if (WaitForResponseTimeout(CMD_ACK
,&respb
,1500)) {
513 uint8_t isOK
= respb
.arg
[0] & 0xff;
514 uint8_t * data2
= respb
.d
.asBytes
;
517 PrintAndLog("enc(RndA'):%s", sprint_hex(data2
+1, 8));
521 PrintAndLog("Command execute timeout");
527 // Ultralight C Read Single Block
529 int CmdHF14AMfUCRdBl(const char *Cmd
)
534 PrintAndLog("Usage: hf mfu ucrdbl <block number>");
535 PrintAndLog(" sample: hf mfu ucrdbl 0");
539 blockNo
= param_get8(Cmd
, 0);
540 if (blockNo
>MAX_ULTRAC_BLOCKS
){
541 PrintAndLog("Error: Maximum number of readable blocks is 44 for Ultralight Cards!");
544 PrintAndLog("--block no:%02x", (int)blockNo
);
547 UsbCommand e
= {CMD_MIFAREU_READBL
, {blockNo
}};
550 if (WaitForResponseTimeout(CMD_ACK
,&resp_c
,1500)) {
551 uint8_t isOK
= resp_c
.arg
[0] & 0xff;
552 uint8_t * data
= resp_c
.d
.asBytes
;
554 PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4));
556 PrintAndLog("isOk:%02x", isOK
);
558 PrintAndLog("Command execute timeout");
564 // Mifare Ultralight C Write Single Block
566 int CmdHF14AMfUCWrBl(const char *Cmd
){
569 bool chinese_card
= 0;
570 uint8_t bldata
[16] = {0x00};
574 PrintAndLog("Usage: hf mfu ucwrbl <block number> <block data (8 hex symbols)> [w]");
575 PrintAndLog(" sample: hf mfu uwrbl 0 01020304");
578 blockNo
= param_get8(Cmd
, 0);
579 if (blockNo
>(MAX_ULTRAC_BLOCKS
+4)){
580 PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight Cards!");
583 if (param_gethex(Cmd
, 1, bldata
, 8)) {
584 PrintAndLog("Block data must include 8 HEX symbols");
587 if (strchr(Cmd
,'w') != 0) {
593 PrintAndLog("Access Denied");
595 PrintAndLog("--specialblock no:%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");
610 PrintAndLog("Access Denied");
612 PrintAndLog("--specialblock no:%02x", blockNo
);
613 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
614 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
615 memcpy(d
.d
.asBytes
,bldata
, 4);
617 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
618 uint8_t isOK
= resp
.arg
[0] & 0xff;
619 PrintAndLog("isOk:%02x", isOK
);
621 PrintAndLog("Command execute timeout");
627 PrintAndLog("Access Denied");
629 PrintAndLog("--specialblock no:%02x", blockNo
);
630 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
631 UsbCommand c
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
632 memcpy(c
.d
.asBytes
, bldata
, 4);
634 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
635 uint8_t isOK
= resp
.arg
[0] & 0xff;
636 PrintAndLog("isOk:%02x", isOK
);
638 PrintAndLog("Command execute timeout");
643 PrintAndLog("--specialblock no:%02x", blockNo
);
644 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
645 UsbCommand d
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
646 memcpy(d
.d
.asBytes
,bldata
, 4);
648 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
649 uint8_t isOK
= resp
.arg
[0] & 0xff;
650 PrintAndLog("isOk:%02x", isOK
);
652 PrintAndLog("Command execute timeout");
656 PrintAndLog("--block no:%02x", blockNo
);
657 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));
658 UsbCommand e
= {CMD_MIFAREU_WRITEBL
, {blockNo
}};
659 memcpy(e
.d
.asBytes
,bldata
, 4);
661 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
662 uint8_t isOK
= resp
.arg
[0] & 0xff;
663 PrintAndLog("isOk:%02x", isOK
);
665 PrintAndLog("Command execute timeout");
672 //------------------------------------
674 //------------------------------------
675 static command_t CommandTable
[] =
677 {"help", CmdHelp
, 1,"This help"},
678 {"dbg", CmdHF14AMfDbg
, 0,"Set default debug mode"},
679 {"info", CmdHF14AMfUInfo
, 0,"Taginfo"},
680 {"rdbl", CmdHF14AMfURdBl
, 0,"Read block - MIFARE Ultralight"},
681 {"dump", CmdHF14AMfUDump
, 0,"Dump MIFARE Ultralight / Ultralight-C tag to binary file"},
682 {"wrbl", CmdHF14AMfUWrBl
, 0,"Write block - MIFARE Ultralight"},
683 {"crdbl", CmdHF14AMfUCRdBl
, 0,"Read block - MIFARE Ultralight C"},
684 {"cwrbl", CmdHF14AMfUCWrBl
, 0,"Write MIFARE Ultralight C block"},
685 {"cauth", CmdHF14AMfucAuth
, 0,"try a Ultralight C Authentication"},
686 {NULL
, NULL
, 0, NULL
}
689 int CmdHFMFUltra(const char *Cmd
){
690 WaitForResponseTimeout(CMD_ACK
,NULL
,100);
691 CmdsParse(CommandTable
, Cmd
);
695 int CmdHelp(const char *Cmd
){
696 CmdsHelp(CommandTable
);