From 369db7c9d7fa0459fcc184efb4a09bb56bcb4bd3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 27 May 2024 20:29:02 +0200 Subject: [PATCH] style --- armsrc/dbprint.c | 5 +- armsrc/em4x50.c | 2 +- armsrc/em4x70.c | 82 ++++++++++++++++----------------- armsrc/hitag2_crack.c | 10 ++-- armsrc/hitagS.c | 2 +- armsrc/lfsampling.c | 2 +- client/src/cmddata.c | 4 +- client/src/cmdlfem4x70.c | 10 ++-- client/src/cmdlfhitag.c | 10 ++-- client/src/cmdtrace.c | 2 +- client/src/graph.c | 8 ++-- client/src/pm3line_vocabulary.h | 2 + doc/commands.json | 45 +++++++++++++++--- doc/commands.md | 2 + 14 files changed, 112 insertions(+), 74 deletions(-) diff --git a/armsrc/dbprint.c b/armsrc/dbprint.c index 4c58ccbddc..903adf872a 100644 --- a/armsrc/dbprint.c +++ b/armsrc/dbprint.c @@ -101,9 +101,10 @@ void Dbhexdump(int len, const uint8_t *d, bool bAsci) { d += 16; } #endif -}void print_result(const char *name, const uint8_t *d, size_t +} +void print_result(const char *name, const uint8_t *d, size_t - n) { + n) { const uint8_t *p = d; uint16_t tmp = n & 0xFFF0; diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 9d4d2648df..952c39a304 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -1257,7 +1257,7 @@ static int em4x50_sim_read_bit(void) { // wait 16 cycles to make sure there is no field when reading a "0" bit uint32_t waitval = GetTicks(); - while(GetTicks() - waitval < EM4X50_T_TAG_QUARTER_PERIOD * CYCLES2TICKS); + while (GetTicks() - waitval < EM4X50_T_TAG_QUARTER_PERIOD * CYCLES2TICKS); while (cycles < EM4X50_T_TAG_THREE_QUARTER_PERIOD) { diff --git a/armsrc/em4x70.c b/armsrc/em4x70.c index 6f962fe403..2f92dfbf1c 100644 --- a/armsrc/em4x70.c +++ b/armsrc/em4x70.c @@ -32,47 +32,47 @@ static bool command_parity = true; #if 1 // Calculation of ticks for timing functions - // Conversion from Ticks to RF periods - // 1 us = 1.5 ticks - // 1RF Period = 8us = 12 Ticks - #define TICKS_PER_FC 12 - - // Chip timing from datasheet - // Converted into Ticks for timing functions - #define EM4X70_T_TAG_QUARTER_PERIOD (8 * TICKS_PER_FC) - #define EM4X70_T_TAG_HALF_PERIOD (16 * TICKS_PER_FC) - #define EM4X70_T_TAG_THREE_QUARTER_PERIOD (24 * TICKS_PER_FC) - #define EM4X70_T_TAG_FULL_PERIOD (32 * TICKS_PER_FC) // 1 Bit Period - #define EM4X70_T_TAG_TWA (128 * TICKS_PER_FC) // Write Access Time - #define EM4X70_T_TAG_DIV (224 * TICKS_PER_FC) // Divergency Time - #define EM4X70_T_TAG_AUTH (4224 * TICKS_PER_FC) // Authentication Time - #define EM4X70_T_TAG_WEE (3072 * TICKS_PER_FC) // EEPROM write Time - #define EM4X70_T_TAG_TWALB (672 * TICKS_PER_FC) // Write Access Time of Lock Bits - #define EM4X70_T_TAG_BITMOD (4 * TICKS_PER_FC) // Initial time to stop modulation when sending 0 - #define EM4X70_T_TAG_TOLERANCE (8 * TICKS_PER_FC) // Tolerance in RF periods for receive/LIW - - #define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this - #define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window - #define EM4X70_T_READ_HEADER_LEN 16 // Read header length (16 bit periods) - - #define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command - #define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command +// Conversion from Ticks to RF periods +// 1 us = 1.5 ticks +// 1RF Period = 8us = 12 Ticks +#define TICKS_PER_FC 12 + +// Chip timing from datasheet +// Converted into Ticks for timing functions +#define EM4X70_T_TAG_QUARTER_PERIOD (8 * TICKS_PER_FC) +#define EM4X70_T_TAG_HALF_PERIOD (16 * TICKS_PER_FC) +#define EM4X70_T_TAG_THREE_QUARTER_PERIOD (24 * TICKS_PER_FC) +#define EM4X70_T_TAG_FULL_PERIOD (32 * TICKS_PER_FC) // 1 Bit Period +#define EM4X70_T_TAG_TWA (128 * TICKS_PER_FC) // Write Access Time +#define EM4X70_T_TAG_DIV (224 * TICKS_PER_FC) // Divergency Time +#define EM4X70_T_TAG_AUTH (4224 * TICKS_PER_FC) // Authentication Time +#define EM4X70_T_TAG_WEE (3072 * TICKS_PER_FC) // EEPROM write Time +#define EM4X70_T_TAG_TWALB (672 * TICKS_PER_FC) // Write Access Time of Lock Bits +#define EM4X70_T_TAG_BITMOD (4 * TICKS_PER_FC) // Initial time to stop modulation when sending 0 +#define EM4X70_T_TAG_TOLERANCE (8 * TICKS_PER_FC) // Tolerance in RF periods for receive/LIW + +#define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this +#define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window +#define EM4X70_T_READ_HEADER_LEN 16 // Read header length (16 bit periods) + +#define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command +#define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command #endif // Calculation of ticks for timing functions #if 1 // EM4x70 Command IDs - /** - * These IDs are from the EM4170 datasheet. - * Some versions of the chip require a - * (even) parity bit, others do not. - * The command is thus stored only in the - * three least significant bits (mask 0x07). - */ - #define EM4X70_COMMAND_ID 0x01 - #define EM4X70_COMMAND_UM1 0x02 - #define EM4X70_COMMAND_AUTH 0x03 - #define EM4X70_COMMAND_PIN 0x04 - #define EM4X70_COMMAND_WRITE 0x05 - #define EM4X70_COMMAND_UM2 0x07 +/** + * These IDs are from the EM4170 datasheet. + * Some versions of the chip require a + * (even) parity bit, others do not. + * The command is thus stored only in the + * three least significant bits (mask 0x07). + */ +#define EM4X70_COMMAND_ID 0x01 +#define EM4X70_COMMAND_UM1 0x02 +#define EM4X70_COMMAND_AUTH 0x03 +#define EM4X70_COMMAND_PIN 0x04 +#define EM4X70_COMMAND_WRITE 0x05 +#define EM4X70_COMMAND_UM2 0x07 #endif // EM4x70 Command IDs // Constants used to determine high/low state of signal @@ -309,7 +309,7 @@ static bool check_ack(void) { // ACK 64 + 64 // NAK 64 + 48 if (check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD) && - check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) { + check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) { // ACK return true; } @@ -549,8 +549,8 @@ static bool find_listen_window(bool command) { return false; } -// *bits == array of bytes, each byte storing a single bit. -// *out == array of bytes, storing converted bits --> bytes. +// *bits == array of bytes, each byte storing a single bit. +// *out == array of bytes, storing converted bits --> bytes. // // [in, bcount(count_of_bits) ] const uint8_t *bits // [out, bcount(count_of_bits/8)] uint8_t *out diff --git a/armsrc/hitag2_crack.c b/armsrc/hitag2_crack.c index ed71e8ad5b..e5dea8a641 100644 --- a/armsrc/hitag2_crack.c +++ b/armsrc/hitag2_crack.c @@ -380,7 +380,7 @@ void ht2_crack2(uint8_t *nrar_hex) { // We got 42 bits of keystream in c2->keybits. // using the 40 bits of keystream in keybits, sending commands with ever - // increasing lengths to acquire 2048 bits of key stream. + // increasing lengths to acquire 2048 bits of key stream. int kslen = 40; int res = PM3_SUCCESS; @@ -409,17 +409,17 @@ void ht2_crack2(uint8_t *nrar_hex) { uint8_t resp[4] = {0}; res = ht2_tx_rx(c2->e_ext_cmd, kslen, resp, &n, true, false); if (res != PM3_SUCCESS) { - Dbprintf("tx/rx failed, got %zu (res... %i)", n, res); + Dbprintf("tx/rx failed, got %zu (res... %i)", n, res); break; } - // convert response to binarray + // convert response to binarray hex2binarray_n((char *)e_response, (char *)resp, 4); // recover keystream from encrypted response hitag2crack_xor(c2->keybits + kslen, e_response, c2->uid, 32); - // extented with 30 bits or 3 * 10 read_p0_cmds + // extented with 30 bits or 3 * 10 read_p0_cmds hitag2crack_xor(c2->e_ext_cmd + kslen, read_p0_cmd, c2->keybits + kslen, 10); kslen += 10; hitag2crack_xor(c2->e_ext_cmd + kslen, read_p0_cmd, c2->keybits + kslen, 10); @@ -437,5 +437,5 @@ void ht2_crack2(uint8_t *nrar_hex) { reply_ng(CMD_LF_HITAG2_CRACK_2, res, (uint8_t *)packet, sizeof(lf_hitag_crack_response_t)); BigBuf_free(); - return; + return; } diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index f80c350d05..c17756d059 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1090,7 +1090,7 @@ static void hitagS_receive_frame(uint8_t *rx, size_t sizeofrx, size_t *rxlen, ui // Dbprintf("RX0 %i:%02X.. err:%i resptime:%i", *rxlen, rx[0], errorCount, *resptime); } -static void sendReceiveHitagS( const uint8_t *tx, size_t txlen, uint8_t *rx, size_t sizeofrx, size_t *prxbits, int t_wait, bool ledcontrol, bool ac_seq) { +static void sendReceiveHitagS(const uint8_t *tx, size_t txlen, uint8_t *rx, size_t sizeofrx, size_t *prxbits, int t_wait, bool ledcontrol, bool ac_seq) { LogTraceBits(tx, txlen, HITAG_T_WAIT_2, HITAG_T_WAIT_2, true); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 8325bbed18..88787b4e12 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -538,7 +538,7 @@ int ReadLF_realtime(bool reader_field) { return_value = async_usb_write_stop(); -out: +out: LED_D_OFF(); // DoAcquisition() end diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 14144c77c5..1ce0aadef0 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -3683,7 +3683,7 @@ static int CmdTestSaveState8(const char *Cmd) { size_t length = (rand() % 256); PrintAndLogEx(DEBUG, "Testing with length = %llu", length); - uint8_t *srcBuffer = (uint8_t*)calloc(length + 1, sizeof(uint8_t)); + uint8_t *srcBuffer = (uint8_t *)calloc(length + 1, sizeof(uint8_t)); //Set up the source buffer with random data for (int i = 0; i < length; i++) { @@ -3706,7 +3706,7 @@ static int CmdTestSaveState8(const char *Cmd) { } else { PrintAndLogEx(DEBUG, _GREEN_("Lengths match!") "\n"); } - + for (size_t i = 0; i < returnedLength; i++) { if (srcBuffer[i] != destBuffer[i]) { PrintAndLogEx(FAILED, "Buffers don't match at index %lu!, Expected %i, got %i", i, srcBuffer[i], destBuffer[i]); diff --git a/client/src/cmdlfem4x70.c b/client/src/cmdlfem4x70.c index 181dbc734e..cffac044d7 100644 --- a/client/src/cmdlfem4x70.c +++ b/client/src/cmdlfem4x70.c @@ -545,7 +545,7 @@ static int CmdEM4x70Brute(const char *Cmd) { "lf em 4x70 brute -b 9 --rnd 45F54ADA252AAC --frn 4866BB70 --> bruteforcing key bits k95...k80 (pm3 test key)\n" "lf em 4x70 brute -b 8 --rnd 3FFE1FB6CC513F --frn F355F1A0 --> bruteforcing key bits k79...k64 (research paper key)\n" "lf em 4x70 brute -b 7 --rnd 7D5167003571F8 --frn 982DBCC0 --> bruteforcing key bits k63...k48 (autorecovery test key)\n" - ); + ); void *argtable[] = { arg_param_begin, arg_lit0(NULL, "par", "Add parity bit when sending commands"), @@ -1505,22 +1505,22 @@ static int CmdEM4x70Calc(const char *Cmd) { opts.key.k[ 0], opts.key.k[ 1], opts.key.k[ 2], opts.key.k[ 3], opts.key.k[ 4], opts.key.k[ 5], opts.key.k[ 6], opts.key.k[ 7], opts.key.k[ 8], opts.key.k[ 9], opts.key.k[10], opts.key.k[11] - ); + ); snprintf( rnd_string, 15, "%02X%02X%02X%02X%02X%02X%02X", opts.rn.rn[0], opts.rn.rn[1], opts.rn.rn[2], opts.rn.rn[3], opts.rn.rn[4], opts.rn.rn[5], opts.rn.rn[6] - ); + ); snprintf( frn_string, 9, "%02X%02X%02X%02X", data.frn.frn[0], data.frn.frn[1], data.frn.frn[2], data.frn.frn[3] - ); + ); snprintf( grn_string, 7, "%02X%02X%02X", data.grn.grn[0], data.grn.grn[1], data.grn.grn[2] - ); + ); } PrintAndLogEx(SUCCESS, "KEY: %s RND: %s FRN: " _GREEN_("%s") " GRN: " _GREEN_("%s"), key_string, rnd_string, frn_string, grn_string); return PM3_SUCCESS; diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 1d79fb68fb..1705bf50f8 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -766,7 +766,7 @@ void annotateHitag2(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, void annotateHitagS(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response) { } -static const char* identify_transponder_hitag2(uint32_t uid) { +static const char *identify_transponder_hitag2(uint32_t uid) { switch (uid) { case 0x53505910: @@ -858,10 +858,10 @@ static int CmdLFHitagInfo(const char *Cmd) { static int CmdLFHitagReader(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf hitag reader", - "Act as a Hitag2 reader. Look for Hitag2 tags until Enter or the pm3 button is pressed\n", - "lf hitag reader\n" - "lf hitag reader -@ -> Continuous mode" - ); + "Act as a Hitag2 reader. Look for Hitag2 tags until Enter or the pm3 button is pressed\n", + "lf hitag reader\n" + "lf hitag reader -@ -> Continuous mode" + ); void *argtable[] = { arg_param_begin, diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index b4191c94d6..da83821180 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -646,7 +646,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr // handle partial bytes. The parity array[0] is used to store number of left over bits from NBYTES // This part prints the number of bits in the trace entry for hitag. uint8_t nbits = parityBytes[0]; - + // only apply this to lesser than one byte if (data_len == 1) { diff --git a/client/src/graph.c b/client/src/graph.c index 50b31abf1b..bf5a042c01 100644 --- a/client/src/graph.c +++ b/client/src/graph.c @@ -613,13 +613,13 @@ size_t restore_buffer8(buffer_savestate_t saveState, uint8_t *dest) { // Unpack the array for (size_t i = 0; i < saveState.bufferSize; i++) { dest[index++] = saveState.buffer[i]; - if(index == length) break; + if (index == length) break; dest[index++] = (saveState.buffer[i] >> 8) & 0xFF; - if(index == length) break; + if (index == length) break; dest[index++] = (saveState.buffer[i] >> 16) & 0xFF; - if(index == length) break; + if (index == length) break; dest[index++] = (saveState.buffer[i] >> 24) & 0xFF; - if(index == length) break; + if (index == length) break; } return index; diff --git a/client/src/pm3line_vocabulary.h b/client/src/pm3line_vocabulary.h index 2cb832da45..9ab543d4a2 100644 --- a/client/src/pm3line_vocabulary.h +++ b/client/src/pm3line_vocabulary.h @@ -623,6 +623,7 @@ const static vocabulary_t vocabulary[] = { { 0, "lf em 4x70 auth" }, { 0, "lf em 4x70 setpin" }, { 0, "lf em 4x70 setkey" }, + { 1, "lf em 4x70 calc" }, { 1, "lf em 4x70 recover" }, { 0, "lf em 4x70 autorecover" }, { 1, "lf fdxb help" }, @@ -650,6 +651,7 @@ const static vocabulary_t vocabulary[] = { { 1, "lf hitag help" }, { 1, "lf hitag list" }, { 0, "lf hitag info" }, + { 0, "lf hitag reader" }, { 1, "lf hitag test" }, { 0, "lf hitag dump" }, { 0, "lf hitag read" }, diff --git a/doc/commands.json b/doc/commands.json index 1cf347b1d0..90890ad220 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -9016,11 +9016,29 @@ ], "usage": "lf em 4x70 autorecover [-h] [--par] --rnd --frn --grn " }, + "lf em 4x70 calc": { + "command": "lf em 4x70 calc", + "description": "Calculates both the reader and tag challenge for a user-provided key and rnd.", + "notes": [ + "lf em 4x70 calc --key F32AA98CF5BE4ADFA6D3480B --rnd 45F54ADA252AAC (pm3 test key)", + "lf em 4x70 calc --key A090A0A02080000000000000 --rnd 3FFE1FB6CC513F (research paper key)", + "lf em 4x70 calc --key 022A028C02BE000102030405 --rnd 7D5167003571F8 (autorecovery test key)" + ], + "offline": true, + "options": [ + "-h, --help This help", + "--key Key 96-bit as 12 hex bytes", + "--rnd 56-bit random value sent to tag for authentication" + ], + "usage": "lf em 4x70 calc [-h] --key --rnd " + }, "lf em 4x70 help": { "command": "lf em 4x70 help", - "description": "help This help recover Recover remaining key from partial key --------------------------------------------------------------------------------------- lf em 4x70 brute available offline: no Optimized partial key-update attack of 16-bit key block 7, 8 or 9 of an EM4x70 This attack does NOT write anything to the tag. Before starting this attack, 0000 must be written to the 16-bit key block: 'lf em 4x70 write -b 9 -d 0000'. After success, the 16-bit key block have to be restored with the key found: 'lf em 4x70 write -b 9 -d c0de'", + "description": "help This help calc Calculate EM4x70 challenge and response recover Recover remaining key from partial key --------------------------------------------------------------------------------------- lf em 4x70 brute available offline: no Optimized partial key-update attack of 16-bit key block 7, 8 or 9 of an EM4x70 This attack does NOT write anything to the tag. Before starting this attack, 0000 must be written to the 16-bit key block: 'lf em 4x70 write -b 9 -d 0000'. After success, the 16-bit key block have to be restored with the key found: 'lf em 4x70 write -b 9 -d c0de'", "notes": [ - "lf em 4x70 brute -b 9 --rnd 45F54ADA252AAC --frn 4866BB70 -> bruteforcing key bits k95...k80" + "lf em 4x70 brute -b 9 --rnd 45F54ADA252AAC --frn 4866BB70 -> bruteforcing key bits k95...k80 (pm3 test key)", + "lf em 4x70 brute -b 8 --rnd 3FFE1FB6CC513F --frn F355F1A0 -> bruteforcing key bits k79...k64 (research paper key)", + "lf em 4x70 brute -b 7 --rnd 7D5167003571F8 --frn 982DBCC0 -> bruteforcing key bits k63...k48 (autorecovery test key)" ], "offline": true, "options": [ @@ -9052,7 +9070,8 @@ "description": "After obtaining key bits 95..48 (such as via 'lf em 4x70 brute'), this command will recover key bits 47..00. By default, this process does NOT require a tag to be present. By default, the potential keys are shown (typically 1-6) along with a corresponding 'lf em 4x70 auth' command that will authenticate, if that potential key is correct. The user can copy/paste these commands when the tag is present to manually check which of the potential keys is correct.", "notes": [ "lf em 4x70 recover --key F32AA98CF5BE --rnd 45F54ADA252AAC --frn 4866BB70 --grn 9BD180 (pm3 test key)", - "lf em 4x70 recover --key A090A0A02080 --rnd 3FFE1FB6CC513F --frn F355F1A0 --grn 609D60 (research paper key)" + "lf em 4x70 recover --key A090A0A02080 --rnd 3FFE1FB6CC513F --frn F355F1A0 --grn 609D60 (research paper key)", + "lf em 4x70 recover --key 022A028C02BE --rnd 7D5167003571F8 --frn 982DBCC0 --grn 36C0E0 (autorecovery test key)" ], "offline": true, "options": [ @@ -9518,7 +9537,7 @@ "-h, --help This help", "--nrar specify nonce / answer as 8 hex bytes" ], - "usage": "lf hitag lookup [-h] [--nrar ]" + "usage": "lf hitag crack2 [-h] [--nrar ]" }, "lf hitag dump": { "command": "lf hitag dump", @@ -9653,6 +9672,20 @@ ], "usage": "lf hitag read [-hs2] [--pwd] [--nrar ] [--crypto] [-k ]" }, + "lf hitag reader": { + "command": "lf hitag reader", + "description": "Act as a Hitag2 reader. Look for Hitag2 tags until Enter or the pm3 button is pressed", + "notes": [ + "lf hitag reader", + "lf hitag reader -@ -> Continuous mode" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-@ continuous reader mode" + ], + "usage": "lf hitag reader [-h@]" + }, "lf hitag sim": { "command": "lf hitag sim", "description": "Simulate Hitag transponder You need to `lf hitag eload` first", @@ -12699,8 +12732,8 @@ } }, "metadata": { - "commands_extracted": 735, + "commands_extracted": 737, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2024-05-14T08:02:41" + "extracted_on": "2024-05-27T13:38:05" } } diff --git a/doc/commands.md b/doc/commands.md index e010a8a174..dd7f275a49 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -979,6 +979,7 @@ Check column "offline" for their availability. |`lf em 4x70 auth `|N |`Authenticate EM4x70` |`lf em 4x70 setpin `|N |`Write PIN` |`lf em 4x70 setkey `|N |`Write key` +|`lf em 4x70 calc `|Y |`Calculate EM4x70 challenge and response` |`lf em 4x70 recover `|Y |`Recover remaining key from partial key` |`lf em 4x70 autorecover `|N |`Recover entire key from writable tag` @@ -1046,6 +1047,7 @@ Check column "offline" for their availability. |`lf hitag help `|Y |`This help` |`lf hitag list `|Y |`List Hitag trace history` |`lf hitag info `|N |`Hitag 2 tag information` +|`lf hitag reader `|N |`Act line an Hitag 2 reader` |`lf hitag test `|Y |`Perform self tests` |`lf hitag dump `|N |`Dump Hitag 2 tag` |`lf hitag read `|N |`Read Hitag memory`