Legic: Implemented setup phase for card simulation

This commit is contained in:
AntiCat 2018-09-05 22:23:35 +02:00
parent 2c6c4e5bc6
commit cd78b00815
2 changed files with 90 additions and 9 deletions

View file

@ -302,8 +302,8 @@ static void init_reader(bool clear_mem) {
// The setup consists of a three way handshake: // The setup consists of a three way handshake:
// - Transmit initialisation vector 7 bits // - Transmit initialisation vector 7 bits
// - Receive card type 6 bits // - Receive card type 6 bits
// - Acknowledge frame 6 bits // - Transmit Acknowledge 6 bits
static uint32_t setup_phase_reader(uint8_t iv) { static uint32_t setup_phase(uint8_t iv) {
// init coordination timestamp // init coordination timestamp
last_frame_end = GET_TICKS; last_frame_end = GET_TICKS;
@ -398,7 +398,7 @@ void LegicRfInfo(void) {
init_reader(false); init_reader(false);
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase_reader(0x01); uint8_t card_type = setup_phase(0x01);
if(init_card(card_type, &card) != 0) { if(init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
@ -435,7 +435,7 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
init_reader(false); init_reader(false);
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase_reader(iv); uint8_t card_type = setup_phase(iv);
if(init_card(card_type, &card) != 0) { if(init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
@ -474,7 +474,7 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
} }
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase_reader(iv); uint8_t card_type = setup_phase(iv);
if(init_card(card_type, &card) != 0) { if(init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;

View file

@ -321,6 +321,78 @@ static void init_tag() {
StartCountSspClk(); StartCountSspClk();
} }
// Setup reader to card connection
//
// The setup consists of a three way handshake:
// - Receive initialisation vector 7 bits
// - Transmit card type 6 bits
// - Receive Acknowledge 6 bits
static int32_t setup_phase(legic_card_select_t *p_card) {
uint8_t len = 0;
// init coordination timestamp
last_frame_end = GetCountSspClk();
// reset prng
legic_prng_init(0);
// wait for iv
int32_t iv = rx_frame(&len);
if((len != 7) || (iv < 0)) {
return -1;
}
// configure prng
legic_prng_init(iv);
// reply with card type
switch(p_card->tagtype) {
case 0:
tx_frame(0x0D, 6);
break;
case 1:
tx_frame(0x1D, 6);
break;
case 2:
tx_frame(0x3D, 6);
break;
}
// wait for ack
int32_t ack = rx_frame(&len);
if((len != 6) || (ack < 0)) {
return -1;
}
// validate data
switch(p_card->tagtype) {
case 0:
if(ack != 0x19) return -1;
break;
case 1:
if(ack != 0x39) return -1;
break;
case 2:
if(ack != 0x39) return -1;
break;
}
// During rx the prng is clocked using the variable reader period.
// Since rx_frame detects end of frame by detecting a code violation,
// the prng is off by one bit period after each rx phase. Hence, tx
// code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1).
// This is not possible for back to back rx, so this quirk reduces
// the gap by one period.
last_frame_end += TAG_BIT_PERIOD;
return 0;
}
// TODO Commands are left as an exercise to the reader
static int32_t connected_phase(legic_card_select_t *p_card) {
return 0;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Command Line Interface // Command Line Interface
// //
@ -342,11 +414,20 @@ void LegicRfSimulate(uint8_t cardtype) {
while(!BUTTON_PRESS()) { while(!BUTTON_PRESS()) {
WDT_HIT(); WDT_HIT();
// init coordination timestamp // wait for carrier, restart after timeout
last_frame_end = GetCountSspClk(); if(!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
continue;
}
// reset prng // wait for connection, restart on error
legic_prng_init(0); if(setup_phase(&card)) {
continue;
}
// conection is established, process commands until one fails
while(!connected_phase(&card)) {
WDT_HIT();
}
} }
OUT: OUT: