lf em 4x70 writekey --> lf em 4x70 setkey

This commit is contained in:
Henry Gabryjelski 2024-03-13 09:38:35 -07:00
commit cc2bae2f4d
9 changed files with 91 additions and 91 deletions

View file

@ -1253,7 +1253,7 @@ static void PacketReceived(PacketCommandNG *packet) {
em4x70_write_pin((em4x70_data_t *)packet->data.asBytes, true);
break;
}
case CMD_LF_EM4X70_WRITEKEY: {
case CMD_LF_EM4X70_SETKEY: {
em4x70_write_key((em4x70_data_t *)packet->data.asBytes, true);
break;
}

View file

@ -919,5 +919,5 @@ void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol) {
StopTicks();
lf_finalize(ledcontrol);
reply_ng(CMD_LF_EM4X70_WRITEKEY, status, tag.data, sizeof(tag.data));
reply_ng(CMD_LF_EM4X70_SETKEY, status, tag.data, sizeof(tag.data));
}

View file

@ -250,20 +250,20 @@ then `Aᵥ' = Aᵥ`.
```
REM using the key and auth values from the research paper
lf em 4x70 writekey --key A090A0A02080000000000000
lf em 4x70 setkey --key A090A0A02080000000000000
REM expect a tag response of `60 9D 6`
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
REM repeat using 31 additional keys in the same "block"
lf em 4x70 writekey --key A090A0A02080000000000001
lf em 4x70 setkey --key A090A0A02080000000000001
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
lf em 4x70 writekey --key A090A0A02080000000000002
lf em 4x70 setkey --key A090A0A02080000000000002
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
lf em 4x70 writekey --key A090A0A02080000000000003
lf em 4x70 setkey --key A090A0A02080000000000003
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
REM ... and so on, for a total of 31 more keys
lf em 4x70 writekey --key A090A0A0208000000000001E
lf em 4x70 setkey --key A090A0A0208000000000001E
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
lf em 4x70 writekey --key A090A0A0208000000000001F
lf em 4x70 setkey --key A090A0A0208000000000001F
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
```
@ -287,11 +287,11 @@ then `Aᵥ' ^ Aᵥ <= 0x1`.
```
REM using the key and auth values from the research paper
lf em 4x70 writekey --key A090A0A02080000000000000
lf em 4x70 setkey --key A090A0A02080000000000000
REM expect a tag response of `60 9D 6`
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
REM repeat using 31 additional keys in the same "block"
lf em 4x70 writekey --key A090A0A02080000000000020
lf em 4x70 setkey --key A090A0A02080000000000020
REM 50% chance that this is the correct FRN value
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0
REM 50% chance that this is the correct FRN value
@ -313,7 +313,7 @@ in a successful authentication:
```
REM modify the key's lowest nine bits
lf em 4x70 writekey --key A090A0A02080000000000100
lf em 4x70 setkey --key A090A0A02080000000000100
REM 1/16 chance for each of these to work:
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F100
lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F110
@ -451,60 +451,60 @@ influence a given output bit?
| sₙ | Output Bit | Bits in `K` | Delta from s(N-1) | Hex Value |
|-------|-------------|-------------|-------------------|------------------|
| `s₁` | ` ` | `K[39..95]` | `K₃₉` | `0x80_0000_0000` |
| `s₂` | ` ` | `K[38..95]` | `K₃₈` | `0x40_0000_0000` |
| `s₃` | ` ` | `K[37..95]` | `K₃₇` | `0x20_0000_0000` |
| `s₄` | ` ` | `K[36..95]` | `K₃₆` | `0x10_0000_0000` |
| `s₅` | ` ` | `K[35..95]` | `K₃₅` | `0x08_0000_0000` |
| `s₆` | ` ` | `K[34..95]` | `K₃₄` | `0x04_0000_0000` |
| `s₇` | `Aᵥ₂₇` | `K[33..95]` | `K₃₃` | `0x02_0000_0000` |
| `s₈` | `Aᵥ₂₆` | `K[32..95]` | `K₃₂` | `0x01_0000_0000` |
| `s₉` | `Aᵥ₂₅` | `K[31..95]` | `K₃₁` | `0x00_8000_0000` |
| `s₁₀` | `Aᵥ₂₄` | `K[30..95]` | `K₃₀` | `0x00_4000_0000` |
| `s₁₁` | `Aᵥ₂₃` | `K[29..95]` | `K₂₉` | `0x00_2000_0000` |
| `s₁₂` | `Aᵥ₂₂` | `K[28..95]` | `K₂₈` | `0x00_1000_0000` |
| `s₁₃` | `Aᵥ₂₁` | `K[27..95]` | `K₂₇` | `0x00_0800_0000` |
| `s₁₄` | `Aᵥ₂₀` | `K[26..95]` | `K₂₆` | `0x00_0400_0000` |
| `s₁₅` | `Aᵥ₁₉` | `K[25..95]` | `K₂₅` | `0x00_0200_0000` |
| `s₁₆` | `Aᵥ₁₈` | `K[24..95]` | `K₂₄` | `0x00_0100_0000` |
| `s₁₇` | `Aᵥ₁₇` | `K[23..95]` | `K₂₃` | `0x00_0080_0000` |
| `s₁₈` | `Aᵥ₁₆` | `K[22..95]` | `K₂₂` | `0x00_0040_0000` |
| `s₁₉` | `Aᵥ₁₅` | `K[21..95]` | `K₂₁` | `0x00_0020_0000` |
| `s₂₀` | `Aᵥ₁₄` | `K[20..95]` | `K₂₀` | `0x00_0010_0000` |
| `s₂₁` | `Aᵥ₁₃` | `K[19..95]` | `K₁₉` | `0x00_0008_0000` |
| `s₂₂` | `Aᵥ₁₂` | `K[18..95]` | `K₁₈` | `0x00_0004_0000` |
| `s₂₃` | `Aᵥ₁₁` | `K[17..95]` | `K₁₇` | `0x00_0002_0000` |
| `s₂₄` | `Aᵥ₁₀` | `K[16..95]` | `K₁₆` | `0x00_0001_0000` |
| `s₂₅` | `Aᵥ₉` | `K[15..95]` | `K₁₅` | `0x00_0000_8000` |
| `s₂₆` | `Aᵥ₈` | `K[14..95]` | `K₁₄` | `0x00_0000_4000` |
| `s₂₇` | `Aᵥ₇` | `K[13..95]` | `K₁₃` | `0x00_0000_2000` |
| `s₂₈` | `Aᵥ₆` | `K[12..95]` | `K₁₂` | `0x00_0000_1000` |
| `s₂₉` | `Aᵥ₅` | `K[11..95]` | `K₁₁` | `0x00_0000_0800` |
| `s₃₀` | `Aᵥ₄` | `K[10..95]` | `K₁₀` | `0x00_0000_0400` |
| `s₃₁` | `Aᵥ₃` | `K[ 9..95]` | `K₉` | `0x00_0000_0200` |
| `s₃₂` | `Aᵥ₂` | `K[ 8..95]` | `K₈` | `0x00_0000_0100` |
| `s₃₃` | `Aᵥ₁` | `K[ 7..95]` | `K₇` | `0x00_0000_0080` |
| `s₃₄` | `Aᵥ₀` | `K[ 6..95]` | `K₆` | `0x00_0000_0040` |
| `s₃₅` | `Aₜ₁₉` | `K[ 5..95]` | `K₅` | `0x00_0000_0020` |
| `s₃₆` | `Aₜ₁₈` | `K[ 4..95]` | `K₄` | `0x00_0000_0010` |
| `s₃₇` | `Aₜ₁₇` | `K[ 3..95]` | `K₃` | `0x00_0000_0008` |
| `s₃₈` | `Aₜ₁₆` | `K[ 2..95]` | `K₂` | `0x00_0000_0004` |
| `s₃₉` | `Aₜ₁₅` | `K[ 1..95]` | `K₁` | `0x00_0000_0002` |
| `s₄₀` | `Aₜ₁₄` | `K[ 0..95]` | `K₀` | `0x00_0000_0001` |
| `s₄₁` | `Aₜ₁₃` | `K[ 0..95]` | ... | |
| `s₄₂` | `Aₜ₁₂` | `K[ 0..95]` | ... | |
| `s₄₃` | `Aₜ₁₁` | `K[ 0..95]` | ... | |
| `s₄₄` | `Aₜ₁₀` | `K[ 0..95]` | ... | |
| `s₄₅` | `Aₜ₉` | `K[ 0..95]` | ... | |
| `s₄₆` | `Aₜ₈` | `K[ 0..95]` | ... | |
| `s₄₇` | `Aₜ₇` | `K[ 0..95]` | ... | |
| `s₄₈` | `Aₜ₆` | `K[ 0..95]` | ... | |
| `s₄₉` | `Aₜ₅` | `K[ 0..95]` | ... | |
| `s₅₀` | `Aₜ₄` | `K[ 0..95]` | ... | |
| `s₅₁` | `Aₜ₃` | `K[ 0..95]` | ... | |
| `s₅₂` | `Aₜ₂` | `K[ 0..95]` | ... | |
| `s₅₃` | `Aₜ₁` | `K[ 0..95]` | ... | |
| `s₅₄` | `Aₜ₀` | `K[ 0..95]` | ... | |
| `s₁` | ` ` | `K[39..95]` | `K₃₉` | `0x80_0000_0000` |
| `s₂` | ` ` | `K[38..95]` | `K₃₈` | `0x40_0000_0000` |
| `s₃` | ` ` | `K[37..95]` | `K₃₇` | `0x20_0000_0000` |
| `s₄` | ` ` | `K[36..95]` | `K₃₆` | `0x10_0000_0000` |
| `s₅` | ` ` | `K[35..95]` | `K₃₅` | `0x08_0000_0000` |
| `s₆` | ` ` | `K[34..95]` | `K₃₄` | `0x04_0000_0000` |
| `s₇` | `Aᵥ₂₇` | `K[33..95]` | `K₃₃` | `0x02_0000_0000` |
| `s₈` | `Aᵥ₂₆` | `K[32..95]` | `K₃₂` | `0x01_0000_0000` |
| `s₉` | `Aᵥ₂₅` | `K[31..95]` | `K₃₁` | `0x00_8000_0000` |
| `s₁₀` | `Aᵥ₂₄` | `K[30..95]` | `K₃₀` | `0x00_4000_0000` |
| `s₁₁` | `Aᵥ₂₃` | `K[29..95]` | `K₂₉` | `0x00_2000_0000` |
| `s₁₂` | `Aᵥ₂₂` | `K[28..95]` | `K₂₈` | `0x00_1000_0000` |
| `s₁₃` | `Aᵥ₂₁` | `K[27..95]` | `K₂₇` | `0x00_0800_0000` |
| `s₁₄` | `Aᵥ₂₀` | `K[26..95]` | `K₂₆` | `0x00_0400_0000` |
| `s₁₅` | `Aᵥ₁₉` | `K[25..95]` | `K₂₅` | `0x00_0200_0000` |
| `s₁₆` | `Aᵥ₁₈` | `K[24..95]` | `K₂₄` | `0x00_0100_0000` |
| `s₁₇` | `Aᵥ₁₇` | `K[23..95]` | `K₂₃` | `0x00_0080_0000` |
| `s₁₈` | `Aᵥ₁₆` | `K[22..95]` | `K₂₂` | `0x00_0040_0000` |
| `s₁₉` | `Aᵥ₁₅` | `K[21..95]` | `K₂₁` | `0x00_0020_0000` |
| `s₂₀` | `Aᵥ₁₄` | `K[20..95]` | `K₂₀` | `0x00_0010_0000` |
| `s₂₁` | `Aᵥ₁₃` | `K[19..95]` | `K₁₉` | `0x00_0008_0000` |
| `s₂₂` | `Aᵥ₁₂` | `K[18..95]` | `K₁₈` | `0x00_0004_0000` |
| `s₂₃` | `Aᵥ₁₁` | `K[17..95]` | `K₁₇` | `0x00_0002_0000` |
| `s₂₄` | `Aᵥ₁₀` | `K[16..95]` | `K₁₆` | `0x00_0001_0000` |
| `s₂₅` | `Aᵥ₉` | `K[15..95]` | `K₁₅` | `0x00_0000_8000` |
| `s₂₆` | `Aᵥ₈` | `K[14..95]` | `K₁₄` | `0x00_0000_4000` |
| `s₂₇` | `Aᵥ₇` | `K[13..95]` | `K₁₃` | `0x00_0000_2000` |
| `s₂₈` | `Aᵥ₆` | `K[12..95]` | `K₁₂` | `0x00_0000_1000` |
| `s₂₉` | `Aᵥ₅` | `K[11..95]` | `K₁₁` | `0x00_0000_0800` |
| `s₃₀` | `Aᵥ₄` | `K[10..95]` | `K₁₀` | `0x00_0000_0400` |
| `s₃₁` | `Aᵥ₃` | `K[ 9..95]` | `K₉` | `0x00_0000_0200` |
| `s₃₂` | `Aᵥ₂` | `K[ 8..95]` | `K₈` | `0x00_0000_0100` |
| `s₃₃` | `Aᵥ₁` | `K[ 7..95]` | `K₇` | `0x00_0000_0080` |
| `s₃₄` | `Aᵥ₀` | `K[ 6..95]` | `K₆` | `0x00_0000_0040` |
| `s₃₅` | `Aₜ₁₉` | `K[ 5..95]` | `K₅` | `0x00_0000_0020` |
| `s₃₆` | `Aₜ₁₈` | `K[ 4..95]` | `K₄` | `0x00_0000_0010` |
| `s₃₇` | `Aₜ₁₇` | `K[ 3..95]` | `K₃` | `0x00_0000_0008` |
| `s₃₈` | `Aₜ₁₆` | `K[ 2..95]` | `K₂` | `0x00_0000_0004` |
| `s₃₉` | `Aₜ₁₅` | `K[ 1..95]` | `K₁` | `0x00_0000_0002` |
| `s₄₀` | `Aₜ₁₄` | `K[ 0..95]` | `K₀` | `0x00_0000_0001` |
| `s₄₁` | `Aₜ₁₃` | `K[ 0..95]` | ... | |
| `s₄₂` | `Aₜ₁₂` | `K[ 0..95]` | ... | |
| `s₄₃` | `Aₜ₁₁` | `K[ 0..95]` | ... | |
| `s₄₄` | `Aₜ₁₀` | `K[ 0..95]` | ... | |
| `s₄₅` | `Aₜ₉` | `K[ 0..95]` | ... | |
| `s₄₆` | `Aₜ₈` | `K[ 0..95]` | ... | |
| `s₄₇` | `Aₜ₇` | `K[ 0..95]` | ... | |
| `s₄₈` | `Aₜ₆` | `K[ 0..95]` | ... | |
| `s₄₉` | `Aₜ₅` | `K[ 0..95]` | ... | |
| `s₅₀` | `Aₜ₄` | `K[ 0..95]` | ... | |
| `s₅₁` | `Aₜ₃` | `K[ 0..95]` | ... | |
| `s₅₂` | `Aₜ₂` | `K[ 0..95]` | ... | |
| `s₅₃` | `Aₜ₁` | `K[ 0..95]` | ... | |
| `s₅₄` | `Aₜ₀` | `K[ 0..95]` | ... | |
## 128k table ... too large to fit in IoT flash memory
@ -725,7 +725,7 @@ Updating the pin code:
`lf em 4x70 info`
2. Because Lockbit 0 was set, send the PIN to unlock:
2. Because Lockbit 0 was set, unlock with the PIN:
`lf em 4x70 unlock --pin AAAAAAAA`
@ -737,7 +737,7 @@ Updating the pin code:
4. Write the new pin code as DEADBEEF
`lf em 4x70 writepin --pin DEADBEEF`
`lf em 4x70 setpin --pin DEADBEEF`
5. Set lockbit0 to 1 (based on existing data in block1):
e.g, `AD08 | 4000 == ED08`

