Merge branch 'master' into lf_emul
This commit is contained in:
@@ -45,7 +45,7 @@
|
||||
* This module emits debug strings during normal operation -- so try it out in
|
||||
* the lab connected to PM3 client before taking it into the field.
|
||||
*
|
||||
* To delete the trace data from flash:
|
||||
* To delete the trace data from flash:
|
||||
*
|
||||
* Caveats / notes:
|
||||
* - Trace buffer will be cleared on starting stand-alone mode. Data in flash
|
||||
@@ -97,7 +97,7 @@ void RunMod() {
|
||||
if (trace_len > 0) {
|
||||
Dbprintf("[!] Trace length (bytes) = %u", trace_len);
|
||||
|
||||
uint8_t* trace_buffer = BigBuf_get_addr();
|
||||
uint8_t *trace_buffer = BigBuf_get_addr();
|
||||
if (!exists_in_spiffs(HF_14ASNIFF_LOGFILE)) {
|
||||
rdv40_spiffs_write(
|
||||
HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
@@ -117,7 +117,7 @@ void RunMod() {
|
||||
|
||||
SpinErr(LED_A, 200, 5);
|
||||
SpinDelay(100);
|
||||
|
||||
|
||||
LEDsoff();
|
||||
SpinDelay(300);
|
||||
DownloadTraceInstructions();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// main code for HID collector aka IceHID by Iceman
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <inttypes.h>
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
@@ -63,7 +64,7 @@ void DownloadLogInstructions() {
|
||||
|
||||
bool log_exists;
|
||||
|
||||
void append(uint8_t* entry, size_t entry_len) {
|
||||
void append(uint8_t *entry, size_t entry_len) {
|
||||
|
||||
LED_B_ON();
|
||||
if (log_exists == false) {
|
||||
@@ -105,23 +106,23 @@ uint32_t IceEM410xdemod() {
|
||||
memset(entry, 0, sizeof(entry));
|
||||
|
||||
if (size == 128) {
|
||||
sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)\n",
|
||||
hi,
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
sprintf((char *)entry, "EM XL TAG ID: %06"PRIx32"%08"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n",
|
||||
hi,
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
} else {
|
||||
sprintf((char *)entry, "EM TAG ID: %02lx%08lx - (%05ld_%03ld_%08ld)\n",
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
sprintf((char *)entry, "EM TAG ID: %02"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n",
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
}
|
||||
|
||||
append(entry, strlen((char*)entry));
|
||||
append(entry, strlen((char *)entry));
|
||||
Dbprintf("%s", entry);
|
||||
BigBuf_free();
|
||||
return PM3_SUCCESS;
|
||||
@@ -160,20 +161,20 @@ uint32_t IceAWIDdemod() {
|
||||
uint8_t fac = bytebits_to_byte(dest + 9, 8);
|
||||
uint32_t cardnum = bytebits_to_byte(dest + 17, 16);
|
||||
uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
|
||||
sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||
sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||
} else {
|
||||
uint32_t cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16);
|
||||
if (fmtLen > 32) {
|
||||
uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen - 32);
|
||||
uint32_t code2 = bytebits_to_byte(dest + 8 + (fmtLen - 32), 32);
|
||||
sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx%08lx, Raw: %08lx%08lx%08lx\n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
||||
sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32"%08"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
||||
} else {
|
||||
uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
|
||||
sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||
sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||
}
|
||||
}
|
||||
|
||||
append(entry, strlen((char*)entry));
|
||||
append(entry, strlen((char *)entry));
|
||||
Dbprintf("%s", entry);
|
||||
BigBuf_free();
|
||||
return PM3_SUCCESS;
|
||||
@@ -209,15 +210,15 @@ uint32_t IceIOdemod() {
|
||||
uint8_t entry[64];
|
||||
memset(entry, 0, sizeof(entry));
|
||||
|
||||
sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx)\n"
|
||||
, version
|
||||
, facilitycode
|
||||
, number
|
||||
, hi
|
||||
, lo
|
||||
);
|
||||
sprintf((char *)entry, "IO Prox XSF(%02u)%02x:%05u (%08"PRIx32"%08"PRIx32")\n"
|
||||
, version
|
||||
, facilitycode
|
||||
, number
|
||||
, hi
|
||||
, lo
|
||||
);
|
||||
|
||||
append(entry, strlen((char*)entry));
|
||||
append(entry, strlen((char *)entry));
|
||||
Dbprintf("%s", entry);
|
||||
BigBuf_free();
|
||||
return PM3_SUCCESS;
|
||||
@@ -249,14 +250,14 @@ uint32_t IceHIDDemod() {
|
||||
// go over previously decoded manchester data and decode into usable tag ID
|
||||
if (hi2 != 0) { //extra large HID tags 88/192 bits
|
||||
|
||||
sprintf((char *)entry, "HID large: %lx%08lx%08lx (%ld)\n",
|
||||
hi2,
|
||||
hi,
|
||||
lo,
|
||||
(lo >> 1) & 0xFFFF
|
||||
);
|
||||
sprintf((char *)entry, "HID large: %"PRIx32"%08"PRIx32"%08"PRIx32" (%"PRIu32")\n",
|
||||
hi2,
|
||||
hi,
|
||||
lo,
|
||||
(lo >> 1) & 0xFFFF
|
||||
);
|
||||
|
||||
append(entry, strlen((char*)entry));
|
||||
append(entry, strlen((char *)entry));
|
||||
|
||||
} else { //standard HID tags 44/96 bits
|
||||
uint8_t bitlen = 0;
|
||||
@@ -296,16 +297,16 @@ uint32_t IceHIDDemod() {
|
||||
fac = ((hi & 0xF) << 12) | (lo >> 20);
|
||||
}
|
||||
|
||||
sprintf((char *)entry, "HID: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld\n",
|
||||
hi,
|
||||
lo,
|
||||
(lo >> 1) & 0xFFFF,
|
||||
bitlen,
|
||||
fac,
|
||||
cardnum
|
||||
);
|
||||
sprintf((char *)entry, "HID: %"PRIx32"%08"PRIx32" (%"PRIu32") Format: %d bit FC: %"PRIu32" Card: %"PRIu32"\n",
|
||||
hi,
|
||||
lo,
|
||||
(lo >> 1) & 0xFFFF,
|
||||
bitlen,
|
||||
fac,
|
||||
cardnum
|
||||
);
|
||||
|
||||
append(entry, strlen((char*)entry));
|
||||
append(entry, strlen((char *)entry));
|
||||
}
|
||||
|
||||
Dbprintf("%s", entry);
|
||||
@@ -349,7 +350,7 @@ void RunMod() {
|
||||
|
||||
uint32_t res;
|
||||
|
||||
// since we steal 12800 from bigbuffer, no need to sample it.
|
||||
// since we steal 12800 from bigbuffer, no need to sample it.
|
||||
DoAcquisition_config(false, 28000);
|
||||
res = IceHIDDemod();
|
||||
if (res == PM3_SUCCESS) {
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "Standalone/standalone.h"
|
||||
#include "util.h"
|
||||
#include "ticks.h"
|
||||
#include "commonutil.h"
|
||||
|
||||
#ifdef WITH_LCD
|
||||
#include "LCD.h"
|
||||
@@ -548,7 +549,7 @@ void ListenReaderField(uint8_t limit) {
|
||||
// iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader.
|
||||
hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40);
|
||||
#else
|
||||
hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
|
||||
hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
|
||||
#endif
|
||||
Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10);
|
||||
hf_baseline = hf_av;
|
||||
@@ -1247,6 +1248,17 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
// SniffMifare(packet->oldarg[0]);
|
||||
// break;
|
||||
// }
|
||||
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
||||
struct p {
|
||||
uint8_t keytype;
|
||||
uint8_t pers_option;
|
||||
uint8_t key[6];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
uint64_t authkey = bytes_to_num(payload->key, 6);
|
||||
MifarePersonalizeUID(payload->keytype, payload->pers_option, authkey);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_SETMOD: {
|
||||
MifareSetMod(packet->data.asBytes);
|
||||
break;
|
||||
|
||||
@@ -408,7 +408,7 @@ void fix_ac_decoding(uint8_t *input, size_t len) {
|
||||
*/
|
||||
|
||||
|
||||
// looks at number of received bits.
|
||||
// looks at number of received bits.
|
||||
// 0 = collision?
|
||||
// 32 = good response
|
||||
bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) {
|
||||
@@ -544,7 +544,7 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t
|
||||
// will receive 32-bit configuration page
|
||||
} else if (bSelecting) {
|
||||
// Initiate auth
|
||||
tx[0] = 0xa0 | key_no >> 4; // WRCPAGE
|
||||
tx[0] = 0xa0 | (key_no); // WRCPAGE
|
||||
tx[1] = blocknr << 4;
|
||||
crc = hitag_crc(tx, 12);
|
||||
tx[1] |= crc >> 4;
|
||||
@@ -582,15 +582,15 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t
|
||||
Dbhexdump(4, logdata_1, false);
|
||||
bSuccessful = true;
|
||||
return false;
|
||||
/*
|
||||
// read next page of card until done
|
||||
tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
|
||||
tx[1] = blocknr << 4;
|
||||
crc = hitag_crc(tx, 12);
|
||||
tx[1] |= crc >> 4;
|
||||
tx[2] = crc << 4;
|
||||
*txlen = 20;
|
||||
*/
|
||||
/*
|
||||
// read next page of card until done
|
||||
tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
|
||||
tx[1] = blocknr << 4;
|
||||
crc = hitag_crc(tx, 12);
|
||||
tx[1] |= crc >> 4;
|
||||
tx[2] = crc << 4;
|
||||
*txlen = 20;
|
||||
*/
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1091,7 +1091,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
||||
uint32_t block = 0;
|
||||
for (size_t i = 0; i < 12; i++) {
|
||||
|
||||
// num2bytes?
|
||||
// num2bytes?
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
block <<= 8;
|
||||
block |= tag.sectors[i][j];
|
||||
@@ -1105,30 +1105,30 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
||||
size_t nrzs = 0, periods = 0;
|
||||
|
||||
// uint32_t command_start = 0, command_duration = 0;
|
||||
// int16_t checked = 0;
|
||||
// int16_t checked = 0;
|
||||
|
||||
// SIMULATE
|
||||
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
||||
LED_D_ON();
|
||||
|
||||
|
||||
// lf_reset_counter();
|
||||
LED_A_OFF();
|
||||
WDT_HIT();
|
||||
|
||||
/*
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 100) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
*/
|
||||
/*
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 100) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
*/
|
||||
|
||||
rxlen = 0;
|
||||
|
||||
@@ -1220,8 +1220,8 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
||||
if (nrzs < 5) {
|
||||
Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
|
||||
continue;
|
||||
} else {
|
||||
for (size_t i = 0; i < 5; i++){
|
||||
} else {
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
if (nrz_samples[i] != 1) {
|
||||
Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i);
|
||||
}
|
||||
@@ -1229,7 +1229,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
||||
}
|
||||
|
||||
// Pack the response into a byte array
|
||||
for (size_t i = 5; i < 37; i++){
|
||||
for (size_t i = 5; i < 37; i++) {
|
||||
uint8_t bit = nrz_samples[i];
|
||||
rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
@@ -1401,7 +1401,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||
// hitagS settings
|
||||
t_wait_1 = 204;
|
||||
t_wait_2 = 128;
|
||||
/*tag_size = 256;*/
|
||||
flipped_bit = 0;
|
||||
tag_size = 8;
|
||||
DBG DbpString("Configured for hitagS reader");
|
||||
@@ -1657,7 +1656,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||
uint32_t command_start = 0;
|
||||
uint32_t command_duration = 0;
|
||||
uint32_t response_start = 0;
|
||||
uint32_t response_duration = 0;
|
||||
uint32_t response_duration = 0;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
uint8_t txbuf[HITAG_FRAME_LEN];
|
||||
@@ -1731,14 +1730,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||
tag_size = 8;
|
||||
DbpString("Configured for hitagS writer");
|
||||
} else if (htf < 20) {
|
||||
// hitag1 settings
|
||||
// hitag1 settings
|
||||
t_wait_1 = 204;
|
||||
t_wait_2 = 128;
|
||||
tag_size = 256;
|
||||
flipped_bit = 0;
|
||||
DbpString("Configured for hitag1 writer");
|
||||
} else if (htf < 30) {
|
||||
// hitag2 settings
|
||||
// hitag2 settings
|
||||
t_wait_1 = HITAG_T_WAIT_1_MIN;
|
||||
t_wait_2 = HITAG_T_WAIT_2_MIN;
|
||||
tag_size = 48;
|
||||
@@ -1783,7 +1782,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
|
||||
// Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
|
||||
lf_wait_periods(t_wait_2);
|
||||
command_start += t_wait_2;
|
||||
|
||||
|
||||
@@ -38,70 +38,60 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
|
||||
uint8_t temp[20];
|
||||
int i;
|
||||
uint8_t *spaceptr = NULL;
|
||||
|
||||
|
||||
// get uid as hexstring
|
||||
if(!hitag2_get_uid(uidhex))
|
||||
{
|
||||
if (!hitag2_get_uid(uidhex)) {
|
||||
UserMessage("Cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert uid hexstring to binarray
|
||||
hextobinarray(uid, uidhex);
|
||||
|
||||
|
||||
// convert nR and aR hexstrings to binarray
|
||||
spaceptr = strchr(nrarhex, ' ');
|
||||
if (!spaceptr)
|
||||
{
|
||||
if (!spaceptr) {
|
||||
UserMessage("Please supply a valid nR aR pair\r\n");
|
||||
return false;
|
||||
}
|
||||
*spaceptr = 0x00;
|
||||
|
||||
if (hextobinarray(nrar, nrarhex) != 32)
|
||||
{
|
||||
|
||||
if (hextobinarray(nrar, nrarhex) != 32) {
|
||||
UserMessage("nR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
|
||||
{
|
||||
|
||||
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
|
||||
UserMessage("aR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find a valid encrypted command
|
||||
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
|
||||
{
|
||||
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
|
||||
UserMessage("Cannot find a valid encrypted command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// find the 'read page 0' command and recover key stream
|
||||
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
|
||||
{
|
||||
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
|
||||
UserMessage("Cannot find encrypted 'read page0' command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// empty the response string
|
||||
response[0] = 0x00;
|
||||
|
||||
|
||||
// read all pages using key stream
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
if (hitag2crack_read_page(pagehex, i, nrar, keybits))
|
||||
{
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (hitag2crack_read_page(pagehex, i, nrar, keybits)) {
|
||||
sprintf(temp, "%1d: %s\r\n", i, pagehex);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
sprintf(temp, "%1d:\r\n", i);
|
||||
}
|
||||
// add page string to response
|
||||
strcat(response, temp);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -113,16 +103,16 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
|
||||
bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) {
|
||||
uint8_t guess[10];
|
||||
uint8_t responsestr[9];
|
||||
|
||||
|
||||
// UserMessage("Finding valid encrypted command:");
|
||||
// we're going to hold bits 5, 7, 8 and 9 and brute force the rest
|
||||
// e.g. x x x x x 0 x 0 0 0
|
||||
for (uint8_t a=0; a<2; a++) {
|
||||
for (uint8_t b=0; b<2; b++) {
|
||||
for (uint8_t c=0; c<2; c++) {
|
||||
for (uint8_t d=0; d<2; d++) {
|
||||
for (uint8_t e=0; e<2; e++) {
|
||||
for (uint8_t g=0; g<2; g++) {
|
||||
for (uint8_t a = 0; a < 2; a++) {
|
||||
for (uint8_t b = 0; b < 2; b++) {
|
||||
for (uint8_t c = 0; c < 2; c++) {
|
||||
for (uint8_t d = 0; d < 2; d++) {
|
||||
for (uint8_t e = 0; e < 2; e++) {
|
||||
for (uint8_t g = 0; g < 2; g++) {
|
||||
// build binarray
|
||||
guess[0] = a;
|
||||
guess[1] = b;
|
||||
@@ -175,65 +165,50 @@ bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8
|
||||
|
||||
UserMessage("Finding 'read page 0' command:");
|
||||
// we're going to brute the missing 4 bits of the valid encrypted command
|
||||
for (a=0; a<2; a++)
|
||||
{
|
||||
for (b=0; b<2; b++)
|
||||
{
|
||||
for (c=0; c<2; c++)
|
||||
{
|
||||
for (d=0; d<2; d++)
|
||||
{
|
||||
for (a = 0; a < 2; a++) {
|
||||
for (b = 0; b < 2; b++) {
|
||||
for (c = 0; c < 2; c++) {
|
||||
for (d = 0; d < 2; d++) {
|
||||
// create our guess by bit flipping the pattern of bits
|
||||
// representing the inverted bit and the 3 page bits
|
||||
// in both the non-inverted and inverted parts of the
|
||||
// encrypted command.
|
||||
memcpy(guess, e_firstcmd, 10);
|
||||
if (a)
|
||||
{
|
||||
if (a) {
|
||||
guess[5] = !guess[5];
|
||||
guess[0] = !guess[0];
|
||||
}
|
||||
if (b)
|
||||
{
|
||||
if (b) {
|
||||
guess[7] = !guess[7];
|
||||
guess[2] = !guess[2];
|
||||
}
|
||||
if (c)
|
||||
{
|
||||
if (c) {
|
||||
guess[8] = !guess[8];
|
||||
guess[3] = !guess[3];
|
||||
}
|
||||
if (d)
|
||||
{
|
||||
if (d) {
|
||||
guess[9] = !guess[9];
|
||||
guess[4] = !guess[4];
|
||||
}
|
||||
|
||||
|
||||
// try the guess
|
||||
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10))
|
||||
{
|
||||
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
|
||||
// check if it was valid
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) != 0)
|
||||
{
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
|
||||
// convert response to binarray
|
||||
hextobinarray(e_uid, responsestr);
|
||||
// test if the guess was 'read page 0' command
|
||||
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid))
|
||||
{
|
||||
|
||||
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef RFIDLER_DEBUG
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
|
||||
#endif
|
||||
}
|
||||
@@ -262,56 +237,51 @@ bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, u
|
||||
uint8_t e_ext_cmd[40];
|
||||
uint8_t responsestr[9];
|
||||
int i;
|
||||
|
||||
|
||||
// copy encrypted cmd to cipherbits
|
||||
memcpy(cipherbits, e_cmd, 10);
|
||||
|
||||
|
||||
// copy encrypted uid to cipherbits
|
||||
memcpy(cipherbits + 10, e_uid, 32);
|
||||
|
||||
|
||||
// copy cmd to plainbits
|
||||
binstringtobinarray(plainbits, READP0CMD);
|
||||
|
||||
|
||||
// copy uid to plainbits
|
||||
memcpy(plainbits + 10, uid, 32);
|
||||
|
||||
// xor the plainbits with the cipherbits to get keybits
|
||||
hitag2crack_xor(keybits, plainbits, cipherbits, 42);
|
||||
|
||||
|
||||
// create extended cmd -> 4 * READP0CMD = 40 bits
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
for (i = 0; i < 4; i++) {
|
||||
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
|
||||
}
|
||||
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
|
||||
|
||||
|
||||
// send extended encrypted cmd
|
||||
if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40))
|
||||
{
|
||||
if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) {
|
||||
// test if it was valid
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) != 0)
|
||||
{
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// hitag2crack_xor XORs the source with the pad to produce the target.
|
||||
// source, target and pad are binarrays of length len.
|
||||
void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) {
|
||||
|
||||
for (int i=0; i<len; i++) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
target[i] = source[i] ^ pad[i];
|
||||
}
|
||||
}
|
||||
@@ -329,40 +299,34 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar,
|
||||
uint8_t e_response[32];
|
||||
uint8_t response[32];
|
||||
int i;
|
||||
|
||||
if ((pagenum < 0) || (pagenum > 7))
|
||||
{
|
||||
|
||||
if (pagenum > 7) {
|
||||
UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// create cmd
|
||||
binstringtobinarray(cmd, READP0CMD);
|
||||
if (pagenum & 0x1)
|
||||
{
|
||||
if (pagenum & 0x1) {
|
||||
cmd[9] = !cmd[9];
|
||||
cmd[4] = !cmd[4];
|
||||
}
|
||||
if (pagenum & 0x2)
|
||||
{
|
||||
if (pagenum & 0x2) {
|
||||
cmd[8] = !cmd[8];
|
||||
cmd[3] = !cmd[3];
|
||||
}
|
||||
if (pagenum & 0x4)
|
||||
{
|
||||
if (pagenum & 0x4) {
|
||||
cmd[7] = !cmd[7];
|
||||
cmd[2] = !cmd[2];
|
||||
}
|
||||
|
||||
|
||||
// encrypt command
|
||||
hitag2crack_xor(e_cmd, cmd, keybits, 10);
|
||||
|
||||
|
||||
// send encrypted command
|
||||
if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10))
|
||||
{
|
||||
if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) {
|
||||
// check if it is valid
|
||||
if (strcmp(e_responsestr, ERROR_RESPONSE) != 0)
|
||||
{
|
||||
if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) {
|
||||
// convert to binarray
|
||||
hextobinarray(e_response, e_responsestr);
|
||||
// decrypt response
|
||||
@@ -370,17 +334,13 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar,
|
||||
// convert to hexstring
|
||||
binarraytohex(responsestr, response, 32);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -391,14 +351,13 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar,
|
||||
// cmd is the binarray of the encrypted command to send;
|
||||
// len is the length of the encrypted command.
|
||||
bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) {
|
||||
uint8_t tmp[37];
|
||||
// uint8_t tmp[37];
|
||||
uint8_t uid[9];
|
||||
uint8_t e_page3str[9];
|
||||
int ret = 0;
|
||||
|
||||
// get the UID
|
||||
if(!hitag2_get_uid(uid))
|
||||
{
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
@@ -407,22 +366,19 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i
|
||||
CryptoActive = false;
|
||||
|
||||
// get the UID again
|
||||
if(!hitag2_get_uid(uid))
|
||||
{
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// send nrar and receive (useless) encrypted page 3 value
|
||||
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false))
|
||||
{
|
||||
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// send encrypted command
|
||||
if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false))
|
||||
{
|
||||
if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
|
||||
#endif
|
||||
@@ -442,34 +398,29 @@ bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, b
|
||||
int ret = 0;
|
||||
|
||||
// START_AUTH kills active crypto session
|
||||
CryptoActive= false;
|
||||
|
||||
if(!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX))
|
||||
{
|
||||
CryptoActive = false;
|
||||
|
||||
if (!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) {
|
||||
UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// skip 1/2 bit to synchronise manchester
|
||||
HW_Skip_Bits = 1;
|
||||
ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY);
|
||||
|
||||
// check if response was a valid length (5 sync bits + 32 bits response)
|
||||
if (ret == 37)
|
||||
{
|
||||
if (ret == 37) {
|
||||
// check sync bits
|
||||
if (memcmp(tmp, Hitag2Sync, 5) != 0)
|
||||
{
|
||||
if (memcmp(tmp, Hitag2Sync, 5) != 0) {
|
||||
UserMessage("hitag2crack_tx_rx: no sync\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// convert response to hexstring
|
||||
binarraytohex(responsestr, tmp + 5, 32);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
|
||||
#endif
|
||||
@@ -485,58 +436,53 @@ bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
|
||||
uint32_t initvector;
|
||||
uint8_t *spaceptr;
|
||||
uint8_t *dataptr;
|
||||
|
||||
|
||||
// extract vals from input
|
||||
dataptr = input;
|
||||
spaceptr = strchr(dataptr, ' ');
|
||||
if (!spaceptr)
|
||||
{
|
||||
if (!spaceptr) {
|
||||
UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
*spaceptr = 0x00;
|
||||
|
||||
if (strlen(dataptr) != 12)
|
||||
{
|
||||
|
||||
if (strlen(dataptr) != 12) {
|
||||
UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
sharedkey = rev64(hexreversetoulonglong(dataptr));
|
||||
|
||||
dataptr = spaceptr+1;
|
||||
|
||||
dataptr = spaceptr + 1;
|
||||
spaceptr = strchr(dataptr, ' ');
|
||||
if (!spaceptr)
|
||||
{
|
||||
if (!spaceptr) {
|
||||
UserMessage("/r/nno UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
*spaceptr = 0x00;
|
||||
if (strlen(dataptr) != 8)
|
||||
{
|
||||
if (strlen(dataptr) != 8) {
|
||||
UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
serialnum = rev32(hexreversetoulong(dataptr));
|
||||
|
||||
dataptr = spaceptr+1;
|
||||
|
||||
if (strlen(dataptr) != 8)
|
||||
{
|
||||
|
||||
dataptr = spaceptr + 1;
|
||||
|
||||
if (strlen(dataptr) != 8) {
|
||||
UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
initvector = rev32(hexreversetoulong(dataptr));
|
||||
|
||||
|
||||
// start up crypto engine
|
||||
hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector);
|
||||
|
||||
|
||||
strcpy(response, "Success\r\n");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -545,21 +491,20 @@ bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
|
||||
uint8_t binhex[9];
|
||||
uint8_t binstr[33];
|
||||
uint32_t binulong;
|
||||
|
||||
if (strlen(hex) != 8)
|
||||
{
|
||||
|
||||
if (strlen(hex) != 8) {
|
||||
UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
binulong = hextoulong(hex);
|
||||
|
||||
|
||||
ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32);
|
||||
binarraytobinstring(binstr, bin, 32);
|
||||
binarraytohex(binhex, bin, 32);
|
||||
// UserMessage("ar = %s\r\n", binstr);
|
||||
// UserMessage("arhex = %s\r\n", binhex);
|
||||
|
||||
|
||||
strcpy(response, binhex);
|
||||
return true;
|
||||
}
|
||||
@@ -570,17 +515,16 @@ bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
|
||||
uint8_t binstr[33];
|
||||
uint32_t binulong;
|
||||
int len;
|
||||
|
||||
|
||||
len = strlen(e_binstr);
|
||||
if (len > 32)
|
||||
{
|
||||
if (len > 32) {
|
||||
UserMessage("\r\nbinary string must be <= 32 bits\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
binstringtobinarray(e_bin, e_binstr);
|
||||
binulong = binarraytoulong(e_bin, len);
|
||||
|
||||
|
||||
ulongtobinarray(bin, hitag2_crypt(binulong, len), len);
|
||||
binarraytobinstring(binstr, bin, len);
|
||||
strcpy(response, binstr);
|
||||
@@ -595,7 +539,7 @@ bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) {
|
||||
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) {
|
||||
return hitag2crack_decrypt_bin(response, e_binstr);
|
||||
}
|
||||
|
||||
|
||||
// hitag2_keystream uses the first crack algorithm described in the paper,
|
||||
// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
|
||||
// of keystream.
|
||||
@@ -607,113 +551,101 @@ bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
|
||||
uint8_t uid[32];
|
||||
uint8_t nrar[64];
|
||||
uint8_t e_firstcmd[10];
|
||||
uint8_t e_page0cmd[10];
|
||||
// uint8_t e_page0cmd[10];
|
||||
// uint8_t keybits[2080];
|
||||
uint8_t *keybits = DataBuff;
|
||||
uint8_t keybitshex[67];
|
||||
int kslen;
|
||||
int ksoffset;
|
||||
uint8_t pagehex[9];
|
||||
uint8_t temp[20];
|
||||
// uint8_t pagehex[9];
|
||||
// uint8_t temp[20];
|
||||
int i;
|
||||
uint8_t *spaceptr = NULL;
|
||||
|
||||
/*
|
||||
keybits = malloc(2080);
|
||||
if (!keybits) {
|
||||
UserMessage("cannot malloc keybits\r\n");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
keybits = malloc(2080);
|
||||
if (!keybits) {
|
||||
UserMessage("cannot malloc keybits\r\n");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
// get uid as hexstring
|
||||
if(!hitag2_get_uid(uidhex))
|
||||
{
|
||||
if (!hitag2_get_uid(uidhex)) {
|
||||
UserMessage("Cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert uid hexstring to binarray
|
||||
hextobinarray(uid, uidhex);
|
||||
|
||||
|
||||
// convert nR and aR hexstrings to binarray
|
||||
spaceptr = strchr(nrarhex, ' ');
|
||||
if (!spaceptr)
|
||||
{
|
||||
if (!spaceptr) {
|
||||
UserMessage("Please supply a valid nR aR pair\r\n");
|
||||
return false;
|
||||
}
|
||||
*spaceptr = 0x00;
|
||||
|
||||
if (hextobinarray(nrar, nrarhex) != 32)
|
||||
{
|
||||
|
||||
if (hextobinarray(nrar, nrarhex) != 32) {
|
||||
UserMessage("nR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
|
||||
{
|
||||
|
||||
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
|
||||
UserMessage("aR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find a valid encrypted command
|
||||
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
|
||||
{
|
||||
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
|
||||
UserMessage("Cannot find a valid encrypted command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// find the 'read page 0' command and recover key stream
|
||||
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
|
||||
{
|
||||
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
|
||||
UserMessage("Cannot find encrypted 'read page0' command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// using the 40 bits of keystream in keybits, sending commands with ever
|
||||
// increasing lengths to acquire 2048 bits of key stream.
|
||||
kslen = 40;
|
||||
|
||||
while (kslen < 2048)
|
||||
{
|
||||
|
||||
while (kslen < 2048) {
|
||||
ksoffset = 0;
|
||||
if (!hitag2crack_send_auth(nrar))
|
||||
{
|
||||
if (!hitag2crack_send_auth(nrar)) {
|
||||
UserMessage("hitag2crack_send_auth failed\r\n");
|
||||
return false;
|
||||
}
|
||||
// while we have at least 52 bits of keystream, consume it with
|
||||
// extended read page 0 commands. 52 = 10 (min command len) +
|
||||
// 32 (response) + 10 (min command len we'll send)
|
||||
while ((kslen - ksoffset) >= 52)
|
||||
{
|
||||
while ((kslen - ksoffset) >= 52) {
|
||||
// consume the keystream, updating ksoffset as we go
|
||||
if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar))
|
||||
{
|
||||
if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) {
|
||||
UserMessage("hitag2crack_consume_keystream failed\r\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// send an extended command to retrieve more keystream, updating kslen
|
||||
// as we go
|
||||
if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid))
|
||||
{
|
||||
if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) {
|
||||
UserMessage("hitag2crack_extend_keystream failed\r\n");
|
||||
return false;
|
||||
}
|
||||
UserMessage("Recovered %d bits of keystream\r\n", kslen);
|
||||
|
||||
}
|
||||
|
||||
for (i=0; i<2048; i+=256)
|
||||
{
|
||||
|
||||
for (i = 0; i < 2048; i += 256) {
|
||||
binarraytohex(keybitshex, keybits + i, 256);
|
||||
UserMessage("%s\r\n", keybitshex);
|
||||
}
|
||||
|
||||
response[0] = 0x00;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -724,8 +656,7 @@ bool hitag2crack_send_auth(uint8_t *nrar) {
|
||||
uint8_t e_page3str[9];
|
||||
|
||||
// get the UID
|
||||
if(!hitag2_get_uid(uid))
|
||||
{
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
@@ -734,15 +665,13 @@ bool hitag2crack_send_auth(uint8_t *nrar) {
|
||||
CryptoActive = false;
|
||||
|
||||
// get the UID again
|
||||
if(!hitag2_get_uid(uid))
|
||||
{
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// send nrar and receive (useless) encrypted page 3 value
|
||||
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false))
|
||||
{
|
||||
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
|
||||
return false;
|
||||
}
|
||||
@@ -767,46 +696,41 @@ bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, u
|
||||
// 42 = 32 bit response + 10 bit command reserved for next command. conlen
|
||||
// cannot be longer than 510 bits to fit into the small RWD buffer.
|
||||
conlen = kslen - *ksoffset - 42;
|
||||
if (conlen < 10)
|
||||
{
|
||||
if (conlen < 10) {
|
||||
UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// sanitise conlen
|
||||
if (conlen > 510)
|
||||
{
|
||||
if (conlen > 510) {
|
||||
conlen = 510;
|
||||
}
|
||||
|
||||
|
||||
// calculate how many repeated commands to send in this extended command.
|
||||
numcmds = conlen / 10;
|
||||
|
||||
|
||||
// build extended command
|
||||
for (i=0; i<numcmds; i++)
|
||||
{
|
||||
for (i = 0; i < numcmds; i++) {
|
||||
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
|
||||
}
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10);
|
||||
|
||||
|
||||
// send encrypted command
|
||||
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false))
|
||||
{
|
||||
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// test response
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) == 0)
|
||||
{
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
|
||||
UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// dont bother decrypting the response - we already know the keybits
|
||||
|
||||
|
||||
// update ksoffset with command length and response
|
||||
*ksoffset += (numcmds * 10) + 32;
|
||||
}
|
||||
@@ -825,36 +749,32 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
|
||||
uint8_t responsestr[9];
|
||||
uint8_t e_response[32];
|
||||
int i;
|
||||
|
||||
|
||||
// calc number of command iterations to send
|
||||
cmdlen = *kslen - ksoffset;
|
||||
if (cmdlen < 10)
|
||||
{
|
||||
if (cmdlen < 10) {
|
||||
UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
numcmds = cmdlen / 10;
|
||||
|
||||
|
||||
// build extended command
|
||||
for (i=0; i<numcmds; i++)
|
||||
{
|
||||
for (i = 0; i < numcmds; i++) {
|
||||
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
|
||||
}
|
||||
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10);
|
||||
|
||||
|
||||
// send extended encrypted cmd
|
||||
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false))
|
||||
{
|
||||
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// test response
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) == 0)
|
||||
{
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
|
||||
UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
|
||||
return false;
|
||||
}
|
||||
@@ -867,7 +787,7 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
|
||||
|
||||
// update kslen
|
||||
*kslen = ksoffset + (numcmds * 10) + 32;
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
@@ -875,49 +795,39 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
|
||||
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) {
|
||||
uint8_t tmp[9];
|
||||
int i;
|
||||
|
||||
|
||||
response[0] = '\0';
|
||||
// auth to tag
|
||||
if (hitag2_crypto_auth(tmp, key))
|
||||
{
|
||||
if (hitag2_crypto_auth(tmp, key)) {
|
||||
// read tag, one page at a time
|
||||
for (i= 0; i <= 7; ++i)
|
||||
{
|
||||
if(!read_tag(tmp, i, i))
|
||||
{
|
||||
for (i = 0; i <= 7; ++i) {
|
||||
if (!read_tag(tmp, i, i)) {
|
||||
// if read fails, it could be because of auth,
|
||||
// so try to reauth
|
||||
if (!hitag2_crypto_auth(tmp, key))
|
||||
{
|
||||
if (!hitag2_crypto_auth(tmp, key)) {
|
||||
// if we can't reauth, it's a real failure
|
||||
return false;
|
||||
}
|
||||
// temp failure (probably due to page protections)
|
||||
strcpy(tmp, "XXXXXXXX");
|
||||
strcpy(tmp, "XXXXXXXX");
|
||||
}
|
||||
// page contents are in tmp
|
||||
strcat(response, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (interactive)
|
||||
{
|
||||
tmp[8]= '\0';
|
||||
for(i= 0; i <= 7 ; ++i)
|
||||
{
|
||||
UserMessageNum("%d: ", i);
|
||||
memcpy(tmp, response + (i * 8), 8);
|
||||
UserMessage("%s\r\n", tmp);
|
||||
}
|
||||
UserMessage("%s", "\r\n");
|
||||
if (interactive) {
|
||||
tmp[8] = '\0';
|
||||
for (i = 0; i <= 7 ; ++i) {
|
||||
UserMessageNum("%d: ", i);
|
||||
memcpy(tmp, response + (i * 8), 8);
|
||||
UserMessage("%s\r\n", tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
hitag2_nvm_store_tag(response);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UserMessage("%s", "\r\n");
|
||||
} else {
|
||||
hitag2_nvm_store_tag(response);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, b
|
||||
|
||||
bool hitag2crack_rng_init(uint8_t *response, uint8_t *input);
|
||||
bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex);
|
||||
bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *hex);
|
||||
bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr);
|
||||
bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex);
|
||||
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *hex);
|
||||
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr);
|
||||
|
||||
bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex);
|
||||
bool hitag2crack_send_auth(uint8_t *nrar);
|
||||
|
||||
636
armsrc/hitagS.c
636
armsrc/hitagS.c
@@ -10,6 +10,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Some code was copied from Hitag2.c
|
||||
//-----------------------------------------------------------------------------
|
||||
// bosb 2020
|
||||
|
||||
#include "hitagS.h"
|
||||
|
||||
@@ -23,6 +24,7 @@
|
||||
#include "string.h"
|
||||
#include "commonutil.h"
|
||||
#include "hitag2_crypto.h"
|
||||
#include "lfadc.h"
|
||||
|
||||
#define CRC_PRESET 0xFF
|
||||
#define CRC_POLYNOM 0x1D
|
||||
@@ -50,6 +52,22 @@ size_t blocknr;
|
||||
bool end = false;
|
||||
//#define SENDBIT_TEST
|
||||
|
||||
/* array index 3 2 1 0 // bytes in sim.bin file are 0 1 2 3
|
||||
// UID is 0 1 2 3 // tag.uid is 3210
|
||||
// datasheet HitagS_V11.pdf bytes in tables printed 3 2 1 0
|
||||
|
||||
#db# UID: 5F C2 11 84
|
||||
#db# conf0: C9 conf1: 00 conf2: 00
|
||||
3 2 1 0
|
||||
#db# Page[ 0]: 84 11 C2 5F uid
|
||||
#db# Page[ 1]: AA 00 00 C9 conf, HITAG S 256
|
||||
#db# Page[ 2]: 4E 4F 54 48
|
||||
#db# Page[ 3]: 52 4B 49 4D
|
||||
#db# Page[ 4]: 00 00 00 00
|
||||
#db# Page[ 5]: 00 00 00 00
|
||||
#db# Page[ 6]: 00 00 00 00
|
||||
#db# Page[ 7]: 4B 4F 5F 57 */
|
||||
|
||||
#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b))
|
||||
#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b)))
|
||||
#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
|
||||
@@ -86,7 +104,7 @@ bool end = false;
|
||||
#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
|
||||
#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
|
||||
|
||||
#define DEBUG 0
|
||||
#define DBGLEVEL 0
|
||||
|
||||
/*
|
||||
* Implementation of the crc8 calculation from Hitag S
|
||||
@@ -207,6 +225,22 @@ static void hitag_send_bit(int bit) {
|
||||
}
|
||||
|
||||
static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("hitag_send_frame: (%i) %02X %02X %02X %02X", frame_len, frame[0], frame[1], frame[2], frame[3]);
|
||||
// The beginning of the frame is hidden in some high level; pause until our bits will have an effect
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
switch (m) {
|
||||
case AC4K:
|
||||
case MC8K:
|
||||
while (AT91C_BASE_TC0->TC_CV < T0 * 40) {}; //FADV
|
||||
break;
|
||||
case AC2K:
|
||||
case MC4K:
|
||||
while (AT91C_BASE_TC0->TC_CV < T0 * 20) {}; //STD + ADV
|
||||
break;
|
||||
}
|
||||
|
||||
// SOF - send start of frame
|
||||
for (size_t i = 0; i < sof_bits; i++) {
|
||||
hitag_send_bit(1);
|
||||
@@ -299,6 +333,25 @@ static int check_select(uint8_t *rx, uint32_t uid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hitagS_set_frame_modulation() {
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* handles all commands from a reader
|
||||
*/
|
||||
@@ -318,20 +371,28 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
switch (rxlen) {
|
||||
case 5: {
|
||||
//UID request with a selected response protocol mode
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("UID request: length: %i first byte: %02x", rxlen, rx[0]);
|
||||
tag.pstate = HT_READY;
|
||||
tag.tstate = HT_NO_OP;
|
||||
if ((rx[0] & 0xf0) == 0x30) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("HT_STANDARD");
|
||||
tag.mode = HT_STANDARD;
|
||||
sof_bits = 1;
|
||||
m = AC2K;
|
||||
}
|
||||
if ((rx[0] & 0xf0) == 0xc0) {
|
||||
tag.mode = HT_ADVANCED;
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("HT_ADVANCED");
|
||||
sof_bits = 3;
|
||||
m = AC2K;
|
||||
}
|
||||
|
||||
if ((rx[0] & 0xf0) == 0xd0) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("HT_FAST_ADVANCED");
|
||||
tag.mode = HT_FAST_ADVANCED;
|
||||
sof_bits = 3;
|
||||
m = AC4K;
|
||||
@@ -344,29 +405,18 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
break;
|
||||
case 45: {
|
||||
//select command from reader received
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
DbpString("SELECT");
|
||||
if (check_select(rx, tag.uid) == 1) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
DbpString("SELECT match");
|
||||
//if the right tag was selected
|
||||
*txlen = 32;
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hitagS_set_frame_modulation();
|
||||
|
||||
//send configuration
|
||||
for (int i = 0; i < 4; i++)
|
||||
tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff;
|
||||
tx[i] = tag.pages[1][i];
|
||||
tx[3] = 0xff;
|
||||
if (tag.mode != HT_STANDARD) {
|
||||
*txlen = 40;
|
||||
@@ -390,22 +440,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}",
|
||||
rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
|
||||
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hitagS_set_frame_modulation();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
_hitag2_byte(&state);
|
||||
@@ -438,7 +473,10 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("WRITE");
|
||||
//data received to be written
|
||||
if (tag.tstate == HT_WRITING_PAGE_DATA) {
|
||||
tag.tstate = HT_NO_OP;
|
||||
@@ -448,44 +486,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
*txlen = 2;
|
||||
tx[0] = 0x40;
|
||||
page_to_be_written = 0;
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hitagS_set_frame_modulation();
|
||||
} else if (tag.tstate == HT_WRITING_BLOCK_DATA) {
|
||||
tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
|
||||
<< 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3];
|
||||
//send ack
|
||||
*txlen = 2;
|
||||
tx[0] = 0x40;
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hitagS_set_frame_modulation();
|
||||
page_to_be_written++;
|
||||
block_data_left--;
|
||||
if (block_data_left == 0) {
|
||||
@@ -500,29 +508,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
//send page data
|
||||
uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
|
||||
*txlen = 32;
|
||||
tx[0] = (tag.pages[page / 4][page % 4]) & 0xff;
|
||||
tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
|
||||
tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
|
||||
tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
|
||||
tx[0] = tag.pages[page][0];
|
||||
tx[1] = tag.pages[page][1];
|
||||
tx[2] = tag.pages[page][2];
|
||||
tx[3] = tag.pages[page][3];
|
||||
if (tag.LKP && page == 1)
|
||||
tx[3] = 0xff;
|
||||
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hitagS_set_frame_modulation();
|
||||
|
||||
if (tag.mode != HT_STANDARD) {
|
||||
//add crc8
|
||||
@@ -543,29 +536,13 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
*txlen = 32 * 4;
|
||||
//send page,...,page+3 data
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff;
|
||||
tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
|
||||
tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
|
||||
tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
|
||||
page++;
|
||||
tx[0 + i * 4] = tag.pages[page + 0 + i * 4][0];
|
||||
tx[1 + i * 4] = tag.pages[page + 1 + i * 4][1];
|
||||
tx[2 + i * 4] = tag.pages[page + 2 + i * 4][2];
|
||||
tx[3 + i * 4] = tag.pages[page + 3 + i * 4][3];
|
||||
}
|
||||
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hitagS_set_frame_modulation();
|
||||
|
||||
if (tag.mode != HT_STANDARD) {
|
||||
//add crc8
|
||||
@@ -576,29 +553,12 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
tx[16] = crc;
|
||||
}
|
||||
|
||||
if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) {
|
||||
if ((page) % 4 != 0 || (tag.LKP && (page) == 0)) {
|
||||
sof_bits = 0;
|
||||
*txlen = 0;
|
||||
}
|
||||
} else if ((rx[0] & 0xf0) == 0x80) { //write page
|
||||
uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
|
||||
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((tag.LCON && page == 1)
|
||||
|| (tag.LKP && (page == 2 || page == 3))) {
|
||||
//deny
|
||||
@@ -613,22 +573,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
|
||||
} else if ((rx[0] & 0xf0) == 0x90) { //write block
|
||||
uint8_t page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16);
|
||||
switch (tag.mode) {
|
||||
case HT_STANDARD:
|
||||
sof_bits = 1;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC4K;
|
||||
break;
|
||||
case HT_FAST_ADVANCED:
|
||||
sof_bits = 6;
|
||||
m = MC8K;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hitagS_set_frame_modulation();
|
||||
if (page % 4 != 0 || page == 0) {
|
||||
//deny
|
||||
*txlen = 0;
|
||||
@@ -644,7 +589,8 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("unknown rxlen: (%i) %02X %02X %02X %02X ...", rxlen, rx[0], rx[1], rx[2], rx[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -722,7 +668,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
|
||||
| (uid[30] << 1)
|
||||
| uid[31];
|
||||
|
||||
if (DEBUG)
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4);
|
||||
|
||||
tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1);
|
||||
@@ -816,7 +762,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
|
||||
tag.LCK1 = response_bit[26];
|
||||
tag.LCK0 = response_bit[27];
|
||||
|
||||
if (DEBUG)
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]);
|
||||
|
||||
if (tag.auth == 1) {
|
||||
@@ -839,7 +785,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
|
||||
tx[5] = auth_ks[1];
|
||||
tx[6] = auth_ks[2];
|
||||
tx[7] = auth_ks[3];
|
||||
if (DEBUG)
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0],
|
||||
tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]);
|
||||
} else if (htf == 01 || htf == 03) { //RHTS_CHALLENGE //WHTS_CHALLENGE
|
||||
@@ -864,7 +810,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
|
||||
calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8);
|
||||
calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8);
|
||||
calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8);
|
||||
if (DEBUG) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("UID:::%X", tag.uid);
|
||||
Dbprintf("RND:::%X", rnd);
|
||||
}
|
||||
@@ -884,7 +830,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
|
||||
pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state);
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1);
|
||||
|
||||
//Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16));
|
||||
@@ -930,28 +876,30 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
|
||||
tag.pstate = HT_READY;
|
||||
tag.tstate = HT_NO_OP;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
tag.pages[i][j] = 0x0;
|
||||
|
||||
// read tag data into memory
|
||||
if (tag_mem_supplied) {
|
||||
for (i = 0; i < 16; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
tag.pages[i][j] = 0x0;
|
||||
|
||||
DbpString("Loading hitagS memory...");
|
||||
memcpy((uint8_t *)tag.pages, data, 4 * 64);
|
||||
} else {
|
||||
// use the last read tag
|
||||
}
|
||||
|
||||
tag.uid = (uint32_t)tag.pages[0];
|
||||
tag.key = (intptr_t)tag.pages[3];
|
||||
tag.uid = (tag.pages[0][3] << 24 | tag.pages[0][2] << 16 | tag.pages[0][1] << 8 | tag.pages[0][0]);
|
||||
tag.key = (tag.pages[3][3] << 24 | tag.pages[3][2] << 16 | tag.pages[3][1] << 8 | tag.pages[3][0]);
|
||||
tag.key <<= 16;
|
||||
tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1];
|
||||
tag.pwdl0 = tag.pages[2][3];
|
||||
tag.pwdl1 = tag.pages[2][2];
|
||||
tag.pwdh0 = tag.pages[1][0];
|
||||
tag.key += ((tag.pages[2][3]) << 8) + tag.pages[2][2];
|
||||
tag.pwdl0 = tag.pages[2][0];
|
||||
tag.pwdl1 = tag.pages[2][1];
|
||||
tag.pwdh0 = tag.pages[1][3];
|
||||
//con0
|
||||
tag.max_page = 64;
|
||||
if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 1)
|
||||
if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 1)
|
||||
tag.max_page = 8;
|
||||
if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 0)
|
||||
if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 0)
|
||||
tag.max_page = 0;
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
for (i = 0; i < tag.max_page; i++)
|
||||
@@ -962,41 +910,42 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
|
||||
tag.pages[i][0] & 0xff);
|
||||
//con1
|
||||
tag.auth = 0;
|
||||
if ((tag.pages[1][2] & 0x80) == 0x80)
|
||||
if ((tag.pages[1][1] & 0x80) == 0x80)
|
||||
tag.auth = 1;
|
||||
tag.LCON = 0;
|
||||
if ((tag.pages[1][2] & 0x2) == 0x02)
|
||||
if ((tag.pages[1][1] & 0x2) == 0x02)
|
||||
tag.LCON = 1;
|
||||
tag.LKP = 0;
|
||||
if ((tag.pages[1][2] & 0x1) == 0x01)
|
||||
if ((tag.pages[1][1] & 0x1) == 0x01)
|
||||
tag.LKP = 1;
|
||||
//con2
|
||||
//0=read write 1=read only
|
||||
tag.LCK7 = 0;
|
||||
if ((tag.pages[1][1] & 0x80) == 0x80)
|
||||
if ((tag.pages[1][2] & 0x80) == 0x80)
|
||||
tag.LCK7 = 1;
|
||||
tag.LCK6 = 0;
|
||||
if ((tag.pages[1][1] & 0x40) == 0x040)
|
||||
if ((tag.pages[1][2] & 0x40) == 0x040)
|
||||
tag.LCK6 = 1;
|
||||
tag.LCK5 = 0;
|
||||
if ((tag.pages[1][1] & 0x20) == 0x20)
|
||||
if ((tag.pages[1][2] & 0x20) == 0x20)
|
||||
tag.LCK5 = 1;
|
||||
tag.LCK4 = 0;
|
||||
if ((tag.pages[1][1] & 0x10) == 0x10)
|
||||
if ((tag.pages[1][2] & 0x10) == 0x10)
|
||||
tag.LCK4 = 1;
|
||||
tag.LCK3 = 0;
|
||||
if ((tag.pages[1][1] & 0x8) == 0x08)
|
||||
if ((tag.pages[1][2] & 0x8) == 0x08)
|
||||
tag.LCK3 = 1;
|
||||
tag.LCK2 = 0;
|
||||
if ((tag.pages[1][1] & 0x4) == 0x04)
|
||||
if ((tag.pages[1][2] & 0x4) == 0x04)
|
||||
tag.LCK2 = 1;
|
||||
tag.LCK1 = 0;
|
||||
if ((tag.pages[1][1] & 0x2) == 0x02)
|
||||
if ((tag.pages[1][2] & 0x2) == 0x02)
|
||||
tag.LCK1 = 1;
|
||||
tag.LCK0 = 0;
|
||||
if ((tag.pages[1][1] & 0x1) == 0x01)
|
||||
if ((tag.pages[1][2] & 0x1) == 0x01)
|
||||
tag.LCK0 = 1;
|
||||
|
||||
|
||||
// Set up simulator mode, frequency divisor which will drive the FPGA
|
||||
// and analog mux selection.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
@@ -1028,7 +977,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
|
||||
// TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
||||
// external trigger rising edge, load RA on rising edge of TIOA.
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
|
||||
| AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
|
||||
| AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
|
||||
|
||||
// Enable and reset counter
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
@@ -1100,12 +1049,13 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
|
||||
LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
|
||||
}
|
||||
|
||||
// Enable and reset external trigger in timer for capturing future frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
// Reset the received frame and response timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
response = 0;
|
||||
|
||||
// Enable and reset external trigger in timer for capturing future frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
LED_B_OFF();
|
||||
}
|
||||
// Reset the frame length
|
||||
@@ -1114,22 +1064,92 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
|
||||
overflow += (AT91C_BASE_TC1->TC_CV / T0);
|
||||
// Reset the timer to restart while-loop that receives frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
|
||||
}
|
||||
|
||||
LEDsoff();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
lf_finalize();
|
||||
// release allocated memory from BigBuff.
|
||||
BigBuf_free();
|
||||
|
||||
StartTicks();
|
||||
|
||||
DbpString("Sim Stopped");
|
||||
}
|
||||
|
||||
void hitagS_receive_frame(uint8_t *rx, size_t *rxlen, int *response) {
|
||||
|
||||
// Reset values for receiving frames
|
||||
memset(rx, 0x00, HITAG_FRAME_LEN * sizeof(uint8_t));
|
||||
*rxlen = 0;
|
||||
int lastbit = 1;
|
||||
bool bSkip = true;
|
||||
int tag_sof = 1;
|
||||
*response = 0;
|
||||
uint32_t errorCount = 0;
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
|
||||
// Check if falling edge in tag modulation is detected
|
||||
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
|
||||
// Retrieve the new timing values
|
||||
int ra = (AT91C_BASE_TC1->TC_RA / T0);
|
||||
|
||||
// Reset timer every frame, we have to capture the last edge for timing
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
// Capture tag frame (manchester decoding using only falling edges)
|
||||
if (ra >= HITAG_T_EOF) {
|
||||
if (*rxlen != 0) {
|
||||
//DbpString("wierd1?");
|
||||
}
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
|
||||
*response = ra - HITAG_T_TAG_HALF_PERIOD;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
|
||||
// Manchester coding example |-_|_-|-_| (101)
|
||||
rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8));
|
||||
(*rxlen)++;
|
||||
rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8));
|
||||
(*rxlen)++;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
|
||||
// Manchester coding example |_-|...|_-|-_| (0...01)
|
||||
rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8));
|
||||
(*rxlen)++;
|
||||
// We have to skip this half period at start and add the 'one' the second time
|
||||
if (!bSkip) {
|
||||
rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8));
|
||||
(*rxlen)++;
|
||||
}
|
||||
lastbit = !lastbit;
|
||||
bSkip = !bSkip;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
|
||||
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
|
||||
if (tag_sof) {
|
||||
// Ignore bits that are transmitted during SOF
|
||||
tag_sof--;
|
||||
} else {
|
||||
// bit is same as last bit
|
||||
rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8));
|
||||
(*rxlen)++;
|
||||
}
|
||||
} else {
|
||||
// Ignore wierd value, is to small to mean anything
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// if we saw over 100 wierd values break it probably isn't hitag...
|
||||
if (errorCount > 100) break;
|
||||
|
||||
// We can break this loop if we received the last bit from a frame
|
||||
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
|
||||
if ((*rxlen) > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticates to the Tag with the given key or challenge.
|
||||
* If the key was given the password will be decrypted.
|
||||
@@ -1149,7 +1169,6 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
|
||||
uint8_t *tx = txbuf;
|
||||
size_t txlen = 0;
|
||||
int lastbit = 1;
|
||||
int reset_sof = 1;
|
||||
int t_wait = HITAG_T_WAIT_MAX;
|
||||
bool bStop = false;
|
||||
int pageNum = 0;
|
||||
@@ -1164,6 +1183,9 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
|
||||
uint64_t NrAr = 0;
|
||||
uint8_t key_[6];
|
||||
|
||||
tag.pstate = HT_READY;
|
||||
tag.tstate = HT_NO_OP;
|
||||
|
||||
switch (htf) {
|
||||
case RHTSF_CHALLENGE: {
|
||||
DbpString("Authenticating using nr,ar pair:");
|
||||
@@ -1238,10 +1260,8 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
|
||||
|
||||
// synchronized startup procedure
|
||||
while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero
|
||||
|
||||
// Reset the received frame, frame count and timing info
|
||||
t_wait = 200;
|
||||
|
||||
while (!bStop && !BUTTON_PRESS() && !data_available()) {
|
||||
|
||||
WDT_HIT();
|
||||
@@ -1381,85 +1401,12 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
|
||||
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
|
||||
}
|
||||
|
||||
// Reset values for receiving frames
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
rxlen = 0;
|
||||
lastbit = 1;
|
||||
bool bSkip = true;
|
||||
int tag_sof = reset_sof;
|
||||
response = 0;
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
|
||||
// Check if falling edge in tag modulation is detected
|
||||
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
|
||||
// Retrieve the new timing values
|
||||
int ra = (AT91C_BASE_TC1->TC_RA / T0);
|
||||
|
||||
// Reset timer every frame, we have to capture the last edge for timing
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
// Capture tag frame (manchester decoding using only falling edges)
|
||||
if (ra >= HITAG_T_EOF) {
|
||||
if (rxlen != 0) {
|
||||
//DbpString("wierd1?");
|
||||
}
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
|
||||
response = ra - HITAG_T_TAG_HALF_PERIOD;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
|
||||
// Manchester coding example |-_|_-|-_| (101)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
|
||||
// Manchester coding example |_-|...|_-|-_| (0...01)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
// We have to skip this half period at start and add the 'one' the second time
|
||||
if (!bSkip) {
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
lastbit = !lastbit;
|
||||
bSkip = !bSkip;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
|
||||
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
|
||||
if (tag_sof) {
|
||||
// Ignore bits that are transmitted during SOF
|
||||
tag_sof--;
|
||||
} else {
|
||||
// bit is same as last bit
|
||||
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
} else {
|
||||
// Ignore wierd value, is to small to mean anything
|
||||
}
|
||||
}
|
||||
|
||||
// We can break this loop if we received the last bit from a frame
|
||||
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
|
||||
if (rxlen > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
hitagS_receive_frame(rx, &rxlen, &response);
|
||||
}
|
||||
end = false;
|
||||
|
||||
LEDsoff();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
StartTicks();
|
||||
|
||||
lf_finalize();
|
||||
reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1479,7 +1426,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
|
||||
uint8_t *tx = txbuf;
|
||||
size_t txlen = 0;
|
||||
int lastbit;
|
||||
int reset_sof;
|
||||
int t_wait = HITAG_T_WAIT_MAX;
|
||||
bool bStop;
|
||||
unsigned char crc;
|
||||
@@ -1555,6 +1501,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
|
||||
// external trigger rising edge, load RA on falling edge of TIOA.
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
|
||||
| AT91C_TC_ETRGEDG_FALLING
|
||||
@@ -1570,7 +1517,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
|
||||
// Reset the received frame, frame count and timing info
|
||||
lastbit = 1;
|
||||
bStop = false;
|
||||
reset_sof = 1;
|
||||
t_wait = 200;
|
||||
|
||||
while (!bStop && !BUTTON_PRESS() && !data_available()) {
|
||||
@@ -1670,87 +1616,13 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
|
||||
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
|
||||
}
|
||||
|
||||
// Reset values for receiving frames
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
rxlen = 0;
|
||||
lastbit = 1;
|
||||
bool bSkip = true;
|
||||
int tag_sof = reset_sof;
|
||||
response = 0;
|
||||
uint32_t errorCount = 0;
|
||||
hitagS_receive_frame(rx, &rxlen, &response);
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
|
||||
// Check if falling edge in tag modulation is detected
|
||||
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
|
||||
// Retrieve the new timing values
|
||||
int ra = (AT91C_BASE_TC1->TC_RA / T0);
|
||||
|
||||
// Reset timer every frame, we have to capture the last edge for timing
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
// Capture tag frame (manchester decoding using only falling edges)
|
||||
if (ra >= HITAG_T_EOF) {
|
||||
if (rxlen != 0) {
|
||||
//DbpString("wierd1?");
|
||||
}
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
|
||||
response = ra - HITAG_T_TAG_HALF_PERIOD;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
|
||||
// Manchester coding example |-_|_-|-_| (101)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
|
||||
// Manchester coding example |_-|...|_-|-_| (0...01)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
// We have to skip this half period at start and add the 'one' the second time
|
||||
if (!bSkip) {
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
lastbit = !lastbit;
|
||||
bSkip = !bSkip;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
|
||||
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
|
||||
if (tag_sof) {
|
||||
// Ignore bits that are transmitted during SOF
|
||||
tag_sof--;
|
||||
} else {
|
||||
// bit is same as last bit
|
||||
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
} else {
|
||||
// Ignore wierd value, is to small to mean anything
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// if we saw over 100 wierd values break it probably isn't hitag...
|
||||
if (errorCount > 100) break;
|
||||
|
||||
// We can break this loop if we received the last bit from a frame
|
||||
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
|
||||
if (rxlen > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
end = false;
|
||||
LEDsoff();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
StartTicks();
|
||||
lf_finalize();
|
||||
|
||||
reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
|
||||
}
|
||||
@@ -1773,7 +1645,7 @@ void check_challenges(bool file_given, uint8_t *data) {
|
||||
size_t rxlen = 0;
|
||||
uint8_t txbuf[HITAG_FRAME_LEN];
|
||||
int t_wait = HITAG_T_WAIT_MAX;
|
||||
int lastbit, reset_sof, STATE = 0;;
|
||||
int lastbit, STATE = 0;;
|
||||
bool bStop;
|
||||
int response_bit[200];
|
||||
unsigned char mask = 1;
|
||||
@@ -1834,7 +1706,6 @@ void check_challenges(bool file_given, uint8_t *data) {
|
||||
// Reset the received frame, frame count and timing info
|
||||
lastbit = 1;
|
||||
bStop = false;
|
||||
reset_sof = 1;
|
||||
t_wait = 200;
|
||||
|
||||
if (file_given) {
|
||||
@@ -1952,11 +1823,11 @@ void check_challenges(bool file_given, uint8_t *data) {
|
||||
u1++;
|
||||
|
||||
} else if (STATE == 2 && rxlen >= 44) {
|
||||
Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X",
|
||||
unlocker[u1 - 1][0], unlocker[u1 - 1][1],
|
||||
unlocker[u1 - 1][2], unlocker[u1 - 1][3],
|
||||
unlocker[u1 - 1][4], unlocker[u1 - 1][5],
|
||||
unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
|
||||
Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X",
|
||||
unlocker[u1 - 1][0], unlocker[u1 - 1][1],
|
||||
unlocker[u1 - 1][2], unlocker[u1 - 1][3],
|
||||
unlocker[u1 - 1][4], unlocker[u1 - 1][5],
|
||||
unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
|
||||
STATE = 0;
|
||||
}
|
||||
|
||||
@@ -1984,85 +1855,10 @@ void check_challenges(bool file_given, uint8_t *data) {
|
||||
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
|
||||
}
|
||||
|
||||
// Reset values for receiving frames
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
rxlen = 0;
|
||||
lastbit = 1;
|
||||
bool bSkip = true;
|
||||
int tag_sof = reset_sof;
|
||||
response = 0;
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
|
||||
// Check if falling edge in tag modulation is detected
|
||||
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
|
||||
// Retrieve the new timing values
|
||||
int ra = (AT91C_BASE_TC1->TC_RA / T0);
|
||||
|
||||
// Reset timer every frame, we have to capture the last edge for timing
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
// Capture tag frame (manchester decoding using only falling edges)
|
||||
if (ra >= HITAG_T_EOF) {
|
||||
if (rxlen != 0) {
|
||||
//DbpString("wierd1?");
|
||||
}
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
|
||||
response = ra - HITAG_T_TAG_HALF_PERIOD;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
|
||||
// Manchester coding example |-_|_-|-_| (101)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
|
||||
// Manchester coding example |_-|...|_-|-_| (0...01)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
// We have to skip this half period at start and add the 'one' the second time
|
||||
if (!bSkip) {
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
lastbit = !lastbit;
|
||||
bSkip = !bSkip;
|
||||
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
|
||||
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
|
||||
if (tag_sof) {
|
||||
// Ignore bits that are transmitted during SOF
|
||||
tag_sof--;
|
||||
} else {
|
||||
// bit is same as last bit
|
||||
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
} else {
|
||||
// Ignore wierd value, is to small to mean anything
|
||||
}
|
||||
}
|
||||
|
||||
// We can break this loop if we received the last bit from a frame
|
||||
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
|
||||
if (rxlen > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
hitagS_receive_frame(rx, &rxlen, &response);
|
||||
}
|
||||
|
||||
LEDsoff();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
StartTicks();
|
||||
|
||||
lf_finalize();
|
||||
reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1817,15 +1817,15 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
||||
++check;
|
||||
|
||||
// test if the field exists
|
||||
#if defined RDV4
|
||||
#if defined RDV4
|
||||
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF_RDV40)) {
|
||||
|
||||
|
||||
analogCnt++;
|
||||
|
||||
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40];
|
||||
|
||||
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
|
||||
if (analogCnt >= 32) {
|
||||
|
||||
if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
|
||||
@@ -1847,13 +1847,13 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
||||
}
|
||||
#else
|
||||
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
|
||||
|
||||
|
||||
analogCnt++;
|
||||
|
||||
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
|
||||
|
||||
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
|
||||
if (analogCnt >= 32) {
|
||||
|
||||
if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
|
||||
|
||||
@@ -1291,7 +1291,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol)
|
||||
cardnum = (lo >> 1) & 0x7FFFF;
|
||||
fac = ((hi & 0xF) << 12) | (lo >> 20);
|
||||
}
|
||||
Dbprintf("TAG ID: " _YELLOW_("%x%08x (%d)") "- Format Len: " _YELLOW_("%d") "bit - FC: " _YELLOW_("%d") "- Card: "_YELLOW_("%d"),
|
||||
Dbprintf("TAG ID: " _GREEN_("%x%08x (%d)") "- Format Len: " _GREEN_("%d") "bit - FC: " _GREEN_("%d") "- Card: "_GREEN_("%d"),
|
||||
hi,
|
||||
lo,
|
||||
(lo >> 1) & 0xFFFF,
|
||||
@@ -2399,13 +2399,13 @@ void SendForward(uint8_t fwd_bit_count) {
|
||||
TurnReadLF_off(EM_START_GAP);
|
||||
TurnReadLFOn(18 * 8);
|
||||
|
||||
// now start writting with bitbanging the antenna.
|
||||
// now start writting with bitbanging the antenna. (each bit should be 32*8 total length)
|
||||
while (fwd_bit_sz-- > 0) { //prepare next bit modulation
|
||||
if (((*fwd_write_ptr++) & 1) == 1) {
|
||||
WaitUS(32 * 8);
|
||||
} else {
|
||||
TurnReadLF_off(23 * 8);
|
||||
TurnReadLFOn(18 * 8);
|
||||
TurnReadLFOn(32-23 * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,8 +117,8 @@ void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) {
|
||||
|
||||
if (use_malloc) {
|
||||
|
||||
if (sample_size == NULL || *sample_size == 0 ) {
|
||||
*sample_size = BigBuf_max_traceLen();
|
||||
if (sample_size == NULL || *sample_size == 0) {
|
||||
*sample_size = BigBuf_max_traceLen();
|
||||
data.buffer = BigBuf_get_addr();
|
||||
} else {
|
||||
*sample_size = MIN(*sample_size, BigBuf_max_traceLen());
|
||||
@@ -127,7 +127,7 @@ void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) {
|
||||
}
|
||||
|
||||
} else {
|
||||
if (sample_size == NULL || *sample_size == 0 ) {
|
||||
if (sample_size == NULL || *sample_size == 0) {
|
||||
*sample_size = BigBuf_max_traceLen();
|
||||
}
|
||||
data.buffer = BigBuf_get_addr();
|
||||
@@ -221,7 +221,7 @@ void LFSetupFPGAForADC(int divisor, bool reader_field) {
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
// 50ms for the resonant antenna to settle.
|
||||
if (reader_field)
|
||||
SpinDelay(50);
|
||||
SpinDelay(50);
|
||||
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
|
||||
@@ -1805,6 +1805,63 @@ void MifareChkKeys_file(uint8_t *fn) {
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MIFARE Personalize UID. Only for Mifare Classic EV1 7Byte UID
|
||||
//-----------------------------------------------------------------------------
|
||||
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) {
|
||||
|
||||
uint16_t isOK = PM3_EUNDEF;
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
while (true) {
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t block_number = 0;
|
||||
if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if (len != 1 || receivedAnswer[0] != CARD_ACK) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
break;;
|
||||
}
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
|
||||
break;
|
||||
}
|
||||
isOK = PM3_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_HF_MIFARE_PERSONALIZE_UID, isOK, NULL, 0);
|
||||
LED_B_OFF();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Work with emulator memory
|
||||
//
|
||||
@@ -2276,23 +2333,23 @@ void MifareSetMod(uint8_t *datain) {
|
||||
|
||||
while (true) {
|
||||
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
|
||||
if (DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) {
|
||||
if (DBGLEVEL >= 1) Dbprintf("Auth error");
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error");
|
||||
break;
|
||||
}
|
||||
|
||||
int respLen;
|
||||
if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen);
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
if (DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2304,7 +2361,6 @@ void MifareSetMod(uint8_t *datain) {
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_HF_MIFARE_SETMOD, isOK, NULL, 0);
|
||||
|
||||
LED_B_OFF();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
@@ -45,6 +45,8 @@ void MifareCIdent(); // is "magic chinese" card?
|
||||
void MifareHasStaticNonce(); // Has the tag a static nonce?
|
||||
|
||||
void MifareSetMod(uint8_t *datain);
|
||||
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
|
||||
|
||||
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
|
||||
void OnSuccessMagic();
|
||||
void OnErrorMagic(uint8_t reason);
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "crc16.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "commonutil.h"
|
||||
#include "util.h"
|
||||
#include "mifare.h"
|
||||
|
||||
#define MAX_APPLICATION_COUNT 28
|
||||
#define MAX_FILE_COUNT 16
|
||||
@@ -31,8 +33,11 @@ static uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4};
|
||||
/* PCB CID CMD PAYLOAD */
|
||||
//static uint8_t __res[MAX_FRAME_SIZE];
|
||||
|
||||
|
||||
bool InitDesfireCard() {
|
||||
|
||||
pcb_blocknum = 0;
|
||||
|
||||
iso14a_card_select_t card;
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
@@ -46,28 +51,14 @@ bool InitDesfireCard() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ARG0 flag enums
|
||||
enum {
|
||||
NONE = 0x00,
|
||||
INIT = 0x01,
|
||||
DISCONNECT = 0x02,
|
||||
CLEARTRACE = 0x04,
|
||||
BAR = 0x08,
|
||||
} CmdOptions ;
|
||||
|
||||
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||
|
||||
/* ARG0 contains flags.
|
||||
0x01 = init card.
|
||||
0x02 = Disconnect
|
||||
0x03
|
||||
*/
|
||||
uint8_t flags = arg0;
|
||||
size_t datalen = arg1;
|
||||
uint8_t resp[RECEIVE_SIZE];
|
||||
memset(resp, 0, sizeof(resp));
|
||||
|
||||
if (DBGLEVEL >= 4) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf(" flags : %02X", flags);
|
||||
Dbprintf(" len : %02X", datalen);
|
||||
print_result(" RX : ", datain, datalen);
|
||||
@@ -77,35 +68,42 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||
clear_trace();
|
||||
|
||||
if (flags & INIT) {
|
||||
if (!InitDesfireCard())
|
||||
if (!InitDesfireCard()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int len = DesfireAPDU(datain, datalen, resp);
|
||||
if (DBGLEVEL >= 4)
|
||||
print_result("ERR <--: ", resp, len);
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
print_result("RESP <--: ", resp, len);
|
||||
|
||||
if (!len) {
|
||||
OnError(2);
|
||||
return;
|
||||
}
|
||||
|
||||
// reset the pcb_blocknum,
|
||||
pcb_blocknum = 0;
|
||||
|
||||
if (flags & DISCONNECT)
|
||||
OnSuccess();
|
||||
|
||||
reply_old(CMD_ACK, 1, len, 0, resp, len);
|
||||
reply_mix(CMD_ACK, 1, len, 0, resp, len);
|
||||
}
|
||||
|
||||
void MifareDesfireGetInformation() {
|
||||
|
||||
LEDsoff();
|
||||
|
||||
int len = 0;
|
||||
iso14a_card_select_t card;
|
||||
uint8_t resp[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
uint8_t dataout[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
|
||||
struct p {
|
||||
uint8_t isOK;
|
||||
uint8_t uid[7];
|
||||
uint8_t versionHW[7];
|
||||
uint8_t versionSW[7];
|
||||
uint8_t details[14];
|
||||
} PACKED payload;
|
||||
|
||||
/*
|
||||
1 = PCB 1
|
||||
2 = cid 2
|
||||
@@ -122,61 +120,65 @@ void MifareDesfireGetInformation() {
|
||||
// card select - information
|
||||
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) DbpString("Can't select card");
|
||||
OnError(1);
|
||||
payload.isOK = 1; // 2 == can not select
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload));
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
if (card.uidlen != 7) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen);
|
||||
OnError(2);
|
||||
payload.isOK = 2; // 2 == WRONG UID
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload));
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(dataout, card.uid, 7);
|
||||
// add uid.
|
||||
memcpy(payload.uid, card.uid, sizeof(card.uid));
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
uint8_t cmd[] = {GET_VERSION};
|
||||
uint8_t cmd[] = {GET_VERSION, 0x00, 0x00, 0x00};
|
||||
size_t cmd_len = sizeof(cmd);
|
||||
|
||||
len = DesfireAPDU(cmd, cmd_len, resp);
|
||||
if (!len) {
|
||||
print_result("ERROR <--: ", resp, len);
|
||||
OnError(3);
|
||||
payload.isOK = 3; // 3 == DOESNT ANSWER TO GET_VERSION
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload));
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
LED_A_OFF();
|
||||
LED_B_ON();
|
||||
memcpy(dataout + 7, resp + 3, 7);
|
||||
memcpy(payload.versionHW, resp + 1, sizeof(payload.versionHW));
|
||||
|
||||
// ADDITION_FRAME 1
|
||||
cmd[0] = ADDITIONAL_FRAME;
|
||||
len = DesfireAPDU(cmd, cmd_len, resp);
|
||||
if (!len) {
|
||||
print_result("ERROR <--: ", resp, len);
|
||||
OnError(3);
|
||||
payload.isOK = 3; // 3 == DOESNT ANSWER TO GET_VERSION
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload));
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
LED_B_OFF();
|
||||
LED_C_ON();
|
||||
memcpy(dataout + 7 + 7, resp + 3, 7);
|
||||
memcpy(payload.versionSW, resp + 1, sizeof(payload.versionSW));
|
||||
|
||||
// ADDITION_FRAME 2
|
||||
len = DesfireAPDU(cmd, cmd_len, resp);
|
||||
if (!len) {
|
||||
print_result("ERROR <--: ", resp, len);
|
||||
OnError(3);
|
||||
payload.isOK = 3; // 3 == DOESNT ANSWER TO GET_VERSION
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload));
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(dataout + 7 + 7 + 7, resp + 3, 14);
|
||||
|
||||
reply_old(CMD_ACK, 1, 0, 0, dataout, sizeof(dataout));
|
||||
memcpy(payload.details, resp + 1, sizeof(payload.details));
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
||||
LED_B_OFF();
|
||||
|
||||
// reset the pcb_blocknum,
|
||||
pcb_blocknum = 0;
|
||||
OnSuccess();
|
||||
@@ -467,7 +469,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
|
||||
// dekryptera tagnonce.
|
||||
if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) {
|
||||
if (DBGLEVEL >= 4) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
DbpString("mbedtls_aes_setkey_dec failed");
|
||||
}
|
||||
OnError(7);
|
||||
@@ -480,7 +482,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
memcpy(both + 16, decRndB, 16);
|
||||
uint8_t encBoth[32] = {0x00};
|
||||
if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) {
|
||||
if (DBGLEVEL >= 4) {
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
DbpString("mbedtls_aes_setkey_enc failed");
|
||||
}
|
||||
OnError(7);
|
||||
@@ -517,7 +519,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
}
|
||||
|
||||
OnSuccess();
|
||||
reply_old(CMD_ACK, 1, len, 0, resp, len);
|
||||
reply_mix(CMD_ACK, 1, len, 0, resp, len);
|
||||
}
|
||||
|
||||
// 3 different ISO ways to send data to a DESFIRE (direct, capsuled, capsuled ISO)
|
||||
@@ -534,23 +536,23 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout) {
|
||||
|
||||
wrappedLen = CreateAPDU(cmd, cmd_len, wCmd);
|
||||
|
||||
if (DBGLEVEL >= 4)
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
print_result("WCMD <--: ", wCmd, wrappedLen);
|
||||
|
||||
ReaderTransmit(wCmd, wrappedLen, NULL);
|
||||
|
||||
len = ReaderReceive(resp, par);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= 4) Dbprintf("fukked");
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("fukked");
|
||||
return false; //DATA LINK ERROR
|
||||
}
|
||||
// if we received an I- or R(ACK)-Block with a block number equal to the
|
||||
// current block number, toggle the current block number
|
||||
else if (len >= 4 // PCB+CID+CRC = 4 bytes
|
||||
if (len >= 4 // PCB+CID+CRC = 4 bytes
|
||||
&& ((resp[0] & 0xC0) == 0 // I-Block
|
||||
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
||||
&& (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
|
||||
pcb_blocknum ^= 1; //toggle next block
|
||||
pcb_blocknum ^= 1; //toggle next block
|
||||
}
|
||||
|
||||
memcpy(dataout, resp, len);
|
||||
@@ -565,15 +567,22 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) {
|
||||
uint8_t cmd[cmdlen];
|
||||
memset(cmd, 0, cmdlen);
|
||||
|
||||
cmd[0] = 0x0A; // 0x0A = send cid, 0x02 = no cid.
|
||||
cmd[0] = 0x02; // 0x0A = send cid, 0x02 = no cid.
|
||||
cmd[0] |= pcb_blocknum; // OR the block number into the PCB
|
||||
cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0] );
|
||||
|
||||
cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards
|
||||
|
||||
memcpy(cmd + 2, datain, len);
|
||||
AddCrc14A(cmd, len + 2);
|
||||
|
||||
|
||||
/*
|
||||
hf 14a apdu -sk 90 60 00 00 00
|
||||
hf 14a apdu -k 90 AF 00 00 00
|
||||
hf 14a apdu 90AF000000
|
||||
*/
|
||||
memcpy(dataout, cmd, cmdlen);
|
||||
|
||||
return cmdlen;
|
||||
}
|
||||
|
||||
|
||||
@@ -537,13 +537,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||
|
||||
// find reader field
|
||||
if (cardSTATE == MFEMUL_NOFIELD) {
|
||||
|
||||
|
||||
#if defined RDV4
|
||||
vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
|
||||
#else
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
|
||||
#endif
|
||||
|
||||
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
cardSTATE_TO_IDLE();
|
||||
LED_A_ON();
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
// PRIx64 definition missing with gcc-arm-none-eabi v8?
|
||||
#ifndef PRIx64
|
||||
#define PRIx64 "llx"
|
||||
#endif
|
||||
|
||||
// Basic macros
|
||||
|
||||
#ifndef SHORT_COIL
|
||||
|
||||
Reference in New Issue
Block a user