Merge pull request #2513 from douniwan5788/hitagS_tag

refactor: switch hitagS_tag to union
This commit is contained in:
Iceman 2024-09-17 13:18:27 +02:00 committed by GitHub
commit 6149a6f6c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 114 additions and 193 deletions

View file

@ -39,7 +39,7 @@
#define CRC_POLYNOM 0x1D
static struct hitagS_tag tag = {
.pages =
.data.pages =
{
// Plain mode: | Authentication mode:
[0] = {0x88, 0xcd, 0x6d, 0xf3}, // UID | UID
@ -70,8 +70,8 @@ static uint32_t rnd = 0x74124485; // random number
//#define SENDBIT_TEST
/* array index 3 2 1 0 // bytes in sim.bin file are 0 1 2 3
// UID is 0 1 2 3 // tag.uid is 3210
// datasheet HitagS_V11.pdf bytes in tables printed 3 2 1 0
UID is 0 1 2 3 // tag.data.s.uid_le is 3210
datasheet HitagS_V11.pdf bytes in tables printed 3 2 1 0
#db# UID: 5F C2 11 84
#db# conf0: C9 conf1: 00 conf2: 00
@ -401,7 +401,7 @@ static int check_select(const uint8_t *rx, uint32_t uid) {
// global var?
temp_uid = ans;
if (ans == tag.uid) {
if (ans == BSWAP_32(tag.data.s.uid_le)) {
return 1;
}
@ -473,7 +473,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
//send uid as a response
*txlen = 32;
for (int i = 0; i < 4; i++) {
tx[i] = (tag.uid >> (24 - (i * 8))) & 0xFF;
tx[i] = (BSWAP_32(tag.data.s.uid_le) >> (24 - (i * 8))) & 0xFF;
}
break;
}
@ -481,7 +481,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
//select command from reader received
DBG DbpString("SELECT");
if ((rx[0] & 0xf8) == HITAGS_SELECT && check_select(rx, tag.uid) == 1) {
if ((rx[0] & 0xf8) == HITAGS_SELECT && check_select(rx, BSWAP_32(tag.data.s.uid_le)) == 1) {
DBG DbpString("SELECT match");
@ -491,7 +491,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
//send configuration
for (int i = 0; i < 4; i++) {
tx[i] = tag.pages[1][i];
tx[i] = tag.data.pages[1][i];
}
tx[3] = 0xff;
@ -517,8 +517,8 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
temp2++;
*txlen = 32;
// init crypt engine
state = ht2_hitag2_init(REV64(tag.key),
REV32((tag.pages[0][3] << 24) + (tag.pages[0][2] << 16) + (tag.pages[0][1] << 8) + tag.pages[0][0]),
state = ht2_hitag2_init(reflect64(tag.data.s.key) >> 16 & 0xFFFFFFFFFFFF,
REV32((tag.data.pages[0][3] << 24) + (tag.data.pages[0][2] << 16) + (tag.data.pages[0][1] << 8) + tag.data.pages[0][0]),
REV32((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])
);
DBG Dbprintf(", {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
@ -530,19 +530,19 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
}
//send con2, pwdh0, pwdl0, pwdl1 encrypted as a response
tx[0] = ht2_hitag2_byte(&state) ^ tag.pages[1][2];
tx[1] = ht2_hitag2_byte(&state) ^ tag.pwdh0;
tx[2] = ht2_hitag2_byte(&state) ^ tag.pwdl0;
tx[3] = ht2_hitag2_byte(&state) ^ tag.pwdl1;
tx[0] = ht2_hitag2_byte(&state) ^ tag.data.pages[1][2];
tx[1] = ht2_hitag2_byte(&state) ^ tag.data.s.pwdh0;
tx[2] = ht2_hitag2_byte(&state) ^ tag.data.s.pwdl0;
tx[3] = ht2_hitag2_byte(&state) ^ tag.data.s.pwdl1;
if (tag.mode != HT_STANDARD) {
//add crc8
*txlen = 40;
crc = CRC_PRESET;
calc_crc(&crc, tag.pages[1][2], 8);
calc_crc(&crc, tag.pwdh0, 8);
calc_crc(&crc, tag.pwdl0, 8);
calc_crc(&crc, tag.pwdl1, 8);
calc_crc(&crc, tag.data.pages[1][2], 8);
calc_crc(&crc, tag.data.s.pwdh0, 8);
calc_crc(&crc, tag.data.s.pwdl0, 8);
calc_crc(&crc, tag.data.s.pwdl1, 8);
tx[4] = (crc ^ ht2_hitag2_byte(&state));
}
/*
@ -550,17 +550,9 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
* use this to change the uid between authentications.
if (temp2 % 2 == 0) {
tag.uid = 0x11223344;
tag.pages[0][0] = 0x11;
tag.pages[0][1] = 0x22;
tag.pages[0][2] = 0x33;
tag.pages[0][3] = 0x44;
tag.data.s.uid_le = 0x44332211;
} else {
tag.uid = 0x55667788;
tag.pages[0][0] = 0x55;
tag.pages[0][1] = 0x66;
tag.pages[0][2] = 0x77;
tag.pages[0][3] = 0x88;
tag.data.s.uid_le = 0x88776655;
}
*/
break;
@ -571,10 +563,10 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
//data received to be written
if (tag.tstate == HT_WRITING_PAGE_DATA) {
tag.tstate = HT_NO_OP;
tag.pages[page_to_be_written][0] = rx[0];
tag.pages[page_to_be_written][1] = rx[1];
tag.pages[page_to_be_written][2] = rx[2];
tag.pages[page_to_be_written][3] = rx[3];
tag.data.pages[page_to_be_written][0] = rx[0];
tag.data.pages[page_to_be_written][1] = rx[1];
tag.data.pages[page_to_be_written][2] = rx[2];
tag.data.pages[page_to_be_written][3] = rx[3];
//send ack
*txlen = 2;
tx[0] = 0x40;
@ -582,10 +574,10 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
hts_set_frame_modulation();
} else if (tag.tstate == HT_WRITING_BLOCK_DATA) {
tag.pages[page_to_be_written][0] = rx[0];
tag.pages[page_to_be_written][1] = rx[1];
tag.pages[page_to_be_written][2] = rx[2];
tag.pages[page_to_be_written][3] = rx[3];
tag.data.pages[page_to_be_written][0] = rx[0];
tag.data.pages[page_to_be_written][1] = rx[1];
tag.data.pages[page_to_be_written][2] = rx[2];
tag.data.pages[page_to_be_written][3] = rx[3];
//send ack
*txlen = 2;
tx[0] = 0x40;
@ -606,12 +598,12 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
//send page data
uint8_t page = ((rx[0] & 0x0f) << 4) + ((rx[1] & 0xf0) >> 4);
*txlen = 32;
tx[0] = tag.pages[page][0];
tx[1] = tag.pages[page][1];
tx[2] = tag.pages[page][2];
tx[3] = tag.pages[page][3];
tx[0] = tag.data.pages[page][0];
tx[1] = tag.data.pages[page][1];
tx[2] = tag.data.pages[page][2];
tx[3] = tag.data.pages[page][3];
if (tag.LKP && page == 1) {
if (tag.data.s.LKP && page == 1) {
tx[3] = 0xFF;
}
@ -627,7 +619,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
tx[4] = crc;
}
if (tag.LKP && (page == 2 || page == 3)) {
if (tag.data.s.LKP && (page == 2 || page == 3)) {
//if reader asks for key or password and the LKP-mark is set do not respond
sof_bits = 0;
*txlen = 0;
@ -640,10 +632,10 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
//send page,...,page+3 data
for (int i = 0; i < 4; i++) {
tx[0 + i * 4] = tag.pages[page + 0 + i * 4][0];
tx[1 + i * 4] = tag.pages[page + 1 + i * 4][1];
tx[2 + i * 4] = tag.pages[page + 2 + i * 4][2];
tx[3 + i * 4] = tag.pages[page + 3 + i * 4][3];
tx[0 + i * 4] = tag.data.pages[page + 0 + i * 4][0];
tx[1 + i * 4] = tag.data.pages[page + 1 + i * 4][1];
tx[2 + i * 4] = tag.data.pages[page + 2 + i * 4][2];
tx[3 + i * 4] = tag.data.pages[page + 3 + i * 4][3];
}
hts_set_frame_modulation();
@ -658,7 +650,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
tx[16] = crc;
}
if ((page) % 4 != 0 || (tag.LKP && (page) == 0)) {
if ((page) % 4 != 0 || (tag.data.s.LKP && (page) == 0)) {
sof_bits = 0;
*txlen = 0;
}
@ -667,8 +659,8 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen,
uint8_t page = ((rx[0] & 0x0f) << 4) + ((rx[1] & 0xf0) >> 4);
if ((tag.LCON && page == 1)
|| (tag.LKP && (page == 2 || page == 3))) {
if ((tag.data.s.LCON && page == 1)
|| (tag.data.s.LKP && (page == 2 || page == 3))) {
//deny
*txlen = 0;
} else {
@ -737,101 +729,32 @@ void hts_simulate(bool tag_mem_supplied, const uint8_t *data, bool ledcontrol) {
// read tag data into memory
if (tag_mem_supplied) {
DbpString("Loading hitag S memory...");
memcpy((uint8_t *)tag.pages, data, 4 * 64);
memcpy((uint8_t *)tag.data.pages, data, 4 * 64);
} else {
// use the last read tag
}
tag.uid = ((tag.pages[0][3]) << 24) | ((tag.pages[0][2]) << 16) | ((tag.pages[0][1]) << 8) | tag.pages[0][0];
tag.key = (((uint64_t)tag.pages[3][3]) << 40) |
(((uint64_t)tag.pages[3][2]) << 32) |
(((uint64_t)tag.pages[3][1]) << 24) |
(((uint64_t)tag.pages[3][0]) << 16) |
(((uint64_t)tag.pages[2][3]) << 8) |
(((uint64_t)tag.pages[2][2]));
tag.pwdl0 = tag.pages[2][0];
tag.pwdl1 = tag.pages[2][1];
tag.pwdh0 = tag.pages[1][3];
//con0
tag.max_page = 64;
if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 1) {
if ((tag.data.pages[1][0] & 0x2) == 0 && (tag.data.pages[1][0] & 0x1) == 1) {
tag.max_page = 8;
}
if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 0) {
if ((tag.data.pages[1][0] & 0x2) == 0 && (tag.data.pages[1][0] & 0x1) == 0) {
tag.max_page = 0;
}
for (int i = 0; i < tag.max_page; i++) {
DBG Dbprintf("Page[%2d]: %02X %02X %02X %02X",
i,
(tag.pages[i][3]) & 0xFF,
(tag.pages[i][2]) & 0xFF,
(tag.pages[i][1]) & 0xFF,
tag.pages[i][0] & 0xFF
tag.data.pages[i][3],
tag.data.pages[i][2],
tag.data.pages[i][1],
tag.data.pages[i][0]
);
}
//con1
tag.auth = 0;
if ((tag.pages[1][1] & 0x80) == 0x80) {
tag.auth = 1;
}
tag.LCON = 0;
if ((tag.pages[1][1] & 0x2) == 0x02) {
tag.LCON = 1;
}
tag.LKP = 0;
if ((tag.pages[1][1] & 0x1) == 0x01) {
tag.LKP = 1;
}
//con2
//0=read write 1=read only
tag.LCK7 = 0;
if ((tag.pages[1][2] & 0x80) == 0x80) {
tag.LCK7 = 1;
}
tag.LCK6 = 0;
if ((tag.pages[1][2] & 0x40) == 0x040) {
tag.LCK6 = 1;
}
tag.LCK5 = 0;
if ((tag.pages[1][2] & 0x20) == 0x20) {
tag.LCK5 = 1;
}
tag.LCK4 = 0;
if ((tag.pages[1][2] & 0x10) == 0x10) {
tag.LCK4 = 1;
}
tag.LCK3 = 0;
if ((tag.pages[1][2] & 0x8) == 0x08) {
tag.LCK3 = 1;
}
tag.LCK2 = 0;
if ((tag.pages[1][2] & 0x4) == 0x04) {
tag.LCK2 = 1;
}
tag.LCK1 = 0;
if ((tag.pages[1][2] & 0x2) == 0x02) {
tag.LCK1 = 1;
}
tag.LCK0 = 0;
if ((tag.pages[1][2] & 0x1) == 0x01) {
tag.LCK0 = 1;
}
// Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection.
@ -1200,7 +1123,7 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz
return -1;
}
tag.uid = (rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0]);
memcpy(&tag.data.pages[HITAGS_UID_PADR], rx, HITAGS_PAGE_SIZE);
DBG Dbprintf("UID... %02X%02X%02X%02X", rx[0], rx[1], rx[2], rx[3]);
@ -1219,40 +1142,20 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz
return -1;
}
uint8_t conf_pages[3];
conf_pages[0] = rx[0];
memcpy(&tag.data.pages[HITAGS_CONFIG_PADR], rx, HITAGS_PAGE_SIZE - 1);
//check which memorysize this tag has
if ((conf_pages[0] & 0x3) == 0x00) {
if ((tag.data.s.CON0 & 0x3) == 0x00) {
tag.max_page = 32 / 32;
} else if ((conf_pages[0] & 0x3) == 0x1) {
} else if ((tag.data.s.CON0 & 0x3) == 0x1) {
tag.max_page = 256 / 32;
} else if ((conf_pages[0] & 0x3) == 0x2) {
} else if ((tag.data.s.CON0 & 0x3) == 0x2) {
tag.max_page = 2048 / 32;
}
conf_pages[1] = rx[1];
tag.auth = (conf_pages[1] >> 7) & 0x1;
tag.TTFC = (conf_pages[1] >> 6) & 0x1;
tag.TTFDR = (conf_pages[1] >> 5) & 0x3;
tag.TTFM = (conf_pages[1] >> 3) & 0x3;
tag.LCON = (conf_pages[1] >> 1) & 0x1;
tag.LKP = (conf_pages[1] >> 0) & 0x1;
DBG Dbprintf("conf 0: %02X conf 1: %02X conf 2: %02X", tag.data.pages[HITAGS_CONFIG_PADR][0], tag.data.pages[HITAGS_CONFIG_PADR][1], tag.data.pages[HITAGS_CONFIG_PADR][2]);
conf_pages[2] = rx[2];
tag.LCK7 = (conf_pages[2] >> 7) & 0x1;
tag.LCK6 = (conf_pages[2] >> 6) & 0x1;
tag.LCK5 = (conf_pages[2] >> 5) & 0x1;
tag.LCK4 = (conf_pages[2] >> 4) & 0x1;
tag.LCK3 = (conf_pages[2] >> 3) & 0x1;
tag.LCK2 = (conf_pages[2] >> 2) & 0x1;
tag.LCK1 = (conf_pages[2] >> 1) & 0x1;
tag.LCK0 = (conf_pages[2] >> 0) & 0x1;
DBG Dbprintf("conf 0: %02X conf 1: %02X conf 2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]);
if (tag.auth == 1) {
if (tag.data.s.auth == 1) {
uint64_t key = 0;
// if the tag is in authentication mode try the key or challenge
@ -1269,7 +1172,7 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz
((uint64_t)packet->key[5]) << 40
;
uint64_t state = ht2_hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
uint64_t state = ht2_hitag2_init(REV64(key), reflect32(tag.data.s.uid_le), REV32(rnd));
uint8_t auth_ks[4];
for (int i = 0; i < 4; i++) {
@ -1353,7 +1256,7 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz
}
//encrypted con2,password received.
DBG Dbprintf("UID... %X", tag.uid);
DBG Dbprintf("UID... %X", BSWAP_32(tag.data.s.uid_le));
DBG Dbprintf("RND... %X", rnd);
//decrypt password
@ -1362,7 +1265,7 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz
pwdl1 = 0;
if (packet->cmd == RHTSF_KEY || packet->cmd == WHTSF_KEY) {
uint64_t state = ht2_hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
uint64_t state = ht2_hitag2_init(REV64(key), reflect32(tag.data.s.uid_le), REV32(rnd));
for (int i = 0; i < 4; i++) {
ht2_hitag2_byte(&state);
}
@ -1421,27 +1324,27 @@ void hts_read(const lf_hitag_data_t *payload, bool ledcontrol) {
//save received data - 40 bits
for (int i = 0; i < 4 && i < rxlen; i++) { // set page bytes from received bits
tag.pages[pageNum][i] = rx[i];
tag.data.pages[pageNum][i] = rx[i];
}
if (g_dbglevel >= DBG_EXTENDED) {
if (tag.auth && tag.LKP && pageNum == 1) {
if (tag.data.s.auth && tag.data.s.LKP && pageNum == 1) {
DBG Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, pwdh0,
(tag.pages[pageNum][2]) & 0xff,
(tag.pages[pageNum][1]) & 0xff,
tag.pages[pageNum][0] & 0xff);
tag.data.pages[pageNum][2],
tag.data.pages[pageNum][1],
tag.data.pages[pageNum][0]);
} else {
DBG Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum,
(tag.pages[pageNum][3]) & 0xff,
(tag.pages[pageNum][2]) & 0xff,
(tag.pages[pageNum][1]) & 0xff,
tag.pages[pageNum][0] & 0xff);
tag.data.pages[pageNum][3],
tag.data.pages[pageNum][2],
tag.data.pages[pageNum][1],
tag.data.pages[pageNum][0]);
}
}
pageNum++;
//display key and password if possible
if (pageNum == 2 && tag.auth == 1 && tag.LKP) {
if (pageNum == 2 && tag.data.s.auth == 1 && tag.data.s.LKP) {
if (payload->cmd == RHTSF_KEY) {
DBG Dbprintf("Page[ 2]: %02X %02X %02X %02X",
payload->key[1],
@ -1473,7 +1376,7 @@ read_end:
hts_stop_clock();
set_tracing(false);
lf_finalize(ledcontrol);
reply_ng(CMD_LF_HITAGS_READ, status, (uint8_t *)tag.pages, sizeof(tag.pages));
reply_ng(CMD_LF_HITAGS_READ, status, (uint8_t *)tag.data.pages, sizeof(tag.data.pages));
}
/*
@ -1610,10 +1513,10 @@ int hts_read_uid(uint32_t *uid, bool ledcontrol, bool send_answer) {
int status = PM3_SUCCESS;
if (rxlen == 32) {
memcpy(&tag.pages[0], rx, HITAGS_PAGE_SIZE);
tag.uid = (rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0]);
memcpy(&tag.data.pages[0], rx, HITAGS_PAGE_SIZE);
if (uid) {
*uid = tag.uid;
*uid = BSWAP_32(tag.data.s.uid_le);
}
} else {
@ -1624,7 +1527,7 @@ int hts_read_uid(uint32_t *uid, bool ledcontrol, bool send_answer) {
hts_stop_clock();
set_tracing(false);
lf_finalize(ledcontrol);
reply_ng(CMD_LF_HITAGS_UID, status, (uint8_t *)tag.pages, sizeof(tag.pages));
reply_ng(CMD_LF_HITAGS_UID, status, (uint8_t *)tag.data.pages, sizeof(tag.data.pages));
return status;
}

View file

@ -38,6 +38,7 @@
#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
// need to see which limits these cards has
@ -126,31 +127,48 @@ typedef enum SOF_TYPE {
struct hitagS_tag {
PSTATE pstate; // protocol-state
TSATE tstate; // tag-state
uint32_t uid;
uint8_t pages[64][4];
uint64_t key;
uint8_t pwdl0, pwdl1, pwdh0;
// con0
TSATE tstate; // tag-state
int max_page;
stype mode;
// con1
bool auth; // 0 = Plain 1 = Auth
bool TTFC; // Transponder Talks first coding. 0 = Manchester 1 = Biphase
int TTFDR; // data rate in TTF Mode
int TTFM; // the number of pages that are sent to the RWD
bool LCON; // 0 = con1/2 read write 1 =con1 read only and con2 OTP
bool LKP; // 0 = page2/3 read write 1 =page2/3 read only in Plain mode and no access in authenticate mode
// con2
// 0 = read write 1 = read only
bool LCK7; // page4/5
bool LCK6; // page6/7
bool LCK5; // page8-11
bool LCK4; // page12-15
bool LCK3; // page16-23
bool LCK2; // page24-31
bool LCK1; // page32-47
bool LCK0; // page48-63
};
union {
uint8_t pages[64][4];
struct {
// page 0
uint32_t uid_le;
// page 1
uint8_t CON0;
// con1
bool LKP : 1; // 0 = page2/3 read write 1 =page2/3 read only in Plain mode and no access in authenticate mode
bool LCON : 1; // 0 = con1/2 read write 1 =con1 read only and con2 OTP
int TTFM : 2; // the number of pages that are sent to the RWD
int TTFDR : 2; // data rate in TTF Mode
bool TTFC : 1; // Transponder Talks first coding. 0 = Manchester 1 = Biphase
bool auth : 1; // 0 = Plain 1 = Auth
// con2
// 0 = read write 1 = read only
bool LCK0 : 1; // page48-63
bool LCK1 : 1; // page32-47
bool LCK2 : 1; // page24-31
bool LCK3 : 1; // page16-23
bool LCK4 : 1; // page12-15
bool LCK5 : 1; // page8-11
bool LCK6 : 1; // page6/7
bool LCK7 : 1; // page4/5
// reserved/pwdh0
uint8_t pwdh0;
// page 2
uint8_t pwdl0;
uint8_t pwdl1;
uint64_t key : 48;
// page 4
} s;
} data;
} PACKED;
#endif