mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-12-29 11:52:59 +08:00
fixed iso14443a-4 similation, got rid of many ugly memory allocation issues
This commit is contained in:
parent
2fca3ad92d
commit
ce02f6f992
1 changed files with 225 additions and 198 deletions
|
@ -775,48 +775,48 @@ static void CodeIso14443aAsTag(const uint8_t *cmd, int len){
|
||||||
CodeIso14443aAsTagPar(cmd, len, GetParity(cmd, len));
|
CodeIso14443aAsTagPar(cmd, len, GetParity(cmd, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
////-----------------------------------------------------------------------------
|
||||||
// This is to send a NACK kind of answer, its only 3 bits, I know it should be 4
|
//// This is to send a NACK kind of answer, its only 3 bits, I know it should be 4
|
||||||
//-----------------------------------------------------------------------------
|
////-----------------------------------------------------------------------------
|
||||||
static void CodeStrangeAnswerAsTag()
|
//static void CodeStrangeAnswerAsTag()
|
||||||
{
|
//{
|
||||||
int i;
|
// int i;
|
||||||
|
//
|
||||||
ToSendReset();
|
// ToSendReset();
|
||||||
|
//
|
||||||
// Correction bit, might be removed when not needed
|
// // Correction bit, might be removed when not needed
|
||||||
ToSendStuffBit(0);
|
// ToSendStuffBit(0);
|
||||||
ToSendStuffBit(0);
|
// ToSendStuffBit(0);
|
||||||
ToSendStuffBit(0);
|
// ToSendStuffBit(0);
|
||||||
ToSendStuffBit(0);
|
// ToSendStuffBit(0);
|
||||||
ToSendStuffBit(1); // 1
|
// ToSendStuffBit(1); // 1
|
||||||
ToSendStuffBit(0);
|
// ToSendStuffBit(0);
|
||||||
ToSendStuffBit(0);
|
// ToSendStuffBit(0);
|
||||||
ToSendStuffBit(0);
|
// ToSendStuffBit(0);
|
||||||
|
//
|
||||||
// Send startbit
|
// // Send startbit
|
||||||
ToSend[++ToSendMax] = SEC_D;
|
// ToSend[++ToSendMax] = SEC_D;
|
||||||
|
//
|
||||||
// 0
|
// // 0
|
||||||
ToSend[++ToSendMax] = SEC_E;
|
// ToSend[++ToSendMax] = SEC_E;
|
||||||
|
//
|
||||||
// 0
|
// // 0
|
||||||
ToSend[++ToSendMax] = SEC_E;
|
// ToSend[++ToSendMax] = SEC_E;
|
||||||
|
//
|
||||||
// 1
|
// // 1
|
||||||
ToSend[++ToSendMax] = SEC_D;
|
// ToSend[++ToSendMax] = SEC_D;
|
||||||
|
//
|
||||||
// Send stopbit
|
// // Send stopbit
|
||||||
ToSend[++ToSendMax] = SEC_F;
|
// ToSend[++ToSendMax] = SEC_F;
|
||||||
|
//
|
||||||
// Flush the buffer in FPGA!!
|
// // Flush the buffer in FPGA!!
|
||||||
for(i = 0; i < 5; i++) {
|
// for(i = 0; i < 5; i++) {
|
||||||
ToSend[++ToSendMax] = SEC_F;
|
// ToSend[++ToSendMax] = SEC_F;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Convert from last byte pos to length
|
// // Convert from last byte pos to length
|
||||||
ToSendMax++;
|
// ToSendMax++;
|
||||||
}
|
//}
|
||||||
|
|
||||||
static void Code4bitAnswerAsTag(uint8_t cmd)
|
static void Code4bitAnswerAsTag(uint8_t cmd)
|
||||||
{
|
{
|
||||||
|
@ -908,6 +908,67 @@ int EmSendCmdEx(uint8_t *resp, int respLen, int correctionNeeded);
|
||||||
int EmSendCmd(uint8_t *resp, int respLen);
|
int EmSendCmd(uint8_t *resp, int respLen);
|
||||||
int EmSendCmdPar(uint8_t *resp, int respLen, uint32_t par);
|
int EmSendCmdPar(uint8_t *resp, int respLen, uint32_t par);
|
||||||
|
|
||||||
|
static uint8_t* free_buffer_pointer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* response;
|
||||||
|
size_t response_n;
|
||||||
|
uint8_t* modulation;
|
||||||
|
size_t modulation_n;
|
||||||
|
} tag_response_info_t;
|
||||||
|
|
||||||
|
void reset_free_buffer() {
|
||||||
|
free_buffer_pointer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) {
|
||||||
|
// Exmaple response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes
|
||||||
|
// This will need the following byte array for a modulation sequence
|
||||||
|
// 144 data bits (18 * 8)
|
||||||
|
// 18 parity bits
|
||||||
|
// 2 Start and stop
|
||||||
|
// 1 Correction bit (Answer in 1172 or 1236 periods, see FPGA)
|
||||||
|
// 1 just for the case
|
||||||
|
// ----------- +
|
||||||
|
// 166 bytes, since every bit that needs to be send costs us a byte
|
||||||
|
//
|
||||||
|
|
||||||
|
// Prepare the tag modulation bits from the message
|
||||||
|
CodeIso14443aAsTag(response_info->response,response_info->response_n);
|
||||||
|
|
||||||
|
// Make sure we do not exceed the free buffer space
|
||||||
|
if (ToSendMax > max_buffer_size) {
|
||||||
|
Dbprintf("Out of memory, when modulating bits for tag answer:");
|
||||||
|
Dbhexdump(response_info->response_n,response_info->response,false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the byte array, used for this modulation to the buffer position
|
||||||
|
memcpy(response_info->modulation,ToSend,ToSendMax);
|
||||||
|
|
||||||
|
// Store the number of bytes that were used for encoding/modulation
|
||||||
|
response_info->modulation_n = ToSendMax;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) {
|
||||||
|
// Retrieve and store the current buffer index
|
||||||
|
response_info->modulation = free_buffer_pointer;
|
||||||
|
|
||||||
|
// Determine the maximum size we can use from our buffer
|
||||||
|
size_t max_buffer_size = (((uint8_t *)BigBuf)+FREE_BUFFER_OFFSET+FREE_BUFFER_SIZE)-free_buffer_pointer;
|
||||||
|
|
||||||
|
// Forward the prepare tag modulation function to the inner function
|
||||||
|
if (prepare_tag_modulation(response_info,max_buffer_size)) {
|
||||||
|
// Update the free buffer offset
|
||||||
|
free_buffer_pointer += ToSendMax;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Main loop of simulated tag: receive commands from reader, decide what
|
// Main loop of simulated tag: receive commands from reader, decide what
|
||||||
// response to send, and send it.
|
// response to send, and send it.
|
||||||
|
@ -990,57 +1051,41 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
|
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
|
||||||
|
|
||||||
uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
|
uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
|
||||||
uint8_t response6[] = { 0x03, 0x3B, 0x00, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS
|
uint8_t response6[] = { 0x04, 0x58, 0x00, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS
|
||||||
ComputeCrc14443(CRC_14443_A, response6, 3, &response6[3], &response6[4]);
|
ComputeCrc14443(CRC_14443_A, response6, 4, &response6[4], &response6[5]);
|
||||||
|
|
||||||
uint8_t *resp = NULL;
|
#define TAG_RESPONSE_COUNT 7
|
||||||
int respLen;
|
tag_response_info_t responses[TAG_RESPONSE_COUNT] = {
|
||||||
|
{ .response = response1, .response_n = sizeof(response1) }, // Answer to request - respond with card type
|
||||||
|
{ .response = response2, .response_n = sizeof(response2) }, // Anticollision cascade1 - respond with uid
|
||||||
|
{ .response = response2a, .response_n = sizeof(response2a) }, // Anticollision cascade2 - respond with 2nd half of uid if asked
|
||||||
|
{ .response = response3, .response_n = sizeof(response3) }, // Acknowledge select - cascade 1
|
||||||
|
{ .response = response3a, .response_n = sizeof(response3a) }, // Acknowledge select - cascade 2
|
||||||
|
{ .response = response5, .response_n = sizeof(response5) }, // Authentication answer (random nonce)
|
||||||
|
{ .response = response6, .response_n = sizeof(response6) }, // dummy ATS (pseudo-ATR), answer to RATS
|
||||||
|
};
|
||||||
|
|
||||||
// Longest possible response will be 16 bytes + 2 CRC = 18 bytes
|
// Allocate 512 bytes for the dynamic modulation, created when the reader querries for it
|
||||||
// This will need
|
// Such a response is less time critical, so we can prepare them on the fly
|
||||||
// 144 data bits (18 * 8)
|
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
|
||||||
// 18 parity bits
|
#define DYNAMIC_MODULATION_BUFFER_SIZE 512
|
||||||
// 2 Start and stop
|
uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE];
|
||||||
// 1 Correction bit (Answer in 1172 or 1236 periods, see FPGA)
|
uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE];
|
||||||
// 1 just for the case
|
tag_response_info_t dynamic_response_info = {
|
||||||
// ----------- +
|
.response = dynamic_response_buffer,
|
||||||
// 166
|
.response_n = 0,
|
||||||
//
|
.modulation = dynamic_modulation_buffer,
|
||||||
// 166 bytes, since every bit that needs to be send costs us a byte
|
.modulation_n = 0
|
||||||
//
|
};
|
||||||
|
|
||||||
// Respond with card type
|
// Reset the offset pointer of the free buffer
|
||||||
uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
|
reset_free_buffer();
|
||||||
int resp1Len;
|
|
||||||
|
// Prepare the responses of the anticollision phase
|
||||||
// Anticollision cascade1 - respond with uid
|
// there will be not enough time to do this at the moment the reader sends it REQA
|
||||||
uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 166);
|
for (size_t i=0; i<TAG_RESPONSE_COUNT; i++) {
|
||||||
int resp2Len;
|
prepare_allocated_tag_modulation(&responses[i]);
|
||||||
|
}
|
||||||
// Anticollision cascade2 - respond with 2nd half of uid if asked
|
|
||||||
// we're only going to be asked if we set the 1st byte of the UID (during cascade1) to 0x88
|
|
||||||
uint8_t *resp2a = (((uint8_t *)BigBuf) + 1140);
|
|
||||||
int resp2aLen;
|
|
||||||
|
|
||||||
// Acknowledge select - cascade 1
|
|
||||||
uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*2));
|
|
||||||
int resp3Len;
|
|
||||||
|
|
||||||
// Acknowledge select - cascade 2
|
|
||||||
uint8_t *resp3a = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*3));
|
|
||||||
int resp3aLen;
|
|
||||||
|
|
||||||
// Response to a read request - not implemented atm
|
|
||||||
uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*4));
|
|
||||||
// int resp4Len;
|
|
||||||
|
|
||||||
// Authenticate response - nonce
|
|
||||||
uint8_t *resp5 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*5));
|
|
||||||
int resp5Len;
|
|
||||||
|
|
||||||
// Authenticate response - nonce
|
|
||||||
uint8_t *resp6 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*6));
|
|
||||||
int resp6Len;
|
|
||||||
|
|
||||||
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
||||||
int len;
|
int len;
|
||||||
|
@ -1052,60 +1097,22 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
// Just to allow some checks
|
// Just to allow some checks
|
||||||
int happened = 0;
|
int happened = 0;
|
||||||
int happened2 = 0;
|
int happened2 = 0;
|
||||||
|
|
||||||
int cmdsRecvd = 0;
|
int cmdsRecvd = 0;
|
||||||
uint8_t* respdata = NULL;
|
|
||||||
int respsize = 0;
|
|
||||||
// uint8_t nack = 0x04;
|
|
||||||
|
|
||||||
memset(receivedCmd, 0x44, RECV_CMD_SIZE);
|
|
||||||
|
|
||||||
// Prepare the responses of the anticollision phase
|
|
||||||
// there will be not enough time to do this at the moment the reader sends it REQA
|
|
||||||
|
|
||||||
// Answer to request
|
|
||||||
CodeIso14443aAsTag(response1, sizeof(response1));
|
|
||||||
memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
|
|
||||||
|
|
||||||
// Send our UID (cascade 1)
|
|
||||||
CodeIso14443aAsTag(response2, sizeof(response2));
|
|
||||||
memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;
|
|
||||||
|
|
||||||
// Answer to select (cascade1)
|
|
||||||
CodeIso14443aAsTag(response3, sizeof(response3));
|
|
||||||
memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;
|
|
||||||
|
|
||||||
// Send the cascade 2 2nd part of the uid
|
|
||||||
CodeIso14443aAsTag(response2a, sizeof(response2a));
|
|
||||||
memcpy(resp2a, ToSend, ToSendMax); resp2aLen = ToSendMax;
|
|
||||||
|
|
||||||
// Answer to select (cascade 2)
|
|
||||||
CodeIso14443aAsTag(response3a, sizeof(response3a));
|
|
||||||
memcpy(resp3a, ToSend, ToSendMax); resp3aLen = ToSendMax;
|
|
||||||
|
|
||||||
// Strange answer is an example of rare message size (3 bits)
|
|
||||||
CodeStrangeAnswerAsTag();
|
|
||||||
memcpy(resp4, ToSend, ToSendMax);// resp4Len = ToSendMax;
|
|
||||||
|
|
||||||
// Authentication answer (random nonce)
|
|
||||||
CodeIso14443aAsTag(response5, sizeof(response5));
|
|
||||||
memcpy(resp5, ToSend, ToSendMax); resp5Len = ToSendMax;
|
|
||||||
|
|
||||||
// dummy ATS (pseudo-ATR), answer to RATS
|
|
||||||
CodeIso14443aAsTag(response6, sizeof(response6));
|
|
||||||
memcpy(resp6, ToSend, ToSendMax); resp6Len = ToSendMax;
|
|
||||||
|
|
||||||
// We need to listen to the high-frequency, peak-detected path.
|
// We need to listen to the high-frequency, peak-detected path.
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc();
|
||||||
|
|
||||||
cmdsRecvd = 0;
|
cmdsRecvd = 0;
|
||||||
|
tag_response_info_t* p_response;
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
// Clean receive command buffer
|
||||||
|
memset(receivedCmd, 0x44, RECV_CMD_SIZE);
|
||||||
|
|
||||||
if(!GetIso14443aCommandFromReader(receivedCmd, &len, RECV_CMD_SIZE)) {
|
if(!GetIso14443aCommandFromReader(receivedCmd, &len, RECV_CMD_SIZE)) {
|
||||||
DbpString("button press");
|
DbpString("Button press");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,69 +1120,98 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
LogTrace(receivedCmd,len, 0, Uart.parityBits, TRUE);
|
LogTrace(receivedCmd,len, 0, Uart.parityBits, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p_response = NULL;
|
||||||
|
|
||||||
// doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated
|
// doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated
|
||||||
// Okay, look at the command now.
|
// Okay, look at the command now.
|
||||||
lastorder = order;
|
lastorder = order;
|
||||||
if(receivedCmd[0] == 0x26) { // Received a REQUEST
|
if(receivedCmd[0] == 0x26) { // Received a REQUEST
|
||||||
resp = resp1; respLen = resp1Len; order = 1;
|
p_response = &responses[0]; order = 1;
|
||||||
respdata = response1;
|
|
||||||
respsize = sizeof(response1);
|
|
||||||
} else if(receivedCmd[0] == 0x52) { // Received a WAKEUP
|
} else if(receivedCmd[0] == 0x52) { // Received a WAKEUP
|
||||||
resp = resp1; respLen = resp1Len; order = 6;
|
p_response = &responses[0]; order = 6;
|
||||||
respdata = response1;
|
|
||||||
respsize = sizeof(response1);
|
|
||||||
} else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // Received request for UID (cascade 1)
|
} else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // Received request for UID (cascade 1)
|
||||||
resp = resp2; respLen = resp2Len; order = 2;
|
p_response = &responses[1]; order = 2;
|
||||||
respdata = response2;
|
|
||||||
respsize = sizeof(response2);
|
|
||||||
} else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x95) { // Received request for UID (cascade 2)
|
} else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x95) { // Received request for UID (cascade 2)
|
||||||
resp = resp2a; respLen = resp2aLen; order = 20;
|
p_response = &responses[2]; order = 20;
|
||||||
respdata = response2a;
|
|
||||||
respsize = sizeof(response2a);
|
|
||||||
} else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x93) { // Received a SELECT (cascade 1)
|
} else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x93) { // Received a SELECT (cascade 1)
|
||||||
resp = resp3; respLen = resp3Len; order = 3;
|
p_response = &responses[3]; order = 3;
|
||||||
respdata = response3;
|
|
||||||
respsize = sizeof(response3);
|
|
||||||
} else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x95) { // Received a SELECT (cascade 2)
|
} else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x95) { // Received a SELECT (cascade 2)
|
||||||
resp = resp3a; respLen = resp3aLen; order = 30;
|
p_response = &responses[4]; order = 30;
|
||||||
respdata = response3a;
|
|
||||||
respsize = sizeof(response3a);
|
|
||||||
} else if(receivedCmd[0] == 0x30) { // Received a (plain) READ
|
} else if(receivedCmd[0] == 0x30) { // Received a (plain) READ
|
||||||
// resp = resp4; respLen = resp4Len; order = 4; // Do nothing
|
|
||||||
// respdata = &nack;
|
|
||||||
// respsize = sizeof(nack); // 4-bit answer
|
|
||||||
EmSendCmdEx(data+(4*receivedCmd[0]),16,false);
|
EmSendCmdEx(data+(4*receivedCmd[0]),16,false);
|
||||||
Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]);
|
Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]);
|
||||||
// We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
|
// We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
|
||||||
respLen = 0;
|
p_response = NULL;
|
||||||
} else if(receivedCmd[0] == 0x50) { // Received a HALT
|
} else if(receivedCmd[0] == 0x50) { // Received a HALT
|
||||||
// DbpString("Reader requested we HALT!:");
|
// DbpString("Reader requested we HALT!:");
|
||||||
// Do not respond
|
p_response = NULL;
|
||||||
resp = resp1; respLen = 0; order = 0;
|
|
||||||
respdata = NULL;
|
|
||||||
respsize = 0;
|
|
||||||
} else if(receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61) { // Received an authentication request
|
} else if(receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61) { // Received an authentication request
|
||||||
resp = resp5; respLen = resp5Len; order = 7;
|
p_response = &responses[5]; order = 7;
|
||||||
respdata = response5;
|
|
||||||
respsize = sizeof(response5);
|
|
||||||
} else if(receivedCmd[0] == 0xE0) { // Received a RATS request
|
} else if(receivedCmd[0] == 0xE0) { // Received a RATS request
|
||||||
resp = resp6; respLen = resp6Len; order = 70;
|
p_response = &responses[6]; order = 70;
|
||||||
respdata = response6;
|
} else if (order == 7 && len ==8) { // Received authentication request
|
||||||
respsize = sizeof(response6);
|
uint32_t nr = bytes_to_num(receivedCmd,4);
|
||||||
} else {
|
uint32_t ar = bytes_to_num(receivedCmd+4,4);
|
||||||
if (order == 7 && len ==8) {
|
Dbprintf("Auth attempt {nr}{ar}: %08x %08x",nr,ar);
|
||||||
uint32_t nr = bytes_to_num(receivedCmd,4);
|
} else {
|
||||||
uint32_t ar = bytes_to_num(receivedCmd+4,4);
|
// Check for ISO 14443A-4 compliant commands, look at left nibble
|
||||||
Dbprintf("Auth attempt {nr}{ar}: %08x %08x",nr,ar);
|
switch (receivedCmd[0]) {
|
||||||
} else {
|
|
||||||
// Never seen this command before
|
case 0x0B:
|
||||||
Dbprintf("Received unknown command (len=%d):",len);
|
case 0x0A: { // IBlock (command)
|
||||||
Dbhexdump(len,receivedCmd,false);
|
dynamic_response_info.response[0] = receivedCmd[0];
|
||||||
|
dynamic_response_info.response[1] = 0x00;
|
||||||
|
dynamic_response_info.response[2] = 0x90;
|
||||||
|
dynamic_response_info.response[3] = 0x00;
|
||||||
|
dynamic_response_info.response_n = 4;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x1A:
|
||||||
|
case 0x1B: { // Chaining command
|
||||||
|
dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1);
|
||||||
|
dynamic_response_info.response_n = 2;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0xaa:
|
||||||
|
case 0xbb: {
|
||||||
|
dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11;
|
||||||
|
dynamic_response_info.response_n = 2;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0xBA: { //
|
||||||
|
memcpy(dynamic_response_info.response,"\xAB\x00",2);
|
||||||
|
dynamic_response_info.response_n = 2;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0xCA:
|
||||||
|
case 0xC2: { // Readers sends deselect command
|
||||||
|
memcpy(dynamic_response_info.response,"\xCA\x00",2);
|
||||||
|
dynamic_response_info.response_n = 2;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// Never seen this command before
|
||||||
|
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
|
||||||
|
AppendCrc14443a(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) {
|
||||||
|
Dbprintf("Error preparing tag response");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p_response = &dynamic_response_info;
|
||||||
}
|
}
|
||||||
// Do not respond
|
|
||||||
resp = resp1; respLen = 0; order = 0;
|
|
||||||
respdata = NULL;
|
|
||||||
respsize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count number of wakeups received after a halt
|
// Count number of wakeups received after a halt
|
||||||
|
@ -1193,25 +1229,19 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
if(cmdsRecvd > 999) {
|
if(cmdsRecvd > 999) {
|
||||||
DbpString("1000 commands later...");
|
DbpString("1000 commands later...");
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
cmdsRecvd++;
|
|
||||||
}
|
}
|
||||||
|
cmdsRecvd++;
|
||||||
|
|
||||||
if(respLen > 0) {
|
if (p_response != NULL) {
|
||||||
EmSendCmd14443aRaw(resp, respLen, receivedCmd[0] == 0x52);
|
EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n, receivedCmd[0] == 0x52);
|
||||||
}
|
if (tracing) {
|
||||||
|
LogTrace(p_response->response,p_response->response_n,0,SwapBits(GetParity(p_response->response,p_response->response_n),p_response->response_n),FALSE);
|
||||||
if (tracing) {
|
if(traceLen > TRACE_SIZE) {
|
||||||
if (respdata != NULL) {
|
DbpString("Trace full");
|
||||||
LogTrace(respdata,respsize, 0, SwapBits(GetParity(respdata,respsize),respsize), FALSE);
|
// break;
|
||||||
}
|
}
|
||||||
if(traceLen > TRACE_SIZE) {
|
}
|
||||||
DbpString("Trace full");
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(receivedCmd, 0x44, RECV_CMD_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
|
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
|
||||||
|
@ -1242,9 +1272,6 @@ void PrepareDelayedTransfer(uint16_t delay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Transmit the command (to the tag) that was placed in ToSend[].
|
// Transmit the command (to the tag) that was placed in ToSend[].
|
||||||
// Parameter timing:
|
// Parameter timing:
|
||||||
|
|
Loading…
Reference in a new issue