mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Update iso14443a.c
Added SimulateIso14443aTagAID Signed-off-by: Adam Jon Foster <me@evildaemond.com>
This commit is contained in:
parent
4ff0726eb6
commit
95a8829f20
1 changed files with 239 additions and 0 deletions
|
@ -3865,3 +3865,242 @@ void DetectNACKbug(void) {
|
||||||
hf_field_off();
|
hf_field_off();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ///
|
||||||
|
Based upon the SimulateIso14443aTag, this aims to instead take an AID Value you've supplied, and return your selected response.
|
||||||
|
It can also continue after the AID has been selected, and respond to other request types.
|
||||||
|
This was forked from the original function to allow for more flexibility in the future, and to increase the processing speed of the original function.
|
||||||
|
/// */
|
||||||
|
|
||||||
|
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *iRATs, uint8_t *aid, uint8_t *resp, uint8_t *apdu, int aidLen, int respondLen, int apduLen, bool enumerate) {
|
||||||
|
tag_response_info_t *responses;
|
||||||
|
uint32_t cuid = 0;
|
||||||
|
uint32_t counters[3] = { 0x00, 0x00, 0x00 };
|
||||||
|
uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
|
||||||
|
uint8_t pages = 0;
|
||||||
|
|
||||||
|
// command buffers
|
||||||
|
uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 };
|
||||||
|
uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 };
|
||||||
|
|
||||||
|
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||||
|
BigBuf_free_keep_EM();
|
||||||
|
|
||||||
|
// Increased the buffer size to allow for more complex responses
|
||||||
|
#define DYNAMIC_RESPONSE_BUFFER2_SIZE 512
|
||||||
|
#define DYNAMIC_MODULATION_BUFFER2_SIZE 1536
|
||||||
|
|
||||||
|
uint8_t * dynamic_response_buffer2 = BigBuf_calloc(DYNAMIC_RESPONSE_BUFFER2_SIZE);
|
||||||
|
uint8_t * dynamic_modulation_buffer2 = BigBuf_calloc(DYNAMIC_MODULATION_BUFFER2_SIZE);
|
||||||
|
tag_response_info_t dynamic_response_info = {
|
||||||
|
.response = dynamic_response_buffer2,
|
||||||
|
.response_n = 0,
|
||||||
|
.modulation = dynamic_modulation_buffer2,
|
||||||
|
.modulation_n = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (SimulateIso14443aInit(tagType, flags, data, iRATs, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||||
|
BigBuf_free_keep_EM();
|
||||||
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to listen to the high-frequency, peak-detected path.
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||||
|
|
||||||
|
iso14a_set_timeout(201400); // 106 * 19ms default *100?
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
int retval = PM3_SUCCESS;
|
||||||
|
int sentCount = 0;
|
||||||
|
bool odd_reply = true;
|
||||||
|
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
LED_A_ON();
|
||||||
|
|
||||||
|
// Filters for when this comes through
|
||||||
|
static uint8_t aidFilter[30] = { 0x00 }; // Default AID Value
|
||||||
|
static uint8_t aidResponse[100] = { 0x00 }; // Default AID Response
|
||||||
|
static uint8_t apduCommand [100] = { 0x00 }; // Default APDU GetData Response
|
||||||
|
|
||||||
|
// Copy the AID, AID Response, and the GetData APDU response into our variables
|
||||||
|
if (aid != 0) {
|
||||||
|
memcpy(aidFilter, aid, aidLen);
|
||||||
|
}
|
||||||
|
if (resp != 0) {
|
||||||
|
memcpy(aidResponse, resp, respondLen);
|
||||||
|
}
|
||||||
|
if (apdu != 0) {
|
||||||
|
memcpy(apduCommand, apdu, apduLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// main loop
|
||||||
|
bool finished = false;
|
||||||
|
while (finished == false) {
|
||||||
|
// BUTTON_PRESS check done in GetIso14443aCommandFromReader
|
||||||
|
WDT_HIT();
|
||||||
|
|
||||||
|
tag_response_info_t *p_response = NULL;
|
||||||
|
|
||||||
|
// Clean receive command buffer
|
||||||
|
if (GetIso14443aCommandFromReader(receivedCmd, sizeof(receivedCmd), receivedCmdPar, &len) == false) {
|
||||||
|
Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
|
||||||
|
retval = PM3_EOPABORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST, but in HALTED, skip
|
||||||
|
odd_reply = !odd_reply;
|
||||||
|
if (odd_reply) {
|
||||||
|
p_response = &responses[RESP_INDEX_ATQA];
|
||||||
|
}
|
||||||
|
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
|
||||||
|
p_response = &responses[RESP_INDEX_ATQA];
|
||||||
|
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1)
|
||||||
|
p_response = &responses[RESP_INDEX_UIDC1];
|
||||||
|
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 2) { // Received request for UID (cascade 2)
|
||||||
|
p_response = &responses[RESP_INDEX_UIDC2];
|
||||||
|
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && len == 2) { // Received request for UID (cascade 3)
|
||||||
|
p_response = &responses[RESP_INDEX_UIDC3];
|
||||||
|
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
|
||||||
|
p_response = &responses[RESP_INDEX_SAKC1];
|
||||||
|
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 9) { // Received a SELECT (cascade 2)
|
||||||
|
p_response = &responses[RESP_INDEX_SAKC2];
|
||||||
|
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && len == 9) { // Received a SELECT (cascade 3)
|
||||||
|
p_response = &responses[RESP_INDEX_SAKC3];
|
||||||
|
} else if (receivedCmd[0] == ISO14443A_CMD_PPS) {
|
||||||
|
p_response = &responses[RESP_INDEX_PPS];
|
||||||
|
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT
|
||||||
|
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||||
|
p_response = NULL;
|
||||||
|
finished = true;
|
||||||
|
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
|
||||||
|
p_response = &responses[RESP_INDEX_RATS];
|
||||||
|
} else {
|
||||||
|
// clear old dynamic responses
|
||||||
|
dynamic_response_info.response_n = 0;
|
||||||
|
dynamic_response_info.modulation_n = 0;
|
||||||
|
|
||||||
|
// Check for ISO 14443A-4 compliant commands, look at left nibble
|
||||||
|
switch (receivedCmd[0]) {
|
||||||
|
case 0x0B:
|
||||||
|
case 0x0A: { // IBlock (command CID)
|
||||||
|
dynamic_response_info.response[0] = receivedCmd[0];
|
||||||
|
dynamic_response_info.response[1] = 0x00;
|
||||||
|
|
||||||
|
switch (receivedCmd[3]) { // APDU Class Byte
|
||||||
|
// receivedCmd in this case is expecting to structured with a CID, then the APDU command for SelectFile
|
||||||
|
// | IBlock (CID) | CID | APDU Command | CRC |
|
||||||
|
|
||||||
|
case 0xA4: { // SELECT FILE
|
||||||
|
// Select File AID uses the following format for GlobalPlatform
|
||||||
|
//
|
||||||
|
// | 00 | A4 | 04 | 00 | xx | AID | 00 |
|
||||||
|
// xx in this case is len of the AID value in hex
|
||||||
|
|
||||||
|
// aid len is found as a hex value in receivedCmd[6] (Index Starts at 0)
|
||||||
|
int aid_len = receivedCmd[6];
|
||||||
|
uint8_t* recieved_aid = &receivedCmd[7];
|
||||||
|
|
||||||
|
// aid enumeration flag
|
||||||
|
if (enumerate == true) {
|
||||||
|
Dbprintf("Received AID (%d):", aid_len);
|
||||||
|
Dbhexdump(aid_len, recieved_aid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(aidFilter, recieved_aid, aid_len) == 0) { // Evaluate the AID sent by the Reader to the AID supplied
|
||||||
|
// AID Response will be parsed here
|
||||||
|
memcpy(dynamic_response_info.response + 2 , aidResponse, respondLen + 2);
|
||||||
|
dynamic_response_info.response_n = respondLen + 2;
|
||||||
|
} else { // Any other SELECT FILE command will return with a Not Found
|
||||||
|
dynamic_response_info.response[2] = 0x6A;
|
||||||
|
dynamic_response_info.response[3] = 0x82;
|
||||||
|
dynamic_response_info.response_n = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xDA: { // PUT DATA
|
||||||
|
// Just send them a 90 00 response
|
||||||
|
dynamic_response_info.response[2] = 0x90;
|
||||||
|
dynamic_response_info.response[3] = 0x00;
|
||||||
|
dynamic_response_info.response_n = 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xCA: { // GET DATA
|
||||||
|
if (sentCount == 0) {
|
||||||
|
// APDU Command will just be parsed here
|
||||||
|
memcpy(dynamic_response_info.response + 2 , apduCommand, apduLen + 2);
|
||||||
|
dynamic_response_info.response_n = respondLen + 2;
|
||||||
|
} else {
|
||||||
|
finished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sentCount++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default : {
|
||||||
|
// Any other non-listed command
|
||||||
|
// Respond Not Found
|
||||||
|
dynamic_response_info.response[2] = 0x6A;
|
||||||
|
dynamic_response_info.response[3] = 0x82;
|
||||||
|
dynamic_response_info.response_n = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xCA:
|
||||||
|
case 0xC2: { // Readers sends deselect command
|
||||||
|
dynamic_response_info.response[0] = 0xCA;
|
||||||
|
dynamic_response_info.response[1] = 0x00;
|
||||||
|
dynamic_response_info.response_n = 2;
|
||||||
|
finished = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// Never seen this command before
|
||||||
|
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||||
|
if (g_dbglevel >= DBG_DEBUG) {
|
||||||
|
Dbprintf("Received unknown command (len=%d):", len);
|
||||||
|
Dbhexdump(len, receivedCmd, false);
|
||||||
|
}
|
||||||
|
// Do not respond
|
||||||
|
dynamic_response_info.response_n = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dynamic_response_info.response_n > 0) {
|
||||||
|
|
||||||
|
// Copy the CID from the reader query
|
||||||
|
dynamic_response_info.response[1] = receivedCmd[1];
|
||||||
|
|
||||||
|
// Add CRC bytes, always used in ISO 14443A-4 compliant cards
|
||||||
|
AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n);
|
||||||
|
dynamic_response_info.response_n += 2;
|
||||||
|
|
||||||
|
if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
|
||||||
|
if (g_dbglevel >= DBG_DEBUG) DbpString("Error preparing tag response");
|
||||||
|
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p_response = &dynamic_response_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send response
|
||||||
|
EmSendPrecompiledCmd(p_response);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_off();
|
||||||
|
|
||||||
|
set_tracing(false);
|
||||||
|
BigBuf_free_keep_EM();
|
||||||
|
|
||||||
|
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue