mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
Add hf iclass creditepurse
command to allow crediting the epurse debit value.
This commit is contained in:
parent
b59fad842b
commit
186308cb4a
10 changed files with 318 additions and 6 deletions
157
armsrc/iclass.c
157
armsrc/iclass.c
|
@ -1902,13 +1902,13 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
|
||||
// verify write
|
||||
uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
if (payload->req.blockno == 2) {
|
||||
if (pagemap == PICOPASS_SECURE_PAGEMODE && payload->req.blockno == 2) {
|
||||
// check response. e-purse update swaps first and second half
|
||||
if (memcmp(payload->data + 4, resp, 4) || memcmp(payload->data, resp + 4, 4)) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
} else if (payload->req.blockno == 3 || payload->req.blockno == 4) {
|
||||
} else if (pagemap == PICOPASS_SECURE_PAGEMODE && (payload->req.blockno == 3 || payload->req.blockno == 4)) {
|
||||
// check response. Key updates always return 0xffffffffffffffff
|
||||
if (memcmp(all_ff, resp, 8)) {
|
||||
res = false;
|
||||
|
@ -1929,6 +1929,159 @@ out:
|
|||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
void iclass_credit_epurse(iclass_credit_epurse_t *payload) {
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
bool shallow_mod = payload->req.shallow_mod;
|
||||
|
||||
Iso15693InitReader();
|
||||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr_t hdr = {0};
|
||||
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
uint8_t mac[4] = {0};
|
||||
|
||||
// authenticate
|
||||
if (payload->req.do_auth) {
|
||||
|
||||
res = authenticate_iclass_tag(&payload->req, &hdr, &start_time, &eof_time, mac);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
uint8_t cmd_read[] = {ICLASS_CMD_READ_OR_IDENTIFY, payload->req.blockno, 0x00, 0x00};
|
||||
AddCrc(cmd_read + 1, 1);
|
||||
|
||||
uint8_t epurse[10];
|
||||
res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), epurse, sizeof(epurse), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
|
||||
if (!res) {
|
||||
switch_off();
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETIMEOUT, (uint8_t *)&res, sizeof(uint8_t));
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno };
|
||||
uint8_t write_len = 14;
|
||||
|
||||
uint8_t epurse_offset = 0;
|
||||
const uint8_t empty_epurse[] = {0xff, 0xff, 0xff, 0xff};
|
||||
if (!memcmp(epurse, empty_epurse, 4)) {
|
||||
// epurse data in stage 2
|
||||
epurse_offset = 4;
|
||||
}
|
||||
|
||||
memcpy(epurse + epurse_offset, payload->epurse, 4);
|
||||
|
||||
// blank out debiting value as per the first step of the crediting procedure
|
||||
epurse[epurse_offset + 0] = 0xFF;
|
||||
epurse[epurse_offset + 1] = 0xFF;
|
||||
|
||||
// initial epurse write for credit
|
||||
memcpy(write + 2, epurse, 8);
|
||||
|
||||
doMAC_N(write + 1, 9, payload->req.use_credit_key ? hdr.key_c : hdr.key_d, mac);
|
||||
memcpy(write + 10, mac, sizeof(mac));
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
|
||||
uint8_t tries = 3;
|
||||
while (tries-- > 0) {
|
||||
|
||||
iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
res = false;
|
||||
switch_off();
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
|
||||
return;
|
||||
} else {
|
||||
|
||||
uint16_t resp_len = 0;
|
||||
int res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time, false, true, &resp_len);
|
||||
if (res2 == PM3_SUCCESS && resp_len == 10) {
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tries == 0) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// check response. e-purse update swaps first and second half
|
||||
if (memcmp(write + 2 + 4, resp, 4) || memcmp(write + 2, resp + 4, 4)) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// new epurse write
|
||||
// epurse offset is now flipped after the first write
|
||||
epurse_offset ^= 4;
|
||||
memcpy(resp + epurse_offset, payload->epurse, 4);
|
||||
memcpy(write + 2, resp, 8);
|
||||
|
||||
doMAC_N(write + 1, 9, payload->req.use_credit_key ? hdr.key_c : hdr.key_d, mac);
|
||||
memcpy(write + 10, mac, sizeof(mac));
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
tries = 3;
|
||||
while (tries-- > 0) {
|
||||
|
||||
iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
res = false;
|
||||
switch_off();
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
|
||||
return;
|
||||
} else {
|
||||
|
||||
uint16_t resp_len = 0;
|
||||
int res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time, false, true, &resp_len);
|
||||
if (res2 == PM3_SUCCESS && resp_len == 10) {
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tries == 0) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// check response. e-purse update swaps first and second half
|
||||
if (memcmp(write + 2 + 4, resp, 4) || memcmp(write + 2, resp + 4, 4)) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
switch_off();
|
||||
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
void iClass_Restore(iclass_restore_req_t *msg) {
|
||||
|
||||
// sanitation
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue