rework simaid & rename few vars

This commit is contained in:
Philippe Teuwen 2025-02-12 08:32:13 +01:00
commit 1acc030fd4
8 changed files with 137 additions and 121 deletions

View file

@ -445,7 +445,7 @@ void RunMod(void) {
// received a RATS request
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) {
prevCmd = 0;
p_response = &responses[RESP_INDEX_RATS];
p_response = &responses[RESP_INDEX_ATS];
} else {
if (g_dbglevel == DBG_DEBUG) {

View file

@ -338,7 +338,7 @@ void RunMod() {
} 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[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
p_response = &responses[RESP_INDEX_RATS];
p_response = &responses[RESP_INDEX_ATS];
resp = 1;
} else if (receivedCmd[0] == 0xf2 && len == 4) { // ACKed - Time extension
DbpString(_YELLOW_("!!") " Reader accepted time extension!");

View file

@ -247,7 +247,7 @@ void RunMod(void) {
} 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[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
p_response = &responses[RESP_INDEX_RATS];
p_response = &responses[RESP_INDEX_ATS];
} else if (receivedCmd[0] == ISO14443A_CMD_PPS) {
p_response = &responses[RESP_INDEX_PPS];
} else {
@ -425,7 +425,7 @@ void RunMod(void) {
} 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[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
p_response = &responses[RESP_INDEX_RATS];
p_response = &responses[RESP_INDEX_ATS];
} else if (receivedCmd[0] == ISO14443A_CMD_PPS) {
p_response = &responses[RESP_INDEX_PPS];
} else {

View file

@ -1696,20 +1696,21 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t tagtype;
uint16_t flags;
uint8_t uid[10];
uint8_t rats[20];
uint8_t ats[20];
uint8_t aid[30];
uint8_t response[100];
uint8_t apdu[100];
int aid_len;
int respond_len;
int apdu_len;
bool enumerate;
uint8_t selectaid_response[100];
uint8_t getdata_response[100];
uint32_t ats_len;
uint32_t aid_len;
uint32_t selectaid_response_len;
uint32_t getdata_response_len;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
// ## Simulate iso14443a tag - pass tag type, UID, ATS, AID, responses
SimulateIso14443aTagAID(payload->tagtype, payload->flags, payload->uid,
payload->rats, sizeof(payload->rats), payload->aid, payload->response,
payload->apdu, payload->aid_len, payload->respond_len,
payload->apdu_len, payload->enumerate); // ## Simulate iso14443a tag - pass tag type, UID, rats, aid, resp, apdu
payload->ats, payload->ats_len, payload->aid, payload->aid_len,
payload->selectaid_response, payload->selectaid_response_len,
payload->getdata_response, payload->getdata_response_len);
break;
}
case CMD_HF_ISO14443A_ANTIFUZZ: {

View file

@ -1108,7 +1108,7 @@ bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_
}
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
uint8_t *iRATs, size_t irats_len, tag_response_info_t **responses,
uint8_t *ats, size_t ats_len, tag_response_info_t **responses,
uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages) {
uint8_t sak = 0;
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
@ -1130,9 +1130,9 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
// TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
// TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us)
// TC(1) = 0x02: CID supported, NAD not supported
// static uint8_t rRATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 };
static uint8_t rRATS[40] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 };
uint8_t rRATS_len = 8;
// static uint8_t rATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 };
static uint8_t rATS[40] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 };
uint8_t rATS_len = 8;
// GET_VERSION response for EV1/NTAG
static uint8_t rVERSION[10] = { 0x00 };
@ -1184,8 +1184,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
rATQA[0] = 0x44;
rATQA[1] = 0x03;
sak = 0x20;
memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8);
rRATS_len = 8; // including CRC
memcpy(rATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8);
rATS_len = 8; // including CRC
break;
}
case 4: { // ISO/IEC 14443-4 - javacard (JCOP)
@ -1254,8 +1254,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
}
case 11: { // ISO/IEC 14443-4 - javacard (JCOP) / EMV
memcpy(rRATS, "\x13\x78\x80\x72\x02\x80\x31\x80\x66\xb1\x84\x0c\x01\x6e\x01\x83\x00\x90\x00\x00\x00", 21);
rRATS_len = 21; // including CRC
memcpy(rATS, "\x13\x78\x80\x72\x02\x80\x31\x80\x66\xb1\x84\x0c\x01\x6e\x01\x83\x00\x90\x00\x00\x00", 21);
rATS_len = 21; // including CRC
rATQA[0] = 0x04;
sak = 0x20;
break;
@ -1271,17 +1271,17 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
}
}
// copy the iRATs if supplied.
// iRATs is a pointer to 20 byte array
// rRATS is a 40 byte array
if ((flags & FLAG_RATS_IN_DATA) == FLAG_RATS_IN_DATA) {
memcpy(rRATS, iRATs, irats_len);
// copy the ats if supplied.
// ats is a pointer to 20 byte array
// rATS is a 40 byte array
if ((flags & FLAG_ATS_IN_DATA) == FLAG_ATS_IN_DATA) {
memcpy(rATS, ats, ats_len);
// rats len is dictated by the first char of the string, add 2 crc bytes
rRATS_len = (iRATs[0] + 2);
rATS_len = (ats[0] + 2);
// Since its Varible length we can send value > 40 and overflow our array.
// Even if RATS protocol defined as max 40 bytes doesn't mean people try stuff
if (rRATS_len > sizeof(rRATS)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("[-] ERROR: iRATS overflow. Max %zu, got %zu", sizeof(rRATS), rRATS_len);
if (rATS_len > sizeof(rATS)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("[-] ERROR: ATS overflow. Max %zu, got %zu", sizeof(rATS), rATS_len);
return false;
}
}
@ -1379,7 +1379,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
return false;
}
AddCrc14A(rRATS, rRATS_len - 2);
AddCrc14A(rATS, rATS_len - 2);
AddCrc14A(rPPS, sizeof(rPPS) - 2);
@ -1407,7 +1407,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
{ .response = rSAKc1, .response_n = sizeof(rSAKc1) }, // Acknowledge select - cascade 1
{ .response = rSAKc2, .response_n = sizeof(rSAKc2) }, // Acknowledge select - cascade 2
{ .response = rSAKc3, .response_n = sizeof(rSAKc3) }, // Acknowledge select - cascade 3
{ .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS
{ .response = rATS, .response_n = sizeof(rATS) }, // dummy ATS (pseudo-ATR), answer to RATS
{ .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response
{ .response = rSIGN, .response_n = sizeof(rSIGN) }, // EV1/NTAG READ_SIG response
{ .response = rPPS, .response_n = sizeof(rPPS) }, // PPS response
@ -1415,7 +1415,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
};
// since rats len is variable now.
responses_init[RESP_INDEX_RATS].response_n = rRATS_len;
responses_init[RESP_INDEX_ATS].response_n = rATS_len;
// "precompiled" responses.
// These exist for speed reasons. There are no time in the anti collision phase to calculate responses.
@ -1428,7 +1428,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
// 85 bytes normally (rats = 8 bytes)
// 77 bytes + ratslen,
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE ( ((77 + rRATS_len) * 8) + 77 + rRATS_len + 12 + 12 + 12)
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE ( ((77 + rATS_len) * 8) + 77 + rATS_len + 12 + 12 + 12)
uint8_t *free_buffer = BigBuf_calloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
// modulation buffer pointer and current buffer free space size
@ -1455,7 +1455,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
// 'hf 14a sim'
//-----------------------------------------------------------------------------
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads,
uint8_t *iRATs, size_t irats_len) {
uint8_t *ats, size_t ats_len) {
#define ATTACK_KEY_COUNT 16
@ -1497,7 +1497,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
.modulation_n = 0
};
if (SimulateIso14443aInit(tagType, flags, data, iRATs, irats_len, &responses, &cuid, counters, tearings, &pages) == false) {
if (SimulateIso14443aInit(tagType, flags, data, ats, ats_len, &responses, &cuid, counters, tearings, &pages) == false) {
BigBuf_free_keep_EM();
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
return;
@ -1820,7 +1820,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
EmSend4bit(CARD_NACK_NA);
p_response = NULL;
} else {
p_response = &responses[RESP_INDEX_RATS];
p_response = &responses[RESP_INDEX_ATS];
}
} else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
@ -3941,9 +3941,10 @@ It can also continue after the AID has been selected, and respond to other reque
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, size_t irats_len, uint8_t *aid, uint8_t *resp,
uint8_t *apdu, int aidLen, int respondLen, int apduLen, bool enumerate) {
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len,
uint8_t *selectaid_response, size_t selectaid_response_len,
uint8_t *getdata_response, size_t getdata_response_len) {
tag_response_info_t *responses;
uint32_t cuid = 0;
uint32_t counters[3] = { 0x00, 0x00, 0x00 };
@ -3954,6 +3955,12 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data,
uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 };
uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 };
// Buffers must be provided by the caller, even if lengths are 0
// Copy the AID, AID Response, and the GetData APDU response into our variables
if ((aid == NULL) || (selectaid_response == NULL) || (getdata_response == NULL)) {
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINVARG, NULL, 0);
}
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
@ -3970,7 +3977,7 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data,
.modulation_n = 0
};
if (SimulateIso14443aInit(tagType, flags, data, iRATs, irats_len, &responses, &cuid, counters, tearings, &pages) == false) {
if (SimulateIso14443aInit(tagType, flags, uid, ats, ats_len, &responses, &cuid, counters, tearings, &pages) == false) {
BigBuf_free_keep_EM();
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
return;
@ -3990,23 +3997,6 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data,
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;
bool got_rats = false;
@ -4051,7 +4041,7 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data,
finished = true;
}
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
p_response = &responses[RESP_INDEX_RATS];
p_response = &responses[RESP_INDEX_ATS];
got_rats = true;
} else {
// clear old dynamic responses
@ -4081,19 +4071,19 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data,
// 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[5+offset];
int received_aid_len = receivedCmd[5+offset];
uint8_t *received_aid = &receivedCmd[6+offset];
// aid enumeration flag
if (enumerate == true) {
Dbprintf("Received AID (%d):", aid_len);
Dbhexdump(aid_len, received_aid, false);
if ((flags & FLAG_ENUMERATE_AID) == FLAG_ENUMERATE_AID) {
Dbprintf("Received AID (%d):", received_aid_len);
Dbhexdump(received_aid_len, received_aid, false);
}
if (memcmp(aidFilter, received_aid, aid_len) == 0) { // Evaluate the AID sent by the Reader to the AID supplied
if ((received_aid_len == aid_len) && (memcmp(aid, received_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 + 1 + offset, aidResponse, respondLen + 1 + offset);
dynamic_response_info.response_n = respondLen + 2;
memcpy(dynamic_response_info.response + 1 + offset, selectaid_response, selectaid_response_len + 1 + offset);
dynamic_response_info.response_n = selectaid_response_len + 2;
} else { // Any other SELECT FILE command will return with a Not Found
dynamic_response_info.response[1 + offset] = 0x6A;
dynamic_response_info.response[2 + offset] = 0x82;
@ -4113,8 +4103,8 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data,
case 0xCA: { // GET DATA
if (sentCount == 0) {
// APDU Command will just be parsed here
memcpy(dynamic_response_info.response + 1 + offset, apduCommand, apduLen + 2);
dynamic_response_info.response_n = respondLen + 1 + offset;
memcpy(dynamic_response_info.response + 1 + offset, getdata_response, getdata_response_len + 2);
dynamic_response_info.response_n = selectaid_response_len + 1 + offset;
} else {
finished = true;
break;

View file

@ -105,7 +105,7 @@ typedef enum {
RESP_INDEX_SAKC1,
RESP_INDEX_SAKC2,
RESP_INDEX_SAKC3,
RESP_INDEX_RATS,
RESP_INDEX_ATS,
RESP_INDEX_VERSION,
RESP_INDEX_SIGNATURE,
RESP_INDEX_PPS,
@ -145,9 +145,10 @@ void RAMFUNC SniffIso14443a(uint8_t param);
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads,
uint8_t *iRATs, size_t irats_len);
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data,
uint8_t *iRATs, size_t irats_len, uint8_t *aid, uint8_t *resp,
uint8_t *apdu, int aid_len, int respond_len, int apdu_len, bool enumerate);
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len,
uint8_t *selectaid_response, size_t selectaid_response_len,
uint8_t *getdata_response, size_t getdata_response_len);
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
uint8_t *iRATs, size_t irats_len, tag_response_info_t **responses,

View file

@ -3715,58 +3715,61 @@ int CmdHF14AAIDSim(const char *Cmd) {
CLIParserInit(&ctx, "hf 14a simaid",
"Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values\n"
"These AID Values can be responded to and include extra APDU commands on GetData after response\n",
"hf 14a simaid -t 3 -> MIFARE Desfire\n"
"hf 14a simaid -t 4 -> ISO/IEC 14443-4\n"
"hf 14a simaid -t 11 -> Javacard (JCOP)\n"
"hf 14a simaid -t 3 --aid a000000000000000000000 --response 9000 --apdu 9000 -> AID, Response and APDU\n"
"hf 14a simaid -t 3 --rats 05788172220101 --response 01009000 --apdu 86009000 -> Custom RATS Added\n"
"hf 14a simaid -t 3 --rats 05788172220101 -x -> Enumerate AID Values\n"
"hf 14a simaid -t 3 -> MIFARE Desfire\n"
"hf 14a simaid -t 4 -> ISO/IEC 14443-4\n"
"hf 14a simaid -t 11 -> Javacard (JCOP)\n"
"hf 14a simaid -t 3 --aid a000000000000000000000 --selectaid_response 9000 --getdata_response 9000 -> Custom AID and responses\n"
"hf 14a simaid -t 3 --ats 05788172220101 --selectaid_response 01009000 --getdata_response 86009000 -> Custom ATS and responses\n"
"hf 14a simaid -t 3 --ats 05788172220101 -x -> Enumerate AID Values\n"
);
void *argtable[] = {
arg_param_begin,
arg_int1("t", "type", "<1-12> ", "Simulation type to use"),
arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
arg_str0("r", "rats", "<hex>", "<0-20> hex bytes RATS"),
arg_str0("a", "aid", "<hex>", "<0-100> hex bytes for AID to respond to (Default: A000000000000000000000)"),
arg_str0("e", "response", "<hex>", "<0-100> hex bytes for APDU Response to AID Select (Default: 9000)"),
arg_str0("p", "apdu", "<hex>", "<0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)"),
arg_str0("r", "ats", "<hex>", "<0-20> hex bytes ATS"),
arg_str0("a", "aid", "<hex>", "<0-30> hex bytes for AID to respond to (Default: A000000000000000000000)"),
arg_str0("e", "selectaid_response", "<hex>", "<0-100> hex bytes for APDU Response to AID Select (Default: 9000)"),
arg_str0("p", "getdata_response", "<hex>", "<0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)"),
arg_lit0("x", "enumerate", "Enumerate all AID values via returning Not Found and print them to console "),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int tagtype = arg_get_int_def(ctx, 1, 1);
bool enumerate = arg_get_lit(ctx, 7);
int uid_len = 0;
int rats_len = 0;
int ats_len = 0;
int aid_len = 0;
int respond_len = 0;
int apdu_len = 0;
int selectaid_response_len = 0;
int getdata_response_len = 0;
uint8_t uid[10] = {0};
uint8_t rats[20] = {0};
uint8_t aid[30] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t response[100] = {0x90, 0x00};
uint8_t apdu[100] = {0x90, 0x00};
uint8_t ats[20] = {0};
uint8_t aid[30] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t default_aid_len = 11;
uint8_t selectaid_response[100] = {0x90, 0x00};
uint8_t default_selectaid_response_len = 2;
uint8_t getdata_response[100] = {0x90, 0x00};
uint8_t default_getdata_response_len = 2;
int tagtype = arg_get_int_def(ctx, 1, 1);
CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
CLIGetHexWithReturn(ctx, 3, rats, &rats_len);
CLIGetHexWithReturn(ctx, 3, ats, &ats_len);
CLIGetHexWithReturn(ctx, 4, aid, &aid_len);
CLIGetHexWithReturn(ctx, 5, response, &respond_len);
CLIGetHexWithReturn(ctx, 6, apdu, &apdu_len);
CLIGetHexWithReturn(ctx, 5, selectaid_response, &selectaid_response_len);
CLIGetHexWithReturn(ctx, 6, getdata_response, &getdata_response_len);
bool enumerate = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
// default value fill for the AID, response, and apdu
// default value fill for the AID, selectaid_response, and getdata_response
if (aid_len == 0) {
aid_len = 11;
aid_len = default_aid_len;
}
if (respond_len == 0) {
respond_len = 2;
if (selectaid_response_len == 0) {
selectaid_response_len = default_selectaid_response_len;
}
if (apdu_len == 0) {
apdu_len = 2;
if (getdata_response_len == 0) {
getdata_response_len = default_getdata_response_len;
}
uint16_t flags = 0;
@ -3776,19 +3779,39 @@ int CmdHF14AAIDSim(const char *Cmd) {
FLAG_SET_UID_IN_DATA(flags, uid_len);
if (IS_FLAG_UID_IN_EMUL(flags)) {
PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
CLIParserFree(ctx);
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
useUIDfromEML = false;
}
if (rats_len > 0) {
flags |= FLAG_RATS_IN_DATA;
if (ats_len > sizeof(ats)) {
PrintAndLogEx(ERR, "Provided ATS too long");
return PM3_EINVARG;
}
if (aid_len > sizeof(aid)) {
PrintAndLogEx(ERR, "Provided AID too long");
return PM3_EINVARG;
}
CLIParserFree(ctx);
if (selectaid_response_len > sizeof(selectaid_response)) {
PrintAndLogEx(ERR, "Provided SelectAID response too long");
return PM3_EINVARG;
}
if (getdata_response_len > sizeof(getdata_response)) {
PrintAndLogEx(ERR, "Provided GetData response too long");
return PM3_EINVARG;
}
if (ats_len > 0) {
flags |= FLAG_ATS_IN_DATA;
}
if (enumerate) {
flags |= FLAG_ENUMERATE_AID;
}
if (tagtype > 12) {
PrintAndLogEx(ERR, "Undefined tag %d", tagtype);
@ -3803,31 +3826,31 @@ int CmdHF14AAIDSim(const char *Cmd) {
uint8_t tagtype;
uint16_t flags;
uint8_t uid[10];
uint8_t rats[20];
uint8_t ats[20];
uint8_t aid[30];
uint8_t response[100];
uint8_t apdu[100];
int aid_len;
int respond_len;
int apdu_len;
bool enumerate;
uint8_t selectaid_response[100];
uint8_t getdata_response[100];
uint32_t ats_len;
uint32_t aid_len;
uint32_t selectaid_response_len;
uint32_t getdata_response_len;
} PACKED payload;
payload.tagtype = tagtype;
payload.flags = flags;
payload.enumerate = enumerate;
// Copy data to payload
memcpy(payload.uid, uid, uid_len);
memcpy(payload.rats, rats, rats_len);
memcpy(payload.ats, ats, ats_len);
memcpy(payload.aid, aid, aid_len);
memcpy(payload.response, response, respond_len);
memcpy(payload.apdu, apdu, apdu_len);
memcpy(payload.selectaid_response, selectaid_response, selectaid_response_len);
memcpy(payload.getdata_response, getdata_response, getdata_response_len);
// copy the lengths data to the payload
memcpy(&payload.aid_len, &aid_len, sizeof(aid_len));
memcpy(&payload.respond_len, &respond_len, sizeof(respond_len));
memcpy(&payload.apdu_len, &apdu_len, sizeof(apdu_len));
payload.ats_len = ats_len;
payload.aid_len = aid_len;
payload.selectaid_response_len = selectaid_response_len;
payload.getdata_response_len = getdata_response_len;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443A_SIM_AID, (uint8_t *)&payload, sizeof(payload));

View file

@ -772,7 +772,8 @@ typedef struct {
#define FLAG_INTERACTIVE 0x0001
#define FLAG_ATQA_IN_DATA 0x0002
#define FLAG_SAK_IN_DATA 0x0004
#define FLAG_RATS_IN_DATA 0x0008
#define FLAG_ATS_IN_DATA 0x0008
#define FLAG_ENUMERATE_AID 0x0010
// internal constants, use the function macros instead
#define FLAG_MASK_UID 0x0030