mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-12-29 11:52:59 +08:00
chg: 'hf iclass sim' - better iClass protocol implementation
This commit is contained in:
parent
a384774ba2
commit
341703d9a7
3 changed files with 75 additions and 63 deletions
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue