mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge pull request #2895 from henrygab/em4x70_no_more_par
EM4x70 -- Remove deprecated `--par` option
This commit is contained in:
commit
cd14990dc5
4 changed files with 57 additions and 112 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Removed `--par` from `lf em 4x70` commands.
|
||||
- Changed `hf 14a info` - refactored code to be able to detect card technology across the client easier (@iceman1001)
|
||||
- Changed `hf mf info` - now informs better if a different card technology is detected (@iceman1001)
|
||||
- Changed `hf mf autopwn` - now exits if desfire is detected and limit attacks if mifare plus is detected (@iceman1001)
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#define DPRINTF_EXTENDED(x) do { if ((FORCE_ENABLE_LOGGING) || (g_dbglevel >= DBG_EXTENDED)) { Dbprintf x ; } } while (0);
|
||||
#define DPRINTF_PROLIX(x) do { if ((FORCE_ENABLE_LOGGING) || (g_dbglevel > DBG_EXTENDED)) { Dbprintf x ; } } while (0);
|
||||
// EM4170 requires a parity bit on commands, other variants do not.
|
||||
static bool g_command_parity = true;
|
||||
static bool g_deprecated_command_parity = false;
|
||||
static em4x70_tag_t g_tag = { 0 };
|
||||
|
||||
|
||||
|
@ -905,8 +905,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_id(em4x70_command_bitstream_t
|
|||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
out_cmd_bitstream->command = EM4X70_COMMAND_ID;
|
||||
//uint8_t cmd = with_command_parity ? 0x3u : 0x1u;
|
||||
uint8_t cmd = 0x3u;
|
||||
uint8_t cmd = 0x3u; // CMD + Parity bit == 0b001'1
|
||||
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
||||
out_cmd_bitstream->to_receive.bitcount = 32;
|
||||
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
||||
|
@ -920,8 +919,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_um1(em4x70_command_bitstream_
|
|||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
out_cmd_bitstream->command = EM4X70_COMMAND_UM1;
|
||||
//uint8_t cmd = with_command_parity ? 0x5u : 0x2u;
|
||||
uint8_t cmd = 0x5u;
|
||||
uint8_t cmd = 0x5u; // CMD + Parity bit == 0b010'1
|
||||
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
||||
out_cmd_bitstream->to_receive.bitcount = 32;
|
||||
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
||||
|
@ -935,8 +933,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_um2(em4x70_command_bitstream_
|
|||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
out_cmd_bitstream->command = EM4X70_COMMAND_UM2;
|
||||
//uint8_t cmd = with_command_parity ? 0xFu : 0x7u;
|
||||
uint8_t cmd = 0xFu;
|
||||
uint8_t cmd = 0xFu; // CMD + Parity bit == 0b111'1
|
||||
result = result && add_nibble_to_bitstream(&out_cmd_bitstream->to_send, cmd, false);
|
||||
out_cmd_bitstream->to_receive.bitcount = 64;
|
||||
if (out_cmd_bitstream->to_send.bitcount != expected_bits_to_send) {
|
||||
|
@ -954,8 +951,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_auth(em4x70_command_bitstream
|
|||
|
||||
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
||||
|
||||
// uint8_t cmd = with_command_parity ? 0x6u : 0x3u;
|
||||
uint8_t cmd = 0x6u; // HACK - always sent with cmd parity
|
||||
uint8_t cmd = 0x6u; // CMD + Parity bit == 0b011'0
|
||||
result = result && add_nibble_to_bitstream(s, cmd, false);
|
||||
|
||||
// Reader: [RM][0][Command][N55..N0][0000000][f(RN)27..f(RN)0]
|
||||
|
@ -1004,8 +1000,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_pin(em4x70_command_bitstream_
|
|||
|
||||
out_cmd_bitstream->command = EM4X70_COMMAND_PIN;
|
||||
|
||||
//uint8_t cmd = with_command_parity ? 0x9u : 0x4u;
|
||||
uint8_t cmd = 0x9u; // HACK - always sent with cmd parity, with extra zero bit in RM?
|
||||
uint8_t cmd = 0x9u; // CMD + Parity bit == 0b100'1
|
||||
result = result && add_nibble_to_bitstream(s, cmd, false);
|
||||
|
||||
// Send tag's ID ... indexes 4 .. 35
|
||||
|
@ -1037,8 +1032,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_write(em4x70_command_bitstrea
|
|||
|
||||
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
||||
|
||||
//uint8_t cmd = with_command_parity ? 0xAu : 0x5u;
|
||||
uint8_t cmd = 0xAu; // HACK - always sent with cmd parity, with extra zero bit in RM?
|
||||
uint8_t cmd = 0xAu; // CMD + Parity bit == 0b101'0
|
||||
result = result && add_nibble_to_bitstream(s, cmd, false);
|
||||
|
||||
if ((address & 0x0Fu) != address) {
|
||||
|
@ -1097,7 +1091,7 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
|
|||
em4x70_command_bitstream_t auth_cmd;
|
||||
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->auth(&auth_cmd, g_command_parity, rnd, frnd);
|
||||
generator->auth(&auth_cmd, g_deprecated_command_parity, rnd, frnd);
|
||||
|
||||
bool result = send_bitstream_and_read(&auth_cmd);
|
||||
if (result) {
|
||||
|
@ -1185,7 +1179,7 @@ static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *
|
|||
static int send_pin(const uint32_t pin) {
|
||||
em4x70_command_bitstream_t send_pin_cmd;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->pin(&send_pin_cmd, g_command_parity, &g_tag.data[4], pin);
|
||||
generator->pin(&send_pin_cmd, g_deprecated_command_parity, &g_tag.data[4], pin);
|
||||
|
||||
bool result = send_bitstream_wait_ack_wait_read(&send_pin_cmd);
|
||||
return result ? PM3_SUCCESS : PM3_ESOFT;
|
||||
|
@ -1196,7 +1190,7 @@ static int write(const uint16_t word, const uint8_t address) {
|
|||
em4x70_command_bitstream_t write_cmd;
|
||||
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->write(&write_cmd, g_command_parity, word, address);
|
||||
generator->write(&write_cmd, g_deprecated_command_parity, word, address);
|
||||
|
||||
bool result = send_bitstream_wait_ack_wait_ack(&write_cmd);
|
||||
if (!result) {
|
||||
|
@ -1283,7 +1277,7 @@ static uint8_t encoded_bit_array_to_byte(const uint8_t *bits, int count_of_bits)
|
|||
static bool em4x70_read_id(void) {
|
||||
em4x70_command_bitstream_t read_id_cmd;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->id(&read_id_cmd, g_command_parity);
|
||||
generator->id(&read_id_cmd, g_deprecated_command_parity);
|
||||
|
||||
bool result = send_bitstream_and_read(&read_id_cmd);
|
||||
if (result) {
|
||||
|
@ -1300,7 +1294,7 @@ static bool em4x70_read_id(void) {
|
|||
static bool em4x70_read_um1(void) {
|
||||
em4x70_command_bitstream_t read_um1_cmd;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->um1(&read_um1_cmd, g_command_parity);
|
||||
generator->um1(&read_um1_cmd, g_deprecated_command_parity);
|
||||
|
||||
bool result = send_bitstream_and_read(&read_um1_cmd);
|
||||
if (result) {
|
||||
|
@ -1319,7 +1313,7 @@ static bool em4x70_read_um1(void) {
|
|||
static bool em4x70_read_um2(void) {
|
||||
em4x70_command_bitstream_t read_um2_cmd;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->um2(&read_um2_cmd, g_command_parity);
|
||||
generator->um2(&read_um2_cmd, g_deprecated_command_parity);
|
||||
|
||||
bool result = send_bitstream_and_read(&read_um2_cmd);
|
||||
if (result) {
|
||||
|
@ -1435,7 +1429,7 @@ void em4x70_info(const em4x70_data_t *etd, bool ledcontrol) {
|
|||
bool success_with_UM2 = false;
|
||||
|
||||
// Support tags with and without command parity bits
|
||||
g_command_parity = etd->parity;
|
||||
g_deprecated_command_parity = false;
|
||||
|
||||
init_tag();
|
||||
em4x70_setup_read();
|
||||
|
@ -1463,10 +1457,10 @@ void em4x70_info(const em4x70_data_t *etd, bool ledcontrol) {
|
|||
void em4x70_write(const em4x70_data_t *etd, bool ledcontrol) {
|
||||
int status = PM3_ESOFT;
|
||||
|
||||
g_command_parity = etd->parity;
|
||||
g_deprecated_command_parity = false;
|
||||
|
||||
// Disable to prevent sending corrupted data to the tag.
|
||||
if (g_command_parity) {
|
||||
if (g_deprecated_command_parity) {
|
||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 write` is non-functional and may corrupt data on the tag."));
|
||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||
// return;
|
||||
|
@ -1499,7 +1493,7 @@ void em4x70_unlock(const em4x70_data_t *etd, bool ledcontrol) {
|
|||
|
||||
int status = PM3_ESOFT;
|
||||
|
||||
g_command_parity = etd->parity;
|
||||
g_deprecated_command_parity = false;
|
||||
|
||||
init_tag();
|
||||
em4x70_setup_read();
|
||||
|
@ -1534,10 +1528,10 @@ void em4x70_auth(const em4x70_data_t *etd, bool ledcontrol) {
|
|||
|
||||
uint8_t response[3] = {0};
|
||||
|
||||
g_command_parity = etd->parity;
|
||||
g_deprecated_command_parity = false;
|
||||
|
||||
// Disable to prevent sending corrupted data to the tag.
|
||||
if (g_command_parity) {
|
||||
if (g_deprecated_command_parity) {
|
||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 auth` is non-functional."));
|
||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||
// return;
|
||||
|
@ -1562,10 +1556,10 @@ void em4x70_brute(const em4x70_data_t *etd, bool ledcontrol) {
|
|||
int status = PM3_ESOFT;
|
||||
uint8_t response[2] = {0};
|
||||
|
||||
g_command_parity = etd->parity;
|
||||
g_deprecated_command_parity = false;
|
||||
|
||||
// Disable to prevent sending corrupted data to the tag.
|
||||
if (g_command_parity) {
|
||||
if (g_deprecated_command_parity) {
|
||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 brute` is non-functional and may corrupt data on the tag."));
|
||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||
// return;
|
||||
|
@ -1590,10 +1584,10 @@ void em4x70_write_pin(const em4x70_data_t *etd, bool ledcontrol) {
|
|||
|
||||
int status = PM3_ESOFT;
|
||||
|
||||
g_command_parity = etd->parity;
|
||||
g_deprecated_command_parity = false;
|
||||
|
||||
// Disable to prevent sending corrupted data to the tag.
|
||||
if (g_command_parity) {
|
||||
if (g_deprecated_command_parity) {
|
||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 setpin` is non-functional and may corrupt data on the tag."));
|
||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||
// return;
|
||||
|
@ -1639,10 +1633,10 @@ void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol) {
|
|||
|
||||
int status = PM3_ESOFT;
|
||||
|
||||
g_command_parity = etd->parity;
|
||||
g_deprecated_command_parity = false;
|
||||
|
||||
// Disable to prevent sending corrupted data to the tag.
|
||||
if (g_command_parity) {
|
||||
if (g_deprecated_command_parity) {
|
||||
DPRINTF_ALWAYS(("Use of `--par` option with `lf em 4x70 setkey` is non-functional and may corrupt data on the tag."));
|
||||
// reply_ng(CMD_LF_EM4X70_WRITE, PM3_ENOTIMPL, NULL, 0);
|
||||
// return;
|
||||
|
|
|
@ -86,18 +86,12 @@ typedef struct _em4x70_tag_info_t {
|
|||
uint8_t Raw[32];
|
||||
} em4x70_tag_info_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_info_t {
|
||||
uint8_t use_parity;
|
||||
} em4x70_cmd_input_info_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_writeblock_t {
|
||||
uint8_t use_parity;
|
||||
uint8_t block;
|
||||
uint8_t value[2];
|
||||
} em4x70_cmd_input_writeblock_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_brute_t {
|
||||
uint8_t use_parity;
|
||||
ID48LIB_NONCE rn;
|
||||
ID48LIB_FRN frn;
|
||||
uint8_t block;
|
||||
|
@ -121,12 +115,10 @@ typedef struct _em4x70_cmd_output_brute_t {
|
|||
} em4x70_cmd_output_brute_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_unlock_t {
|
||||
uint8_t use_parity;
|
||||
uint8_t pin[4];
|
||||
} em4x70_cmd_input_unlock_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_auth_t {
|
||||
uint8_t use_parity;
|
||||
ID48LIB_NONCE rn;
|
||||
ID48LIB_FRN frn;
|
||||
} em4x70_cmd_input_auth_t;
|
||||
|
@ -136,12 +128,10 @@ typedef struct _em4x70_cmd_output_auth_t {
|
|||
} em4x70_cmd_output_auth_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_setpin_t {
|
||||
uint8_t use_parity;
|
||||
uint8_t pin[4];
|
||||
} em4x70_cmd_input_setpin_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_setkey_t {
|
||||
uint8_t use_parity;
|
||||
ID48LIB_KEY key;
|
||||
} em4x70_cmd_input_setkey_t;
|
||||
|
||||
|
@ -151,7 +141,6 @@ typedef struct _em4x70_cmd_input_recover_t {
|
|||
ID48LIB_NONCE nonce;
|
||||
ID48LIB_FRN frn;
|
||||
ID48LIB_GRN grn;
|
||||
bool parity; // if true, add parity bit to commands sent to tag
|
||||
bool verify; // if true, tag must be present
|
||||
} em4x70_cmd_input_recover_t;
|
||||
|
||||
|
@ -164,7 +153,6 @@ typedef struct _em4x70_cmd_output_recover_t {
|
|||
} em4x70_cmd_output_recover_t;
|
||||
|
||||
typedef struct _em4x70_cmd_input_verify_auth_t {
|
||||
uint8_t use_parity;
|
||||
ID48LIB_NONCE rn;
|
||||
ID48LIB_FRN frn;
|
||||
ID48LIB_GRN grn;
|
||||
|
@ -228,12 +216,12 @@ static void em4x70_print_info_result(const em4x70_tag_info_t *data) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
static int get_em4x70_info(const em4x70_cmd_input_info_t *opts, em4x70_tag_info_t *data_out) {
|
||||
static int get_em4x70_info(em4x70_tag_info_t *data_out) {
|
||||
|
||||
memset(data_out, 0, sizeof(em4x70_tag_info_t));
|
||||
|
||||
// TODO: change firmware to use per-cmd structures
|
||||
em4x70_data_t edata = { .parity = opts->use_parity };
|
||||
em4x70_data_t edata = {0};
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X70_INFO, (uint8_t *)&edata, sizeof(em4x70_data_t));
|
||||
PacketResponseNG resp;
|
||||
|
@ -251,10 +239,10 @@ static int writeblock_em4x70(const em4x70_cmd_input_writeblock_t *opts, em4x70_t
|
|||
memset(data_out, 0, sizeof(em4x70_tag_info_t));
|
||||
|
||||
// TODO: change firmware to use per-cmd structures
|
||||
em4x70_data_t etd = {0};
|
||||
etd.address = opts->block;
|
||||
etd.word = BYTES2UINT16(opts->value);
|
||||
etd.parity = opts->use_parity;
|
||||
em4x70_data_t etd = {
|
||||
.address = opts->block,
|
||||
.word = BYTES2UINT16(opts->value),
|
||||
};
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X70_WRITE, (uint8_t *)&etd, sizeof(etd));
|
||||
|
@ -273,7 +261,6 @@ static int auth_em4x70(const em4x70_cmd_input_auth_t *opts, em4x70_cmd_output_au
|
|||
|
||||
// TODO: change firmware to use per-cmd structures
|
||||
em4x70_data_t etd = {0};
|
||||
etd.parity = opts->use_parity;
|
||||
memcpy(&etd.rnd[0], &opts->rn.rn[0], 7);
|
||||
memcpy(&etd.frnd[0], &opts->frn.frn[0], 4);
|
||||
|
||||
|
@ -298,7 +285,6 @@ static int setkey_em4x70(const em4x70_cmd_input_setkey_t *opts) {
|
|||
|
||||
// TODO: change firmware to use per-cmd structures
|
||||
em4x70_data_t etd = {0};
|
||||
etd.parity = opts->use_parity;
|
||||
memcpy(&etd.crypt_key[0], &opts->key.k[0], 12);
|
||||
|
||||
clearCommandBuffer();
|
||||
|
@ -315,7 +301,6 @@ static int brute_em4x70(const em4x70_cmd_input_brute_t *opts, em4x70_cmd_output_
|
|||
|
||||
// TODO: change firmware to use per-cmd structures
|
||||
em4x70_data_t etd = {0};
|
||||
etd.parity = opts->use_parity;
|
||||
etd.address = opts->block;
|
||||
memcpy(&etd.rnd[0], &opts->rn.rn[0], 7);
|
||||
memcpy(&etd.frnd[0], &opts->frn.frn[0], 4);
|
||||
|
@ -366,7 +351,6 @@ static int unlock_em4x70(const em4x70_cmd_input_unlock_t *opts, em4x70_tag_info_
|
|||
|
||||
// TODO: change firmware to use per-cmd structures
|
||||
em4x70_data_t etd = {0};
|
||||
etd.parity = opts->use_parity;
|
||||
etd.pin = BYTES2UINT32(opts->pin);
|
||||
|
||||
clearCommandBuffer();
|
||||
|
@ -386,7 +370,6 @@ static int setpin_em4x70(const em4x70_cmd_input_setpin_t *opts, em4x70_tag_info_
|
|||
|
||||
// TODO: change firmware to use per-cmd structures
|
||||
em4x70_data_t etd = {0};
|
||||
etd.parity = opts->use_parity;
|
||||
etd.pin = BYTES2UINT32(opts->pin);
|
||||
|
||||
clearCommandBuffer();
|
||||
|
@ -429,7 +412,6 @@ static int recover_em4x70(const em4x70_cmd_input_recover_t *opts, em4x70_cmd_out
|
|||
|
||||
static int verify_auth_em4x70(const em4x70_cmd_input_verify_auth_t *opts) {
|
||||
em4x70_cmd_input_auth_t opts_auth = {
|
||||
.use_parity = opts->use_parity,
|
||||
.rn = opts->rn,
|
||||
.frn = opts->frn,
|
||||
};
|
||||
|
@ -458,24 +440,19 @@ static int CmdEM4x70Info(const char *Cmd) {
|
|||
" ID48 does not use command parity (default).\n"
|
||||
" V4070 and EM4170 do require parity bit.",
|
||||
"lf em 4x70 info\n"
|
||||
"lf em 4x70 info --par -> adds parity bit to command\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
em4x70_cmd_input_info_t opts = {
|
||||
.use_parity = arg_get_lit(ctx, 0),
|
||||
};
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// Client command line parsing and validation complete ... now use the helper function
|
||||
em4x70_tag_info_t info;
|
||||
int result = get_em4x70_info(&opts, &info);
|
||||
int result = get_em4x70_info(&info);
|
||||
|
||||
if (result == PM3_ETIMEOUT) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
|
@ -494,12 +471,10 @@ static int CmdEM4x70Write(const char *Cmd) {
|
|||
CLIParserInit(&ctx, "lf em 4x70 write",
|
||||
"Write EM4x70\n",
|
||||
"lf em 4x70 write -b 15 -d c0de -> write 'c0de' to block 15\n"
|
||||
"lf em 4x70 write -b 15 -d c0de --par -> adds parity bit to commands\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_int1("b", "block", "<dec>", "block/word address, dec"),
|
||||
arg_str1("d", "data", "<hex>", "data, 2 bytes"),
|
||||
arg_param_end
|
||||
|
@ -508,12 +483,12 @@ static int CmdEM4x70Write(const char *Cmd) {
|
|||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
em4x70_cmd_input_writeblock_t opts = {
|
||||
.use_parity = arg_get_lit(ctx, 1),
|
||||
.block = arg_get_int_def(ctx, 2, 1),
|
||||
.block = arg_get_int_def(ctx, 1, 1),
|
||||
.value = {0}, // hex value macro exits function, so cannot be initialized here
|
||||
};
|
||||
|
||||
int value_len = 0;
|
||||
CLIGetHexWithReturn(ctx, 3, opts.value, &value_len);
|
||||
CLIGetHexWithReturn(ctx, 2, opts.value, &value_len);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (opts.block >= EM4X70_NUM_BLOCKS) {
|
||||
|
@ -555,7 +530,6 @@ static int CmdEM4x70Brute(const char *Cmd) {
|
|||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_int1("b", "block", "<dec>", "block/word address, dec"),
|
||||
arg_str1(NULL, "rnd", "<hex>", "Random 56-bit"),
|
||||
arg_str1(NULL, "frn", "<hex>", "F(RN) 28-bit as 4 hex bytes"),
|
||||
|
@ -565,8 +539,7 @@ static int CmdEM4x70Brute(const char *Cmd) {
|
|||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
em4x70_cmd_input_brute_t opts = {
|
||||
.use_parity = arg_get_lit(ctx, 1),
|
||||
.block = arg_get_int_def(ctx, 2, 0),
|
||||
.block = arg_get_int_def(ctx, 1, 0),
|
||||
.rn = {{0}}, // hex value macro exits function, so cannot be initialized here
|
||||
.frn = {{0}}, // hex value macro exits function, so cannot be initialized here
|
||||
.partial_key_start = {0}, // hex value macro exits function, so cannot be initialized here
|
||||
|
@ -579,15 +552,15 @@ static int CmdEM4x70Brute(const char *Cmd) {
|
|||
}
|
||||
|
||||
int rnd_len = 7;
|
||||
CLIGetHexWithReturn(ctx, 3, opts.rn.rn, &rnd_len);
|
||||
CLIGetHexWithReturn(ctx, 2, opts.rn.rn, &rnd_len);
|
||||
|
||||
int frnd_len = 4;
|
||||
CLIGetHexWithReturn(ctx, 4, opts.frn.frn, &frnd_len);
|
||||
CLIGetHexWithReturn(ctx, 3, opts.frn.frn, &frnd_len);
|
||||
|
||||
// would prefer to use above CLIGetHexWithReturn(), but it does not
|
||||
// appear to support optional arguments.
|
||||
uint32_t start_key = 0;
|
||||
int res = arg_get_u32_hexstr_def_nlen(ctx, 5, 0, &start_key, 2, true); // this stores in NATIVE ENDIAN
|
||||
int res = arg_get_u32_hexstr_def_nlen(ctx, 4, 0, &start_key, 2, true); // this stores in NATIVE ENDIAN
|
||||
if (res == 2) {
|
||||
PrintAndLogEx(WARNING, "start key parameter must be in range [0, FFFF]");
|
||||
CLIParserFree(ctx);
|
||||
|
@ -635,11 +608,9 @@ static int CmdEM4x70Unlock(const char *Cmd) {
|
|||
" AAAAAAAA\n"
|
||||
" 00000000\n",
|
||||
"lf em 4x70 unlock -p 11223344 -> Unlock with PIN\n"
|
||||
"lf em 4x70 unlock -p 11223344 --par -> Unlock with PIN using parity commands\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_str1("p", "pin", "<hex>", "pin, 4 bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -647,11 +618,10 @@ static int CmdEM4x70Unlock(const char *Cmd) {
|
|||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
em4x70_cmd_input_unlock_t opts = {
|
||||
.use_parity = arg_get_lit(ctx, 1),
|
||||
.pin = {0}, // hex value macro exits function, so cannot be initialized here
|
||||
};
|
||||
int pin_len = 0;
|
||||
CLIGetHexWithReturn(ctx, 2, opts.pin, &pin_len);
|
||||
CLIGetHexWithReturn(ctx, 1, opts.pin, &pin_len);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (pin_len != 4) {
|
||||
|
@ -691,7 +661,6 @@ static int CmdEM4x70Auth(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_str1(NULL, "rnd", "<hex>", "Random 56-bit"),
|
||||
arg_str1(NULL, "frn", "<hex>", "F(RN) 28-bit as 4 hex bytes"),
|
||||
arg_param_end
|
||||
|
@ -700,15 +669,14 @@ static int CmdEM4x70Auth(const char *Cmd) {
|
|||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
em4x70_cmd_input_auth_t opts = {
|
||||
.use_parity = arg_get_lit(ctx, 1),
|
||||
.rn = {{0}}, // hex value macro exits function, so cannot be initialized here
|
||||
.frn = {{0}}, // hex value macro exits function, so cannot be initialized here
|
||||
};
|
||||
int rn_len = 7;
|
||||
CLIGetHexWithReturn(ctx, 2, opts.rn.rn, &rn_len);
|
||||
CLIGetHexWithReturn(ctx, 1, opts.rn.rn, &rn_len);
|
||||
|
||||
int frn_len = 4;
|
||||
CLIGetHexWithReturn(ctx, 3, opts.frn.frn, &frn_len);
|
||||
CLIGetHexWithReturn(ctx, 2, opts.frn.frn, &frn_len);
|
||||
CLIParserFree(ctx);
|
||||
if (rn_len != 7) {
|
||||
PrintAndLogEx(FAILED, "Random number length must be 7 bytes, got %d", rn_len);
|
||||
|
@ -738,23 +706,19 @@ static int CmdEM4x70SetPIN(const char *Cmd) {
|
|||
CLIParserInit(&ctx, "lf em 4x70 setpin",
|
||||
"Write new PIN\n",
|
||||
"lf em 4x70 setpin -p 11223344 -> Write new PIN\n"
|
||||
"lf em 4x70 setpin -p 11223344 --par -> Write new PIN using parity commands\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_str1("p", "pin", "<hex>", "pin, 4 bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
em4x70_cmd_input_setpin_t opts = {
|
||||
.use_parity = arg_get_lit(ctx, 1),
|
||||
.pin = {0}, // hex value macro exits function, so cannot be initialized here
|
||||
};
|
||||
|
||||
int pin_len = 0;
|
||||
CLIGetHexWithReturn(ctx, 2, opts.pin, &pin_len);
|
||||
CLIGetHexWithReturn(ctx, 1, opts.pin, &pin_len);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (pin_len != 4) {
|
||||
|
@ -789,19 +753,16 @@ static int CmdEM4x70SetKey(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_str1("k", "key", "<hex>", "Key as 12 hex bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
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
|
||||
};
|
||||
int key_len = 12;
|
||||
CLIGetHexWithReturn(ctx, 2, opts.key.k, &key_len);
|
||||
CLIGetHexWithReturn(ctx, 1, opts.key.k, &key_len);
|
||||
CLIParserFree(ctx);
|
||||
if (key_len != 12) {
|
||||
PrintAndLogEx(FAILED, "Key length must be 12 bytes, got %d", key_len);
|
||||
|
@ -823,7 +784,6 @@ static int CmdEM4x70SetKey(const char *Cmd) {
|
|||
|
||||
// Now verify authentication using the new key, to ensure it was correctly written
|
||||
em4x70_cmd_input_verify_auth_t opts_v = {
|
||||
.use_parity = opts.use_parity,
|
||||
//.rn = opts_auth.rn,
|
||||
//.frn = opts_auth.frn,
|
||||
//.grn = {{0}},
|
||||
|
@ -909,7 +869,6 @@ static int CmdEM4x70Recover_ParseArgs(const char *Cmd, em4x70_cmd_input_recover_
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_str1("k", "key", "<hex>", "Key as 6 hex bytes"),
|
||||
arg_str1(NULL, "rnd", "<hex>", "Random 56-bit"),
|
||||
arg_str1(NULL, "frn", "<hex>", "F(RN) 28-bit as 4 hex bytes"),
|
||||
|
@ -931,17 +890,16 @@ static int CmdEM4x70Recover_ParseArgs(const char *Cmd, em4x70_cmd_input_recover_
|
|||
// if all OK so far, convert to internal data structure
|
||||
if (PM3_SUCCESS == result) {
|
||||
// magic number == index in argtable above. Fragile technique!
|
||||
out_results->parity = arg_get_lit(ctx, 1);
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 2), &(out_results->key.k[0]), 12, &key_len)) {
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 1), &(out_results->key.k[0]), 12, &key_len)) {
|
||||
result = PM3_ESOFT;
|
||||
}
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 3), &(out_results->nonce.rn[0]), 7, &rnd_len)) {
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 2), &(out_results->nonce.rn[0]), 7, &rnd_len)) {
|
||||
result = PM3_ESOFT;
|
||||
}
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 4), &(out_results->frn.frn[0]), 4, &frn_len)) {
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 3), &(out_results->frn.frn[0]), 4, &frn_len)) {
|
||||
result = PM3_ESOFT;
|
||||
}
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 5), &(out_results->grn.grn[0]), 3, &grn_len)) {
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 4), &(out_results->grn.grn[0]), 3, &grn_len)) {
|
||||
result = PM3_ESOFT;
|
||||
}
|
||||
//out_results->verify = arg_get_lit(ctx, 6);
|
||||
|
@ -1112,7 +1070,6 @@ static int CmdEM4x70AutoRecover_ParseArgs(const char *Cmd, em4x70_cmd_input_reco
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
|
||||
arg_str1(NULL, "rnd", "<hex>", "Random 56-bit from known-good authentication"),
|
||||
arg_str1(NULL, "frn", "<hex>", "F(RN) 28-bit as 4 hex bytes from known-good authentication"),
|
||||
arg_str1(NULL, "grn", "<hex>", "G(RN) 20-bit as 3 hex bytes from known-good authentication"),
|
||||
|
@ -1125,10 +1082,9 @@ static int CmdEM4x70AutoRecover_ParseArgs(const char *Cmd, em4x70_cmd_input_reco
|
|||
int rnd_len = 0; // must be 7 bytes hex data
|
||||
int frn_len = 0; // must be 4 bytes hex data
|
||||
int grn_len = 0; // must be 3 bytes hex data
|
||||
out_results->parity = arg_get_lit(ctx, 1);
|
||||
CLIGetHexWithReturn(ctx, 2, out_results->nonce.rn, &rnd_len);
|
||||
CLIGetHexWithReturn(ctx, 3, out_results->frn.frn, &frn_len);
|
||||
CLIGetHexWithReturn(ctx, 4, out_results->grn.grn, &grn_len);
|
||||
CLIGetHexWithReturn(ctx, 1, out_results->nonce.rn, &rnd_len);
|
||||
CLIGetHexWithReturn(ctx, 2, out_results->frn.frn, &frn_len);
|
||||
CLIGetHexWithReturn(ctx, 3, out_results->grn.grn, &grn_len);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (rnd_len != 7) {
|
||||
|
@ -1190,7 +1146,6 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
|
|||
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 auth --rnd %s --frn %s"), rnd_string, frn_string);
|
||||
|
||||
em4x70_cmd_input_auth_t opts_auth = {
|
||||
.use_parity = opts.parity,
|
||||
.rn = opts.nonce,
|
||||
.frn = opts.frn,
|
||||
};
|
||||
|
@ -1234,7 +1189,6 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
|
|||
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 write -b %d -d 0000"), block);
|
||||
|
||||
em4x70_cmd_input_writeblock_t opt_write_zeros = {
|
||||
.use_parity = opts.parity,
|
||||
.block = block,
|
||||
.value = {0x00, 0x00},
|
||||
};
|
||||
|
@ -1255,7 +1209,6 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
|
|||
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 brute -b %d --rnd %s --frn %s"), block, rnd_string, frn_string);
|
||||
|
||||
em4x70_cmd_input_brute_t opts_brute = {
|
||||
.use_parity = opts.parity,
|
||||
.block = block,
|
||||
.rn = opts.nonce,
|
||||
.frn = opts.frn,
|
||||
|
@ -1294,7 +1247,6 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
|
|||
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 write -b %d -d %02X%02X"), block, brute.partial_key[0], brute.partial_key[1]);
|
||||
|
||||
em4x70_cmd_input_writeblock_t opt_write_zeros2 = {
|
||||
.use_parity = opts.parity,
|
||||
.block = block,
|
||||
.value = {brute.partial_key[0], brute.partial_key[1]},
|
||||
};
|
||||
|
@ -1354,7 +1306,6 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "Step 6. Verify which potential key is actually on the tag");
|
||||
|
||||
em4x70_cmd_input_verify_auth_t opts_v = {
|
||||
.use_parity = opts.parity,
|
||||
//.rn = {{0}},
|
||||
//.frn = {{0}},
|
||||
//.grn = {{0}},
|
||||
|
@ -1554,9 +1505,8 @@ int CmdLFEM4X70(const char *Cmd) {
|
|||
// Use helper function `get_em4x70_info()` if wanting to limit / avoid output.
|
||||
bool detect_4x70_block(void) {
|
||||
em4x70_tag_info_t info;
|
||||
em4x70_cmd_input_info_t opts = { 0 };
|
||||
|
||||
int result = get_em4x70_info(&opts, &info);
|
||||
int result = get_em4x70_info(&info);
|
||||
|
||||
if (result == PM3_ETIMEOUT) { // consider removing this output?
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
/// The only requirement is that this structure remain
|
||||
/// smaller than the NG buffer size (256 bytes).
|
||||
typedef struct {
|
||||
bool parity;
|
||||
bool _ignored__was_use_parity; // BUGBUG: Ignored, but kept for structure size / offset compatibility
|
||||
|
||||
// Used for writing address
|
||||
uint8_t address;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue