mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
refactor: process Hitag S common args
This commit is contained in:
parent
d2783214e3
commit
f03eb1156a
2 changed files with 97 additions and 166 deletions
|
@ -92,85 +92,60 @@ int read_hts_uid(void) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdLFHitagSRead(const char *Cmd) {
|
static int process_hitags_common_args(CLIParserContext *ctx, lf_hitag_data_t *const packet) {
|
||||||
CLIParserContext *ctx;
|
|
||||||
CLIParserInit(&ctx, "lf hitag hts rdbl",
|
|
||||||
"Read Hitag S memory.\n\n"
|
|
||||||
" Crypto mode: \n"
|
|
||||||
" - key format ISK high + ISK low\n"
|
|
||||||
" - default key 4F4E4D494B52 (ONMIKR)\n\n"
|
|
||||||
" 8268/8310 password mode: \n"
|
|
||||||
" - default password BBDD3399\n",
|
|
||||||
" lf hitag hts rdbl -> Hitag S/8211, plain mode\n"
|
|
||||||
" lf hitag hts rdbl --82xx -k BBDD3399 -> 8268/8310, password mode\n"
|
|
||||||
" lf hitag hts rdbl --nrar 0102030411223344 -> Hitag S, challenge mode\n"
|
|
||||||
" lf hitag hts rdbl --crypto -> Hitag S, crypto mode, def key\n"
|
|
||||||
" lf hitag hts rdbl -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
void *argtable[] = {
|
|
||||||
arg_param_begin,
|
|
||||||
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
|
|
||||||
arg_lit0("8", "82xx", "8268/8310 mode"),
|
|
||||||
arg_lit0(NULL, "crypto", "crypto mode"),
|
|
||||||
arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
|
|
||||||
arg_param_end
|
|
||||||
};
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
|
||||||
|
|
||||||
bool use_plain = false;
|
bool use_plain = false;
|
||||||
|
bool use_82xx = arg_get_lit(ctx, 1);
|
||||||
|
|
||||||
uint8_t nrar[8];
|
bool use_nrar = false;
|
||||||
|
uint8_t nrar[HITAG_NRAR_SIZE];
|
||||||
int nrar_len = 0;
|
int nrar_len = 0;
|
||||||
|
|
||||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), nrar, sizeof(nrar), &nrar_len);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), nrar, HITAG_NRAR_SIZE, &nrar_len);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_nrar = nrar_len > 0;
|
use_nrar = nrar_len > 0;
|
||||||
bool use_82xx = arg_get_lit(ctx, 2);
|
|
||||||
bool use_crypto = arg_get_lit(ctx, 3);
|
bool use_crypto = arg_get_lit(ctx, 3);
|
||||||
|
|
||||||
uint8_t key[6];
|
uint8_t key[HITAG_CRYPTOKEY_SIZE];
|
||||||
int key_len = 0;
|
int key_len = 0;
|
||||||
|
|
||||||
res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &key_len);
|
res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, HITAG_CRYPTOKEY_SIZE, &key_len);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
if (key_len != 0 && key_len != HITAG_PASSWORD_SIZE && key_len != HITAG_CRYPTOKEY_SIZE) {
|
||||||
|
|
||||||
if (key_len != 0 && key_len != 4 && key_len != 6) {
|
|
||||||
PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", key_len);
|
PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", key_len);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nrar_len && nrar_len != HITAGS_NRAR_SIZE) {
|
if (nrar_len && nrar_len != HITAG_NRAR_SIZE) {
|
||||||
PrintAndLogEx(WARNING, "Wrong NR/AR len expected %d, got %d", HITAGS_NRAR_SIZE, nrar_len);
|
PrintAndLogEx(WARNING, "Wrong NR/AR len expected %d, got %d", HITAG_NRAR_SIZE, nrar_len);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete options
|
// complete options
|
||||||
if (key_len == 4) {
|
switch (key_len) {
|
||||||
use_82xx = true;
|
case HITAG_PASSWORD_SIZE:
|
||||||
}
|
use_82xx = true;
|
||||||
|
break;
|
||||||
if (key_len == 6) {
|
case HITAG_CRYPTOKEY_SIZE:
|
||||||
use_crypto = true;
|
use_crypto = true;
|
||||||
}
|
break;
|
||||||
|
default: // key_len == 0
|
||||||
if ((key_len == 0) && use_82xx) {
|
if (use_82xx) {
|
||||||
memcpy(key, "\xBB\xDD\x33\x99", 4);
|
memcpy(key, "\xBB\xDD\x33\x99", 4);
|
||||||
key_len = 4;
|
key_len = 4;
|
||||||
}
|
} else if (use_crypto) {
|
||||||
|
memcpy(key, "ONMIKR", 6);
|
||||||
if ((key_len == 0) && use_crypto) {
|
key_len = 6;
|
||||||
memcpy(key, "ONMIKR", 6);
|
}
|
||||||
key_len = 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check coherence
|
// check coherence
|
||||||
|
@ -184,23 +159,60 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
||||||
use_plain = true;
|
use_plain = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(packet, 0, sizeof(*packet));
|
||||||
|
|
||||||
|
if (use_plain) {
|
||||||
|
PrintAndLogEx(INFO, "Access " _YELLOW_("Hitag S") " in Plain mode");
|
||||||
|
} else if (use_nrar) {
|
||||||
|
packet->cmd = HTSF_CHALLENGE;
|
||||||
|
memcpy(packet->NrAr, nrar, sizeof(packet->NrAr));
|
||||||
|
PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Challenge mode");
|
||||||
|
} else if (use_82xx) {
|
||||||
|
packet->cmd = HTSF_82xx;
|
||||||
|
memcpy(packet->pwd, key, sizeof(packet->pwd));
|
||||||
|
PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in 82xx mode");
|
||||||
|
} else if (use_crypto) {
|
||||||
|
packet->cmd = HTSF_KEY;
|
||||||
|
memcpy(packet->key, key, sizeof(packet->key));
|
||||||
|
PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Crypto mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
static int CmdLFHitagSRead(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf hitag hts rdbl",
|
||||||
|
"Read Hitag S memory.\n\n"
|
||||||
|
" Crypto mode: \n"
|
||||||
|
" - key format ISK high + ISK low\n"
|
||||||
|
" - default key 4F4E4D494B52 (ONMIKR)\n\n"
|
||||||
|
" 8268/8310 password mode: \n"
|
||||||
|
" - default password BBDD3399\n",
|
||||||
|
" lf hitag hts rdbl -p 1 -> Hitag S/8211, plain mode\n"
|
||||||
|
" lf hitag hts rdbl -p 1 --82xx -k BBDD3399 -> 8268/8310, password mode\n"
|
||||||
|
" lf hitag hts rdbl -p 1 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
|
||||||
|
" lf hitag hts rdbl -p 1 --crypto -> Hitag S, crypto mode, def key\n"
|
||||||
|
" lf hitag hts rdbl -p 1 -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("8", "82xx", "8268/8310 mode"),
|
||||||
|
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
|
||||||
|
arg_lit0(NULL, "crypto", "crypto mode"),
|
||||||
|
arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
|
||||||
|
arg_int1("p", "page", "<dec>", "page address to read from"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
lf_hitag_data_t packet;
|
lf_hitag_data_t packet;
|
||||||
memset(&packet, 0, sizeof(packet));
|
|
||||||
|
|
||||||
if (use_nrar) {
|
if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
|
||||||
packet.cmd = HTSF_CHALLENGE;
|
|
||||||
memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_82xx) {
|
// int page = arg_get_int_def(ctx, 5, 0); // not implemented yet
|
||||||
packet.cmd = HTSF_82xx;
|
|
||||||
memcpy(packet.pwd, key, sizeof(packet.pwd));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_crypto) {
|
CLIParserFree(ctx);
|
||||||
packet.cmd = HTSF_KEY;
|
|
||||||
memcpy(packet.key, key, sizeof(packet.key));
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_HITAGS_READ, (uint8_t *) &packet, sizeof(packet));
|
SendCommandNG(CMD_LF_HITAGS_READ, (uint8_t *) &packet, sizeof(packet));
|
||||||
|
@ -217,11 +229,6 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ??
|
|
||||||
if (use_nrar) {
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
|
|
||||||
hitags_config_t config = hitags_config_unpack(&data[HITAGS_PAGE_SIZE * HITAGS_CONFIG_PADR]);
|
hitags_config_t config = hitags_config_unpack(&data[HITAGS_PAGE_SIZE * HITAGS_CONFIG_PADR]);
|
||||||
|
@ -260,8 +267,8 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
|
|
||||||
arg_lit0("8", "82xx", "8268/8310 mode"),
|
arg_lit0("8", "82xx", "8268/8310 mode"),
|
||||||
|
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
|
||||||
arg_lit0(NULL, "crypto", "crypto mode"),
|
arg_lit0(NULL, "crypto", "crypto mode"),
|
||||||
arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
|
arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
|
||||||
arg_int1("p", "page", "<dec>", "page address to write to"),
|
arg_int1("p", "page", "<dec>", "page address to write to"),
|
||||||
|
@ -270,36 +277,16 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
bool use_plain = false;
|
lf_hitag_data_t packet;
|
||||||
|
|
||||||
uint8_t nrar[8];
|
if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
|
||||||
int nrar_len = 0;
|
|
||||||
|
|
||||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), nrar, sizeof(nrar), &nrar_len);
|
|
||||||
if (res != 0) {
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool use_nrar = nrar_len > 0;
|
|
||||||
bool use_82xx = arg_get_lit(ctx, 2);
|
|
||||||
bool use_crypto = arg_get_lit(ctx, 3);
|
|
||||||
|
|
||||||
uint8_t key[6];
|
|
||||||
int key_len = 0;
|
|
||||||
|
|
||||||
res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &key_len);
|
|
||||||
if (res != 0) {
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
int page = arg_get_int_def(ctx, 5, 0);
|
int page = arg_get_int_def(ctx, 5, 0);
|
||||||
|
|
||||||
uint8_t data[4];
|
uint8_t data[HITAGS_PAGE_SIZE];
|
||||||
int data_len = 0;
|
int data_len = 0;
|
||||||
|
|
||||||
res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, sizeof(data), &data_len);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, HITAGS_PAGE_SIZE, &data_len);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
@ -307,64 +294,8 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (key_len != 0 && key_len != 4 && key_len != 6) {
|
|
||||||
PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", key_len);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nrar_len && nrar_len != HITAGS_NRAR_SIZE) {
|
|
||||||
PrintAndLogEx(WARNING, "Wrong NR/AR len expected %d, got %d", HITAGS_NRAR_SIZE, nrar_len);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// complete options
|
|
||||||
if (key_len == 4) {
|
|
||||||
use_82xx = true;
|
|
||||||
}
|
|
||||||
if (key_len == 6) {
|
|
||||||
use_crypto = true;
|
|
||||||
}
|
|
||||||
if ((key_len == 0) && use_82xx) {
|
|
||||||
memcpy(key, "\xBB\xDD\x33\x99", 4);
|
|
||||||
key_len = 4;
|
|
||||||
}
|
|
||||||
if ((key_len == 0) && use_crypto) {
|
|
||||||
memcpy(key, "ONMIKR", 6);
|
|
||||||
key_len = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check coherence
|
|
||||||
uint8_t auth_methods = (use_plain + use_nrar + use_82xx + use_crypto);
|
|
||||||
if (auth_methods > 1) {
|
|
||||||
PrintAndLogEx(WARNING, "Specify only one authentication mode");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
} else if (auth_methods == 0) {
|
|
||||||
use_plain = true;
|
|
||||||
PrintAndLogEx(INFO, "Write to " _YELLOW_("Hitag S") " in Plain mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
lf_hitag_data_t packet;
|
|
||||||
memset(&packet, 0, sizeof(packet));
|
|
||||||
|
|
||||||
packet.page = page;
|
packet.page = page;
|
||||||
memcpy(packet.data, data, sizeof(data));
|
memcpy(packet.data, data, sizeof(packet.data));
|
||||||
|
|
||||||
if (use_nrar) {
|
|
||||||
packet.cmd = HTSF_CHALLENGE;
|
|
||||||
memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
|
|
||||||
PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Challenge mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_82xx) {
|
|
||||||
packet.cmd = HTSF_82xx;
|
|
||||||
memcpy(packet.pwd, key, sizeof(packet.pwd));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_crypto) {
|
|
||||||
packet.cmd = HTSF_KEY;
|
|
||||||
memcpy(packet.key, key, sizeof(packet.key));
|
|
||||||
PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Crypto mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *) &packet, sizeof(packet));
|
SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *) &packet, sizeof(packet));
|
||||||
|
|
|
@ -31,15 +31,13 @@
|
||||||
#define HITAG2_MAX_BLOCKS 8
|
#define HITAG2_MAX_BLOCKS 8
|
||||||
#define HITAG2_MAX_BYTE_SIZE (HITAG2_MAX_BLOCKS * HITAG_BLOCK_SIZE)
|
#define HITAG2_MAX_BYTE_SIZE (HITAG2_MAX_BLOCKS * HITAG_BLOCK_SIZE)
|
||||||
|
|
||||||
#define HITAGS_NRAR_SIZE 8
|
#define HITAGS_PAGE_SIZE HITAG_BLOCK_SIZE
|
||||||
#define HITAGS_CRYPTOKEY_SIZE 6
|
#define HITAGS_BLOCK_PAGES 4
|
||||||
#define HITAGS_UID_SIZE 4
|
#define HITAGS_BLOCK_SIZE (HITAGS_BLOCK_PAGES * HITAGS_MAX_PAGES)
|
||||||
#define HITAGS_PAGE_SIZE 4
|
#define HITAGS_MAX_PAGES 64
|
||||||
#define HITAGS_BLOCK_SIZE 16
|
#define HITAGS_MAX_BYTE_SIZE (HITAGS_MAX_PAGES * HITAGS_PAGE_SIZE)
|
||||||
#define HITAGS_MAX_PAGES 64
|
#define HITAGS_UID_PADR 0
|
||||||
#define HITAGS_MAX_BYTE_SIZE (HITAGS_MAX_PAGES * HITAGS_PAGE_SIZE)
|
#define HITAGS_CONFIG_PADR 1
|
||||||
#define HITAGS_UID_PADR 0
|
|
||||||
#define HITAGS_CONFIG_PADR 1
|
|
||||||
|
|
||||||
// need to see which limits these cards has
|
// need to see which limits these cards has
|
||||||
#define HITAG1_MAX_BYTE_SIZE 64
|
#define HITAG1_MAX_BYTE_SIZE 64
|
||||||
|
@ -70,10 +68,12 @@ typedef enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
hitag_function cmd;
|
hitag_function cmd;
|
||||||
int16_t page;
|
int16_t page;
|
||||||
uint8_t data[4];
|
uint8_t data[HITAGS_PAGE_SIZE];
|
||||||
uint8_t NrAr[8];
|
uint8_t NrAr[HITAG_NRAR_SIZE];
|
||||||
uint8_t key[6];
|
// unaligned access to key as uint64_t will abort.
|
||||||
uint8_t pwd[4];
|
// todo: Why does the compiler without -munaligned-access generate unaligned-access code in the first place?
|
||||||
|
uint8_t key[HITAG_CRYPTOKEY_SIZE] __attribute__((aligned(4)));
|
||||||
|
uint8_t pwd[HITAG_PASSWORD_SIZE];
|
||||||
|
|
||||||
// Hitag 1 section.
|
// Hitag 1 section.
|
||||||
// will reuse pwd or key field.
|
// will reuse pwd or key field.
|
||||||
|
@ -157,7 +157,7 @@ struct hitagS_tag {
|
||||||
// page 2
|
// page 2
|
||||||
uint8_t pwdl0;
|
uint8_t pwdl0;
|
||||||
uint8_t pwdl1;
|
uint8_t pwdl1;
|
||||||
uint64_t key : 48;
|
uint64_t key : 48; // fixme: unaligned access
|
||||||
|
|
||||||
// page 4
|
// page 4
|
||||||
} s;
|
} s;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue