1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2012 Roel Verdult
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 // Low frequency Hitag support
9 //-----------------------------------------------------------------------------
11 #include "cmdlfhitag.h"
18 #include "cmdparser.h"
25 static size_t nbytes(size_t nbits
) {
26 return (nbits
/8) + ((nbits
%8)>0);
30 static int CmdLFHitagList(const char *Cmd
) {
31 uint8_t *got
= malloc(USB_CMD_DATA_SIZE
);
32 // Query for the actual size of the trace
34 GetFromBigBuf(got
, USB_CMD_DATA_SIZE
, 0, &response
, -1, false);
35 uint16_t traceLen
= response
.arg
[2];
36 if (traceLen
> USB_CMD_DATA_SIZE
) {
37 uint8_t *p
= realloc(got
, traceLen
);
39 PrintAndLog("Cannot allocate memory for trace");
44 GetFromBigBuf(got
, traceLen
, 0, NULL
, -1, false);
47 PrintAndLog("recorded activity (TraceLen = %d bytes):");
48 PrintAndLog(" ETU :nbits: who bytes");
49 PrintAndLog("---------+-----+----+-----------");
54 int len
= strlen(Cmd
);
56 char filename
[FILE_PATH_SIZE
] = { 0x00 };
59 if (len
> FILE_PATH_SIZE
)
61 memcpy(filename
, Cmd
, len
);
63 if (strlen(filename
) > 0) {
64 if ((pf
= fopen(filename
,"wb")) == NULL
) {
65 PrintAndLog("Error: Could not open file [%s]",filename
);
73 if(i
> traceLen
) { break; }
76 int timestamp
= *((uint32_t *)(got
+i
));
77 if (timestamp
& 0x80000000) {
78 timestamp
&= 0x7fffffff;
84 int parityBits
= *((uint32_t *)(got
+i
+4));
85 // 4 bytes of additional information...
86 // maximum of 32 additional parity bit information
89 // at each quarter bit period we can send power level (16 levels)
90 // or each half bit period in 256 levels.
93 int len
= nbytes(bits
);
98 if (i
+ len
> traceLen
) { break;}
100 uint8_t *frame
= (got
+i
+9);
102 int fillupBits = 8 - (bits % 8);
103 byte_t framefilled[bits+fillupBits];
104 byte_t* ff = framefilled;
106 int response_bit[200] = {0};
108 for (int y = 0; y < len; y++) {
109 for (j = 0; j < 8; j++) {
111 if ((frame[y] & ((mask << 7) >> j)) != 0)
117 for (int y = 0; y < len; y++) {
118 ff[y] = (response_bit[z] << 7) | (response_bit[z + 1] << 6)
119 | (response_bit[z + 2] << 5) | (response_bit[z + 3] << 4)
120 | (response_bit[z + 4] << 3) | (response_bit[z + 5] << 2)
121 | (response_bit[z + 6] << 1) | response_bit[z + 7];
129 // Break and stick with current result if buffer was not completely full
130 if (frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; }
132 char line
[1000] = "";
133 for (j
= 0; j
< len
; j
++) {
134 //if((parityBits >> (len - j - 1)) & 0x01) {
135 if (isResponse
&& (oddparity8(frame
[j
]) != ((parityBits
>> (len
- j
- 1)) & 0x01))) {
136 sprintf(line
+(j
*4), "%02x! ", frame
[j
]);
138 sprintf(line
+(j
*4), "%02x ", frame
[j
]);
142 PrintAndLog(" +%7d: %3d: %s %s",
143 (prev
< 0 ? 0 : (timestamp
- prev
)),
145 (isResponse
? "TAG" : " "),
149 fprintf(pf
," +%7d: %3d: %s %s\n",
150 (prev
< 0 ? 0 : (timestamp
- prev
)),
152 (isResponse
? "TAG" : " "),
162 PrintAndLog("Recorded activity succesfully written to file: %s", filename
);
170 static int CmdLFHitagSnoop(const char *Cmd
) {
171 UsbCommand c
= {CMD_SNOOP_HITAG
};
177 static int CmdLFHitagSim(const char *Cmd
) {
179 UsbCommand c
= {CMD_SIMULATE_HITAG
};
180 char filename
[FILE_PATH_SIZE
] = { 0x00 };
182 bool tag_mem_supplied
;
183 int len
= strlen(Cmd
);
184 if (len
> FILE_PATH_SIZE
) len
= FILE_PATH_SIZE
;
185 memcpy(filename
, Cmd
, len
);
187 if (strlen(filename
) > 0) {
188 if ((pf
= fopen(filename
,"rb+")) == NULL
) {
189 PrintAndLog("Error: Could not open file [%s]",filename
);
192 tag_mem_supplied
= true;
193 if (fread(c
.d
.asBytes
,1,48,pf
) != 48) {
194 PrintAndLog("Error: File reading error");
200 tag_mem_supplied
= false;
203 // Does the tag comes with memory
204 c
.arg
[0] = (uint32_t)tag_mem_supplied
;
211 static bool getHitagUid(uint32_t *uid
) {
212 // ToDo: this is for Hitag2 only (??)
214 UsbCommand c
= {CMD_READER_HITAG
, {RHT2F_UID_ONLY
}};
219 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
220 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
224 if (resp
.arg
[0] == false) {
225 PrintAndLogEx(DEBUG
, "DEBUG: Error - failed getting UID");
230 *uid
= bytes_to_num(resp
.d
.asBytes
, 4);
236 static int CmdLFHitagInfo(const char *Cmd
) {
237 char ctmp
= param_getchar(Cmd
, 0);
239 PrintAndLog("Usage: lf hitag info [h]");
240 PrintAndLog("Options:");
241 PrintAndLog(" h This help");
242 PrintAndLog("Examples:");
243 PrintAndLog(" lf hitag info");
249 if (getHitagUid(&uid
) == false)
252 PrintAndLogEx(SUCCESS
, "UID: %08X", uid
);
254 // how to detemine Hitag types?
255 // read block3, get configuration byte.
256 // PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!"));
258 // common configurations.
259 // printHitagConfiguration(0x06);
260 //printHitagConfiguration( 0x0E );
261 //printHitagConfiguration( 0x02 );
262 //printHitagConfiguration( 0x00 );
263 //printHitagConfiguration( 0x04 );
268 int CmdLFHitagReader(const char *Cmd
) {
269 UsbCommand c
= {CMD_READER_HITAG
};
270 hitag_data
* htd
= (hitag_data
*)c
.d
.asBytes
;
271 hitag_function htf
= param_get32ex(Cmd
, 0, 0, 10);
274 case 01: { //RHTSF_CHALLENGE
275 c
= (UsbCommand
){ CMD_READ_HITAG_S
};
276 num_to_bytes(param_get32ex(Cmd
, 1, 0, 16), 4, htd
->auth
.NrAr
);
277 num_to_bytes(param_get32ex(Cmd
, 2, 0, 16), 4, htd
->auth
.NrAr
+4);
278 c
.arg
[1] = param_get64ex(Cmd
, 3, 0, 0); //firstpage
279 c
.arg
[2] = param_get64ex(Cmd
, 4, 0, 0); //tag mode
281 case 02: { //RHTSF_KEY
282 c
= (UsbCommand
){ CMD_READ_HITAG_S
};
283 num_to_bytes(param_get64ex(Cmd
, 1, 0, 16), 6, htd
->crypto
.key
);
284 c
.arg
[1] = param_get64ex(Cmd
, 2, 0, 0); //firstpage
285 c
.arg
[2] = param_get64ex(Cmd
, 3, 0, 0); //tag mode
287 case 03: { //RHTSF_CHALLENGE BLOCK
288 c
= (UsbCommand
){ CMD_READ_HITAG_S_BLK
};
289 num_to_bytes(param_get32ex(Cmd
, 1, 0, 16), 4, htd
->auth
.NrAr
);
290 num_to_bytes(param_get32ex(Cmd
, 2, 0, 16), 4, htd
->auth
.NrAr
+4);
291 c
.arg
[1] = param_get64ex(Cmd
, 3, 0, 0); //firstpage
292 c
.arg
[2] = param_get64ex(Cmd
, 4, 0, 0); //tag mode
294 case 04: { //RHTSF_KEY BLOCK
295 c
= (UsbCommand
){ CMD_READ_HITAG_S_BLK
};
296 num_to_bytes(param_get64ex(Cmd
, 1, 0, 16), 6, htd
->crypto
.key
);
297 c
.arg
[1] = param_get64ex(Cmd
, 2, 0, 0); //firstpage
298 c
.arg
[2] = param_get64ex(Cmd
, 3, 0, 0); //tag mode
300 case RHT2F_PASSWORD
: {
301 num_to_bytes(param_get32ex(Cmd
, 1, 0, 16), 4, htd
->pwd
.password
);
303 case RHT2F_AUTHENTICATE
: {
304 num_to_bytes(param_get32ex(Cmd
, 1, 0, 16), 4, htd
->auth
.NrAr
);
305 num_to_bytes(param_get32ex(Cmd
, 2, 0, 16), 4, htd
->auth
.NrAr
+4);
308 num_to_bytes(param_get64ex(Cmd
, 1, 0, 16), 6, htd
->crypto
.key
);
309 // num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
311 case RHT2F_TEST_AUTH_ATTEMPTS
: {
312 // No additional parameters needed
314 case RHT2F_UID_ONLY
: {
315 // No additional parameters needed
318 PrintAndLog("\nError: unkown reader function %d",htf
);
320 PrintAndLog("Usage: hitag reader <Reader Function #>");
321 PrintAndLog("Reader Functions:");
322 PrintAndLog(" HitagS (0*):");
323 PrintAndLog(" 01 <nr> <ar> (Challenge) <firstPage> <tagmode> read all pages from a Hitag S tag");
324 PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all pages from a Hitag S tag");
325 PrintAndLog(" 03 <nr> <ar> (Challenge) <firstPage> <tagmode> read all blocks from a Hitag S tag");
326 PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all blocks from a Hitag S tag");
327 PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
328 PrintAndLog(" Hitag1 (1*):");
329 PrintAndLog(" (not yet implemented)");
330 PrintAndLog(" Hitag2 (2*):");
331 PrintAndLog(" 21 <password> (password mode)");
332 PrintAndLog(" 22 <nr> <ar> (authentication)");
333 PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
334 PrintAndLog(" 25 (test recorded authentications)");
335 PrintAndLog(" 26 just read UID");
340 // Copy the hitag2 function into the first argument
343 // Send the command to the proxmark
344 clearCommandBuffer();
348 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4000)) {
349 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
353 // Check the return status, stored in the first argument
354 if (resp
.arg
[0] == false) {
355 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag failed");
359 uint32_t id
= bytes_to_num(resp
.d
.asBytes
,4);
361 if (htf
== RHT2F_UID_ONLY
){
362 PrintAndLog("Valid Hitag2 tag found - UID: %08x",id
);
367 sprintf(filename
,"%08x_%04x.ht2",id
,(rand() & 0xffff));
368 if ((pf
= fopen(filename
,"wb")) == NULL
) {
369 PrintAndLog("Error: Could not open file [%s]",filename
);
373 // Write the 48 tag memory bytes to file and finalize
374 fwrite(resp
.d
.asBytes
,1,48,pf
);
377 PrintAndLog("Succesfully saved tag memory to [%s]",filename
);
384 static int CmdLFHitagSimS(const char *Cmd
) {
385 UsbCommand c
= { CMD_SIMULATE_HITAG_S
};
386 char filename
[FILE_PATH_SIZE
] = { 0x00 };
388 bool tag_mem_supplied
;
389 int len
= strlen(Cmd
);
390 if (len
> FILE_PATH_SIZE
)
391 len
= FILE_PATH_SIZE
;
392 memcpy(filename
, Cmd
, len
);
394 if (strlen(filename
) > 0) {
395 if ((pf
= fopen(filename
, "rb+")) == NULL
) {
396 PrintAndLog("Error: Could not open file [%s]", filename
);
399 tag_mem_supplied
= true;
400 if (fread(c
.d
.asBytes
, 1, 4*64, pf
) != 4*64) {
401 PrintAndLog("Error: File reading error");
407 tag_mem_supplied
= false;
410 // Does the tag comes with memory
411 c
.arg
[0] = (uint32_t) tag_mem_supplied
;
418 static int CmdLFHitagCheckChallenges(const char *Cmd
) {
419 UsbCommand c
= { CMD_TEST_HITAGS_TRACES
};
420 char filename
[FILE_PATH_SIZE
] = { 0x00 };
423 int len
= strlen(Cmd
);
424 if (len
> FILE_PATH_SIZE
) len
= FILE_PATH_SIZE
;
425 memcpy(filename
, Cmd
, len
);
427 if (strlen(filename
) > 0) {
428 if ((pf
= fopen(filename
,"rb+")) == NULL
) {
429 PrintAndLog("Error: Could not open file [%s]",filename
);
433 if (fread(c
.d
.asBytes
,1,8*60,pf
) != 8*60) {
434 PrintAndLog("Error: File reading error");
443 //file with all the challenges to try
444 c
.arg
[0] = (uint32_t)file_given
;
445 c
.arg
[1] = param_get64ex(Cmd
,2,0,0); //get mode
452 static int CmdLFHitagWriter(const char *Cmd
) {
453 UsbCommand c
= { CMD_WR_HITAG_S
};
454 hitag_data
* htd
= (hitag_data
*)c
.d
.asBytes
;
455 hitag_function htf
= param_get32ex(Cmd
,0,0,10);
457 case WHTSF_CHALLENGE
: {
458 num_to_bytes(param_get64ex(Cmd
,1,0,16),8,htd
->auth
.NrAr
);
459 c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10);
460 num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->auth
.data
);
464 num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
);
465 c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10);
466 num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->crypto
.data
);
468 case WHT2F_PASSWORD
: {
469 num_to_bytes(param_get64ex(Cmd
, 1, 0, 16), 4, htd
->pwd
.password
);
470 c
.arg
[2] = param_get32ex(Cmd
, 2, 0, 10);
471 num_to_bytes(param_get32ex(Cmd
, 3, 0, 16), 4, htd
->crypto
.data
);
474 PrintAndLog("Error: unkown writer function %d",htf
);
475 PrintAndLog("Hitag writer functions");
476 PrintAndLog(" HitagS (0*):");
477 PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
478 PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
479 PrintAndLog(" Hitag1 (1*)");
480 PrintAndLog(" (not yet implemented)");
481 PrintAndLog(" Hitag2 (2*):");
482 PrintAndLog(" 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
483 PrintAndLog(" 27 <password> <page> <byte0...byte3> write page on a Hitag2 tag");
487 // Copy the hitag function into the first argument
490 // Send the command to the proxmark
494 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4000)) {
495 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
499 // Check the return status, stored in the first argument
500 if (resp
.arg
[0] == false) {
501 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag write failed");
508 static int CmdHelp(const char *Cmd
);
510 static command_t CommandTable
[] =
512 {"help", CmdHelp
, 1, "This help"},
513 {"list", CmdLFHitagList
, 0, "<outfile> List Hitag trace history"},
514 {"info", CmdLFHitagInfo
, 0, "Tag information" },
515 {"reader", CmdLFHitagReader
, 0, "Act like a Hitag Reader"},
516 {"sim", CmdLFHitagSim
, 0, "Simulate Hitag transponder"},
517 {"snoop", CmdLFHitagSnoop
, 0, "Eavesdrop Hitag communication"},
518 {"writer", CmdLFHitagWriter
, 0, "Act like a Hitag Writer" },
519 {"simS", CmdLFHitagSimS
, 0, "Simulate HitagS transponder" },
520 {"checkChallenges", CmdLFHitagCheckChallenges
, 0, "Test challenges from a file" },
521 { NULL
, NULL
, 0, NULL
}
525 static int CmdHelp(const char *Cmd
) {
526 CmdsHelp(CommandTable
);
531 int CmdLFHitag(const char *Cmd
) {
532 CmdsParse(CommandTable
, Cmd
);