Update iso14443a.c

Added SimulateIso14443aTagAID

Signed-off-by: Adam Jon Foster <me@evildaemond.com>
This commit is contained in:
Adam Jon Foster 2024-09-23 14:38:30 +08:00 committed by GitHub
commit 95a8829f20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

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