X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/ebfb4447b867205750692ca9bb54bcb6d9dc41e6..fb27c733133554aab2888a48bdb58c4502bc8a9b:/armsrc/lfops.c diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 9c6c9ed8..1816bdca 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -4,7 +4,7 @@ // the license. //----------------------------------------------------------------------------- // Miscellaneous routines for low frequency tag operations. -// Tags supported here so far are Texas Instruments (TI), HID +// Tags supported here so far are Texas Instruments (TI), HID, EM4x05, EM410x // Also routines for raw mode reading/simulating of LF waveform //----------------------------------------------------------------------------- @@ -28,51 +28,103 @@ */ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command) { + // start timer + StartTicks(); - int divisor_used = 95; // 125 KHz - // see if 'h' was specified - - if (command[strlen((char *) command) - 1] == 'h') - divisor_used = 88; // 134.8 KHz - - sample_config sc = { 0,0,1, divisor_used, 0}; - setSamplingConfig(&sc); - //clear read buffer - BigBuf_Clear_keep_EM(); + // use lf config settings + sample_config *sc = getSamplingConfig(); - /* Make sure the tag is reset */ + // Make sure the tag is reset FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(2500); + WaitMS(2500); - LFSetupFPGAForADC(sc.divisor, 1); + // clear read buffer (after fpga bitstream loaded...) + BigBuf_Clear_keep_EM(); - // And a little more time for the tag to fully power up - SpinDelay(2000); + // power on + LFSetupFPGAForADC(sc->divisor, 1); + // And a little more time for the tag to fully power up + WaitMS(2000); + // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods. + bool bitbang = delay_off == 0; // now modulate the reader field - while(*command != '\0' && *command != ' ') { + + if (bitbang) { + // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly... + uint8_t hack_cnt = 7; + if (period_0 < hack_cnt || period_1 < hack_cnt) { + DbpString("Warning periods cannot be less than 7us in bit bang mode"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + return; + } + + // hack2 needed--- it appears to take about 8-16us to turn the antenna back on + // leading to ~ 1 to 2 125khz samples extra in every off period + // so we should test for last 0 before next 1 and reduce period_0 by this extra amount... + // but is this time different for every antenna or other hw builds??? more testing needed + + // prime cmd_len to save time comparing strings while modulating + int cmd_len = 0; + while(command[cmd_len] != '\0' && command[cmd_len] != ' ') + cmd_len++; + + int counter = 0; + bool off = false; + for (counter = 0; counter < cmd_len; counter++) { + // if cmd = 0 then turn field off + if (command[counter] == '0') { + // if field already off leave alone (affects timing otherwise) + if (off == false) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + off = true; + } + // note we appear to take about 7us to switch over (or run the if statements/loop...) + WaitUS(period_0-hack_cnt); + // else if cmd = 1 then turn field on + } else { + // if field already on leave alone (affects timing otherwise) + if (off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + LED_D_ON(); + off = false; + } + // note we appear to take about 7us to switch over (or run the if statements/loop...) + WaitUS(period_1-hack_cnt); + } + } + } else { // old mode of cmd read using delay as off period + while(*command != '\0' && *command != ' ') { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + WaitUS(delay_off); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + LED_D_ON(); + if(*(command++) == '0') { + WaitUS(period_0); + } else { + WaitUS(period_1); + } + } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); - SpinDelayUs(delay_off); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - LED_D_ON(); - if(*(command++) == '0') - SpinDelayUs(period_0); - else - SpinDelayUs(period_1); + WaitUS(delay_off); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); - SpinDelayUs(delay_off); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); // now do the read - DoAcquisition_config(false); + DoAcquisition_config(false, 0); + + // Turn off antenna + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // tell client we are done + cmd_send(CMD_ACK,0,0,0,0,0); } /* blank r/w tag data stream @@ -387,7 +439,8 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol) int i; uint8_t *tab = BigBuf_get_addr(); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + //note FpgaDownloadAndGo destroys the bigbuf so be sure this is called before now... + //FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK; @@ -401,13 +454,19 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol) i = 0; for(;;) { //wait until SSC_CLK goes HIGH + int ii = 0; while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { - if(BUTTON_PRESS() || (usb_poll_validate_length() )) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Stopped"); - return; + //only check every 1000th time (usb_poll_validate_length on some systems was too slow) + if ( ii == 1000 ) { + if (BUTTON_PRESS() || usb_poll_validate_length() ) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Stopped"); + return; + } + ii=0; } WDT_HIT(); + ii++; } if (ledcontrol) LED_D_ON(); @@ -419,14 +478,20 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol) if (ledcontrol) LED_D_OFF(); + ii=0; //wait until SSC_CLK goes LOW while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { - if(BUTTON_PRESS() || (usb_poll_validate_length() )) { - DbpString("Stopped"); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return; + //only check every 1000th time (usb_poll_validate_length on some systems was too slow) + if ( ii == 1000 ) { + if (BUTTON_PRESS() || usb_poll_validate_length() ) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Stopped"); + return; + } + ii=0; } WDT_HIT(); + ii++; } i++; @@ -503,7 +568,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) uint8_t wavesPerClock = clock/fc; uint8_t mod = clock % fc; //modifier uint8_t modAdj = fc/mod; //how often to apply modifier - bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk=TRUE; + bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk=true; // loop through clock - step field clock for (uint8_t idx=0; idx < wavesPerClock; idx++){ // put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave) @@ -528,7 +593,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) // prepare a waveform pattern in the buffer based on the ID given then // simulate a HID tag until the button is pressed -void CmdHIDsimTAG(int hi, int lo, int ledcontrol) +void CmdHIDsimTAG(int hi2, int hi, int lo, int ledcontrol) { int n=0, i=0; /* @@ -541,10 +606,13 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol) nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10) */ - if (hi>0xFFF) { - DbpString("Tags can only have 44 bits. - USE lf simfsk for larger tags"); + if (hi2>0x0FFFFFFF) { + DbpString("Tags can only have 44 or 84 bits. - USE lf simfsk for larger tags"); return; } + // set LF so we don't kill the bigbuf we are setting with simulation data. + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + fc(0,&n); // special start of frame marker containing invalid bit sequences fc(8, &n); fc(8, &n); // invalid @@ -553,13 +621,35 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol) fc(8, &n); fc(10, &n); // logical 0 WDT_HIT(); - // manchester encode bits 43 to 32 - for (i=11; i>=0; i--) { - if ((i%4)==3) fc(0,&n); - if ((hi>>i)&1) { - fc(10, &n); fc(8, &n); // low-high transition - } else { - fc(8, &n); fc(10, &n); // high-low transition + if (hi2 > 0 || hi > 0xFFF){ + // manchester encode bits 91 to 64 (91-84 are part of the header) + for (i=27; i>=0; i--) { + if ((i%4)==3) fc(0,&n); + if ((hi2>>i)&1) { + fc(10, &n); fc(8, &n); // low-high transition + } else { + fc(8, &n); fc(10, &n); // high-low transition + } + } + WDT_HIT(); + // manchester encode bits 63 to 32 + for (i=31; i>=0; i--) { + if ((i%4)==3) fc(0,&n); + if ((hi>>i)&1) { + fc(10, &n); fc(8, &n); // low-high transition + } else { + fc(8, &n); fc(10, &n); // high-low transition + } + } + } else { + // manchester encode bits 43 to 32 + for (i=11; i>=0; i--) { + if ((i%4)==3) fc(0,&n); + if ((hi>>i)&1) { + fc(10, &n); fc(8, &n); // low-high transition + } else { + fc(8, &n); fc(10, &n); // high-low transition + } } } @@ -595,6 +685,9 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) uint8_t clk = arg2 & 0xFF; uint8_t invert = (arg2 >> 8) & 1; + // set LF so we don't kill the bigbuf we are setting with simulation data. + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + for (i=0; i> 8) & 1; + // set LF so we don't kill the bigbuf we are setting with simulation data. + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + if (encoding==2){ //biphase uint8_t phase=0; for (i=0; i0 && lo>0 && (size==96 || size==192)){ + uint8_t bitlen = 0; + uint32_t fc = 0; + uint32_t cardnum = 0; + bool decoded = false; + // go over previously decoded manchester data and decode into usable tag ID - if (hi2 != 0){ //extra large HID tags 88/192 bits - Dbprintf("TAG ID: %x%08x%08x (%d)", - (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); - }else { //standard HID tags 44/96 bits - //Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd - uint8_t bitlen = 0; - uint32_t fc = 0; - uint32_t cardnum = 0; - if (((hi>>5)&1) == 1){//if bit 38 is set then < 37 bit format is used - uint32_t lo2=0; - lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit - uint8_t idx3 = 1; - while(lo2 > 1){ //find last bit set to 1 (format len bit) - lo2=lo2 >> 1; - idx3++; - } - bitlen = idx3+19; - fc =0; - cardnum=0; - if(bitlen == 26){ - cardnum = (lo>>1)&0xFFFF; - fc = (lo>>17)&0xFF; - } - if(bitlen == 37){ - cardnum = (lo>>1)&0x7FFFF; - fc = ((hi&0xF)<<12)|(lo>>20); - } - if(bitlen == 34){ - cardnum = (lo>>1)&0xFFFF; - fc= ((hi&1)<<15)|(lo>>17); - } - if(bitlen == 35){ - cardnum = (lo>>1)&0xFFFFF; - fc = ((hi&1)<<11)|(lo>>21); - } + if ((hi2 & 0x000FFFF) != 0){ //extra large HID tags 88/192 bits + uint32_t bp = hi2 & 0x000FFFFF; + bitlen = 63; + while (bp > 0) { + bp = bp >> 1; + bitlen++; } - else { //if bit 38 is not set then 37 bit format is used - bitlen= 37; - fc =0; - cardnum=0; - if(bitlen==37){ - cardnum = (lo>>1)&0x7FFFF; - fc = ((hi&0xF)<<12)|(lo>>20); - } + } else if ((hi >> 6) > 0) { + uint32_t bp = hi; + bitlen = 31; + while (bp > 0) { + bp = bp >> 1; + bitlen++; + } + } else if (((hi >> 5) & 1) == 0) { + bitlen = 37; + } else if ((hi & 0x0000001F) > 0 ) { + uint32_t bp = (hi & 0x0000001F); + bitlen = 31; + while (bp > 0) { + bp = bp >> 1; + bitlen++; } - //Dbprintf("TAG ID: %x%08x (%d)", - // (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); - Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", - (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, - (unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum); + } else { + uint32_t bp = lo; + bitlen = 0; + while (bp > 0) { + bp = bp >> 1; + bitlen++; + } + } + switch (bitlen){ + case 26: + cardnum = (lo>>1)&0xFFFF; + fc = (lo>>17)&0xFF; + decoded = true; + break; + case 35: + cardnum = (lo>>1)&0xFFFFF; + fc = ((hi&1)<<11)|(lo>>21); + decoded = true; + break; } + + if (hi2 != 0) //extra large HID tags 88/192 bits + 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 (decoded) + Dbprintf("Format Len: %dbits - FC: %d - Card: %d", + (unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum); + if (findone){ if (ledcontrol) LED_A_OFF(); + *high2 = hi2; *high = hi; *low = lo; break; @@ -861,7 +970,7 @@ void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); size_t size; - int idx=0; + int idx=0, dummyIdx=0; //clear read buffer BigBuf_Clear_keep_EM(); // Configure to go in 125Khz listen mode @@ -875,7 +984,7 @@ void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol) DoAcquisition_default(-1,true); // FSK demodulator size = 50*128*2; //big enough to catch 2 sequences of largest format - idx = AWIDdemodFSK(dest, &size); + idx = AWIDdemodFSK(dest, &size, &dummyIdx); if (idx<=0 || size!=96) continue; // Index map @@ -1017,6 +1126,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) uint8_t version=0; uint8_t facilitycode=0; uint16_t number=0; + int dummyIdx=0; //clear read buffer BigBuf_Clear_keep_EM(); // Configure to go in 125Khz listen mode @@ -1028,7 +1138,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) DoAcquisition_default(-1,true); //fskdemod and get start index WDT_HIT(); - idx = IOdemodFSK(dest, BigBuf_max_traceLen()); + idx = IOdemodFSK(dest, BigBuf_max_traceLen(), &dummyIdx); if (idx<0) continue; //valid tag found @@ -1132,7 +1242,7 @@ void T55xxResetRead(void) { TurnReadLFOn(READ_GAP); // Acquisition - doT55x7Acquisition(BigBuf_max_traceLen()); + DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off @@ -1161,7 +1271,8 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg // Std Opcode 10 T55xxWriteBit(testMode ? 0 : 1); T55xxWriteBit(testMode ? 1 : Page); //Page 0 - if (PwdMode){ + + if (PwdMode) { // Send Pwd for (i = 0x80000000; i != 0; i >>= 1) T55xxWriteBit(Pwd & i); @@ -1181,22 +1292,19 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg // so wait a little more) // "there is a clock delay before programming" - // - programming takes ~5.6ms for t5577 ~18ms for E5550 + // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 // so we should wait 1 clock + 5.6ms then read response? - // but we need to know we are dealing with t55x7 vs e5550 (or q5) marshmellow... + // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... if (testMode) { - // Turn field on to read the response - TurnReadLFOn(READ_GAP); + //TESTMODE TIMING TESTS: + // <566us does nothing + // 566-568 switches between wiping to 0s and doing nothing + // 5184 wipes and allows 1 block to be programmed. + // indefinite power on wipes and then programs all blocks with bitshifted data sent. + TurnReadLFOn(5184); - // Acquisition - // Now do the acquisition - // Now do the acquisition - DoPartialAcquisition(20, true, 12000); - - //doT55x7Acquisition(12000); } else { TurnReadLFOn(20 * 1000); - } //could attempt to do a read to confirm write took // as the tag should repeat back the new block // until it is reset, but to confirm it we would @@ -1205,6 +1313,9 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg // response should be (for t55x7) a 0 bit then (ST if on) // block data written in on repeat until reset. + //DoPartialAcquisition(20, true, 12000); + } + // turn field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_A_OFF(); @@ -1263,9 +1374,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Acquisition // Now do the acquisition - DoPartialAcquisition(0, true, 12000); - - // doT55x7Acquisition(12000); + DoPartialAcquisition(0, true, 12000, 0); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off @@ -1308,8 +1417,8 @@ void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) { } } -// Copy HID id to card and setup block 0 config -void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { +// Copy a HID-like card (e.g. HID Proximity, Paradox) to a T55x7 compatible card +void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, uint8_t preamble) { uint32_t data[] = {0,0,0,0,0,0,0}; uint8_t last_block = 0; @@ -1321,15 +1430,15 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { } // Build the 6 data blocks for supplied 84bit ID last_block = 6; - // load preamble (1D) & long format identifier (9E manchester encoded) - data[1] = 0x1D96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF); + // load preamble & long format identifier (9E manchester encoded) + data[1] = (preamble << 24) | 0x96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF); // load raw id from hi2, hi, lo to data blocks (manchester encoded) data[2] = manchesterEncode2Bytes(hi2 & 0xFFFF); data[3] = manchesterEncode2Bytes(hi >> 16); data[4] = manchesterEncode2Bytes(hi & 0xFFFF); data[5] = manchesterEncode2Bytes(lo >> 16); data[6] = manchesterEncode2Bytes(lo & 0xFFFF); - } else { + } else { // Ensure no more than 44 bits supplied if (hi>0xFFF) { DbpString("Tags can only have 44 bits."); @@ -1338,7 +1447,7 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { // Build the 3 data blocks for supplied 44bit ID last_block = 3; // load preamble - data[1] = 0x1D000000 | (manchesterEncode2Bytes(hi) & 0xFFFFFF); + data[1] = (preamble << 24) | (manchesterEncode2Bytes(hi) & 0xFFFFFF); data[2] = manchesterEncode2Bytes(lo >> 16); data[3] = manchesterEncode2Bytes(lo & 0xFFFF); } @@ -1391,10 +1500,10 @@ void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t //Program the 7 data blocks for supplied 224bit UID uint32_t data[] = {0, uid1, uid2, uid3, uid4, uid5, uid6, uid7}; // and the block 0 for Indala224 format - //Config for Indala (RF/32;PSK1 with RF/2;Maxblock=7) - data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (7 << T55x7_MAXBLOCK_SHIFT); + //Config for Indala (RF/32;PSK2 with RF/2;Maxblock=7) + data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT); //TODO add selection of chip for Q5 or T55x7 - // data[0] = (((32-2)>>1)<>1)<