mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
Merge pull request #2532 from douniwan5788/hitag_common
refactor: process Hitag S common args
This commit is contained in:
commit
4f0e062f21
2 changed files with 97 additions and 166 deletions
|
@ -92,85 +92,60 @@ int read_hts_uid(void) {
|
|||
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 -> 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);
|
||||
static int process_hitags_common_args(CLIParserContext *ctx, lf_hitag_data_t *const packet) {
|
||||
|
||||
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 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) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool use_nrar = nrar_len > 0;
|
||||
bool use_82xx = arg_get_lit(ctx, 2);
|
||||
use_nrar = nrar_len > 0;
|
||||
|
||||
bool use_crypto = arg_get_lit(ctx, 3);
|
||||
|
||||
uint8_t key[6];
|
||||
uint8_t key[HITAG_CRYPTOKEY_SIZE];
|
||||
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) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (key_len != 0 && key_len != 4 && key_len != 6) {
|
||||
if (key_len != 0 && key_len != HITAG_PASSWORD_SIZE && key_len != HITAG_CRYPTOKEY_SIZE) {
|
||||
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);
|
||||
if (nrar_len && nrar_len != HITAG_NRAR_SIZE) {
|
||||
PrintAndLogEx(WARNING, "Wrong NR/AR len expected %d, got %d", HITAG_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;
|
||||
switch (key_len) {
|
||||
case HITAG_PASSWORD_SIZE:
|
||||
use_82xx = true;
|
||||
break;
|
||||
case HITAG_CRYPTOKEY_SIZE:
|
||||
use_crypto = true;
|
||||
break;
|
||||
default: // key_len == 0
|
||||
if (use_82xx) {
|
||||
memcpy(key, "\xBB\xDD\x33\x99", 4);
|
||||
key_len = 4;
|
||||
} else if (use_crypto) {
|
||||
memcpy(key, "ONMIKR", 6);
|
||||
key_len = 6;
|
||||
}
|
||||
}
|
||||
|
||||
// check coherence
|
||||
|
@ -184,23 +159,60 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
|||
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;
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
|
||||
if (use_nrar) {
|
||||
packet.cmd = HTSF_CHALLENGE;
|
||||
memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
|
||||
}
|
||||
if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
|
||||
|
||||
if (use_82xx) {
|
||||
packet.cmd = HTSF_82xx;
|
||||
memcpy(packet.pwd, key, sizeof(packet.pwd));
|
||||
}
|
||||
// int page = arg_get_int_def(ctx, 5, 0); // not implemented yet
|
||||
|
||||
if (use_crypto) {
|
||||
packet.cmd = HTSF_KEY;
|
||||
memcpy(packet.key, key, sizeof(packet.key));
|
||||
}
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_HITAGS_READ, (uint8_t *) &packet, sizeof(packet));
|
||||
|
@ -217,11 +229,6 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// ??
|
||||
if (use_nrar) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
|
||||
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[] = {
|
||||
arg_param_begin,
|
||||
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
|
||||
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 write to"),
|
||||
|
@ -270,36 +277,16 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool use_plain = false;
|
||||
lf_hitag_data_t packet;
|
||||
|
||||
uint8_t nrar[8];
|
||||
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;
|
||||
}
|
||||
if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
|
||||
|
||||
int page = arg_get_int_def(ctx, 5, 0);
|
||||
|
||||
uint8_t data[4];
|
||||
uint8_t data[HITAGS_PAGE_SIZE];
|
||||
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) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
|
@ -307,64 +294,8 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
|||
|
||||
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;
|
||||
memcpy(packet.data, data, sizeof(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");
|
||||
}
|
||||
memcpy(packet.data, data, sizeof(packet.data));
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *) &packet, sizeof(packet));
|
||||
|
|
|
@ -31,15 +31,13 @@
|
|||
#define HITAG2_MAX_BLOCKS 8
|
||||
#define HITAG2_MAX_BYTE_SIZE (HITAG2_MAX_BLOCKS * HITAG_BLOCK_SIZE)
|
||||
|
||||
#define HITAGS_NRAR_SIZE 8
|
||||
#define HITAGS_CRYPTOKEY_SIZE 6
|
||||
#define HITAGS_UID_SIZE 4
|
||||
#define HITAGS_PAGE_SIZE 4
|
||||
#define HITAGS_BLOCK_SIZE 16
|
||||
#define HITAGS_MAX_PAGES 64
|
||||
#define HITAGS_MAX_BYTE_SIZE (HITAGS_MAX_PAGES * HITAGS_PAGE_SIZE)
|
||||
#define HITAGS_UID_PADR 0
|
||||
#define HITAGS_CONFIG_PADR 1
|
||||
#define HITAGS_PAGE_SIZE HITAG_BLOCK_SIZE
|
||||
#define HITAGS_BLOCK_PAGES 4
|
||||
#define HITAGS_BLOCK_SIZE (HITAGS_BLOCK_PAGES * HITAGS_MAX_PAGES)
|
||||
#define HITAGS_MAX_PAGES 64
|
||||
#define HITAGS_MAX_BYTE_SIZE (HITAGS_MAX_PAGES * HITAGS_PAGE_SIZE)
|
||||
#define HITAGS_UID_PADR 0
|
||||
#define HITAGS_CONFIG_PADR 1
|
||||
|
||||
// need to see which limits these cards has
|
||||
#define HITAG1_MAX_BYTE_SIZE 64
|
||||
|
@ -70,10 +68,12 @@ typedef enum {
|
|||
typedef struct {
|
||||
hitag_function cmd;
|
||||
int16_t page;
|
||||
uint8_t data[4];
|
||||
uint8_t NrAr[8];
|
||||
uint8_t key[6];
|
||||
uint8_t pwd[4];
|
||||
uint8_t data[HITAGS_PAGE_SIZE];
|
||||
uint8_t NrAr[HITAG_NRAR_SIZE];
|
||||
// unaligned access to key as uint64_t will abort.
|
||||
// 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.
|
||||
// will reuse pwd or key field.
|
||||
|
@ -157,7 +157,7 @@ struct hitagS_tag {
|
|||
// page 2
|
||||
uint8_t pwdl0;
|
||||
uint8_t pwdl1;
|
||||
uint64_t key : 48;
|
||||
uint64_t key : 48; // fixme: unaligned access
|
||||
|
||||
// page 4
|
||||
} s;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue