From cd78b008156e4d1fe084c16757bd5b15036fd49f Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:35 +0200 Subject: [PATCH] Legic: Implemented setup phase for card simulation --- armsrc/legicrf.c | 10 ++--- armsrc/legicrfsim.c | 89 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 59cda1221..00d284926 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -302,8 +302,8 @@ static void init_reader(bool clear_mem) { // The setup consists of a three way handshake: // - Transmit initialisation vector 7 bits // - Receive card type 6 bits -// - Acknowledge frame 6 bits -static uint32_t setup_phase_reader(uint8_t iv) { +// - Transmit Acknowledge 6 bits +static uint32_t setup_phase(uint8_t iv) { // init coordination timestamp last_frame_end = GET_TICKS; @@ -398,7 +398,7 @@ void LegicRfInfo(void) { init_reader(false); // 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) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; @@ -435,7 +435,7 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { init_reader(false); // 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) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); 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 - uint8_t card_type = setup_phase_reader(iv); + uint8_t card_type = setup_phase(iv); if(init_card(card_type, &card) != 0) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index d73f09857..195aa2738 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -321,6 +321,78 @@ static void init_tag() { 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 // @@ -342,11 +414,20 @@ void LegicRfSimulate(uint8_t cardtype) { while(!BUTTON_PRESS()) { WDT_HIT(); - // init coordination timestamp - last_frame_end = GetCountSspClk(); + // wait for carrier, restart after timeout + if(!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) { + continue; + } - // reset prng - legic_prng_init(0); + // wait for connection, restart on error + if(setup_phase(&card)) { + continue; + } + + // conection is established, process commands until one fails + while(!connected_phase(&card)) { + WDT_HIT(); + } } OUT: