mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 15:26:13 +08:00
fpga merge changes
This commit is contained in:
parent
7d1a278197
commit
d83a45f0cb
|
@ -336,7 +336,7 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) {
|
|||
}
|
||||
|
||||
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
|
||||
uint8_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
|
||||
uint16_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
|
||||
if (power)
|
||||
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
||||
if (highspeed)
|
||||
|
|
|
@ -41,12 +41,12 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
|||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SNIFF);
|
||||
|
||||
// Setting Frame Mode For better performance on high speed data transfer.
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNIFF);
|
||||
SpinDelay(100);
|
||||
|
||||
*len = (BigBuf_max_traceLen() & 0xFFFE);
|
||||
|
|
274
armsrc/iclass.c
274
armsrc/iclass.c
|
@ -3,6 +3,7 @@
|
|||
// Hagen Fritsch - June 2010
|
||||
// Gerhard de Koning Gans - May 2011
|
||||
// Gerhard de Koning Gans - June 2012 - Added iClass card and reader emulation
|
||||
// piwi - 2019
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
|
@ -10,7 +11,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Routines to support iClass.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Based on ISO14443a implementation. Still in experimental phase.
|
||||
// Contribution made during a security research at Radboud University Nijmegen
|
||||
//
|
||||
// Please feel free to contribute and extend iClass support!!
|
||||
|
@ -56,11 +56,6 @@
|
|||
#include "ticks.h"
|
||||
#include "iso15693.h"
|
||||
|
||||
static int g_wait = 290;
|
||||
static int timeout = 5000;
|
||||
static uint32_t time_rdr = 0;
|
||||
static uint32_t time_response = 0;
|
||||
|
||||
static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay);
|
||||
int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf);
|
||||
|
||||
|
@ -117,8 +112,9 @@ void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
}
|
||||
|
||||
static void rotateCSN(uint8_t *original_csn, uint8_t *rotated_csn) {
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
rotated_csn[i] = (original_csn[i] >> 3) | (original_csn[(i + 1) % 8] << 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Encode SOF only
|
||||
|
@ -376,8 +372,6 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
}
|
||||
}
|
||||
|
||||
int exitLoop = 0;
|
||||
|
||||
// Anti-collision process:
|
||||
// Reader 0a
|
||||
// Tag 0f
|
||||
|
@ -409,7 +403,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
uint8_t *resp_conf = BigBuf_malloc(28);
|
||||
int resp_conf_len;
|
||||
|
||||
// e-Purse
|
||||
// e-Purse (blk 2)
|
||||
// 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
|
||||
uint8_t *resp_cc = BigBuf_malloc(28);
|
||||
int resp_cc_len;
|
||||
|
@ -420,7 +414,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
uint8_t ff_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
|
||||
AddCrc(ff_data, 8);
|
||||
|
||||
// Application Issuer Area
|
||||
// Application Issuer Area (blk 5)
|
||||
uint8_t *resp_aia = BigBuf_malloc(28);
|
||||
int resp_aia_len;
|
||||
|
||||
|
@ -467,7 +461,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
|
||||
//This is used for responding to READ-block commands or other data which is dynamically generated
|
||||
//First the 'trace'-data, not encoded for FPGA
|
||||
uint8_t *data_generic_trace = BigBuf_malloc(32 + 2);//8 bytes data + 2byte CRC is max tag answer
|
||||
uint8_t *data_generic_trace = BigBuf_malloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer
|
||||
|
||||
//Then storage for the modulated data
|
||||
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
|
||||
|
@ -479,14 +473,15 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
uint8_t cmd, options, block;
|
||||
int len = 0;
|
||||
|
||||
while (exitLoop == false) {
|
||||
bool exit_loop = 0;
|
||||
while (exit_loop == false) {
|
||||
WDT_HIT();
|
||||
|
||||
uint32_t reader_eof_time = 0;
|
||||
len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time);
|
||||
if (len < 0) {
|
||||
button_pressed = true;
|
||||
exitLoop = true;
|
||||
exit_loop = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -506,7 +501,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
// Reader in anticollission phase
|
||||
if (chip_state != HALTED) {
|
||||
modulated_response = resp_sof;
|
||||
modulated_response_size = resp_sof_len; //order = 1;
|
||||
modulated_response_size = resp_sof_len;
|
||||
chip_state = ACTIVATED;
|
||||
goto send;
|
||||
}
|
||||
|
@ -527,19 +522,21 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
if (chip_state == SELECTED) {
|
||||
// block0,1,2,5 is always readable.
|
||||
switch (block) {
|
||||
case 0: // csn (0c 00)
|
||||
case 0: { // csn (0c 00)
|
||||
modulated_response = resp_csn;
|
||||
modulated_response_size = resp_csn_len;
|
||||
trace_data = csn_data;
|
||||
trace_data_size = sizeof(csn_data);
|
||||
goto send;
|
||||
case 1: // configuration (0c 01)
|
||||
}
|
||||
case 1: { // configuration (0c 01)
|
||||
modulated_response = resp_conf;
|
||||
modulated_response_size = resp_conf_len;
|
||||
trace_data = conf_data;
|
||||
trace_data_size = sizeof(conf_data);
|
||||
trace_data = conf_block;
|
||||
trace_data_size = sizeof(conf_block);
|
||||
goto send;
|
||||
case 2: // e-purse (0c 02)
|
||||
}
|
||||
case 2: {// e-purse (0c 02)
|
||||
modulated_response = resp_cc;
|
||||
modulated_response_size = resp_cc_len;
|
||||
trace_data = card_challenge_data;
|
||||
|
@ -549,19 +546,22 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
memcpy(reader_mac_buf, card_challenge_data, 8);
|
||||
}
|
||||
goto send;
|
||||
}
|
||||
case 3:
|
||||
case 4: // Kd, Kc, always respond with 0xff bytes
|
||||
case 4: { // Kd, Kc, always respond with 0xff bytes
|
||||
modulated_response = resp_ff;
|
||||
modulated_response_size = resp_ff_len;
|
||||
trace_data = ff_data;
|
||||
trace_data_size = sizeof(ff_data);
|
||||
goto send;
|
||||
case 5:// Application Issuer Area (0c 05)
|
||||
}
|
||||
case 5: { // Application Issuer Area (0c 05)
|
||||
modulated_response = resp_aia;
|
||||
modulated_response_size = resp_aia_len;
|
||||
trace_data = aia_data;
|
||||
trace_data_size = sizeof(aia_data);
|
||||
goto send;
|
||||
}
|
||||
default : {
|
||||
if (simulationMode == ICLASS_SIM_MODE_FULL) { // 0x0C
|
||||
//Read block
|
||||
|
@ -570,7 +570,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
AddCrc(data_generic_trace, 8);
|
||||
trace_data = data_generic_trace;
|
||||
trace_data_size = 10;
|
||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
||||
CodeIso15693AsTag(trace_data, trace_data_size);
|
||||
memcpy(modulated_response, ToSend, ToSendMax);
|
||||
modulated_response_size = ToSendMax;
|
||||
goto send;
|
||||
|
@ -588,23 +588,33 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
trace_data = csn_data;
|
||||
trace_data_size = sizeof(csn_data);
|
||||
goto send;
|
||||
|
||||
} 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;
|
||||
if (chip_state == SELECTED) {
|
||||
if ( ICLASS_DEBIT(cmd) ){
|
||||
cipher_state = &cipher_state_KD[current_page];
|
||||
diversified_key = diversified_kd;
|
||||
} else {
|
||||
cipher_state = &cipher_state_KC[current_page];
|
||||
diversified_key = diversified_kc;
|
||||
}
|
||||
modulated_response = resp_cc;
|
||||
modulated_response_size = resp_cc_len;
|
||||
trace_data = card_challenge_data;
|
||||
trace_data_size = sizeof(card_challenge_data);
|
||||
goto send;
|
||||
}
|
||||
|
||||
} else if (cmd == ICLASS_CMD_CHECK) { // 0x05
|
||||
// Reader random and reader MAC!!!
|
||||
if (simulationMode == ICLASS_SIM_MODE_FULL) {
|
||||
// NR, from reader, is in receivedCmd +1
|
||||
opt_doTagMAC_2(cipher_state, receivedCmd + 1, data_generic_trace, diversified_key);
|
||||
opt_doTagMAC_2(*cipher_state, receivedCmd + 1, data_generic_trace, diversified_key);
|
||||
|
||||
trace_data = data_generic_trace;
|
||||
trace_data_size = 4;
|
||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
||||
CodeIso15693AsTag(trace_data, trace_data_size);
|
||||
memcpy(data_response, ToSend, ToSendMax);
|
||||
modulated_response = data_response;
|
||||
modulated_response_size = ToSendMax;
|
||||
|
@ -628,21 +638,24 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
Dbprintf("[+] CSN: %02x .... %02x OK", csn[0], csn[7]);
|
||||
}
|
||||
if (reader_mac_buf != NULL) {
|
||||
// save NR and MAC for sim 2,4
|
||||
memcpy(reader_mac_buf + 8, receivedCmd + 1, 8);
|
||||
}
|
||||
exitLoop = true;
|
||||
exit_loop = true;
|
||||
}
|
||||
}
|
||||
goto send;
|
||||
|
||||
} else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
|
||||
|
||||
if (chip_state == SELECTED) {
|
||||
// Reader ends the session
|
||||
modulated_response = resp_sof;
|
||||
modulated_response_size = resp_sof_Len;
|
||||
modulated_response_size = resp_sof_len;
|
||||
chip_state = HALTED;
|
||||
goto send;
|
||||
}
|
||||
|
||||
} else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
|
||||
|
||||
if (chip_state == SELECTED) {
|
||||
|
@ -656,31 +669,86 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
modulated_response_size = ToSendMax;
|
||||
goto send;
|
||||
}
|
||||
} else if (simulationMode == ICLASS_SIM_MODE_FULL && 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
|
||||
//We're expected to respond with the data+crc, exactly what's already in the receivedcmd
|
||||
//receivedcmd is now UPDATE 1b | ADDRESS 1b| DATA 8b| Signature 4b or CRC 2b|
|
||||
} else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_UPDATE && (len == 12 || len == 14)) {
|
||||
|
||||
//Take the data...
|
||||
memcpy(data_generic_trace, receivedCmd + 2, 8);
|
||||
AddCrc(data_generic_trace, 8);
|
||||
trace_data = data_generic_trace;
|
||||
trace_data_size = 10;
|
||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
||||
// We're expected to respond with the data+crc, exactly what's already in the receivedCmd
|
||||
// receivedCmd is now UPDATE 1b | ADDRESS 1b | DATA 8b | Signature 4b or CRC 2b
|
||||
if (chip_state == SELECTED) {
|
||||
|
||||
memcpy(data_response, ToSend, ToSendMax);
|
||||
modulated_response = data_response;
|
||||
modulated_response_size = ToSendMax;
|
||||
// response_delay = 4600 * 1.5; // tPROG 4-15ms
|
||||
if (block == 2) { // update e-purse
|
||||
memcpy(card_challenge_data, receivedCmd + 2, 8);
|
||||
CodeIso15693AsTag(card_challenge_data, sizeof(card_challenge_data));
|
||||
memcpy(resp_cc, ToSend, ToSendMax);
|
||||
resp_cc_len = ToSendMax;
|
||||
cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
|
||||
cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
|
||||
|
||||
} else if (block == 3) { // update Kd
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (personalization_mode) {
|
||||
diversified_kd[i] = receivedCmd[2 + i];
|
||||
} else {
|
||||
diversified_kd[i] ^= receivedCmd[2 + i];
|
||||
}
|
||||
}
|
||||
cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
|
||||
|
||||
} else if (block == 4) { // update Kc
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (personalization_mode) {
|
||||
diversified_kc[i] = receivedCmd[2 + i];
|
||||
} else {
|
||||
diversified_kc[i] ^= receivedCmd[2 + i];
|
||||
}
|
||||
}
|
||||
cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
|
||||
}
|
||||
|
||||
// update emulator
|
||||
memcpy(emulator + (current_page * page_size) + (8 * block), receivedCmd + 2, 8);
|
||||
|
||||
memcpy(data_generic_trace, receivedCmd + 2, 8);
|
||||
AddCrc(data_generic_trace, 8);
|
||||
trace_data = data_generic_trace;
|
||||
trace_data_size = 10;
|
||||
CodeIso15693AsTag(trace_data, trace_data_size);
|
||||
memcpy(data_response, ToSend, ToSendMax);
|
||||
modulated_response = data_response;
|
||||
modulated_response_size = ToSendMax;
|
||||
}
|
||||
goto send;
|
||||
// } else if(receivedCmd[0] == ICLASS_CMD_PAGESEL) { // 0x84
|
||||
//Pagesel
|
||||
//Pagesel enables to select a page in the selected chip memory and return its configuration block
|
||||
//Chips with a single page will not answer to this command
|
||||
// It appears we're fine ignoring this.
|
||||
//Otherwise, we should answer 8bytes (block) + 2bytes CRC
|
||||
|
||||
} else if (receivedCmd[0] == ICLASS_CMD_PAGESEL && len == 4) { // 0x84
|
||||
// Pagesel,
|
||||
// - enables to select a page in the selected chip memory and return its configuration block
|
||||
// Chips with a single page will not answer to this command
|
||||
// Otherwise, we should answer 8bytes (conf block 1) + 2bytes CRC
|
||||
if (chip_state == SELECTED) {
|
||||
|
||||
if (simulationMode == ICLASS_SIM_MODE_FULL && max_page > 0) {
|
||||
|
||||
current_page = receivedCmd[1];
|
||||
|
||||
memcpy(data_generic_trace, emulator + (current_page * page_size) + (8 * 1), 8);
|
||||
memcpy(diversified_kd, emulator + (current_page * page_size) + (8 * 3), 8);
|
||||
memcpy(diversified_kc, emulator + (current_page * page_size) + (8 * 4), 8);
|
||||
|
||||
cipher_state = &cipher_state_KD[current_page];
|
||||
|
||||
personalization_mode = data_generic_trace[7] & 0x80;
|
||||
AddCrc(data_generic_trace, 8);
|
||||
|
||||
trace_data = data_generic_trace;
|
||||
trace_data_size = 10;
|
||||
|
||||
CodeIso15693AsTag(trace_data, trace_data_size);
|
||||
memcpy(data_response, ToSend, ToSendMax);
|
||||
modulated_response = data_response;
|
||||
modulated_response_size = ToSendMax;
|
||||
}
|
||||
}
|
||||
|
||||
// } else if(receivedCmd[0] == ICLASS_CMD_DETECT) { // 0x0F
|
||||
} else if (receivedCmd[0] == 0x26 && len == 5) {
|
||||
// standard ISO15693 INVENTORY command. Ignore.
|
||||
|
@ -697,7 +765,7 @@ send:
|
|||
if (modulated_response_size > 0) {
|
||||
uint32_t response_time = reader_eof_time + DELAY_ICLASS_VCD_TO_VICC_SIM;
|
||||
TransmitTo15693Reader(modulated_response, modulated_response_size, &response_time, 0, false);
|
||||
LogTrace(trace_data, trace_data_size, response_time*32, response_time*32 + modulated_response_size*32*64, NULL, false);
|
||||
LogTrace(trace_data, trace_data_size, response_time * 32, (response_time * 32) + (modulated_response_size * 32 * 64), NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -711,54 +779,6 @@ send:
|
|||
|
||||
|
||||
/// THE READER CODE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Transmit the command (to the tag) that was placed in ToSend[].
|
||||
//-----------------------------------------------------------------------------
|
||||
static void TransmitIClassCommand(const uint8_t *cmd, int len, int *wait) {
|
||||
|
||||
int c = 0;
|
||||
bool firstpart = true;
|
||||
uint8_t sendbyte;
|
||||
|
||||
time_rdr = 0;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
|
||||
// make sure we timeout previous comms.
|
||||
if (*wait)
|
||||
SpinDelayUs(*wait);
|
||||
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
|
||||
// DOUBLE THE SAMPLES!
|
||||
if (firstpart) {
|
||||
sendbyte = (cmd[c] & 0xf0) | (cmd[c] >> 4);
|
||||
} else {
|
||||
sendbyte = (cmd[c] & 0x0f) | (cmd[c] << 4);
|
||||
c++;
|
||||
}
|
||||
|
||||
if (sendbyte == 0xff)
|
||||
sendbyte = 0xfe;
|
||||
|
||||
AT91C_BASE_SSC->SSC_THR = sendbyte;
|
||||
firstpart = !firstpart;
|
||||
|
||||
if (c >= len) break;
|
||||
}
|
||||
}
|
||||
|
||||
time_rdr = GetCountSspClk();
|
||||
}
|
||||
|
||||
static void ReaderTransmitIClass(uint8_t *frame, int len, uint32_t *start_time) {
|
||||
|
||||
CodeIso15693AsReader(frame, len);
|
||||
|
@ -800,7 +820,7 @@ static bool selectIclassTag(uint8_t *card_data, bool use_credit_key, uint32_t *e
|
|||
// bit 7: parity.
|
||||
|
||||
if (use_credit_key)
|
||||
readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
|
||||
read_check_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
|
||||
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
|
||||
|
@ -850,7 +870,7 @@ static bool selectIclassTag(uint8_t *card_data, bool use_credit_key, uint32_t *e
|
|||
|
||||
// card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
|
||||
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc), &start_time);
|
||||
ReaderTransmitIClass(read_check_cc, sizeof(read_check_cc), &start_time);
|
||||
|
||||
// expect a 8-byte response here
|
||||
len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time);
|
||||
|
@ -864,25 +884,24 @@ static bool selectIclassTag(uint8_t *card_data, bool use_credit_key, uint32_t *e
|
|||
|
||||
// Reader iClass Anticollission
|
||||
// turn off afterwards
|
||||
void ReaderIClass(uint8_t arg0) {
|
||||
void ReaderIClass(uint8_t flags) {
|
||||
|
||||
uint8_t card_data[6 * 8] = {0};
|
||||
uint8_t card_data[6 * 8] = {0xFF};
|
||||
uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
|
||||
memset(card_data, 0xFF, sizeof(card_data));
|
||||
// memset(card_data, 0xFF, sizeof(card_data));
|
||||
memset(resp, 0xFF, sizeof(resp));
|
||||
|
||||
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully
|
||||
bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag
|
||||
bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key
|
||||
bool flagReadAIA = arg0 & FLAG_ICLASS_READER_AIA; // flag to read block5, application issuer area
|
||||
bool flag_readonce = flags & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully
|
||||
bool use_credit_key = flags & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key
|
||||
bool flag_read_aia = flags & FLAG_ICLASS_READER_AIA; // flag to read block5, application issuer area
|
||||
|
||||
if (flags & FLAG_ICLASS_READER_INIT) {
|
||||
if ((flags & FLAG_ICLASS_READER_INIT) == FLAG_ICLASS_READER_INIT) {
|
||||
Iso15693InitReader();
|
||||
}
|
||||
|
||||
if (flags & FLAG_ICLASS_READER_CLEARTRACE) {
|
||||
if ((flags & FLAG_ICLASS_READER_CLEARTRACE) == FLAG_ICLASS_READER_CLEARTRACE) {
|
||||
set_tracing(true);
|
||||
clear_trace();
|
||||
StartCountSspClk();
|
||||
|
@ -890,7 +909,6 @@ void ReaderIClass(uint8_t arg0) {
|
|||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
|
||||
int read_status = selectIclassTag(card_data, use_credit_key, &eof_time);
|
||||
if (read_status == 0) {
|
||||
reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
|
||||
|
@ -898,18 +916,18 @@ void ReaderIClass(uint8_t arg0) {
|
|||
return;
|
||||
}
|
||||
|
||||
uint8_t result_status = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC;
|
||||
uint8_t result_status = FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC;
|
||||
|
||||
//Read block 5, AIA
|
||||
if (flagReadAIA) {
|
||||
if (flag_read_aia) {
|
||||
//Read App Issuer Area block CRC(0x05) => 0xde 0x64
|
||||
uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
|
||||
uint8_t read_aa[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
|
||||
|
||||
if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
|
||||
result_status |= FLAG_ICLASS_READER_AIA;
|
||||
if (sendCmdGetResponseWithRetries(read_aa, sizeof(read_aa), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
|
||||
result_status |= FLAG_ICLASS_AIA;
|
||||
memcpy(card_data + (8 * 5), resp, 8);
|
||||
} else {
|
||||
if (DBGLEVEL >= DBG_EXTENDED) DbpString("Failed to dump AA block");
|
||||
if (DBGLEVEL >= DBG_EXTENDED) DbpString("Failed to dump AIA block");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -929,12 +947,10 @@ void ReaderIClass(uint8_t arg0) {
|
|||
// only useful if looping in arm (not try_once && not abort_after_read)
|
||||
if (memcmp(last_csn, card_data, 8) != 0) {
|
||||
|
||||
if (send) {
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
||||
if (abort_after_read) {
|
||||
LED_B_OFF();
|
||||
return;
|
||||
}
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
||||
if (flag_readonce) {
|
||||
LED_B_OFF();
|
||||
return;
|
||||
}
|
||||
LED_B_OFF();
|
||||
}
|
||||
|
@ -1269,12 +1285,12 @@ static bool iClass_WriteBlock_ext(uint8_t blockno, uint8_t *data) {
|
|||
}
|
||||
|
||||
uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
if (blockNo == 2) {
|
||||
if (blockno == 2) {
|
||||
// check response. e-purse update swaps first and second half
|
||||
if (memcmp(data+4, resp, 4) || memcmp(data, resp+4, 4)) {
|
||||
return false;
|
||||
}
|
||||
} else if (blockNo == 3 || blockNo == 4) {
|
||||
} else if (blockno == 3 || blockno == 4) {
|
||||
// check response. Key updates always return 0xffffffffffffffff
|
||||
if (memcmp(all_ff, resp, 8)) {
|
||||
return false;
|
||||
|
|
|
@ -1101,7 +1101,7 @@ static void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_
|
|||
|
||||
static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) {
|
||||
PacketResponseNG resp;
|
||||
uint8_t flags = FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_ONE_TRY;
|
||||
uint8_t flags = FLAG_ICLASS_READER_ONLY_ONCE;
|
||||
|
||||
if (use_credit_key)
|
||||
flags |= FLAG_ICLASS_READER_CEDITKEY;
|
||||
|
@ -1279,9 +1279,12 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
|||
// if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
|
||||
if (!have_debit_key && have_credit_key) use_credit_key = true;
|
||||
|
||||
uint32_t flags = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC |
|
||||
FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE |
|
||||
FLAG_ICLASS_READER_ONE_TRY;
|
||||
uint32_t flags = (
|
||||
FLAG_ICLASS_READER_INIT |
|
||||
FLAG_ICLASS_READER_CLEARTRACE |
|
||||
FLAG_ICLASS_READER_ONLY_ONCE
|
||||
);
|
||||
|
||||
|
||||
//get config and first 3 blocks
|
||||
PacketResponseNG resp;
|
||||
|
@ -1305,7 +1308,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (readStatus & (FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC)) {
|
||||
if (readStatus & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) {
|
||||
memcpy(tag_data, data, 8 * 3);
|
||||
blockno += 2; // 2 to force re-read of block 2 later. (seems to respond differently..)
|
||||
numblks = data[8];
|
||||
|
@ -2927,9 +2930,12 @@ int CmdHFiClass(const char *Cmd) {
|
|||
int readIclass(bool loop, bool verbose) {
|
||||
bool tagFound = false;
|
||||
|
||||
uint32_t flags = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_AIA |
|
||||
FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE |
|
||||
FLAG_ICLASS_READER_ONE_TRY;
|
||||
uint32_t flags = (
|
||||
FLAG_ICLASS_READER_INIT |
|
||||
FLAG_ICLASS_READER_CLEARTRACE |
|
||||
FLAG_ICLASS_READER_ONLY_ONCE |
|
||||
FLAG_ICLASS_READER_AIA
|
||||
);
|
||||
|
||||
uint32_t res = PM3_ETIMEOUT;
|
||||
// loop in client not device - else on windows have a communication error
|
||||
|
@ -2960,35 +2966,35 @@ int readIclass(bool loop, bool verbose) {
|
|||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------");
|
||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||
|
||||
if (readStatus & FLAG_ICLASS_READER_CSN) {
|
||||
if (readStatus & FLAG_ICLASS_CSN) {
|
||||
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " (uid)", sprint_hex(hdr->csn, sizeof(hdr->csn)));
|
||||
tagFound = true;
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_READER_CONF) {
|
||||
if (readStatus & FLAG_ICLASS_CONF) {
|
||||
PrintAndLogEx(SUCCESS, " Config: %s (Card configuration)", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_READER_CC) {
|
||||
if (readStatus & FLAG_ICLASS_CC) {
|
||||
PrintAndLogEx(SUCCESS, "E-purse: %s (Card challenge, CC)", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " Kd: %s (Debit key, hidden)", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
PrintAndLogEx(SUCCESS, " Kc: %s (Credit key, hidden)", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
|
||||
if (readStatus & FLAG_ICLASS_READER_AIA) {
|
||||
if (readStatus & FLAG_ICLASS_AIA) {
|
||||
// PrintAndLogEx(INFO, "--------- " _CYAN_("AIA") " ---------");
|
||||
PrintAndLogEx(SUCCESS, " AIA: %s (Application Issuer area)", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_READER_CONF) {
|
||||
if (readStatus & FLAG_ICLASS_CONF) {
|
||||
printIclassDumpInfo(data);
|
||||
}
|
||||
|
||||
// if CSN ends with FF12E0, it's inside HID CSN range.
|
||||
bool isHidRange = (memcmp((uint8_t *)(data + 5), "\xFF\x12\xE0", 3) == 0);
|
||||
|
||||
if (readStatus & FLAG_ICLASS_READER_AIA) {
|
||||
if (readStatus & FLAG_ICLASS_AIA) {
|
||||
bool legacy = (memcmp((uint8_t *)(data + 8 * 5), "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0);
|
||||
|
||||
bool se_enabled = (memcmp((uint8_t *)(data + 8 * 5), "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0);
|
||||
|
|
|
@ -579,14 +579,18 @@ typedef struct {
|
|||
#define FLAG_FORCED_ATQA 0x800
|
||||
#define FLAG_FORCED_SAK 0x1000
|
||||
|
||||
//Iclass reader flags
|
||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
||||
#define FLAG_ICLASS_READER_CC 0x02
|
||||
#define FLAG_ICLASS_READER_CSN 0x04
|
||||
#define FLAG_ICLASS_READER_CONF 0x08
|
||||
// iCLASS reader flags
|
||||
#define FLAG_ICLASS_READER_INIT 0x01
|
||||
#define FLAG_ICLASS_READER_CLEARTRACE 0x02
|
||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x04
|
||||
#define FLAG_ICLASS_READER_CEDITKEY 0x08
|
||||
#define FLAG_ICLASS_READER_AIA 0x10
|
||||
#define FLAG_ICLASS_READER_ONE_TRY 0x20
|
||||
#define FLAG_ICLASS_READER_CEDITKEY 0x40
|
||||
|
||||
// iCLASS reader status flags
|
||||
#define FLAG_ICLASS_CSN 0x01
|
||||
#define FLAG_ICLASS_CC 0x02
|
||||
#define FLAG_ICLASS_CONF 0x04
|
||||
#define FLAG_ICLASS_AIA 0x08
|
||||
|
||||
// iCLASS simulation modes
|
||||
#define ICLASS_SIM_MODE_CSN 0
|
||||
|
|
|
@ -135,7 +135,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define ICLASS_CMD_ACT 0xE
|
||||
|
||||
#define ICLASS_CREDIT(x) (((x) & 0x10) == 0x10)
|
||||
#define ICLASS_DEBIT(x) !(ICLASS_CREDIT(x))
|
||||
#define ICLASS_DEBIT(x) (((x) & 0x80) == 0x80)
|
||||
|
||||
|
||||
#define ISO14443A_CMD_REQA 0x26
|
||||
|
|
Loading…
Reference in a new issue