View file

@ -131,10 +131,10 @@ typedef struct _em4x70_cmd_input_setpin_t {
uint8_t pin[4];
} em4x70_cmd_input_setpin_t;
typedef struct _em4x70_cmd_input_writekey_t {
typedef struct _em4x70_cmd_input_setkey_t {
uint8_t use_parity;
ID48LIB_KEY key;
} em4x70_cmd_input_writekey_t;
} em4x70_cmd_input_setkey_t;
// There is no output data when writing a new key
typedef struct _em4x70_cmd_input_recover_t {
ID48LIB_KEY key; // only the first 6 bytes (48 bits) are considered valid
@ -276,7 +276,7 @@ static int auth_em4x70(const em4x70_cmd_input_auth_t *opts, em4x70_cmd_output_au
}
return PM3_ESOFT;
}
static int writekey_em4x70(const em4x70_cmd_input_writekey_t *opts) {
static int setkey_em4x70(const em4x70_cmd_input_setkey_t *opts) {
// TODO: change firmware to use per-cmd structures
em4x70_data_t etd = {0};
@ -284,10 +284,10 @@ static int writekey_em4x70(const em4x70_cmd_input_writekey_t *opts) {
memcpy(&etd.crypt_key[0], &opts->key.k[0], 12);
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X70_WRITEKEY, (uint8_t *)&etd, sizeof(etd));
SendCommandNG(CMD_LF_EM4X70_SETKEY, (uint8_t *)&etd, sizeof(etd));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X70_WRITEKEY, &resp, TIMEOUT)) {
if (!WaitForResponseTimeout(CMD_LF_EM4X70_SETKEY, &resp, TIMEOUT)) {
return PM3_ETIMEOUT;
}
if (resp.status) {
@ -767,12 +767,12 @@ int CmdEM4x70SetPIN(const char *Cmd) {
return result;
}
int CmdEM4x70WriteKey(const char *Cmd) {
int CmdEM4x70SetKey(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x70 writekey",
CLIParserInit(&ctx, "lf em 4x70 setkey",
"Write new 96-bit key to tag\n",
"lf em 4x70 writekey -k F32AA98CF5BE4ADFA6D3480B (pm3 test key)\n"
"lf em 4x70 writekey -k A090A0A02080000000000000 (research paper key)\n"
"lf em 4x70 setkey -k F32AA98CF5BE4ADFA6D3480B (pm3 test key)\n"
"lf em 4x70 setkey -k A090A0A02080000000000000 (research paper key)\n"
);
void *argtable[] = {
@ -784,7 +784,7 @@ int CmdEM4x70WriteKey(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, true);
em4x70_cmd_input_writekey_t opts = {
em4x70_cmd_input_setkey_t opts = {
.use_parity = arg_get_lit(ctx, 1),
.key = {{0}}, // hex value macro exits function, so cannot be initialized here
};
@ -797,7 +797,7 @@ int CmdEM4x70WriteKey(const char *Cmd) {
}
// Client command line parsing and validation complete ... now use the helper function
int result = writekey_em4x70(&opts);
int result = setkey_em4x70(&opts);
if (PM3_ETIMEOUT == result) {
PrintAndLogEx(WARNING, "Timeout while waiting for reply.");
return PM3_ETIMEOUT;
@ -1046,7 +1046,7 @@ static int CmdEM4x70AutoRecover_ParseArgs(const char *Cmd, em4x70_cmd_input_reco
int result = PM3_SUCCESS;
// The following key is found quickly, and has multiple potential keys.
// Useful for quicker testing, as this function could take over 2 hours.
// lf em 4x70 writekey -k 001200340055BAADCAFEF00D
// lf em 4x70 setkey -k 001200340055BAADCAFEF00D
// lf em 4x70 autorecover --rnd 1782779E7E3BC8 --frn 00357080 --grn F3C480
CLIParserContext *ctx;
CLIParserInit(
@ -1393,7 +1393,7 @@ static command_t CommandTable[] = {
{"unlock", CmdEM4x70Unlock, IfPm3EM4x70, "Unlock EM4x70 for writing"},
{"auth", CmdEM4x70Auth, IfPm3EM4x70, "Authenticate EM4x70"},
{"setpin", CmdEM4x70SetPIN, IfPm3EM4x70, "Write PIN"},
{"writekey", CmdEM4x70WriteKey, IfPm3EM4x70, "Write key"},
{"setkey", CmdEM4x70SetKey, IfPm3EM4x70, "Write key"},
{"recover", CmdEM4x70Recover, AlwaysAvailable, "Recover remaining key from partial key"},
{"autorecover", CmdEM4x70AutoRecover, IfPm3EM4x70, "Recover entire key from writable tag"},
{NULL, NULL, NULL, NULL}

View file

@ -30,7 +30,7 @@ int CmdEM4x70Brute(const char *Cmd);
int CmdEM4x70Unlock(const char *Cmd);
int CmdEM4x70Auth(const char *Cmd);
int CmdEM4x70SetPIN(const char *Cmd);
int CmdEM4x70WriteKey(const char *Cmd);
int CmdEM4x70SetKey(const char *Cmd);
int CmdEM4x70Recover(const char *Cmd);
// for `lf search`:

View file

@ -614,8 +614,8 @@ const static vocabulary_t vocabulary[] = {
{ 0, "lf em 4x70 unlock" },
{ 0, "lf em 4x70 auth" },
{ 0, "lf em 4x70 setpin" },
{ 0, "lf em 4x70 writekey" },
{ 0, "lf em 4x70 recover" },
{ 0, "lf em 4x70 setkey" },
{ 1, "lf em 4x70 recover" },
{ 0, "lf em 4x70 autorecover" },
{ 1, "lf fdxb help" },
{ 1, "lf fdxb demod" },

View file

@ -8967,12 +8967,12 @@
],
"usage": "lf em 4x70 write [-h] [--par] -b <dec> -d <hex>"
},
"lf em 4x70 writekey": {
"command": "lf em 4x70 writekey",
"lf em 4x70 setkey": {
"command": "lf em 4x70 setkey",
"description": "Write new 96-bit key to tag",
"notes": [
"lf em 4x70 writekey -k F32AA98CF5BE4ADFA6D3480B (pm3 test key)",
"lf em 4x70 writekey -k A090A0A02080000000000000 (research paper key)"
"lf em 4x70 setkey -k F32AA98CF5BE4ADFA6D3480B (pm3 test key)",
"lf em 4x70 setkey -k A090A0A02080000000000000 (research paper key)"
],
"offline": false,
"options": [
@ -8980,7 +8980,7 @@
"--par Add parity bit when sending commands",
"-k, --key <hex> Key as 12 hex bytes"
],
"usage": "lf em 4x70 writekey [-h] [--par] -k <hex>"
"usage": "lf em 4x70 setkey [-h] [--par] -k <hex>"
},
"lf em 4x70 setpin": {
"command": "lf em 4x70 setpin",

View file

@ -961,8 +961,8 @@ Check column "offline" for their availability.
|`lf em 4x70 unlock `|N |`Unlock EM4x70 for writing`
|`lf em 4x70 auth `|N |`Authenticate EM4x70`
|`lf em 4x70 setpin `|N |`Write new PIN`
|`lf em 4x70 writekey `|N |`Write new key`
|`lf em 4x70 recover `|N |`Recover remaining key from partial key`
|`lf em 4x70 setkey `|N |`Write new key`
|`lf em 4x70 recover `|Y |`Recover remaining key from partial key`
|`lf em 4x70 autorecover `|N |`Recover entire key from writable tag`

View file

@ -528,7 +528,7 @@ typedef struct {
#define CMD_LF_EM4X70_UNLOCK 0x0262
#define CMD_LF_EM4X70_AUTH 0x0263
#define CMD_LF_EM4X70_SETPIN 0x0264
#define CMD_LF_EM4X70_WRITEKEY 0x0265
#define CMD_LF_EM4X70_SETKEY 0x0265
#define CMD_LF_EM4X70_BRUTE 0x0266
// Sampling configuration for LF reader/sniffer
#define CMD_LF_SAMPLING_SET_CONFIG 0x021D