Пример #1
0
// wait for a gap on the reader coil and return it's length
// note this will return a partial gap if it's already started
// return pulse length in ticks
unsigned long get_reader_gap(unsigned int timeout_us)
{
    // wait for start of gap
    GetTimer_us(RESET);
    while(READER_DATA)
        if(timeout_us)
            if (GetTimer_us(NO_RESET) > timeout_us)
                return 0;

    // measure gap length
    GetTimer_us(RESET);
    while(!READER_DATA)
        if(timeout_us)
            if (GetTimer_us(NO_RESET) > timeout_us)
                return 0;

    return GetTimer_ticks(NO_RESET);
}
Пример #2
0
// h/w clock reader - initialise data pointers for ISR and start timers
// timer2 creates clock output for external reader
// timer4 reads data bit values
// period_us == clock for reader
// ticks == clock periods per bit
// bits == number of bits to read
// oneshot must be set if we are reading data in response to RWD, so no repeating stream
BOOL read_ASK_HW_clock(unsigned int period, unsigned int ticks, BYTE *data, unsigned int bits, unsigned int timeout_us, BOOL oneshot)
{
    unsigned long dwell, time;
    BYTE count;
    
    Manchester_Error= FALSE;

    // if we're manchester or bi-phase encoding, we want to clock twice as fast so we can read both halves of the bit
    if(RFIDlerConfig.Manchester || RFIDlerConfig.BiPhase)
    {
        ticks /= 2;
        HW_Bits= (unsigned long) bits * 2;
    }
    else
       HW_Bits= (unsigned long) bits;

    // point globals at data for ISR
    EMU_Data= data;

    memset(EMU_Data, '\0', bits);

    // stop USB interfering
    USBMaskInterrupts();

    // start clock if not already running
    if(!mGetLED_Clock() == mLED_ON)
    {
        InitHWReaderClock(OC_TOGGLE_PULSE, period / 2L, period, RWD_STATE_ACTIVE);

        // give reader time to wake up and settle
        Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100);
    }

    // align ourselves to reader's bit period by waiting until the end of a pulse
    GetTimer_us(RESET);
    count= READER_DATA;
    while(count == READER_DATA)
        if(GetTimer_us(NO_RESET) > timeout_us)
            return FALSE;

    // convert to ticks
    period= CONVERT_TO_TICKS(period);

    // biphase cannot auto-align when it detects a half-bit error, so we must align
    // on a full bit before we start
    if(!oneshot && RFIDlerConfig.BiPhase)
    {
        dwell= period * ticks * 2;
        count= 0;
        while((time= get_reader_gap(timeout_us)))
        {
            if(!time || count == 255)
                return;
            else
                if(approx(time, dwell, 10))
                    break;
            ++count;
        }
    }

    // wait for half the bit period so we sample mid-tick, not just as bit is toggling
    dwell= ((period * ticks) / 2L);
    GetTimer_ticks(RESET);
    //DEBUG_PIN_2= HIGH;
    while(GetTimer_ticks(NO_RESET) < dwell)
            ;

    // reset timer for external timeouts
    GetTimer_us(RESET);

    //DEBUG_PIN_2= LOW;
    
    // re-start reader ISR to read this bit if required
    InitHWReaderISR(period * ticks - 1L, TRUE);

    return TRUE;
}
Пример #3
0
// note that PRN is not created with security in mind - just using a simple seed
BOOL hitag2_crypto_auth(BYTE *response, BYTE *hexkey)
{
    BYTE tmp[65], tmphex[9];
    int seed;
    unsigned long long key;
    unsigned long uid;
    unsigned long initvec;

    // use default transport key if none specified
    if(strlen(hexkey) == 0)
        hexkey= HITAG2_KEY_DEFAULT;

    // get UID for initialisation
    if(!hitag2_get_uid(tmp))
        return FALSE;
    
    // convert to numerics for crypto routines
    uid= hexreversetoulong(tmp);
    key= hexreversetoulonglong(hexkey);

    // generate 32 bit PRN for challenge
    seed= (int) GetTimer_ticks(NO_RESET);
    srand(seed);
    initvec= rand();
    initvec <<= 16;
    initvec += rand();

    // prepare to send IV in the clear to tag
    ulongtobinstring(tmp, initvec, 32);

    // convert IV to MSB for crypto routines
    binstringtohex(tmphex, tmp);
    initvec= hexreversetoulong(tmphex);

    // initialise  crypto
    hitag2_init(&Hitag_Crypto_State, rev64(key), rev32(uid), rev32(initvec));

    // send inverse of 1st 32bits of keystream to tag for authentication
    ulongtobinstring(tmp + 32, hitag2_crypt(0xFFFFFFFF, 32), 32);

    // restart the tag & auth process
    if(!hitag2_get_uid(TmpBuff))
        return FALSE;

    // wait for RX->TX period, then send PRN+secret
    if(!rwd_send(tmp, strlen(tmp), NO_RESET, BLOCK, RWD_STATE_WAKING, 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))
        return FALSE;

    // get 37 bit response: sync + config byte + 24 bit TAG pwd
    if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY) == 37)
    {
        // check sync bits
        if (memcmp(tmp, Hitag2Sync, 5) != 0)
            return FALSE;
        CryptoActive= TRUE;

        // decrypt
        binarraytohex(response, tmp + 5, 32);
        return hitag2_hex_crypt(response, response);
    }
    return FALSE;
}
Пример #4
0
// Reader clock ISR
// also process RWD commands while we toggle clock line
void __ISR(_OUTPUT_COMPARE_5_VECTOR, ipl6auto) reader_clock_tick (void)
{
    static unsigned int count= 0;
    static unsigned int bcount= 0;

    // Clear interrupt flag
    mOC5ClearIntFlag();
    
    mLED_Clock_On();

    // process RWD commands (if any)
    switch (RWD_State)
    {
        case RWD_STATE_INACTIVE:
        case RWD_STATE_ACTIVE:
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            break;

        case RWD_STATE_GO_TO_SLEEP:
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            // initial shutdown of coil to restart tag
            READER_CLOCK_ENABLE_OFF();
            COIL_OUT_LOW();
            // time small amounts with ticks, large with uS
            if(RWD_Sleep_Period > MAX_TIMER5_TICKS)
                Delay_us(CONVERT_TICKS_TO_US(RWD_Sleep_Period));
            else
            {
                WriteTimer5(0);
                while(GetTimer_ticks(NO_RESET) < RWD_Sleep_Period)
                    ;
            }
            count= 0;
            RWD_State= RWD_STATE_WAKING;
            // restart clock only if we have a wake period
            if(RWD_Wake_Period)
                READER_CLOCK_ENABLE_ON();
            break;

        case RWD_STATE_WAKING:
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            // leave coil running for wakeup period
            if(count == RWD_Wake_Period)
            {
                count= 0;
                bcount = 0;
                if(*RWD_Command_ThisBit != '*')
                    RWD_State= RWD_STATE_START_SEND;
                else
                    RWD_State= RWD_STATE_ACTIVE;
            }
            else
                count++;
            break;

        case RWD_STATE_START_SEND:
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            // send initial gap
            // stop modulation of coil and wait
            READER_CLOCK_ENABLE_OFF();
            COIL_OUT_LOW();
            count= 0;
            if(RWD_Barrier)
		RWD_State= RWD_STATE_SENDING_BARRIER_LOW;
            else
                RWD_State= RWD_STATE_SENDING_BIT_LOW;
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            // restart clock
            //READER_CLOCK_ENABLE_ON();
            break;

        case RWD_STATE_SENDING_BIT_HIGH:
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            // clock running for bit period, then wait for gap period
            if((*RWD_Command_ThisBit && count == RWD_One_Period) || (!*RWD_Command_ThisBit && count == RWD_Zero_Period))
            {                    
		count= 0;
                if(*RWD_Command_ThisBit == '*')
                    RWD_State= RWD_STATE_POST_WAIT;
		else if(RWD_Barrier && bcount == 7)
		    RWD_State= RWD_STATE_SENDING_BARRIER_LOW;
                else
                    RWD_State= RWD_STATE_SENDING_BIT_LOW;
		READER_CLOCK_ENABLE_OFF();
                COIL_OUT_LOW();
                bcount++;
                if(bcount == 8)
                   bcount = 0;
		          
            }
            else
                count++;
            break;

	case RWD_STATE_SENDING_BIT_LOW:

            if((*RWD_Command_ThisBit && count == RWD_One_Gap_Period) || (!*RWD_Command_ThisBit && count == RWD_Zero_Gap_Period))
            {
		
                ++RWD_Command_ThisBit;
                count= 0;

                RWD_State= RWD_STATE_SENDING_BIT_HIGH;
                // restart clock

               READER_CLOCK_ENABLE_ON();
            }
            else
                count++;
            break;

	case RWD_STATE_SENDING_BARRIER_HIGH:

            if(count == RWD_One_Barrier_Period){
                count= 0;
                RWD_State= RWD_STATE_SENDING_BIT_LOW;
		READER_CLOCK_ENABLE_OFF();
                COIL_OUT_LOW();
	    }else
                count++;
            break;

	case RWD_STATE_SENDING_BARRIER_LOW:

            if(count == RWD_Zero_Barrier_Period){
                count= 0;
                RWD_State= RWD_STATE_SENDING_BARRIER_HIGH;
		READER_CLOCK_ENABLE_ON();
	    }else
                count++;
            break;

        case RWD_STATE_POST_WAIT:
            //DEBUG_PIN_4= !DEBUG_PIN_4;
            // coil running for forced post-command wait period
            if(count == RWD_Post_Wait)
            {
                count= 0;
                RWD_State= RWD_STATE_ACTIVE;
            }
            else
                count++;
            break;

        default:
            break;
    }
}