chg: 'hf iclass sim' - better iClass protocol implementation

This commit is contained in:
Iceman 2019-09-11 13:09:08 +02:00
parent a384774ba2
commit 341703d9a7
3 changed files with 75 additions and 63 deletions

View file

@ -1435,6 +1435,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
uint32_t r2t_stime, r2t_etime = 0;
LED_A_ON();
bool buttonPressed = false;
uint8_t cmd, options, block;
while (!exitLoop) {
WDT_HIT();
@ -1455,7 +1456,11 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
LED_C_ON(); //Signal tracer
if (receivedCmd[0] == ICLASS_CMD_ACTALL) { // 0x0A
cmd = receivedCmd[0] & 0xF;
options = (receivedCmd[0] >> 4) & 0xFF;
block = receivedCmd[1];
if (cmd == ICLASS_CMD_ACTALL) { // 0x0A
// Reader in anticollission phase
modulated_response = resp_sof;
modulated_response_size = resp_sof_Len; //order = 1;
@ -1463,7 +1468,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
trace_data_size = sizeof(sof_data);
// adjusted for 330 + (160*num of slot)
goto send;
} else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C
} else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C
if (len == 1) {
// Reader asks for anticollission CSN
modulated_response = resp_anticoll;
@ -1475,7 +1480,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
if (len == 4) {
// block0,1,2,5 is always readable.
switch (receivedCmd[1]) {
switch (block) {
case 0: // csn (0c 00)
modulated_response = resp_csn;
modulated_response_size = resp_csn_len;
@ -1508,7 +1513,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
if (simulationMode == MODE_FULLSIM) { // 0x0C
//Read block
//Take the data...
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8);
memcpy(data_generic_trace, emulator + (block << 3), 8);
AddCrc(data_generic_trace, 8);
trace_data = data_generic_trace;
trace_data_size = 10;
@ -1521,7 +1526,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
}
}//swith
}// if 4
} else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81
} else if (cmd == ICLASS_CMD_SELECT) { // 0x81
// Reader selects anticollission CSN.
// Tag sends the corresponding real CSN
modulated_response = resp_csn;
@ -1529,23 +1534,15 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
trace_data = csn_data;
trace_data_size = sizeof(csn_data);
goto send;
} else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KD) { // 0x88
// Read e-purse (88 02)
} else if (cmd == ICLASS_CMD_READCHECK ) { // 0x88
// Read e-purse KD (88 02) KC (18 02)
modulated_response = resp_cc;
modulated_response_size = resp_cc_len; //order = 4;
trace_data = card_challenge_data;
trace_data_size = sizeof(card_challenge_data);
LED_B_ON();
goto send;
} else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KC) { // 0x18
// Read e-purse (18 02)
modulated_response = resp_cc;
modulated_response_size = resp_cc_len; //order = 4;
trace_data = card_challenge_data;
trace_data_size = sizeof(card_challenge_data);
LED_B_ON();
goto send;
} else if (receivedCmd[0] == ICLASS_CMD_CHECK) { // 0x05
} else if (cmd == ICLASS_CMD_CHECK) { // 0x05
// Reader random and reader MAC!!!
if (simulationMode == MODE_FULLSIM) {
// NR, from reader, is in receivedCmd +1
@ -1583,17 +1580,17 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
}
}
goto send;
} else if (receivedCmd[0] == ICLASS_CMD_HALT && len == 1) {
} else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
// Reader ends the session
modulated_response = resp_sof;
modulated_response_size = 0; //order = 0;
trace_data = NULL;
trace_data_size = 0;
goto send;
} else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_READ4 && len == 4) { // 0x06
} else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
//Read block
//Take the data...
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8 * 4);
memcpy(data_generic_trace, emulator + (block << 3), 8 * 4);
AddCrc(data_generic_trace, 8 * 4);
trace_data = data_generic_trace;
trace_data_size = 34;
@ -1601,7 +1598,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
memcpy(modulated_response, ToSend, ToSendMax);
modulated_response_size = ToSendMax;
goto send;
} else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_UPDATE) {
} else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_UPDATE) {
//Probably the reader wants to update the nonce. Let's just ignore that for now.
// OBS! If this is implemented, don't forget to regenerate the cipher_state
@ -1854,6 +1851,7 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
SpinDelayUs(g_wait); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments.
uint32_t foo = GetCountSspClk();
uint32_t bar;
// clear RXRDY:
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
@ -1892,7 +1890,11 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
return true;
}
if (GetCountSspClk() - foo > timeout) return false;
bar = GetCountSspClk();
if ( foo > bar )
bar += ( UINT32_MAX - foo );
if (bar - foo > timeout) return false;
}
}
@ -1985,10 +1987,10 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) {
static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 };
uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK, 0x02 };
if (use_credit_key)
readcheck_cc[0] = ICLASS_CMD_READCHECK_KC;
if (use_credit_key == false)
readcheck_cc[0] |= 0x10;
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
uint8_t read_status = 0;
@ -2353,10 +2355,10 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
uint8_t keyCount = arg1 & 0xFF;
uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t resp[ICLASS_BUFFER_SIZE];
uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 };
uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK, 0x02 };
if (use_credit_key)
readcheck_cc[0] = ICLASS_CMD_READCHECK_KC;
if (use_credit_key == false)
readcheck_cc[0] |= 0x10;
// select card / e-purse
uint8_t card_data[6 * 8] = {0};

View file

@ -323,10 +323,35 @@ void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
}
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
switch (cmd[0]) {
uint8_t c = cmd[0] & 0x0F;
uint8_t parity = 0;
for ( uint8_t i=0; i<7; i++) {
parity ^= (cmd[0] >> i) & 1;
}
if ( parity == ((cmd[0] >> 7) & 1) ) {
printf("Calc %d, cmd %02x, Par %d \n", parity, cmd[0], (cmd[0] >> 7) & 1);
}
switch (c) {
case ICLASS_CMD_HALT:
snprintf(exp, size, "HALT");
break;
case ICLASS_CMD_SELECT:
snprintf(exp, size, "SELECT");
break;
case ICLASS_CMD_ACTALL:
snprintf(exp, size, "ACTALL");
break;
case ICLASS_CMD_DETECT:
snprintf(exp, size, "DETECT");
break;
case ICLASS_CMD_CHECK:
snprintf(exp, size, "CHECK");
break;
case ICLASS_CMD_READ4:
snprintf(exp, size, "READ4(%d)", cmd[1]);
break;
case ICLASS_CMD_READ_OR_IDENTIFY: {
if (cmdsize > 1) {
snprintf(exp, size, "READ(%d)", cmd[1]);
@ -335,36 +360,22 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
}
break;
}
case ICLASS_CMD_SELECT:
snprintf(exp, size, "SELECT");
break;
case ICLASS_CMD_PAGESEL:
snprintf(exp, size, "PAGESEL(%d)", cmd[1]);
break;
case ICLASS_CMD_READCHECK_KC:
snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]);
break;
case ICLASS_CMD_READCHECK_KD:
snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]);
break;
case ICLASS_CMD_CHECK:
snprintf(exp, size, "CHECK");
break;
case ICLASS_CMD_DETECT:
snprintf(exp, size, "DETECT");
break;
case ICLASS_CMD_HALT:
snprintf(exp, size, "HALT");
break;
case ICLASS_CMD_UPDATE:
snprintf(exp, size, "UPDATE(%d)", cmd[1]);
break;
case ICLASS_CMD_READCHECK:
if ( ICLASS_CREDIT(c) ) {
snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]);
} else {
snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]);
}
break;
case ICLASS_CMD_ACT:
snprintf(exp, size, "ACT");
break;
case ICLASS_CMD_READ4:
snprintf(exp, size, "READ4(%d)", cmd[1]);
break;
default:
snprintf(exp, size, "?");
break;

View file

@ -120,22 +120,21 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
// for instance ICLASS_CMD_SELECT 0x81 tells if ISO14443b/BPSK coding/106 kbits/s
// for instance ICLASS_CMD_SELECT 0x41 tells if ISO14443b/BPSK coding/423 kbits/s
//
#define ICLASS_CMD_HALT 0x00
#define ICLASS_CMD_SELECT_15 0x01
#define ICLASS_CMD_ACTALL 0x0A
#define ICLASS_CMD_DETECT 0x0F
#define ICLASS_CMD_HALT 0x0
#define ICLASS_CMD_SELECT 0x1
#define ICLASS_CMD_ACTALL 0xA
#define ICLASS_CMD_DETECT 0xF
#define ICLASS_CMD_CHECK 0x05
#define ICLASS_CMD_READ4 0x06
#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C
#define ICLASS_CMD_SELECT 0x81
#define ICLASS_CMD_PAGESEL 0x84
#define ICLASS_CMD_UPDATE 0x87
#define ICLASS_CMD_READCHECK_KC 0x18
#define ICLASS_CMD_READCHECK_KD 0x88
#define ICLASS_CMD_ACT 0x8E
#define ICLASS_CMD_PAGESEL 0x4
#define ICLASS_CMD_CHECK 0x5
#define ICLASS_CMD_READ4 0x6
#define ICLASS_CMD_UPDATE 0x7
#define ICLASS_CMD_READCHECK 0x8
#define ICLASS_CMD_READ_OR_IDENTIFY 0xC
#define ICLASS_CMD_ACT 0xE
#define ICLASS_CREDIT(x) (((x) & 0x5) == 1)
#define ICLASS_DEBIT(x) (((x) & 0x5) == 0)
#define ISO14443A_CMD_REQA 0x26