Merge pull request #2532 from douniwan5788/hitag_common

refactor: process Hitag S common args
This commit is contained in:
Iceman 2024-09-23 12:01:31 +03:00 committed by GitHub
commit 4f0e062f21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 97 additions and 166 deletions

View file

@ -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));

View file

@ -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;