mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-10 09:32:41 +08:00
fix auth and
This commit is contained in:
parent
3354f0d9d3
commit
a1529b44ca
8 changed files with 367 additions and 257 deletions
|
@ -960,6 +960,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type
|
||||
SniffHitag2();
|
||||
// SniffHitag2(packet->oldarg[0]);
|
||||
reply_ng(CMD_LF_HITAG_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content
|
||||
|
@ -1027,6 +1028,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SniffIso15693(payload->jam_search_len, payload->jam_search_string);
|
||||
reply_ng(CMD_HF_ISO15693_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_COMMAND: {
|
||||
|
@ -1089,6 +1091,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
}
|
||||
case CMD_HF_ISO14443B_SNIFF: {
|
||||
SniffIso14443b();
|
||||
reply_ng(CMD_HF_ISO14443B_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443B_SIMULATE: {
|
||||
|
@ -1113,6 +1116,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
}
|
||||
case CMD_HF_FELICA_SNIFF: {
|
||||
felica_sniff(packet->oldarg[0], packet->oldarg[1]);
|
||||
reply_ng(CMD_HF_FELICA_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_FELICALITE_DUMP: {
|
||||
|
@ -1124,6 +1128,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
#ifdef WITH_ISO14443a
|
||||
case CMD_HF_ISO14443A_SNIFF: {
|
||||
SniffIso14443a(packet->data.asBytes[0]);
|
||||
reply_ng(CMD_HF_ISO14443A_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_READER: {
|
||||
|
@ -1380,6 +1385,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SniffIClass(payload->jam_search_len, payload->jam_search_string);
|
||||
reply_ng(CMD_HF_ICLASS_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_SIMULATE: {
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
// The length of a received command will in most cases be no more than 18 bytes.
|
||||
// we expect max 34 bytes as tag answer (response to READ4)
|
||||
#ifndef ICLASS_BUFFER_SIZE
|
||||
#define ICLASS_BUFFER_SIZE 34
|
||||
#define ICLASS_BUFFER_SIZE 34 + 2
|
||||
#endif
|
||||
|
||||
// iCLASS has a slightly different timing compared to ISO15693. According to the picopass data sheet the tag response is expected 330us after
|
||||
|
@ -481,7 +481,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
uint8_t cmd, options, block;
|
||||
int len = 0;
|
||||
|
||||
bool exit_loop = 0;
|
||||
bool exit_loop = false;
|
||||
while (exit_loop == false) {
|
||||
WDT_HIT();
|
||||
|
||||
|
@ -863,12 +863,11 @@ static bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t
|
|||
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
|
||||
static uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static uint8_t read_conf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22 };
|
||||
static uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
||||
uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
|
||||
// Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) will be used
|
||||
// bit 7: parity.
|
||||
|
||||
if (use_credit_key)
|
||||
read_check_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
|
||||
|
||||
|
@ -878,7 +877,6 @@ static bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t
|
|||
int len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time);
|
||||
if (len < 0)
|
||||
return false;
|
||||
|
||||
|
||||
// send Identify
|
||||
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
@ -936,7 +934,7 @@ void ReaderIClass(uint8_t flags) {
|
|||
|
||||
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];
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
memset(resp, 0xFF, sizeof(resp));
|
||||
|
||||
// bool flag_readonce = flags & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully
|
||||
|
@ -1162,21 +1160,9 @@ void iClass_Authentication(uint8_t *bytes) {
|
|||
|
||||
bool iclass_auth(uint8_t *bytes, bool send_reply, uint8_t *dataout) {
|
||||
|
||||
struct p {
|
||||
uint8_t key[8];
|
||||
bool use_raw;
|
||||
bool use_elite;
|
||||
bool use_credit_key;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)bytes;
|
||||
|
||||
// device response message
|
||||
struct {
|
||||
bool isOK;
|
||||
uint8_t div_key[8];
|
||||
uint8_t mac[4];
|
||||
} PACKED packet;
|
||||
|
||||
iclass_auth_req_t *payload = (iclass_auth_req_t *)bytes;
|
||||
iclass_auth_resp_t packet;
|
||||
|
||||
Iso15693InitReader();
|
||||
|
||||
uint8_t card_data[3 * 8] = {0xFF};
|
||||
|
@ -1208,7 +1194,7 @@ bool iclass_auth(uint8_t *bytes, bool send_reply, uint8_t *dataout) {
|
|||
check[7] = packet.mac[2];
|
||||
check[8] = packet.mac[3];
|
||||
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
packet.isOK = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 3, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time);
|
||||
|
||||
if (send_reply)
|
||||
|
@ -1236,12 +1222,12 @@ typedef struct iclass_premac {
|
|||
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
||||
|
||||
uint8_t i = 0, isOK = 0;
|
||||
uint8_t lastChunk = ((arg0 >> 8) & 0xFF);
|
||||
// uint8_t lastChunk = ((arg0 >> 8) & 0xFF);
|
||||
bool use_credit_key = ((arg0 >> 16) & 0xFF);
|
||||
uint8_t keyCount = arg1 & 0xFF;
|
||||
|
||||
uint8_t check[9] = { ICLASS_CMD_CHECK };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
||||
|
||||
if (use_credit_key)
|
||||
|
@ -1260,8 +1246,8 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
|||
|
||||
Iso15693InitReader();
|
||||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
uint32_t start_time = 0, eof_time = 0;
|
||||
|
||||
if (select_iclass_tag(card_data, use_credit_key, &eof_time) == false)
|
||||
goto out;
|
||||
|
||||
|
@ -1305,15 +1291,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
|||
out:
|
||||
// send keyindex.
|
||||
reply_mix(CMD_HF_ICLASS_CHKKEYS, isOK, i, 0, 0, 0);
|
||||
|
||||
if (isOK >= 1 || lastChunk) {
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
switch_off();
|
||||
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
}
|
||||
|
||||
// Tries to read block.
|
||||
|
@ -1338,8 +1316,8 @@ void iClass_ReadBlk(uint8_t blockno) {
|
|||
|
||||
LED_A_ON();
|
||||
result.isOK = iclass_readblock(blockno, result.blockdata);
|
||||
switch_off();
|
||||
reply_ng(CMD_HF_ICLASS_READBL, PM3_SUCCESS, (uint8_t *)&result, sizeof(result));
|
||||
switch_off();
|
||||
}
|
||||
|
||||
// Dump command seems to dump a block related portion of card memory.
|
||||
|
@ -1372,11 +1350,6 @@ void iClass_Dump(uint8_t start_blockno, uint8_t numblks) {
|
|||
|
||||
switch_off();
|
||||
|
||||
// return pointer to dump memory in arg3
|
||||
// iceman: why not return | dataout - getbigbuf ? Should give exact location.
|
||||
// Dbprintf("ICE:: dataout, %u max trace %u, bb start %u, data-bb %u ", dataout, BigBuf_max_traceLen(), BigBuf_get_addr(), dataout - BigBuf_get_addr() );
|
||||
// Dbprintf("ICE:: bb size %u, malloced %u (255*8)", BigBuf_get_size(), BigBuf_get_size() - (dataout - BigBuf_get_addr()) );
|
||||
// reply_mix(CMD_ACK, isOK, blkcnt, BigBuf_max_traceLen(), 0, 0);
|
||||
struct p {
|
||||
bool isOK;
|
||||
uint8_t block_cnt;
|
||||
|
@ -1384,7 +1357,7 @@ void iClass_Dump(uint8_t start_blockno, uint8_t numblks) {
|
|||
} PACKED payload;
|
||||
payload.isOK = isOK;
|
||||
payload.block_cnt = blkcnt;
|
||||
payload.bb_offset = BigBuf_max_traceLen();
|
||||
payload.bb_offset = dataout - BigBuf_get_addr();
|
||||
reply_ng(CMD_HF_ICLASS_DUMP, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
||||
BigBuf_free();
|
||||
}
|
||||
|
|
|
@ -91,7 +91,6 @@
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// buffers
|
||||
//#define ISO15693_DMA_BUFFER_SIZE 256 // must be a power of 2
|
||||
#define ISO15693_MAX_RESPONSE_LENGTH 36 // allows read single block with the maximum block size of 256bits. Read multiple blocks not supported yet
|
||||
#define ISO15693_MAX_COMMAND_LENGTH 45 // allows write single block with the maximum block size of 256bits. Write multiple blocks not supported yet
|
||||
|
||||
|
@ -106,7 +105,6 @@
|
|||
#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
|
||||
static void BuildIdentifyRequest(uint8_t *cmd);
|
||||
static void BuildInventoryResponse(uint8_t *uid);
|
||||
|
||||
// ---------------------------
|
||||
// Signal Processing
|
||||
|
@ -255,12 +253,13 @@ void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) {
|
|||
*start_time = (GetCountSspClk() + 16) & 0xfffffff0; // next possible time
|
||||
}
|
||||
|
||||
while (GetCountSspClk() < *start_time)
|
||||
/* wait */ ;
|
||||
// wait
|
||||
while (GetCountSspClk() < *start_time) ;
|
||||
|
||||
LED_B_ON();
|
||||
for (int c = 0; c < len; c++) {
|
||||
volatile uint8_t data = cmd[c];
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
uint16_t send_word = (data & 0x80) ? 0xffff : 0x0000;
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ;
|
||||
|
@ -294,8 +293,8 @@ void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time,
|
|||
}
|
||||
}
|
||||
|
||||
while (GetCountSspClk() < (modulation_start_time & 0xfffffff8))
|
||||
/* wait */ ;
|
||||
// wait
|
||||
while (GetCountSspClk() < (modulation_start_time & 0xfffffff8)) ;
|
||||
|
||||
uint8_t shift_delay = modulation_start_time & 0x00000007;
|
||||
|
||||
|
@ -304,9 +303,12 @@ void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time,
|
|||
LED_C_ON();
|
||||
uint8_t bits_to_shift = 0x00;
|
||||
uint8_t bits_to_send = 0x00;
|
||||
|
||||
for (size_t c = 0; c < len; c++) {
|
||||
for (int i = (c == 0 ? 4 : 7); i >= 0; i--) {
|
||||
|
||||
uint8_t cmd_bits = ((cmd[c] >> i) & 0x01) ? 0xff : 0x00;
|
||||
|
||||
for (int j = 0; j < (slow ? 4 : 1); ) {
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
bits_to_send = bits_to_shift << (8 - shift_delay) | cmd_bits >> shift_delay;
|
||||
|
@ -380,7 +382,7 @@ typedef struct DecodeTag {
|
|||
//-----------------------------------------------------------------------------
|
||||
static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *DecodeTag) {
|
||||
switch (DecodeTag->state) {
|
||||
case STATE_TAG_SOF_LOW:
|
||||
case STATE_TAG_SOF_LOW: {
|
||||
// waiting for a rising edge
|
||||
if (amplitude > NOISE_THRESHOLD + DecodeTag->previous_amplitude) {
|
||||
if (DecodeTag->posCount > 10) {
|
||||
|
@ -395,8 +397,8 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *De
|
|||
DecodeTag->previous_amplitude = amplitude;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_TAG_SOF_RISING_EDGE:
|
||||
}
|
||||
case STATE_TAG_SOF_RISING_EDGE: {
|
||||
if (amplitude > DecodeTag->threshold_sof + DecodeTag->previous_amplitude) { // edge still rising
|
||||
if (amplitude > DecodeTag->threshold_sof + DecodeTag->threshold_sof) { // steeper edge, take this as time reference
|
||||
DecodeTag->posCount = 1;
|
||||
|
@ -411,8 +413,8 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *De
|
|||
// DecodeTag->posCount = 2;
|
||||
DecodeTag->state = STATE_TAG_SOF_HIGH;
|
||||
break;
|
||||
|
||||
case STATE_TAG_SOF_HIGH:
|
||||
}
|
||||
case STATE_TAG_SOF_HIGH: {
|
||||
// waiting for 10 times high. Take average over the last 8
|
||||
if (amplitude > DecodeTag->threshold_sof) {
|
||||
DecodeTag->posCount++;
|
||||
|
@ -429,8 +431,8 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *De
|
|||
DecodeTag->state = STATE_TAG_SOF_LOW;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_TAG_SOF_HIGH_END:
|
||||
}
|
||||
case STATE_TAG_SOF_HIGH_END: {
|
||||
// check for falling edge
|
||||
if (DecodeTag->posCount == 13 && amplitude < DecodeTag->threshold_sof) {
|
||||
DecodeTag->lastBit = SOF_PART1; // detected 1st part of SOF (12 samples low and 12 samples high)
|
||||
|
@ -458,8 +460,8 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *De
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_TAG_RECEIVING_DATA:
|
||||
}
|
||||
case STATE_TAG_RECEIVING_DATA: {
|
||||
// FpgaDisableTracing(); // DEBUGGING
|
||||
// Dbprintf("amplitude = %d, threshold_sof = %d, threshold_half/4 = %d, previous_amplitude = %d",
|
||||
// amplitude,
|
||||
|
@ -547,8 +549,8 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *De
|
|||
}
|
||||
DecodeTag->posCount++;
|
||||
break;
|
||||
|
||||
case STATE_TAG_EOF:
|
||||
}
|
||||
case STATE_TAG_EOF: {
|
||||
if (DecodeTag->posCount == 1) {
|
||||
DecodeTag->sum1 = 0;
|
||||
DecodeTag->sum2 = 0;
|
||||
|
@ -571,8 +573,8 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *De
|
|||
}
|
||||
DecodeTag->posCount++;
|
||||
break;
|
||||
|
||||
case STATE_TAG_EOF_TAIL:
|
||||
}
|
||||
case STATE_TAG_EOF_TAIL: {
|
||||
if (DecodeTag->posCount == 1) {
|
||||
DecodeTag->sum1 = 0;
|
||||
DecodeTag->sum2 = 0;
|
||||
|
@ -595,6 +597,7 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *De
|
|||
}
|
||||
DecodeTag->posCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -690,20 +693,22 @@ int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeo
|
|||
|
||||
FpgaDisableSscDma();
|
||||
|
||||
|
||||
uint32_t sof_time = *eof_time
|
||||
- (DecodeTag.len * 8 * 8 * 16) // time for byte transfers
|
||||
- (32 * 16) // time for SOF transfer
|
||||
- (DecodeTag.lastBit != SOF_PART2 ? (32 * 16) : 0); // time for EOF transfer
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("samples = %d, ret = %d, Decoder: state = %d, lastBit = %d, len = %d, bitCount = %d, posCount = %d",
|
||||
Dbprintf("samples = %d, ret = %d, Decoder: state = %d, lastBit = %d, len = %d, bitCount = %d, posCount = %d, maxlen = %u",
|
||||
samples,
|
||||
ret,
|
||||
DecodeTag.state,
|
||||
DecodeTag.lastBit,
|
||||
DecodeTag.len,
|
||||
DecodeTag.bitCount,
|
||||
DecodeTag.posCount
|
||||
DecodeTag.posCount,
|
||||
DecodeTag.max_len
|
||||
);
|
||||
Dbprintf("timing: sof_time = %d, eof_time = %d", (sof_time * 4), (*eof_time * 4));
|
||||
}
|
||||
|
@ -890,11 +895,11 @@ static RAMFUNC int Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeR
|
|||
case STATE_READER_RECEIVE_DATA_1_OUT_OF_4:
|
||||
DecodeReader->posCount++;
|
||||
if (DecodeReader->posCount == 1) {
|
||||
DecodeReader->sum1 = bit?1:0;
|
||||
DecodeReader->sum1 = bit ? 1 : 0;
|
||||
} else if (DecodeReader->posCount <= 4) {
|
||||
if (bit) DecodeReader->sum1++;
|
||||
} else if (DecodeReader->posCount == 5) {
|
||||
DecodeReader->sum2 = bit?1:0;
|
||||
DecodeReader->sum2 = bit ? 1 : 0;
|
||||
} else {
|
||||
if (bit) DecodeReader->sum2++;
|
||||
}
|
||||
|
@ -935,11 +940,11 @@ static RAMFUNC int Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeR
|
|||
case STATE_READER_RECEIVE_DATA_1_OUT_OF_256:
|
||||
DecodeReader->posCount++;
|
||||
if (DecodeReader->posCount == 1) {
|
||||
DecodeReader->sum1 = bit?1:0;
|
||||
DecodeReader->sum1 = bit ? 1 : 0;
|
||||
} else if (DecodeReader->posCount <= 4) {
|
||||
if (bit) DecodeReader->sum1++;
|
||||
} else if (DecodeReader->posCount == 5) {
|
||||
DecodeReader->sum2 = bit?1:0;
|
||||
DecodeReader->sum2 = bit ? 1 : 0;
|
||||
} else if (bit) {
|
||||
DecodeReader->sum2++;
|
||||
}
|
||||
|
@ -976,20 +981,20 @@ static RAMFUNC int Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeR
|
|||
case STATE_READER_RECEIVE_JAMMING:
|
||||
DecodeReader->posCount++;
|
||||
if (DecodeReader->Coding == CODING_1_OUT_OF_4) {
|
||||
if (DecodeReader->posCount == 7*16) { // 7 bits jammed
|
||||
if (DecodeReader->posCount == 7 * 16) { // 7 bits jammed
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); // stop jamming
|
||||
// FpgaDisableTracing();
|
||||
LED_D_OFF();
|
||||
} else if (DecodeReader->posCount == 8*16) {
|
||||
} else if (DecodeReader->posCount == 8 * 16) {
|
||||
DecodeReader->posCount = 0;
|
||||
DecodeReader->output[DecodeReader->byteCount++] = 0x00;
|
||||
DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_4;
|
||||
}
|
||||
} else {
|
||||
if (DecodeReader->posCount == 7*256) { // 7 bits jammend
|
||||
if (DecodeReader->posCount == 7 * 256) { // 7 bits jammend
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); // stop jamming
|
||||
LED_D_OFF();
|
||||
} else if (DecodeReader->posCount == 8*256) {
|
||||
} else if (DecodeReader->posCount == 8 * 256) {
|
||||
DecodeReader->posCount = 0;
|
||||
DecodeReader->output[DecodeReader->byteCount++] = 0x00;
|
||||
DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_256;
|
||||
|
@ -1083,8 +1088,11 @@ int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eo
|
|||
|
||||
FpgaDisableSscDma();
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("samples = %d, gotFrame = %d, Decoder: state = %d, len = %d, bitCount = %d, posCount = %d",
|
||||
samples, gotFrame, DecodeReader.state, DecodeReader.byteCount, DecodeReader.bitCount, DecodeReader.posCount);
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("samples = %d, gotFrame = %d, Decoder: state = %d, len = %d, bitCount = %d, posCount = %d",
|
||||
samples, gotFrame, DecodeReader.state, DecodeReader.byteCount,
|
||||
DecodeReader.bitCount, DecodeReader.posCount);
|
||||
}
|
||||
|
||||
if (DecodeReader.byteCount > 0) {
|
||||
uint32_t sof_time = *eof_time
|
||||
|
@ -1154,11 +1162,11 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
int samples = 0;
|
||||
|
||||
DecodeTag_t DecodeTag = {0};
|
||||
uint8_t response[ISO15693_MAX_RESPONSE_LENGTH];
|
||||
uint8_t response[ISO15693_MAX_RESPONSE_LENGTH] = {0};
|
||||
DecodeTagInit(&DecodeTag, response, sizeof(response));
|
||||
|
||||
DecodeReader_t DecodeReader = {0};
|
||||
uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH];
|
||||
uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH] = {0};
|
||||
DecodeReaderInit(&DecodeReader, cmd, sizeof(cmd), jam_search_len, jam_search_string);
|
||||
|
||||
// Print some debug information about the buffer sizes
|
||||
|
@ -1166,7 +1174,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
Dbprintf("Sniffing buffers initialized:");
|
||||
Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
|
||||
Dbprintf(" Reader -> tag: %i bytes", ISO15693_MAX_COMMAND_LENGTH);
|
||||
Dbprintf(" tag -> Reader: %i bytes", ISO15693_MAX_RESPONSE_LENGTH);
|
||||
Dbprintf(" Tag -> Reader: %i bytes", ISO15693_MAX_RESPONSE_LENGTH);
|
||||
Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
|
@ -1184,9 +1192,9 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
FpgaSetupSscDma((uint8_t*)dma->buf, DMA_BUFFER_SIZE);
|
||||
uint16_t *upTo = dma->buf;
|
||||
|
||||
bool TagIsActive = false;
|
||||
bool ReaderIsActive = false;
|
||||
bool ExpectTagAnswer = false;
|
||||
bool tag_is_active = false;
|
||||
bool reader_is_active = false;
|
||||
bool expect_tag_answer = false;
|
||||
uint32_t dma_start_time = 0;
|
||||
uint16_t max_behindBy = 0;
|
||||
|
||||
|
@ -1225,7 +1233,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
}
|
||||
|
||||
// no need to try decoding reader data if the tag is sending
|
||||
if (TagIsActive == false) {
|
||||
if (tag_is_active == false) {
|
||||
|
||||
if (Handle15693SampleFromReader(sniffdata & 0x02, &DecodeReader)) {
|
||||
|
||||
|
@ -1242,8 +1250,8 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
// And also reset the demod code, which might have been
|
||||
// false-triggered by the commands from the reader.
|
||||
DecodeTagReset(&DecodeTag);
|
||||
ReaderIsActive = false;
|
||||
ExpectTagAnswer = true;
|
||||
reader_is_active = false;
|
||||
expect_tag_answer = true;
|
||||
|
||||
} else if (Handle15693SampleFromReader(sniffdata & 0x01, &DecodeReader)) {
|
||||
|
||||
|
@ -1261,15 +1269,15 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
// And also reset the demod code, which might have been
|
||||
// false-triggered by the commands from the reader.
|
||||
DecodeTagReset(&DecodeTag);
|
||||
ReaderIsActive = false;
|
||||
ExpectTagAnswer = true;
|
||||
reader_is_active = false;
|
||||
expect_tag_answer = true;
|
||||
|
||||
} else {
|
||||
ReaderIsActive = (DecodeReader.state >= STATE_READER_RECEIVE_DATA_1_OUT_OF_4);
|
||||
reader_is_active = (DecodeReader.state >= STATE_READER_RECEIVE_DATA_1_OUT_OF_4);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ReaderIsActive && ExpectTagAnswer) { // no need to try decoding tag data if the reader is currently sending or no answer expected yet
|
||||
if (!reader_is_active && expect_tag_answer) { // no need to try decoding tag data if the reader is currently sending or no answer expected yet
|
||||
if (Handle15693SamplesFromTag(sniffdata >> 2, &DecodeTag)) {
|
||||
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
|
||||
|
@ -1285,19 +1293,18 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
// And ready to receive another response.
|
||||
DecodeTagReset(&DecodeTag);
|
||||
DecodeReaderReset(&DecodeReader);
|
||||
ExpectTagAnswer = false;
|
||||
TagIsActive = false;
|
||||
expect_tag_answer = false;
|
||||
tag_is_active = false;
|
||||
} else {
|
||||
TagIsActive = (DecodeTag.state >= STATE_TAG_RECEIVING_DATA);
|
||||
tag_is_active = (DecodeTag.state >= STATE_TAG_RECEIVING_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FpgaDisableSscDma();
|
||||
switch_off();
|
||||
|
||||
DbpString("Sniff statistics:");
|
||||
Dbprintf(" ExpectTagAnswer: %d, TagIsActive: %d, ReaderIsActive: %d", ExpectTagAnswer, TagIsActive, ReaderIsActive);
|
||||
Dbprintf(" ExpectTagAnswer: %d, TagIsActive: %d, ReaderIsActive: %d", expect_tag_answer, tag_is_active, reader_is_active);
|
||||
Dbprintf(" DecodeTag State: %d", DecodeTag.state);
|
||||
Dbprintf(" DecodeTag byteCnt: %d", DecodeTag.len);
|
||||
Dbprintf(" DecodeTag posCount: %d", DecodeTag.posCount);
|
||||
|
@ -1305,18 +1312,18 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) {
|
|||
Dbprintf(" DecodeReader byteCnt: %d", DecodeReader.byteCount);
|
||||
Dbprintf(" DecodeReader posCount: %d", DecodeReader.posCount);
|
||||
Dbprintf(" Trace length: %d", BigBuf_get_traceLen());
|
||||
Dbprintf(" Max behindBy: %d", max_behindBy);
|
||||
Dbprintf(" Max behindBy: %d", max_behindBy);
|
||||
}
|
||||
|
||||
// Initialize Proxmark3 as ISO15693 reader
|
||||
void Iso15693InitReader(void) {
|
||||
|
||||
|
||||
LEDsoff();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// Start from off (no field generated)
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
SpinDelay(50);
|
||||
SpinDelay(10);
|
||||
|
||||
// switch field on
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER);
|
||||
|
@ -1329,7 +1336,7 @@ void Iso15693InitReader(void) {
|
|||
set_tracing(true);
|
||||
|
||||
// give tags some time to energize
|
||||
SpinDelay(200);
|
||||
SpinDelay(250);
|
||||
|
||||
StartCountSspClk();
|
||||
}
|
||||
|
@ -1354,31 +1361,6 @@ static void BuildIdentifyRequest(uint8_t *cmd) {
|
|||
AddCrc15(cmd, 3);
|
||||
}
|
||||
|
||||
// uid is in transmission order (which is reverse of display order)
|
||||
|
||||
// When SIM: now the VICC>VCD responses when we are simulating a tag
|
||||
static void BuildInventoryResponse(uint8_t *uid) {
|
||||
|
||||
uint8_t cmd[CMD_INV_RESP] = {0};
|
||||
|
||||
cmd[0] = 0; // No error, no protocol format extension
|
||||
cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
|
||||
|
||||
// 64-bit UID
|
||||
cmd[2] = uid[7];
|
||||
cmd[3] = uid[6];
|
||||
cmd[4] = uid[5];
|
||||
cmd[5] = uid[4];
|
||||
cmd[6] = uid[3];
|
||||
cmd[7] = uid[2];
|
||||
cmd[8] = uid[1];
|
||||
cmd[9] = uid[0];
|
||||
|
||||
// CRC
|
||||
AddCrc15(cmd, 10);
|
||||
CodeIso15693AsTag(cmd, CMD_INV_RESP);
|
||||
}
|
||||
|
||||
// Universal Method for sending to and recv bytes from a tag
|
||||
// init ... should we initialize the reader?
|
||||
// speed ... 0 low speed, 1 hi speed
|
||||
|
@ -1403,7 +1385,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
|
|||
|
||||
tosend_t *ts = get_tosend();
|
||||
TransmitTo15693Tag(ts->buf, ts->max, &start_time);
|
||||
uint32_t end_time = start_time + 32 * (8 * ts->max - 4); // substract the 4 padding bits after EOF
|
||||
uint32_t end_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF
|
||||
LogTrace(send, sendlen, (start_time * 4), (end_time * 4), NULL, true);
|
||||
|
||||
int res = 0;
|
||||
|
@ -1573,9 +1555,9 @@ void Iso15693InitTag(void) {
|
|||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// turn on clock
|
||||
StartCountSspClk();
|
||||
}
|
||||
|
||||
|
@ -1583,44 +1565,90 @@ void Iso15693InitTag(void) {
|
|||
// all demodulation performed in arm rather than host. - greg
|
||||
void SimTagIso15693(uint8_t *uid) {
|
||||
|
||||
// free eventually allocated BigBuf memory
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
Iso15693InitTag();
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
|
||||
|
||||
uint8_t buf[ISO15_MAX_FRAME];
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
// Build a suitable reponse to the reader INVENTORY cocmmand
|
||||
// not so obvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below.
|
||||
BuildInventoryResponse(uid);
|
||||
// Build INVENTORY command
|
||||
uint8_t resp_inv[CMD_INV_RESP] = {0};
|
||||
|
||||
resp_inv[0] = 0; // No error, no protocol format extension
|
||||
resp_inv[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
|
||||
|
||||
// 64-bit UID
|
||||
resp_inv[2] = uid[7];
|
||||
resp_inv[3] = uid[6];
|
||||
resp_inv[4] = uid[5];
|
||||
resp_inv[5] = uid[4];
|
||||
resp_inv[6] = uid[3];
|
||||
resp_inv[7] = uid[2];
|
||||
resp_inv[8] = uid[1];
|
||||
resp_inv[9] = uid[0];
|
||||
|
||||
// CRC
|
||||
AddCrc15(resp_inv, 10);
|
||||
CodeIso15693AsTag(resp_inv, CMD_INV_RESP);
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
while (!BUTTON_PRESS()) {
|
||||
enum { NO_FIELD, IDLE, ACTIVATED, SELECTED, HALTED } chip_state = NO_FIELD;
|
||||
|
||||
bool button_pressed = false;
|
||||
int vHf = 0; // in mV
|
||||
|
||||
bool exit_loop = false;
|
||||
while (exit_loop == false) {
|
||||
WDT_HIT();
|
||||
|
||||
// find reader field
|
||||
if (chip_state == NO_FIELD) {
|
||||
|
||||
#if defined RDV4
|
||||
vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
|
||||
#else
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
||||
#endif
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
chip_state = IDLE;
|
||||
LED_A_ON();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Listen to reader
|
||||
uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH];
|
||||
uint32_t eof_time = 0, start_time = 0;
|
||||
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &eof_time);
|
||||
|
||||
if ((cmd_len >= 5) && (cmd[0] & ISO15_REQ_INVENTORY) && (cmd[1] == ISO15_CMD_INVENTORY)) { // TODO: check more flags
|
||||
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
|
||||
start_time = eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
|
||||
TransmitTo15693Reader(ts->buf, ts->max, &start_time, 0, slow);
|
||||
uint32_t reader_eof_time = 0;
|
||||
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &reader_eof_time);
|
||||
if (cmd_len < 0) {
|
||||
Dbprintf("button pressed, exiting");
|
||||
button_pressed = true;
|
||||
exit_loop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf(" %d bytes read from reader:", cmd_len);
|
||||
Dbhexdump(cmd_len, cmd, false);
|
||||
// TODO: check more flags
|
||||
if ((cmd_len >= 5) && (cmd[0] & ISO15_REQ_INVENTORY) && (cmd[1] == ISO15_CMD_INVENTORY)) {
|
||||
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
|
||||
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
|
||||
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
|
||||
LogTrace(resp_inv, CMD_INV_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
|
||||
|
||||
chip_state = SELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch_off();
|
||||
|
||||
if (button_pressed)
|
||||
DbpString("button pressed");
|
||||
}
|
||||
|
||||
// Since there is no standardized way of reading the AFI out of a tag, we will brute force it
|
||||
|
|
|
@ -47,7 +47,7 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
|
|||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
};
|
||||
|
||||
static int usage_hf_iclass_sim(void) {
|
||||
|
@ -379,6 +379,28 @@ static inline uint32_t leadingzeros(uint64_t a) {
|
|||
#endif
|
||||
}
|
||||
|
||||
// iclass card descriptors
|
||||
const char * card_types[] = {
|
||||
"PicoPass 16K / 16", // 000
|
||||
"PicoPass 32K with current book 16K / 16", // 001
|
||||
"Unknown Card Type!", // 010
|
||||
"Unknown Card Type!", // 011
|
||||
"PicoPass 2K", // 100
|
||||
"Unknown Card Type!", // 101
|
||||
"PicoPass 16K / 2", // 110
|
||||
"PicoPass 32K with current book 16K / 2", // 111
|
||||
};
|
||||
|
||||
uint8_t card_app2_limit[] = {
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x1f,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
};
|
||||
|
||||
static uint8_t isset(uint8_t val, uint8_t mask) {
|
||||
return (val & mask);
|
||||
|
@ -434,7 +456,7 @@ static void fuse_config(const picopass_hdr *hdr) {
|
|||
);
|
||||
}
|
||||
|
||||
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) {
|
||||
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) {
|
||||
// mem-bit 5, mem-bit 7, chip-bit 4: defines chip type
|
||||
uint8_t k16 = isset(mem_cfg, 0x80);
|
||||
//uint8_t k2 = isset(mem_cfg, 0x08);
|
||||
|
@ -443,47 +465,54 @@ static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, ui
|
|||
if (isset(chip_cfg, 0x10) && !k16 && !book) {
|
||||
*kb = 2;
|
||||
*app_areas = 2;
|
||||
*max_blk = 31;
|
||||
} else if (isset(chip_cfg, 0x10) && k16 && !book) {
|
||||
*kb = 16;
|
||||
*app_areas = 2;
|
||||
*max_blk = 255; //16kb
|
||||
} else if (notset(chip_cfg, 0x10) && !k16 && !book) {
|
||||
*kb = 16;
|
||||
*app_areas = 16;
|
||||
*max_blk = 255; //16kb
|
||||
} else if (isset(chip_cfg, 0x10) && k16 && book) {
|
||||
*kb = 32;
|
||||
*app_areas = 3;
|
||||
*max_blk = 255; //16kb
|
||||
} else if (notset(chip_cfg, 0x10) && !k16 && book) {
|
||||
*kb = 32;
|
||||
*app_areas = 17;
|
||||
*max_blk = 255; //16kb
|
||||
} else {
|
||||
*kb = 32;
|
||||
*app_areas = 2;
|
||||
*max_blk = 255;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t get_mem_config(const picopass_hdr *hdr) {
|
||||
uint8_t mem = hdr->conf.mem_config;
|
||||
uint8_t chip = hdr->conf.chip_config;
|
||||
// three configuration bits that decides sizes
|
||||
uint8_t type = (chip & 0x10) >> 2;
|
||||
type |= (mem & 0x80) >> 6;
|
||||
type |= (mem & 0x20) >> 5;
|
||||
return type;
|
||||
}
|
||||
|
||||
static void mem_app_config(const picopass_hdr *hdr) {
|
||||
uint8_t mem = hdr->conf.mem_config;
|
||||
uint8_t chip = hdr->conf.chip_config;
|
||||
uint8_t applimit = hdr->conf.app_limit;
|
||||
uint8_t kb = 2;
|
||||
uint8_t app_areas = 2;
|
||||
uint8_t max_blk = 31;
|
||||
|
||||
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
|
||||
getMemConfig(mem, chip, &app_areas, &kb);
|
||||
|
||||
if (applimit < 6) applimit = 26;
|
||||
if (kb == 2 && (applimit > 0x1f)) applimit = 26;
|
||||
// three configuration bits that decides sizes
|
||||
uint8_t type = (chip & 0x10) >> 2;
|
||||
type |= (mem & 0x80) >> 6;
|
||||
type |= (mem & 0x20) >> 5;
|
||||
|
||||
uint8_t app1_limit = hdr->conf.app_limit - 5; // minus header blocks
|
||||
uint8_t app2_limit = card_app2_limit[type];
|
||||
|
||||
PrintAndLogEx(INFO, "------ " _CYAN_("Memory") " ------");
|
||||
PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u bytes), max blocks 0x%02X (%02d)", kb, app_areas, max_blk * 8, mem, mem);
|
||||
PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", applimit - 5 , applimit, applimit);
|
||||
PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", max_blk - applimit, applimit + 1, max_blk, applimit + 1, max_blk);
|
||||
PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u bytes)", kb, app_areas, app2_limit * 8);
|
||||
PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", app1_limit , app1_limit + 5, app1_limit + 5);
|
||||
PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", app2_limit - app1_limit, app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit);
|
||||
|
||||
PrintAndLogEx(INFO, "------ " _CYAN_("KeyAccess") " ------");
|
||||
PrintAndLogEx(INFO, " Kd = Debit key (AA1), Kc = Credit key (AA2)");
|
||||
|
@ -552,7 +581,15 @@ static int CmdHFiClassSniff(const char *Cmd) {
|
|||
payload.jam_search_len = sizeof(update_epurse_sequence);
|
||||
memcpy(payload.jam_search_string, update_epurse_sequence, sizeof(payload.jam_search_string));
|
||||
}
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ICLASS_SNIFF, (uint8_t *)&payload, sizeof(payload));
|
||||
|
||||
WaitForResponse(CMD_HF_ICLASS_SNIFF, &resp);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass list") "` to look at the collected trace");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -956,6 +993,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
}
|
||||
|
||||
if (have_file) {
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)decrypted;
|
||||
|
||||
uint8_t mem = hdr->conf.mem_config;
|
||||
|
@ -963,10 +1001,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
uint8_t applimit = hdr->conf.app_limit;
|
||||
uint8_t kb = 2;
|
||||
uint8_t app_areas = 2;
|
||||
uint8_t max_blk = 31;
|
||||
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
|
||||
|
||||
|
||||
getMemConfig(mem, chip, &app_areas, &kb);
|
||||
|
||||
BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03);
|
||||
|
||||
|
@ -976,7 +1011,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%zu") " vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8);
|
||||
PrintAndLogEx(INFO, "Setting limit to " _GREEN_("%u"), limit * 8);
|
||||
}
|
||||
uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8));
|
||||
|
||||
//uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8));
|
||||
|
||||
for (uint16_t blocknum = 0; blocknum < limit; ++blocknum) {
|
||||
|
||||
|
@ -987,7 +1023,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
continue;
|
||||
|
||||
// Decrypted block 7,8,9 if configured.
|
||||
if (blocknum > 6 && blocknum <= 6 + numblocks4userid && memcmp(enc_data, empty, 8) != 0) {
|
||||
if (blocknum > 6 && blocknum <= 9 && memcmp(enc_data, empty, 8) != 0) {
|
||||
if (use_sc) {
|
||||
Decrypt(enc_data, decrypted + idx);
|
||||
} else {
|
||||
|
@ -996,13 +1032,14 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
//Use the first block (CSN) for filename
|
||||
// use the first block (CSN) for filename
|
||||
char *fptr = calloc(50, sizeof(uint8_t));
|
||||
if (!fptr) {
|
||||
if (fptr == false) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
free(decrypted);
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
strcat(fptr, "hf-iclass-");
|
||||
FillFileNameByUID(fptr, hdr->csn, "-dump-decrypted", sizeof(hdr->csn));
|
||||
|
||||
|
@ -1013,6 +1050,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "Following output skips CSN / block0");
|
||||
printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
// decode block 6
|
||||
if (memcmp(decrypted + (8 * 6), empty, 8) != 0) {
|
||||
if (use_sc) {
|
||||
|
@ -1029,7 +1068,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
mid = bytes_to_num(decrypted + (8 * 7), 4);
|
||||
bot = bytes_to_num(decrypted + (8 * 7) + 4, 4);
|
||||
|
||||
PrintAndLogEx(INFO, "Block 7 binary");
|
||||
PrintAndLogEx(INFO, "Block 7 decoder");
|
||||
|
||||
char hexstr[8 + 1] = {0};
|
||||
hex_to_buffer((uint8_t *)hexstr, decrypted + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true);
|
||||
|
@ -1039,15 +1078,36 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
uint8_t i = 0;
|
||||
while (i < strlen(binstr) && binstr[i++] == '0');
|
||||
|
||||
PrintAndLogEx(SUCCESS, "%s", binstr + i);
|
||||
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), binstr + i);
|
||||
|
||||
PrintAndLogEx(INFO, "Wiegand decode");
|
||||
wiegand_message_t packed = initialize_message_object(top, mid, bot);
|
||||
HIDTryUnpack(&packed, true);
|
||||
PrintAndLogEx(INFO, "-----------------------------------------------------------------");
|
||||
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "No credential found.");
|
||||
}
|
||||
|
||||
// decode block 9
|
||||
if (memcmp(decrypted + (8 * 9), empty, 8) != 0) {
|
||||
|
||||
uint8_t usr_blk_len = GetNumberBlocksForUserId(decrypted + (8 * 6));
|
||||
if (usr_blk_len < 3) {
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Block 9 decoder");
|
||||
uint8_t pinsize = 10;
|
||||
if (use_sc) {
|
||||
pinsize = GetPinSize(decrypted + (8 * 6));
|
||||
}
|
||||
uint64_t pin = bytes_to_num(decrypted + (8 * 9), 5);
|
||||
char tmp[17] = {0};
|
||||
sprintf(tmp, "%."PRIu64, BCD2DEC(pin));
|
||||
PrintAndLogEx(INFO, "PIN........................ " _GREEN_("%.*s"), pinsize, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "-----------------------------------------------------------------");
|
||||
|
||||
free(decrypted);
|
||||
free(fptr);
|
||||
|
@ -1178,7 +1238,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
|
|||
.use_credit_key = use_credit_key
|
||||
};
|
||||
memcpy(payload.key, KEY, 8);
|
||||
|
||||
|
||||
SendCommandNG(CMD_HF_ICLASS_AUTH, (uint8_t*)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
|
@ -1205,7 +1265,9 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
|
|||
if (MAC)
|
||||
memcpy(MAC, packet->mac, sizeof(packet->mac));
|
||||
|
||||
if (verbose) PrintAndLogEx(SUCCESS, "authing with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8));
|
||||
if (verbose)
|
||||
PrintAndLogEx(SUCCESS, "authing with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1214,15 +1276,11 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t c_div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t blockno = 0;
|
||||
uint8_t numblks = 0;
|
||||
uint8_t maxBlk = 31;
|
||||
uint8_t app_areas = 1;
|
||||
uint8_t kb = 2;
|
||||
uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t CreditKEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t keyNbr = 0;
|
||||
uint8_t dataLen = 0;
|
||||
uint8_t app_limit1, app_limit2 = 0;
|
||||
uint8_t fileNameLen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
char tempStr[50] = {0};
|
||||
|
@ -1329,6 +1387,7 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
|
||||
uint8_t readStatus = resp.oldarg[0] & 0xff;
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
picopass_hdr *hdr = (picopass_hdr *)data;
|
||||
|
||||
if (readStatus == 0) {
|
||||
PrintAndLogEx(FAILED, "no tag found");
|
||||
|
@ -1338,11 +1397,14 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
|
||||
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];
|
||||
getMemConfig(data[13], data[12], &maxBlk, &app_areas, &kb);
|
||||
// large memory - not able to dump pages currently
|
||||
if (numblks > maxBlk) numblks = maxBlk;
|
||||
|
||||
uint8_t type = get_mem_config(hdr);
|
||||
app_limit1 = hdr->conf.app_limit;
|
||||
app_limit2 = card_app2_limit[type];
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "failed to read block 0,1,2");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// authenticate debit key and get div_key - later store in dump block 3
|
||||
|
@ -1356,8 +1418,8 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
uint8_t start_blockno;
|
||||
uint8_t numblks;
|
||||
} PACKED payload;
|
||||
payload.start_blockno = blockno;
|
||||
payload.numblks = numblks - blockno + 1;
|
||||
payload.start_blockno = 5;
|
||||
payload.numblks = app_limit1 - 5;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
|
||||
|
@ -1397,20 +1459,24 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint16_t offset = (5 * 8);
|
||||
uint32_t startindex = packet->bb_offset;
|
||||
|
||||
if (blocks_read * 8 > sizeof(tag_data) - (blockno * 8)) {
|
||||
if (blocks_read * 8 > sizeof(tag_data) - offset) {
|
||||
PrintAndLogEx(FAILED, "data exceeded buffer size!");
|
||||
blocks_read = (sizeof(tag_data) / 8) - blockno;
|
||||
blocks_read = (sizeof(tag_data) / 8) - 5;
|
||||
}
|
||||
|
||||
// response ok - now get bigbuf content of the dump
|
||||
if (!GetFromDevice(BIG_BUF, tag_data + (blockno * 8), blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
||||
if (!GetFromDevice(BIG_BUF, tag_data + offset, blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "BB start index :: %u", startindex);
|
||||
PrintAndLogEx(INFO, "BB :: %s", sprint_hex(tag_data + (5*8), 32));
|
||||
|
||||
size_t gotBytes = blocks_read * 8 + blockno * 8;
|
||||
offset += (blocks_read * 8);
|
||||
|
||||
// try AA2 Kc, Credit
|
||||
if (have_credit_key) {
|
||||
|
@ -1424,46 +1490,44 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// do we still need to read more block? (aa2 enabled?)
|
||||
if (maxBlk > blockno + numblks + 1) {
|
||||
payload.start_blockno = app_limit1;
|
||||
payload.numblks = app_limit2 - app_limit1 - 5;
|
||||
|
||||
payload.start_blockno = blockno + blocks_read;
|
||||
payload.numblks = maxBlk - (blockno + blocks_read);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000)) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout 2");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "failed to communicate with card");
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
packet = (struct p_resp *)resp.data.asBytes;
|
||||
if (packet->isOK == false) {
|
||||
PrintAndLogEx(WARNING, "read block failed using credit key");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
blocks_read = packet->block_cnt;
|
||||
startindex = packet->bb_offset;
|
||||
|
||||
if (blocks_read * 8 > sizeof(tag_data) - gotBytes) {
|
||||
PrintAndLogEx(FAILED, "data exceeded buffer size!");
|
||||
blocks_read = (sizeof(tag_data) - gotBytes) / 8;
|
||||
}
|
||||
// get dumped data from bigbuf
|
||||
if (!GetFromDevice(BIG_BUF, tag_data + gotBytes, blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
gotBytes += blocks_read * 8;
|
||||
if (!WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000)) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout 2");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "failed to communicate with card");
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
packet = (struct p_resp *)resp.data.asBytes;
|
||||
if (packet->isOK == false) {
|
||||
PrintAndLogEx(WARNING, "read block failed using credit key");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
//
|
||||
blocks_read = packet->block_cnt;
|
||||
startindex = packet->bb_offset;
|
||||
|
||||
if (blocks_read * 8 > sizeof(tag_data) - offset) {
|
||||
PrintAndLogEx(FAILED, "data exceeded buffer size!");
|
||||
blocks_read = (sizeof(tag_data) - offset) / 8;
|
||||
}
|
||||
|
||||
// get dumped data from bigbuf
|
||||
if (!GetFromDevice(BIG_BUF, tag_data + offset, blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
offset += blocks_read * 8;
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
@ -1480,7 +1544,7 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "------+--+-------------------------+----------");
|
||||
PrintAndLogEx(INFO, " CSN |00| " _GREEN_("%s") "|", sprint_hex(tag_data, 8));
|
||||
printIclassDumpContents(tag_data, 1, (gotBytes / 8), gotBytes);
|
||||
printIclassDumpContents(tag_data, 1, (offset / 8), offset);
|
||||
|
||||
if (filename[0] == 0) {
|
||||
//Use the first block (CSN) for filename
|
||||
|
@ -1489,10 +1553,10 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
}
|
||||
|
||||
// save the dump to .bin file
|
||||
PrintAndLogEx(SUCCESS, "saving dump file - %zu blocks read", gotBytes / 8);
|
||||
saveFile(filename, ".bin", tag_data, gotBytes);
|
||||
saveFileEML(filename, tag_data, gotBytes, 8);
|
||||
saveFileJSON(filename, jsfIclass, tag_data, gotBytes, NULL);
|
||||
PrintAndLogEx(SUCCESS, "saving dump file - %zu blocks read", offset / 8);
|
||||
saveFile(filename, ".bin", tag_data, offset);
|
||||
saveFileEML(filename, tag_data, offset, 8);
|
||||
saveFileJSON(filename, jsfIclass, tag_data, offset, NULL);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1825,25 +1889,22 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
|||
|
||||
static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
|
||||
|
||||
// return data.
|
||||
struct p {
|
||||
bool isOK;
|
||||
uint8_t blockdata[8];
|
||||
} PACKED;
|
||||
struct p *result = NULL;
|
||||
|
||||
// block 0,1 should always be able to read, and block 5 on some cards.
|
||||
if (auth || blockno >= 2) {
|
||||
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
if (select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose) == false) {
|
||||
if (verbose) PrintAndLogEx(FAILED, "select/auth failed");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
} else {
|
||||
uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
if (select_only(CSN, CCNR, (keyType == 0x18), verbose) == false) {
|
||||
return PM3_ESOFT;
|
||||
if (verbose) PrintAndLogEx(FAILED, "select only failed");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1851,22 +1912,29 @@ static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, boo
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ICLASS_READBL, (uint8_t *)&blockno, sizeof(uint8_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == 0) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == false) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "Command execute timeout");
|
||||
DropField();
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
|
||||
return PM3_EWRONGANSWER;
|
||||
}
|
||||
|
||||
result = (struct p *)resp.data.asBytes;
|
||||
if (result->isOK == false)
|
||||
return PM3_ESOFT;
|
||||
// return data.
|
||||
struct p {
|
||||
bool isOK;
|
||||
uint8_t blockdata[8];
|
||||
} PACKED;
|
||||
|
||||
DropField();
|
||||
struct p *result = (struct p *)resp.data.asBytes;
|
||||
if (result->isOK == false) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " block %02X : " _GREEN_("%s"), blockno, sprint_hex(result->blockdata, sizeof(result->blockdata)));
|
||||
|
||||
|
@ -1943,6 +2011,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
|||
bool auth = false;
|
||||
bool verbose = false;
|
||||
uint8_t cmdp = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
|
@ -2000,10 +2069,10 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
|||
if (got_blockno == false)
|
||||
errors = true;
|
||||
|
||||
if (errors || cmdp < 4) return usage_hf_iclass_readblock();
|
||||
if (errors) return usage_hf_iclass_readblock();
|
||||
|
||||
if (!auth)
|
||||
PrintAndLogEx(FAILED, "warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
|
||||
if (auth == false)
|
||||
PrintAndLogEx(WARNING, "warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
|
||||
|
||||
return iclass_read_block(KEY, blockno, keyType, elite, rawkey, verbose, auth);
|
||||
}
|
||||
|
@ -2993,6 +3062,20 @@ int CmdHFiClass(const char *Cmd) {
|
|||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
|
||||
//static void test_credential_type(void) {
|
||||
// need AA1 key
|
||||
// Block 5 -> tells if its a legacy or SIO, also tells which key to use.
|
||||
|
||||
// tech | blocks used | desc | num of payloads
|
||||
// -------+-----------------------+-----------------------------------+------
|
||||
// legacy | 6,7,8,9 | AA!, Access control payload | 1
|
||||
// SE | 6,7,8,9,10,11,12 | AA1, Secure identity object (SIO) | 1
|
||||
// SR | 6,7,8,9, | AA1, Access control payload | 2
|
||||
// | 10,11,12,13,14,15,16 | AA1, Secure identity object (SIO) |
|
||||
// SEOS | | |
|
||||
//}
|
||||
|
||||
int readIclass(bool loop, bool verbose) {
|
||||
bool tagFound = false;
|
||||
|
||||
|
@ -3079,6 +3162,10 @@ int readIclass(bool loop, bool verbose) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t cardtype = get_mem_config(hdr);
|
||||
PrintAndLogEx(SUCCESS, "%s", card_types[cardtype]);
|
||||
|
||||
|
||||
if (tagFound && !loop) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
DropField();
|
||||
|
|
|
@ -27,19 +27,6 @@ typedef struct iclass_prekey {
|
|||
uint8_t key[8];
|
||||
} iclass_prekey_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t key[8];
|
||||
bool use_raw;
|
||||
bool use_elite;
|
||||
bool use_credit_key;
|
||||
} PACKED iclass_auth_req_t;
|
||||
|
||||
typedef struct {
|
||||
bool isOK;
|
||||
uint8_t div_key[8];
|
||||
uint8_t mac[4];
|
||||
} PACKED iclass_auth_resp_t;
|
||||
|
||||
int CmdHFiClass(const char *Cmd);
|
||||
|
||||
int readIclass(bool loop, bool verbose);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define CARD_INS_ENCRYPT 0x02
|
||||
#define CARD_INS_DECODE 0x06
|
||||
#define CARD_INS_NUMBLOCKS 0x07
|
||||
#define CARD_INS_PINSIZE 0x08
|
||||
static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// look for CryptoHelper
|
||||
|
@ -91,3 +92,13 @@ uint8_t GetNumberBlocksForUserId(uint8_t *src) {
|
|||
ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
|
||||
return resp[8];
|
||||
}
|
||||
|
||||
// Call with block6
|
||||
uint8_t GetPinSize(uint8_t *src) {
|
||||
int resp_len = 0;
|
||||
uint8_t resp[254] = {0};
|
||||
uint8_t c[] = {0x96, CARD_INS_PINSIZE, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
memcpy(c + 5, src, 8);
|
||||
ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
|
||||
return resp[8];
|
||||
}
|
||||
|
|
|
@ -19,4 +19,5 @@ bool Encrypt(uint8_t *src, uint8_t *dest);
|
|||
bool Decrypt(uint8_t *src, uint8_t *dest);
|
||||
void DecodeBlock6(uint8_t *src);
|
||||
uint8_t GetNumberBlocksForUserId(uint8_t *src);
|
||||
uint8_t GetPinSize(uint8_t *src);
|
||||
#endif
|
||||
|
|
|
@ -289,6 +289,23 @@ typedef struct {
|
|||
const char *value;
|
||||
} PACKED ecdsa_publickey_t;
|
||||
|
||||
|
||||
// iCLASS auth request data structure
|
||||
typedef struct {
|
||||
uint8_t key[8];
|
||||
bool use_raw;
|
||||
bool use_elite;
|
||||
bool use_credit_key;
|
||||
} PACKED iclass_auth_req_t;
|
||||
|
||||
// iCLASS auth response data structure
|
||||
typedef struct {
|
||||
bool isOK;
|
||||
uint8_t div_key[8];
|
||||
uint8_t mac[4];
|
||||
} PACKED iclass_auth_resp_t;
|
||||
|
||||
|
||||
// For the bootloader
|
||||
#define CMD_DEVICE_INFO 0x0000
|
||||
//#define CMD_SETUP_WRITE 0x0001
|
||||
|
|
Loading…
Reference in a new issue