diff --git a/armsrc/iclass.c b/armsrc/iclass.c index c87bade4b..08f05857b 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -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}; diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 5a2ff5248..d0fcea8f5 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -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; diff --git a/include/protocols.h b/include/protocols.h index cb38d9c84..9b47266c3 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -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