Merge branch 'master' into allin

update
This commit is contained in:
tharexde
2020-10-22 01:01:59 +02:00
175 changed files with 155010 additions and 25622 deletions

View File

@@ -147,14 +147,18 @@ void RunMod(void) {
int state = STATE_SEARCH;
DbpString("Scanning...");
int button_pressed = BUTTON_NO_CLICK;
for (;;) {
// Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000);
button_pressed = BUTTON_HELD(1000);
if (button_pressed != BUTTON_NO_CLICK || data_available())
break;
else if (state == STATE_SEARCH) {
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelay(500);
continue;
} else {
if (card.sak == SAK && card.atqa[0] == ATQA0 && card.atqa[1] == ATQA1 && card.uidlen == 7) {
@@ -245,6 +249,8 @@ void RunMod(void) {
state = STATE_SEARCH;
}
}
if (button_pressed == BUTTON_HOLD) //Holding down the button
break;
}
DbpString("exiting");

View File

@@ -484,22 +484,18 @@ failtag:
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
SpinOff(50);
LED_A_ON();
uint8_t ticker = 0;
while (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
WDT_HIT();
ticker++;
if (ticker % 64 == 0) {
LED_A_INV();
}
if (BUTTON_HELD(10) == BUTTON_HOLD) {
WDT_HIT();
DbprintfEx(FLAG_NEWLINE, "\t\t\t[ READING FLASH ]");
ReadLastTagFromFlash();
goto readysim;
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(500);
LED_A_INV();
}
SpinOff(50);

View File

@@ -125,7 +125,7 @@ static void download_instructions(uint8_t t) {
case ICE_STATE_FULLSIM: {
DbpString("The emulator memory was saved to SPIFFS");
DbpString("1. " _YELLOW_("mem spiffs dump o " HF_ICLASS_FULLSIM_MOD_BIN " f " HF_ICLASS_FULLSIM_MOD" e"));
DbpString("2. " _YELLOW_("hf iclass view f " HF_ICLASS_FULLSIM_MOD_BIN));
DbpString("2. " _YELLOW_("hf iclass view -f " HF_ICLASS_FULLSIM_MOD_BIN));
break;
}
case ICE_STATE_ATTACK: {
@@ -302,15 +302,17 @@ static int reader_dump_mode(void) {
Iso15693InitReader();
set_tracing(false);
picopass_hdr *hdr = (picopass_hdr *)card_data;
// select tag.
uint32_t eof_time = 0;
bool res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
if (res == false) {
switch_off();
continue;
}
picopass_hdr *hdr = (picopass_hdr *)card_data;
// sanity check of CSN.
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
switch_off();
@@ -366,7 +368,7 @@ static int reader_dump_mode(void) {
auth.use_credit_key = true;
memcpy(auth.key, aa2_key, sizeof(auth.key));
res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
if (res) {
// sanity check of CSN.

View File

@@ -575,4 +575,5 @@ void RunMod(void) {
}
}
}
LEDsoff();
}

View File

@@ -305,6 +305,8 @@ void RunMod(void) {
DbpString("\n"_YELLOW_("!!") "Waiting for a card reader...");
}
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
} else if (state == STATE_EMU) {
LED_A_OFF();
LED_C_ON();

View File

@@ -54,7 +54,7 @@ void RunMod(void) {
for (;;) {
WDT_HIT();
// exit from Standalone Mode, send a usbcommand.
if (data_available()) return;
if (data_available()) break;
SpinDelay(300);
@@ -72,7 +72,7 @@ void RunMod(void) {
for (;;) {
// exit from Standalone Mode, send a usbcommand.
if (data_available()) return;
if (data_available()) break;
if (BUTTON_PRESS()) {
if (cardRead[selected]) {
@@ -89,6 +89,9 @@ void RunMod(void) {
}
if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelay(500);
continue;
} else {
Dbprintf("Read UID:");
@@ -220,7 +223,7 @@ void RunMod(void) {
DbpString("Playing");
for (; ;) {
// exit from Standalone Mode, send a usbcommand.
if (data_available()) return;
if (data_available()) break;
int button_pressed = BUTTON_HELD(1000);
if (button_pressed == BUTTON_NO_CLICK) { // No button action, proceed with sim
@@ -277,4 +280,6 @@ void RunMod(void) {
LED(selected + 1, 0);
}
}
DbpString(_YELLOW_("[=]") "exiting");
LEDsoff();
}

View File

@@ -68,6 +68,24 @@ extern uint32_t _stack_start, _stack_end;
struct common_area common_area __attribute__((section(".commonarea")));
static int button_status = BUTTON_NO_CLICK;
static bool allow_send_wtx = false;
static uint16_t tearoff_delay_us = 0;
static bool tearoff_enabled = false;
int tearoff_hook(void) {
if (tearoff_enabled) {
if (tearoff_delay_us == 0) {
Dbprintf(_RED_("No tear-off delay configured!"));
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
}
SpinDelayUsPrecision(tearoff_delay_us);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
tearoff_enabled = false;
Dbprintf(_YELLOW_("Tear-off triggered!"));
return PM3_ETEAROFF;
} else {
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
}
}
void send_wtx(uint16_t wtx) {
if (allow_send_wtx) {
@@ -731,6 +749,24 @@ static void PacketReceived(PacketCommandNG *packet) {
reply_ng(CMD_SET_DBGMODE, PM3_SUCCESS, NULL, 0);
break;
}
case CMD_SET_TEAROFF: {
struct p {
uint16_t delay_us;
bool on;
bool off;
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
if (payload->on && payload->off)
reply_ng(CMD_SET_TEAROFF, PM3_EINVARG, NULL, 0);
if (payload->on)
tearoff_enabled = true;
if (payload->off)
tearoff_enabled = false;
if (payload->delay_us > 0)
tearoff_delay_us = payload->delay_us;
reply_ng(CMD_SET_TEAROFF, PM3_SUCCESS, NULL, 0);
break;
}
// always available
case CMD_HF_DROPFIELD: {
hf_field_off();
@@ -827,7 +863,8 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_LF_HID_CLONE: {
CopyHIDtoT55x7(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes[0]);
lf_hidsim_t *payload = (lf_hidsim_t *)packet->data.asBytes;
CopyHIDtoT55x7(payload->hi2, payload->hi, payload->lo, payload->longFMT);
break;
}
case CMD_LF_IO_WATCH: {
@@ -933,6 +970,23 @@ static void PacketReceived(PacketCommandNG *packet) {
);
break;
}
case CMD_LF_EM4X_LOGIN: {
struct p {
uint32_t password;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
EM4xLogin(payload->password);
break;
}
case CMD_LF_EM4X_BF: {
struct p {
uint32_t start_pwd;
uint32_t n;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
EM4xBruteforce(payload->start_pwd, payload->n);
break;
}
case CMD_LF_EM4X_READWORD: {
struct p {
uint32_t password;
@@ -954,6 +1008,16 @@ static void PacketReceived(PacketCommandNG *packet) {
EM4xWriteWord(payload->address, payload->data, payload->password, payload->usepwd);
break;
}
case CMD_LF_EM4X_PROTECTWORD: {
struct p {
uint32_t password;
uint32_t data;
uint8_t usepwd;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
EM4xProtectWord(payload->data, payload->password, payload->usepwd);
break;
}
case CMD_LF_AWID_WATCH: {
uint32_t high, low;
int res = lf_awid_watch(0, &high, &low);
@@ -1211,7 +1275,11 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_ISO14443A_ANTIFUZZ: {
iso14443a_antifuzz(packet->oldarg[0]);
struct p {
uint8_t flag;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
iso14443a_antifuzz(payload->flag);
break;
}
case CMD_HF_EPA_COLLECT_NONCE: {
@@ -1442,6 +1510,15 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
break;
}
case CMD_HF_MFU_COUNTER_TEAROFF: {
struct p {
uint8_t counter;
uint32_t tearoff_time;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
MifareU_Counter_Tearoff(payload->counter, payload->tearoff_time);
break;
}
case CMD_HF_MIFARE_STATIC_NONCE: {
MifareHasStaticNonce();
break;
@@ -1472,6 +1549,14 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_ICLASS_SIMULATE: {
/*
struct p {
uint8_t reader[4];
uint8_t mac[4];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
*/
SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
break;
}
@@ -1479,15 +1564,6 @@ static void PacketReceived(PacketCommandNG *packet) {
ReaderIClass(packet->oldarg[0]);
break;
}
case CMD_HF_ICLASS_REPLAY: {
struct p {
uint8_t reader[4];
uint8_t mac[4];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
ReaderIClass_Replay(payload->reader, payload->mac);
break;
}
case CMD_HF_ICLASS_EML_MEMSET: {
//iceman, should call FPGADOWNLOAD before, since it corrupts BigBuf
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@@ -1514,18 +1590,8 @@ static void PacketReceived(PacketCommandNG *packet) {
iClass_Dump(packet->data.asBytes);
break;
}
case CMD_HF_ICLASS_CLONE: {
struct p {
uint8_t startblock;
uint8_t endblock;
uint8_t data[];
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
iClass_Clone(payload->startblock, payload->endblock, payload->data);
break;
}
case CMD_HF_ICLASS_RESTORE: {
iClass_Restore(packet->data.asBytes);
iClass_Restore((iclass_restore_req_t *)packet->data.asBytes);
break;
}
#endif
@@ -1567,7 +1633,11 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_SMART_SETCLOCK: {
SmartCardSetClock(packet->oldarg[0]);
struct p {
uint32_t new_clk;
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
SmartCardSetClock(payload->new_clk);
break;
}
case CMD_SMART_RAW: {

View File

@@ -16,6 +16,8 @@
extern int g_rsamples; // = 0;
extern uint8_t g_trigger;
int tearoff_hook(void);
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
#define MAX_ADC_HF_VOLTAGE 36300
// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV

View File

@@ -14,6 +14,7 @@
#include "lfadc.h"
#include "commonutil.h"
#include "em4x50.h"
#include "appmain.h" // tear
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
@@ -350,6 +351,8 @@ static int find_double_listen_window(bool bcommand) {
if (bcommand) {
// SpinDelay(10);
// data transmission from card has to be stopped, because
// a commamd shall be issued
@@ -953,14 +956,18 @@ static bool write(uint32_t word, uint32_t addresses) {
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
wait_timer0(T0 * EM4X50_T_TAG_TWA);
// look for ACK sequence
if (check_ack(false)) {
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
// now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time)
// for saving data and should return with ACK
if (check_ack(false))
return true;
// look for ACK sequence
if (check_ack(false)) {
// now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time)
// for saving data and should return with ACK
if (check_ack(false))
return PM3_SUCCESS;
}
}
} else {
@@ -968,7 +975,7 @@ static bool write(uint32_t word, uint32_t addresses) {
Dbprintf("error in command request");
}
return false;
return PM3_ESOFT;
}
static bool write_password(uint32_t password, uint32_t new_password) {
@@ -986,9 +993,8 @@ static bool write_password(uint32_t password, uint32_t new_password) {
// wait for T0 * EM4x50_T_TAG_TPP (processing pause time)
wait_timer0(T0 * EM4X50_T_TAG_TPP);
// look for ACK sequence and send rm request
// during following listen window
if (check_ack(true)) {
// wait for T0 * EM4x50_T_TAG_TPP (processing pause time)
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TPP);
// send new password
em4x50_reader_send_word(new_password);
@@ -996,10 +1002,11 @@ static bool write_password(uint32_t password, uint32_t new_password) {
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
wait_timer0(T0 * EM4X50_T_TAG_TWA);
if (check_ack(false))
if (check_ack(false))
return true;
if (check_ack(false))
return PM3_SUCCESS;
}
}
} else {
@@ -1007,7 +1014,7 @@ static bool write_password(uint32_t password, uint32_t new_password) {
Dbprintf("error in command request");
}
return false;
return PM3_ESOFT;
}
void em4x50_write(em4x50_data_t *etd) {
@@ -1031,6 +1038,7 @@ void em4x50_write(em4x50_data_t *etd) {
// write word to given address
if (write(etd->word, etd->addresses)) {
if (res == PM3_SUCCESS) {
// to verify result reset EM4x50
if (reset()) {
@@ -1049,7 +1057,6 @@ void em4x50_write(em4x50_data_t *etd) {
}
status = (bsuccess << 1) + blogin;
lf_finalize();
reply_ng(CMD_ACK, status, (uint8_t *)words, 136);
}
@@ -1071,7 +1078,7 @@ void em4x50_write_password(em4x50_data_t *etd) {
}
lf_finalize();
reply_ng(CMD_ACK, bsuccess, 0, 0);
reply_ng(CMD_LF_EM4X50_WRITE_PASSWORD, bsuccess, 0, 0);
}
void em4x50_wipe(uint32_t *password) {

View File

@@ -99,7 +99,7 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
optimizedSniff((uint16_t *)mem, *len);
if (DBGLEVEL >= DBG_INFO) {
if (DBGLEVEL >= DBG_INFO) {
Dbprintf("Trigger kicked in (%d >= 180)", r);
Dbprintf("Collected %u samples", *len);
}

View File

@@ -47,12 +47,6 @@ static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
#define I2C_DELAY_2CLK I2CSpinDelayClk(2)
#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
#define I2C_DELAY_100us I2CSpinDelayClk( 100 / 3)
#define I2C_DELAY_600us I2CSpinDelayClk( 600 / 3)
#define I2C_DELAY_10ms I2CSpinDelayClk( 10 * 1000 / 3 )
#define I2C_DELAY_30ms I2CSpinDelayClk( 30 * 1000 / 3 )
#define I2C_DELAY_100ms I2CSpinDelayClk( 100 * 1000 / 3)
#define ISO7618_MAX_FRAME 255
// try i2c bus recovery at 100kHz = 5us high, 5us low
@@ -134,11 +128,11 @@ void I2C_Reset_EnterMainProgram(void) {
StartTicks();
I2C_init();
I2C_SetResetStatus(0, 0, 0);
I2C_DELAY_30ms;
WaitMS(30);
I2C_SetResetStatus(1, 0, 0);
I2C_DELAY_30ms;
WaitMS(30);
I2C_SetResetStatus(1, 1, 1);
I2C_DELAY_10ms;
WaitMS(10);
}
// Reset the SIM_Adapter, then enter the bootloader program
@@ -147,9 +141,9 @@ void I2C_Reset_EnterBootloader(void) {
StartTicks();
I2C_init();
I2C_SetResetStatus(0, 1, 1);
I2C_DELAY_100ms;
WaitMS(100);
I2C_SetResetStatus(1, 1, 1);
I2C_DELAY_10ms;
WaitMS(10);
}
// Wait for the clock to go High.
@@ -193,7 +187,7 @@ static bool WaitSCL_L_timeout(void) {
if (!SCL_read)
return true;
I2C_DELAY_100us;
WaitMS(1);
}
return (delay == 0);
}
@@ -440,8 +434,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
// extra wait 500us (514us measured)
// 200us (xx measured)
// WaitUS(600);
I2C_DELAY_600us;
WaitUS(600);
bool bBreak = true;
uint16_t readcount = 0;
@@ -811,8 +804,7 @@ void SmartCardUpgrade(uint64_t arg0) {
}
// writing takes time.
// WaitMS(50);
I2C_DELAY_100ms;
WaitMS(100);
// read
res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
@@ -844,12 +836,10 @@ void SmartCardSetClock(uint64_t arg0) {
LED_D_ON();
set_tracing(true);
I2C_Reset_EnterMainProgram();
// Send SIM CLC
// start [C0 05 xx] stop
I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN);
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
reply_ng(CMD_SMART_SETCLOCK, PM3_SUCCESS, NULL, 0);
set_tracing(false);
LEDsoff();
}

View File

@@ -1276,7 +1276,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *
* @return false = fail
* true = Got all.
*/
static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
@@ -1286,8 +1286,6 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
picopass_hdr *hdr = (picopass_hdr *)card_data;
// Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) will be used
// bit 7: parity.
if (use_credit_key)
@@ -1370,6 +1368,8 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
} else {
// on NON_SECURE_PAGEMODE cards, AIA is on block2..
// read App Issuer Area block 2
read_aia[1] = 0x02;
read_aia[2] = 0x61;
@@ -1385,23 +1385,23 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
if (status) {
*status |= FLAG_ICLASS_AIA;
memcpy(card_data + (8 * 2), resp, 8);
memcpy(hdr->epurse, resp, sizeof(hdr->epurse));
}
}
return true;
}
bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time) {
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time) {
uint8_t result = 0;
return select_iclass_tag_ex(card_data, use_credit_key, eof_time, &result);
return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result);
}
// Reader iClass Anticollission
// turn off afterwards
void ReaderIClass(uint8_t flags) {
uint8_t card_data[6 * 8] = {0xFF};
picopass_hdr hdr = {0};
// uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
memset(resp, 0xFF, sizeof(resp));
@@ -1419,14 +1419,13 @@ void ReaderIClass(uint8_t flags) {
uint8_t result_status = 0;
uint32_t eof_time = 0;
bool status = select_iclass_tag_ex(card_data, use_credit_key, &eof_time, &result_status);
bool status = select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &result_status);
if (status == false) {
reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
reply_mix(CMD_ACK, 0xFF, 0, 0, NULL, 0);
switch_off();
return;
}
// Page mapping for secure mode
// 0 : CSN
// 1 : Configuration
@@ -1444,7 +1443,7 @@ void ReaderIClass(uint8_t flags) {
// with 0xFF:s in block 3 and 4.
LED_B_ON();
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
reply_mix(CMD_ACK, result_status, 0, 0, (uint8_t *)&hdr, sizeof(hdr));
//Send back to client, but don't bother if we already sent this -
// only useful if looping in arm (not try_once && not abort_after_read)
@@ -1470,101 +1469,6 @@ void ReaderIClass(uint8_t flags) {
switch_off();
}
// turn off afterwards
void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac) {
BigBuf_free();
uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(check + 1, rnr, 4);
memcpy(check + 5, mac, 4);
uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE);
if (card_data == NULL) {
DbpString("fail to allocate memory");
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_EMALLOC, NULL, 0);
return;
}
memset(card_data, 0xFF, ICLASS_16KS_SIZE);
uint32_t start_time = 0;
uint32_t eof_time = 0;
Iso15693InitReader();
picopass_hdr hdr = {0};
bool res = select_iclass_tag((uint8_t *)&hdr, false, &eof_time);
if (res == false) {
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0);
switch_off();
return;
}
uint8_t resp[10] = {0};
//for now replay captured auth (as cc not updated)
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
res = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time);
if (res == false) {
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0);
switch_off();
return;
}
uint8_t mem = hdr.conf.mem_config;
uint8_t cardsize = ((mem & 0x80) == 0x80) ? 255 : 32;
/*
static struct memory_t {
int k16;
int book;
int k2;
int lockauth;
int keyaccess;
} memory;
// memory.k16 = ((mem & 0x80) == 0x80);
// memory.book = ((mem & 0x20) == 0x20);
// memory.k2 = ((mem & 0x08) == 0x08);
// memory.lockauth = ((mem & 0x02) == 0x02);
// memory.keyaccess = ((mem & 0x01) == 0x01);
// uint8_t cardsize = memory.k16 ? 255 : 32;
*/
bool dumpsuccess = true;
// main read loop
uint16_t i;
for (i = 0; i <= cardsize; i++) {
uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, i, 0x00, 0x00};
AddCrc(c + 1, 1);
res = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time);
if (res) {
memcpy(card_data + (8 * i), resp, 8);
} else {
Dbprintf("failed to read block %u ( 0x%02x)", i, i);
dumpsuccess = false;
}
}
struct p {
bool isOK;
uint16_t block_cnt;
uint32_t bb_offset;
} PACKED response;
response.isOK = dumpsuccess;
response.block_cnt = i;
response.bb_offset = card_data - BigBuf_get_addr();
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_SUCCESS, (uint8_t *)&response, sizeof(response));
BigBuf_free();
switch_off();
}
// used with function select_and_auth (cmdhficlass.c)
// which needs to authenticate before doing more things like read/write
// selects and authenticate to a card, sends back div_key and mac to client.
@@ -1585,24 +1489,30 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint
memcpy(ccnr, hdr->epurse, sizeof(hdr->epurse));
if (payload->use_raw)
memcpy(div_key, payload->key, 8);
else
iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite);
if (payload->use_replay) {
if (payload->use_credit_key)
memcpy(hdr->key_c, div_key, sizeof(hdr->key_c));
else
memcpy(hdr->key_d, div_key, sizeof(hdr->key_d));
memcpy(pmac, payload->key + 4, 4);
memcpy(cmd_check + 1, payload->key, 8);
opt_doReaderMAC(ccnr, div_key, pmac);
} else {
if (payload->use_raw)
memcpy(div_key, payload->key, 8);
else
iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite);
// copy MAC to check command (readersignature)
cmd_check[5] = pmac[0];
cmd_check[6] = pmac[1];
cmd_check[7] = pmac[2];
cmd_check[8] = pmac[3];
if (payload->use_credit_key)
memcpy(hdr->key_c, div_key, sizeof(hdr->key_c));
else
memcpy(hdr->key_d, div_key, sizeof(hdr->key_d));
opt_doReaderMAC(ccnr, div_key, pmac);
// copy MAC to check command (readersignature)
cmd_check[5] = pmac[0];
cmd_check[6] = pmac[1];
cmd_check[7] = pmac[2];
cmd_check[8] = pmac[3];
}
return iclass_send_cmd_with_retries(cmd_check, sizeof(cmd_check), resp_auth, sizeof(resp_auth), 4, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time);
}
@@ -1632,7 +1542,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
// select card / e-purse
uint8_t card_data[6 * 8] = {0};
picopass_hdr hdr = {0};
iclass_premac_t *keys = (iclass_premac_t *)datain;
@@ -1646,7 +1556,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
uint32_t start_time = 0, eof_time = 0;
if (select_iclass_tag(card_data, use_credit_key, &eof_time) == false)
if (select_iclass_tag(&hdr, use_credit_key, &eof_time) == false)
goto out;
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
@@ -1723,7 +1633,7 @@ void iClass_ReadBlock(uint8_t *msg) {
// select tag.
uint32_t eof_time = 0;
picopass_hdr hdr = {0};
bool res = select_iclass_tag((uint8_t *)&hdr, payload->use_credit_key, &eof_time);
bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time);
if (res == false) {
if (payload->send_reply) {
response.isOK = res;
@@ -1796,7 +1706,7 @@ void iClass_Dump(uint8_t *msg) {
// select tag.
uint32_t eof_time = 0;
picopass_hdr hdr = {0};
bool res = select_iclass_tag((uint8_t *)&hdr, req->use_credit_key, &eof_time);
bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time);
if (res == false) {
if (req->send_reply) {
reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0);
@@ -1866,10 +1776,12 @@ void iClass_Dump(uint8_t *msg) {
BigBuf_free();
}
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data) {
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac) {
// write command: cmd, 1 blockno, 8 data, 4 mac
uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
memcpy(write + 2, data, 12); // data + mac
memcpy(write + 2, data, 8);
memcpy(write + 10, mac, 4);
AddCrc(write + 1, 13);
uint8_t resp[10] = {0};
@@ -1914,7 +1826,7 @@ void iClass_WriteBlock(uint8_t *msg) {
// select tag.
uint32_t eof_time = 0;
picopass_hdr hdr = {0};
bool res = select_iclass_tag((uint8_t *)&hdr, payload->req.use_credit_key, &eof_time);
bool res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time);
if (res == false) {
goto out;
}
@@ -1937,10 +1849,14 @@ void iClass_WriteBlock(uint8_t *msg) {
wb[0] = payload->req.blockno;
memcpy(wb + 1, payload->data, 8);
if (payload->req.use_credit_key)
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
else
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
if (payload->req.use_replay) {
doMAC_N(wb, sizeof(wb), payload->req.key + 4, mac);
} else {
if (payload->req.use_credit_key)
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
else
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
}
memcpy(write + 2, payload->data, 8); // data
memcpy(write + 10, mac, sizeof(mac)); // mac
@@ -1949,8 +1865,29 @@ void iClass_WriteBlock(uint8_t *msg) {
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
uint8_t resp[10] = {0};
res = iclass_send_cmd_with_retries(write, sizeof(write), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time);
if (res == false) {
uint8_t tries = 3;
while (tries-- > 0) {
iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
res = false;
switch_off();
if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
return;
} else {
if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time) == 10) {
res = true;
break;
}
}
}
if (tries == 0) {
res = false;
goto out;
}
@@ -1983,29 +1920,75 @@ out:
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
}
// turn off afterwards
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
}
void iClass_Restore(iclass_restore_req_t *msg) {
void iClass_Restore(uint8_t *msg) {
// sanitation
if (msg == NULL) {
reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
return;
}
iclass_restore_req_t *cmd = (iclass_restore_req_t *)msg;
// iclass_auth_req_t *req = &cmd->req;
if (msg->item_cnt == 0) {
if (msg->req.send_reply) {
reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
}
return;
}
LED_A_ON();
uint16_t written = 0;
uint16_t total_blocks = (cmd->end_block - cmd->start_block) + 1;
for (uint8_t b = cmd->start_block; b < total_blocks; b++) {
Iso15693InitReader();
if (iclass_writeblock_ext(b, cmd->data + ((b - cmd->start_block) * 12))) {
Dbprintf("Write block [%02x] successful", b);
written++;
} else {
Dbprintf("Write block [%02x] failed", b);
uint16_t written = 0;
uint32_t eof_time = 0;
picopass_hdr hdr = {0};
// select
bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time);
if (res == false) {
goto out;
}
// authenticate
uint8_t mac[4] = {0};
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
// authenticate
if (msg->req.do_auth) {
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac);
if (res == false) {
goto out;
}
}
// main loop
for (uint8_t i = 0; i < msg->item_cnt; i++) {
iclass_restore_item_t item = msg->blocks[i];
// calc new mac for data, using 1b blockno, 8b data,
uint8_t wb[9] = {0};
wb[0] = item.blockno;
memcpy(wb + 1, item.data, 8);
if (msg->req.use_credit_key)
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
else
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
// data + mac
if (iclass_writeblock_ext(item.blockno, item.data, mac)) {
Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno);
written++;
} else {
Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno);
}
}
out:
switch_off();
uint8_t isOK = (written == total_blocks) ? 1 : 0;
reply_ng(CMD_HF_ICLASS_CLONE, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t));
if (msg->req.send_reply) {
int isOK = (written == msg->item_cnt) ? PM3_SUCCESS : PM3_ESOFT;
reply_ng(CMD_HF_ICLASS_RESTORE, isOK, NULL, 0);
}
}

View File

@@ -17,13 +17,11 @@
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
void ReaderIClass(uint8_t arg0);
void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac);
void iClass_WriteBlock(uint8_t *msg);
void iClass_Dump(uint8_t *msg);
void iClass_Restore(uint8_t *msg);
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
void iClass_Restore(iclass_restore_req_t *msg);
int do_iclass_simulation_nonsec(void);
int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf);
@@ -37,6 +35,6 @@ bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
void iClass_ReadBlock(uint8_t *msg);
bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time);
bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time);
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time);
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
#endif

View File

@@ -134,11 +134,36 @@ static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config"));
Dbprintf("[a] Anticol override......%i: %s%s%s", hf14aconfig.forceanticol, (hf14aconfig.forceanticol == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forceanticol == 1) ? _RED_("Yes: Always do anticol") : "", (hf14aconfig.forceanticol == 2) ? _RED_("Yes: Always skip anticol") : "");
Dbprintf("[b] BCC override..........%i: %s%s%s", hf14aconfig.forcebcc, (hf14aconfig.forcebcc == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcebcc == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcebcc == 2) ? _RED_("Yes: Always use card BCC") : "");
Dbprintf("[2] CL2 override..........%i: %s%s%s", hf14aconfig.forcecl2, (hf14aconfig.forcecl2 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl2 == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2 == 2) ? _RED_("Yes: Always skip CL2") : "");
Dbprintf("[3] CL3 override..........%i: %s%s%s", hf14aconfig.forcecl3, (hf14aconfig.forcecl3 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl3 == 1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3 == 2) ? _RED_("Yes: Always skip CL3") : "");
Dbprintf("[r] RATS override.........%i: %s%s%s", hf14aconfig.forcerats, (hf14aconfig.forcerats == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcerats == 1) ? _RED_("Yes: Always do RATS") : "", (hf14aconfig.forcerats == 2) ? _RED_("Yes: Always skip RATS") : "");
Dbprintf(" [a] Anticol override....%i %s%s%s",
hf14aconfig.forceanticol,
(hf14aconfig.forceanticol == 0) ? "( " _GREEN_("No") " ) follow standard " : "",
(hf14aconfig.forceanticol == 1) ? "( " _RED_("Yes") " ) always do anticol" : "",
(hf14aconfig.forceanticol == 2) ? "( " _RED_("Yes") " ) always skip anticol" : ""
);
Dbprintf(" [b] BCC override........%i %s%s%s",
hf14aconfig.forcebcc,
(hf14aconfig.forcebcc == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
(hf14aconfig.forcebcc == 1) ? "( " _RED_("Yes") " ) always do CL2" : "",
(hf14aconfig.forcebcc == 2) ? "( " _RED_("Yes") " ) always use card BCC" : ""
);
Dbprintf(" [2] CL2 override........%i %s%s%s",
hf14aconfig.forcecl2,
(hf14aconfig.forcecl2 == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
(hf14aconfig.forcecl2 == 1) ? "( " _RED_("Yes") " ) always do CL2" : "",
(hf14aconfig.forcecl2 == 2) ? "( " _RED_("Yes") " ) always skip CL2" : ""
);
Dbprintf(" [3] CL3 override........%i %s%s%s",
hf14aconfig.forcecl3,
(hf14aconfig.forcecl3 == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
(hf14aconfig.forcecl3 == 1) ? "( " _RED_("Yes") " ) always do CL3" : "",
(hf14aconfig.forcecl3 == 2) ? "( " _RED_("Yes") " ) always skip CL3" : ""
);
Dbprintf(" [r] RATS override.......%i %s%s%s",
hf14aconfig.forcerats,
(hf14aconfig.forcerats == 0) ? "( " _GREEN_("No") " q follow standard " : "",
(hf14aconfig.forcerats == 1) ? "( " _RED_("Yes") " ) always do RATS" : "",
(hf14aconfig.forcerats == 2) ? "( " _RED_("Yes") " ) always skip RATS" : ""
);
}
/**
@@ -2365,7 +2390,7 @@ void iso14443a_antifuzz(uint32_t flags) {
}
}
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
reply_ng(CMD_HF_ISO14443A_ANTIFUZZ, PM3_SUCCESS, NULL, 0);
switch_off();
BigBuf_free_keep_EM();
}
@@ -2599,13 +2624,13 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
} // else force RATS
// RATS, Request for answer to select
if (!no_rats) {
uint8_t rats[] = { ISO14443A_CMD_RATS, 0x80, 0x00, 0x00 }; // FSD=256, FSDI=8, CID=0
if (no_rats == false) {
uint8_t rats[] = { ISO14443A_CMD_RATS, 0x80, 0x00, 0x00 }; // FSD=256, FSDI=8, CID=0
AddCrc14A(rats, 2);
ReaderTransmit(rats, sizeof(rats), NULL);
int len = ReaderReceive(resp, resp_par);
if (!len) return 0;
if (len == 0)
return 0;
if (p_card) {
memcpy(p_card->ats, resp, sizeof(p_card->ats));
@@ -2687,7 +2712,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
LED_D_ON();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
SpinDelay(100);
SpinDelay(50);
// Start the timer
StartCountSspClk();
@@ -2904,10 +2929,15 @@ void ReaderIso14443a(PacketCommandNG *c) {
ReaderTransmit(cmd, len, NULL); // 8 bits, odd parity
}
}
arg0 = ReaderReceive(buf, par);
FpgaDisableTracing();
reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
FpgaDisableTracing();
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
} else {
arg0 = ReaderReceive(buf, par);
FpgaDisableTracing();
reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
}
}
if ((param & ISO14A_REQUEST_TRIGGER))

View File

@@ -752,26 +752,26 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
// The soft decision on the bit uses an estimate of just the
// quadrant of the reference angle, not the exact angle.
#define MAKE_SOFT_DECISION() { \
if(Demod.sumI > 0) { \
v = ci; \
} else { \
v = -ci; \
} \
if(Demod.sumQ > 0) { \
v += cq; \
} else { \
v -= cq; \
} \
}
if(Demod.sumI > 0) { \
v = ci; \
} else { \
v = -ci; \
} \
if(Demod.sumQ > 0) { \
v += cq; \
} else { \
v -= cq; \
} \
}
#define SUBCARRIER_DETECT_THRESHOLD 8
#define SUBCARRIER_DETECT_THRESHOLD 8
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
switch (Demod.state) {
case DEMOD_UNSYNCD: {
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
Demod.state = DEMOD_PHASE_REF_TRAINING;
Demod.sumI = ci;
Demod.sumQ = cq;
@@ -783,7 +783,8 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
// While we get a constant signal
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
if (((ABS(Demod.sumI) > ABS(Demod.sumQ)) && (((ci > 0) && (Demod.sumI > 0)) || ((ci < 0) && (Demod.sumI < 0)))) || // signal closer to horizontal, polarity check based on on I
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
if (Demod.posCount < 10) { // refine signal approximation during first 10 samples
Demod.sumI += ci;
Demod.sumQ += cq;
@@ -798,7 +799,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
} else {
// at this point it can be start of 14b' data or start of 14b SOF
MAKE_SOFT_DECISION();
Demod.posCount = 1; // this was the first half
Demod.posCount = 1; // this was the first half
Demod.thisBit = v;
Demod.shiftReg = 0;
Demod.state = DEMOD_RECEIVING_DATA;
@@ -814,7 +815,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
Demod.posCount++;
MAKE_SOFT_DECISION();
if (v > 0) {
if (Demod.posCount > 3 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
if (Demod.posCount > 3 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
LED_C_OFF();
if (Demod.bitCount == 0 && Demod.len == 0) { // received SOF only, this is valid for iClass/Picopass
return true;
@@ -822,8 +823,8 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
Demod.state = DEMOD_UNSYNCD;
}
}
} else { // start bit detected
Demod.posCount = 1; // this was the first half
} else { // start bit detected
Demod.posCount = 1; // this was the first half
Demod.thisBit = v;
Demod.shiftReg = 0;
Demod.state = DEMOD_RECEIVING_DATA;
@@ -856,14 +857,14 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
MAKE_SOFT_DECISION();
if (Demod.posCount == 0) { // first half of bit
if (Demod.posCount == 0) { // first half of bit
Demod.thisBit = v;
Demod.posCount = 1;
} else { // second half of bit
} else { // second half of bit
Demod.thisBit += v;
Demod.shiftReg >>= 1;
if (Demod.thisBit > 0) { // logic '1'
if (Demod.thisBit > 0) { // logic '1'
Demod.shiftReg |= 0x200;
}
@@ -926,12 +927,12 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
* Demodulate the samples we received from the tag, also log to tracebuffer
*/
static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeout, uint32_t *eof_time) {
int samples = 0, ret = 0;
// Set up the demodulator for tag -> reader responses.
Demod14bInit(response, max_len);
// Setup and start DMA.
//FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
@@ -995,7 +996,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
if (Handle14443bSamplesFromTag(ci, cq)) {
*eof_time = dma_start_time + (samples ) - DELAY_TAG_TO_ARM; // end of EOF
*eof_time = dma_start_time + (samples) - DELAY_TAG_TO_ARM; // end of EOF
if (Demod.len > Demod.max_len) {
ret = -2; // overflow
@@ -1043,7 +1044,7 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
if (GetCountSspClk() > *start_time) { // we may miss the intended time
*start_time = (GetCountSspClk() + 32) & 0xfffffff0; // next possible time
}
// wait
while (GetCountSspClk() < *start_time);
@@ -1067,7 +1068,7 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
LED_B_OFF();
*start_time += DELAY_ARM_TO_TAG;
// wait for last transfer to complete
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) {};
}
@@ -1092,7 +1093,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
*
* QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode?
* 1 "stuffbit" = 1ETU (9us)
*
*
* TR2 - After the PICC response, the PCD is required to wait the Frame Delay Time (TR2)
before transmission of the next command. The minimum frame delay time required for
all commands is 14 ETUs
@@ -1100,10 +1101,10 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
*/
int i;
tosend_reset();
// Send SOF
// 10-11 ETUs of ZERO
for (i = 0; i < 10; i++) {
for (i = 0; i < 11; i++) {
tosend_stuffbit(0);
}
// 2-3 ETUs of ONE
@@ -1132,23 +1133,21 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// EGT extra guard time 1 ETU = 9us
// For PCD it ranges 0-57us === 0 - 6 ETU
// FOR PICC it ranges 0-19us == 0 - 2 ETU
}
// Send EOF
// 10-11 ETUs of ZERO
for (i = 0; i < 10; i++) {
for (i = 0; i < 11; i++) {
tosend_stuffbit(0);
}
tosend_stuffbit(1);
/* Transition time. TR0 - guard time
* TR0 - 8 ETU's minimum.
* TR0 - 32 ETU's maximum for ATQB only
* TR0 - FWT for all other commands
* 32,64,128,256,512, ... , 262144, 524288 ETU
*/
int pad = (12 + (len * 10) + 11) & 0x7;
int pad = (11 + 2 + (len * 10) + 11) & 0x7;
for (i = 0; i < 16 - pad; ++i)
tosend_stuffbit(1);
@@ -1186,7 +1185,7 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void
real_cmd[0] = 0xA2; // r-block + ACK
real_cmd[0] |= iso14b_pcb_blocknum;
}
AddCrc14B(real_cmd, msg_len + 1);
// send
@@ -1270,7 +1269,7 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
AddCrc14B(cmdLSBUID, 1);
uint8_t r[8];
uint32_t start_time = 0;
uint32_t eof_time = 0;
CodeAndTransmit14443bAsReader(cmdINIT, sizeof(cmdINIT), &start_time, &eof_time);
@@ -1524,7 +1523,7 @@ void iso14443b_setup(void) {
// Signal field is on with the appropriate LED
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
SpinDelay(100);
SpinDelay(50);
// Start the timer
StartCountSspClk();
@@ -1841,17 +1840,21 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) {
iso14443b_setup();
clear_trace();
}
if ((param & ISO14B_SET_TIMEOUT))
if ((param & ISO14B_SET_TIMEOUT) == ISO14B_SET_TIMEOUT) {
iso14b_set_timeout(timeout);
}
if ((param & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) {
clear_trace();
}
set_tracing(true);
int status;
uint32_t sendlen = sizeof(iso14b_card_select_t);
iso14b_card_select_t card;
memset((void *)&card, 0x00, sizeof(card));
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
status = iso14443b_select_card(&card);
@@ -1874,7 +1877,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&cts, sendlen);
// 0: OK 2: demod fail, 3:crc fail,
if (status > 0) goto out;
}
}
if ((param & ISO14B_APDU) == ISO14B_APDU) {
uint8_t res;
@@ -1892,12 +1895,17 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
uint32_t eof_time = 0;
CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time);
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
FpgaDisableTracing();
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
FpgaDisableTracing();
reply_mix(CMD_HF_ISO14443B_COMMAND, -2, 0, 0, NULL, 0);
} else {
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
FpgaDisableTracing();
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen);
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen);
}
}
out:

View File

@@ -290,6 +290,7 @@ void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) {
LED_B_OFF();
*start_time = *start_time + DELAY_ARM_TO_TAG;
FpgaDisableTracing();
}
//-----------------------------------------------------------------------------
@@ -732,6 +733,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
}
FpgaDisableSscDma();
FpgaDisableTracing();
uint32_t sof_time = *eof_time
- (dt->len * 8 * 8 * 16) // time for byte transfers
@@ -1469,15 +1471,21 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
// low speed (1 out of 256)
CodeIso15693AsReader256(send, sendlen);
}
int res = 0;
tosend_t *ts = get_tosend();
TransmitTo15693Tag(ts->buf, ts->max, &start_time);
*eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF
LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true);
int res = 0;
if (recv != NULL) {
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
res = PM3_ETEAROFF;
} else {
*eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF
LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true);
if (recv != NULL) {
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
}
}
return res;
}
@@ -1586,41 +1594,49 @@ void ReaderIso15693(uint32_t parameter) {
BuildIdentifyRequest(cmd);
uint32_t start_time = 0;
uint32_t eof_time;
int answerLen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time);
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
int recvlen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time);
// we should do a better check than this
if (answerLen >= 12) {
uint8_t uid[8];
uid[0] = answer[9]; // always E0
uid[1] = answer[8]; // IC Manufacturer code
uid[2] = answer[7];
uid[3] = answer[6];
uid[4] = answer[5];
uid[5] = answer[4];
uid[6] = answer[3];
uid[7] = answer[2];
if (recvlen == PM3_ETEAROFF) { // tearoff occured
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
} else {
if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
uid[0], uid[1], uid[2], uid[3],
uid[4], uid[5], uid[5], uid[6]
);
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
// we should do a better check than this
if (recvlen >= 12) {
uint8_t uid[8];
uid[0] = answer[9]; // always E0
uid[1] = answer[8]; // IC Manufacturer code
uid[2] = answer[7];
uid[3] = answer[6];
uid[4] = answer[5];
uid[5] = answer[4];
uid[6] = answer[3];
uid[7] = answer[2];
if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
uid[0], uid[1], uid[2], uid[3],
uid[4], uid[5], uid[5], uid[6]
);
}
// send UID back to client.
// arg0 = 1 = OK
// arg1 = len of response (12 bytes)
// arg2 = rtf
// asbytes = uid.
reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("[+] %d octets read from IDENTIFY request:", recvlen);
DbdecodeIso15693Answer(recvlen, answer);
Dbhexdump(recvlen, answer, true);
}
} else {
DbpString("Failed to select card");
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
}
// send UID back to client.
// arg0 = 1 = OK
// arg1 = len of response (12 bytes)
// arg2 = rtf
// asbytes = uid.
reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
}
if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen);
DbdecodeIso15693Answer(answerLen, answer);
Dbhexdump(answerLen, answer, true);
}
switch_off();
BigBuf_free();
}
@@ -1765,6 +1781,11 @@ void BruteforceIso15693Afi(uint32_t speed) {
if (recvlen >= 12) {
Dbprintf("NoAFI UID = %s", iso15693_sprintUID(NULL, recv + 2));
} else {
DbpString("Failed to select card");
reply_ng(CMD_ACK, PM3_ESOFT, NULL, 0);
switch_off();
return;
}
// now with AFI
@@ -1814,10 +1835,9 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
LED_A_ON();
int recvlen = 0;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint32_t eof_time = 0;
uint16_t timeout;
uint32_t eof_time = 0;
bool request_answer = false;
switch (data[1]) {
@@ -1835,43 +1855,29 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
timeout = ISO15693_READER_TIMEOUT;
}
if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("SEND:");
Dbhexdump(datalen, data, false);
}
uint32_t start_time = 0;
recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time);
int recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time);
// send a single EOF to get the tag response
if (request_answer) {
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time);
if (recvlen == PM3_ETEAROFF) { // tearoff occured
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
} else {
// send a single EOF to get the tag response
if (request_answer) {
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time);
}
if (recv) {
recvlen = MIN(recvlen, ISO15693_MAX_RESPONSE_LENGTH);
reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
} else {
reply_mix(CMD_ACK, 1, 0, 0, NULL, 0);
}
}
// for the time being, switch field off to protect rdv4.0
// note: this prevents using hf 15 cmd with s option - which isn't implemented yet anyway
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
if (recv) {
if (recvlen > ISO15693_MAX_RESPONSE_LENGTH) {
recvlen = ISO15693_MAX_RESPONSE_LENGTH;
}
reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("RECV:");
if (recvlen > 0) {
Dbhexdump(recvlen, recvbuf, false);
DbdecodeIso15693Answer(recvlen, recvbuf);
}
}
} else {
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
}
}
/*
@@ -1881,112 +1887,112 @@ void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
LED_A_ON();
uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 };
uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 };
uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//uint8_t cmd_write_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t cmd_lock_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 };
uint16_t crc;
int recvlen = 0;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint32_t start_time = 0;
bool done = false;
uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 };
uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 };
uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//uint8_t cmd_write_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t cmd_lock_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 };
uint16_t crc;
int recvlen = 0;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint32_t start_time = 0;
bool done = false;
// setup 'get random number' command
crc = Iso15693Crc(cmd_get_rnd, 3);
cmd_get_rnd[3] = crc & 0xff;
cmd_get_rnd[4] = crc >> 8;
// setup 'get random number' command
crc = Iso15693Crc(cmd_get_rnd, 3);
cmd_get_rnd[3] = crc & 0xff;
cmd_get_rnd[4] = crc >> 8;
Dbprintf("LockPass: Press button lock password, long-press to terminate.");
Dbprintf("LockPass: Press button lock password, long-press to terminate.");
while (!done) {
while (!done) {
LED_D_ON();
switch(BUTTON_HELD(1000)) {
case BUTTON_SINGLE_CLICK:
Dbprintf("LockPass: Reset 'DONE'-LED (A)");
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
break;
case BUTTON_HOLD:
Dbprintf("LockPass: Terminating");
done = true;
break;
default:
SpinDelay(50);
continue;
}
LED_D_ON();
switch(BUTTON_HELD(1000)) {
case BUTTON_SINGLE_CLICK:
Dbprintf("LockPass: Reset 'DONE'-LED (A)");
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
break;
case BUTTON_HOLD:
Dbprintf("LockPass: Terminating");
done = true;
break;
default:
SpinDelay(50);
continue;
}
if (done) [
break;
}
if (done) [
break;
}
recvlen = SendDataTag(cmd_get_rnd, sizeof(cmd_get_rnd), true, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 5) {
LED_C_ON();
} else {
Dbprintf("LockPass: Received random 0x%02X%02X (%d)", recvbuf[1], recvbuf[2], recvlen);
recvlen = SendDataTag(cmd_get_rnd, sizeof(cmd_get_rnd), true, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 5) {
LED_C_ON();
} else {
Dbprintf("LockPass: Received random 0x%02X%02X (%d)", recvbuf[1], recvbuf[2], recvlen);
// setup 'set password' command
cmd_set_pass[4] = ((password>>0) &0xFF) ^ recvbuf[1];
cmd_set_pass[5] = ((password>>8) &0xFF) ^ recvbuf[2];
cmd_set_pass[6] = ((password>>16) &0xFF) ^ recvbuf[1];
cmd_set_pass[7] = ((password>>24) &0xFF) ^ recvbuf[2];
// setup 'set password' command
cmd_set_pass[4] = ((password>>0) &0xFF) ^ recvbuf[1];
cmd_set_pass[5] = ((password>>8) &0xFF) ^ recvbuf[2];
cmd_set_pass[6] = ((password>>16) &0xFF) ^ recvbuf[1];
cmd_set_pass[7] = ((password>>24) &0xFF) ^ recvbuf[2];
crc = Iso15693Crc(cmd_set_pass, 8);
cmd_set_pass[8] = crc & 0xff;
cmd_set_pass[9] = crc >> 8;
crc = Iso15693Crc(cmd_set_pass, 8);
cmd_set_pass[8] = crc & 0xff;
cmd_set_pass[9] = crc >> 8;
Dbprintf("LockPass: Sending old password to end privacy mode", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7]);
recvlen = SendDataTag(cmd_set_pass, sizeof(cmd_set_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to set password (%d)", recvlen);
LED_B_ON();
} else {
crc = Iso15693Crc(cmd_inventory, 3);
cmd_inventory[3] = crc & 0xff;
cmd_inventory[4] = crc >> 8;
Dbprintf("LockPass: Sending old password to end privacy mode", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7]);
recvlen = SendDataTag(cmd_set_pass, sizeof(cmd_set_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to set password (%d)", recvlen);
LED_B_ON();
} else {
crc = Iso15693Crc(cmd_inventory, 3);
cmd_inventory[3] = crc & 0xff;
cmd_inventory[4] = crc >> 8;
Dbprintf("LockPass: Searching for tag...");
recvlen = SendDataTag(cmd_inventory, sizeof(cmd_inventory), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 12) {
Dbprintf("LockPass: Failed to read inventory (%d)", recvlen);
LED_B_ON();
LED_C_ON();
} else {
Dbprintf("LockPass: Searching for tag...");
recvlen = SendDataTag(cmd_inventory, sizeof(cmd_inventory), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 12) {
Dbprintf("LockPass: Failed to read inventory (%d)", recvlen);
LED_B_ON();
LED_C_ON();
} else {
Dbprintf("LockPass: Answer from %02X%02X%02X%02X%02X%02X%02X%02X", recvbuf[9], recvbuf[8], recvbuf[7], recvbuf[6], recvbuf[5], recvbuf[4], recvbuf[3], recvbuf[2]);
Dbprintf("LockPass: Answer from %02X%02X%02X%02X%02X%02X%02X%02X", recvbuf[9], recvbuf[8], recvbuf[7], recvbuf[6], recvbuf[5], recvbuf[4], recvbuf[3], recvbuf[2]);
memcpy(&cmd_lock_pass[3], &recvbuf[2], 8);
memcpy(&cmd_lock_pass[3], &recvbuf[2], 8);
cmd_lock_pass[8+3] = pass_id;
cmd_lock_pass[8+3] = pass_id;
crc = Iso15693Crc(cmd_lock_pass, 8+4);
cmd_lock_pass[8+4] = crc & 0xff;
cmd_lock_pass[8+5] = crc >> 8;
crc = Iso15693Crc(cmd_lock_pass, 8+4);
cmd_lock_pass[8+4] = crc & 0xff;
cmd_lock_pass[8+5] = crc >> 8;
Dbprintf("LockPass: locking to password 0x%02X%02X%02X%02X for ID %02X", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7], pass_id);
Dbprintf("LockPass: locking to password 0x%02X%02X%02X%02X for ID %02X", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7], pass_id);
recvlen = SendDataTag(cmd_lock_pass, sizeof(cmd_lock_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to lock password (%d)", recvlen);
} else {
Dbprintf("LockPass: Successful (%d)", recvlen);
}
LED_A_ON();
}
} }
}
recvlen = SendDataTag(cmd_lock_pass, sizeof(cmd_lock_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to lock password (%d)", recvlen);
} else {
Dbprintf("LockPass: Successful (%d)", recvlen);
}
LED_A_ON();
}
} }
}
Dbprintf("LockPass: Finishing");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
Dbprintf("LockPass: Finishing");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
cmd_send(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
}
*/

View File

@@ -2369,6 +2369,7 @@ int copy_em410x_to_t55xx(uint8_t card, uint8_t clock, uint32_t id_hi, uint32_t i
#define FWD_CMD_LOGIN 0xC
#define FWD_CMD_WRITE 0xA
#define FWD_CMD_READ 0x9
#define FWD_CMD_PROTECT 0x3
#define FWD_CMD_DISABLE 0x5
static uint8_t forwardLink_data[64]; //array of forwarded bits
@@ -2466,7 +2467,7 @@ static uint8_t Prepare_Data(uint16_t data_low, uint16_t data_hi) {
// Requires: forwarLink_data filled with valid bits (1 bit per byte)
// fwd_bit_count set with number of bits to be sent
//====================================================================
static void SendForward(uint8_t fwd_bit_count) {
static void SendForward(uint8_t fwd_bit_count, bool fast) {
// iceman, 21.3us increments for the USclock verification.
// 55FC * 8us == 440us / 21.3 === 20.65 steps. could be too short. Go for 56FC instead
@@ -2479,9 +2480,10 @@ static void SendForward(uint8_t fwd_bit_count) {
fwd_write_ptr = forwardLink_data;
fwd_bit_sz = fwd_bit_count;
// Set up FPGA, 125kHz or 95 divisor
LFSetupFPGAForADC(LF_DIVISOR_125, true);
if (! fast) {
// Set up FPGA, 125kHz or 95 divisor
LFSetupFPGAForADC(LF_DIVISOR_125, true);
}
// force 1st mod pulse (start gap must be longer for 4305)
fwd_bit_sz--; //prepare next bit modulation
fwd_write_ptr++;
@@ -2489,28 +2491,98 @@ static void SendForward(uint8_t fwd_bit_count) {
TurnReadLF_off(EM_START_GAP);
TurnReadLFOn(18 * 8);
// now start writting with bitbanging the antenna. (each bit should be 32*8 total length)
// now start writing 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((32 - 23) * 8);
TurnReadLFOn(18 * 8);
}
}
}
static void EM4xLogin(uint32_t pwd) {
static void EM4xLoginEx(uint32_t pwd) {
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
SendForward(len);
SendForward(len, false);
//WaitUS(20); // no wait for login command.
// should receive
// 0000 1010 ok
// 0000 0001 fail
}
void EM4xBruteforce(uint32_t start_pwd, uint32_t n) {
// With current timing, 18.6 ms per test = 53.8 pwds/s
reply_ng(CMD_LF_EM4X_BF, PM3_SUCCESS, NULL, 0);
StartTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitMS(20);
LED_A_ON();
LFSetupFPGAForADC(LF_DIVISOR_125, true);
uint32_t candidates_found = 0;
for (uint32_t pwd = start_pwd; pwd < 0xFFFFFFFF; pwd++) {
if (((pwd - start_pwd) & 0x3F) == 0x00) {
WDT_HIT();
if (BUTTON_PRESS() || data_available()) {
Dbprintf("EM4x05 Bruteforce Interrupted");
break;
}
}
// Report progress every 256 attempts
if (((pwd - start_pwd) & 0xFF) == 0x00) {
Dbprintf("Trying: %06Xxx", pwd >> 8);
}
clear_trace();
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
SendForward(len, true);
WaitUS(400);
DoPartialAcquisition(0, false, 350, 1000);
uint8_t *mem = BigBuf_get_addr();
if (mem[334] < 128) {
candidates_found++;
Dbprintf("Password candidate: " _GREEN_("%08X"), pwd);
if ((n != 0) && (candidates_found == n)) {
Dbprintf("EM4x05 Bruteforce Stopped. %i candidate%s found", candidates_found, candidates_found > 1 ? "s" : "");
break;
}
}
// Beware: if smaller, tag might not have time to be back in listening state yet
WaitMS(1);
}
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void EM4xLogin(uint32_t pwd) {
StartTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitMS(20);
LED_A_ON();
// clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
EM4xLoginEx(pwd);
WaitUS(400);
// We need to acquire more than needed, to help demodulators finding the proper modulation
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_LOGIN, PM3_SUCCESS, NULL, 0);
LEDsoff();
}
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
StartTicks();
@@ -2528,17 +2600,17 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
* 0000 1010 ok
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
if (usepwd) EM4xLoginEx(pwd);
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
len += Prepare_Addr(addr);
SendForward(len);
SendForward(len, false);
WaitUS(400);
DoPartialAcquisition(20, false, 6000, 1000);
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@@ -2563,23 +2635,70 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
* 0000 1010 ok.
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
if (usepwd) EM4xLoginEx(pwd);
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
len += Prepare_Addr(addr);
len += Prepare_Data(data & 0xFFFF, data >> 16);
SendForward(len);
SendForward(len, false);
// Wait 20ms for write to complete?
WaitMS(7);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
StopTicks();
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_ETEAROFF, NULL, 0);
} else {
// Wait 20ms for write to complete?
// No, when write is denied, err preamble comes much sooner
//WaitUS(10820); // tPC+tWEE
DoPartialAcquisition(20, false, 6000, 1000);
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
}
LEDsoff();
}
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
StartTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
WaitMS(50);
LED_A_ON();
// clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
/* should we read answer from Logincommand?
*
* should receive
* 0000 1010 ok.
* 0000 0001 fail
**/
if (usepwd) EM4xLoginEx(pwd);
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
len += Prepare_Data(data & 0xFFFF, data >> 16);
SendForward(len, false);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
StopTicks();
reply_ng(CMD_LF_EM4X_PROTECTWORD, PM3_ETEAROFF, NULL, 0);
} else {
// Wait 20ms for write to complete?
// No, when write is denied, err preamble comes much sooner
//WaitUS(13640); // tPC+tPR
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_PROTECTWORD, PM3_SUCCESS, NULL, 0);
}
LEDsoff();
}

View File

@@ -56,8 +56,11 @@ void T55xxDangerousRawTest(uint8_t *data);
void TurnReadLFOn(uint32_t delay);
void EM4xLogin(uint32_t pwd);
void EM4xBruteforce(uint32_t start_pwd, uint32_t n);
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);
void Cotag(uint32_t arg0);
void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c);

View File

@@ -2695,32 +2695,30 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
//
// Tear-off attack against MFU.
// - Moebius et al
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t tearoff_time, uint8_t *datain) {
uint8_t blockNo = arg0;
uint32_t tearOffTime = arg1;
uint8_t data_fullwrite[4] = {0x00};
uint8_t data_testwrite[4] = {0x00};
memcpy(data_fullwrite, datain, 4);
memcpy(data_testwrite, datain + 4, 4);
// optional authentication before?
if (DBGLEVEL >= DBG_ERROR) DbpString("Preparing OTP tear-off");
if (DBGLEVEL >= DBG_DEBUG) DbpString("Preparing OTP tear-off");
if (tearoff_time > 43000)
tearoff_time = 43000;
MifareUWriteBlock(blockNo, 0, data_fullwrite);
LEDsoff();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(true);
StartTicks();
// write cmd to send, include CRC
// 1b write, 1b block, 4b data, 2 crc
uint8_t cmd[] = {MIFARE_ULC_WRITE, blockNo, data_testwrite[0], data_testwrite[1], data_testwrite[2], data_testwrite[3], 0, 0};
MifareUWriteBlock(blockNo, 0, data_fullwrite);
AddCrc14A(cmd, sizeof(cmd) - 2);
if (DBGLEVEL >= DBG_ERROR) DbpString("Transmitting");
// anticollision / select card
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
@@ -2732,11 +2730,51 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
// Wait before cutting power. aka tear-off
LED_D_ON();
WaitUS(tearOffTime);
SpinDelayUsPrecision(tearoff_time);
if (DBGLEVEL >= DBG_DEBUG) Dbprintf(_YELLOW_("OTP tear-off triggered!"));
switch_off();
reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_SUCCESS, NULL, 0);
StopTicks();
if (DBGLEVEL >= DBG_ERROR) DbpString("Done");
}
//
// Tear-off attack against MFU counter
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time) {
if (tearoff_time > 43000)
tearoff_time = 43000;
LEDsoff();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(true);
// Send MFU counter increase cmd
uint8_t cmd[] = {
MIFARE_ULEV1_INCR_CNT,
counter,
0, // lsb
0,
0, // msb
0, // rfu
0,
0,
};
AddCrc14A(cmd, sizeof(cmd) - 2);
// anticollision / select card
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
OnError(1);
return;
};
// send
ReaderTransmit(cmd, sizeof(cmd), NULL);
LED_D_ON();
SpinDelayUsPrecision(tearoff_time);
switch_off();
reply_ng(CMD_HF_MFU_COUNTER_TEAROFF, PM3_SUCCESS, NULL, 0);
}

View File

@@ -64,5 +64,5 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// Tear-off test for MFU
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain);
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time);
#endif

View File

@@ -13,6 +13,31 @@
#include "proxmark3_arm.h"
#include "dbprint.h"
// timer counts in 666ns increments (32/48MHz), rounding applies
// WARNING: timer can't measure more than 43ms (666ns * 0xFFFF)
void SpinDelayUsPrecision(int us) {
int ticks = ((MCK / 1000000) * us + 16) >> 5;
// Borrow a PWM unit for my real-time clock
AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
// 48 MHz / 32 gives 1.5 Mhz
AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(5); // Channel Mode Register
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xFFFF; // Channel Period Register
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
if (now == (uint16_t)(start + ticks))
return;
WDT_HIT();
}
}
// timer counts in 21.3us increments (1024/48MHz), rounding applies
// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
void SpinDelayUs(int us) {

View File

@@ -20,6 +20,7 @@
void SpinDelay(int ms);
void SpinDelayUs(int us);
void SpinDelayUsPrecision(int us); // precision 0.6us , running for 43ms before
void StartTickCount(void);
uint32_t RAMFUNC GetTickCount(void);