X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/54a942b05dd2a601b85e9851a5799929cbdffd5f..07976a256df582dbaf8b51a414e1a0c2188d06fb:/armsrc/lfops.c diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 8d4e2dc9..397ea847 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -15,30 +15,8 @@ #include "crc16.h" #include "string.h" -void AcquireRawAdcSamples125k(int at134khz) -{ - if (at134khz) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - else - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - - // Connect the A/D to the peak-detected low-frequency path. - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(50); - - // Now set up the SSC to get the ADC samples that are now streaming at us. - FpgaSetupSsc(); - - // Now call the acquisition routine - DoAcquisition125k(); -} - // split into two routines so we can avoid timing issues after sending commands // -void DoAcquisition125k(void) +void DoAcquisition125k_internal(bool silent) { uint8_t *dest = (uint8_t *)BigBuf; int n = sizeof(BigBuf); @@ -58,8 +36,44 @@ void DoAcquisition125k(void) if (i >= n) break; } } - Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", - dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); + if( ! silent) + { + Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", + dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); + } +} + +void DoAcquisition125k(void) +{ + DoAcquisition125k_internal(false); +} + +void SetupToAcquireRawAdcSamples(int divisor) +{ + if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + else if (divisor == 0) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + else + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); + + // Connect the A/D to the peak-detected low-frequency path. + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(50); + + // Now set up the SSC to get the ADC samples that are now streaming at us. + FpgaSetupSsc(); +} + +void AcquireRawAdcSamples125k(int divisor) +{ + SetupToAcquireRawAdcSamples(divisor); + // Now call the acquisition routine + DoAcquisition125k_internal(false); } void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command) @@ -592,217 +606,242 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol) LED_A_OFF(); } - -// loop to capture raw HID waveform then FSK demodulate the TAG ID from it -void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) +size_t fsk_demod(uint8_t * dest, size_t size) { - uint8_t *dest = (uint8_t *)BigBuf; - int m=0, n=0, i=0, idx=0, found=0, lastval=0; - uint32_t hi2=0, hi=0, lo=0; + uint32_t last_transition = 0; + uint32_t idx = 1; - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); + // we don't care about actual value, only if it's more or less than a + // threshold essentially we capture zero crossings for later analysis + uint8_t threshold_value = 127; - // Connect the A/D to the peak-detected low-frequency path. - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(50); + // sync to first lo-hi transition, and threshold - // Now set up the SSC to get the ADC samples that are now streaming at us. - FpgaSetupSsc(); + //Need to threshold first sample + if(dest[0] < threshold_value) dest[0] = 0; + else dest[0] = 1; - for(;;) { - WDT_HIT(); - if (ledcontrol) - LED_A_ON(); - if(BUTTON_PRESS()) { - DbpString("Stopped"); - if (ledcontrol) - LED_A_OFF(); - return; - } + size_t numBits = 0; + // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8) + // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere + // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10 + for(idx = 1; idx < size; idx++) { + // threshold current value + if (dest[idx] < threshold_value) dest[idx] = 0; + else dest[idx] = 1; - i = 0; - m = sizeof(BigBuf); - memset(dest,128,m); - for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x43; - if (ledcontrol) - LED_D_ON(); - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - // we don't care about actual value, only if it's more or less than a - // threshold essentially we capture zero crossings for later analysis - if(dest[i] < 127) dest[i] = 0; else dest[i] = 1; - i++; - if (ledcontrol) - LED_D_OFF(); - if(i >= m) { - break; - } + // Check for 0->1 transition + if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition + + if (idx-last_transition < 9) { + dest[numBits]=1; + } else { + dest[numBits]=0; } + last_transition = idx; + numBits++; } + } + return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0 +} - // FSK demodulator - // sync to first lo-hi transition - for( idx=1; idx0 crossing + if ( dest[idx-1] ) { + n=(n+1) / h2l_crossing_value; + } else {// 0->1 crossing + n=(n+1) / l2h_crossing_value; + } + if (n == 0) n = 1; + + if(n < maxConsequtiveBits) + { + memset(dest+numBits, dest[idx-1] , n); + numBits += n; } + n=0; + lastval=dest[idx]; + }//end for + + return numBits; + +} +// loop to capture raw HID waveform then FSK demodulate the TAG ID from it +void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) +{ + uint8_t *dest = (uint8_t *)BigBuf; + + size_t size=0,idx=0; //, found=0; + uint32_t hi2=0, hi=0, lo=0; + + + while(!BUTTON_PRESS()) { + + // Configure to go in 125Khz listen mode + SetupToAcquireRawAdcSamples(0); + WDT_HIT(); + if (ledcontrol) LED_A_ON(); - // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8) - // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere - // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10 - for( i=0; idx0 : fc/8 in sets of 6 + // 0->1 : fc/10 in sets of 5 + size = aggregate_bits(dest,size, 6,5,5); + WDT_HIT(); // final loop, go over previously decoded manchester data and decode into usable tag ID // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0 - for( idx=0; idx>1) & 0xFFFF); - } - else { - Dbprintf("TAG ID: %x%08x (%d)", - (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); - } - /* if we're only looking for one tag */ - if (findone) - { - *high = hi; - *low = lo; - return; - } - hi2=0; - hi=0; - lo=0; - found=0; - } - } - if (found) { - if (dest[idx] && (!dest[idx+1]) ) { - hi2=(hi2<<1)|(hi>>31); - hi=(hi<<1)|(lo>>31); - lo=(lo<<1)|0; - } else if ( (!dest[idx]) && dest[idx+1]) { - hi2=(hi2<<1)|(hi>>31); - hi=(hi<<1)|(lo>>31); - lo=(lo<<1)|1; - } else { - found=0; - hi2=0; - hi=0; - lo=0; + if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0) + { // frame marker found + idx+=sizeof(frame_marker_mask); + + while(dest[idx] != dest[idx+1] && idx < size-2) + { // Keep going until next frame marker (or error) + // Shift in a bit. Start by shifting high registers + hi2 = (hi2<<1)|(hi>>31); + hi = (hi<<1)|(lo>>31); + //Then, shift in a 0 or one into low + if (dest[idx] && !dest[idx+1]) // 1 0 + lo=(lo<<1)|0; + else // 0 1 + lo=(lo<<1)| + 1; + numshifts ++; + idx += 2; } - idx++; - } - if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) ) - { - found=1; - idx+=6; - if (found && (hi|lo)) { - if (hi2 != 0){ - Dbprintf("TAG ID: %x%08x%08x (%d)", - (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); - } - else { - Dbprintf("TAG ID: %x%08x (%d)", - (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); - } - /* if we're only looking for one tag */ - if (findone) - { - *high = hi; - *low = lo; - return; + //Dbprintf("Num shifts: %d ", numshifts); + // Hopefully, we read a tag and hit upon the next frame marker + if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0) + { + if (hi2 != 0){ + Dbprintf("TAG ID: %x%08x%08x (%d)", + (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); + } + else { + Dbprintf("TAG ID: %x%08x (%d)", + (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); } - hi2=0; - hi=0; - lo=0; - found=0; } + + // reset + hi2 = hi = lo = 0; + numshifts = 0; + }else + { + idx++; } } WDT_HIT(); + } + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); +} + +uint32_t bytebits_to_byte(uint8_t* src, int numbits) +{ + uint32_t num = 0; + for(int i = 0 ; i < numbits ; i++) + { + num = (num << 1) | (*src); + src++; + } + return num; +} + + +void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) +{ + uint8_t *dest = (uint8_t *)BigBuf; + + size_t size=0, idx=0; + uint32_t code=0, code2=0; + + + while(!BUTTON_PRESS()) { + + // Configure to go in 125Khz listen mode + SetupToAcquireRawAdcSamples(0); + + WDT_HIT(); + if (ledcontrol) LED_A_ON(); + + DoAcquisition125k_internal(true); + size = sizeof(BigBuf); + + // FSK demodulator + size = fsk_demod(dest, size); + WDT_HIT(); + + // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns + // 1->0 : fc/8 in sets of 7 + // 0->1 : fc/10 in sets of 6 + size = aggregate_bits(dest, size, 7,6,13); + + WDT_HIT(); + + //Handle the data + uint8_t mask[] = {0,0,0,0,0,0,0,0,0,1}; + for( idx=0; idx < size - 64; idx++) { + + if ( memcmp(dest + idx, mask, sizeof(mask)) ) continue; + + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7]); + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+8], dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15]); + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+16],dest[idx+17],dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23]); + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+24],dest[idx+25],dest[idx+26],dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31]); + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35],dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39]); + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44],dest[idx+45],dest[idx+46],dest[idx+47]); + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53],dest[idx+54],dest[idx+55]); + Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]); + + code = bytebits_to_byte(dest+idx,32); + code2 = bytebits_to_byte(dest+idx+32,32); + + short version = bytebits_to_byte(dest+idx+14,4); + char unknown = bytebits_to_byte(dest+idx+19,8) ; + uint16_t number = bytebits_to_byte(dest+idx+36,9); + + Dbprintf("XSF(%02d)%02x:%d (%08x%08x)",version,unknown,number,code,code2); + if (ledcontrol) LED_D_OFF(); + + // if we're only looking for one tag + if (findone){ + LED_A_OFF(); + return; + } + } + WDT_HIT(); + } + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); } /*------------------------------ @@ -1164,6 +1203,26 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) DbpString("DONE!"); } +void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT) +{ + int data1=0, data2=0; //up to six blocks for long format + + data1 = hi; // load preamble + data2 = lo; + + LED_D_ON(); + // Program the data blocks for supplied ID + // and the block 0 for HID format + T55xxWriteBlock(data1,1,0,0); + T55xxWriteBlock(data2,2,0,0); + + //Config Block + T55xxWriteBlock(0x00147040,0,0,0); + LED_D_OFF(); + + DbpString("DONE!"); +} + // Define 9bit header for EM410x tags #define EM410X_HEADER 0x1FF #define EM410X_ID_LENGTH 40 @@ -1175,6 +1234,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) uint64_t rev_id = 0; // reversed ID int c_parity[4]; // column parity int r_parity = 0; // row parity + uint32_t clock = 0; // Reverse ID bits given as parameter (for simpler operations) for (i = 0; i < EM410X_ID_LENGTH; ++i) { @@ -1232,12 +1292,35 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) T55xxWriteBlock((uint32_t)id, 2, 0, 0); // Config for EM410x (RF/64, Manchester, Maxblock=2) - if (card) + if (card) { + // Clock rate is stored in bits 8-15 of the card value + clock = (card & 0xFF00) >> 8; + Dbprintf("Clock rate: %d", clock); + switch (clock) + { + case 32: + clock = T55x7_BITRATE_RF_32; + break; + case 16: + clock = T55x7_BITRATE_RF_16; + break; + case 0: + // A value of 0 is assumed to be 64 for backwards-compatibility + // Fall through... + case 64: + clock = T55x7_BITRATE_RF_64; + break; + default: + Dbprintf("Invalid clock rate: %d", clock); + return; + } + // Writing configuration for T55x7 tag - T55xxWriteBlock(T55x7_BITRATE_RF_64 | + T55xxWriteBlock(clock | T55x7_MODULATION_MANCHESTER | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0); + } else // Writing configuration for T5555(Q5) tag T55xxWriteBlock(0x1F << T5555_BITRATE_SHIFT |