mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
fpga merge changes
This commit is contained in:
parent
7d1a278197
commit
d83a45f0cb
6 changed files with 180 additions and 154 deletions
|
@ -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) {
|
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)
|
if (power)
|
||||||
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
||||||
if (highspeed)
|
if (highspeed)
|
||||||
|
|
|
@ -41,12 +41,12 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
|
||||||
// Set up the synchronous serial port
|
// Set up the synchronous serial port
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SNIFF);
|
||||||
|
|
||||||
// Setting Frame Mode For better performance on high speed data transfer.
|
// Setting Frame Mode For better performance on high speed data transfer.
|
||||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16);
|
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);
|
SpinDelay(100);
|
||||||
|
|
||||||
*len = (BigBuf_max_traceLen() & 0xFFFE);
|
*len = (BigBuf_max_traceLen() & 0xFFFE);
|
||||||
|
|
274
armsrc/iclass.c
274
armsrc/iclass.c
|
@ -3,6 +3,7 @@
|
||||||
// Hagen Fritsch - June 2010
|
// Hagen Fritsch - June 2010
|
||||||
// Gerhard de Koning Gans - May 2011
|
// Gerhard de Koning Gans - May 2011
|
||||||
// Gerhard de Koning Gans - June 2012 - Added iClass card and reader emulation
|
// 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,
|
// 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
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
@ -10,7 +11,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Routines to support iClass.
|
// Routines to support iClass.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Based on ISO14443a implementation. Still in experimental phase.
|
|
||||||
// Contribution made during a security research at Radboud University Nijmegen
|
// Contribution made during a security research at Radboud University Nijmegen
|
||||||
//
|
//
|
||||||
// Please feel free to contribute and extend iClass support!!
|
// Please feel free to contribute and extend iClass support!!
|
||||||
|
@ -56,11 +56,6 @@
|
||||||
#include "ticks.h"
|
#include "ticks.h"
|
||||||
#include "iso15693.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);
|
static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay);
|
||||||
int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf);
|
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) {
|
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);
|
rotated_csn[i] = (original_csn[i] >> 3) | (original_csn[(i + 1) % 8] << 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode SOF only
|
// Encode SOF only
|
||||||
|
@ -376,8 +372,6 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int exitLoop = 0;
|
|
||||||
|
|
||||||
// Anti-collision process:
|
// Anti-collision process:
|
||||||
// Reader 0a
|
// Reader 0a
|
||||||
// Tag 0f
|
// Tag 0f
|
||||||
|
@ -409,7 +403,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
uint8_t *resp_conf = BigBuf_malloc(28);
|
uint8_t *resp_conf = BigBuf_malloc(28);
|
||||||
int resp_conf_len;
|
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)
|
// 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
|
||||||
uint8_t *resp_cc = BigBuf_malloc(28);
|
uint8_t *resp_cc = BigBuf_malloc(28);
|
||||||
int resp_cc_len;
|
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};
|
uint8_t ff_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
|
||||||
AddCrc(ff_data, 8);
|
AddCrc(ff_data, 8);
|
||||||
|
|
||||||
// Application Issuer Area
|
// Application Issuer Area (blk 5)
|
||||||
uint8_t *resp_aia = BigBuf_malloc(28);
|
uint8_t *resp_aia = BigBuf_malloc(28);
|
||||||
int resp_aia_len;
|
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
|
//This is used for responding to READ-block commands or other data which is dynamically generated
|
||||||
//First the 'trace'-data, not encoded for FPGA
|
//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
|
//Then storage for the modulated data
|
||||||
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
|
//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;
|
uint8_t cmd, options, block;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
while (exitLoop == false) {
|
bool exit_loop = 0;
|
||||||
|
while (exit_loop == false) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
uint32_t reader_eof_time = 0;
|
uint32_t reader_eof_time = 0;
|
||||||
len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time);
|
len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
button_pressed = true;
|
button_pressed = true;
|
||||||
exitLoop = true;
|
exit_loop = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +501,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
// Reader in anticollission phase
|
// Reader in anticollission phase
|
||||||
if (chip_state != HALTED) {
|
if (chip_state != HALTED) {
|
||||||
modulated_response = resp_sof;
|
modulated_response = resp_sof;
|
||||||
modulated_response_size = resp_sof_len; //order = 1;
|
modulated_response_size = resp_sof_len;
|
||||||
chip_state = ACTIVATED;
|
chip_state = ACTIVATED;
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
|
@ -527,19 +522,21 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
if (chip_state == SELECTED) {
|
if (chip_state == SELECTED) {
|
||||||
// block0,1,2,5 is always readable.
|
// block0,1,2,5 is always readable.
|
||||||
switch (block) {
|
switch (block) {
|
||||||
case 0: // csn (0c 00)
|
case 0: { // csn (0c 00)
|
||||||
modulated_response = resp_csn;
|
modulated_response = resp_csn;
|
||||||
modulated_response_size = resp_csn_len;
|
modulated_response_size = resp_csn_len;
|
||||||
trace_data = csn_data;
|
trace_data = csn_data;
|
||||||
trace_data_size = sizeof(csn_data);
|
trace_data_size = sizeof(csn_data);
|
||||||
goto send;
|
goto send;
|
||||||
case 1: // configuration (0c 01)
|
}
|
||||||
|
case 1: { // configuration (0c 01)
|
||||||
modulated_response = resp_conf;
|
modulated_response = resp_conf;
|
||||||
modulated_response_size = resp_conf_len;
|
modulated_response_size = resp_conf_len;
|
||||||
trace_data = conf_data;
|
trace_data = conf_block;
|
||||||
trace_data_size = sizeof(conf_data);
|
trace_data_size = sizeof(conf_block);
|
||||||
goto send;
|
goto send;
|
||||||
case 2: // e-purse (0c 02)
|
}
|
||||||
|
case 2: {// e-purse (0c 02)
|
||||||
modulated_response = resp_cc;
|
modulated_response = resp_cc;
|
||||||
modulated_response_size = resp_cc_len;
|
modulated_response_size = resp_cc_len;
|
||||||
trace_data = card_challenge_data;
|
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);
|
memcpy(reader_mac_buf, card_challenge_data, 8);
|
||||||
}
|
}
|
||||||
goto send;
|
goto send;
|
||||||
|
}
|
||||||
case 3:
|
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 = resp_ff;
|
||||||
modulated_response_size = resp_ff_len;
|
modulated_response_size = resp_ff_len;
|
||||||
trace_data = ff_data;
|
trace_data = ff_data;
|
||||||
trace_data_size = sizeof(ff_data);
|
trace_data_size = sizeof(ff_data);
|
||||||
goto send;
|
goto send;
|
||||||
case 5:// Application Issuer Area (0c 05)
|
}
|
||||||
|
case 5: { // Application Issuer Area (0c 05)
|
||||||
modulated_response = resp_aia;
|
modulated_response = resp_aia;
|
||||||
modulated_response_size = resp_aia_len;
|
modulated_response_size = resp_aia_len;
|
||||||
trace_data = aia_data;
|
trace_data = aia_data;
|
||||||
trace_data_size = sizeof(aia_data);
|
trace_data_size = sizeof(aia_data);
|
||||||
goto send;
|
goto send;
|
||||||
|
}
|
||||||
default : {
|
default : {
|
||||||
if (simulationMode == ICLASS_SIM_MODE_FULL) { // 0x0C
|
if (simulationMode == ICLASS_SIM_MODE_FULL) { // 0x0C
|
||||||
//Read block
|
//Read block
|
||||||
|
@ -570,7 +570,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
AddCrc(data_generic_trace, 8);
|
AddCrc(data_generic_trace, 8);
|
||||||
trace_data = data_generic_trace;
|
trace_data = data_generic_trace;
|
||||||
trace_data_size = 10;
|
trace_data_size = 10;
|
||||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
CodeIso15693AsTag(trace_data, trace_data_size);
|
||||||
memcpy(modulated_response, ToSend, ToSendMax);
|
memcpy(modulated_response, ToSend, ToSendMax);
|
||||||
modulated_response_size = ToSendMax;
|
modulated_response_size = ToSendMax;
|
||||||
goto send;
|
goto send;
|
||||||
|
@ -588,23 +588,33 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
trace_data = csn_data;
|
trace_data = csn_data;
|
||||||
trace_data_size = sizeof(csn_data);
|
trace_data_size = sizeof(csn_data);
|
||||||
goto send;
|
goto send;
|
||||||
|
|
||||||
} else if (cmd == ICLASS_CMD_READCHECK) { // 0x88
|
} else if (cmd == ICLASS_CMD_READCHECK) { // 0x88
|
||||||
// Read e-purse KD (88 02) KC (18 02)
|
// Read e-purse KD (88 02) KC (18 02)
|
||||||
modulated_response = resp_cc;
|
if (chip_state == SELECTED) {
|
||||||
modulated_response_size = resp_cc_len; //order = 4;
|
if ( ICLASS_DEBIT(cmd) ){
|
||||||
trace_data = card_challenge_data;
|
cipher_state = &cipher_state_KD[current_page];
|
||||||
trace_data_size = sizeof(card_challenge_data);
|
diversified_key = diversified_kd;
|
||||||
LED_B_ON();
|
} else {
|
||||||
goto send;
|
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
|
} else if (cmd == ICLASS_CMD_CHECK) { // 0x05
|
||||||
// Reader random and reader MAC!!!
|
// Reader random and reader MAC!!!
|
||||||
if (simulationMode == ICLASS_SIM_MODE_FULL) {
|
if (simulationMode == ICLASS_SIM_MODE_FULL) {
|
||||||
// NR, from reader, is in receivedCmd +1
|
// 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 = data_generic_trace;
|
||||||
trace_data_size = 4;
|
trace_data_size = 4;
|
||||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
CodeIso15693AsTag(trace_data, trace_data_size);
|
||||||
memcpy(data_response, ToSend, ToSendMax);
|
memcpy(data_response, ToSend, ToSendMax);
|
||||||
modulated_response = data_response;
|
modulated_response = data_response;
|
||||||
modulated_response_size = ToSendMax;
|
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]);
|
Dbprintf("[+] CSN: %02x .... %02x OK", csn[0], csn[7]);
|
||||||
}
|
}
|
||||||
if (reader_mac_buf != NULL) {
|
if (reader_mac_buf != NULL) {
|
||||||
|
// save NR and MAC for sim 2,4
|
||||||
memcpy(reader_mac_buf + 8, receivedCmd + 1, 8);
|
memcpy(reader_mac_buf + 8, receivedCmd + 1, 8);
|
||||||
}
|
}
|
||||||
exitLoop = true;
|
exit_loop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto send;
|
goto send;
|
||||||
|
|
||||||
} else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
|
} else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
|
||||||
|
|
||||||
if (chip_state == SELECTED) {
|
if (chip_state == SELECTED) {
|
||||||
// Reader ends the session
|
// Reader ends the session
|
||||||
modulated_response = resp_sof;
|
modulated_response = resp_sof;
|
||||||
modulated_response_size = resp_sof_Len;
|
modulated_response_size = resp_sof_len;
|
||||||
chip_state = HALTED;
|
chip_state = HALTED;
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
|
} else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
|
||||||
|
|
||||||
if (chip_state == SELECTED) {
|
if (chip_state == SELECTED) {
|
||||||
|
@ -656,31 +669,86 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
modulated_response_size = ToSendMax;
|
modulated_response_size = ToSendMax;
|
||||||
goto send;
|
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.
|
} else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_UPDATE && (len == 12 || len == 14)) {
|
||||||
// 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|
|
|
||||||
|
|
||||||
//Take the data...
|
// We're expected to respond with the data+crc, exactly what's already in the receivedCmd
|
||||||
memcpy(data_generic_trace, receivedCmd + 2, 8);
|
// receivedCmd is now UPDATE 1b | ADDRESS 1b | DATA 8b | Signature 4b or CRC 2b
|
||||||
AddCrc(data_generic_trace, 8);
|
if (chip_state == SELECTED) {
|
||||||
trace_data = data_generic_trace;
|
|
||||||
trace_data_size = 10;
|
|
||||||
CodeIClassTagAnswer(trace_data, trace_data_size);
|
|
||||||
|
|
||||||
memcpy(data_response, ToSend, ToSendMax);
|
if (block == 2) { // update e-purse
|
||||||
modulated_response = data_response;
|
memcpy(card_challenge_data, receivedCmd + 2, 8);
|
||||||
modulated_response_size = ToSendMax;
|
CodeIso15693AsTag(card_challenge_data, sizeof(card_challenge_data));
|
||||||
// response_delay = 4600 * 1.5; // tPROG 4-15ms
|
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;
|
goto send;
|
||||||
// } else if(receivedCmd[0] == ICLASS_CMD_PAGESEL) { // 0x84
|
|
||||||
//Pagesel
|
} 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
|
// Pagesel,
|
||||||
//Chips with a single page will not answer to this command
|
// - enables to select a page in the selected chip memory and return its configuration block
|
||||||
// It appears we're fine ignoring this.
|
// Chips with a single page will not answer to this command
|
||||||
//Otherwise, we should answer 8bytes (block) + 2bytes CRC
|
// 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] == ICLASS_CMD_DETECT) { // 0x0F
|
||||||
} else if (receivedCmd[0] == 0x26 && len == 5) {
|
} else if (receivedCmd[0] == 0x26 && len == 5) {
|
||||||
// standard ISO15693 INVENTORY command. Ignore.
|
// standard ISO15693 INVENTORY command. Ignore.
|
||||||
|
@ -697,7 +765,7 @@ send:
|
||||||
if (modulated_response_size > 0) {
|
if (modulated_response_size > 0) {
|
||||||
uint32_t response_time = reader_eof_time + DELAY_ICLASS_VCD_TO_VICC_SIM;
|
uint32_t response_time = reader_eof_time + DELAY_ICLASS_VCD_TO_VICC_SIM;
|
||||||
TransmitTo15693Reader(modulated_response, modulated_response_size, &response_time, 0, false);
|
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
|
/// 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) {
|
static void ReaderTransmitIClass(uint8_t *frame, int len, uint32_t *start_time) {
|
||||||
|
|
||||||
CodeIso15693AsReader(frame, len);
|
CodeIso15693AsReader(frame, len);
|
||||||
|
@ -800,7 +820,7 @@ static bool selectIclassTag(uint8_t *card_data, bool use_credit_key, uint32_t *e
|
||||||
// bit 7: parity.
|
// bit 7: parity.
|
||||||
|
|
||||||
if (use_credit_key)
|
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};
|
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)
|
// card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
|
||||||
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
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
|
// expect a 8-byte response here
|
||||||
len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time);
|
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
|
// Reader iClass Anticollission
|
||||||
// turn off afterwards
|
// 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 last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
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));
|
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 flag_readonce = flags & 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 = flags & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key
|
||||||
bool use_credit_key = arg0 & 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
|
||||||
bool flagReadAIA = arg0 & 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();
|
Iso15693InitReader();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & FLAG_ICLASS_READER_CLEARTRACE) {
|
if ((flags & FLAG_ICLASS_READER_CLEARTRACE) == FLAG_ICLASS_READER_CLEARTRACE) {
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
StartCountSspClk();
|
StartCountSspClk();
|
||||||
|
@ -890,7 +909,6 @@ void ReaderIClass(uint8_t arg0) {
|
||||||
|
|
||||||
uint32_t start_time = 0;
|
uint32_t start_time = 0;
|
||||||
uint32_t eof_time = 0;
|
uint32_t eof_time = 0;
|
||||||
|
|
||||||
int read_status = selectIclassTag(card_data, use_credit_key, &eof_time);
|
int read_status = selectIclassTag(card_data, use_credit_key, &eof_time);
|
||||||
if (read_status == 0) {
|
if (read_status == 0) {
|
||||||
reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
|
reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
|
||||||
|
@ -898,18 +916,18 @@ void ReaderIClass(uint8_t arg0) {
|
||||||
return;
|
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
|
//Read block 5, AIA
|
||||||
if (flagReadAIA) {
|
if (flag_read_aia) {
|
||||||
//Read App Issuer Area block CRC(0x05) => 0xde 0x64
|
//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)) {
|
if (sendCmdGetResponseWithRetries(read_aa, sizeof(read_aa), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) {
|
||||||
result_status |= FLAG_ICLASS_READER_AIA;
|
result_status |= FLAG_ICLASS_AIA;
|
||||||
memcpy(card_data + (8 * 5), resp, 8);
|
memcpy(card_data + (8 * 5), resp, 8);
|
||||||
} else {
|
} 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)
|
// only useful if looping in arm (not try_once && not abort_after_read)
|
||||||
if (memcmp(last_csn, card_data, 8) != 0) {
|
if (memcmp(last_csn, card_data, 8) != 0) {
|
||||||
|
|
||||||
if (send) {
|
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
||||||
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
if (flag_readonce) {
|
||||||
if (abort_after_read) {
|
LED_B_OFF();
|
||||||
LED_B_OFF();
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
LED_B_OFF();
|
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};
|
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
|
// check response. e-purse update swaps first and second half
|
||||||
if (memcmp(data+4, resp, 4) || memcmp(data, resp+4, 4)) {
|
if (memcmp(data+4, resp, 4) || memcmp(data, resp+4, 4)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (blockNo == 3 || blockNo == 4) {
|
} else if (blockno == 3 || blockno == 4) {
|
||||||
// check response. Key updates always return 0xffffffffffffffff
|
// check response. Key updates always return 0xffffffffffffffff
|
||||||
if (memcmp(all_ff, resp, 8)) {
|
if (memcmp(all_ff, resp, 8)) {
|
||||||
return false;
|
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) {
|
static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) {
|
||||||
PacketResponseNG resp;
|
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)
|
if (use_credit_key)
|
||||||
flags |= FLAG_ICLASS_READER_CEDITKEY;
|
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 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;
|
if (!have_debit_key && have_credit_key) use_credit_key = true;
|
||||||
|
|
||||||
uint32_t flags = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC |
|
uint32_t flags = (
|
||||||
FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE |
|
FLAG_ICLASS_READER_INIT |
|
||||||
FLAG_ICLASS_READER_ONE_TRY;
|
FLAG_ICLASS_READER_CLEARTRACE |
|
||||||
|
FLAG_ICLASS_READER_ONLY_ONCE
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//get config and first 3 blocks
|
//get config and first 3 blocks
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -1305,7 +1308,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
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);
|
memcpy(tag_data, data, 8 * 3);
|
||||||
blockno += 2; // 2 to force re-read of block 2 later. (seems to respond differently..)
|
blockno += 2; // 2 to force re-read of block 2 later. (seems to respond differently..)
|
||||||
numblks = data[8];
|
numblks = data[8];
|
||||||
|
@ -2927,9 +2930,12 @@ int CmdHFiClass(const char *Cmd) {
|
||||||
int readIclass(bool loop, bool verbose) {
|
int readIclass(bool loop, bool verbose) {
|
||||||
bool tagFound = false;
|
bool tagFound = false;
|
||||||
|
|
||||||
uint32_t flags = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_AIA |
|
uint32_t flags = (
|
||||||
FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE |
|
FLAG_ICLASS_READER_INIT |
|
||||||
FLAG_ICLASS_READER_ONE_TRY;
|
FLAG_ICLASS_READER_CLEARTRACE |
|
||||||
|
FLAG_ICLASS_READER_ONLY_ONCE |
|
||||||
|
FLAG_ICLASS_READER_AIA
|
||||||
|
);
|
||||||
|
|
||||||
uint32_t res = PM3_ETIMEOUT;
|
uint32_t res = PM3_ETIMEOUT;
|
||||||
// loop in client not device - else on windows have a communication error
|
// 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, "--- " _CYAN_("Tag Information") " --------------------------");
|
||||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
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)));
|
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " (uid)", sprint_hex(hdr->csn, sizeof(hdr->csn)));
|
||||||
tagFound = true;
|
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)));
|
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, "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, " 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)));
|
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(INFO, "--------- " _CYAN_("AIA") " ---------");
|
||||||
PrintAndLogEx(SUCCESS, " AIA: %s (Application Issuer area)", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
|
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);
|
printIclassDumpInfo(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if CSN ends with FF12E0, it's inside HID CSN range.
|
// if CSN ends with FF12E0, it's inside HID CSN range.
|
||||||
bool isHidRange = (memcmp((uint8_t *)(data + 5), "\xFF\x12\xE0", 3) == 0);
|
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 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);
|
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_ATQA 0x800
|
||||||
#define FLAG_FORCED_SAK 0x1000
|
#define FLAG_FORCED_SAK 0x1000
|
||||||
|
|
||||||
//Iclass reader flags
|
// iCLASS reader flags
|
||||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
#define FLAG_ICLASS_READER_INIT 0x01
|
||||||
#define FLAG_ICLASS_READER_CC 0x02
|
#define FLAG_ICLASS_READER_CLEARTRACE 0x02
|
||||||
#define FLAG_ICLASS_READER_CSN 0x04
|
#define FLAG_ICLASS_READER_ONLY_ONCE 0x04
|
||||||
#define FLAG_ICLASS_READER_CONF 0x08
|
#define FLAG_ICLASS_READER_CEDITKEY 0x08
|
||||||
#define FLAG_ICLASS_READER_AIA 0x10
|
#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
|
// iCLASS simulation modes
|
||||||
#define ICLASS_SIM_MODE_CSN 0
|
#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_CMD_ACT 0xE
|
||||||
|
|
||||||
#define ICLASS_CREDIT(x) (((x) & 0x10) == 0x10)
|
#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
|
#define ISO14443A_CMD_REQA 0x26
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue