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 bool getHitagUid(uint32_t *uid
, bool quiet
) {
212 // ToDo: this is for Hitag2 only (??)
214 UsbCommand c
= {CMD_READER_HITAG
, {RHT2F_UID_ONLY
}};
219 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
220 if (!quiet
) PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
224 if (resp
.arg
[0] == false) {
225 if (!quiet
) 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) == 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 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
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 RHT2F_PASSWORD
: {
288 num_to_bytes(param_get32ex(Cmd
, 1, 0, 16), 4, htd
->pwd
.password
);
290 case RHT2F_AUTHENTICATE
: {
291 num_to_bytes(param_get32ex(Cmd
, 1, 0, 16), 4, htd
->auth
.NrAr
);
292 num_to_bytes(param_get32ex(Cmd
, 2, 0, 16), 4, htd
->auth
.NrAr
+4);
295 num_to_bytes(param_get64ex(Cmd
, 1, 0, 16), 6, htd
->crypto
.key
);
296 // num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
298 case RHT2F_TEST_AUTH_ATTEMPTS
: {
299 // No additional parameters needed
301 case RHT2F_UID_ONLY
: {
302 // No additional parameters needed
305 PrintAndLog("\nError: unkown reader function %d",htf
);
307 PrintAndLog("Usage: hitag reader <Reader Function #>");
308 PrintAndLog("Reader Functions:");
309 PrintAndLog(" HitagS (0*):");
310 PrintAndLog(" 01 <nr> <ar> (Challenge) <firstPage> <tagmode> read all pages from a Hitag S tag");
311 PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all pages from a Hitag S tag");
312 PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
313 PrintAndLog(" Hitag1 (1*):");
314 PrintAndLog(" (not yet implemented)");
315 PrintAndLog(" Hitag2 (2*):");
316 PrintAndLog(" 21 <password> (password mode)");
317 PrintAndLog(" 22 <nr> <ar> (authentication)");
318 PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
319 PrintAndLog(" 25 (test recorded authentications)");
320 PrintAndLog(" 26 just read UID");
325 // Copy the hitag2 function into the first argument
328 // Send the command to the proxmark
329 clearCommandBuffer();
333 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4000)) {
334 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
338 // Check the return status, stored in the first argument
339 if (resp
.arg
[0] == false) {
340 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag failed");
344 uint32_t id
= bytes_to_num(resp
.d
.asBytes
, 4);
346 PrintAndLog("Valid Hitag2 tag found - UID: %08x", id
);
347 if (htf
!= RHT2F_UID_ONLY
) {
348 PrintAndLogEx(SUCCESS
, "Dumping tag memory...");
352 sprintf(filename
,"%08x_%04x.ht2",id
,(rand() & 0xffff));
353 if ((pf
= fopen(filename
,"wb")) == NULL
) {
354 PrintAndLog("Error: Could not open file [%s]",filename
);
358 // Write the 48 tag memory bytes to file and finalize
359 fwrite(resp
.d
.asBytes
,1,48,pf
);
362 PrintAndLog("Succesfully saved tag memory to [%s]",filename
);
369 static int CmdLFHitagSimS(const char *Cmd
) {
370 UsbCommand c
= { CMD_SIMULATE_HITAG_S
};
371 char filename
[FILE_PATH_SIZE
] = { 0x00 };
373 bool tag_mem_supplied
;
374 int len
= strlen(Cmd
);
375 if (len
> FILE_PATH_SIZE
)
376 len
= FILE_PATH_SIZE
;
377 memcpy(filename
, Cmd
, len
);
379 if (strlen(filename
) > 0) {
380 if ((pf
= fopen(filename
, "rb+")) == NULL
) {
381 PrintAndLog("Error: Could not open file [%s]", filename
);
384 tag_mem_supplied
= true;
385 if (fread(c
.d
.asBytes
, 1, 4*64, pf
) != 4*64) {
386 PrintAndLog("Error: File reading error");
392 tag_mem_supplied
= false;
395 // Does the tag comes with memory
396 c
.arg
[0] = (uint32_t) tag_mem_supplied
;
403 static int CmdLFHitagCheckChallenges(const char *Cmd
) {
404 UsbCommand c
= { CMD_TEST_HITAGS_TRACES
};
405 char filename
[FILE_PATH_SIZE
] = { 0x00 };
408 int len
= strlen(Cmd
);
409 if (len
> FILE_PATH_SIZE
) len
= FILE_PATH_SIZE
;
410 memcpy(filename
, Cmd
, len
);
412 if (strlen(filename
) > 0) {
413 if ((pf
= fopen(filename
,"rb+")) == NULL
) {
414 PrintAndLog("Error: Could not open file [%s]",filename
);
418 if (fread(c
.d
.asBytes
,1,8*60,pf
) != 8*60) {
419 PrintAndLog("Error: File reading error");
428 //file with all the challenges to try
429 c
.arg
[0] = (uint32_t)file_given
;
430 c
.arg
[1] = param_get64ex(Cmd
,2,0,0); //get mode
437 static int CmdLFHitagWriter(const char *Cmd
) {
438 UsbCommand c
= { CMD_WR_HITAG_S
};
439 hitag_data
* htd
= (hitag_data
*)c
.d
.asBytes
;
440 hitag_function htf
= param_get32ex(Cmd
,0,0,10);
442 case WHTSF_CHALLENGE
: {
443 num_to_bytes(param_get64ex(Cmd
,1,0,16),8,htd
->auth
.NrAr
);
444 c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10);
445 num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->auth
.data
);
449 num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
);
450 c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10);
451 num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->crypto
.data
);
453 case WHT2F_PASSWORD
: {
454 num_to_bytes(param_get64ex(Cmd
, 1, 0, 16), 4, htd
->pwd
.password
);
455 c
.arg
[2] = param_get32ex(Cmd
, 2, 0, 10);
456 num_to_bytes(param_get32ex(Cmd
, 3, 0, 16), 4, htd
->crypto
.data
);
459 PrintAndLog("Error: unkown writer function %d",htf
);
460 PrintAndLog("Hitag writer functions");
461 PrintAndLog(" HitagS (0*):");
462 PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
463 PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
464 PrintAndLog(" Hitag1 (1*)");
465 PrintAndLog(" (not yet implemented)");
466 PrintAndLog(" Hitag2 (2*):");
467 PrintAndLog(" 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
468 PrintAndLog(" 27 <password> <page> <byte0...byte3> write page on a Hitag2 tag");
472 // Copy the hitag function into the first argument
475 // Send the command to the proxmark
479 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4000)) {
480 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
484 // Check the return status, stored in the first argument
485 if (resp
.arg
[0] == false) {
486 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag write failed");
493 static int CmdHelp(const char *Cmd
);
495 static command_t CommandTable
[] =
497 {"help", CmdHelp
, 1, "This help"},
498 {"list", CmdLFHitagList
, 0, "<outfile> List Hitag trace history"},
499 {"info", CmdLFHitagInfo
, 0, "Tag information" },
500 {"reader", CmdLFHitagReader
, 0, "Act like a Hitag Reader"},
501 {"sim", CmdLFHitagSim
, 0, "Simulate Hitag transponder"},
502 {"snoop", CmdLFHitagSnoop
, 0, "Eavesdrop Hitag communication"},
503 {"writer", CmdLFHitagWriter
, 0, "Act like a Hitag Writer" },
504 {"simS", CmdLFHitagSimS
, 0, "Simulate HitagS transponder" },
505 {"checkChallenges", CmdLFHitagCheckChallenges
, 0, "Test challenges from a file" },
506 { NULL
, NULL
, 0, NULL
}
510 static int CmdHelp(const char *Cmd
) {
511 CmdsHelp(CommandTable
);
516 int CmdLFHitag(const char *Cmd
) {
517 CmdsParse(CommandTable
, Cmd
);