diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 84db802a9..9f65b7bb7 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -930,7 +930,7 @@ void UsbPacketReceived(uint8_t *packet, int len) setSamplingConfig((sample_config *) c->d.asBytes); break; case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K: - cmd_send(CMD_ACK, SampleLF(c->arg[0]),0,0,0,0); + cmd_send(CMD_ACK,SampleLF(c->arg[0], c->arg[1]),0,0,0,0); break; case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); @@ -1085,7 +1085,15 @@ void UsbPacketReceived(uint8_t *packet, int len) LegicRfInfo(); break; case CMD_LEGIC_ESET: - LegicEMemSet(c->arg[0], c->arg[1], c->d.asBytes); + //----------------------------------------------------------------------------- + // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not + // involved in dealing with emulator memory. But if it is called later, it might + // destroy the Emulator Memory. + //----------------------------------------------------------------------------- + // arg0 = offset + // arg1 = num of bytes + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + emlSet(c->d.asBytes, c->arg[0], c->arg[1]); break; #endif @@ -1499,9 +1507,9 @@ void __attribute__((noreturn)) AppMain(void) for(;;) { if ( usb_poll_validate_length() ) { rx_len = usb_read(rx, sizeof(UsbCommand)); - if (rx_len) { + + if (rx_len) UsbPacketReceived(rx, rx_len); - } } WDT_HIT(); diff --git a/armsrc/apps.h b/armsrc/apps.h index 19d90edc6..4c5a26ce2 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -31,6 +31,7 @@ extern "C" { #include "iso14443b.h" #include "emvcard.h" +extern const uint8_t OddByteParity[256]; extern int rsamples; // = 0; extern int tracing; // = TRUE; extern uint8_t trigger; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 8481c5d6f..3d7386cdf 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -77,7 +77,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t periods, uint3 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); // now do the read - DoAcquisition_config(false); + DoAcquisition_config(false, 0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } @@ -459,7 +459,6 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol) OUT: FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); - DbpString("Simulation stopped"); return; } @@ -784,6 +783,7 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) size_t size = 0; uint32_t hi2=0, hi=0, lo=0; int idx=0; + int dummyIdx = 0; // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); @@ -795,10 +795,10 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition_default(0, true); + DoAcquisition_default(-1,true); // FSK demodulator size = 50*128*2; //big enough to catch 2 sequences of largest format - idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo); + idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx); if (idx>0 && lo>0 && (size==96 || size==192)){ // go over previously decoded manchester data and decode into usable tag ID @@ -880,7 +880,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 @@ -894,87 +894,74 @@ 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 = detectAWID(dest, &size, &dummyIdx); if (idx<=0 || size!=96) continue; - // Index map - // 0 10 20 30 40 50 60 - // | | | | | | | - // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96 - // ----------------------------------------------------------------------------- - // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1 - // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96 - // |---26 bit---| |-----117----||-------------142-------------| - // b = format bit len, o = odd parity of last 3 bits - // f = facility code, c = card number - // w = wiegand parity - // (26 bit format shown) - - //get raw ID before removing parities - uint32_t rawLo = bytebits_to_byte(dest+idx+64,32); - uint32_t rawHi = bytebits_to_byte(dest+idx+32,32); - uint32_t rawHi2 = bytebits_to_byte(dest+idx,32); - - size = removeParity(dest, idx+8, 4, 1, 88); + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96 + // ----------------------------------------------------------------------------- + // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1 + // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96 + // |---26 bit---| |-----117----||-------------142-------------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + // (26 bit format shown) + + //get raw ID before removing parities + uint32_t rawLo = bytebits_to_byte(dest+idx+64,32); + uint32_t rawHi = bytebits_to_byte(dest+idx+32,32); + uint32_t rawHi2 = bytebits_to_byte(dest+idx,32); + + size = removeParity(dest, idx+8, 4, 1, 88); if (size != 66) continue; - - // Index map - // 0 10 20 30 40 50 60 - // | | | | | | | - // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456 - // ----------------------------------------------------------------------------- - // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000 - // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - // |26 bit| |-117--| |-----142------| - // - // 00110010 0 0000011111010000000000000001000100101000100001111 0 00000000 - // bbbbbbbb w ffffffffffffffffccccccccccccccccccccccccccccccccc w xxxxxxxx - // |50 bit| |----4000------||-----------2248975-------------| - // - // b = format bit len, o = odd parity of last 3 bits - // f = facility code, c = card number - // w = wiegand parity - - uint32_t fc = 0; - uint32_t cardnum = 0; - uint32_t code1 = 0; - uint32_t code2 = 0; - uint8_t fmtLen = bytebits_to_byte(dest,8); - switch(fmtLen) { - case 26: - fc = bytebits_to_byte(dest + 9, 8); - cardnum = bytebits_to_byte(dest + 17, 16); - code1 = bytebits_to_byte(dest + 8,fmtLen); - Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); - break; - case 50: - fc = bytebits_to_byte(dest + 9, 16); - cardnum = bytebits_to_byte(dest + 25, 32); - code1 = bytebits_to_byte(dest + 8, (fmtLen-32) ); - code2 = bytebits_to_byte(dest + 8 + (fmtLen-32), 32); - Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); - break; - default: - if (fmtLen > 32 ) { - cardnum = bytebits_to_byte(dest+8+(fmtLen-17), 16); - code1 = bytebits_to_byte(dest+8,fmtLen-32); - code2 = bytebits_to_byte(dest+8+(fmtLen-32),32); - Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); - } else { - cardnum = bytebits_to_byte(dest+8+(fmtLen-17), 16); - code1 = bytebits_to_byte(dest+8,fmtLen); - Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); - } - break; + // ok valid card found! + + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456 + // ----------------------------------------------------------------------------- + // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000 + // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // |26 bit| |-117--| |-----142------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + // (26 bit format shown) + + uint32_t fc = 0; + uint32_t cardnum = 0; + uint32_t code1 = 0; + uint32_t code2 = 0; + uint8_t fmtLen = bytebits_to_byte(dest,8); + if (fmtLen==26){ + fc = bytebits_to_byte(dest+9, 8); + cardnum = bytebits_to_byte(dest+17, 16); + code1 = bytebits_to_byte(dest+8,fmtLen); + Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); + } else { + cardnum = bytebits_to_byte(dest+8+(fmtLen-17), 16); + if (fmtLen>32){ + code1 = bytebits_to_byte(dest+8,fmtLen-32); + code2 = bytebits_to_byte(dest+8+(fmtLen-32),32); + Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); + } else{ + code1 = bytebits_to_byte(dest+8,fmtLen); + Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); } - if (findone) - break; - + } + if (findone){ + if (ledcontrol) LED_A_OFF(); + break; + } + // reset idx = 0; WDT_HIT(); } - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); DbpString("Stopped"); if (ledcontrol) LED_A_OFF(); } @@ -1044,14 +1031,15 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol) void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); - int idx=0; + int dummyIdx = 0; + int idx = 0; uint32_t code=0, code2=0; uint8_t version=0; uint8_t facilitycode=0; uint16_t number=0; uint8_t crc = 0; uint16_t calccrc = 0; - + size_t size = BigBuf_max_traceLen(); //clear read buffer BigBuf_Clear_keep_EM(); @@ -1064,7 +1052,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 = detectIOProx(dest, &size, &dummyIdx); if (idx<0) continue; //valid tag found @@ -1210,7 +1198,7 @@ void T55xxResetRead(void) { TurnReadLFOn(READ_GAP); // Acquisition - doT55x7Acquisition(BigBuf_max_traceLen()); + DoPartialAcquisition(0, true, BigBuf_max_traceLen()); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off @@ -1223,6 +1211,7 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) LED_A_ON(); bool PwdMode = arg & 0x1; uint8_t Page = (arg & 0x2)>>1; + bool testMode = arg & 0x4; uint32_t i = 0; // Set up FPGA, 125kHz @@ -1234,9 +1223,11 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(START_GAP); - // Opcode 10 - T55xxWriteBit(1); - T55xxWriteBit(Page); //Page 0 + if (testMode) Dbprintf("TestMODE"); + // Std Opcode 10 + T55xxWriteBit(testMode ? 0 : 1); + T55xxWriteBit(testMode ? 1 : Page); //Page 0 + if (PwdMode){ // Send Pwd for (i = 0x80000000; i != 0; i >>= 1) @@ -1255,12 +1246,32 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, // so wait a little more) - TurnReadLFOn(20 * 1000); + + // "there is a clock delay before programming" + // - 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 t5577 vs t5567 vs e5550 (or q5) marshmellow... + if (testMode) { + //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); + + } 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 - // need to know the current block 0 config mode + //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 + // need to know the current block 0 config mode for + // modulation clock an other details to demod the response... + // 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); @@ -1279,7 +1290,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { bool PwdMode = arg0 & 0x1; uint8_t Page = (arg0 & 0x2) >> 1; uint32_t i = 0; - bool RegReadMode = (Block == 0xFF); + bool RegReadMode = (Block == 0xFF);//regular read mode //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); @@ -1319,7 +1330,8 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { TurnReadLFOn(210*8); // Acquisition - doT55x7Acquisition(7679); + // Now do the acquisition + DoPartialAcquisition(0, true, 12000); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off @@ -1398,7 +1410,7 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { data[0] = T55x7_BITRATE_RF_50 | T55x7_MODULATION_FSK2a | last_block << T55x7_MAXBLOCK_SHIFT; //TODO add selection of chip for Q5 or T55x7 - // data[0] = (((50-2)>>1)<>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 2 << T5555_MAXBLOCK_SHIFT; + // data[0] = T5555_SET_BITRATE(64) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 2 << T5555_MAXBLOCK_SHIFT; LED_D_ON(); // Program the data blocks for supplied ID @@ -1424,7 +1435,7 @@ void CopyIndala64toT55x7(uint32_t hi, uint32_t lo) { // and the Config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2) uint32_t data[] = { T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo}; //TODO add selection of chip for Q5 or T55x7 - // data[0] = (((32-2)>>1)<>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; + if (Q5) data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; // Program the data blocks for supplied ID and the block 0 config WriteT55xx(data, 0, 3); LED_D_OFF(); @@ -1531,8 +1541,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) { } data[0] = clock | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT); } else { //t5555 (Q5) - // t5555 (Q5) BITRATE = (RF-2)/2 (iceman) - data[0] = ( ((clock-2) >> 1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); + data[0] = T5555_SET_BITRATE(clock) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); } WriteT55xx(data, 0, 3); @@ -1818,7 +1827,7 @@ void Cotag(uint32_t arg0) { switch(rawsignal) { case 0: doCotagAcquisition(50000); break; case 1: doCotagAcquisitionManchester(); break; - case 2: DoAcquisition_config(true); break; + case 2: DoAcquisition_config(true, 0); break; } // Turn the field off diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 668b2493c..a8b8d7a47 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -209,33 +209,33 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag uint32_t DoAcquisition_default(int trigger_threshold, bool silent) { return DoAcquisition(1, 8, 0,trigger_threshold, silent, 0); } -uint32_t DoAcquisition_config( bool silent) { +uint32_t DoAcquisition_config( bool silent, int sample_size) { return DoAcquisition(config.decimation ,config.bits_per_sample ,config.averaging ,config.trigger_threshold ,silent - ,0); + ,sample_size); } uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size) { return DoAcquisition(1, 8, 0, trigger_threshold, silent, sample_size); } -uint32_t ReadLF(bool activeField, bool silent) { +uint32_t ReadLF(bool activeField, bool silent, int sample_size) { if (!silent) printConfig(); LFSetupFPGAForADC(config.divisor, activeField); - return DoAcquisition_config(silent); + return DoAcquisition_config(silent, sample_size); } /** * Initializes the FPGA for reader-mode (field on), and acquires the samples. * @return number of bits sampled **/ -uint32_t SampleLF(bool printCfg) { +uint32_t SampleLF(bool printCfg, int sample_size) { BigBuf_Clear_ext(false); - uint32_t ret = ReadLF(true, printCfg); + uint32_t ret = ReadLF(true, printCfg, sample_size); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); return ret; } @@ -245,7 +245,7 @@ uint32_t SampleLF(bool printCfg) { **/ uint32_t SnoopLF() { BigBuf_Clear_ext(false); - uint32_t ret = ReadLF(false, true); + uint32_t ret = ReadLF(false, true, 0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); return ret; } diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index b300ee73d..4e5cd5295 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -27,13 +27,12 @@ void doT55x7Acquisition(size_t sample_size); * Initializes the FPGA for reader-mode (field on), and acquires the samples. * @return number of bits sampled **/ -uint32_t SampleLF(bool silent); +uint32_t SampleLF(bool silent, int sample_size); /** * Initializes the FPGA for snoop-mode (field off), and acquires the samples. * @return number of bits sampled **/ - uint32_t SnoopLF(); // adds sample size to default options @@ -55,7 +54,7 @@ uint32_t DoAcquisition_default(int trigger_threshold, bool silent); * @return number of bits sampled */ -uint32_t DoAcquisition_config( bool silent); +uint32_t DoAcquisition_config(bool silent, int sample_size); /** * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream diff --git a/client/Makefile b/client/Makefile index c4169dd91..9710c411c 100644 --- a/client/Makefile +++ b/client/Makefile @@ -82,8 +82,8 @@ CORESRCS = uart_posix.c \ uart_win32.c \ util.c \ util_posix.c \ - scandir.c \ - sleep.c + scandir.c + CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ @@ -133,11 +133,13 @@ CMDSRCS = crapto1/crapto1.c \ cmdlfhid.c \ cmdlfhitag.c \ cmdlfio.c \ + cmdlfindala.c \ cmdlfjablotron.c \ cmdlfnexwatch.c \ cmdlfnedap.c \ cmdlfnoralsy.c \ cmdlfpac.c \ + cmdlfparadox.c \ cmdlfpcf7931.c \ cmdlfpresco.c \ cmdlfpyramid.c \ @@ -181,7 +183,7 @@ ifeq ($(MULTIARCHSRCS), ) endif ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c -ZLIBFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED +ZLIBFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED #-DDEBUG -Dverbose=1 QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp guidummy.cpp diff --git a/client/cli.c b/client/cli.c index fe1c6fdec..f0f1c7461 100644 --- a/client/cli.c +++ b/client/cli.c @@ -7,7 +7,7 @@ //----------------------------------------------------------------------------- #include -#include "sleep.h" +#include "util_posix.h" #include "ui.h" //#include "proxusb.h" #include "cmdmain.h" diff --git a/client/cmdcrc.c b/client/cmdcrc.c index 249fdebc0..22abd5488 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -7,23 +7,7 @@ //----------------------------------------------------------------------------- // CRC Calculations from the software reveng commands //----------------------------------------------------------------------------- - -#include -#ifdef _WIN32 -# include -# include -# ifndef STDIN_FILENO -# define STDIN_FILENO 0 -# endif /* STDIN_FILENO */ -#endif /* _WIN32 */ - -#include -#include -#include "cmdmain.h" #include "cmdcrc.h" -#include "reveng/reveng.h" -#include "ui.h" -#include "util.h" #define MAX_ARGS 20 diff --git a/client/cmdcrc.h b/client/cmdcrc.h index d1dd1c171..d625191b3 100644 --- a/client/cmdcrc.h +++ b/client/cmdcrc.h @@ -11,9 +11,28 @@ #ifndef CMDCRC_H__ #define CMDCRC_H__ -int CmdCrc(const char *Cmd); +#ifdef _WIN32 +# include +# include +# ifndef STDIN_FILENO +# define STDIN_FILENO 0 +# endif /* STDIN_FILENO */ +#endif /* _WIN32 */ -int CmdrevengSearch(const char *Cmd); -int GetModels(char *Models[], int *count, uint8_t *width); -int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result); +#include +#include +#include +#include +#include "cmdmain.h" +#include "reveng/reveng.h" +#include "ui.h" +#include "util.h" + + + +extern int CmdCrc(const char *Cmd); + +extern int CmdrevengSearch(const char *Cmd); +extern int GetModels(char *Models[], int *count, uint8_t *width); +extern int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result); #endif diff --git a/client/cmddata.c b/client/cmddata.c index c6b27b26f..91aed6fd8 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -27,19 +27,7 @@ int usage_data_printdemodbuf(void){ PrintAndLog(" l enter length to print in # of bits or hex characters respectively"); return 0; } -int usage_data_askem410xdemod(void){ - PrintAndLog("Usage: data askem410xdemod [clock] <0|1> [maxError]"); - PrintAndLog(" [set clock as integer] optional, if not set, autodetect."); - PrintAndLog(" , 1 for invert output"); - PrintAndLog(" [set maximum allowed errors], default = 100."); - PrintAndLog(""); - PrintAndLog(" sample: data askem410xdemod = demod an EM410x Tag ID from GraphBuffer"); - PrintAndLog(" : data askem410xdemod 32 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32"); - PrintAndLog(" : data askem410xdemod 32 1 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLog(" : data askem410xdemod 1 = demod an EM410x Tag ID from GraphBuffer while inverting data"); - PrintAndLog(" : data askem410xdemod 64 1 0 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors"); - return 0; -} + int usage_data_manrawdecode(void){ PrintAndLog("Usage: data manrawdecode [invert] [maxErr]"); PrintAndLog(" Takes 10 and 01 and converts to 0 and 1 respectively"); @@ -239,21 +227,68 @@ int usage_data_buffclear(void){ return 0; } +int usage_data_fsktonrz() { + PrintAndLog("Usage: data fsktonrz c l f "); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" c enter the a clock (omit to autodetect)"); + PrintAndLog(" l enter a field clock (omit to autodetect)"); + PrintAndLog(" f enter a field clock (omit to autodetect)"); + return 0; +} + + //set the demod buffer with given array of binary (one bit per byte) //by marshmellow -void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx) -{ - if (buff == NULL) return; +void setDemodBuf(uint8_t *buf, size_t size, size_t startIdx) { + if (buf == NULL) return; - if (size >= MAX_DEMOD_BUF_LEN) - size = MAX_DEMOD_BUF_LEN; + if ( size > MAX_DEMOD_BUF_LEN - startIdx) + size = MAX_DEMOD_BUF_LEN - startIdx; for (size_t i = 0; i < size; i++) - DemodBuffer[i] = buff[startIdx++]; + DemodBuffer[i] = buf[startIdx++]; DemodBufferLen = size; } + +bool getDemodBuf(uint8_t *buff, size_t *size) { + if (buff == NULL) return false; + if (size == NULL) return false; + if (*size == 0) return false; + + *size = (*size > DemodBufferLen) ? DemodBufferLen : *size; + + memcpy(buff, DemodBuffer, *size); + return true; +} + +// option '1' to save DemodBuffer any other to restore +void save_restoreDB(uint8_t saveOpt) +{ + static uint8_t SavedDB[MAX_DEMOD_BUF_LEN]; + static size_t SavedDBlen; + static bool DB_Saved = false; + static int savedDemodStartIdx = 0; + static int savedDemodClock = 0; + + if (saveOpt == GRAPH_SAVE) { //save + + memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer)); + SavedDBlen = DemodBufferLen; + DB_Saved=true; + savedDemodStartIdx = g_DemodStartIdx; + savedDemodClock = g_DemodClock; + } else if (DB_Saved) { //restore + memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer)); + DemodBufferLen = SavedDBlen; + g_DemodClock = savedDemodClock; + g_DemodStartIdx = savedDemodStartIdx; + } + return; +} + int CmdSetDebugMode(const char *Cmd) { int demod = 0; sscanf(Cmd, "%i", &demod); @@ -262,25 +297,24 @@ int CmdSetDebugMode(const char *Cmd) { } //by marshmellow -void printDemodBuff(void) -{ +// max output to 512 bits if we have more - should be plenty +void printDemodBuff(void) { int bitLen = DemodBufferLen; if (bitLen < 1) { PrintAndLog("no bits found in demod buffer"); return; } - if (bitLen > 512) bitLen=512; //max output to 512 bits if we have more - should be plenty + if (bitLen > 512) bitLen = 512; char *bin = sprint_bin_break(DemodBuffer, bitLen,16); PrintAndLog("%s",bin); } -int CmdPrintDemodBuff(const char *Cmd) -{ +int CmdPrintDemodBuff(const char *Cmd) { char hex[512] = {0x00}; bool hexMode = false; bool errors = false; - uint32_t offset = 0; //could be size_t but no param_get16... + uint32_t offset = 0; uint32_t length = 512; char cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -335,8 +369,7 @@ int CmdPrintDemodBuff(const char *Cmd) //by marshmellow //this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer -int CmdGetBitStream(const char *Cmd) -{ +int CmdGetBitStream(const char *Cmd) { CmdHpf(Cmd); for (uint32_t i = 0; i < GraphTraceLen; i++) GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; @@ -345,166 +378,6 @@ int CmdGetBitStream(const char *Cmd) return 0; } -//by marshmellow -//print 64 bit EM410x ID in multiple formats -void printEM410x(uint32_t hi, uint64_t id) -{ - if (!id && !hi) return; - - PrintAndLog("EM410x %s pattern found", (hi) ? "XL" : "" ); - - uint64_t iii=1; - uint64_t id2lo=0; - uint32_t ii=0; - uint32_t i=0; - for (ii=5; ii>0;ii--){ - for (i=0;i<8;i++){ - id2lo=(id2lo<<1LL) | ((id & (iii << (i+((ii-1)*8)))) >> (i+((ii-1)*8))); - } - } - - if (hi){ - //output 88 bit em id - PrintAndLog("\nEM TAG ID : %06X%016" PRIX64, hi, id); - } else{ - //output 40 bit em id - PrintAndLog("\nEM TAG ID : %010" PRIX64, id); - PrintAndLog("\nPossible de-scramble patterns"); - PrintAndLog("Unique TAG ID : %010" PRIX64, id2lo); - PrintAndLog("HoneyWell IdentKey {"); - PrintAndLog("DEZ 8 : %08" PRIu64, id & 0xFFFFFF); - PrintAndLog("DEZ 10 : %010" PRIu64, id & 0xFFFFFFFF); - PrintAndLog("DEZ 5.5 : %05" PRIu64 ".%05" PRIu64, (id>>16LL) & 0xFFFF, (id & 0xFFFF)); - PrintAndLog("DEZ 3.5A : %03" PRIu64 ".%05" PRIu64, (id>>32ll), (id & 0xFFFF)); - PrintAndLog("DEZ 3.5B : %03" PRIu64 ".%05" PRIu64, (id & 0xFF000000) >> 24, (id & 0xFFFF)); - PrintAndLog("DEZ 3.5C : %03" PRIu64 ".%05" PRIu64, (id & 0xFF0000) >> 16, (id & 0xFFFF)); - PrintAndLog("DEZ 14/IK2 : %014" PRIu64, id); - PrintAndLog("DEZ 15/IK3 : %015" PRIu64, id2lo); - PrintAndLog("DEZ 20/ZK : %02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64, - (id2lo & 0xf000000000) >> 36, - (id2lo & 0x0f00000000) >> 32, - (id2lo & 0x00f0000000) >> 28, - (id2lo & 0x000f000000) >> 24, - (id2lo & 0x0000f00000) >> 20, - (id2lo & 0x00000f0000) >> 16, - (id2lo & 0x000000f000) >> 12, - (id2lo & 0x0000000f00) >> 8, - (id2lo & 0x00000000f0) >> 4, - (id2lo & 0x000000000f) - ); - uint64_t paxton = (((id>>32) << 24) | (id & 0xffffff)) + 0x143e00; - PrintAndLog("}\nOther : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id&0xFFFF), ((id>>16LL) & 0xFF), (id & 0xFFFFFF)); - PrintAndLog("Pattern Paxton : %" PRIu64 " [0x%" PRIX64 "]", paxton, paxton); - - uint32_t p1id = (id & 0xFFFFFF); - uint8_t arr[32] = {0x00}; - int i =0; - int j = 23; - for (; i < 24; ++i, --j ){ - arr[i] = (p1id >> i) & 1; - } - - uint32_t p1 = 0; - - p1 |= arr[23] << 21; - p1 |= arr[22] << 23; - p1 |= arr[21] << 20; - p1 |= arr[20] << 22; - - p1 |= arr[19] << 18; - p1 |= arr[18] << 16; - p1 |= arr[17] << 19; - p1 |= arr[16] << 17; - - p1 |= arr[15] << 13; - p1 |= arr[14] << 15; - p1 |= arr[13] << 12; - p1 |= arr[12] << 14; - - p1 |= arr[11] << 6; - p1 |= arr[10] << 2; - p1 |= arr[9] << 7; - p1 |= arr[8] << 1; - - p1 |= arr[7] << 0; - p1 |= arr[6] << 8; - p1 |= arr[5] << 11; - p1 |= arr[4] << 3; - - p1 |= arr[3] << 10; - p1 |= arr[2] << 4; - p1 |= arr[1] << 5; - p1 |= arr[0] << 9; - PrintAndLog("Pattern 1 : %d [0x%X]", p1, p1); - - uint16_t sebury1 = id & 0xFFFF; - uint8_t sebury2 = (id >> 16) & 0x7F; - uint32_t sebury3 = id & 0x7FFFFF; - PrintAndLog("Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3); - } - return; -} - -int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ) -{ - size_t idx = 0; - size_t size = DemodBufferLen; - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; - memcpy(BitStream, DemodBuffer, size); - int ans = Em410xDecode(BitStream, &size, &idx, hi, lo); - if ( ans < 0){ - if (g_debugMode){ - if (ans == -1) - PrintAndLog("DEBUG: Error - Em410x not only 0|1 in decoded bitstream"); - else if (ans == -2) - PrintAndLog("DEBUG: Error - Em410x preamble not found"); - else if (ans == -3) - PrintAndLog("DEBUG: Error - Em410x Size not correct: %d", size); - else if (ans == -4) - PrintAndLog("DEBUG: Error - Em410x parity failed"); - } - return 0; - } - if (!lo && !hi) { - PrintAndLog("DEBUG: Error - Em410x decoded to all zeros"); - return 0; - } - - //set GraphBuffer for clone or sim command - setDemodBuf(BitStream, size, idx); - if (g_debugMode){ - PrintAndLog("DEBUG: Em410x idx: %d, Len: %d, Printing Demod Buffer:", idx, size); - printDemodBuff(); - } - - if (verbose) - printEM410x(*hi, *lo); - - return 1; -} - -int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose) -{ - bool st = true; - if (!ASKDemod_ext(Cmd, false, false, 1, &st)) return 0; - return AskEm410xDecode(verbose, hi, lo); -} - -//by marshmellow -//takes 3 arguments - clock, invert and maxErr as integers -//attempts to demodulate ask while decoding manchester -//prints binary found and saves in graphbuffer for further commands -int CmdAskEM410xDemod(const char *Cmd) -{ - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') - return usage_data_askem410xdemod(); - - uint64_t lo = 0; - uint32_t hi = 0; - return AskEm410xDemod(Cmd, &hi, &lo, true); -} - //by marshmellow //Cmd Args: Clock, invert, maxErr, maxLen as integers and amplify as char == 'a' // (amp may not be needed anymore) @@ -540,7 +413,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool st = false; size_t ststart = 0, stend = 0; - if (*stCheck) st = DetectST_ext(BitStream, &BitLen, &foundclk, &ststart, &stend); + if (*stCheck) st = DetectST(BitStream, &BitLen, &foundclk, &ststart, &stend); if (st) { *stCheck = st; clk = (clk == 0) ? foundclk : clk; @@ -548,7 +421,8 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, CursorDPos = stend; if (verbose || g_debugMode) PrintAndLog("\nFound Sequence Terminator - First one is shown by orange and blue graph markers"); } - int errCnt = askdemod(BitStream, &BitLen, &clk, &invert, maxErr, askamp, askType); + int startIdx = 0; + int errCnt = askdemod_ext(BitStream, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); if (errCnt<0 || BitLen<16){ //if fatal error (or -1) if (g_debugMode) PrintAndLog("DEBUG: no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk); return 0; @@ -561,6 +435,8 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, //output setDemodBuf(BitStream,BitLen,0); + setClockGrid(clk, startIdx); + if (verbose || g_debugMode){ if (errCnt>0) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); @@ -615,8 +491,7 @@ int Cmdmandecoderaw(const char *Cmd) if (strlen(Cmd) > 5 || cmdp == 'h' || cmdp == 'H') return usage_data_manrawdecode(); if (DemodBufferLen==0) return 0; - - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; + uint8_t BitStream[MAX_DEMOD_BUF_LEN]={0}; int high = 0, low = 0; for (; i < DemodBufferLen; ++i){ if (DemodBuffer[i] > high) @@ -632,7 +507,8 @@ int Cmdmandecoderaw(const char *Cmd) sscanf(Cmd, "%i %i", &invert, &maxErr); size = i; - errCnt = manrawdecode(BitStream, &size, invert); + uint8_t alignPos = 0; + errCnt = manrawdecode(BitStream, &size, invert, &alignPos); if (errCnt >= maxErr){ PrintAndLog("Too many errors: %d",errCnt); return 0; @@ -670,10 +546,10 @@ int CmdBiphaseDecodeRaw(const char *Cmd) PrintAndLog("DemodBuffer Empty - run 'data rawdemod ar' first"); return 0; } - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - memcpy(BitStream, DemodBuffer, DemodBufferLen); - size = DemodBufferLen; - errCnt=BiphaseRawDecode(BitStream, &size, offset, invert); + uint8_t BitStream[MAX_DEMOD_BUF_LEN]={0}; + size = sizeof(BitStream); + if ( !getDemodBuf(BitStream, &size) ) return 0; + errCnt=BiphaseRawDecode(BitStream, &size, &offset, invert); if (errCnt < 0){ PrintAndLog("Error during decode:%d", errCnt); return 0; @@ -691,6 +567,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) if (offset) setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); //remove first bit from raw demod + setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2); return 1; } @@ -708,15 +585,16 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) if (g_debugMode) PrintAndLog("DEBUG: no data in graphbuf"); return 0; } + int startIdx = 0; //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer - int errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0); + int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx); if ( errCnt < 0 || errCnt > maxErr ) { if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk); return 0; } //attempt to Biphase decode BitStream - errCnt = BiphaseRawDecode(BitStream, &size, offset, invert); + errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert); if (errCnt < 0){ if (g_debugMode || verbose) PrintAndLog("DEBUG: Error BiphaseRawDecode: %d", errCnt); return 0; @@ -727,6 +605,7 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) } //success set DemodBuffer and return setDemodBuf(BitStream, size, 0); + setClockGrid(clk, startIdx + clk*offset/2); if (g_debugMode || verbose){ PrintAndLog("Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt); printDemodBuff(); @@ -742,103 +621,6 @@ int Cmdaskbiphdemod(const char *Cmd) return ASKbiphaseDemod(Cmd, true); } -//by marshmellow -//attempts to demodulate and identify a G_Prox_II verex/chubb card -//WARNING: if it fails during some points it will destroy the DemodBuffer data -// but will leave the GraphBuffer intact. -//if successful it will push askraw data back to demod buffer ready for emulation -int CmdG_Prox_II_Demod(const char *Cmd) -{ - if (!ASKbiphaseDemod(Cmd, false)){ - if (g_debugMode) PrintAndLog("DEBUG: Error - gProxII ASKbiphaseDemod failed 1st try"); - return 0; - } - size_t size = DemodBufferLen; - //call lfdemod.c demod for gProxII - int ans = gProxII_Demod(DemodBuffer, &size); - if (ans < 0){ - if (g_debugMode) PrintAndLog("DEBUG: Error - gProxII demod"); - return 0; - } - //got a good demod of 96 bits - uint8_t ByteStream[8] = {0x00}; - uint8_t xorKey = 0; - size_t startIdx = ans + 6; //start after 6 bit preamble - - uint8_t bits_no_spacer[90]; - //so as to not mess with raw DemodBuffer copy to a new sample array - memcpy(bits_no_spacer, DemodBuffer + startIdx, 90); - // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72)) - size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run - if (bitLen != 72) { - if (g_debugMode) - PrintAndLog("DEBUG: Error - gProxII spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx); - return 0; - } - // get key and then get all 8 bytes of payload decoded - xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8); - for (size_t idx = 0; idx < 8; idx++) { - ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey; - if (g_debugMode) PrintAndLog("DEBUG: gProxII byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]); - } - - //ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data - uint8_t fmtLen = ByteStream[0]>>2; - uint32_t FC = 0; - uint32_t Card = 0; - //get raw 96 bits to print - uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32); - uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32); - uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32); - bool unknown = false; - switch(fmtLen) { - case 36: - FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); - Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); - break; - case 26: - FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7); - Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7); - break; - default : - unknown = true; - break; - } - if ( !unknown) - PrintAndLog("G-Prox-II Found: Format Len: %ubit - FC: %u - Card: %u, Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3); - else - PrintAndLog("Unknown G-Prox-II Fmt Found: Format Len: %u, Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3); - - setDemodBuf(DemodBuffer+ans, 96, 0); - return 1; -} - -//by marshmellow -//see ASKDemod for what args are accepted -int CmdVikingDemod(const char *Cmd) -{ - if (!ASKDemod(Cmd, false, false, 1)) { - if (g_debugMode) PrintAndLog("DEBUG: Error - Viking ASKDemod failed"); - return 0; - } - size_t size = DemodBufferLen; - - int ans = VikingDemod_AM(DemodBuffer, &size); - if (ans < 0) { - if (g_debugMode) PrintAndLog("DEBUG: Error - Viking Demod %d %s", ans, (ans == -5)?"[chksum error]":""); - return 0; - } - //got a good demod - uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32); - uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32); - uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32); - uint8_t checksum = bytebits_to_byte(DemodBuffer+ans+32+24, 8); - PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, checksum); - PrintAndLog("Raw: %08X%08X", raw1,raw2); - setDemodBuf(DemodBuffer+ans, 64, 0); - return 1; -} - //by marshmellow - see ASKDemod int Cmdaskrawdemod(const char *Cmd) { @@ -983,8 +765,7 @@ int CmdUndec(const char *Cmd) //by marshmellow //shift graph zero up or down based on input + or - -int CmdGraphShiftZero(const char *Cmd) -{ +int CmdGraphShiftZero(const char *Cmd) { int shift = 0, shiftedVal = 0; //set options from parameters entered with the command sscanf(Cmd, "%i", &shift); @@ -1021,8 +802,7 @@ int AskEdgeDetect(const int *in, int *out, int len, int threshold) { //use large jumps in read samples to identify edges of waves and then amplify that wave to max //similar to dirtheshold, threshold commands //takes a threshold length which is the measured length between two samples then determines an edge -int CmdAskEdgeDetect(const char *Cmd) -{ +int CmdAskEdgeDetect(const char *Cmd) { int thresLen = 25; int ans = 0; sscanf(Cmd, "%i", &thresLen); @@ -1127,12 +907,15 @@ int FSKrawDemod(const char *Cmd, bool verbose) } //get bit clock length if (!rfLen) { - rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow); + int firstClockEdge = 0; //todo - align grid on graph with this... + rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow, &firstClockEdge); if (!rfLen) rfLen = 50; } - int size = fskdemod(BitStream, BitLen, rfLen, invert, fchigh, fclow); + int startIdx = 0; + int size = fskdemod(BitStream, BitLen, rfLen, invert, fchigh, fclow, &startIdx); if (size > 0) { setDemodBuf(BitStream, size, 0); + setClockGrid(rfLen, startIdx); // Now output the bitstream to the scrollback by line of 16 bits if (verbose || g_debugMode) { @@ -1159,599 +942,6 @@ int CmdFSKrawdemod(const char *Cmd) return FSKrawDemod(Cmd, true); } -//by marshmellow (based on existing demod + holiman's refactor) -//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded) -//print full HID Prox ID and some bit format details if found -int CmdFSKdemodHID(const char *Cmd) -{ - //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint32_t hi2=0, hi=0, lo=0; - - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(BitStream); - if (BitLen==0) return 0; - //get binary from fsk wave - int idx = HIDdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo); - if (idx<0){ - if (g_debugMode){ - if (idx==-1){ - PrintAndLog("DEBUG: Error - HID just noise detected"); - } else if (idx == -2) { - PrintAndLog("DEBUG: Error - HID problem during FSK demod"); - } else if (idx == -3) { - PrintAndLog("DEBUG: Error - HID preamble not found"); - } else if (idx == -4) { - PrintAndLog("DEBUG: Error - HID error in Manchester data, SIZE: %d", BitLen); - } else { - PrintAndLog("DEBUG: Error - HID error demoding fsk %d", idx); - } - } - return 0; - } - if (hi2==0 && hi==0 && lo==0) { - if (g_debugMode) PrintAndLog("DEBUG: Error - HID no values found"); - return 0; - } - if (hi2 != 0){ //extra large HID tags - PrintAndLog("HID Prox TAG ID: %x%08x%08x (%u)", hi2, hi, lo, (lo>>1) & 0xFFFF); - } - else { //standard HID tags <38 bits - uint8_t fmtLen = 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++; - } - fmtLen =idx3+19; - fc =0; - cardnum=0; - if(fmtLen==26){ - cardnum = (lo>>1)&0xFFFF; - fc = (lo>>17)&0xFF; - } - if(fmtLen==34){ - cardnum = (lo>>1)&0xFFFF; - fc= ((hi&1)<<15)|(lo>>17); - } - if(fmtLen==35){ - cardnum = (lo>>1)&0xFFFFF; - fc = ((hi&1)<<11)|(lo>>21); - } - } - else { //if bit 38 is not set then 37 bit format is used - fmtLen = 37; - fc = 0; - cardnum = 0; - if(fmtLen == 37){ - cardnum = (lo>>1)&0x7FFFF; - fc = ((hi&0xF)<<12)|(lo>>20); - } - } - PrintAndLog("HID Prox TAG ID: %x%08x (%u) - Format Len: %ubit - FC: %u - Card: %u", hi, lo, (lo>>1) & 0xFFFF, fmtLen, fc, cardnum); - } - setDemodBuf(BitStream,BitLen,idx); - if (g_debugMode){ - PrintAndLog("DEBUG: HID idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen); - printDemodBuff(); - } - return 1; -} - -//by marshmellow -//Paradox Prox demod - FSK RF/50 with preamble of 00001111 (then manchester encoded) -//print full Paradox Prox ID and some bit format details if found -int CmdFSKdemodParadox(const char *Cmd) -{ - //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint32_t hi2=0, hi=0, lo=0; - - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - size_t BitLen = getFromGraphBuf(BitStream); - if (BitLen==0) return 0; - //get binary from fsk wave - int idx = ParadoxdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo); - if (idx<0){ - if (g_debugMode){ - if (idx==-1){ - PrintAndLog("DEBUG: Error - Paradox just noise detected"); - } else if (idx == -2) { - PrintAndLog("DEBUG: Error - Paradox error demoding fsk"); - } else if (idx == -3) { - PrintAndLog("DEBUG: Error - Paradox preamble not found"); - } else if (idx == -4) { - PrintAndLog("DEBUG: Error - Paradox error in Manchester data"); - } else { - PrintAndLog("DEBUG: Error - Paradox error demoding fsk %d", idx); - } - } - return 0; - } - if (hi2==0 && hi==0 && lo==0){ - if (g_debugMode) PrintAndLog("DEBUG: Error - Paradox no value found"); - return 0; - } - uint32_t fc = ((hi & 0x3)<<6) | (lo>>26); - uint32_t cardnum = (lo>>10)&0xFFFF; - uint32_t rawLo = bytebits_to_byte(BitStream+idx+64,32); - uint32_t rawHi = bytebits_to_byte(BitStream+idx+32,32); - uint32_t rawHi2 = bytebits_to_byte(BitStream+idx,32); - - PrintAndLog("Paradox TAG ID: %x%08x - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x", - hi>>10, (hi & 0x3)<<26 | (lo>>10), fc, cardnum, (lo>>2) & 0xFF, rawHi2, rawHi, rawLo); - setDemodBuf(BitStream,BitLen,idx); - if (g_debugMode){ - PrintAndLog("DEBUG: Paradox idx: %d, len: %d, Printing Demod Buffer:", idx, BitLen); - printDemodBuff(); - } - return 1; -} - -//by marshmellow -//IO-Prox demod - FSK RF/64 with preamble of 000000001 -//print ioprox ID and some format details -int CmdFSKdemodIO(const char *Cmd) -{ - int retval = 0; - int idx = 0; - char crcStr[20]; - memset(crcStr, 0x00, sizeof(crcStr) ); - - //something in graphbuffer? - if (GraphTraceLen < 65) { - if (g_debugMode)PrintAndLog("DEBUG: Error - IO prox not enough samples in GraphBuffer"); - return retval; - } - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - size_t bitlen = getFromGraphBuf(BitStream); - if (bitlen == 0) return retval; - - //get binary from fsk wave - idx = IOdemodFSK(BitStream, bitlen); - if (idx<0){ - if (g_debugMode){ - if (idx==-1){ - PrintAndLog("DEBUG: Error - IO prox just noise detected"); - } else if (idx == -2) { - PrintAndLog("DEBUG: Error - IO prox not enough samples"); - } else if (idx == -3) { - PrintAndLog("DEBUG: Error - IO prox error during fskdemod"); - } else if (idx == -4) { - PrintAndLog("DEBUG: Error - IO prox preamble not found"); - } else if (idx == -5) { - PrintAndLog("DEBUG: Error - IO prox separator bits not found"); - } else { - PrintAndLog("DEBUG: Error - IO prox error demoding fsk %d", idx); - } - } - return retval; - } - if (idx==0){ - if (g_debugMode){ - PrintAndLog("DEBUG: Error - IO prox data not found - FSK Bits: %d", bitlen); - if (bitlen > 92) PrintAndLog("%s", sprint_bin_break(BitStream,92,16)); - } - return retval; - } - //Index map - //0 10 20 30 40 50 60 - //| | | | | | | - //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 - //----------------------------------------------------------------------------- - //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 - // - //XSF(version)facility:codeone+codetwo (raw) - //Handle the data - if (idx + 64 > bitlen) { - if (g_debugMode) PrintAndLog("DEBUG: Error - IO prox not enough bits found - bitlen: %d", bitlen); - return retval; - } - - if (g_debugMode) { - PrintAndLog("%d%d%d%d%d%d%d%d %d", BitStream[idx], BitStream[idx+1], BitStream[idx+2], BitStream[idx+3], BitStream[idx+4], BitStream[idx+5], BitStream[idx+6], BitStream[idx+7], BitStream[idx+8]); - PrintAndLog("%d%d%d%d%d%d%d%d %d", BitStream[idx+9], BitStream[idx+10], BitStream[idx+11],BitStream[idx+12],BitStream[idx+13],BitStream[idx+14],BitStream[idx+15],BitStream[idx+16],BitStream[idx+17]); - PrintAndLog("%d%d%d%d%d%d%d%d %d facility", BitStream[idx+18], BitStream[idx+19], BitStream[idx+20],BitStream[idx+21],BitStream[idx+22],BitStream[idx+23],BitStream[idx+24],BitStream[idx+25],BitStream[idx+26]); - PrintAndLog("%d%d%d%d%d%d%d%d %d version", BitStream[idx+27], BitStream[idx+28], BitStream[idx+29],BitStream[idx+30],BitStream[idx+31],BitStream[idx+32],BitStream[idx+33],BitStream[idx+34],BitStream[idx+35]); - PrintAndLog("%d%d%d%d%d%d%d%d %d code1", BitStream[idx+36], BitStream[idx+37], BitStream[idx+38],BitStream[idx+39],BitStream[idx+40],BitStream[idx+41],BitStream[idx+42],BitStream[idx+43],BitStream[idx+44]); - PrintAndLog("%d%d%d%d%d%d%d%d %d code2", BitStream[idx+45], BitStream[idx+46], BitStream[idx+47],BitStream[idx+48],BitStream[idx+49],BitStream[idx+50],BitStream[idx+51],BitStream[idx+52],BitStream[idx+53]); - PrintAndLog("%d%d%d%d%d%d%d%d %d%d checksum", BitStream[idx+54],BitStream[idx+55],BitStream[idx+56],BitStream[idx+57],BitStream[idx+58],BitStream[idx+59],BitStream[idx+60],BitStream[idx+61],BitStream[idx+62],BitStream[idx+63]); - } - - uint32_t code = bytebits_to_byte(BitStream+idx,32); - uint32_t code2 = bytebits_to_byte(BitStream+idx+32,32); - uint8_t version = bytebits_to_byte(BitStream+idx+27,8); //14,4 - uint8_t facilitycode = bytebits_to_byte(BitStream+idx+18,8) ; - uint16_t number = (bytebits_to_byte(BitStream+idx+36,8)<<8)|(bytebits_to_byte(BitStream+idx+45,8)); //36,9 - uint8_t crc = bytebits_to_byte(BitStream+idx+54,8); - uint16_t calccrc = 0; - - for (uint8_t i = 1; i < 6; ++i){ - calccrc += bytebits_to_byte(BitStream + idx + 9 * i ,8); - } - calccrc &= 0xff; - calccrc = 0xff - calccrc; - - if (crc == calccrc) { - snprintf(crcStr, 3, "ok"); - retval = 1; - } else { - if (g_debugMode) PrintAndLog("DEBUG: Error - IO prox crc failed"); - - snprintf(crcStr, 20, "failed 0x%02X != 0x%02X", crc, calccrc); - retval = 0; - } - - PrintAndLog("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [crc %s]",version,facilitycode,number,code,code2, crcStr); - setDemodBuf(BitStream,64,idx); - if (g_debugMode){ - PrintAndLog("DEBUG: IO prox idx: %d, Len: %d, Printing demod buffer:", idx, 64); - printDemodBuff(); - } - return retval; -} - -//by marshmellow -//AWID Prox demod - FSK RF/50 with preamble of 00000001 (always a 96 bit data stream) -//print full AWID Prox ID and some bit format details if found -int CmdFSKdemodAWID(const char *Cmd) -{ - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - size_t size = getFromGraphBuf(BitStream); - if (size==0) return 0; - - //get binary from fsk wave - int idx = AWIDdemodFSK(BitStream, &size); - if (idx<=0){ - if (g_debugMode){ - if (idx == -1) - PrintAndLog("DEBUG: Error - AWID not enough samples"); - else if (idx == -2) - PrintAndLog("DEBUG: Error - AWID only noise found"); - else if (idx == -3) - PrintAndLog("DEBUG: Error - AWID problem during FSK demod"); - else if (idx == -4) - PrintAndLog("DEBUG: Error - AWID preamble not found"); - else if (idx == -5) - PrintAndLog("DEBUG: Error - AWID size not correct: %d", size); - else - PrintAndLog("DEBUG: Error - AWID error %d",idx); - } - return 0; - } - - // Index map - // 0 10 20 30 40 50 60 - // | | | | | | | - // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96 - // ----------------------------------------------------------------------------- - // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1 - // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96 - // |---26 bit---| |-----117----||-------------142-------------| - // b = format bit len, o = odd parity of last 3 bits - // f = facility code, c = card number - // w = wiegand parity - // (26 bit format shown) - - //get raw ID before removing parities - uint32_t rawLo = bytebits_to_byte(BitStream+idx+64,32); - uint32_t rawHi = bytebits_to_byte(BitStream+idx+32,32); - uint32_t rawHi2 = bytebits_to_byte(BitStream+idx,32); - setDemodBuf(BitStream,96,idx); - - size = removeParity(BitStream, idx+8, 4, 1, 88); - if (size != 66){ - if (g_debugMode) PrintAndLog("DEBUG: Error - AWID at parity check-tag size does not match AWID format"); - return 0; - } - // ok valid card found! - - // Index map - // 0 10 20 30 40 50 60 - // | | | | | | | - // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456 - // ----------------------------------------------------------------------------- - // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000 - // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - // |26 bit| |-117--| |-----142------| - // - // 00110010 0 0000111110100000 00000000000100010010100010000111 1 000000000 - // bbbbbbbb w ffffffffffffffff cccccccccccccccccccccccccccccccc w xxxxxxxxx - // |50 bit| |----4000------| |-----------2248975------------| - // b = format bit len, o = odd parity of last 3 bits - // f = facility code, c = card number - // w = wiegand parity - - uint32_t fc = 0; - uint32_t cardnum = 0; - uint32_t code1 = 0; - uint32_t code2 = 0; - uint8_t fmtLen = bytebits_to_byte(BitStream, 8); - - switch(fmtLen) { - case 26: - fc = bytebits_to_byte(BitStream + 9, 8); - cardnum = bytebits_to_byte(BitStream + 17, 16); - code1 = bytebits_to_byte(BitStream + 8,fmtLen); - PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); - break; - case 34: - fc = bytebits_to_byte(BitStream + 9, 8); - cardnum = bytebits_to_byte(BitStream + 17, 24); - code1 = bytebits_to_byte(BitStream + 8, (fmtLen-32) ); - code2 = bytebits_to_byte(BitStream + 8 + (fmtLen-32), 32); - PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); - break; - case 37: - fc = bytebits_to_byte(BitStream + 9, 13); - cardnum = bytebits_to_byte(BitStream + 22, 18); - code1 = bytebits_to_byte(BitStream + 8, (fmtLen-32) ); - code2 = bytebits_to_byte(BitStream + 8 + (fmtLen-32), 32); - PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); - break; - // case 40: - // break; - case 50: - fc = bytebits_to_byte(BitStream + 9, 16); - cardnum = bytebits_to_byte(BitStream + 25, 32); - code1 = bytebits_to_byte(BitStream + 8, (fmtLen-32) ); - code2 = bytebits_to_byte(BitStream + 8 + (fmtLen-32), 32); - PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); - break; - default: - if (fmtLen > 32 ) { - cardnum = bytebits_to_byte(BitStream+8+(fmtLen-17), 16); - code1 = bytebits_to_byte(BitStream+8,fmtLen-32); - code2 = bytebits_to_byte(BitStream+8+(fmtLen-32),32); - PrintAndLog("AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); - } else { - cardnum = bytebits_to_byte(BitStream+8+(fmtLen-17), 16); - code1 = bytebits_to_byte(BitStream+8,fmtLen); - PrintAndLog("AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); - } - break; - } - - if (g_debugMode){ - PrintAndLog("DEBUG: AWID idx: %d, Len: %d Printing Demod Buffer:", idx, 96); - printDemodBuff(); - } - return 1; -} - -//by marshmellow -//Pyramid Prox demod - FSK RF/50 with preamble of 0000000000000001 (always a 128 bit data stream) -//print full Farpointe Data/Pyramid Prox ID and some bit format details if found -int CmdFSKdemodPyramid(const char *Cmd) -{ - //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - size_t size = getFromGraphBuf(BitStream); - if (size==0) return 0; - - //get binary from fsk wave - int idx = PyramiddemodFSK(BitStream, &size); - if (idx < 0){ - if (g_debugMode){ - if (idx == -5) - PrintAndLog("DEBUG: Error - Pyramid: not enough samples"); - else if (idx == -1) - PrintAndLog("DEBUG: Error - Pyramid: only noise found"); - else if (idx == -2) - PrintAndLog("DEBUG: Error - Pyramid: problem during FSK demod"); - else if (idx == -3) - PrintAndLog("DEBUG: Error - Pyramid: size not correct: %d", size); - else if (idx == -4) - PrintAndLog("DEBUG: Error - Pyramid: preamble not found"); - else - PrintAndLog("DEBUG: Error - Pyramid: idx: %d",idx); - } - return 0; - } - // Index map - // 0 10 20 30 40 50 60 - // | | | | | | | - // 0123456 7 8901234 5 6789012 3 4567890 1 2345678 9 0123456 7 8901234 5 6789012 3 - // ----------------------------------------------------------------------------- - // 0000000 0 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 - // premable xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o - - // 64 70 80 90 100 110 120 - // | | | | | | | - // 4567890 1 2345678 9 0123456 7 8901234 5 6789012 3 4567890 1 2345678 9 0123456 7 - // ----------------------------------------------------------------------------- - // 0000000 1 0000000 1 0000000 1 0110111 0 0011000 1 0000001 0 0001100 1 1001010 0 - // xxxxxxx o xxxxxxx o xxxxxxx o xswffff o ffffccc o ccccccc o ccccccw o ppppppp o - // |---115---||---------71---------| - // s = format start bit, o = odd parity of last 7 bits - // f = facility code, c = card number - // w = wiegand parity, x = extra space for other formats - // p = CRC8maxim checksum - // (26 bit format shown) - - //get bytes for checksum calc - uint8_t checksum = bytebits_to_byte(BitStream + idx + 120, 8); - uint8_t csBuff[14] = {0x00}; - for (uint8_t i = 0; i < 13; i++){ - csBuff[i] = bytebits_to_byte(BitStream + idx + 16 + (i*8), 8); - } - //check checksum calc - //checksum calc thanks to ICEMAN!! - uint32_t checkCS = CRC8Maxim(csBuff, 13); - - //get raw ID before removing parities - uint32_t rawLo = bytebits_to_byte(BitStream+idx+96, 32); - uint32_t rawHi = bytebits_to_byte(BitStream+idx+64, 32); - uint32_t rawHi2 = bytebits_to_byte(BitStream+idx+32, 32); - uint32_t rawHi3 = bytebits_to_byte(BitStream+idx, 32); - setDemodBuf(BitStream, 128, idx); - - size = removeParity(BitStream, idx+8, 8, 1, 120); - if (size != 105){ - if (g_debugMode) { - if ( size == 0) - PrintAndLog("DEBUG: Error - Pyramid: parity check failed - IDX: %d, hi3: %08X", idx, rawHi3); - else - PrintAndLog("DEBUG: Error - Pyramid: at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %08X", size, idx, rawHi3); - } - return 0; - } - - // ok valid card found! - - // Index map - // 0 10 20 30 40 50 60 70 - // | | | | | | | | - // 01234567890123456789012345678901234567890123456789012345678901234567890 - // ----------------------------------------------------------------------- - // 00000000000000000000000000000000000000000000000000000000000000000000000 - // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - - // 71 80 90 100 - // | | | | - // 1 2 34567890 1234567890123456 7 8901234 - // --------------------------------------- - // 1 1 01110011 0000000001000110 0 1001010 - // s w ffffffff cccccccccccccccc w ppppppp - // |--115-| |------71------| - // s = format start bit, o = odd parity of last 7 bits - // f = facility code, c = card number - // w = wiegand parity, x = extra space for other formats - // p = CRC8-Maxim checksum - // (26 bit format shown) - - //find start bit to get fmtLen - int j; - for (j=0; j < size; ++j){ - if(BitStream[j]) break; - } - - uint8_t fmtLen = size-j-8; - uint32_t fc = 0; - uint32_t cardnum = 0; - uint32_t code1 = 0; - - if ( fmtLen == 26 ){ - fc = bytebits_to_byte(BitStream+73, 8); - cardnum = bytebits_to_byte(BitStream+81, 16); - code1 = bytebits_to_byte(BitStream+72,fmtLen); - PrintAndLog("Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi3, rawHi2, rawHi, rawLo); - } else if (fmtLen == 45) { - fmtLen = 42; //end = 10 bits not 7 like 26 bit fmt - fc = bytebits_to_byte(BitStream+53, 10); - cardnum = bytebits_to_byte(BitStream+63, 32); - PrintAndLog("Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, rawHi3, rawHi2, rawHi, rawLo); - } else { - cardnum = bytebits_to_byte(BitStream+81, 16); - PrintAndLog("Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); - } - if (checksum == checkCS) - PrintAndLog("Checksum %02x passed", checksum); - else - PrintAndLog("Checksum %02x failed - should have been %02x", checksum, checkCS); - - if (g_debugMode){ - PrintAndLog("DEBUG: Pyramid: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128); - printDemodBuff(); - } - return 1; -} - -// FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits) -// 8 databits + 1 parity (1) -// CIITT 16 chksum -// NATIONAL CODE, ICAR database -// COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf -// FLAG (animal/non-animal) -/* -38 IDbits -10 country code -1 extra app bit -14 reserved bits -1 animal bit -16 ccitt CRC chksum over 64bit ID CODE. -24 appli bits. - --- sample: 985121004515220 [ 37FF65B88EF94 ] -*/ -int CmdFDXBdemodBI(const char *Cmd){ - - int invert = 1; - int clk = 32; - int errCnt = 0; - int maxErr = 0; - uint8_t BitStream[MAX_DEMOD_BUF_LEN]; - size_t size = getFromGraphBuf(BitStream); - - errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0); - if ( errCnt < 0 || errCnt > maxErr ) { - if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB no data or error found %d, clock: %d", errCnt, clk); - return 0; - } - - errCnt = BiphaseRawDecode(BitStream, &size, maxErr, 1); - if (errCnt < 0 || errCnt > maxErr ) { - if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB BiphaseRawDecode: %d", errCnt); - return 0; - } - - int preambleIndex = FDXBdemodBI(BitStream, &size); - if (preambleIndex < 0){ - if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB preamble not found :: %d",preambleIndex); - return 0; - } - if (size != 128) { - if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB incorrect data length found"); - return 0; - } - - setDemodBuf(BitStream, 128, preambleIndex); - - // remove marker bits (1's every 9th digit after preamble) (pType = 2) - size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117); - if ( size != 104 ) { - if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB error removeParity:: %d", size); - return 0; - } - PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); - - //got a good demod - uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32); - uint32_t countryCode = bytebits_to_byteLSBF(BitStream+38,10); - uint8_t dataBlockBit = BitStream[48]; - uint32_t reservedCode = bytebits_to_byteLSBF(BitStream+49,14); - uint8_t animalBit = BitStream[63]; - uint32_t crc16 = bytebits_to_byteLSBF(BitStream+64,16); - uint32_t extended = bytebits_to_byteLSBF(BitStream+80,24); - - uint64_t rawid = ((uint64_t)bytebits_to_byte(BitStream,32)<<32) | bytebits_to_byte(BitStream+32,32); - uint8_t raw[8]; - num_to_bytes(rawid, 8, raw); - - if (g_debugMode) PrintAndLog("Raw ID Hex: %s", sprint_hex(raw,8)); - - uint16_t calcCrc = crc16_ccitt_kermit(raw, 8); - PrintAndLog("Animal ID: %04u-%012" PRIu64, countryCode, NationalCode); - PrintAndLog("National Code: %012" PRIu64, NationalCode); - PrintAndLog("CountryCode: %04u", countryCode); - - PrintAndLog("Reserved/RFU: %u", reservedCode); - PrintAndLog("Animal Tag: %s", animalBit ? "True" : "False"); - PrintAndLog("Has extended data: %s [0x%X]", dataBlockBit ? "True" : "False", extended); - PrintAndLog("CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); - - if (g_debugMode) { - PrintAndLog("Start marker %d; Size %d", preambleIndex, size); - char *bin = sprint_bin_break(BitStream,size,16); - PrintAndLog("DEBUG BinStream:\n%s",bin); - } - return 1; -} - - //by marshmellow //attempt to psk1 demod graph buffer int PSKDemod(const char *Cmd, bool verbose) @@ -1769,17 +959,9 @@ int PSKDemod(const char *Cmd, bool verbose) uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; size_t BitLen = getFromGraphBuf(BitStream); if (BitLen==0) return 0; - - uint8_t carrier = countFC(BitStream, BitLen, 0); - if (carrier!=2 && carrier!=4 && carrier!=8){ - //invalid carrier - return 0; - } - - if (g_debugMode) PrintAndLog("Carrier: rf/%d",carrier); - int errCnt=0; - errCnt = pskRawDemod(BitStream, &BitLen, &clk, &invert); + int startIdx = 0; + errCnt = pskRawDemod_ext(BitStream, &BitLen, &clk, &invert, &startIdx); if (errCnt > maxErr){ if (g_debugMode || verbose) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); return 0; @@ -1796,60 +978,8 @@ int PSKDemod(const char *Cmd, bool verbose) } //prime demod buffer for output setDemodBuf(BitStream, BitLen, 0); - return 1; -} - -// Indala 26 bit decode -// by marshmellow -// optional arguments - same as CmdpskNRZrawDemod (clock & invert) -int CmdIndalaDecode(const char *Cmd) -{ - int ans; - if (strlen(Cmd)>0){ - ans = PSKDemod(Cmd, 0); - } else{ //default to RF/32 - ans = PSKDemod("32", 0); - } - - if (!ans){ - if (g_debugMode) PrintAndLog("DEBUG: Error - Indala can't demod signal: %d",ans); - return 0; - } - - uint8_t invert = 0; - size_t size = DemodBufferLen; - int startIdx = indala26decode(DemodBuffer, &size, &invert); - if (startIdx < 0 || size > 224) { - if (g_debugMode) PrintAndLog("DEBUG: Error - Indala wrong size, expected [64|224] got: %d", size); - return -1; - } - setDemodBuf(DemodBuffer, size, (size_t)startIdx); - if (invert) - if (g_debugMode) PrintAndLog("DEBUG: Error - Indala had to invert bits"); - - //convert UID to HEX - uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; - uid1 = bytebits_to_byte(DemodBuffer,32); - uid2 = bytebits_to_byte(DemodBuffer+32,32); - if (DemodBufferLen==64){ - PrintAndLog("Indala Found - Bitlength %d, UID = (%x%08x)\n%s", - DemodBufferLen, uid1, uid2, sprint_bin_break(DemodBuffer,DemodBufferLen,32) - ); - } else { - uid3 = bytebits_to_byte(DemodBuffer+64,32); - uid4 = bytebits_to_byte(DemodBuffer+96,32); - uid5 = bytebits_to_byte(DemodBuffer+128,32); - uid6 = bytebits_to_byte(DemodBuffer+160,32); - uid7 = bytebits_to_byte(DemodBuffer+192,32); - PrintAndLog("Indala Found - Bitlength %d, UID = (%x%08x%08x%08x%08x%08x%08x)\n%s", - DemodBufferLen, - uid1, uid2, uid3, uid4, uid5, uid6, uid7, sprint_bin_break(DemodBuffer,DemodBufferLen,32) - ); - } - if (g_debugMode){ - PrintAndLog("DEBUG: Indala - printing demodbuffer:"); - printDemodBuff(); - } + setClockGrid(clk, startIdx); + return 1; } @@ -1862,7 +992,7 @@ int CmdPSKIdteck(const char *Cmd) { size_t size = DemodBufferLen; //get binary from PSK1 wave - int idx = IdteckDemodPSK(DemodBuffer, &size); + int idx = detectIdteck(DemodBuffer, &size); if (idx < 0){ if (g_debugMode){ if (idx == -1) @@ -1880,7 +1010,7 @@ int CmdPSKIdteck(const char *Cmd) { if (g_debugMode) PrintAndLog("DEBUG: Error - Idteck PSKDemod failed"); return 0; } - idx = IdteckDemodPSK(DemodBuffer, &size); + idx = detectIdteck(DemodBuffer, &size); if (idx < 0){ if (g_debugMode){ if (idx == -1) @@ -1932,7 +1062,8 @@ int NRZrawDemod(const char *Cmd, bool verbose) size_t BitLen = getFromGraphBuf(BitStream); if (BitLen==0) return 0; int errCnt=0; - errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert); + int clkStartIdx = 0; + errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert, &clkStartIdx); if (errCnt > maxErr){ if (g_debugMode) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); return 0; @@ -1944,6 +1075,8 @@ int NRZrawDemod(const char *Cmd, bool verbose) if (verbose || g_debugMode) PrintAndLog("Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen); //prime demod buffer for output setDemodBuf(BitStream,BitLen,0); + setClockGrid(clk, clkStartIdx); + if (errCnt>0 && (verbose || g_debugMode)) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); if (verbose || g_debugMode) { @@ -2033,7 +1166,31 @@ int CmdRawDemod(const char *Cmd) return ans; } -//iceman: diff sizes on the plotwindow? + +void setClockGrid(int clk, int offset) { + g_DemodStartIdx = offset; + g_DemodClock = clk; + if (g_debugMode) PrintAndLog("demodoffset %d, clk %d",offset,clk); + + if (offset > clk) offset %= clk; + if (offset < 0) offset += clk; + + if (offset > GraphTraceLen || offset < 0) return; + if (clk < 8 || clk > GraphTraceLen) { + GridLocked = false; + GridOffset = 0; + PlotGridX = 0; + PlotGridXdefault = 0; + RepaintGraphWindow(); + } else { + GridLocked = true; + GridOffset = offset; + PlotGridX = clk; + PlotGridXdefault = clk; + RepaintGraphWindow(); + } +} + int CmdGrid(const char *Cmd) { sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); @@ -2042,10 +1199,6 @@ int CmdGrid(const char *Cmd) RepaintGraphWindow(); return 0; } -void setGrid_Clock(uint8_t clock){ - PlotGridXdefault = clock; - RepaintGraphWindow(); -} int CmdSetGraphMarkers(const char *Cmd) { sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos); @@ -2137,23 +1290,22 @@ uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) return val; } -int getSamples(const char *Cmd, bool silent) +int getSamples(int n, bool silent) { //If we get all but the last byte in bigbuf, // we don't have to worry about remaining trash // in the last byte in case the bits-per-sample // does not line up on byte boundaries - uint8_t got[BIGBUF_SIZE-1] = { 0 }; - int n = strtol(Cmd, NULL, 0); - if ( n == 0 || n > sizeof(got)) n = sizeof(got); if (!silent) PrintAndLog("Reading %d bytes from device memory\n", n); GetFromBigBuf(got,n,0); + if (!silent) PrintAndLog("Data fetched"); + UsbCommand response; if ( !WaitForResponseTimeout(CMD_ACK, &response, 10000) ) { PrintAndLog("timeout while waiting for reply."); @@ -2186,13 +1338,16 @@ int getSamples(const char *Cmd, bool silent) GraphTraceLen = n; } + setClockGrid(0,0); + DemodBufferLen = 0; RepaintGraphWindow(); return 0; } int CmdSamples(const char *Cmd) { - return getSamples(Cmd, false); + int n = strtol(Cmd, NULL, 0); + return getSamples(n, false); } int CmdTuneSamples(const char *Cmd) @@ -2286,16 +1441,17 @@ int CmdLoad(const char *Cmd) fclose(f); PrintAndLog("loaded %d samples", GraphTraceLen); + setClockGrid(0,0); + DemodBufferLen = 0; RepaintGraphWindow(); return 0; } int CmdLtrim(const char *Cmd) { - int ds = atoi(Cmd); - if (GraphTraceLen <= 0) return 0; + int ds = atoi(Cmd); for (int i = ds; i < GraphTraceLen; ++i) GraphBuffer[i-ds] = GraphBuffer[i]; @@ -2321,9 +1477,9 @@ int CmdMtrim(const char *Cmd) { if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return 0; start++; //leave start position sample - GraphTraceLen -= stop - start; + GraphTraceLen = stop - start; for (int i = 0; i < GraphTraceLen; i++) { - GraphBuffer[start+i] = GraphBuffer[stop+i]; + GraphBuffer[i] = GraphBuffer[start+i]; } return 0; } @@ -2341,7 +1497,7 @@ int CmdNorm(const char *Cmd) if (max != min) { for (i = 0; i < GraphTraceLen; ++i) { - GraphBuffer[i] = (GraphBuffer[i] - ((max + min) / 2)) * 256 / (max - min); + GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min); //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work } } @@ -2390,6 +1546,7 @@ int CmdScale(const char *Cmd) RepaintGraphWindow(); return 0; } + int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t down) { int lastValue = in[0]; @@ -2528,6 +1685,196 @@ int Cmdhex2bin(const char *Cmd) return 0; } + /* // example of FSK2 RF/50 Tones + static const int LowTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 + }; + static const int HighTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, // note one extra 1 to padd due to 50/8 remainder (1/2 the remainder) + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, -1, // note one extra -1 to padd due to 50/8 remainder + }; + */ +void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighToneFC) { + int i,j=0; + int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC)/2); + int Right_Modifier = (clk % LowToneFC) / 2; + //int HighToneMod = clk mod HighToneFC; + int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate + int FCs_per_clk = clk/LowToneFC; + + // need to correctly split up the clock to field clocks. + // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk + + // start with LowTone + // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk + for (i = 0; i < Left_Modifier; i++) { + LowTone[i] = 1; + } + + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < LowToneFC; j++) { + LowTone[(i*LowToneFC)+Left_Modifier+j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } + + int k; + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + LowTone[((i-1)*LowToneFC)+Left_Modifier+j+k] = -1; + } + + // now do hightone + Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC)/2); + Right_Modifier = (clk % HighToneFC) / 2; + LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC/2); //truncate + FCs_per_clk = clk/HighToneFC; + + for (i = 0; i < Left_Modifier; i++) { + HighTone[i] = 1; + } + + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < HighToneFC; j++) { + HighTone[(i*HighToneFC)+Left_Modifier+j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } + + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + PrintAndLog("(i-1)*HighToneFC+lm+j+k %i",((i-1)*HighToneFC)+Left_Modifier+j+k); + HighTone[((i-1)*HighToneFC)+Left_Modifier+j+k] = -1; + } + if (g_debugMode == 2) { + for ( i = 0; i < clk; i++) { + PrintAndLog("Low: %i, High: %i",LowTone[i],HighTone[i]); + } + } +} + +//old CmdFSKdemod adapted by marshmellow +//converts FSK to clear NRZ style wave. (or demodulates) +int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { + uint8_t ans=0; + if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) { + int firstClockEdge=0; + ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, false, &firstClockEdge); + if (g_debugMode > 1) { + PrintAndLog ("DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans); + } + } + // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...) + if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) { + if (g_debugMode > 1) { + PrintAndLog ("DEBUG FSKtoNRZ: no fsk clocks found"); + } + return 0; + } + int LowTone[clk]; + int HighTone[clk]; + GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC); + + int i, j; + + // loop through ([all samples] - clk) + for (i = 0; i < *dataLen - clk; ++i) { + int lowSum = 0, highSum = 0; + + // sum all samples together starting from this sample for [clk] samples for each tone (multiply tone value with sample data) + for (j = 0; j < clk; ++j) { + lowSum += LowTone[j] * data[i+j]; + highSum += HighTone[j] * data[i + j]; + } + // get abs( [average sample value per clk] * 100 ) (or a rolling average of sorts) + lowSum = abs(100 * lowSum / clk); + highSum = abs(100 * highSum / clk); + // save these back to buffer for later use + data[i] = (highSum << 16) | lowSum; + } + + // now we have the abs( [average sample value per clk] * 100 ) for each tone + // loop through again [all samples] - clk - 16 + // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc + for(i = 0; i < *dataLen - clk - LowToneFC; ++i) { + int lowTot = 0, highTot = 0; + + // sum a field clock width of abs( [average sample values per clk] * 100) for each tone + for (j = 0; j < LowToneFC; ++j) { //10 for fsk2 + lowTot += (data[i + j] & 0xffff); + } + for (j = 0; j < HighToneFC; j++) { //8 for fsk2 + highTot += (data[i + j] >> 16); + } + + // subtract the sum of lowTone averages by the sum of highTone averages as it + // and write back the new graph value + data[i] = lowTot - highTot; + } + // update dataLen to what we put back to the data sample buffer + *dataLen -= (clk + LowToneFC); + return 0; +} + + +int CmdFSKToNRZ(const char *Cmd) { + // take clk, fc_low, fc_high + // blank = auto; + bool errors = false; + int clk = 0; + char cmdp = 0; + int fc_low = 10, fc_high = 8; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_data_fsktonrz(); + case 'C': + case 'c': + clk = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'F': + case 'f': + fc_high = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'L': + case 'l': + fc_low = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; + } + //Validations + if(errors) return usage_data_fsktonrz(); + + setClockGrid(0,0); + DemodBufferLen = 0; + int ans = FSKToNRZ(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high); + CmdNorm(""); + RepaintGraphWindow(); + return ans; +} + + int CmdDataIIR(const char *Cmd){ uint8_t k = param_get8(Cmd,0); //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); @@ -2540,9 +1887,6 @@ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, - {"askem410xdemod", CmdAskEM410xDemod, 1, "[clock] [invert<0|1>] [maxErr] -- Demodulate an EM410x tag from GraphBuffer (args optional)"}, - {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"}, - {"askvikingdemod", CmdVikingDemod, 1, "Demodulate a Viking AM tag from GraphBuffer"}, {"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"}, {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, {"bin2hex", Cmdbin2hex, 1, " -- Converts binary to hexadecimal"}, @@ -2550,13 +1894,8 @@ static command_t CommandTable[] = {"buffclear", CmdBuffClear, 1, "Clears bigbuff on deviceside. d graph window"}, {"dec", CmdDec, 1, "Decimate samples"}, {"detectclock", CmdDetectClockRate, 1, "[] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"}, - {"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"}, - {"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"}, - //{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"}, - {"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"}, - {"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"}, - {"fskpyramiddemod", CmdFSKdemodPyramid, 1, "Demodulate a Pyramid FSK tag from GraphBuffer"}, - {"fskparadoxdemod", CmdFSKdemodParadox, 1, "Demodulate a Paradox FSK tag from GraphBuffer"}, + {"fsktonrz", CmdFSKToNRZ, 1, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"}, + {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, @@ -2571,7 +1910,6 @@ static command_t CommandTable[] = {"norm", CmdNorm, 1, "Normalize max/min to +/-128"}, {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"}, {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, - {"pskindalademod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"}, {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, {"save", CmdSave, 1, " -- Save trace (from graph window)"}, diff --git a/client/cmddata.h b/client/cmddata.h index 379989622..5cc21f2a8 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -31,15 +31,17 @@ #include "crc.h" // for pyramid checksum maxim #include "crc16.h" // for FDXB demod checksum #include "loclass/cipherutils.h" // for decimating samples in getsamples +#include "cmdlfem4x.h" // askem410xdecode command_t * CmdDataCommands(); int CmdData(const char *Cmd); void printDemodBuff(void); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); -int CmdAskEM410xDemod(const char *Cmd); -int CmdVikingDemod(const char *Cmd); -int CmdG_Prox_II_Demod(const char *Cmd); +bool getDemodBuf(uint8_t *buff, size_t *size); +void save_restoreDB(uint8_t saveOpt);// option '1' to save DemodBuffer any other to restore +int CmdPrintDemodBuff(const char *Cmd); + int Cmdaskrawdemod(const char *Cmd); int Cmdaskmandemod(const char *Cmd); int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose); @@ -50,12 +52,6 @@ int CmdBitsamples(const char *Cmd); int CmdBuffClear(const char *Cmd); int CmdDec(const char *Cmd); int CmdDetectClockRate(const char *Cmd); -int CmdFDXBdemodBI(const char *Cmd); -int CmdFSKdemodAWID(const char *Cmd); -int CmdFSKdemodHID(const char *Cmd); -int CmdFSKdemodIO(const char *Cmd); -int CmdFSKdemodParadox(const char *Cmd); -int CmdFSKdemodPyramid(const char *Cmd); int CmdFSKrawdemod(const char *Cmd); int CmdPSK1rawDemod(const char *Cmd); int CmdPSK2rawDemod(const char *Cmd); @@ -80,19 +76,14 @@ int CmdSave(const char *Cmd); int CmdScale(const char *Cmd); int CmdDirectionalThreshold(const char *Cmd); int CmdZerocrossings(const char *Cmd); -int CmdIndalaDecode(const char *Cmd); -int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ); -int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose); int ASKbiphaseDemod(const char *Cmd, bool verbose); int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType); int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck); int FSKrawDemod(const char *Cmd, bool verbose); int PSKDemod(const char *Cmd, bool verbose); int NRZrawDemod(const char *Cmd, bool verbose); -void printEM410x(uint32_t hi, uint64_t id); -int getSamples(const char *Cmd, bool silent); - -void setGrid_Clock(uint8_t clock); +int getSamples(int n, bool silent); +void setClockGrid(int clk, int offset); int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t down); extern int AskEdgeDetect(const int *in, int *out, int len, int threshold); diff --git a/client/cmdhf.c b/client/cmdhf.c index 1815512ac..825aaee19 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -7,26 +7,7 @@ //----------------------------------------------------------------------------- // High frequency commands //----------------------------------------------------------------------------- - -#include -#include -#include "proxmark3.h" -#include "graph.h" -#include "ui.h" -#include "cmdparser.h" #include "cmdhf.h" -#include "cmdhf14a.h" -#include "cmdhf14b.h" -#include "cmdhf15.h" -#include "cmdhfepa.h" -#include "cmdhflegic.h" // LEGIC -#include "cmdhficlass.h" // ICLASS -#include "cmdhfmf.h" // CLASSIC -#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc -#include "cmdhfmfdes.h" // DESFIRE -#include "cmdhftopaz.h" // TOPAZ -#include "cmdhfemv.h" // EMV -#include "protocols.h" static int CmdHelp(const char *Cmd); @@ -658,14 +639,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui for (int j = 0; j < data_len && j/16 < 16; j++) { - int oddparity = 0x01; - int k; - - for (k=0 ; k<8 ; k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } uint8_t parityBits = parityBytes[j>>3]; - if (protocol != LEGIC && protocol != ISO_14443B && protocol != ISO_7816_4 && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + if (protocol != LEGIC && protocol != ISO_14443B && protocol != ISO_7816_4 && (isResponse || protocol == ISO_14443A) && (oddparity8(frame[j]) != ((parityBits >> (7-(j&0x0007))) & 0x01))) { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); } else { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]); @@ -751,6 +726,10 @@ int usage_hf_list(){ PrintAndLog(" 14a - interpret data as iso14443a communications"); PrintAndLog(" 14b - interpret data as iso14443b communications"); PrintAndLog(" des - interpret data as DESFire communications"); +#ifdef WITH_EMV + PrintAndLog(" emv - interpret data as EMV / communications"); +#endif + PrintAndLog(" iclass - interpret data as iclass communications"); PrintAndLog(" topaz - interpret data as topaz communications"); PrintAndLog(" 7816 - interpret data as iso7816-4 communications"); @@ -809,14 +788,14 @@ int CmdHFList(const char *Cmd) { param_getstr(Cmd,0,type); // validate type of output - if(strcmp(type, "iclass") == 0) protocol = ICLASS; - else if(strcmp(type, "14a") == 0) protocol = ISO_14443A; - else if(strcmp(type, "14b") == 0) protocol = ISO_14443B; - else if(strcmp(type, "topaz")== 0) protocol = TOPAZ; - else if(strcmp(type, "7816")== 0) protocol = ISO_7816_4; - else if(strcmp(type,"des")== 0) protocol = MFDES; - else if(strcmp(type,"legic")==0) protocol = LEGIC; - else if(strcmp(type, "raw")== 0) protocol = -1;//No crc, no annotations + if (strcmp(type, "iclass") == 0) protocol = ICLASS; + else if(strcmp(type, "14a") == 0) protocol = ISO_14443A; + else if(strcmp(type, "14b") == 0) protocol = ISO_14443B; + else if(strcmp(type, "topaz")== 0) protocol = TOPAZ; + else if(strcmp(type, "7816")== 0) protocol = ISO_7816_4; + else if(strcmp(type, "des")== 0) protocol = MFDES; + else if(strcmp(type, "legic")==0) protocol = LEGIC; + else if(strcmp(type, "raw")== 0) protocol = -1;//No crc, no annotations else errors = true; if (errors) return usage_hf_list(); @@ -923,19 +902,19 @@ int CmdHFSnoop(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, - {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, - {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, + {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, + {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, + {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, #ifdef WITH_EMV - {"emv", CmdHFEmv, 1, "{ EMV RFIDs... }"}, + {"emv", CmdHFEmv, 1, "{ EMV RFIDs... }"}, #endif - {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, - {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, - {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, - {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, - {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, - {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, + {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, + {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, + {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, + {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"list", CmdHFList, 1, "List protocol data in trace buffer"}, {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, diff --git a/client/cmdhf.h b/client/cmdhf.h index 74397a38c..dcb9448aa 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -11,8 +11,34 @@ #ifndef CMDHF_H__ #define CMDHF_H__ -int CmdHF(const char *Cmd); +#include +#include +#include +#include "proxmark3.h" +#include "graph.h" +#include "ui.h" +#include "cmdparser.h" +#include "cmdhf14a.h" +#include "cmdhf14b.h" +#include "cmdhf15.h" +#include "cmdhfepa.h" +#include "cmdhflegic.h" // LEGIC +#include "cmdhficlass.h" // ICLASS +#include "cmdhfmf.h" // CLASSIC +#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc +#include "cmdhfmfdes.h" // DESFIRE +#include "cmdhftopaz.h" // TOPAZ +#include "cmdhfemv.h" // EMV +#include "protocols.h" +#include "parity.h" // oddparity + +extern int CmdHF(const char *Cmd); extern int CmdHFTune(const char *Cmd); extern int CmdHFList(const char *Cmd); extern int CmdHFSearch(const char *Cmd); +extern int CmdHFSnoop(const char *Cmd); + +extern int usage_hf_list(); +extern int usage_hf_search(); +extern int usage_hf_snoop(); #endif diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 677efe3b8..82a4c463e 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -9,25 +9,7 @@ //----------------------------------------------------------------------------- // High frequency ISO14443A commands //----------------------------------------------------------------------------- - -#include -#include -#include -#include -#include "util.h" -#include "iso14443crc.h" -#include "data.h" -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" #include "cmdhf14a.h" -#include "common.h" -#include "cmdmain.h" -#include "mifare.h" -#include "cmdhfmf.h" -#include "cmdhfmfu.h" -#include "mifarehost.h" -#include "cmdhf.h" static int CmdHelp(const char *Cmd); static void waitCmd(uint8_t iLen); @@ -430,7 +412,7 @@ int CmdHF14ACUIDs(const char *Cmd) { n = n > 0 ? n : 1; PrintAndLog("Collecting %d UIDs", n); - PrintAndLog("Start: %u", time(NULL)); + PrintAndLog("Start: %" PRIu64, msclock()/1000); // repeat n times for (int i = 0; i < n; i++) { // execute anticollision procedure @@ -453,7 +435,7 @@ int CmdHF14ACUIDs(const char *Cmd) { PrintAndLog("%s", uid_string); } } - PrintAndLog("End: %u", time(NULL)); + PrintAndLog("End: %" PRIu64, msclock()/1000); return 1; } diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 82fa51975..46943f48f 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------- // 2011, Merlok // Copyright (C) 2010 iZsh -// +// 2015,216,2017 iceman, marshmellow, piwi // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -12,17 +12,36 @@ #ifndef CMDHF14A_H__ #define CMDHF14A_H__ -int CmdHF14A(const char *Cmd); -int CmdHF14AList(const char *Cmd); -int CmdHF14AMifare(const char *Cmd); -int CmdHF14AReader(const char *Cmd); -int CmdHF14ASim(const char *Cmd); -int CmdHF14ASniff(const char *Cmd); -int CmdHF14AEMVTransaction(const char *Cmd); +#include +#include +#include +#include +#include +#include "proxmark3.h" +#include "common.h" +#include "ui.h" +#include "util.h" +#include "cmdparser.h" +#include "cmdmain.h" +#include "iso14443crc.h" +#include "data.h" +#include "mifare.h" +#include "cmdhfmf.h" +#include "cmdhfmfu.h" +#include "cmdhf.h" // list cmd +#include "mifarehost.h" -char* getTagInfo(uint8_t uid); +extern int CmdHF14A(const char *Cmd); +extern int CmdHF14AList(const char *Cmd); +extern int CmdHF14AReader(const char *Cmd); +extern int CmdHF14ASim(const char *Cmd); +extern int CmdHF14ASniff(const char *Cmd); +extern int CmdHF14ACmdRaw(const char *Cmd); +extern int CmdHF14ACUIDs(const char *Cmd); -int usage_hf_14a_sim(void); -int usage_hf_14a_sniff(void); -int usage_hf_14a_raw(void); +extern char* getTagInfo(uint8_t uid); + +extern int usage_hf_14a_sim(void); +extern int usage_hf_14a_sniff(void); +extern int usage_hf_14a_raw(void); #endif diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 26527ea2c..c2c0ce378 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -221,10 +221,10 @@ int CmdHF14BCmdRaw (const char *Cmd) { bool success = true; // get back iso14b_card_select_t, don't print it. if (select) - success = waitCmd(false); + success = waitCmd14b(false); // get back response from the raw bytes you sent. - if (success && datalen>0) waitCmd(true); + if (success && datalen>0) waitCmd14b(true); return 1; } @@ -802,7 +802,7 @@ int srix4kValid(const char *Cmd){ return 0; } -bool waitCmd(bool verbose) { +bool waitCmd14b(bool verbose) { bool crc = false; uint8_t b1 = 0, b2 = 0; diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index 26eb9037a..5ee451bcf 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -54,5 +54,5 @@ int CmdHF14BCmdRaw (const char *Cmd); int CmdHF14BReadSri(const char *Cmd); int CmdHF14BWriteSri(const char *Cmd); -bool waitCmd(bool verbose); +bool waitCmd14b(bool verbose); #endif diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index d67735850..b50274296 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -7,16 +7,7 @@ //----------------------------------------------------------------------------- // Commands related to the German electronic Identification Card //----------------------------------------------------------------------------- - #include "cmdhfepa.h" -#include -#include "util.h" -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" -#include "common.h" -#include "cmdmain.h" -#include "sleep.h" static int CmdHelp(const char *Cmd); @@ -24,11 +15,11 @@ static int CmdHelp(const char *Cmd); int CmdHFEPACollectPACENonces(const char *Cmd) { // requested nonce size - unsigned int m = 0; + uint32_t m = 0; // requested number of Nonces - unsigned int n = 0; + uint32_t n = 0; // delay between requests - unsigned int d = 0; + uint32_t d = 0; sscanf(Cmd, "%u %u %u", &m, &n, &d); @@ -37,14 +28,14 @@ int CmdHFEPACollectPACENonces(const char *Cmd) n = n > 0 ? n : 1; PrintAndLog("Collecting %u %u byte nonces", n, m); - PrintAndLog("Start: %u", time(NULL)); + PrintAndLog("Start: %" PRIu64, msclock()/1000); // repeat n times - for (unsigned int i = 0; i < n; i++) { + for (uint32_t i = 0; i < n; i++) { // execute PACE UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}}; + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); // check if command failed @@ -64,13 +55,10 @@ int CmdHFEPACollectPACENonces(const char *Cmd) sleep(d); } } - PrintAndLog("End: %u", time(NULL)); + PrintAndLog("End: %" PRIu64, msclock()/1000); return 1; } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////The commands lie below here///////////////////////////////////////////////////////////////////////////////////////// - // perform the PACE protocol by replaying APDUs int CmdHFEPAPACEReplay(const char *Cmd) { @@ -139,6 +127,8 @@ int CmdHFEPAPACEReplay(const char *Cmd) memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)), apdus[i] + (j * sizeof(usb_cmd.d.asBytes)), packet_length); + + clearCommandBuffer(); SendCommand(&usb_cmd); WaitForResponse(CMD_ACK, &resp); if (resp.arg[0] != 0) { @@ -150,6 +140,7 @@ int CmdHFEPAPACEReplay(const char *Cmd) // now perform the replay usb_cmd.arg[0] = 0; + clearCommandBuffer(); SendCommand(&usb_cmd); WaitForResponse(CMD_ACK, &resp); if (resp.arg[0] != 0) { @@ -168,35 +159,25 @@ int CmdHFEPAPACEReplay(const char *Cmd) PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]); PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]); } - - return 1; } -////////////////////////////////The new commands lie above here///////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // UI-related stuff static const command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"cnonces", CmdHFEPACollectPACENonces, 0, - " Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"}, - {"preplay", CmdHFEPAPACEReplay, 0, - " Perform PACE protocol by replaying given APDUs"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"cnonces", CmdHFEPACollectPACENonces, 0, " Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"}, + {"preplay", CmdHFEPAPACEReplay, 0, " Perform PACE protocol by replaying given APDUs"}, + {NULL, NULL, 0, NULL} }; int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } int CmdHFEPA(const char *Cmd) { - // flush clearCommandBuffer(); - //WaitForResponseTimeout(CMD_ACK,NULL,100); - // parse CmdsParse(CommandTable, Cmd); return 0; } diff --git a/client/cmdhfepa.h b/client/cmdhfepa.h index 94ad7d231..914ce4c5d 100644 --- a/client/cmdhfepa.h +++ b/client/cmdhfepa.h @@ -11,8 +11,22 @@ #ifndef CMDHFEPA_H__ #define CMDHFEPA_H__ -int CmdHFEPA(const char *Cmd); +#include +#include +#include +#include +#include +#include "util.h" +#include "proxmark3.h" +#include "common.h" +#include "ui.h" +#include "cmdparser.h" +#include "cmdmain.h" +#include "util_posix.h" -int CmdHFEPACollectPACENonces(const char *Cmd); + +extern int CmdHFEPA(const char *Cmd); +extern int CmdHFEPACollectPACENonces(const char *Cmd); +extern int CmdHFEPAPACEReplay(const char *Cmd); #endif // CMDHFEPA_H__ diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 3904ba971..327927041 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -319,6 +319,7 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY; UsbCommand resp; while (!ukbhit()){ + clearCommandBuffer(); SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) { @@ -336,8 +337,23 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { PrintAndLog("CSN: %s",sprint_hex(data,8)); tagFound = true; } - if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s", sprint_hex(data+16, 8)); - if( readStatus & FLAG_ICLASS_READER_CONF) printIclassDumpInfo(data); + if( readStatus & FLAG_ICLASS_READER_CC) { + PrintAndLog(" CC: %s",sprint_hex(data+16,8)); + } + if( readStatus & FLAG_ICLASS_READER_CONF) { + printIclassDumpInfo(data); + } + if (readStatus & FLAG_ICLASS_READER_AA) { + bool legacy = true; + PrintAndLog(" AppIA: %s",sprint_hex(data+8*5,8)); + for (int i = 0; i<8; i++) { + if (data[8*5+i] != 0xFF) { + legacy = false; + } + } + PrintAndLog(" : Possible iClass %s",(legacy) ? "(legacy tag)" : "(NOT legacy tag)"); + } + if (tagFound && !loop) return 1; } else { if (verbose) PrintAndLog("Command execute timeout"); @@ -876,9 +892,6 @@ int CmdHFiClassReader_Dump(const char *Cmd) { // add diversified keys to dump if (have_debit_key) memcpy(tag_data+(3*8),div_key,8); if (have_credit_key) memcpy(tag_data+(4*8),c_div_key,8); - - printf("Num of bytes: %zu\n", gotBytes); - // print the dump printf("------+--+-------------------------+\n"); printf("CSN |00| %s|\n", sprint_hex(tag_data, 8)); @@ -1160,20 +1173,21 @@ int CmdHFiClassCloneTag(const char *Cmd) { return 1; } -static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose) { +static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) { uint8_t MAC[4]={0x00,0x00,0x00,0x00}; uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // block 0,1 should always be able to read, and block 5 on some cards. - if (blockno >= 2 ) { + if (auth || blockno >= 2) { if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose)) return 0; } else { uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - if (!select_only(CSN, CCNR, false, verbose)) - return false; + if (!select_only(CSN, CCNR, (keyType==0x18), verbose)) + return 0; } + UsbCommand resp; UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}}; clearCommandBuffer(); @@ -1203,6 +1217,7 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { bool elite = false; bool rawkey = false; bool errors = false; + bool auth = false; uint8_t cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { @@ -1229,6 +1244,7 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { break; case 'k': case 'K': + auth = true; dataLen = param_getstr(Cmd, cmdp+1, tempStr); if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); @@ -1259,7 +1275,10 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { } if (errors || cmdp < 4) return usage_hf_iclass_readblock(); - return ReadBlock(KEY, blockno, keyType, elite, rawkey, true); + + if (!auth) + PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication."); + return ReadBlock(KEY, blockno, keyType, elite, rawkey, true, auth); } int CmdHFiClass_loclass(const char *Cmd) { @@ -1597,8 +1616,8 @@ int CmdHFiClassManageKeys(const char *Cmd) { case 'n': case 'N': keyNbr = param_get8(Cmd, cmdp+1); - if (keyNbr == 0) { - PrintAndLog("Wrong block number"); + if (keyNbr >= ICLASS_KEYS_MAX) { + PrintAndLog("Invalid block number"); errors = true; } cmdp += 2; diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 5cd9b1c24..75871ab8b 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -172,19 +172,34 @@ int CmdLegicInfo(const char *Cmd) { int i = 0, k = 0, segmentNum = 0, segment_len = 0, segment_flag = 0; int crc = 0, wrp = 0, wrc = 0; uint8_t stamp_len = 0; - uint8_t data[1024]; // receiver buffer + uint16_t datalen = 0; char token_type[5] = {0,0,0,0,0}; int dcf = 0; int bIsSegmented = 0; - CmdLegicRdmem("0 22 55"); - - // copy data from device - GetEMLFromBigBuf(data, sizeof(data), 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000)){ - PrintAndLog("Command execute timeout"); + // tagtype + legic_card_select_t card; + if (legic_get_type(&card)) { + PrintAndLog("Failed to identify tagtype"); return 1; } + + PrintAndLog("Reading tag memory %d b...", card.cardsize); + + // allocate receiver buffer + uint8_t *data = malloc(card.cardsize); + if (!data) { + PrintAndLog("Cannot allocate memory"); + return 2; + } + memset(data, 0, card.cardsize); + + int status = legic_read_mem(0, card.cardsize, 0x55, data, &datalen); + if ( status > 0 ) { + PrintAndLog("Failed reading memory"); + free(data); + return 3; + } // Output CDF System area (9 bytes) plus remaining header area (12 bytes) crc = data[4]; @@ -298,8 +313,9 @@ int CmdLegicInfo(const char *Cmd) { uint32_t segCalcCRC = 0; uint32_t segCRC = 0; - // Data card? - if(dcf <= 60000) { + // Not Data card? + if (dcf > 60000) + goto out; PrintAndLog("\nADF: User Area"); PrintAndLog("------------------------------------------------------"); @@ -398,7 +414,8 @@ int CmdLegicInfo(const char *Cmd) { PrintAndLog("-----+------------------------------------------------\n"); // end with last segment - if (segment_flag & 0x8) return 0; + if (segment_flag & 0x8) + goto out; } // end for loop @@ -449,7 +466,9 @@ int CmdLegicInfo(const char *Cmd) { PrintAndLog("-----+------------------------------------------------\n"); } - } + +out: + free(data); return 0; } @@ -461,65 +480,28 @@ int CmdLegicRdmem(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_rdmem(); - uint32_t offset = 0, len = 0, IV = 1; - sscanf(Cmd, "%x %x %x", &offset, &len, &IV); - - // tagtype - legic_card_select_t card; - if (legic_get_type(&card)) { - PrintAndLog("Failed to identify tagtype"); - return 1; - } - - legic_print_type(card.cardsize, 0); - - // OUT-OF-BOUNDS check - // UID 4 bytes can't be written to. - if ( len + offset >= card.cardsize ) { - len = card.cardsize - offset; - PrintAndLog("Out-of-bounds, Cardsize = %d, Trunc offset+len = %d", card.cardsize, len + offset); - } + uint32_t offset = 0, len = 0, iv = 1; + uint16_t datalen = 0; + sscanf(Cmd, "%x %x %x", &offset, &len, &iv); - legic_chk_iv(&IV); - - UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, IV}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 3000) ) { - PrintAndLog("command execution time out"); - return 1; - } - - uint8_t isOK = resp.arg[0] & 0xFF; - uint16_t readlen = resp.arg[1]; - if ( !isOK ) { - PrintAndLog("failed reading tag"); - return 2; - } + PrintAndLog("Reading %d bytes, from offset %d", len, offset); - uint8_t *data = malloc(readlen); + // allocate receiver buffer + uint8_t *data = malloc(len); if ( !data ){ PrintAndLog("Cannot allocate memory"); return 2; } - - if ( readlen != len ) - PrintAndLog("Fail, only managed to read 0x%02X bytes", readlen); - - // copy data from device - GetEMLFromBigBuf(data, readlen, 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)){ - PrintAndLog("Command execute timeout"); - free(data); - return 1; - } + memset(data, 0, len); + int status = legic_read_mem(offset, len, iv, data, &datalen); + if ( status == 0 ) { PrintAndLog("\n ## | 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"); PrintAndLog("-----+------------------------------------------------------------------------------------------------"); - print_hex_break( data, readlen, 32); + print_hex_break(data, datalen, 32); + } free(data); - return 0; + return status; } // should say which tagtype @@ -752,6 +734,37 @@ int CmdLegicCalcCrc(const char *Cmd){ return 0; } +int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uint16_t *outlen) { + + legic_chk_iv(&iv); + + UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, iv}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 3000) ) { + PrintAndLog("command execution time out"); + return 1; + } + + uint8_t isOK = resp.arg[0] & 0xFF; + *outlen = resp.arg[1]; + if ( !isOK ) { + PrintAndLog("failed reading tag"); + return 2; + } + + if ( *outlen != len ) + PrintAndLog("Fail, only managed to read %u bytes", *outlen); + + // copy data from device + if ( !GetEMLFromBigBuf(out, *outlen, 0) ) { + PrintAndLog("Fail, transfer from device time-out"); + return 4; + } + return 0; +} + int legic_print_type(uint32_t tagtype, uint8_t spaces){ char spc[11] = " "; spc[10]=0x00; @@ -798,8 +811,9 @@ void legic_chk_iv(uint32_t *iv){ } void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) { size_t len = 0; + UsbCommand c = {CMD_LEGIC_ESET, {0, 0, 0}}; - for(size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { + for(size_t i = offset; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); c.arg[0] = i; // offset @@ -810,6 +824,7 @@ void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) { } } + int HFLegicReader(const char *Cmd, bool verbose) { char cmdp = param_getchar(Cmd, 0); @@ -818,9 +833,10 @@ int HFLegicReader(const char *Cmd, bool verbose) { legic_card_select_t card; switch(legic_get_type(&card)){ case 1: + return 2; + case 2: if ( verbose ) PrintAndLog("command execution time out"); return 1; - case 2: case 3: if ( verbose ) PrintAndLog("legic card select failed"); return 2; @@ -878,7 +894,7 @@ int CmdLegicDump(const char *Cmd){ dumplen = card.cardsize; legic_print_type(dumplen, 0); - PrintAndLog("Reading tag memory..."); + PrintAndLog("Reading tag memory %d b...", dumplen); UsbCommand c = {CMD_READER_LEGIC_RF, {0x00, dumplen, 0x55}}; clearCommandBuffer(); @@ -907,8 +923,7 @@ int CmdLegicDump(const char *Cmd){ PrintAndLog("Fail, only managed to read 0x%02X bytes of 0x%02X", readlen, dumplen); // copy data from device - GetEMLFromBigBuf(data, readlen, 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)) { + if (!GetEMLFromBigBuf(data, readlen, 0) ) { PrintAndLog("Fail, transfer from device time-out"); free(data); return 4; @@ -1154,8 +1169,7 @@ int CmdLegicESave(const char *Cmd) { // download emulator memory PrintAndLog("Reading emulator memory..."); - GetEMLFromBigBuf(data, numofbytes, 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)) { + if (!GetEMLFromBigBuf(data, numofbytes, 0)) { PrintAndLog("Fail, transfer from device time-out"); free(data); return 4; diff --git a/client/cmdhflegic.h b/client/cmdhflegic.h index db38b723d..44bd85930 100644 --- a/client/cmdhflegic.h +++ b/client/cmdhflegic.h @@ -26,25 +26,26 @@ int CmdHFLegic(const char *Cmd); -int CmdLegicInfo(const char *Cmd); -int CmdLegicRdmem(const char *Cmd); -int CmdLegicLoad(const char *Cmd); -int CmdLegicRfSim(const char *Cmd); -int CmdLegicRfWrite(const char *Cmd); -int CmdLegicCalcCrc(const char *Cmd); -int CmdLegicDump(const char *Cmd); -int CmdLegicRestore(const char *Cmd); -int CmdLegicReader(const char *Cmd); -int CmdLegicELoad(const char *Cmd); -int CmdLegicESave(const char *Cmd); -int CmdLegicList(const char *Cmd); -int CmdLegicWipe(const char *Cmd); +extern int CmdLegicInfo(const char *Cmd); +extern int CmdLegicRdmem(const char *Cmd); +extern int CmdLegicLoad(const char *Cmd); +extern int CmdLegicRfSim(const char *Cmd); +extern int CmdLegicRfWrite(const char *Cmd); +extern int CmdLegicCalcCrc(const char *Cmd); +extern int CmdLegicDump(const char *Cmd); +extern int CmdLegicRestore(const char *Cmd); +extern int CmdLegicReader(const char *Cmd); +extern int CmdLegicELoad(const char *Cmd); +extern int CmdLegicESave(const char *Cmd); +extern int CmdLegicList(const char *Cmd); +extern int CmdLegicWipe(const char *Cmd); int HFLegicReader(const char *Cmd, bool verbose); int legic_print_type(uint32_t tagtype, uint8_t spaces); int legic_get_type(legic_card_select_t *card); void legic_chk_iv(uint32_t *iv); void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes); +int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uint16_t *outlen); int usage_legic_calccrc(void); int usage_legic_load(void); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index fc0050eda..543ee7403 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1100,7 +1100,8 @@ int CmdHF14AMfNestedHard(const char *Cmd) { slow ? "Yes" : "No", tests); - int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key?trgkey:NULL, nonce_file_read, nonce_file_write, slow, tests); + uint64_t foundkey = 0; + int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey); if (isOK) { switch (isOK) { @@ -1350,7 +1351,7 @@ int CmdHF14AMfChk(const char *Cmd) { } - //print them + //print keys printKeyTable( SectorsCnt, e_sector ); if (transferToEml) { @@ -1533,7 +1534,7 @@ int CmdHF14AMf1kSim(const char *Cmd) { if(flags & FLAG_INTERACTIVE) { PrintAndLog("Press pm3-button or send another cmd to abort simulation"); - while( !ukbhit() ){ + while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; @@ -1553,7 +1554,6 @@ int CmdHF14AMfSniff(const char *Cmd){ bool wantSaveToEmlFile = false; //var - int tmpchar; int res = 0; int len = 0; int blockLen = 0; @@ -1597,8 +1597,7 @@ int CmdHF14AMfSniff(const char *Cmd){ printf("."); fflush(stdout); if (ukbhit()) { - tmpchar = getchar(); - (void)tmpchar; + int gc = getchar(); (void)gc; printf("\naborted via keyboard!\n"); break; } diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index fd2068d1b..0c59ae9e3 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -67,4 +67,5 @@ extern int CmdHf14AMfSetMod(const char *Cmd); void showSectorTable(void); void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ); +void printKeyTable_fast( uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo ); #endif diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index c5b686c44..971eb637c 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1,6 +1,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2015, 2016 by piwi -// +// fiddled with 2016 Azcid (hardnested bitsliced Bruteforce imp) +// fiddled with 2016 Matrix ( sub testing of nonces while collecting ) // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -507,12 +508,7 @@ static void init_sum_bitarrays(void) bitarray_OR(sum_a0_bitarrays[ODD_STATE][sum_a0_idx], part_sum_a0_bitarrays[ODD_STATE][p]); } } - // for (uint16_t sum_a0 = 0; sum_a0 < NUM_SUMS; sum_a0++) { - // for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - // uint32_t count = count_states(sum_a0_bitarrays[odd_even][sum_a0]); - // printf("sum_a0_bitarray[%s][%d] has %d states (%5.2f%%)\n", odd_even==EVEN_STATE?"even":"odd ", sums[sum_a0], count, (float)count/(1<<24)*100.0); - // } - // } + } @@ -658,19 +654,7 @@ static void free_nonces_memory(void) } -// static double p_hypergeometric_cache[257][NUM_SUMS][257]; -// #define CACHE_INVALID -1.0 -// static void init_p_hypergeometric_cache(void) -// { - // for (uint16_t n = 0; n <= 256; n++) { - // for (uint16_t i_K = 0; i_K < NUM_SUMS; i_K++) { - // for (uint16_t k = 0; k <= 256; k++) { - // p_hypergeometric_cache[n][i_K][k] = CACHE_INVALID; - // } - // } - // } -// } static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) @@ -688,9 +672,7 @@ static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) uint16_t const N = 256; uint16_t K = sums[i_K]; - // if (p_hypergeometric_cache[n][i_K][k] != CACHE_INVALID) { - // return p_hypergeometric_cache[n][i_K][k]; - // } + if (n-k > N-K || k > K) return 0.0; // avoids log(x<=0) in calculation below if (k == 0) { @@ -702,7 +684,6 @@ static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) for (int16_t i = N; i >= N-n+1; i--) { log_result -= log(i); } - // p_hypergeometric_cache[n][i_K][k] = exp(log_result); return exp(log_result); } else { if (n-k == N-K) { // special case. The published recursion below would fail with a divide by zero exception @@ -713,7 +694,6 @@ static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) for (int16_t i = K+1; i <= N; i++) { log_result -= log(i); } - // p_hypergeometric_cache[n][i_K][k] = exp(log_result); return exp(log_result); } else { // recursion return (p_hypergeometric(i_K, n, k-1) * (K-k+1) * (n-k+1) / (k * (N-K-n+k))); @@ -1459,7 +1439,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ bool reported_suma8 = false; FILE *fnonces = NULL; UsbCommand resp; - + uint8_t timeout = 0; num_acquired_nonces = 0; clearCommandBuffer(); @@ -1472,17 +1452,28 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ UsbCommand c = {CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags}}; memcpy(c.d.asBytes, key, 6); + clearCommandBuffer(); SendCommand(&c); if (field_off) break; if (initialize) { - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) return 1; + while(!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + timeout++; + printf("."); + if (timeout > 3) { + PrintAndLog("\nNo response from Proxmark. Aborting..."); + if (fnonces) fclose(fnonces); + return 1; + } + } - if (resp.arg[0]) return resp.arg[0]; // error during nested_hard + if (resp.arg[0]) { + if (fnonces) fclose(fnonces); + return resp.arg[0]; // error during nested_hard + } cuid = resp.arg[1]; - // PrintAndLog("Acquiring nonces for CUID 0x%08x", cuid); if (nonce_file_write && fnonces == NULL) { if ((fnonces = fopen("nonces.bin","wb")) == NULL) { PrintAndLog("Could not create file nonces.bin"); @@ -1493,7 +1484,9 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ fwrite(write_buf, 1, 4, fnonces); fwrite(&trgBlockNo, 1, 1, fnonces); fwrite(&trgKeyType, 1, 1, fnonces); + fflush(fnonces); } + initialize = false; } if (!initialize) { @@ -1513,6 +1506,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ if (nonce_file_write) { fwrite(bufp, 1, 9, fnonces); + fflush(fnonces); } bufp += 9; } @@ -2171,12 +2165,12 @@ static void pre_XOR_nonces(void) } -static bool brute_force(void) +static bool brute_force(uint64_t *found_key) { if (known_target_key != -1) { TestIfKeyExists(known_target_key); } - return brute_force_bs(NULL, candidates, cuid, num_acquired_nonces, maximum_states, nonces, best_first_bytes); + return brute_force_bs(NULL, candidates, cuid, num_acquired_nonces, maximum_states, nonces, best_first_bytes, found_key); } @@ -2253,7 +2247,7 @@ static void set_test_state(uint8_t byte) } -int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests) +int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey) { char progress_text[80]; @@ -2324,8 +2318,8 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc best_first_bytes[0] = best_first_byte_smallest_bitarray; pre_XOR_nonces(); prepare_bf_test_nonces(nonces, best_first_bytes[0]); - hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force1, 0); - key_found = brute_force(); + //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force1, 0); + key_found = brute_force(foundkey); free(candidates->states[ODD_STATE]); free(candidates->states[EVEN_STATE]); free_candidates_memory(candidates); @@ -2344,8 +2338,8 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc // printf("Estimated remaining states: %" PRIu64 " (2^%1.1f)\n", nonces[best_first_bytes[0]].sum_a8_guess[j].num_states, log(nonces[best_first_bytes[0]].sum_a8_guess[j].num_states)/log(2.0)); generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx); // printf("Time for generating key candidates list: %1.0f sec (%1.1f sec CPU)\n", difftime(time(NULL), start_time), (float)(msclock() - start_clock)/1000.0); - hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force, 0); - key_found = brute_force(); + //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force, 0); + key_found = brute_force(foundkey); free_statelist_cache(); free_candidates_memory(candidates); candidates = NULL; @@ -2439,8 +2433,8 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc best_first_bytes[0] = best_first_byte_smallest_bitarray; pre_XOR_nonces(); prepare_bf_test_nonces(nonces, best_first_bytes[0]); - hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force1, 0); - key_found = brute_force(); + //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force1, 0); + key_found = brute_force(foundkey); free(candidates->states[ODD_STATE]); free(candidates->states[EVEN_STATE]); free_candidates_memory(candidates); @@ -2459,8 +2453,8 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc // printf("Estimated remaining states: %" PRIu64 " (2^%1.1f)\n", nonces[best_first_bytes[0]].sum_a8_guess[j].num_states, log(nonces[best_first_bytes[0]].sum_a8_guess[j].num_states)/log(2.0)); generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx); // printf("Time for generating key candidates list: %1.0f sec (%1.1f sec CPU)\n", difftime(time(NULL), start_time), (float)(msclock() - start_clock)/1000.0); - hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force, 0); - key_found = brute_force(); + //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force, 0); + key_found = brute_force(foundkey); free_statelist_cache(); free_candidates_memory(candidates); candidates = NULL; diff --git a/client/cmdhfmfhard.h b/client/cmdhfmfhard.h index 55eb1583c..d534d9217 100644 --- a/client/cmdhfmfhard.h +++ b/client/cmdhfmfhard.h @@ -41,7 +41,7 @@ typedef struct noncelist { noncelistentry_t *first; } noncelist_t; -extern int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests); +extern int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey); extern void hardnested_print_progress(uint32_t nonces, char *activity, float brute_force, uint64_t min_diff_print_time); #endif diff --git a/client/cmdlf.c b/client/cmdlf.c index 8ebaec9bf..7e730b3f0 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -30,11 +30,16 @@ int usage_lf_cmdread(void) { return 0; } int usage_lf_read(void){ - PrintAndLog("Usage: lf read [h] [s]"); + PrintAndLog("Usage: lf read [h] [s] [d numofsamples]"); PrintAndLog("Options:"); PrintAndLog(" h This help"); PrintAndLog(" s silent run no printout"); + PrintAndLog(" d #samples # samples to collect (optional)"); PrintAndLog("Use 'lf config' to set parameters."); + PrintAndLog(""); + PrintAndLog("Samples:"); + PrintAndLog(" lf read s d 12000 - collects 12000samples silent"); + PrintAndLog(" lf read s"); return 0; } int usage_lf_snoop(void) { @@ -42,6 +47,8 @@ int usage_lf_snoop(void) { PrintAndLog("Usage: lf snoop [h]"); PrintAndLog("Options:"); PrintAndLog(" h This help"); + PrintAndLog("This function takes no arguments. "); + PrintAndLog("Use 'lf config' to set parameters."); return 0; } int usage_lf_config(void) { @@ -244,234 +251,6 @@ int CmdFlexdemod(const char *Cmd) RepaintGraphWindow(); return 0; } - -int CmdIndalaDemod(const char *Cmd) -{ - // PSK1, Bitrate 32, - - // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID - int state = -1; - int count = 0; - int i, j; - - // worst case with GraphTraceLen=64000 is < 4096 - // under normal conditions it's < 2048 - uint8_t rawbits[4096]; - - int rawbit = 0, worst = 0, worstPos = 0; - // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); - - // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) - for (i = 0; i < GraphTraceLen-1; i += 2) { - count += 1; - if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { - // appears redundant - marshmellow - if (state == 0) { - for (j = 0; j < count - 8; j += 16) { - rawbits[rawbit++] = 0; - } - if ((abs(count - j)) > worst) { - worst = abs(count - j); - worstPos = i; - } - } - state = 1; - count = 0; - } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { - //appears redundant - if (state == 1) { - for (j = 0; j < count - 8; j += 16) { - rawbits[rawbit++] = 1; - } - if ((abs(count - j)) > worst) { - worst = abs(count - j); - worstPos = i; - } - } - state = 0; - count = 0; - } - } - if ( rawbit<1 ) return 0; - - if (g_debugMode) { - PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); - PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); - } - - // Finding the start of a UID - int uidlen, long_wait; - if (strcmp(Cmd, "224") == 0) { - uidlen = 224; - long_wait = 30; - } else { - uidlen = 64; - long_wait = 29; - } - - int start; - int first = 0; - for (start = 0; start <= rawbit - uidlen; start++) { - first = rawbits[start]; - for (i = start; i < start + long_wait; i++) { - if (rawbits[i] != first) { - break; - } - } - if (i == (start + long_wait)) { - break; - } - } - - if (start == rawbit - uidlen + 1) { - if (g_debugMode) PrintAndLog("nothing to wait for"); - return 0; - } - - // Inverting signal if needed - if (first == 1) { - for (i = start; i < rawbit; i++) - rawbits[i] = !rawbits[i]; - } - - // Dumping UID - uint8_t bits[224] = {0x00}; - char showbits[225] = {0x00}; - int bit; - i = start; - int times = 0; - - if (uidlen > rawbit) { - PrintAndLog("Warning: not enough raw bits to get a full UID"); - for (bit = 0; bit < rawbit; bit++) { - bits[bit] = rawbits[i++]; - // As we cannot know the parity, let's use "." and "/" - showbits[bit] = '.' + bits[bit]; - } - showbits[bit+1]='\0'; - PrintAndLog("Partial UID=%s", showbits); - return 0; - } else { - for (bit = 0; bit < uidlen; bit++) { - bits[bit] = rawbits[i++]; - showbits[bit] = '0' + bits[bit]; - } - times = 1; - } - - //convert UID to HEX - uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; - int idx; - uid1 = uid2 = 0; - - if (uidlen==64){ - for( idx=0; idx<64; idx++) { - if (showbits[idx] == '0') { - uid1 = (uid1<<1) | (uid2>>31); - uid2 = (uid2<<1) | 0; - } else { - uid1 = (uid1<<1) | (uid2>>31); - uid2 = (uid2<<1) | 1; - } - } - PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2); - } else { - uid3 = uid4 = uid5 = uid6 = uid7 = 0; - - for( idx=0; idx<224; idx++) { - uid1 = (uid1<<1) | (uid2>>31); - uid2 = (uid2<<1) | (uid3>>31); - uid3 = (uid3<<1) | (uid4>>31); - uid4 = (uid4<<1) | (uid5>>31); - uid5 = (uid5<<1) | (uid6>>31); - uid6 = (uid6<<1) | (uid7>>31); - - if (showbits[idx] == '0') - uid7 = (uid7<<1) | 0; - else - uid7 = (uid7<<1) | 1; - } - PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); - } - - // Checking UID against next occurrences - int failed = 0; - for (; i + uidlen <= rawbit;) { - failed = 0; - for (bit = 0; bit < uidlen; bit++) { - if (bits[bit] != rawbits[i++]) { - failed = 1; - break; - } - } - if (failed == 1) { - break; - } - times += 1; - } - - if (g_debugMode) PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); - - // Remodulating for tag cloning - // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) - // since this changes graphbuffer data. - GraphTraceLen = 32 * uidlen; - i = 0; - int phase = 0; - for (bit = 0; bit < uidlen; bit++) { - phase = (bits[bit] == 0) ? 0 : 1; - int j; - for (j = 0; j < 32; j++) { - GraphBuffer[i++] = phase; - phase = !phase; - } - } - - RepaintGraphWindow(); - return 1; -} - -int CmdIndalaClone(const char *Cmd){ - UsbCommand c; - unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7; - - uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0; - int n = 0, i = 0; - - if (strchr(Cmd,'l') != 0) { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - uid1 = (uid1 << 4) | (uid2 >> 28); - uid2 = (uid2 << 4) | (uid3 >> 28); - uid3 = (uid3 << 4) | (uid4 >> 28); - uid4 = (uid4 << 4) | (uid5 >> 28); - uid5 = (uid5 << 4) | (uid6 >> 28); - uid6 = (uid6 << 4) | (uid7 >> 28); - uid7 = (uid7 << 4) | (n & 0xf); - } - PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); - c.cmd = CMD_INDALA_CLONE_TAG_L; - c.d.asDwords[0] = uid1; - c.d.asDwords[1] = uid2; - c.d.asDwords[2] = uid3; - c.d.asDwords[3] = uid4; - c.d.asDwords[4] = uid5; - c.d.asDwords[5] = uid6; - c.d.asDwords[6] = uid7; - } else { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - uid1 = (uid1 << 4) | (uid2 >> 28); - uid2 = (uid2 << 4) | (n & 0xf); - } - PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2); - c.cmd = CMD_INDALA_CLONE_TAG; - c.arg[0] = uid1; - c.arg[1] = uid2; - } - - clearCommandBuffer(); - SendCommand(&c); - return 0; -} int CmdLFSetConfig(const char *Cmd) { uint8_t divisor = 0;//Frequency divisor @@ -541,12 +320,33 @@ int CmdLFSetConfig(const char *Cmd) { return 0; } +bool lf_read(bool silent, uint32_t samples) { + if (offline) return false; + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {silent, samples, 0}}; + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if (g_lf_threshold_set) { + WaitForResponse(CMD_ACK, &resp); + } else { + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { + PrintAndLog("command execution time out"); + return false; + } + } + getSamples(resp.arg[0], silent); + + return true; +} + int CmdLFRead(const char *Cmd) { if (offline) return 0; bool errors = false; - bool arg1 = false; + bool silent = false; + uint32_t samples = 0; uint8_t cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { @@ -555,9 +355,14 @@ int CmdLFRead(const char *Cmd) { return usage_lf_read(); case 's': case 'S': - arg1 = true; + silent = true; cmdp++; break; + case 'd': + case 'D': + samples = param_get32ex(Cmd, cmdp, 0, 10); + cmdp +=2; + break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -568,18 +373,7 @@ int CmdLFRead(const char *Cmd) { //Validations if (errors) return usage_lf_read(); - UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - if ( g_lf_threshold_set ) { - WaitForResponse(CMD_ACK,NULL); - } else { - if ( !WaitForResponseTimeout(CMD_ACK, NULL ,2500) ) { - PrintAndLog("command execution time out"); - return 1; - } - } - return 0; + return lf_read(silent, samples); } int CmdLFSnoop(const char *Cmd) { @@ -590,7 +384,7 @@ int CmdLFSnoop(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); WaitForResponse(CMD_ACK,NULL); - getSamples("", false); + getSamples(0, false); return 0; } @@ -700,9 +494,10 @@ int CmdLFfskSim(const char *Cmd) //Validations if (errors) return usage_lf_simfsk(); + int firstClockEdge = 0; if (dataLen == 0){ //using DemodBuffer if (clk == 0 || fcHigh == 0 || fcLow == 0){ //manual settings must set them all - uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0); + uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0, &firstClockEdge); if (ans==0){ if (!fcHigh) fcHigh = 10; if (!fcLow) fcLow = 8; @@ -1016,30 +811,30 @@ int CmdVchDemod(const char *Cmd) { return 0; } - //by marshmellow -int CheckChipset(bool getDeviceData) { +int CheckChipType(bool getDeviceData) { if (!getDeviceData) return 0; uint32_t word = 0; - save_restoreGB(1); + save_restoreGB(GRAPH_SAVE); //check for em4x05/em4x69 chips first if (EM4x05IsBlock0(&word)) { - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); PrintAndLog("\nValid EM4x05/EM4x69 Chipset found\nTry `lf em 4x05` commands\n"); return 1; } - //TODO check for t55xx chip... - // if ( t55xxIsBlock0(() { - // save_restoreGB(0); - // PrintAndLog("\nValid T55xx Chipset found\nTry `lf t55xx` commands\n"); - // return 1; - // } + //check for t55xx chip... + if (tryDetectP1(true)) { + PrintAndLog("\nValid T55xx Chip Found\nTry `lf t55xx` commands\n"); + save_restoreGB(GRAPH_RESTORE); - save_restoreGB(0); + return 1; + } + + save_restoreDB(GRAPH_RESTORE); return 0; } @@ -1054,8 +849,7 @@ int CmdLFfind(const char *Cmd) { bool getDeviceData = (!offline && (cmdp != '1') ); if (getDeviceData) { - CmdLFRead("s"); - getSamples("30000", false); + lf_read(true, 30000); } else if (GraphTraceLen < minLength) { PrintAndLog("Data in Graphbuffer was too small."); return 0; @@ -1074,7 +868,7 @@ int CmdLFfind(const char *Cmd) { // only run if graphbuffer is just noise as it should be for hitag/cotag if (graphJustNoise(GraphBuffer, testLen)) { - if (CheckChipset(getDeviceData) ) + if (CheckChipType(getDeviceData) ) return 1; ans=CmdLFHitagReader("26"); @@ -1092,102 +886,135 @@ int CmdLFfind(const char *Cmd) { } // identify chipset - CheckChipset(getDeviceData); + CheckChipType(getDeviceData); - ans=CmdFSKdemodIO(""); + ans=CmdIOProxDemod(""); if (ans>0) { PrintAndLog("\nValid IO Prox ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdFSKdemodPyramid(""); + + ans=CmdPyramidDemod(""); if (ans>0) { PrintAndLog("\nValid Pyramid ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdFSKdemodParadox(""); + + ans=CmdParadoxDemod(""); if (ans>0) { PrintAndLog("\nValid Paradox ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdFSKdemodAWID(""); + + ans=CmdAWIDDemod(""); if (ans>0) { PrintAndLog("\nValid AWID ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdFSKdemodHID(""); + + ans=CmdHIDDemod(""); if (ans>0) { PrintAndLog("\nValid HID Prox ID Found!"); - return 1; + return CheckChipType(getDeviceData); } + ans=CmdAskEM410xDemod(""); if (ans>0) { PrintAndLog("\nValid EM410x ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdG_Prox_II_Demod(""); + + ans=CmdVisa2kDemod(""); + if (ans>0) { + PrintAndLog("\nValid Visa2000 ID Found!"); + return CheckChipType(getDeviceData); + } + + ans=CmdGuardDemod(""); if (ans>0) { PrintAndLog("\nValid Guardall G-Prox II ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdFDXBdemodBI(""); + + ans=CmdFdxDemod(""); //biphase if (ans>0) { PrintAndLog("\nValid FDX-B ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=EM4x50Read("", false); if (ans>0) { PrintAndLog("\nValid EM4x50 ID Found!"); return 1; } + + ans=CmdJablotronDemod(""); + if (ans>0) { + PrintAndLog("\nValid Jablotron ID Found!"); + return CheckChipType(getDeviceData); + } + + ans=CmdNoralsyDemod(""); + if (ans>0) { + PrintAndLog("\nValid Noralsy ID Found!"); + return CheckChipType(getDeviceData); + } + + ans=CmdSecurakeyDemod(""); + if (ans>0) { + PrintAndLog("\nValid Securakey ID Found!"); + return CheckChipType(getDeviceData); + } + ans=CmdVikingDemod(""); if (ans>0) { PrintAndLog("\nValid Viking ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdIndalaDecode(""); + ans=CmdIndalaDemod(""); if (ans>0) { PrintAndLog("\nValid Indala ID Found!"); - return 1; + return CheckChipType(getDeviceData); } - ans=CmdPSKNexWatch(""); + + ans=CmdNexWatchDemod(""); if (ans>0) { PrintAndLog("\nValid NexWatch ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdPSKIdteck(""); if (ans>0) { PrintAndLog("\nValid Idteck ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdJablotronDemod(""); if (ans>0) { PrintAndLog("\nValid Jablotron ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdLFNedapDemod(""); if (ans>0) { PrintAndLog("\nValid NEDAP ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdVisa2kDemod(""); if (ans>0) { PrintAndLog("\nValid Visa2000 ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdNoralsyDemod(""); if (ans>0) { PrintAndLog("\nValid Noralsy ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdPrescoDemod(""); if (ans>0) { PrintAndLog("\nValid Presco ID Found!"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdPacDemod(""); if (ans>0) { PrintAndLog("\nValid PAC/Stanley ID Found!"); - return 1; + return CheckChipType(getDeviceData); } // TIdemod? @@ -1229,7 +1056,7 @@ int CmdLFfind(const char *Cmd) { ans=FSKrawDemod("",true); if (ans>0) { PrintAndLog("\nUnknown FSK Modulated Tag Found!"); - return 1; + return CheckChipType(getDeviceData);; } } bool st = true; @@ -1237,7 +1064,7 @@ int CmdLFfind(const char *Cmd) { if (ans>0) { PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!"); PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'"); - return 1; + return CheckChipType(getDeviceData); } ans=CmdPSK1rawDemod(""); @@ -1245,7 +1072,7 @@ int CmdLFfind(const char *Cmd) { PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'"); PrintAndLog("\nCould also be PSK3 - [currently not supported]"); PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod"); - return 1; + return CheckChipType(getDeviceData); } PrintAndLog("\nNo Data Found!\n"); } @@ -1254,34 +1081,32 @@ int CmdLFfind(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"animal", CmdLFFdx, 1, "{ Animal RFIDs... }"}, {"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"}, - {"cotag", CmdLFCOTAG, 1, "{ COTAG RFIDs... }"}, - {"em", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, - {"guard", CmdLFGuard, 1, "{ Guardall RFIDs... }"}, + {"cotag", CmdLFCOTAG, 1, "{ COTAG CHIPs... }"}, + {"em", CmdLFEM4X, 1, "{ EM4X CHIPs & RFIDs... }"}, + {"fdx", CmdLFFdx, 1, "{ FDX-B RFIDs... }"}, + {"gproxii", CmdLFGuard, 1, "{ Guardall Prox II RFIDs... }"}, {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, - {"hitag", CmdLFHitag, 1, "{ HITAG RFIDs... }"}, -// {"indala", CmdLFIndala, 1, "{ Indala RFIDs... }"}, - {"io", CmdLFIO, 1, "{ IOPROX RFIDs... }"}, + {"hitag", CmdLFHitag, 1, "{ Hitag CHIPs... }"}, + {"indala", CmdLFINDALA, 1, "{ Indala RFIDs... }"}, + {"io", CmdLFIO, 1, "{ ioProx RFIDs... }"}, {"jablotron", CmdLFJablotron, 1, "{ Jablotron RFIDs... }"}, {"nedap", CmdLFNedap, 1, "{ Nedap RFIDs... }"}, - {"nexwatch", CmdLFNexWatch, 1, "{ NexWatch RFIDs... }"}, + {"nexwatch", CmdLFNEXWATCH, 1, "{ NexWatch RFIDs... }"}, {"noralsy", CmdLFNoralsy, 1, "{ Noralsy RFIDs... }"}, {"pac", CmdLFPac, 1, "{ PAC/Stanley RFIDs... }"}, - {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"}, + {"paradox", CmdLFParadox, 1, "{ Paradox RFIDs... }"}, + {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 CHIPs... }"}, {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"}, {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, {"securakey", CmdLFSecurakey, 1, "{ Securakey RFIDs... }"}, - {"ti", CmdLFTI, 1, "{ TI RFIDs... }"}, - {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"}, - + {"ti", CmdLFTI, 1, "{ TI CHIPs... }"}, + {"t55xx", CmdLFT55XX, 1, "{ T55xx CHIPs... }"}, {"viking", CmdLFViking, 1, "{ Viking RFIDs... }"}, {"visa2000", CmdLFVisa2k, 1, "{ Visa2000 RFIDs... }"}, {"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"}, {"cmdread", CmdLFCommandRead, 0, " <'0' period> <'1' period> ['h' 134] \n\t\t-- Modulate LF reader field to send command before read (all periods in microseconds)"}, {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, - {"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, - {"indalaclone", CmdIndalaClone, 0, " ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"}, {"read", CmdLFRead, 0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"}, {"search", CmdLFfind, 1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) \n\t\t-- 'u' to search for unknown tags"}, {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, diff --git a/client/cmdlf.h b/client/cmdlf.h index 55856c88b..c5e64c901 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -14,7 +14,6 @@ #include #include #include - #include #include #include "proxmark3.h" @@ -44,6 +43,10 @@ #include "cmdlfnoralsy.h" // for NORALSY meny #include "cmdlffdx.h" // for FDX-B meny #include "cmdlfcotag.h" // for COTAG meny +#include "cmdlfindala.h" // for indala menu +#include "cmdlfguard.h"// for gproxii menu +#include "cmdlffdx.h" // for fdx-b menu +#include "cmdlfparadox.h"// for paradox menu #include "cmdlfnexwatch.h" //for nexwatch menu #include "cmdlfsecurakey.h" //for securakey menu #include "cmdlfpac.h" // for pac menu @@ -56,8 +59,6 @@ extern int CmdLFSetConfig(const char *Cmd); extern int CmdLFCommandRead(const char *Cmd); extern int CmdFlexdemod(const char *Cmd); -extern int CmdIndalaDemod(const char *Cmd); -extern int CmdIndalaClone(const char *Cmd); extern int CmdLFRead(const char *Cmd); extern int CmdLFSim(const char *Cmd); extern int CmdLFaskSim(const char *Cmd); @@ -68,6 +69,7 @@ extern int CmdLFSnoop(const char *Cmd); extern int CmdVchDemod(const char *Cmd); extern int CmdLFfind(const char *Cmd); +extern bool lf_read(bool silent, uint32_t samples); // usages helptext extern int usage_lf_cmdread(void); diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 6a9d301de..6b6d4930b 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -8,24 +8,25 @@ // the license. //----------------------------------------------------------------------------- // Low frequency AWID26/50 commands +// FSK2a, RF/50, 96 bits (complete) //----------------------------------------------------------------------------- #include "cmdlfawid.h" // AWID function declarations static int CmdHelp(const char *Cmd); -int usage_lf_awid_fskdemod(void) { +int usage_lf_awid_read(void) { PrintAndLog("Enables AWID compatible reader mode printing details of scanned AWID26 or AWID50 tags."); PrintAndLog("By default, values are printed and logged until the button is pressed or another USB command is issued."); PrintAndLog("If the [1] option is provided, reader mode is exited after reading a single AWID card."); PrintAndLog(""); - PrintAndLog("Usage: lf awid fskdemod [h] [1]"); + PrintAndLog("Usage: lf awid read [h] [1]"); PrintAndLog("Options:"); PrintAndLog(" h : This help"); PrintAndLog(" 1 : (optional) stop after reading a single card"); PrintAndLog(""); PrintAndLog("Samples:"); - PrintAndLog(" lf awid fskdemod"); - PrintAndLog(" lf awid fskdemod 1"); + PrintAndLog(" lf awid read"); + PrintAndLog(" lf awid read 1"); return 0; } @@ -115,22 +116,6 @@ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, ui return true; } -int CmdAWIDDemodFSK(const char *Cmd) { - - if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod(); - uint8_t findone = (Cmd[0] == '1') ? 1 : 0; - UsbCommand c = {CMD_AWID_DEMOD_FSK, {findone, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; -} - -int CmdAWIDRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("12000", true); - return CmdFSKdemodAWID(Cmd); -} - //refactored by marshmellow int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits) { @@ -225,6 +210,154 @@ static void verify_values(uint8_t *fmtlen, uint32_t *fc, uint32_t *cn){ } } +// this read is the "normal" read, which download lf signal and tries to demod here. +int CmdAWIDRead(const char *Cmd) { + lf_read(true, 12000); + return CmdAWIDDemod(Cmd); +} +// this read loops on device side. +// uses the demod in lfops.c +int CmdAWIDRead_device(const char *Cmd) { + + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_awid_read(); + uint8_t findone = (Cmd[0] == '1') ? 1 : 0; + UsbCommand c = {CMD_AWID_DEMOD_FSK, {findone, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +//by marshmellow +//AWID Prox demod - FSK RF/50 with preamble of 00000001 (always a 96 bit data stream) +//print full AWID Prox ID and some bit format details if found +int CmdAWIDDemod(const char *Cmd) { + uint8_t bits[MAX_GRAPH_TRACE_LEN]={0}; + size_t size = getFromGraphBuf(bits); + if (size==0) { + PrintAndLog("DEBUG: Error - AWID not enough samples"); + return 0; + } + //get binary from fsk wave + int waveIdx = 0; + + int idx = detectAWID(bits, &size, &waveIdx); + if (idx <= 0){ + if (g_debugMode){ + if (idx == -1) + PrintAndLog("DEBUG: Error - AWID not enough samples"); + else if (idx == -2) + PrintAndLog("DEBUG: Error - AWID only noise found"); + else if (idx == -3) + PrintAndLog("DEBUG: Error - AWID problem during FSK demod"); + else if (idx == -4) + PrintAndLog("DEBUG: Error - AWID preamble not found"); + else if (idx == -5) + PrintAndLog("DEBUG: Error - AWID size not correct: %d", size); + else + PrintAndLog("DEBUG: Error - AWID error %d",idx); + } + return 0; + } + + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96 + // ----------------------------------------------------------------------------- + // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1 + // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96 + // |---26 bit---| |-----117----||-------------142-------------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + // (26 bit format shown) + + //get raw ID before removing parities + uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32); + uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32); + uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32); + setDemodBuf(bits, 96, idx); + + size = removeParity(bits, idx+8, 4, 1, 88); + if (size != 66){ + if (g_debugMode) PrintAndLog("DEBUG: Error - AWID at parity check-tag size does not match AWID format"); + return 0; + } + // ok valid card found! + + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456 + // ----------------------------------------------------------------------------- + // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000 + // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // |26 bit| |-117--| |-----142------| + // + // 00110010 0 0000111110100000 00000000000100010010100010000111 1 000000000 + // bbbbbbbb w ffffffffffffffff cccccccccccccccccccccccccccccccc w xxxxxxxxx + // |50 bit| |----4000------| |-----------2248975------------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + + uint32_t fc = 0; + uint32_t cardnum = 0; + uint32_t code1 = 0; + uint32_t code2 = 0; + uint8_t fmtLen = bytebits_to_byte(bits, 8); + + switch(fmtLen) { + case 26: + fc = bytebits_to_byte(bits + 9, 8); + cardnum = bytebits_to_byte(bits + 17, 16); + code1 = bytebits_to_byte(bits + 8,fmtLen); + PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); + break; + case 34: + fc = bytebits_to_byte(bits + 9, 8); + cardnum = bytebits_to_byte(bits + 17, 24); + code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); + code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); + PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + break; + case 37: + fc = bytebits_to_byte(bits + 9, 13); + cardnum = bytebits_to_byte(bits + 22, 18); + code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); + code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); + PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + break; + // case 40: + // break; + case 50: + fc = bytebits_to_byte(bits + 9, 16); + cardnum = bytebits_to_byte(bits + 25, 32); + code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); + code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); + PrintAndLog("AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + break; + default: + if (fmtLen > 32 ) { + cardnum = bytebits_to_byte(bits + 8 + (fmtLen-17), 16); + code1 = bytebits_to_byte(bits + 8, fmtLen-32); + code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); + PrintAndLog("AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); + } else { + cardnum = bytebits_to_byte(bits + 8 + (fmtLen-17), 16); + code1 = bytebits_to_byte(bits + 8, fmtLen); + PrintAndLog("AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); + } + break; + } + + if (g_debugMode){ + PrintAndLog("DEBUG: AWID idx: %d, Len: %d Printing Demod Buffer:", idx, 96); + printDemodBuff(); + } + return 1; +} + int CmdAWIDSim(const char *Cmd) { uint32_t fc = 0, cn = 0; uint8_t fmtlen = 0; @@ -320,7 +453,7 @@ int CmdAWIDClone(const char *Cmd) { return 0; } -int CmdAWIDBrute(const char *Cmd){ +int CmdAWIDBrute(const char *Cmd) { bool errors = false; uint32_t fc = 0, cn = 0, delay = 1000; @@ -399,6 +532,7 @@ int CmdAWIDBrute(const char *Cmd){ return 2; } if (ukbhit()) { + int gc = getchar(); (void)gc; PrintAndLog("aborted via keyboard!"); return sendPing(); } @@ -416,12 +550,12 @@ int CmdAWIDBrute(const char *Cmd){ } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"fskdemod", CmdAWIDDemodFSK, 0, "Realtime AWID FSK demodulator"}, - {"read", CmdAWIDRead, 0, "Attempt to read and extract tag data"}, - {"sim", CmdAWIDSim, 0, "AWID tag simulator"}, - {"clone", CmdAWIDClone, 0, "Clone AWID to T55x7"}, - {"brute", CmdAWIDBrute, 0, "Bruteforce card number against reader"}, + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdAWIDDemod, 0, "Demodulate an AWID FSK tag from the GraphBuffer"}, + {"read", CmdAWIDRead, 0, "Attempt to read and extract tag data"}, + {"sim", CmdAWIDSim, 0, "AWID tag simulator"}, + {"clone", CmdAWIDClone, 0, "Clone AWID to T55x7"}, + {"brute", CmdAWIDBrute, 0, "Bruteforce card number against reader"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfawid.h b/client/cmdlfawid.h index 4f707c058..8a7eced78 100644 --- a/client/cmdlfawid.h +++ b/client/cmdlfawid.h @@ -21,19 +21,20 @@ #include "cmdlf.h" // lf read #include "protocols.h" // for T55xx config register definitions #include "cmdmain.h" -#include "sleep.h" +#include "util_posix.h" -int CmdLFAWID(const char *Cmd); -int CmdAWIDDemodFSK(const char *Cmd); -int CmdAWIDRead(const char *Cmd); -int CmdAWIDSim(const char *Cmd); -int CmdAWIDClone(const char *Cmd); -int CmdAWIDBrute(const char *Cmd); -int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *AWIDBits); -int usage_lf_awid_fskdemod(void); -int usage_lf_awid_clone(void); -int usage_lf_awid_sim(void); -int usage_lf_awid_brute(void); +extern int CmdLFAWID(const char *Cmd); +extern int CmdAWIDDemod(const char *Cmd); +extern int CmdAWIDRead(const char *Cmd); +extern int CmdAWIDSim(const char *Cmd); +extern int CmdAWIDClone(const char *Cmd); +extern int CmdAWIDBrute(const char *Cmd); +extern int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits); + +extern int usage_lf_awid_read(void); +extern int usage_lf_awid_sim(void); +extern int usage_lf_awid_clone(void); +extern int usage_lf_awid_brute(void); #endif diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index f10516a61..c807eca4e 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -33,7 +33,8 @@ int CmdCOTAGDemod(const char *Cmd) { size_t bitlen = COTAG_BITS; memcpy(bits, DemodBuffer, COTAG_BITS); - int err = manrawdecode(bits, &bitlen, 1); + uint8_t alignPos = 0; + int err = manrawdecode(bits, &bitlen, 1, &alignPos); if (err){ if (g_debugMode) PrintAndLog("DEBUG: Error - COTAG too many errors: %d", err); return -1; @@ -85,7 +86,7 @@ int CmdCOTAGRead(const char *Cmd) { case 2: { CmdPlot(""); CmdGrid("384"); - getSamples("", true); break; + getSamples(0, true); break; } case 1: { GetFromBigBuf(DemodBuffer, COTAG_BITS, 0); diff --git a/client/cmdlfcotag.h b/client/cmdlfcotag.h index dab605134..589089a61 100644 --- a/client/cmdlfcotag.h +++ b/client/cmdlfcotag.h @@ -1,11 +1,11 @@ //----------------------------------------------------------------------------- -// Copyright (C) 2010 iZsh +// Authored by Iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency AWID commands +// Low frequency COTAG commands //----------------------------------------------------------------------------- #ifndef CMDLFCOTAG_H__ @@ -23,9 +23,9 @@ #define COTAG_BITS 264 #endif -int CmdLFCOTAG(const char *Cmd); -int CmdCOTAGRead(const char *Cmd); -int CmdCOTAGDemod(const char *Cmd); +extern int CmdLFCOTAG(const char *Cmd); +extern int CmdCOTAGRead(const char *Cmd); +extern int CmdCOTAGDemod(const char *Cmd); -int usage_lf_cotag_read(void); +extern int usage_lf_cotag_read(void); #endif diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 075b9d24c..e23f06ea5 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -14,6 +14,56 @@ uint64_t g_em410xid = 0; static int CmdHelp(const char *Cmd); +//////////////// 410x commands +int usage_lf_em410x_demod(void){ + PrintAndLog("Usage: data askem410xdemod [clock] <0|1> [maxError]"); + PrintAndLog(" [set clock as integer] optional, if not set, autodetect."); + PrintAndLog(" , 1 for invert output"); + PrintAndLog(" [set maximum allowed errors], default = 100."); + PrintAndLog(""); + PrintAndLog(" sample: data askem410xdemod = demod an EM410x Tag ID from GraphBuffer"); + PrintAndLog(" : data askem410xdemod 32 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32"); + PrintAndLog(" : data askem410xdemod 32 1 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLog(" : data askem410xdemod 1 = demod an EM410x Tag ID from GraphBuffer while inverting data"); + PrintAndLog(" : data askem410xdemod 64 1 0 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors"); + return 0; +} +int usage_lf_em410x_write(void) { + PrintAndLog("Writes EM410x ID to a T55x7 / T5555 (Q5) tag"); + PrintAndLog(""); + PrintAndLog("Usage: lf em 410xwrite [h] [clock]"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" - ID number"); + PrintAndLog(" - 0|1 T5555 (Q5) / T55x7"); + PrintAndLog(" - 16|32|40|64, optional, set R/F clock rate, defaults to 64"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 410xwrite 0F0368568B"); + return 0; +} +int usage_lf_em410x_ws(void) { + PrintAndLog("Watch 'nd Spoof, activates reader, waits until a EM410x tag gets presented then it starts simulating the found UID"); + PrintAndLog(""); + PrintAndLog("Usage: lf em 410xspoof [h]"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 410xspoof"); + return 0; +} +int usage_lf_em410x_clone(void) { + PrintAndLog("Simulating EM410x tag"); + PrintAndLog(""); + PrintAndLog("Usage: lf em 410xclone [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" uid - uid (10 HEX symbols)"); + PrintAndLog(" clock - clock (32|64) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 410xclone 0F0368568B"); + PrintAndLog(" lf em 410xclone 0F0368568B 32"); + return 0; +} int usage_lf_em410x_sim(void) { PrintAndLog("Simulating EM410x tag"); PrintAndLog(""); @@ -27,9 +77,326 @@ int usage_lf_em410x_sim(void) { PrintAndLog(" lf em 410xsim 0F0368568B 32"); return 0; } +int usage_lf_em410x_brute(void) { + PrintAndLog("Bruteforcing by emulating EM410x tag"); + PrintAndLog(""); + PrintAndLog("Usage: lf em 410xbrute [h] ids.txt [d 2000] [c clock]"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" ids.txt - file with UIDs in HEX format, one per line"); + PrintAndLog(" d (2000) - pause delay in milliseconds between UIDs simulation, default 1000 ms (optional)"); + PrintAndLog(" c (32) - clock (32|64), default 64 (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 410xbrute ids.txt"); + PrintAndLog(" lf em 410xbrute ids.txt c 32"); + PrintAndLog(" lf em 410xbrute ids.txt d 3000"); + PrintAndLog(" lf em 410xbrute ids.txt d 3000 c 32"); + return 0; +} -int CmdEMdemodASK(const char *Cmd) -{ +//////////////// 4050 / 4450 commands +int usage_lf_em4x50_dump(void) { + PrintAndLog("Dump EM4x50/EM4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x50dump [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x50dump"); + PrintAndLog(" lf em 4x50dump 11223344"); + return 0; +} +int usage_lf_em4x50_read(void) { + PrintAndLog("Read EM 4x50/EM4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x50read [h]
"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" address - memory address to read. (0-15)"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x50read 1"); + PrintAndLog(" lf em 4x50read 1 11223344"); + return 0; +} +int usage_lf_em4x50_write(void) { + PrintAndLog("Write EM 4x50/4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x50write [h]
"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" address - memory address to write to. (0-15)"); + PrintAndLog(" data - data to write (hex)"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x50write 1 deadc0de"); + PrintAndLog(" lf em 4x50write 1 deadc0de 11223344"); + return 0; +} + +//////////////// 4205 / 4305 commands +int usage_lf_em4x05_dump(void) { + PrintAndLog("Dump EM4x05/EM4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x05dump [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x05dump"); + PrintAndLog(" lf em 4x05dump 11223344"); + return 0; +} +int usage_lf_em4x05_read(void) { + PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x05read [h]
"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" address - memory address to read. (0-15)"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x05read 1"); + PrintAndLog(" lf em 4x05read 1 11223344"); + return 0; +} +int usage_lf_em4x05_write(void) { + PrintAndLog("Write EM4x05/4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x05write [h]
"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" address - memory address to write to. (0-15)"); + PrintAndLog(" data - data to write (hex)"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x05write 1 deadc0de"); + PrintAndLog(" lf em 4x05write 1 deadc0de 11223344"); + return 0; +} +int usage_lf_em4x05_info(void) { + PrintAndLog("Tag information EM4205/4305/4469//4569 tags. Tag must be on antenna."); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x05info [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x05info"); + PrintAndLog(" lf em 4x05info deadc0de"); + return 0; +} + + +// Construct the graph for emulating an EM410X tag +void ConstructEM410xEmulGraph(const char *uid,const uint8_t clock) { + + int i, n, j, binary[4], parity[4]; + /* clear our graph */ + ClearGraph(0); + + /* write 9 start bits */ + for (i = 0; i < 9; i++) + AppendGraph(0, clock, 1); + + /* for each hex char */ + parity[0] = parity[1] = parity[2] = parity[3] = 0; + for (i = 0; i < 10; i++){ + /* read each hex char */ + sscanf(&uid[i], "%1x", &n); + for (j = 3; j >= 0; j--, n/= 2) + binary[j] = n % 2; + + /* append each bit */ + AppendGraph(0, clock, binary[0]); + AppendGraph(0, clock, binary[1]); + AppendGraph(0, clock, binary[2]); + AppendGraph(0, clock, binary[3]); + + /* append parity bit */ + AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + + /* keep track of column parity */ + parity[0] ^= binary[0]; + parity[1] ^= binary[1]; + parity[2] ^= binary[2]; + parity[3] ^= binary[3]; + } + + /* parity columns */ + AppendGraph(0, clock, parity[0]); + AppendGraph(0, clock, parity[1]); + AppendGraph(0, clock, parity[2]); + AppendGraph(0, clock, parity[3]); + + /* stop bit */ + AppendGraph(1, clock, 0); +} + +//by marshmellow +//print 64 bit EM410x ID in multiple formats +void printEM410x(uint32_t hi, uint64_t id) { + + if (!id && !hi) return; + + PrintAndLog("EM410x %s pattern found", (hi) ? "XL" : "" ); + + uint64_t iii=1; + uint64_t id2lo=0; + uint32_t ii=0; + uint32_t i=0; + for (ii=5; ii>0;ii--){ + for (i=0;i<8;i++){ + id2lo=(id2lo<<1LL) | ((id & (iii << (i+((ii-1)*8)))) >> (i+((ii-1)*8))); + } + } + + if (hi){ + //output 88 bit em id + PrintAndLog("\nEM TAG ID : %06X%016" PRIX64, hi, id); + } else { + //output 40 bit em id + PrintAndLog("\nEM TAG ID : %010" PRIX64, id); + PrintAndLog("\nPossible de-scramble patterns"); + PrintAndLog("Unique TAG ID : %010" PRIX64, id2lo); + PrintAndLog("HoneyWell IdentKey {"); + PrintAndLog("DEZ 8 : %08" PRIu64, id & 0xFFFFFF); + PrintAndLog("DEZ 10 : %010" PRIu64, id & 0xFFFFFFFF); + PrintAndLog("DEZ 5.5 : %05" PRIu64 ".%05" PRIu64, (id>>16LL) & 0xFFFF, (id & 0xFFFF)); + PrintAndLog("DEZ 3.5A : %03" PRIu64 ".%05" PRIu64, (id>>32ll), (id & 0xFFFF)); + PrintAndLog("DEZ 3.5B : %03" PRIu64 ".%05" PRIu64, (id & 0xFF000000) >> 24, (id & 0xFFFF)); + PrintAndLog("DEZ 3.5C : %03" PRIu64 ".%05" PRIu64, (id & 0xFF0000) >> 16, (id & 0xFFFF)); + PrintAndLog("DEZ 14/IK2 : %014" PRIu64, id); + PrintAndLog("DEZ 15/IK3 : %015" PRIu64, id2lo); + PrintAndLog("DEZ 20/ZK : %02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64, + (id2lo & 0xf000000000) >> 36, + (id2lo & 0x0f00000000) >> 32, + (id2lo & 0x00f0000000) >> 28, + (id2lo & 0x000f000000) >> 24, + (id2lo & 0x0000f00000) >> 20, + (id2lo & 0x00000f0000) >> 16, + (id2lo & 0x000000f000) >> 12, + (id2lo & 0x0000000f00) >> 8, + (id2lo & 0x00000000f0) >> 4, + (id2lo & 0x000000000f) + ); + uint64_t paxton = (((id>>32) << 24) | (id & 0xffffff)) + 0x143e00; + PrintAndLog("}\nOther : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id&0xFFFF), ((id>>16LL) & 0xFF), (id & 0xFFFFFF)); + PrintAndLog("Pattern Paxton : %" PRIu64 " [0x%" PRIX64 "]", paxton, paxton); + + uint32_t p1id = (id & 0xFFFFFF); + uint8_t arr[32] = {0x00}; + int i =0; + int j = 23; + for (; i < 24; ++i, --j ){ + arr[i] = (p1id >> i) & 1; + } + + uint32_t p1 = 0; + + p1 |= arr[23] << 21; + p1 |= arr[22] << 23; + p1 |= arr[21] << 20; + p1 |= arr[20] << 22; + + p1 |= arr[19] << 18; + p1 |= arr[18] << 16; + p1 |= arr[17] << 19; + p1 |= arr[16] << 17; + + p1 |= arr[15] << 13; + p1 |= arr[14] << 15; + p1 |= arr[13] << 12; + p1 |= arr[12] << 14; + + p1 |= arr[11] << 6; + p1 |= arr[10] << 2; + p1 |= arr[9] << 7; + p1 |= arr[8] << 1; + + p1 |= arr[7] << 0; + p1 |= arr[6] << 8; + p1 |= arr[5] << 11; + p1 |= arr[4] << 3; + + p1 |= arr[3] << 10; + p1 |= arr[2] << 4; + p1 |= arr[1] << 5; + p1 |= arr[0] << 9; + PrintAndLog("Pattern 1 : %d [0x%X]", p1, p1); + + uint16_t sebury1 = id & 0xFFFF; + uint8_t sebury2 = (id >> 16) & 0x7F; + uint32_t sebury3 = id & 0x7FFFFF; + PrintAndLog("Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3); + } +} +/* Read the ID of an EM410x tag. + * Format: + * 1111 1111 1 <-- standard non-repeatable header + * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID + * .... + * CCCC <-- each bit here is parity for the 10 bits above in corresponding column + * 0 <-- stop bit, end of tag + */ +int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ) { + size_t idx = 0; + size_t size = DemodBufferLen; + uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; + memcpy(BitStream, DemodBuffer, size); + int ans = Em410xDecode(BitStream, &size, &idx, hi, lo); + if ( ans < 0){ + if (g_debugMode){ + if (ans == -1) + PrintAndLog("DEBUG: Error - Em410x not only 0|1 in decoded bitstream"); + else if (ans == -2) + PrintAndLog("DEBUG: Error - Em410x preamble not found"); + else if (ans == -3) + PrintAndLog("DEBUG: Error - Em410x Size not correct: %d", size); + else if (ans == -4) + PrintAndLog("DEBUG: Error - Em410x parity failed"); + } + return 0; + } + if (!lo && !hi) { + PrintAndLog("DEBUG: Error - Em410x decoded to all zeros"); + return 0; + } + + //set GraphBuffer for clone or sim command + setDemodBuf(BitStream, size, idx); + if (g_debugMode){ + PrintAndLog("DEBUG: Em410x idx: %d, Len: %d, Printing Demod Buffer:", idx, size); + printDemodBuff(); + } + + if (verbose) + printEM410x(*hi, *lo); + + return 1; +} +int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose) { + bool st = true; + if (!ASKDemod_ext(Cmd, false, false, 1, &st)) return 0; + return AskEm410xDecode(verbose, hi, lo); +} + +//by marshmellow +//takes 3 arguments - clock, invert and maxErr as integers +//attempts to demodulate ask while decoding manchester +//prints binary found and saves in graphbuffer for further commands +int CmdAskEM410xDemod(const char *Cmd) { + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') + return usage_lf_em410x_demod(); + + uint64_t lo = 0; + uint32_t hi = 0; + return AskEm410xDemod(Cmd, &hi, &lo, true); +} + +int CmdEMdemodASK(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); uint8_t findone = (cmdp == '1') ? 1 : 0; UsbCommand c = {CMD_EM410X_DEMOD, {findone, 0, 0}}; @@ -45,8 +412,7 @@ int CmdEMdemodASK(const char *Cmd) * CCCC <-- each bit here is parity for the 10 bits above in corresponding column * 0 <-- stop bit, end of tag */ -int CmdEM410xRead(const char *Cmd) -{ +int CmdEM410xRead(const char *Cmd) { uint32_t hi = 0; uint64_t lo = 0; @@ -62,7 +428,6 @@ int CmdEM410xSim(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_sim(); - int i, n, j, binary[4], parity[4]; uint8_t uid[5] = {0x00}; /* clock is 64 in EM410x tags */ @@ -76,50 +441,118 @@ int CmdEM410xSim(const char *Cmd) { param_getdec(Cmd, 1, &clock); PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock); - PrintAndLog("Press pm3-button to about simulation"); - - /* clear our graph */ - ClearGraph(0); + PrintAndLog("Press pm3-button to abort simulation"); - /* write 9 start bits */ - for (i = 0; i < 9; i++) - AppendGraph(0, clock, 1); + ConstructEM410xEmulGraph(Cmd, clock); + + CmdLFSim("0"); //240 start_gap. + return 0; +} - /* for each hex char */ - parity[0] = parity[1] = parity[2] = parity[3] = 0; - for (i = 0; i < 10; i++) - { - /* read each hex char */ - sscanf(&Cmd[i], "%1x", &n); - for (j = 3; j >= 0; j--, n/= 2) - binary[j] = n % 2; +int CmdEM410xBrute(const char *Cmd) { + char filename[FILE_PATH_SIZE] = {0}; + FILE *f = NULL; + char buf[11]; + uint32_t uidcnt = 0; + uint8_t stUidBlock = 20; + uint8_t *uidBlock = NULL, *p = NULL; + uint8_t uid[5] = {0x00}; + /* clock is 64 in EM410x tags */ + uint8_t clock = 64; + /* default pause time: 1 second */ + uint32_t delay = 1000; + + char cmdp = param_getchar(Cmd, 0); + if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_brute(); + + cmdp = param_getchar(Cmd, 1); + if (cmdp == 'd' || cmdp == 'D') { + delay = param_get32ex(Cmd, 2, 1000, 10); + param_getdec(Cmd, 4, &clock); + } else if (cmdp == 'c' || cmdp == 'C') { + param_getdec(Cmd, 2, &clock); + delay = param_get32ex(Cmd, 4, 1000, 10); + } - /* append each bit */ - AppendGraph(0, clock, binary[0]); - AppendGraph(0, clock, binary[1]); - AppendGraph(0, clock, binary[2]); - AppendGraph(0, clock, binary[3]); + param_getstr(Cmd, 0, filename); + + if (strlen(filename) == 0) { + PrintAndLog("Error: Please specify a filename"); + return 1; + } + + if ((f = fopen(filename, "r")) == NULL) { + PrintAndLog("Error: Could not open UIDs file [%s]", filename); + return 1; + } - /* append parity bit */ - AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + uidBlock = calloc(stUidBlock, 5); + if (uidBlock == NULL) return 1; + + while( fgets(buf, sizeof(buf), f) ) { + if (strlen(buf) < 10 || buf[9] == '\n') continue; + while (fgetc(f) != '\n' && !feof(f)); //goto next line - /* keep track of column parity */ - parity[0] ^= binary[0]; - parity[1] ^= binary[1]; - parity[2] ^= binary[2]; - parity[3] ^= binary[3]; + //The line start with # is comment, skip + if( buf[0]=='#' ) continue; + + if (param_gethex(buf, 0, uid, 10)) { + PrintAndLog("UIDs must include 10 HEX symbols"); + free(uidBlock); + fclose(f); + return 1; + } + + buf[10] = 0; + + if ( stUidBlock - uidcnt < 2) { + p = realloc(uidBlock, 5 * (stUidBlock += 10) ); + if (!p) { + PrintAndLog("Cannot allocate memory for UIDs"); + free(uidBlock); + fclose(f); + return 1; + } + uidBlock = p; + } + memset(uidBlock + 5 * uidcnt, 0, 5); + num_to_bytes(strtoll(buf, NULL, 16), 5, uidBlock + 5 * uidcnt); + uidcnt++; + memset(buf, 0, sizeof(buf)); } + + fclose(f); + + if (uidcnt == 0) { + PrintAndLog("No UIDs found in file"); + free(uidBlock); + return 1; + } + PrintAndLog("Loaded %d UIDs from %s, pause delay: %d ms", uidcnt, filename, delay); + + // loop + for(uint32_t c = 0; c < uidcnt; ++c ) { + char testuid[11]; + testuid[10] = 0; + + if (ukbhit()) { + int gc = getchar(); (void)gc; + printf("\nAborted via keyboard!\n"); + free(uidBlock); + return 0; + } + + sprintf(testuid, "%010" PRIX64, bytes_to_num(uidBlock + 5*c, 5)); + PrintAndLog("Bruteforce %d / %d: simulating UID %s, clock %d", c + 1, uidcnt, testuid, clock); + + ConstructEM410xEmulGraph(testuid, clock); + + CmdLFSim("0"); //240 start_gap. - /* parity columns */ - AppendGraph(0, clock, parity[0]); - AppendGraph(0, clock, parity[1]); - AppendGraph(0, clock, parity[2]); - AppendGraph(0, clock, parity[3]); - - /* stop bit */ - AppendGraph(1, clock, 0); - - CmdLFSim("0"); //240 start_gap. + msleep(delay); + } + + free(uidBlock); return 0; } @@ -137,33 +570,38 @@ int CmdEM410xSim(const char *Cmd) { int CmdEM410xWatch(const char *Cmd) { do { if (ukbhit()) { + int gc = getchar(); (void)gc; printf("\naborted via keyboard!\n"); break; } - CmdLFRead("s"); - getSamples("6144",true); + lf_read(true, 8201); + } while (!CmdEM410xRead("")); return 0; } //currently only supports manchester modulations -// todo: helptext -int CmdEM410xWatchnSpoof(const char *Cmd) -{ +int CmdEM410xWatchnSpoof(const char *Cmd) { + + char cmdp = param_getchar(Cmd, 0); + if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_ws(); + // loops if the captured ID was in XL-format. CmdEM410xWatch(Cmd); - PrintAndLog("# Replaying captured ID: %" PRIu64 , g_em410xid); + PrintAndLog("# Replaying captured ID: %010" PRIx64 , g_em410xid); CmdLFaskSim(""); return 0; } -int CmdEM410xWrite(const char *Cmd) -{ +int CmdEM410xWrite(const char *Cmd) { + char cmdp = param_getchar(Cmd, 0); + if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_write(); + uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value int card = 0xFF; // invalid card value uint32_t clock = 0; // invalid clock value - sscanf(Cmd, "%" PRIx64 " %d %d", &id, &card, &clock); + sscanf(Cmd, "%" SCNx64 " %d %d", &id, &card, &clock); // Check ID if (id == 0xFFFFFFFFFFFFFFFF) { @@ -186,7 +624,6 @@ int CmdEM410xWrite(const char *Cmd) } // Check Clock - // Default: 64 if (clock == 0) clock = 64; @@ -216,8 +653,8 @@ int CmdEM410xWrite(const char *Cmd) return 0; } -bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) -{ +//**************** Start of EM4x50 Code ************************ +bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { if (rows*cols>size) return false; uint8_t colP=0; //assume last col is a parity and do not test @@ -230,8 +667,7 @@ bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t col return true; } -bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) -{ +bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { if (rows*cols>size) return false; uint8_t rowP=0; //assume last row is a parity row and do not test @@ -281,50 +717,9 @@ bool EMwordparitytest(uint8_t *bits){ return true; } - //////////////// 4050 / 4450 commands -int usage_lf_em4x50_dump(void) { - PrintAndLog("Dump EM4x50/EM4x69. Tag must be on antenna. "); - PrintAndLog(""); - PrintAndLog("Usage: lf em 4x50dump [h] "); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" pwd - password (hex) (optional)"); - PrintAndLog("samples:"); - PrintAndLog(" lf em 4x50dump"); - PrintAndLog(" lf em 4x50dump 11223344"); - return 0; -} -int usage_lf_em4x50_read(void) { - PrintAndLog("Read EM 4x50/EM4x69. Tag must be on antenna. "); - PrintAndLog(""); - PrintAndLog("Usage: lf em 4x50read [h]
"); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" address - memory address to read. (0-15)"); - PrintAndLog(" pwd - password (hex) (optional)"); - PrintAndLog("samples:"); - PrintAndLog(" lf em 4x50read 1"); - PrintAndLog(" lf em 4x50read 1 11223344"); - return 0; -} -int usage_lf_em4x50_write(void) { - PrintAndLog("Write EM 4x50/4x69. Tag must be on antenna. "); - PrintAndLog(""); - PrintAndLog("Usage: lf em 4x50write [h]
"); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" address - memory address to write to. (0-15)"); - PrintAndLog(" data - data to write (hex)"); - PrintAndLog(" pwd - password (hex) (optional)"); - PrintAndLog("samples:"); - PrintAndLog(" lf em 4x50write 1 deadc0de"); - PrintAndLog(" lf em 4x50write 1 deadc0de 11223344"); - return 0; -} -uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest) -{ +uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest) { if (size<45) return 0; uint32_t code = bytebits_to_byte(BitStream,8); @@ -394,9 +789,6 @@ int EM4x50Read(const char *Cmd, bool verbose) { // get user entry if any sscanf(Cmd, "%i %i", &clk, &invert); - // save GraphBuffer - to restore it later - save_restoreGB(1); - // first get high and low values for (i = 0; i < GraphTraceLen; i++) { if (GraphBuffer[i] > high) @@ -496,6 +888,8 @@ int EM4x50Read(const char *Cmd, bool verbose) { } else if (start < 0) return 0; start = skip; snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47); + // save GraphBuffer - to restore it later + save_restoreGB(GRAPH_SAVE); // get rid of leading crap snprintf(tmp, sizeof(tmp), "%i", skip); CmdLtrim(tmp); @@ -523,7 +917,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { phaseoff = 0; i += 2; if (ASKDemod(tmp2, false, false, 1) < 1) { - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return 0; } //set DemodBufferLen to just one block @@ -562,7 +956,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { } //restore GraphBuffer - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return (int)AllPTest; } @@ -731,58 +1125,6 @@ bool demodEM4x05resp(uint32_t *word) { } //////////////// 4205 / 4305 commands -int usage_lf_em4x05_dump(void) { - PrintAndLog("Dump EM4x05/EM4x69. Tag must be on antenna. "); - PrintAndLog(""); - PrintAndLog("Usage: lf em 4x05dump [h] "); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" pwd - password (hex) (optional)"); - PrintAndLog("samples:"); - PrintAndLog(" lf em 4x05dump"); - PrintAndLog(" lf em 4x05dump 11223344"); - return 0; -} -int usage_lf_em4x05_read(void) { - PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. "); - PrintAndLog(""); - PrintAndLog("Usage: lf em 4x05read [h]
"); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" address - memory address to read. (0-15)"); - PrintAndLog(" pwd - password (hex) (optional)"); - PrintAndLog("samples:"); - PrintAndLog(" lf em 4x05read 1"); - PrintAndLog(" lf em 4x05read 1 11223344"); - return 0; -} -int usage_lf_em4x05_write(void) { - PrintAndLog("Write EM4x05/4x69. Tag must be on antenna. "); - PrintAndLog(""); - PrintAndLog("Usage: lf em 4x05write [h]
"); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" address - memory address to write to. (0-15)"); - PrintAndLog(" data - data to write (hex)"); - PrintAndLog(" pwd - password (hex) (optional)"); - PrintAndLog("samples:"); - PrintAndLog(" lf em 4x05write 1 deadc0de"); - PrintAndLog(" lf em 4x05write 1 deadc0de 11223344"); - return 0; -} -int usage_lf_em4x05_info(void) { - PrintAndLog("Tag information EM4205/4305/4469//4569 tags. Tag must be on antenna."); - PrintAndLog(""); - PrintAndLog("Usage: lf em 4x05info [h] "); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" pwd - password (hex) (optional)"); - PrintAndLog("samples:"); - PrintAndLog(" lf em 4x05info"); - PrintAndLog(" lf em 4x05info deadc0de"); - return 0; -} - int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) { UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}}; clearCommandBuffer(); @@ -852,8 +1194,7 @@ int CmdEM4x05Read(const char *Cmd) { } if ( pwd == 1 ) { PrintAndLog("Reading address %02u", addr); - } - else { + } else { usePwd = true; PrintAndLog("Reading address %02u | password %08X", addr, pwd); } @@ -927,8 +1268,8 @@ void printEM4x05config(uint32_t wordData) { uint8_t delay = (wordData >> 12) & 0x3; char cdelay[33]; memset(cdelay,0,sizeof(cdelay)); - uint8_t LWR = (wordData >> 14) & 0xF; //last word read - + uint8_t numblks = EM4x05_GET_NUM_BLOCKS(wordData); + uint8_t LWR = numblks+5-1; //last word read switch (encoder) { case 0: snprintf(enc,sizeof(enc),"NRZ"); break; case 1: snprintf(enc,sizeof(enc),"Manchester"); break; @@ -956,21 +1297,29 @@ void printEM4x05config(uint32_t wordData) { case 2: snprintf(cdelay, sizeof(cdelay),"BP/4 or 1/4th bit period delay"); break; case 3: snprintf(cdelay, sizeof(cdelay),"no delay"); break; } + uint8_t readLogin = (wordData & EM4x05_READ_LOGIN_REQ)>>18; + uint8_t readHKL = (wordData & EM4x05_READ_HK_LOGIN_REQ)>>19; + uint8_t writeLogin = (wordData & EM4x05_WRITE_LOGIN_REQ)>>20; + uint8_t writeHKL = (wordData & EM4x05_WRITE_HK_LOGIN_REQ)>>21; + uint8_t raw = (wordData & EM4x05_READ_AFTER_WRITE)>>22; + uint8_t disable = (wordData & EM4x05_DISABLE_ALLOWED)>>23; + uint8_t rtf = (wordData & EM4x05_READER_TALK_FIRST)>>24; + uint8_t pigeon = (wordData & (1<<26))>>26; PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData); - PrintAndLog("Config Breakdown:", wordData); + PrintAndLog("Config Breakdown:"); PrintAndLog(" Data Rate: %02u | RF/%u", wordData & 0x3F, datarate); PrintAndLog(" Encoder: %u | %s", encoder, enc); PrintAndLog(" PSK CF: %u | %s", PSKcf, cf); PrintAndLog(" Delay: %u | %s", delay, cdelay); - PrintAndLog(" LastWordR: %02u | Address of last word for default read", LWR); - PrintAndLog(" ReadLogin: %u | Read Login is %s", (wordData & 0x40000)>>18, (wordData & 0x40000) ? "Required" : "Not Required"); - PrintAndLog(" ReadHKL: %u | Read Housekeeping Words Login is %s", (wordData & 0x80000)>>19, (wordData & 0x80000) ? "Required" : "Not Required"); - PrintAndLog("WriteLogin: %u | Write Login is %s", (wordData & 0x100000)>>20, (wordData & 0x100000) ? "Required" : "Not Required"); - PrintAndLog(" WriteHKL: %u | Write Housekeeping Words Login is %s", (wordData & 0x200000)>>21, (wordData & 0x200000) ? "Required" : "Not Required"); - PrintAndLog(" R.A.W.: %u | Read After Write is %s", (wordData & 0x400000)>>22, (wordData & 0x400000) ? "On" : "Off"); - PrintAndLog(" Disable: %u | Disable Command is %s", (wordData & 0x800000)>>23, (wordData & 0x800000) ? "Accepted" : "Not Accepted"); - PrintAndLog(" R.T.F.: %u | Reader Talk First is %s", (wordData & 0x1000000)>>24, (wordData & 0x1000000) ? "Enabled" : "Disabled"); - PrintAndLog(" Pigeon: %u | Pigeon Mode is %s\n", (wordData & 0x4000000)>>26, (wordData & 0x4000000) ? "Enabled" : "Disabled"); + PrintAndLog(" LastWordR: %02u | Address of last word for default read - meaning %u blocks are output", LWR, numblks); + PrintAndLog(" ReadLogin: %u | Read Login is %s", readLogin, readLogin ? "Required" : "Not Required"); + PrintAndLog(" ReadHKL: %u | Read Housekeeping Words Login is %s", readHKL, readHKL ? "Required" : "Not Required"); + PrintAndLog("WriteLogin: %u | Write Login is %s", writeLogin, writeLogin ? "Required" : "Not Required"); + PrintAndLog(" WriteHKL: %u | Write Housekeeping Words Login is %s", writeHKL, writeHKL ? "Required" : "Not Required"); + PrintAndLog(" R.A.W.: %u | Read After Write is %s", raw, raw ? "On" : "Off"); + PrintAndLog(" Disable: %u | Disable Command is %s", disable, disable ? "Accepted" : "Not Accepted"); + PrintAndLog(" R.T.F.: %u | Reader Talk First is %s", rtf, rtf ? "Enabled" : "Disabled"); + PrintAndLog(" Pigeon: %u | Pigeon Mode is %s\n", pigeon, pigeon ? "Enabled" : "Disabled"); } void printEM4x05info(uint32_t block0, uint32_t serial) { @@ -1065,19 +1414,20 @@ int CmdEM4x05Info(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"}, - {"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"}, - {"410xsim", CmdEM410xSim, 0, "simulate EM410x tag"}, - {"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, - {"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, - {"410xwrite", CmdEM410xWrite, 0, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, - {"4x05dump", CmdEM4x05Dump, 0, "dump EM4205/4305 tag"}, - {"4x05info", CmdEM4x05Info, 0, "tag information EM4x05/EM4x69"}, - {"4x05read", CmdEM4x05Read, 0, "read word data from EM4205/4305"}, - {"4x05write", CmdEM4x05Write, 0, "write word data to EM4205/4305"}, - {"4x50read", CmdEM4x50Read, 0, "read word data from EM4x50"}, - {"4x50write", CmdEM4x50Write, 0, "write word data to EM4x50"}, - {"4x50dump", CmdEM4x50Dump, 0, "dump EM4x50 tag"}, + {"410x_demod", CmdEMdemodASK, 0, "Extract ID from EM410x tag on antenna)"}, + {"410x_read", CmdEM410xRead, 1, "Extract ID from EM410x tag from GraphBuffer"}, + {"410x_sim", CmdEM410xSim, 0, "simulate EM410x tag"}, + {"410x_brute", CmdEM410xBrute, 0, "Reader bruteforce attack by simulating EM410x tags"}, + {"410x_watch", CmdEM410xWatch, 0, "Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, + {"410x_spoof", CmdEM410xWatchnSpoof, 0, "Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, + {"410x_write", CmdEM410xWrite, 0, "Write EM410x UID to T5555(Q5) or T55x7 tag"}, + {"4x05_dump", CmdEM4x05Dump, 0, "dump EM4x05/EM4x69 tag"}, + {"4x05_info", CmdEM4x05Info, 0, "tag information EM4x05/EM4x69"}, + {"4x05_read", CmdEM4x05Read, 0, "read word data from EM4x05/EM4x69"}, + {"4x05_write", CmdEM4x05Write, 0, "write word data to EM4x05/EM4x69"}, + {"4x50_read", CmdEM4x50Read, 0, "read word data from EM4x50"}, + {"4x50_write", CmdEM4x50Write, 0, "write word data to EM4x50"}, + {"4x50_dump", CmdEM4x50Dump, 0, "dump EM4x50 tag"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index 168cfbd32..464ae365c 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh -// +// 2016, 2017 marshmellow, iceman // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -26,22 +26,46 @@ #include "cmdlf.h" #include "lfdemod.h" +extern int CmdLFEM4X(const char *Cmd); + extern int CmdEMdemodASK(const char *Cmd); +extern int CmdAskEM410xDemod(const char *Cmd); extern int CmdEM410xRead(const char *Cmd); + extern int CmdEM410xSim(const char *Cmd); +extern int CmdEM410xBrute(const char *Cmd); extern int CmdEM410xWatch(const char *Cmd); extern int CmdEM410xWatchnSpoof(const char *Cmd); extern int CmdEM410xWrite(const char *Cmd); +extern int CmdEM4x05Dump(const char *Cmd); +extern int CmdEM4x05Info(const char *Cmd); +extern int CmdEM4x05Read(const char *Cmd); +extern int CmdEM4x05Write(const char *Cmd); extern int CmdEM4x50Read(const char *Cmd); -extern int CmdLFEM4X(const char *Cmd); -extern int CmdReadWord(const char *Cmd); -extern int CmdWriteWord(const char *Cmd); -extern int EM4x50Read(const char *Cmd, bool verbose); +extern int CmdEM4x50Write(const char *Cmd); +extern int CmdEM4x50Dump(const char *Cmd); +extern int EM4x50Read(const char *Cmd, bool verbose); bool EM4x05IsBlock0(uint32_t *word); -int usage_lf_em410x_sim(void); -int usage_lf_em_read(void); -int usage_lf_em_write(void); +extern void printEM410x(uint32_t hi, uint64_t id); +extern int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ); +extern int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose); + + +extern int usage_lf_em410x_sim(void); +extern int usage_lf_em410x_ws(void); +extern int usage_lf_em410x_clone(void); +extern int usage_lf_em410x_sim(void); +extern int usage_lf_em410x_brute(void); + +extern int usage_lf_em4x50_dump(void); +extern int usage_lf_em4x50_read(void); +extern int usage_lf_em4x50_write(void); + +extern int usage_lf_em4x05_dump(void); +extern int usage_lf_em4x05_read(void); +extern int usage_lf_em4x05_write(void); +extern int usage_lf_em4x05_info(void); #endif diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index f6f725aa8..e141df836 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -4,7 +4,8 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency Presco tag commands +// Low frequency fdx-b tag commands +// Differential Biphase, rf/32, 128 bits (known) //----------------------------------------------------------------------------- #include "cmdlffdx.h" @@ -32,7 +33,7 @@ static int CmdHelp(const char *Cmd); int usage_lf_fdx_clone(void){ PrintAndLog("Clone a FDX-B animal tag to a T55x7 tag."); - PrintAndLog("Usage: lf animal clone [h] "); + PrintAndLog("Usage: lf fdx clone [h] "); PrintAndLog("Options:"); PrintAndLog(" h : This help"); PrintAndLog(" : Country id"); @@ -43,7 +44,7 @@ int usage_lf_fdx_clone(void){ // extended data PrintAndLog(" : Specify write to Q5 (t5555 instead of t55x7)"); PrintAndLog(""); - PrintAndLog("Sample: lf animal clone 999 112233"); + PrintAndLog("Sample: lf fdx clone 999 112233"); return 0; } @@ -51,15 +52,31 @@ int usage_lf_fdx_sim(void) { PrintAndLog("Enables simulation of FDX-B animal tag"); PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); PrintAndLog(""); - PrintAndLog("Usage: lf animal sim [h] "); + PrintAndLog("Usage: lf fdx sim [h] "); PrintAndLog("Options:"); PrintAndLog(" h : This help"); PrintAndLog(" : Country ID"); PrintAndLog(" : Animal ID"); PrintAndLog(""); - PrintAndLog("Sample: lf animal sim 999 112233"); + PrintAndLog("Sample: lf fdx sim 999 112233"); return 0; } + + +// Ask/Biphase Demod then try to locate an ISO 11784/85 ID +// BitStream must contain previously askrawdemod and biphasedemoded data +int detectFDXB(uint8_t *dest, size_t *size) { + //make sure buffer has enough data + if (*size < 128*2) return -1; + size_t startIdx = 0; + uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,1}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -2; //preamble not found + if (*size != 128) return -3; //wrong demoded size + //return start position + return (int)startIdx; +} + // clearing the topbit needed for the preambl detection. static void verify_values(uint32_t countryid, uint64_t animalid){ if ((animalid & 0x3FFFFFFFFF) != animalid) { @@ -122,6 +139,98 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t return 1; } +// FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits) +// 8 databits + 1 parity (1) +// CIITT 16 chksum +// NATIONAL CODE, ICAR database +// COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf +// FLAG (animal/non-animal) +/* +38 IDbits +10 country code +1 extra app bit +14 reserved bits +1 animal bit +16 ccitt CRC chksum over 64bit ID CODE. +24 appli bits. + +-- sample: 985121004515220 [ 37FF65B88EF94 ] +*/ +int CmdFDXBdemodBI(const char *Cmd){ + + int invert = 1; + int clk = 32; + int errCnt = 0; + int offset = 0, maxErr = 0; + uint8_t BitStream[MAX_DEMOD_BUF_LEN]; + size_t size = getFromGraphBuf(BitStream); + + errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0); + if ( errCnt < 0 || errCnt > maxErr ) { + if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB no data or error found %d, clock: %d", errCnt, clk); + return 0; + } + + errCnt = BiphaseRawDecode(BitStream, &size, &offset, 1); + if (errCnt < 0 || errCnt > maxErr ) { + if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB BiphaseRawDecode: %d", errCnt); + return 0; + } + + int preambleIndex = detectFDXB(BitStream, &size); + if (preambleIndex < 0){ + if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB preamble not found :: %d",preambleIndex); + return 0; + } + if (size != 128) { + if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB incorrect data length found"); + return 0; + } + + setDemodBuf(BitStream, 128, preambleIndex); + + // remove marker bits (1's every 9th digit after preamble) (pType = 2) + size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117); + if ( size != 104 ) { + if (g_debugMode) PrintAndLog("DEBUG: Error - FDXB error removeParity:: %d", size); + return 0; + } + PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); + + //got a good demod + uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32); + uint32_t countryCode = bytebits_to_byteLSBF(BitStream+38,10); + uint8_t dataBlockBit = BitStream[48]; + uint32_t reservedCode = bytebits_to_byteLSBF(BitStream+49,14); + uint8_t animalBit = BitStream[63]; + uint32_t crc16 = bytebits_to_byteLSBF(BitStream+64,16); + uint32_t extended = bytebits_to_byteLSBF(BitStream+80,24); + + uint64_t rawid = ((uint64_t)bytebits_to_byte(BitStream,32)<<32) | bytebits_to_byte(BitStream+32,32); + uint8_t raw[8]; + num_to_bytes(rawid, 8, raw); + + if (g_debugMode) PrintAndLog("Raw ID Hex: %s", sprint_hex(raw,8)); + + uint16_t calcCrc = crc16_ccitt_kermit(raw, 8); + PrintAndLog("Animal ID: %04u-%012" PRIu64, countryCode, NationalCode); + PrintAndLog("National Code: %012" PRIu64, NationalCode); + PrintAndLog("CountryCode: %04u", countryCode); + + PrintAndLog("Reserved/RFU: %u", reservedCode); + PrintAndLog("Animal Tag: %s", animalBit ? "True" : "False"); + PrintAndLog("Has extended data: %s [0x%X]", dataBlockBit ? "True" : "False", extended); + PrintAndLog("CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); + + if (g_debugMode) { + PrintAndLog("Start marker %d; Size %d", preambleIndex, size); + char *bin = sprint_bin_break(BitStream,size,16); + PrintAndLog("DEBUG BinStream:\n%s",bin); + } + return 1; +} + + //see ASKDemod for what args are accepted //almost the same demod as cmddata.c/CmdFDXBdemodBI int CmdFdxDemod(const char *Cmd) { @@ -133,23 +242,24 @@ int CmdFdxDemod(const char *Cmd) { return 0; } size_t size = DemodBufferLen; - int ans = FDXBdemodBI(DemodBuffer, &size); - if (ans < 0){ + int preambleIndex = detectFDXB(DemodBuffer, &size); + if (preambleIndex < 0){ if (g_debugMode){ - if (ans == -1) + if (preambleIndex == -1) PrintAndLog("DEBUG: Error - FDX-B too few bits found"); - else if (ans == -2) + else if (preambleIndex == -2) PrintAndLog("DEBUG: Error - FDX-B preamble not found"); - else if (ans == -3) + else if (preambleIndex == -3) PrintAndLog("DEBUG: Error - FDX-B Size not correct: %d", size); else - PrintAndLog("DEBUG: Error - FDX-B ans: %d", ans); + PrintAndLog("DEBUG: Error - FDX-B ans: %d", preambleIndex); } return 0; } - setDemodBuf(DemodBuffer, 128, ans); - setGrid_Clock(32); + // set and leave DemodBuffer intact + setDemodBuf(DemodBuffer, 128, preambleIndex); + setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex*g_DemodClock)); // remove marker bits (1's every 9th digit after preamble) (pType = 2) size = removeParity(DemodBuffer, 11, 9, 2, 117); if ( size != 104 ) { @@ -165,14 +275,11 @@ int CmdFdxDemod(const char *Cmd) { uint8_t animalBit = DemodBuffer[63]; uint32_t crc16 = bytebits_to_byteLSBF(DemodBuffer+64,16); uint32_t extended = bytebits_to_byteLSBF(DemodBuffer+80,24); - uint64_t rawid = ((uint64_t) - //bytebits_to_byte(DemodBuffer, 8) << 96) | - //bytebits_to_byte(DemodBuffer,32) << 64) | - bytebits_to_byte(DemodBuffer,32) << 32) | - bytebits_to_byte(DemodBuffer+32, 32); + uint64_t rawid = (uint64_t)(bytebits_to_byte(DemodBuffer,32)) << 32 | bytebits_to_byte(DemodBuffer+32, 32); uint8_t raw[8]; num_to_bytes(rawid, 8, raw); + uint16_t calcCrc = crc16_ccitt_kermit(raw, 8); PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found: Raw : %s", sprint_hex(raw, 8)); @@ -180,22 +287,24 @@ int CmdFdxDemod(const char *Cmd) { PrintAndLog("National Code %012" PRIu64 " (0x%" PRIx64 ")", NationalCode, NationalCode); PrintAndLog("Country Code %04u", countryCode); PrintAndLog("Reserved/RFU %u (0x04%X)", reservedCode, reservedCode); - PrintAndLog(""); PrintAndLog("Animal Tag %s", animalBit ? "True" : "False"); PrintAndLog("Has extended data %s [0x%X]", dataBlockBit ? "True" : "False", extended); PrintAndLog("CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? "Ok" : "Failed"); if (g_debugMode) { - PrintAndLog("Start marker %d; Size %d", ans, size); + PrintAndLog("Start marker %d; Size %d", preambleIndex, size); char *bin = sprint_bin_break(DemodBuffer, size, 16); PrintAndLog("DEBUG bin stream:\n%s", bin); } + + // set block 0 for later + //g_DemodConfig = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT; + return 1; } int CmdFdxRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("12000", true); + lf_read(true, 10000); return CmdFdxDemod(Cmd); } @@ -290,9 +399,9 @@ int CmdFdxSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdFdxDemod,1, "Attempt to extract tag data from graphbuf"}, - {"read", CmdFdxRead, 0, "Attempt to read and extract tag data"}, - {"clone", CmdFdxClone,0, "Clone animal ID tag to T55x7"}, + {"demod", CmdFdxDemod, 1, "Attempt to extract FDX-B ISO11784/85 data from the GraphBuffer"}, + {"read", CmdFdxRead, 0, "Attempt to read and extract FDX-B ISO11784/85 data"}, + {"clone", CmdFdxClone, 0, "Clone animal ID tag to T55x7 (or to q5/T5555)"}, {"sim", CmdFdxSim, 0, "Animal ID tag simulator"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlffdx.h b/client/cmdlffdx.h index 7a0c3c4db..b7b019909 100644 --- a/client/cmdlffdx.h +++ b/client/cmdlffdx.h @@ -26,9 +26,10 @@ extern int CmdFdxRead(const char *Cmd); extern int CmdFdxDemod(const char *Cmd); int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits); -int usage_lf_fdx_clone(void); -int usage_lf_fdx_sim(void); -int usage_lf_fdx_read(void); -int usage_lf_fdx_demod(void); + +extern int usage_lf_fdx_clone(void); +extern int usage_lf_fdx_sim(void); +extern int usage_lf_fdx_read(void); +extern int usage_lf_fdx_demod(void); #endif diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index 4ce4edd14..8b4491f07 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -4,10 +4,11 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency Farpoint / Pyramid tag commands +// Low frequency Farpoint G Prox II / Pyramid tag commands +// Biphase, rf/ , 96 bits (unknown key calc + some bits) //----------------------------------------------------------------------------- - #include "cmdlfguard.h" + static int CmdHelp(const char *Cmd); int usage_lf_guard_clone(void){ @@ -136,10 +137,103 @@ int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { return 1; } +// by marshmellow +// demod gProxIIDemod +// error returns as -x +// success returns start position in BitStream +// BitStream must contain previously askrawdemod and biphasedemoded data +int detectGProxII(uint8_t BitStream[], size_t *size) { + size_t startIdx=0; + uint8_t preamble[] = {1,1,1,1,1,0}; + + if (!preambleSearch(BitStream, preamble, sizeof(preamble), size, &startIdx)) + return -3; //preamble not found + + if (*size != 96) return -2; //should have found 96 bits + + //check first 6 spacer bits to verify format + if (!BitStream[startIdx+5] && !BitStream[startIdx+10] && !BitStream[startIdx+15] && !BitStream[startIdx+20] && !BitStream[startIdx+25] && !BitStream[startIdx+30]){ + //confirmed proper separator bits found + //return start position + return (int) startIdx; + } + return -5; //spacer bits not found - not a valid gproxII +} + +//by marshmellow +//attempts to demodulate and identify a G_Prox_II verex/chubb card +//WARNING: if it fails during some points it will destroy the DemodBuffer data +// but will leave the GraphBuffer intact. +//if successful it will push askraw data back to demod buffer ready for emulation +int CmdGuardDemod(const char *Cmd) { + if (!ASKbiphaseDemod(Cmd, false)){ + if (g_debugMode) PrintAndLog("DEBUG: Error - gProxII ASKbiphaseDemod failed 1st try"); + return 0; + } + size_t size = DemodBufferLen; + //call lfdemod.c demod for gProxII + int ans = detectGProxII(DemodBuffer, &size); + if (ans < 0){ + if (g_debugMode) PrintAndLog("DEBUG: Error - gProxII demod"); + return 0; + } + //got a good demod of 96 bits + uint8_t ByteStream[8] = {0x00}; + uint8_t xorKey = 0; + size_t startIdx = ans + 6; //start after 6 bit preamble + + uint8_t bits_no_spacer[90]; + //so as to not mess with raw DemodBuffer copy to a new sample array + memcpy(bits_no_spacer, DemodBuffer + startIdx, 90); + // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72)) + size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run + if (bitLen != 72) { + if (g_debugMode) + PrintAndLog("DEBUG: Error - gProxII spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx); + return 0; + } + // get key and then get all 8 bytes of payload decoded + xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8); + for (size_t idx = 0; idx < 8; idx++) { + ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey; + if (g_debugMode) PrintAndLog("DEBUG: gProxII byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]); + } + + //ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data + uint8_t fmtLen = ByteStream[0]>>2; + uint32_t FC = 0; + uint32_t Card = 0; + //get raw 96 bits to print + uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32); + uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32); + bool unknown = false; + switch(fmtLen) { + case 36: + FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); + Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); + break; + case 26: + FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7); + Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7); + break; + default : + unknown = true; + break; + } + if ( !unknown) + PrintAndLog("G-Prox-II Found: Format Len: %ubit - FC: %u - Card: %u, Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3); + else + PrintAndLog("Unknown G-Prox-II Fmt Found: Format Len: %u, Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3); + + setDemodBuf(DemodBuffer, 96, ans); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); + return 1; +} + int CmdGuardRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("12000", true); - return CmdG_Prox_II_Demod(""); + lf_read(true, 10000); + return CmdGuardDemod(Cmd); } int CmdGuardClone(const char *Cmd) { @@ -240,9 +334,10 @@ int CmdGuardSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"read", CmdGuardRead, 0, "Attempt to read and extract tag data"}, - {"clone", CmdGuardClone, 0, " clone Guardall tag"}, - {"sim", CmdGuardSim, 0, " simulate Guardall tag"}, + {"demod", CmdGuardDemod, 1, "Demodulate a G Prox II tag from the GraphBuffer"}, + {"read", CmdGuardRead, 0, "Attempt to read and extract tag data from the antenna"}, + {"clone", CmdGuardClone, 0, " clone Guardall tag"}, + {"sim", CmdGuardSim, 0, " simulate Guardall tag"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfguard.h b/client/cmdlfguard.h index 63b28789d..b01a99aff 100644 --- a/client/cmdlfguard.h +++ b/client/cmdlfguard.h @@ -4,7 +4,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency T55xx commands +// Low frequency G Prox II tag commands //----------------------------------------------------------------------------- #ifndef CMDLFGUARD_H__ #define CMDLFGUARD_H__ @@ -22,11 +22,12 @@ #include "lfdemod.h" // parityTest #include "crc.h" -int CmdLFGuard(const char *Cmd); -int CmdGuardClone(const char *Cmd); -int CmdGuardSim(const char *Cmd); +extern int CmdLFGuard(const char *Cmd); +extern int CmdGuardDemod(const char *Cmd); +extern int CmdGuardRead(const char *Cmd); +extern int CmdGuardClone(const char *Cmd); +extern int CmdGuardSim(const char *Cmd); -int usage_lf_guard_clone(void); -int usage_lf_quard_sim(void); +extern int usage_lf_guard_clone(void); +extern int usage_lf_quard_sim(void); #endif - diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index daa698086..a9f72ae34 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh -// +// 2016,2017, marshmellow, iceman // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -16,27 +16,43 @@ static int CmdHelp(const char *Cmd); +int usage_lf_hid_read(void){ + PrintAndLog("Enables HID compatible reader mode printing details."); + PrintAndLog("By default, values are printed and logged until the button is pressed or another USB command is issued."); + PrintAndLog("If the [1] option is provided, reader mode is exited after reading a single HID card."); + PrintAndLog(""); + PrintAndLog("Usage: lf hid read [h] [1]"); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" 1 : (optional) stop after reading a single card"); + PrintAndLog(""); + PrintAndLog("Samples:"); + PrintAndLog(" lf hid read"); + PrintAndLog(" lf hid read 1"); + return 0; +} int usage_lf_hid_wiegand(void){ PrintAndLog("This command converts facility code/card number to Wiegand code"); + PrintAndLog(""); PrintAndLog("Usage: lf hid wiegand [h] [OEM] [FC] [CN]"); - PrintAndLog("Options:"); PrintAndLog(" h - This help"); PrintAndLog(" OEM - OEM number / site code"); PrintAndLog(" FC - facility code"); PrintAndLog(" CN - card number"); - PrintAndLog("Examples:"); + PrintAndLog("Samples:"); PrintAndLog(" lf hid wiegand 0 101 2001"); return 0; } int usage_lf_hid_sim(void){ - PrintAndLog("HID Tag simulator"); + PrintAndLog("Enables simulation of HID card with card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); PrintAndLog(""); PrintAndLog("Usage: lf hid sim [h] [ID]"); PrintAndLog("Options:"); PrintAndLog(" h - This help"); PrintAndLog(" ID - HID id"); - PrintAndLog("Examples:"); + PrintAndLog("Samples:"); PrintAndLog(" lf hid sim 224"); return 0; } @@ -48,7 +64,7 @@ int usage_lf_hid_clone(void){ PrintAndLog(" h - This help"); PrintAndLog(" ID - HID id"); PrintAndLog(" L - 84bit ID"); - PrintAndLog("Examples:"); + PrintAndLog("Samples:"); PrintAndLog(" lf hid clone 224"); PrintAndLog(" lf hid clone 224 L"); return 0; @@ -100,7 +116,105 @@ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, ui return true; } -int CmdHIDDemodFSK(const char *Cmd) { +//by marshmellow (based on existing demod + holiman's refactor) +//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded) +//print full HID Prox ID and some bit format details if found +int CmdHIDDemod(const char *Cmd) { + //raw fsk demod no manchester decoding no start bit finding just get binary from wave + uint32_t hi2=0, hi=0, lo=0; + + uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(BitStream); + if (BitLen==0) return 0; + //get binary from fsk wave + int waveIdx = 0; + int idx = HIDdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo, &waveIdx); + + if (idx < 0) { + if (g_debugMode){ + if (idx==-1){ + PrintAndLog("DEBUG: Error - HID just noise detected"); + } else if (idx == -2) { + PrintAndLog("DEBUG: Error - HID problem during FSK demod"); + } else if (idx == -3) { + PrintAndLog("DEBUG: Error - HID preamble not found"); + } else if (idx == -4) { + PrintAndLog("DEBUG: Error - HID error in Manchester data, SIZE: %d", BitLen); + } else { + PrintAndLog("DEBUG: Error - HID error demoding fsk %d", idx); + } + } + return 0; + } + + if (hi2==0 && hi==0 && lo==0) { + if (g_debugMode) PrintAndLog("DEBUG: Error - HID no values found"); + return 0; + } + + if (hi2 != 0){ //extra large HID tags + PrintAndLog("HID Prox TAG ID: %x%08x%08x (%u)", hi2, hi, lo, (lo>>1) & 0xFFFF); + } + else { //standard HID tags <38 bits + uint8_t fmtLen = 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 >>= 1; + idx3++; + } + fmtLen = idx3 + 19; + fc = 0; + cardnum = 0; + if(fmtLen==26){ + cardnum = (lo >> 1) & 0xFFFF; + fc = ( lo >> 17) & 0xFF; + } + if(fmtLen==34){ + cardnum = (lo >> 1) & 0xFFFF; + fc= ((hi & 1)<< 15) | (lo >> 17); + } + if(fmtLen==35){ + cardnum = (lo >> 1) & 0xFFFFF; + fc = ((hi & 1) << 11 ) | (lo >> 21); + } + } + else { //if bit 38 is not set then 37 bit format is used + fmtLen = 37; + fc = 0; + cardnum = 0; + if(fmtLen == 37){ + cardnum = (lo >> 1 ) & 0x7FFFF; + fc = ((hi & 0xF) << 12) | (lo >> 20); + } + } + PrintAndLog("HID Prox TAG ID: %x%08x (%u) - Format Len: %ubit - FC: %u - Card: %u", hi, lo, (lo>>1) & 0xFFFF, fmtLen, fc, cardnum); + } + setDemodBuf(BitStream,BitLen,idx); + setClockGrid(50, waveIdx + (idx*50)); + + if (g_debugMode){ + PrintAndLog("DEBUG: HID idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen); + printDemodBuff(); + } + return 1; +} + +// this read is the "normal" read, which download lf signal and tries to demod here. +int CmdHIDRead(const char *Cmd) { + lf_read(true, 12000); + return CmdHIDDemod(Cmd); +} + +// this read loops on device side. +// uses the demod in lfops.c +int CmdHIDRead_device(const char *Cmd) { + + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_hid_read(); uint8_t findone = ( Cmd[0] == '1' ) ? 1 : 0; UsbCommand c = {CMD_HID_DEMOD_FSK, {findone, 0 , 0}}; clearCommandBuffer(); @@ -426,6 +540,7 @@ int CmdHIDBrute(const char *Cmd){ } if (ukbhit()) { + int gc = getchar(); (void)gc; PrintAndLog("aborted via keyboard!"); return sendPing(); } @@ -443,12 +558,13 @@ int CmdHIDBrute(const char *Cmd){ } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"fskdemod",CmdHIDDemodFSK, 0, "Realtime HID FSK demodulator"}, - {"sim", CmdHIDSim, 0, "HID tag simulator"}, - {"clone", CmdHIDClone, 0, "Clone HID to T55x7"}, - {"wiegand", CmdHIDWiegand, 1, "Convert facility code/card number to Wiegand code"}, - {"brute", CmdHIDBrute, 0, "Bruteforce card number against reader"}, + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdHIDDemod, 0, "Demodulate HID Prox tag from the GraphBuffer"}, + {"read", CmdHIDRead, 0, "Attempt to read and extract tag data"}, + {"sim", CmdHIDSim, 0, "HID tag simulator"}, + {"clone", CmdHIDClone, 0, "Clone HID to T55x7"}, + {"wiegand", CmdHIDWiegand, 1, "Convert facility code/card number to Wiegand code"}, + {"brute", CmdHIDBrute, 0, "Bruteforce card number against reader"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index 5f5409678..c34a48406 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -18,23 +18,26 @@ #include "graph.h" #include "cmdparser.h" #include "util.h" // wiegand_add_parity etc -#include "cmdmain.h" -#include "sleep.h" +#include "cmddata.h" //for g_debugMode, demodbuff cmds +#include "cmdlf.h" // lf_read +#include "cmdmain.h" +#include "util_posix.h" #include "lfdemod.h" -int CmdLFHID(const char *Cmd); -//int CmdHIDDemod(const char *Cmd); -int CmdHIDDemodFSK(const char *Cmd); -int CmdHIDSim(const char *Cmd); -int CmdHIDClone(const char *Cmd); -int CmdHIDWiegand(const char *Cmd); -int CmdHIDBrute(const char *Cmd); +extern int CmdLFHID(const char *Cmd); +extern int CmdHIDDemod(const char *Cmd); +extern int CmdHIDRead(const char *Cmd); +extern int CmdHIDSim(const char *Cmd); +extern int CmdHIDClone(const char *Cmd); +extern int CmdHIDWiegand(const char *Cmd); +extern int CmdHIDBrute(const char *Cmd); -int usage_lf_hid_wiegand(void); -int usage_lf_hid_sim(void); -int usage_lf_hid_clone(void); -int usage_lf_hid_brute(void); +extern int usage_lf_hid_read(void); +extern int usage_lf_hid_wiegand(void); +extern int usage_lf_hid_sim(void); +extern int usage_lf_hid_clone(void); +extern int usage_lf_hid_brute(void); //void calc26(uint16_t fc, uint32_t cardno, uint8_t *out); -void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits); +extern void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits); #endif diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index b32990cdd..41f1e09b3 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -17,9 +17,10 @@ #include "cmdparser.h" #include "common.h" #include "util.h" +#include "parity.h" #include "hitag2.h" #include "hitagS.h" -#include "sleep.h" +#include "util_posix.h" #include "cmdmain.h" static int CmdHelp(const char *Cmd); @@ -107,15 +108,9 @@ int CmdLFHitagList(const char *Cmd) { char line[1000] = ""; int j; for (j = 0; j < len; j++) { - int oddparity = 0x01; - int k; - - for (k=0;k<8;k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } //if((parityBits >> (len - j - 1)) & 0x01) { - if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { + if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) { sprintf(line+(j*4), "%02x! ", frame[j]); } else { @@ -355,7 +350,9 @@ int CmdLFHitagWP(const char *Cmd) { c.arg[2]= param_get32ex(Cmd, 2, 0, 10); num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data); } break; - case 04: { //WHTSF_KEY + case 04: + case 24: + { //WHTSF_KEY num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key); c.arg[2]= param_get32ex(Cmd, 2, 0, 10); num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->crypto.data); @@ -387,15 +384,15 @@ int CmdLFHitagWP(const char *Cmd) { static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdLFHitagList, 1, " List Hitag trace history"}, - {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, - {"sim", CmdLFHitagSim, 1, " Simulate Hitag transponder"}, - {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, - {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" }, - {"simS", CmdLFHitagSimS, 1, " Simulate HitagS transponder" }, - {"checkChallenges", CmdLFHitagCheckChallenges, 1, " test all challenges" }, { - NULL,NULL, 0, NULL } + {"help", CmdHelp, 1, "This help"}, + {"list", CmdLFHitagList, 1, " List Hitag trace history"}, + {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, + {"sim", CmdLFHitagSim, 1, " Simulate Hitag transponder"}, + {"simS", CmdLFHitagSimS, 1, " Simulate HitagS transponder" }, + {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, + {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" }, + {"check_challenges", CmdLFHitagCheckChallenges, 1, " test all challenges" }, + { NULL,NULL, 0, NULL } }; int CmdLFHitag(const char *Cmd) { diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index 22b6bb063..e43ed58ff 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2012 Roel Verdult -// +// 2017 iceman // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -11,11 +11,14 @@ #ifndef CMDLFHITAG_H__ #define CMDLFHITAG_H__ -int CmdLFHitag(const char *Cmd); +extern int CmdLFHitag(const char *Cmd); -int CmdLFHitagList(const char *Cmd); -int CmdLFHitagSnoop(const char *Cmd); -int CmdLFHitagSim(const char *Cmd); -int CmdLFHitagReader(const char *Cmd); +extern int CmdLFHitagList(const char *Cmd); +extern int CmdLFHitagReader(const char *Cmd); +extern int CmdLFHitagSim(const char *Cmd); +extern int CmdLFHitagSimS(const char *Cmd); +extern int CmdLFHitagSnoop(const char *Cmd); +extern int CmdLFHitagWP(const char *Cmd); +extern int CmdLFHitagCheckChallenges(const char *Cmd); #endif diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c new file mode 100644 index 000000000..26406823b --- /dev/null +++ b/client/cmdlfindala.c @@ -0,0 +1,408 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency Indala commands +// PSK1, rf/32, 64 or 224 bits (known) +//----------------------------------------------------------------------------- + +#include "cmdlfindala.h" + +static int CmdHelp(const char *Cmd); + +int usage_lf_indala_demod(void) { + PrintAndLog("Enables Indala compatible reader mode printing details of scanned tags."); + PrintAndLog("By default, values are printed and logged until the button is pressed or another USB command is issued."); + PrintAndLog(""); + PrintAndLog("Usage: lf indala demod [h]"); + PrintAndLog("Options :"); + PrintAndLog(" h : This help"); + PrintAndLog(""); + PrintAndLog("Samples"); + PrintAndLog(" lf indala demod"); + return 0; +} + +int usage_lf_indala_sim(void) { + PrintAndLog("Enables simulation of Indala card with specified facility-code and card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog(""); + PrintAndLog("Usage: lf indala sim [h] "); + PrintAndLog("Options :"); + PrintAndLog(" h : This help"); + PrintAndLog(" : 8bit version"); + PrintAndLog(" : 8bit value facility code"); + PrintAndLog(" : 16bit value card number"); + PrintAndLog(""); + PrintAndLog("Samples"); + PrintAndLog(" lf indala sim 26 101 1337"); + return 0; +} + +int usage_lf_indala_clone(void) { + PrintAndLog("Enables cloning of Indala card with specified facility-code and card number onto T55x7."); + PrintAndLog("The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process."); + PrintAndLog(""); + PrintAndLog("Usage: lf indala clone [h] [Q5]"); + PrintAndLog("Options :"); + PrintAndLog(" h : This help"); + PrintAndLog(" : 64/221 UID"); + PrintAndLog(" Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip"); + PrintAndLog(""); + PrintAndLog("Samples"); + PrintAndLog(" lf indala clone 112233"); + return 0; +} + +// this read is the "normal" read, which download lf signal and tries to demod here. +int CmdIndalaRead(const char *Cmd) { + lf_read(true, 30000); + return CmdIndalaDemod(Cmd); +} + +// Indala 26 bit decode +// by marshmellow +// optional arguments - same as PSKDemod (clock & invert & maxerr) +int CmdIndalaDemod(const char *Cmd) { + int ans; + if (strlen(Cmd) > 0) + ans = PSKDemod(Cmd, 0); + else //default to RF/32 + ans = PSKDemod("32", 0); + + if (!ans){ + if (g_debugMode) PrintAndLog("DEBUG: Error - Indala can't demod signal: %d",ans); + return 0; + } + + uint8_t invert = 0; + size_t size = DemodBufferLen; + int idx = detectIndala26(DemodBuffer, &size, &invert); + if (idx < 0 || size > 224) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Indala wrong size, expected [64|224] got: %d", size); + return -1; + } + setDemodBuf(DemodBuffer, size, (size_t)idx); + setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); + if (invert) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Indala had to invert bits"); + for (size_t i = 0; i < size; i++) + DemodBuffer[i] ^= 1; + } + + //convert UID to HEX + uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; + uid1 = bytebits_to_byte(DemodBuffer,32); + uid2 = bytebits_to_byte(DemodBuffer+32,32); + if (DemodBufferLen==64){ + PrintAndLog("Indala Found - Bitlength %d, UID = (%x%08x)\n%s", + DemodBufferLen, uid1, uid2, sprint_bin_break(DemodBuffer,DemodBufferLen,32) + ); + } else { + uid3 = bytebits_to_byte(DemodBuffer+64,32); + uid4 = bytebits_to_byte(DemodBuffer+96,32); + uid5 = bytebits_to_byte(DemodBuffer+128,32); + uid6 = bytebits_to_byte(DemodBuffer+160,32); + uid7 = bytebits_to_byte(DemodBuffer+192,32); + PrintAndLog("Indala Found - Bitlength %d, UID = (%x%08x%08x%08x%08x%08x%08x)\n%s", + DemodBufferLen, + uid1, uid2, uid3, uid4, uid5, uid6, uid7, sprint_bin_break(DemodBuffer,DemodBufferLen,32) + ); + } + if (g_debugMode){ + PrintAndLog("DEBUG: Indala - printing demodbuffer:"); + printDemodBuff(); + } + return 1; +} + +// older alternative indala demodulate (has some positives and negatives) +// returns false positives more often - but runs against more sets of samples +// poor psk signal can be difficult to demod this approach might succeed when the other fails +// but the other appears to currently be more accurate than this approach most of the time. +int CmdIndalaDemodAlt(const char *Cmd) { + // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID + + int state = -1; + int count = 0; + int i, j; + + // worst case with GraphTraceLen=64000 is < 4096 + // under normal conditions it's < 2048 + + uint8_t rawbits[4096]; + int rawbit = 0; + int worst = 0, worstPos = 0; + + //clear clock grid and demod plot + setClockGrid(0, 0); + DemodBufferLen = 0; + + // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); + // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) + for (i = 0; i < GraphTraceLen-1; i += 2) { + count += 1; + if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { + // appears redundant - marshmellow + if (state == 0) { + for (j = 0; j < count - 8; j += 16) { + rawbits[rawbit++] = 0; + } + if ((abs(count - j)) > worst) { + worst = abs(count - j); + worstPos = i; + } + } + state = 1; + count = 0; + } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { + //appears redundant + if (state == 1) { + for (j = 0; j < count - 8; j += 16) { + rawbits[rawbit++] = 1; + } + if ((abs(count - j)) > worst) { + worst = abs(count - j); + worstPos = i; + } + } + state = 0; + count = 0; + } + } + + if (rawbit>0){ + PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); + PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); + } else { + return 0; + } + + // Finding the start of a UID + int uidlen, long_wait; + if (strcmp(Cmd, "224") == 0) { + uidlen = 224; + long_wait = 30; + } else { + uidlen = 64; + long_wait = 29; + } + + int start; + int first = 0; + for (start = 0; start <= rawbit - uidlen; start++) { + first = rawbits[start]; + for (i = start; i < start + long_wait; i++) { + if (rawbits[i] != first) { + break; + } + } + if (i == (start + long_wait)) { + break; + } + } + + if (start == rawbit - uidlen + 1) { + PrintAndLog("nothing to wait for"); + return 0; + } + + // Inverting signal if needed + if (first == 1) { + for (i = start; i < rawbit; i++) { + rawbits[i] = !rawbits[i]; + } + } + + // Dumping UID + uint8_t bits[224] = {0x00}; + char showbits[225] = {0x00}; + int bit; + i = start; + int times = 0; + + if (uidlen > rawbit) { + PrintAndLog("Warning: not enough raw bits to get a full UID"); + for (bit = 0; bit < rawbit; bit++) { + bits[bit] = rawbits[i++]; + // As we cannot know the parity, let's use "." and "/" + showbits[bit] = '.' + bits[bit]; + } + showbits[bit+1]='\0'; + PrintAndLog("Partial UID=%s", showbits); + return 0; + } else { + for (bit = 0; bit < uidlen; bit++) { + bits[bit] = rawbits[i++]; + showbits[bit] = '0' + bits[bit]; + } + times = 1; + } + + //convert UID to HEX + uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; + int idx; + uid1 = uid2 = 0; + + if (uidlen==64){ + for( idx=0; idx<64; idx++) { + if (showbits[idx] == '0') { + uid1=(uid1<<1)|(uid2>>31); + uid2=(uid2<<1)|0; + } else { + uid1=(uid1<<1)|(uid2>>31); + uid2=(uid2<<1)|1; + } + } + PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2); + } + else { + uid3 = uid4 = uid5 = uid6 = uid7 = 0; + + for( idx=0; idx<224; idx++) { + uid1=(uid1<<1)|(uid2>>31); + uid2=(uid2<<1)|(uid3>>31); + uid3=(uid3<<1)|(uid4>>31); + uid4=(uid4<<1)|(uid5>>31); + uid5=(uid5<<1)|(uid6>>31); + uid6=(uid6<<1)|(uid7>>31); + + if (showbits[idx] == '0') + uid7 = (uid7<<1) | 0; + else + uid7 = (uid7<<1) | 1; + } + PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); + } + + // Checking UID against next occurrences + int failed = 0; + for (; i + uidlen <= rawbit;) { + failed = 0; + for (bit = 0; bit < uidlen; bit++) { + if (bits[bit] != rawbits[i++]) { + failed = 1; + break; + } + } + if (failed == 1) { + break; + } + times += 1; + } + + PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); + + // Remodulating for tag cloning + // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) + // since this changes graphbuffer data. + GraphTraceLen = 32*uidlen; + i = 0; + int phase = 0; + for (bit = 0; bit < uidlen; bit++) { + if (bits[bit] == 0) { + phase = 0; + } else { + phase = 1; + } + int j; + for (j = 0; j < 32; j++) { + GraphBuffer[i++] = phase; + phase = !phase; + } + } + + RepaintGraphWindow(); + return 1; +} + +int CmdIndalaSim(const char *Cmd) { + uint16_t cn = 0; + uint8_t bits[64]; + uint8_t *bs = bits; + size_t size = sizeof(bits); + memset(bs, 0x00, size); + + uint64_t arg1 = ( 10 << 8 ) + 8; // fcHigh = 10, fcLow = 8 + uint64_t arg2 = (64 << 8)| + 1; // clk RF/64 invert=1 + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_indala_sim(); + + + + PrintAndLog("Emulating Indala UID: %u \n", cn); + PrintAndLog("Press pm3-button to abort simulation or run another command"); + + UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; + memcpy(c.d.asBytes, bs, size); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +// iceman - needs refactoring +int CmdIndalaClone(const char *Cmd) { + UsbCommand c; + uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; + + uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0; + int n = 0, i = 0; + + if (strchr(Cmd,'l') != 0) { + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + uid1 = (uid1 << 4) | (uid2 >> 28); + uid2 = (uid2 << 4) | (uid3 >> 28); + uid3 = (uid3 << 4) | (uid4 >> 28); + uid4 = (uid4 << 4) | (uid5 >> 28); + uid5 = (uid5 << 4) | (uid6 >> 28); + uid6 = (uid6 << 4) | (uid7 >> 28); + uid7 = (uid7 << 4) | (n & 0xf); + } + PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); + c.cmd = CMD_INDALA_CLONE_TAG_L; + c.d.asDwords[0] = uid1; + c.d.asDwords[1] = uid2; + c.d.asDwords[2] = uid3; + c.d.asDwords[3] = uid4; + c.d.asDwords[4] = uid5; + c.d.asDwords[5] = uid6; + c.d.asDwords[6] = uid7; + } else { + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + uid1 = (uid1 << 4) | (uid2 >> 28); + uid2 = (uid2 << 4) | (n & 0xf); + } + PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2); + c.cmd = CMD_INDALA_CLONE_TAG; + c.arg[0] = uid1; + c.arg[1] = uid2; + } + + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdIndalaDemod, 1, "Demodulate an indala tag (PSK1) from GraphBuffer"}, + {"altdemod", CmdIndalaDemodAlt, 1, "Alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, + {"read", CmdIndalaRead, 0, "Read an Indala Prox tag from the antenna"}, + {"sim", CmdIndalaSim, 0, "Indala tag simulator"}, + {"clone", CmdIndalaClone, 0, "Clone Indala to T55x7"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFINDALA(const char *Cmd){ + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfindala.h b/client/cmdlfindala.h new file mode 100644 index 000000000..80ccca22a --- /dev/null +++ b/client/cmdlfindala.h @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency Indala commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFINDALA_H__ +#define CMDLFINDALA_H__ + +#include // sscanf +#include +#include +#include "proxmark3.h" // Definitions, USB controls, etc +#include "ui.h" // PrintAndLog +#include "cmdparser.h" // CmdsParse, CmdsHelp +#include "lfdemod.h" // parityTest +#include "util.h" // weigandparity +#include "protocols.h" // for T55xx config register definitions +#include "data.h" +#include "cmdmain.h" +#include "cmddata.h" +#include "cmdlf.h" // lf_read +#include "lfdemod.h" // bitbytes_to_byte + +extern int CmdLFINDALA(const char *Cmd); + +extern int CmdIndalaDemod(const char *Cmd); +extern int CmdIndalaDemodAlt(const char *Cmd); +extern int CmdIndalaRead(const char *Cmd); +extern int CmdIndalaClone(const char *Cmd); +extern int CmdIndalaSim(const char *Cmd); + +extern int usage_lf_indala_demod(void); +extern int usage_lf_indala_clone(void); +extern int usage_lf_indala_sim(void); +#endif diff --git a/client/cmdlfio.c b/client/cmdlfio.c index 99a570e4e..2d10f0d88 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -1,20 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency ioProx commands +// FSK2a, rf/64, 64 bits (complete) +//----------------------------------------------------------------------------- + #include "cmdlfio.h" static int CmdHelp(const char *Cmd); -int usage_lf_io_fskdemod(void) { +int usage_lf_io_read(void) { PrintAndLog("Enables IOProx compatible reader mode printing details of scanned tags."); PrintAndLog("By default, values are printed and logged until the button is pressed or another USB command is issued."); PrintAndLog("If the [1] option is provided, reader mode is exited after reading a single card."); PrintAndLog(""); - PrintAndLog("Usage: lf io fskdemod [h] [1]"); + PrintAndLog("Usage: lf io read [h] [1]"); PrintAndLog("Options :"); PrintAndLog(" h : This help"); PrintAndLog(" 1 : (optional) stop after reading a single card"); PrintAndLog(""); PrintAndLog("Samples"); - PrintAndLog(" lf io fskdemod"); - PrintAndLog(" lf io fskdemod 1"); + PrintAndLog(" lf io read"); + PrintAndLog(" lf io read 1"); return 0; } @@ -51,29 +61,124 @@ int usage_lf_io_clone(void) { return 0; } -int CmdIODemodFSK(const char *Cmd) { - if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_io_fskdemod(); +// this read is the "normal" read, which download lf signal and tries to demod here. +int CmdIOProxRead(const char *Cmd) { + lf_read(true, 12000); + return CmdIOProxDemod(Cmd); +} +// this read loops on device side. +// uses the demod in lfops.c +int CmdIOProxRead_device(const char *Cmd) { + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_io_read(); int findone = (Cmd[0]=='1') ? 1 : 0; - UsbCommand c = {CMD_IO_DEMOD_FSK}; - c.arg[0] = findone; + UsbCommand c = {CMD_IO_DEMOD_FSK, {findone, 0, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; } -/* -int CmdIOProxDemod(const char *Cmd){ - if (GraphTraceLen < 4800) { - PrintAndLog("too short; need at least 4800 samples"); - return 0; - } - GraphTraceLen = 4800; - for (int i = 0; i < GraphTraceLen; ++i) { - GraphBuffer[i] = (GraphBuffer[i] < 0) ? 0 : 1; - } - RepaintGraphWindow(); - return 0; -} -*/ + +//by marshmellow +//IO-Prox demod - FSK RF/64 with preamble of 000000001 +//print ioprox ID and some format details +int CmdIOProxDemod(const char *Cmd) { + int retval = 0; + int idx = 0; + char crcStr[20]; + memset(crcStr, 0x00, sizeof(crcStr) ); + + //something in graphbuffer? + if (GraphTraceLen < 65) { + if (g_debugMode)PrintAndLog("DEBUG: Error - IO prox not enough samples in GraphBuffer"); + return retval; + } + uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; + size_t bitlen = getFromGraphBuf(BitStream); + if (bitlen == 0) return retval; + + int waveIdx = 0; + //get binary from fsk wave + idx = detectIOProx(BitStream, &bitlen, &waveIdx); + if (idx<0){ + if (g_debugMode){ + if (idx==-1){ + PrintAndLog("DEBUG: Error - IO prox just noise detected"); + } else if (idx == -2) { + PrintAndLog("DEBUG: Error - IO prox not enough samples"); + } else if (idx == -3) { + PrintAndLog("DEBUG: Error - IO prox error during fskdemod"); + } else if (idx == -4) { + PrintAndLog("DEBUG: Error - IO prox preamble not found"); + } else if (idx == -5) { + PrintAndLog("DEBUG: Error - IO prox separator bits not found"); + } else { + PrintAndLog("DEBUG: Error - IO prox error demoding fsk %d", idx); + } + } + return retval; + } + if (idx==0){ + if (g_debugMode){ + PrintAndLog("DEBUG: Error - IO prox data not found - FSK Bits: %d", bitlen); + if (bitlen > 92) PrintAndLog("%s", sprint_bin_break(BitStream,92,16)); + } + return retval; + } + //Index map + //0 10 20 30 40 50 60 + //| | | | | | | + //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 + //----------------------------------------------------------------------------- + //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 + // + //XSF(version)facility:codeone+codetwo (raw) + //Handle the data + if (idx + 64 > bitlen) { + if (g_debugMode) PrintAndLog("DEBUG: Error - IO prox not enough bits found - bitlen: %d", bitlen); + return retval; + } + + if (g_debugMode) { + PrintAndLog("%d%d%d%d%d%d%d%d %d", BitStream[idx], BitStream[idx+1], BitStream[idx+2], BitStream[idx+3], BitStream[idx+4], BitStream[idx+5], BitStream[idx+6], BitStream[idx+7], BitStream[idx+8]); + PrintAndLog("%d%d%d%d%d%d%d%d %d", BitStream[idx+9], BitStream[idx+10], BitStream[idx+11],BitStream[idx+12],BitStream[idx+13],BitStream[idx+14],BitStream[idx+15],BitStream[idx+16],BitStream[idx+17]); + PrintAndLog("%d%d%d%d%d%d%d%d %d facility", BitStream[idx+18], BitStream[idx+19], BitStream[idx+20],BitStream[idx+21],BitStream[idx+22],BitStream[idx+23],BitStream[idx+24],BitStream[idx+25],BitStream[idx+26]); + PrintAndLog("%d%d%d%d%d%d%d%d %d version", BitStream[idx+27], BitStream[idx+28], BitStream[idx+29],BitStream[idx+30],BitStream[idx+31],BitStream[idx+32],BitStream[idx+33],BitStream[idx+34],BitStream[idx+35]); + PrintAndLog("%d%d%d%d%d%d%d%d %d code1", BitStream[idx+36], BitStream[idx+37], BitStream[idx+38],BitStream[idx+39],BitStream[idx+40],BitStream[idx+41],BitStream[idx+42],BitStream[idx+43],BitStream[idx+44]); + PrintAndLog("%d%d%d%d%d%d%d%d %d code2", BitStream[idx+45], BitStream[idx+46], BitStream[idx+47],BitStream[idx+48],BitStream[idx+49],BitStream[idx+50],BitStream[idx+51],BitStream[idx+52],BitStream[idx+53]); + PrintAndLog("%d%d%d%d%d%d%d%d %d%d checksum", BitStream[idx+54],BitStream[idx+55],BitStream[idx+56],BitStream[idx+57],BitStream[idx+58],BitStream[idx+59],BitStream[idx+60],BitStream[idx+61],BitStream[idx+62],BitStream[idx+63]); + } + + uint32_t code = bytebits_to_byte(BitStream+idx,32); + uint32_t code2 = bytebits_to_byte(BitStream+idx+32,32); + uint8_t version = bytebits_to_byte(BitStream+idx+27,8); //14,4 + uint8_t facilitycode = bytebits_to_byte(BitStream+idx+18,8) ; + uint16_t number = (bytebits_to_byte(BitStream+idx+36,8)<<8)|(bytebits_to_byte(BitStream+idx+45,8)); //36,9 + uint8_t crc = bytebits_to_byte(BitStream+idx+54,8); + uint16_t calccrc = 0; + + for (uint8_t i = 1; i < 6; ++i){ + calccrc += bytebits_to_byte(BitStream + idx + 9 * i ,8); + } + calccrc &= 0xff; + calccrc = 0xff - calccrc; + + if (crc == calccrc) { + snprintf(crcStr, 3, "ok"); + retval = 1; + } else { + if (g_debugMode) PrintAndLog("DEBUG: Error - IO prox crc failed"); + + snprintf(crcStr, 20, "failed 0x%02X != 0x%02X", crc, calccrc); + retval = 0; + } + + PrintAndLog("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [crc %s]",version,facilitycode,number,code,code2, crcStr); + setDemodBuf(BitStream,64,idx); + if (g_debugMode){ + PrintAndLog("DEBUG: IO prox idx: %d, Len: %d, Printing demod buffer:", idx, 64); + printDemodBuff(); + } + return retval; +} //Index map //0 10 20 30 40 50 60 @@ -140,7 +245,7 @@ int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) { return 1; } -int CmdIOSim(const char *Cmd) { +int CmdIOProxSim(const char *Cmd) { uint16_t cn = 0; uint8_t version = 0, fc = 0; uint8_t bits[64]; @@ -183,7 +288,7 @@ int CmdIOSim(const char *Cmd) { return 0; } -int CmdIOClone(const char *Cmd) { +int CmdIOProxClone(const char *Cmd) { uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0}; uint16_t cn = 0; @@ -233,10 +338,10 @@ int CmdIOClone(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, -// {"demod", CmdIOProxDemod, 1, "Demodulate Stream"}, - {"fskdemod",CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"}, - {"sim", CmdIOSim, 0, " -- IOProx tag simulator"}, - {"clone", CmdIOClone, 0, " -- Clone IOProx to T55x7"}, + {"demod", CmdIOProxDemod, 1, "Demodulate an IOProx tag from the GraphBuffer"}, + {"read", CmdIOProxRead, 1, "Attempt to read and extract tag data"}, + {"sim", CmdIOProxSim, 0, "IOProx tag simulator"}, + {"clone", CmdIOProxClone, 0, "Clone IOProx to T55x7"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfio.h b/client/cmdlfio.h index 1e8745bba..c718cef1d 100644 --- a/client/cmdlfio.h +++ b/client/cmdlfio.h @@ -5,26 +5,28 @@ #define CMDLFIO_H__ #include // sscanf +#include +#include #include "proxmark3.h" // Definitions, USB controls, etc #include "ui.h" // PrintAndLog #include "cmdparser.h" // CmdsParse, CmdsHelp -#include "cmdlfawid.h" // AWID function declarations #include "lfdemod.h" // parityTest #include "util.h" // weigandparity #include "protocols.h" // for T55xx config register definitions - -#include -#include #include "data.h" #include "cmdmain.h" #include "cmddata.h" #include "lfdemod.h" // bitbytes_to_byte -int CmdLFIO(const char *Cmd); -int CmdIODemodFSK(const char *Cmd); -int CmdIOClone(const char *Cmd); + +extern int CmdLFIO(const char *Cmd); +extern int CmdIOProxDemod(const char *Cmd); +extern int CmdIOProxRead(const char *Cmd); +extern int CmdIOProxSim(const char *Cmd); +extern int CmdIOProxClone(const char *Cmd); int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits); -int usage_lf_io_fskdemod(void); -int usage_lf_io_clone(void); -int usage_lf_io_sim(void); + +extern int usage_lf_io_read(void); +extern int usage_lf_io_clone(void); +extern int usage_lf_io_sim(void); #endif diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index f8544020e..fddca9eeb 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -5,6 +5,7 @@ // the license. //----------------------------------------------------------------------------- // Low frequency Jablotron tag commands +// Differential Biphase, RF/64, 64 bits long (complete) //----------------------------------------------------------------------------- #include "cmdlfjablotron.h" @@ -58,6 +59,24 @@ int getJablotronBits(uint64_t fullcode, uint8_t *bits) { return 1; } +// ASK/Diphase fc/64 (inverted Biphase) +// Note: this is not a demod, this is only a detection +// the parameter *bits needs to be demoded before call +// 0xFFFF preamble, 64bits +int detectJablotron(uint8_t *bits, size_t *size) { + if (*size < 64*2) return -1; //make sure buffer has enough data + size_t startIdx = 0; + uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}; + if (preambleSearch(bits, preamble, sizeof(preamble), size, &startIdx) == 0) + return -2; //preamble not found + if (*size != 64) return -3; // wrong demoded size + + uint8_t checkchksum = jablontron_chksum(bits+startIdx); + uint8_t crc = bytebits_to_byte(bits+startIdx+56, 8); + if ( checkchksum != crc ) return -5; + return (int)startIdx; +} + static uint64_t getJablontronCardId( uint64_t rawcode ){ uint64_t id = 0; uint8_t bytes[] = {0,0,0,0,0}; @@ -79,7 +98,7 @@ int CmdJablotronDemod(const char *Cmd) { return 0; } size_t size = DemodBufferLen; - int ans = JablotronDemod(DemodBuffer, &size); + int ans = detectJablotron(DemodBuffer, &size); if (ans < 0){ if (g_debugMode){ if (ans == -1) @@ -96,8 +115,8 @@ int CmdJablotronDemod(const char *Cmd) { return 0; } - setDemodBuf(DemodBuffer+ans, 64, 0); - setGrid_Clock(64); + setDemodBuf(DemodBuffer, 64, ans); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); @@ -106,7 +125,7 @@ int CmdJablotronDemod(const char *Cmd) { uint64_t rawid = bytebits_to_byte(DemodBuffer+16, 40); uint64_t id = getJablontronCardId(rawid); - PrintAndLog("Jablotron Tag Found: Card ID %u :: Raw: %08X%08X", id, raw1 ,raw2); + PrintAndLog("Jablotron Tag Found: Card ID: %"PRIx64" :: Raw: %08X%08X", id, raw1, raw2); uint8_t chksum = raw2 & 0xFF; PrintAndLog("Checksum: %02X [%s]", @@ -125,8 +144,7 @@ int CmdJablotronDemod(const char *Cmd) { } int CmdJablotronRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("10000", true); + lf_read(true, 10000); return CmdJablotronDemod(Cmd); } @@ -161,7 +179,6 @@ int CmdJablotronClone(const char *Cmd) { return 1; } - // blocks[1] = bytebits_to_byte(bs,32); blocks[2] = bytebits_to_byte(bs+32,32); @@ -219,7 +236,8 @@ int CmdJablotronSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"read", CmdJablotronRead, 0, "Attempt to read and extract tag data"}, + {"demod", CmdJablotronDemod, 1, "Demodulate an Jablotron tag from the GraphBuffer"}, + {"read", CmdJablotronRead, 0, "Attempt to read and extract tag data from the antenna"}, {"clone", CmdJablotronClone, 0, "clone jablotron tag"}, {"sim", CmdJablotronSim, 0, "simulate jablotron tag"}, {NULL, NULL, 0, NULL} diff --git a/client/cmdlfjablotron.h b/client/cmdlfjablotron.h index d5bfd0265..127157e67 100644 --- a/client/cmdlfjablotron.h +++ b/client/cmdlfjablotron.h @@ -21,17 +21,21 @@ #include "cmdlf.h" #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // parityTest -int CmdLFJablotron(const char *Cmd); -int CmdJablotronClone(const char *Cmd); -int CmdJablotronSim(const char *Cmd); -int CmdJablotronRead(const char *Cmd); -int CmdJablotronDemod(const char *Cmd); -int getJablotronBits(uint64_t fullcode, uint8_t *bits); +extern int CmdLFJablotron(const char *Cmd); + +extern int CmdJablotronDemod(const char *Cmd); +extern int CmdJablotronRead(const char *Cmd); +extern int CmdJablotronClone(const char *Cmd); +extern int CmdJablotronSim(const char *Cmd); + +extern int detectJablotron(uint8_t *bits, size_t *size); +extern int getJablotronBits(uint64_t fullcode, uint8_t *bits); + +//extern int usage_lf_jablotron_demod(void); +//extern int usage_lf_jablotron_read(void); +extern int usage_lf_jablotron_clone(void); +extern int usage_lf_jablotron_sim(void); -int usage_lf_jablotron_clone(void); -int usage_lf_jablotron_sim(void); -int usage_lf_jablotron_read(void); -int usage_lf_jablotron_demod(void); #endif diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index f732659f9..71552650a 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -6,8 +6,7 @@ //----------------------------------------------------------------------------- // Low frequency NEDAP tag commands //----------------------------------------------------------------------------- -#include -#include + #include "cmdlfnedap.h" static int CmdHelp(const char *Cmd); @@ -37,6 +36,20 @@ int usage_lf_nedap_sim(void) { return 0; } +// find nedap preamble in already demoded data +int detectNedap(uint8_t *dest, size_t *size) { + //make sure buffer has data + if (*size < 128) return -3; + + size_t startIdx = 0; + //uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,0,0,0,1}; + uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,0}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -4; //preamble not found + return (int) startIdx; +} + + int GetNedapBits(uint32_t cn, uint8_t *nedapBits) { uint8_t pre[128]; @@ -89,7 +102,7 @@ int CmdLFNedapDemod(const char *Cmd) { return 0; } size_t size = DemodBufferLen; - int idx = NedapDemod(DemodBuffer, &size); + int idx = detectNedap(DemodBuffer, &size); if (idx < 0){ if (g_debugMode){ // if (idx == -5) @@ -135,8 +148,8 @@ int CmdLFNedapDemod(const char *Cmd) { raw[1] = bytebits_to_byte(DemodBuffer+idx+64,32); raw[2] = bytebits_to_byte(DemodBuffer+idx+32,32); raw[3] = bytebits_to_byte(DemodBuffer+idx,32); - setDemodBuf(DemodBuffer,128,idx); - setGrid_Clock(64); + setDemodBuf(DemodBuffer, 128, idx); + setClockGrid(g_DemodClock, g_DemodStartIdx + (idx*g_DemodClock)); uint8_t firstParity = GetParity( DemodBuffer, EVEN, 63); if ( firstParity != DemodBuffer[63] ) { @@ -202,9 +215,8 @@ lf t55xx wr b 4 d 4c0003ff */ int CmdLFNedapRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("12000", true); - return CmdLFNedapDemod(""); + lf_read(true, 12000); + return CmdLFNedapDemod(Cmd); } /* int CmdLFNedapClone(const char *Cmd) { @@ -345,9 +357,9 @@ int CmdLFNedapChk(const char *Cmd){ return 0; } - static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, + {"demod", CmdLFNedapDemod,0, "Demodulate an Nedap tag from the GraphBuffer"}, {"read", CmdLFNedapRead, 0, "Attempt to read and extract tag data"}, // {"clone", CmdLFNedapClone,0, " clone nedap tag"}, {"sim", CmdLFNedapSim, 0, " simulate nedap tag"}, diff --git a/client/cmdlfnedap.h b/client/cmdlfnedap.h index b39ebd742..fd10c5e76 100644 --- a/client/cmdlfnedap.h +++ b/client/cmdlfnedap.h @@ -4,10 +4,12 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency T55xx commands +// Low frequency NEDAP tag commands //----------------------------------------------------------------------------- #ifndef CMDLFNEDAP_H__ #define CMDLFNEDAP_H__ +#include +#include #include "proxmark3.h" #include "ui.h" #include "util.h" @@ -20,15 +22,17 @@ #include "lfdemod.h" // parityTest #include "crc.h" -int CmdLFNedap(const char *Cmd); -int CmdLFNedapDemod(const char *Cmd); -int CmdLFNedapRead(const char *Cmd); -//int CmdLFNedapClone(const char *Cmd); -int CmdLFNedapSim(const char *Cmd); -int CmdLFNedapChk(const char *Cmd); +extern int CmdLFNedap(const char *Cmd); +extern int CmdLFNedapDemod(const char *Cmd); +extern int CmdLFNedapRead(const char *Cmd); +//extern int CmdLFNedapClone(const char *Cmd); +extern int CmdLFNedapSim(const char *Cmd); +extern int CmdLFNedapChk(const char *Cmd); -int usage_lf_nedap_read(void); -//int usage_lf_nedap_clone(void); -int usage_lf_nedap_sim(void); +extern int detectNedap(uint8_t *dest, size_t *size); + +extern int usage_lf_nedap_read(void); +//extern int usage_lf_nedap_clone(void); +extern int usage_lf_nedap_sim(void); #endif diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 0097d1758..70a391911 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -7,50 +7,67 @@ // Low frequency Honeywell NexWatch tag commands // PSK1 RF/16, RF/2, 128 bits long (known) //----------------------------------------------------------------------------- -#include -#include -#include -#include + #include "cmdlfnexwatch.h" -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "lfdemod.h" static int CmdHelp(const char *Cmd); -int CmdPSKNexWatch(const char *Cmd) -{ - if (!PSKDemod("", false)) return 0; - - uint8_t preamble[28] = {0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - size_t startIdx = 0, size = DemodBufferLen; +int detectNexWatch(uint8_t *dest, size_t *size, bool *invert) { + uint8_t preamble[28] = {0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t preamble_i[28] = {1,1,1,1,1,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; // sanity check. - if ( size < sizeof(preamble) + 100) return 0; + if ( *size < sizeof(preamble) + 100) return -1; - bool invert = false; - if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx)){ + size_t startIdx = 0; + + if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx)){ // if didn't find preamble try again inverting - if (!PSKDemod("1", false)) return 0; - - size = DemodBufferLen; - if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx)) return 0; - invert = true; + if (!preambleSearch(DemodBuffer, preamble_i, sizeof(preamble_i), size, &startIdx)) return -4; + *invert ^= 1; + } + + // size tests? + return (int) startIdx; +} + +int CmdNexWatchDemod(const char *Cmd) { + + if (!PSKDemod("", false)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - NexWatch can't demod signal"); + return 0; + } + bool invert = false; + size_t size = DemodBufferLen; + int idx = detectNexWatch(DemodBuffer, &size, &invert); + if (idx <= 0){ + if (g_debugMode){ + if (idx == -1) + PrintAndLog("DEBUG: Error - NexWatch not enough samples"); + // else if (idx == -2) + // PrintAndLog("DEBUG: Error - NexWatch only noise found"); + // else if (idx == -3) + // PrintAndLog("DEBUG: Error - NexWatch problem during PSK demod"); + else if (idx == -4) + PrintAndLog("DEBUG: Error - NexWatch preamble not found"); + // else if (idx == -5) + // PrintAndLog("DEBUG: Error - NexWatch size not correct: %d", size); + else + PrintAndLog("DEBUG: Error - NexWatch error %d",idx); + } + return 0; } - if (size != 128) return 0; - setDemodBuf(DemodBuffer, size, startIdx+4); - //setClockGrid(g_DemodClock, g_DemodStartIdx + ((startIdx+4)*g_DemodClock)); - startIdx = 8+32; // 8 = preamble, 32 = reserved bits (always 0) + + setDemodBuf(DemodBuffer, size, idx+4); + setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx+4)*g_DemodClock)); + + idx = 8+32; // 8 = preamble, 32 = reserved bits (always 0) + //get ID uint32_t ID = 0; - for (uint8_t wordIdx=0; wordIdx<4; wordIdx++){ - for (uint8_t idx=0; idx<8; idx++){ - ID = (ID << 1) | DemodBuffer[startIdx+wordIdx+(idx*4)]; + for (uint8_t k = 0; k < 4; k++){ + for (uint8_t m = 0; m < 8; m++){ + ID = (ID << 1) | DemodBuffer[m + k + (m*4)]; } } //parity check (TBD) @@ -60,9 +77,9 @@ int CmdPSKNexWatch(const char *Cmd) //output PrintAndLog("NexWatch ID: %d", ID); if (invert){ - PrintAndLog("DEBUG: Error - NexWatch had to Invert - probably NexKey"); - for (uint8_t idx=0; idx +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" // preamblesearch +#include "cmdlf.h" +#include "lfdemod.h" + +extern int CmdLFNEXWATCH(const char *Cmd); +extern int CmdNexWatchDemod(const char *Cmd); extern int CmdNexWatchRead(const char *Cmd); + +extern int detectNexWatch(uint8_t *dest, size_t *size, bool *invert); #endif diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index ed38e98b3..b283690af 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -72,6 +72,18 @@ int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits) { return 1; } +// by iceman +// find Noralsy preamble in already demoded data +int detectNoralsy(uint8_t *dest, size_t *size) { + if (*size < 96) return -1; //make sure buffer has data + size_t startIdx = 0; + uint8_t preamble[] = {1,0,1,1,1,0,1,1,0,0,0,0}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -2; //preamble not found + if (*size != 96) return -3; //wrong demoded size + //return start position + return (int)startIdx; +} /* * * 2520116 | BB0214FF2529900116360000 | 10111011 00000011 00010100 11111111 00100101 00101001 10010000 00000001 00010110 00110110 00000000 00000000 @@ -97,7 +109,7 @@ int CmdNoralsyDemod(const char *Cmd) { if (!st) return 0; size_t size = DemodBufferLen; - int ans = NoralsyDemod_AM(DemodBuffer, &size); + int ans = detectNoralsy(DemodBuffer, &size); if (ans < 0){ if (g_debugMode){ if (ans == -1) @@ -112,7 +124,7 @@ int CmdNoralsyDemod(const char *Cmd) { return 0; } setDemodBuf(DemodBuffer, 96, ans); - setGrid_Clock(32); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); @@ -136,21 +148,24 @@ int CmdNoralsyDemod(const char *Cmd) { chk2 = bytebits_to_byte(DemodBuffer+76, 4); // test checksums if ( chk1 != calc1 ) { - printf("checksum 1 failed %x - %x\n", chk1, calc1); + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: checksum 1 failed %x - %x\n", chk1, calc1); return 0; } if ( chk2 != calc2 ) { - printf("checksum 2 failed %x - %x\n", chk2, calc2); + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: checksum 2 failed %x - %x\n", chk2, calc2); return 0; } PrintAndLog("Noralsy Tag Found: Card ID %u, Year: %u Raw: %08X%08X%08X", cardid, year, raw1 ,raw2, raw3); + if (raw1 != 0xBB0214FF) { + PrintAndLog("Unknown bits set in first block! Expected 0xBB0214FF, Found: 0x%08X", raw1); + PrintAndLog("Please post this output in forum to further research on this format"); + } return 1; } int CmdNoralsyRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("8000",true); + lf_read(true, 8000); return CmdNoralsyDemod(Cmd); } @@ -246,9 +261,10 @@ int CmdNoralsySim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"read", CmdNoralsyRead, 0, "Attempt to read and extract tag data"}, - {"clone", CmdNoralsyClone,0, "clone Noralsy tag"}, - {"sim", CmdNoralsySim, 0, "simulate Noralsy tag"}, + {"demod", CmdNoralsyDemod,1, "Demodulate an Noralsy tag from the GraphBuffer"}, + {"read", CmdNoralsyRead, 0, "Attempt to read and extract tag data from the antenna"}, + {"sim", CmdNoralsySim, 0, "Noralsy tag simulator"}, + {"clone", CmdNoralsyClone,0, "clone Noralsy to T55x7"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfnoralsy.h b/client/cmdlfnoralsy.h index a1ddc6e3b..63065a0d6 100644 --- a/client/cmdlfnoralsy.h +++ b/client/cmdlfnoralsy.h @@ -23,16 +23,16 @@ #include "lfdemod.h" // parityTest extern int CmdLFNoralsy(const char *Cmd); +extern int CmdNoralsyDemod(const char *Cmd); +extern int CmdNoralsyRead(const char *Cmd); extern int CmdNoralsyClone(const char *Cmd); extern int CmdNoralsySim(const char *Cmd); -extern int CmdNoralsyRead(const char *Cmd); -extern int CmdNoralsyDemod(const char *Cmd); int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits); -int usage_lf_noralsy_clone(void); -int usage_lf_noralsy_sim(void); -int usage_lf_noralsy_read(void); -int usage_lf_noralsy_demod(void); +extern int usage_lf_noralsy_clone(void); +extern int usage_lf_noralsy_sim(void); +//extern int usage_lf_noralsy_read(void); +//extern int usage_lf_noralsy_demod(void); #endif diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index f0b6c0626..a120bd36d 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -8,23 +8,12 @@ // NRZ, RF/32, 128 bits long (unknown cs) //----------------------------------------------------------------------------- #include "cmdlfpac.h" -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "lfdemod.h" // preamble test static int CmdHelp(const char *Cmd); // by marshmellow // find PAC preamble in already demoded data -int PacFind(uint8_t *dest, size_t *size) { +int detectPac(uint8_t *dest, size_t *size) { if (*size < 128) return -1; //make sure buffer has data size_t startIdx = 0; uint8_t preamble[] = {1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,1,0}; @@ -44,7 +33,7 @@ int CmdPacDemod(const char *Cmd) { return 0; } size_t size = DemodBufferLen; - int ans = PacFind(DemodBuffer, &size); + int ans = detectPac(DemodBuffer, &size); if (ans < 0) { if (g_debugMode) { if (ans == -1) @@ -59,7 +48,7 @@ int CmdPacDemod(const char *Cmd) { return 0; } setDemodBuf(DemodBuffer, 128, ans); -// setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer , 32); @@ -77,15 +66,13 @@ int CmdPacDemod(const char *Cmd) { } int CmdPacRead(const char *Cmd) { - //lf_read(true, 4096*2 + 20); - CmdLFRead("s"); - getSamples("8192",true); + lf_read(true, 4096*2 + 20); return CmdPacDemod(Cmd); } static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdPacDemod,1, "Attempt to read and extract tag data from the GraphBuffer"}, + {"demod", CmdPacDemod,1, "Demodulate an PAC tag from the GraphBuffer"}, {"read", CmdPacRead, 0, "Attempt to read and extract tag data from the antenna"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfpac.h b/client/cmdlfpac.h index 99b35a530..88e97a42e 100644 --- a/client/cmdlfpac.h +++ b/client/cmdlfpac.h @@ -4,14 +4,27 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency Securakey tag commands +// Low frequency Stanley/PAC tag commands //----------------------------------------------------------------------------- #ifndef CMDLFPAC_H__ #define CMDLFPAC_H__ +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "lfdemod.h" // preamble test + extern int CmdLFPac(const char *Cmd); extern int CmdPacRead(const char *Cmd); extern int CmdPacDemod(const char *Cmd); +extern int detectPac(uint8_t *dest, size_t *size); #endif diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c new file mode 100644 index 000000000..a11d230ea --- /dev/null +++ b/client/cmdlfparadox.c @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency Paradox tag commands +// FSK2a, rf/50, 96 bits (completely known) +//----------------------------------------------------------------------------- +#include +#include +#include +#include "cmdlfparadox.h" +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" +static int CmdHelp(const char *Cmd); + + +// loop to get raw paradox waveform then FSK demodulate the TAG ID from it +int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) { + if (justNoise(dest, *size)) return -1; + + size_t numStart = 0, startIdx = 0; + // FSK demodulator + *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //fsk2a + if (*size < 96) return -2; + + // 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 + uint8_t preamble[] = {0,0,0,0,1,1,1,1}; + if (preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -3; //preamble not found + + numStart = startIdx + sizeof(preamble); + // final loop, go over previously decoded FSK data and manchester decode into usable tag ID + for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){ + if (dest[idx] == dest[idx+1]) + return -4; //not manchester data + *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)|1; + else // 0 1 + *lo=(*lo<<1)|0; + } + return (int)startIdx; +} + +//by marshmellow +//Paradox Prox demod - FSK RF/50 with preamble of 00001111 (then manchester encoded) +//print full Paradox Prox ID and some bit format details if found +int CmdParadoxDemod(const char *Cmd) { + //raw fsk demod no manchester decoding no start bit finding just get binary from wave + uint8_t bits[MAX_GRAPH_TRACE_LEN]={0}; + size_t BitLen = getFromGraphBuf(bits); + if (BitLen==0) return 0; + + uint32_t hi2=0, hi=0, lo=0; + int waveIdx=0; + //get binary from fsk wave + int idx = detectParadox(bits, &BitLen, &hi2, &hi, &lo, &waveIdx); + if (idx < 0){ + if (g_debugMode){ + if (idx == -1){ + PrintAndLog("DEBUG: Error - Paradox just noise detected"); + } else if (idx == -2) { + PrintAndLog("DEBUG: Error - Paradox error demoding fsk"); + } else if (idx == -3) { + PrintAndLog("DEBUG: Error - Paradox preamble not found"); + } else if (idx == -4) { + PrintAndLog("DEBUG: Error - Paradox error in Manchester data"); + } else { + PrintAndLog("DEBUG: Error - Paradox error demoding fsk %d", idx); + } + } + return 0; + } + if (hi2==0 && hi==0 && lo==0){ + if (g_debugMode) PrintAndLog("DEBUG: Error - Paradox no value found"); + return 0; + } + uint32_t fc = ((hi & 0x3)<<6) | (lo>>26); + uint32_t cardnum = (lo>>10) & 0xFFFF; + uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32); + uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32); + uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32); + + PrintAndLog("Paradox TAG ID: %x%08x - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x", + hi >> 10, + (hi & 0x3)<<26 | (lo>>10), + fc, cardnum, + (lo>>2) & 0xFF, + rawHi2, + rawHi, + rawLo + ); + + setDemodBuf(bits, BitLen, idx); + setClockGrid(50, waveIdx + (idx*50)); + + if (g_debugMode){ + PrintAndLog("DEBUG: Paradox idx: %d, len: %d, Printing Demod Buffer:", idx, BitLen); + printDemodBuff(); + } + return 1; +} +//by marshmellow +//see ASKDemod for what args are accepted +int CmdParadoxRead(const char *Cmd) { + lf_read(true, 10000); + return CmdParadoxDemod(Cmd); +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdParadoxDemod, 1, "Demodulate a Paradox FSK tag from the GraphBuffer"}, + {"read", CmdParadoxRead, 0, "Attempt to read and Extract tag data from the antenna"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFParadox(const char *Cmd) { + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfparadox.h b/client/cmdlfparadox.h new file mode 100644 index 000000000..a136ba54f --- /dev/null +++ b/client/cmdlfparadox.h @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency Paradox tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFPARADOX_H__ +#define CMDLFPARADOX_H__ +extern int CmdLFParadox(const char *Cmd); +extern int CmdParadoxDemod(const char *Cmd); +extern int CmdParadoxRead(const char *Cmd); + +extern int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); +#endif diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index 5cc576fe5..e7b63c4b3 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -12,6 +12,7 @@ #include #include "proxmark3.h" #include "ui.h" +#include "util.h" #include "graph.h" #include "cmdparser.h" #include "cmddata.h" @@ -156,8 +157,7 @@ int CmdLFPCF7931Write(const char *Cmd){ return 0; } -static command_t CommandTable[] = -{ +static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"read", CmdLFPCF7931Read, 0, "Read content of a PCF7931 transponder"}, {"write", CmdLFPCF7931Write, 0, "Write data on a PCF7931 transponder."}, diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 79192ef7b..6f0e7c394 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -6,8 +6,7 @@ //----------------------------------------------------------------------------- // Low frequency Presco tag commands //----------------------------------------------------------------------------- -#include -#include + #include "cmdlfpresco.h" static int CmdHelp(const char *Cmd); @@ -37,6 +36,18 @@ int usage_lf_presco_sim(void) { return 0; } +// find presco preamble 0x10D in already demoded data +int detectPresco(uint8_t *dest, size_t *size) { + if (*size < 128*2) return -1; //make sure buffer has data + size_t startIdx = 0; + uint8_t preamble[] = {0,0,0,1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -2; //preamble not found + if (*size != 128) return -3; //wrong demoded size + //return start position + return (int)startIdx; +} + // convert base 12 ID to sitecode & usercode & 8 bit other unknown code int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) { @@ -57,12 +68,12 @@ int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode *fullcode = param_get32ex(Cmd, cmdp+1, 0, 16); cmdp+=2; break; - case 'P': - case 'p': + case 'D': + case 'd': //param get string int param_getstr(const char *line, int paramnum, char * str) stringlen = param_getstr(Cmd, cmdp+1, id); if (stringlen < 2) return -1; - cmdp+=2; + cmdp += 2; break; case 'Q': case 'q': @@ -117,8 +128,7 @@ int CmdPrescoDemod(const char *Cmd) { return 0; } size_t size = DemodBufferLen; - //call lfdemod.c demod for Presco - int ans = PrescoDemod(DemodBuffer, &size); + int ans = detectPresco(DemodBuffer, &size); if (ans < 0) { if (g_debugMode){ if (ans == -1) @@ -133,7 +143,7 @@ int CmdPrescoDemod(const char *Cmd) { return 0; } setDemodBuf(DemodBuffer, 128, ans); - setGrid_Clock(32); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); @@ -155,12 +165,7 @@ int CmdPrescoDemod(const char *Cmd) { //see ASKDemod for what args are accepted int CmdPrescoRead(const char *Cmd) { // Presco Number: 123456789 --> Sitecode 30 | usercode 8665 - - // read lf silently - CmdLFRead("s"); - // get samples silently - getSamples("12000", true); - // demod and output Presco ID + lf_read(true, 12000); return CmdPrescoDemod(Cmd); } diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h index 14b8d2135..563f0ac98 100644 --- a/client/cmdlfpresco.h +++ b/client/cmdlfpresco.h @@ -8,6 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFPRESCO_H__ #define CMDLFPRESCO_H__ +#include +#include #include "proxmark3.h" #include "ui.h" #include "util.h" @@ -20,14 +22,15 @@ #include "lfdemod.h" // parityTest extern int CmdLFPresco(const char *Cmd); -extern int CmdPrescoClone(const char *Cmd); -extern int CmdPrescoSim(const char *Cmd); extern int CmdPrescoRead(const char *Cmd); extern int CmdPrescoDemod(const char *Cmd); +extern int CmdPrescoClone(const char *Cmd); +extern int CmdPrescoSim(const char *Cmd); +extern int detectPresco(uint8_t *dest, size_t *size); int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5); -int usage_lf_presco_clone(void); -int usage_lf_presco_sim(void); +extern int usage_lf_presco_clone(void); +extern int usage_lf_presco_sim(void); #endif diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index cc41455d3..0896e20e8 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -7,9 +7,8 @@ // Low frequency Farpoint / Pyramid tag commands // FSK2a, rf/50, 128 bits (complete) //----------------------------------------------------------------------------- -#include -#include #include "cmdlfpyramid.h" + static int CmdHelp(const char *Cmd); int usage_lf_pyramid_clone(void){ @@ -42,6 +41,26 @@ int usage_lf_pyramid_sim(void) { return 0; } +// by marshmellow +// FSK Demod then try to locate a Farpointe Data (pyramid) ID +int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx) { + //make sure buffer has data + if (*size < 128*50) return -5; + + //test samples are not just noise + if (justNoise(dest, *size)) return -1; + + // FSK demodulator + *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); // fsk2a RF/50 + if (*size < 128) return -2; //did we get a good demod? + size_t startIdx = 0; + uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -4; //preamble not found + if (*size != 128) return -3; + return (int)startIdx; +} + // Works for 26bits. int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) { @@ -73,10 +92,155 @@ int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) { return 1; } +//by marshmellow +//Pyramid Prox demod - FSK RF/50 with preamble of 0000000000000001 (always a 128 bit data stream) +//print full Farpointe Data/Pyramid Prox ID and some bit format details if found +int CmdPyramidDemod(const char *Cmd) { + //raw fsk demod no manchester decoding no start bit finding just get binary from wave + uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; + size_t size = getFromGraphBuf(BitStream); + if (size==0) return 0; + + int waveIdx=0; + //get binary from fsk wave + int idx = detectPyramid(BitStream, &size, &waveIdx); + if (idx < 0){ + if (g_debugMode){ + if (idx == -5) + PrintAndLog("DEBUG: Error - Pyramid: not enough samples"); + else if (idx == -1) + PrintAndLog("DEBUG: Error - Pyramid: only noise found"); + else if (idx == -2) + PrintAndLog("DEBUG: Error - Pyramid: problem during FSK demod"); + else if (idx == -3) + PrintAndLog("DEBUG: Error - Pyramid: size not correct: %d", size); + else if (idx == -4) + PrintAndLog("DEBUG: Error - Pyramid: preamble not found"); + else + PrintAndLog("DEBUG: Error - Pyramid: idx: %d",idx); + } + return 0; + } + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 0123456 7 8901234 5 6789012 3 4567890 1 2345678 9 0123456 7 8901234 5 6789012 3 + // ----------------------------------------------------------------------------- + // 0000000 0 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 0000000 1 + // premable xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o xxxxxxx o + + // 64 70 80 90 100 110 120 + // | | | | | | | + // 4567890 1 2345678 9 0123456 7 8901234 5 6789012 3 4567890 1 2345678 9 0123456 7 + // ----------------------------------------------------------------------------- + // 0000000 1 0000000 1 0000000 1 0110111 0 0011000 1 0000001 0 0001100 1 1001010 0 + // xxxxxxx o xxxxxxx o xxxxxxx o xswffff o ffffccc o ccccccc o ccccccw o ppppppp o + // |---115---||---------71---------| + // s = format start bit, o = odd parity of last 7 bits + // f = facility code, c = card number + // w = wiegand parity, x = extra space for other formats + // p = CRC8maxim checksum + // (26 bit format shown) + + //get bytes for checksum calc + uint8_t checksum = bytebits_to_byte(BitStream + idx + 120, 8); + uint8_t csBuff[14] = {0x00}; + for (uint8_t i = 0; i < 13; i++){ + csBuff[i] = bytebits_to_byte(BitStream + idx + 16 + (i*8), 8); + } + //check checksum calc + //checksum calc thanks to ICEMAN!! + uint32_t checkCS = CRC8Maxim(csBuff, 13); + + //get raw ID before removing parities + uint32_t rawLo = bytebits_to_byte(BitStream+idx+96, 32); + uint32_t rawHi = bytebits_to_byte(BitStream+idx+64, 32); + uint32_t rawHi2 = bytebits_to_byte(BitStream+idx+32, 32); + uint32_t rawHi3 = bytebits_to_byte(BitStream+idx, 32); + setDemodBuf(BitStream, 128, idx); + setClockGrid(50, waveIdx + (idx*50)); + + size = removeParity(BitStream, idx+8, 8, 1, 120); + if (size != 105){ + if (g_debugMode) { + if ( size == 0) + PrintAndLog("DEBUG: Error - Pyramid: parity check failed - IDX: %d, hi3: %08X", idx, rawHi3); + else + PrintAndLog("DEBUG: Error - Pyramid: at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %08X", size, idx, rawHi3); + } + return 0; + } + + // ok valid card found! + + // Index map + // 0 10 20 30 40 50 60 70 + // | | | | | | | | + // 01234567890123456789012345678901234567890123456789012345678901234567890 + // ----------------------------------------------------------------------- + // 00000000000000000000000000000000000000000000000000000000000000000000000 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + // 71 80 90 100 + // | | | | + // 1 2 34567890 1234567890123456 7 8901234 + // --------------------------------------- + // 1 1 01110011 0000000001000110 0 1001010 + // s w ffffffff cccccccccccccccc w ppppppp + // |--115-| |------71------| + // s = format start bit, o = odd parity of last 7 bits + // f = facility code, c = card number + // w = wiegand parity, x = extra space for other formats + // p = CRC8-Maxim checksum + // (26 bit format shown) + + //find start bit to get fmtLen + int j; + for (j=0; j < size; ++j){ + if(BitStream[j]) break; + } + + uint8_t fmtLen = size-j-8; + uint32_t fc = 0; + uint32_t cardnum = 0; + uint32_t code1 = 0; + + if ( fmtLen == 26 ){ + fc = bytebits_to_byte(BitStream+73, 8); + cardnum = bytebits_to_byte(BitStream+81, 16); + code1 = bytebits_to_byte(BitStream+72,fmtLen); + PrintAndLog("Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi3, rawHi2, rawHi, rawLo); + } else if (fmtLen == 45) { + fmtLen = 42; //end = 10 bits not 7 like 26 bit fmt + fc = bytebits_to_byte(BitStream+53, 10); + cardnum = bytebits_to_byte(BitStream+63, 32); + PrintAndLog("Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, rawHi3, rawHi2, rawHi, rawLo); + } else { + cardnum = bytebits_to_byte(BitStream+81, 16); + if (fmtLen>32){ + //code1 = bytebits_to_byte(BitStream+(size-fmtLen),fmtLen-32); + //code2 = bytebits_to_byte(BitStream+(size-32),32); + PrintAndLog("Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); + } else{ + //code1 = bytebits_to_byte(BitStream+(size-fmtLen),fmtLen); + PrintAndLog("Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); + } + } + if (checksum == checkCS) + PrintAndLog("Checksum %02x passed", checksum); + else + PrintAndLog("Checksum %02x failed - should have been %02x", checksum, checkCS); + + if (g_debugMode){ + PrintAndLog("DEBUG: Pyramid: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128); + printDemodBuff(); + } + return 1; +} + int CmdPyramidRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("12000", true); - return CmdFSKdemodPyramid(""); + lf_read(true, 15000); + return CmdPyramidDemod(Cmd); } int CmdPyramidClone(const char *Cmd) { @@ -171,9 +335,10 @@ int CmdPyramidSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"read", CmdPyramidRead, 0, "Attempt to read and extract tag data"}, - {"clone", CmdPyramidClone, 0, " clone pyramid tag"}, - {"sim", CmdPyramidSim, 0, " simulate pyramid tag"}, + {"demod", CmdPyramidDemod,0, "Demodulate a Pyramid FSK tag from the GraphBuffer"}, + {"read", CmdPyramidRead, 0, "Attempt to read and extract tag data"}, + {"clone", CmdPyramidClone,0, " clone pyramid tag"}, + {"sim", CmdPyramidSim, 0, " simulate pyramid tag"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h index 2ddb55d57..425914bbb 100644 --- a/client/cmdlfpyramid.h +++ b/client/cmdlfpyramid.h @@ -8,6 +8,8 @@ //----------------------------------------------------------------------------- #ifndef CMDLFPYRAMID_H__ #define CMDLFPYRAMID_H__ +#include +#include #include "proxmark3.h" #include "ui.h" #include "util.h" @@ -20,11 +22,15 @@ #include "lfdemod.h" // parityTest #include "crc.h" -int CmdLFPyramid(const char *Cmd); -int CmdPyramidClone(const char *Cmd); -int CmdPyramidSim(const char *Cmd); +extern int CmdLFPyramid(const char *Cmd); +extern int CmdPyramidDemod(const char *Cmd); +extern int CmdPyramidRead(const char *Cmd); +extern int CmdPyramidClone(const char *Cmd); +extern int CmdPyramidSim(const char *Cmd); -int usage_lf_pyramid_clone(void); -int usage_lf_pyramid_sim(void); +extern int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx); + +extern int usage_lf_pyramid_clone(void); +extern int usage_lf_pyramid_sim(void); #endif diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 084eb6bce..5f4ccbe4d 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -8,26 +8,12 @@ // ASK/Manchester, RF/40, 96 bits long (unknown cs) //----------------------------------------------------------------------------- #include "cmdlfsecurakey.h" -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // preamble test -#include "parity.h" // for wiegand parity test static int CmdHelp(const char *Cmd); // by marshmellow // find Securakey preamble in already demoded data -int SecurakeyFind(uint8_t *dest, size_t *size) { +int detectSecurakey(uint8_t *dest, size_t *size) { if (*size < 96) return -1; //make sure buffer has data size_t startIdx = 0; uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1,0,0,1}; @@ -49,7 +35,7 @@ int CmdSecurakeyDemod(const char *Cmd) { } if (st) return 0; size_t size = DemodBufferLen; - int ans = SecurakeyFind(DemodBuffer, &size); + int ans = detectSecurakey(DemodBuffer, &size); if (ans < 0) { if (g_debugMode) { if (ans == -1) @@ -64,7 +50,7 @@ int CmdSecurakeyDemod(const char *Cmd) { return 0; } setDemodBuf(DemodBuffer, 96, ans); - //setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer , 32); @@ -123,15 +109,13 @@ int CmdSecurakeyDemod(const char *Cmd) { } int CmdSecurakeyRead(const char *Cmd) { - //lf_read(true, 8000); - CmdLFRead("s"); - getSamples("8000",true); + lf_read(true, 8000); return CmdSecurakeyDemod(Cmd); } static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdSecurakeyDemod,1, "Attempt to read and extract tag data from the GraphBuffer"}, + {"demod", CmdSecurakeyDemod,1, "Demodulate an Securakey tag from the GraphBuffer"}, {"read", CmdSecurakeyRead, 0, "Attempt to read and extract tag data from the antenna"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfsecurakey.h b/client/cmdlfsecurakey.h index f3c0cf881..5155c2ada 100644 --- a/client/cmdlfsecurakey.h +++ b/client/cmdlfsecurakey.h @@ -9,9 +9,24 @@ #ifndef CMDLFSECURAKEY_H__ #define CMDLFSECURAKEY_H__ +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // preamble test +#include "parity.h" // for wiegand parity test + extern int CmdLFSecurakey(const char *Cmd); -extern int CmdSecurakeyClone(const char *Cmd); -extern int CmdSecurakeySim(const char *Cmd); +//extern int CmdSecurakeyClone(const char *Cmd); +//extern int CmdSecurakeySim(const char *Cmd); extern int CmdSecurakeyRead(const char *Cmd); extern int CmdSecurakeyDemod(const char *Cmd); diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 997fdad62..510c85518 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -55,12 +55,13 @@ int usage_t55xx_read(){ return 0; } int usage_t55xx_write(){ - PrintAndLog("Usage: lf t55xx write [b ] [d ] [p ] [1]"); + PrintAndLog("Usage: lf t55xx write [b ] [d ] [p ] [1] [t]"); PrintAndLog("Options:"); PrintAndLog(" b - block number to write. Between 0-7"); PrintAndLog(" d - 4 bytes of data to write (8 hex characters)"); PrintAndLog(" p - OPTIONAL password 4bytes (8 hex characters)"); PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0"); + PrintAndLog(" t - OPTIONAL test mode write - ****DANGER****"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); @@ -115,6 +116,20 @@ int usage_t55xx_detect(){ PrintAndLog(""); return 0; } +int usage_t55xx_detectP1(){ + PrintAndLog("Command: Detect Page 1 of a t55xx chip"); + PrintAndLog("Usage: lf t55xx p1detect [1] [p ]"); + PrintAndLog("Options:"); + PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog(" p - OPTIONAL password (8 hex characters)"); + PrintAndLog(""); + PrintAndLog("Examples:"); + PrintAndLog(" lf t55xx p1detect"); + PrintAndLog(" lf t55xx p1detect 1"); + PrintAndLog(" lf t55xx p1detect p 11223344"); + PrintAndLog(""); + return 0; +} int usage_t55xx_wakup(){ PrintAndLog("Usage: lf t55xx wakeup [h] p "); PrintAndLog("This commands send the Answer-On-Request command and leaves the readerfield ON afterwards."); @@ -395,23 +410,23 @@ bool DecodeT55xxBlock(){ break; case DEMOD_PSK1: // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - save_restoreGB(1); + save_restoreGB(GRAPH_SAVE); CmdLtrim("160"); snprintf(cmdStr, sizeof(buf),"%d %d 6", bitRate[config.bitrate], config.inverted ); ans = PSKDemod(cmdStr, false); //undo trim samples - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); break; case DEMOD_PSK2: //inverted won't affect this case DEMOD_PSK3: //not fully implemented // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - save_restoreGB(1); + save_restoreGB(GRAPH_SAVE); CmdLtrim("160"); snprintf(cmdStr, sizeof(buf),"%d 0 6", bitRate[config.bitrate] ); ans = PSKDemod(cmdStr, false); psk1TOpsk2(DemodBuffer, DemodBufferLen); //undo trim samples - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); break; case DEMOD_NRZ: snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted ); @@ -494,10 +509,10 @@ bool tryDetectModulation(){ uint8_t hits = 0; t55xx_conf_block_t tests[15]; int bitRate=0; - uint8_t fc1 = 0, fc2 = 0, clk=0; - - if (GetFskClock("", false, false)){ - fskClocks(&fc1, &fc2, &clk, false); + uint8_t fc1 = 0, fc2 = 0, ans = 0; + int clk = 0, firstClockEdge = 0; + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, false, &firstClockEdge); + if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { if ( FSKrawDemod("0 0", false) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ tests[hits].modulation = DEMOD_FSK; if (fc1==8 && fc2 == 5) @@ -568,10 +583,8 @@ bool tryDetectModulation(){ ++hits; } } - //undo trim from ask - //save_restoreGB(0); clk = GetNrzClock("", false, false); - if (clk>0) { + if (clk>8) { //clock of rf/8 is likely a false positive, so don't use it. if ( NRZrawDemod("0 0 1", false) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_NRZ; tests[hits].bitrate = bitRate; @@ -591,12 +604,12 @@ bool tryDetectModulation(){ } } - // allow undo - // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - save_restoreGB(1); - CmdLtrim("160"); clk = GetPskClock("", false, false); if (clk>0) { + // allow undo + save_restoreGB(GRAPH_SAVE); + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + CmdLtrim("160"); if ( PSKDemod("0 0 6", false) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_PSK1; tests[hits].bitrate = bitRate; @@ -638,9 +651,9 @@ bool tryDetectModulation(){ ++hits; } } // inverse waves does not affect this demod - } //undo trim samples - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); + } } if ( hits == 1) { config.modulation = tests[0].modulation; @@ -829,9 +842,7 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) // moved test to here, since this gets most faults first. if ( resv > 0x00) continue; - uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //extended mode part of rate - int bitRate = PackBits(si, 3, DemodBuffer); si += 3; //bit rate - if (bitRate > 7) continue; + int bitRate = PackBits(si, 6, DemodBuffer); si += 6; //bit rate (includes extended mode part of rate) uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr @@ -842,11 +853,14 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) bool extMode =( (safer == 0x6 || safer == 0x9) && extend) ? true : false; if (!extMode){ - if (xtRate) continue; //nml01 || nml02 || caused issues on noralys tags + if (bitRate > 7) continue; + if (!testBitRate(bitRate, clk)) continue; + } else { //extended mode bitrate = same function to calc bitrate as em4x05 + if (EM4x05_GET_BITRATE(bitRate) != clk) continue; + } //test modulation if (!testModulation(mode, modread)) continue; - if (!testBitRate(bitRate, clk)) continue; *fndBitRate = bitRate; *offset = idx; *Q5 = false; @@ -905,7 +919,7 @@ int special(const char *Cmd) { int printConfiguration( t55xx_conf_block_t b){ PrintAndLog("Chip Type : %s", (b.Q5) ? "T5555(Q5)" : "T55x7"); PrintAndLog("Modulation : %s", GetSelectedModulationStr(b.modulation) ); - PrintAndLog("Bit Rate : %s", GetBitRateStr(b.bitrate) ); + PrintAndLog("Bit Rate : %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE && (b.block0>>28==6 || b.block0>>28==9))) ); PrintAndLog("Inverted : %s", (b.inverted) ? "Yes" : "No" ); PrintAndLog("Offset : %d", b.offset); PrintAndLog("Seq. Term. : %s", (b.ST) ? "Yes" : "No" ); @@ -951,6 +965,7 @@ int CmdT55xxWriteBlock(const char *Cmd) { bool usepwd = false; bool page1 = false; bool gotdata = false; + bool testMode = false; bool errors = false; uint8_t cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -975,6 +990,11 @@ int CmdT55xxWriteBlock(const char *Cmd) { usepwd = true; cmdp += 2; break; + case 't': + case 'T': + testMode = true; + cmdp++; + break; case '1': page1 = true; cmdp++; @@ -995,6 +1015,7 @@ int CmdT55xxWriteBlock(const char *Cmd) { UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}}; UsbCommand resp; c.d.asBytes[0] = (page1) ? 0x2 : 0; + c.d.asBytes[0] |= (testMode) ? 0x4 : 0; char pwdStr[16] = {0}; snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); @@ -1227,7 +1248,7 @@ int CmdT55xxInfo(const char *Cmd){ PrintAndLog("-------------------------------------------------------------"); PrintAndLog(" Safer key : %s", GetSaferStr(safer)); PrintAndLog(" reserved : %d", resv); - PrintAndLog(" Data bit rate : %s", GetBitRateStr(dbr)); + PrintAndLog(" Data bit rate : %s", GetBitRateStr(dbr, extend)); PrintAndLog(" eXtended mode : %s", (extend) ? "Yes - Warning":"No"); PrintAndLog(" Modulation : %s", GetModulationStr(datamod)); PrintAndLog(" PSK clock frequency : %d", pskcf); @@ -1298,10 +1319,13 @@ int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ return 1; } -char * GetBitRateStr(uint32_t id){ +char * GetBitRateStr(uint32_t id, bool xmode) { static char buf[25]; char *retStr = buf; + if (xmode) { //xmode bitrate calc is same as em4x05 calc + snprintf(retStr,sizeof(buf),"%d - RF/%d", id, EM4x05_GET_BITRATE(id)); + } else { switch (id){ case 0: snprintf(retStr,sizeof(buf),"%d - RF/8",id); break; case 1: snprintf(retStr,sizeof(buf),"%d - RF/16",id); break; @@ -1313,6 +1337,7 @@ char * GetBitRateStr(uint32_t id){ case 7: snprintf(retStr,sizeof(buf),"%d - RF/128",id); break; default: snprintf(retStr,sizeof(buf),"%d - (Unknown)",id); break; } + } return buf; } @@ -1455,8 +1480,7 @@ int CmdT55xxWipe(const char *Cmd) { bool IsCancelled(void) { if (ukbhit()) { - int ch = getchar(); - (void)ch; + int gc = getchar(); (void)gc; printf("\naborted via keyboard!\n"); return true; } @@ -1713,12 +1737,160 @@ int CmdT55xxRecoverPW(const char *Cmd) { return 0; } +// note length of data returned is different for different chips. +// some return all page 1 (64 bits) and others return just that block (32 bits) +// unfortunately the 64 bits makes this more likely to get a false positive... +bool tryDetectP1(bool getData) { + uint8_t preamble[] = {1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,1}; + size_t startIdx = 0; + uint8_t fc1 = 0, fc2 = 0, ans = 0; + int clk = 0, firstClockEdge = 0; + bool st = true; + + if ( getData ) { + if ( !AquireData(T55x7_PAGE1, 1, false, 0) ) + return false; + } + + // try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...) + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, false, &firstClockEdge); + if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { + if ( FSKrawDemod("0 0", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( FSKrawDemod("0 1", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + return false; + } + + // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...) + clk = GetPskClock("", false, false); + if (clk>0) { + // allow undo + // save_restoreGB(1); + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + //CmdLtrim("160"); + if ( PSKDemod("0 0 6", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + if ( PSKDemod("0 1 6", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + // PSK2 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 6", false)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + } // inverse waves does not affect PSK2 demod + //undo trim samples + //save_restoreGB(0); + // no other modulation clocks = 2 or 4 so quit searching + if (fc1 != 8) return false; + } + + // try ask clock detect. it could be another type even if successful. + clk = GetAskClock("", false, false); + if (clk>0) { + if ( ASKDemod_ext("0 0 1", false, false, 1, &st) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + st = true; + if ( ASKDemod_ext("0 1 1", false, false, 1, &st) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( ASKbiphaseDemod("0 0 0 2", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( ASKbiphaseDemod("0 0 1 2", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + } + + // try NRZ clock detect. it could be another type even if successful. + clk = GetNrzClock("", false, false); //has the most false positives :( + if (clk>0) { + if ( NRZrawDemod("0 0 1", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( NRZrawDemod("0 1 1", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + } + return false; +} +// does this need to be a callable command? +int CmdT55xxDetectPage1(const char *Cmd){ + bool errors = false; + bool useGB = false; + bool usepwd = false; + uint32_t password = 0; + uint8_t cmdp = 0; + + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_t55xx_detectP1(); + case 'p': + case 'P': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case '1': + // use Graphbuffer data + useGB = true; + cmdp++; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_t55xx_detectP1(); + + if ( !useGB ) { + if ( !AquireData(T55x7_PAGE1, 1, usepwd, password) ) + return false; + } + bool success = tryDetectP1(false); + if (success) PrintAndLog("T55xx chip found!"); + return success; +} static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, + {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, {"info", CmdT55xxInfo, 1, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, {"read", CmdT55xxReadBlock, 0, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 10980294e..fd83dc06a 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -124,10 +124,12 @@ typedef struct { bool Q5; bool ST; } t55xx_conf_block_t; -t55xx_conf_block_t Get_t55xx_Config(); + +t55xx_conf_block_t Get_t55xx_Config(void); void Set_t55xx_Config(t55xx_conf_block_t conf); extern int CmdLFT55XX(const char *Cmd); +extern int CmdT55xxBruteForce(const char *Cmd); extern int CmdT55xxSetConfig(const char *Cmd); extern int CmdT55xxReadBlock(const char *Cmd); extern int CmdT55xxWriteBlock(const char *Cmd); @@ -136,9 +138,8 @@ extern int CmdT55xxInfo(const char *Cmd); extern int CmdT55xxDetect(const char *Cmd); extern int CmdResetRead(const char *Cmd); extern int CmdT55xxWipe(const char *Cmd); -extern int CmdT55xxBruteForce(const char *Cmd); -char * GetBitRateStr(uint32_t id); +char * GetBitRateStr(uint32_t id, bool xmode); char * GetSaferStr(uint32_t id); char * GetModulationStr( uint32_t id); char * GetModelStrFromCID(uint32_t cid); @@ -151,6 +152,7 @@ int printConfiguration( t55xx_conf_block_t b); bool DecodeT55xxBlock(void); bool tryDetectModulation(void); bool testKnownConfigBlock(uint32_t block0); +extern bool tryDetectP1(bool getData); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); int special(const char *Cmd); int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); diff --git a/client/cmdlfti.c b/client/cmdlfti.c index a2da85ad8..b7bdea54b 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -295,7 +295,7 @@ int CmdTIWrite(const char *Cmd) static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF tag"}, + {"demod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF tag from the GraphBuffer"}, {"read", CmdTIRead, 0, "Read and decode a TI 134 kHz tag"}, {"write", CmdTIWrite, 0, "Write new data to a r/w TI 134 kHz tag"}, {NULL, NULL, 0, NULL} diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index e628c3849..9439023c3 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -7,22 +7,11 @@ // Low frequency Viking tag commands (AKA FDI Matalec Transit) // ASK/Manchester, RF/32, 64 bits (complete) //----------------------------------------------------------------------------- -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "util.h" -#include "graph.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdmain.h" -#include "cmdlf.h" #include "cmdlfviking.h" -#include "lfdemod.h" + static int CmdHelp(const char *Cmd); -int usage_lf_viking_clone(void){ +int usage_lf_viking_clone(void) { PrintAndLog("clone a Viking AM tag to a T55x7 tag."); PrintAndLog("Usage: lf viking clone "); PrintAndLog("Options :"); @@ -54,15 +43,60 @@ uint64_t getVikingBits(uint32_t id) { ret |= checksum; return ret; } +// by marshmellow +// find viking preamble 0xF200 in already demoded data +int detectViking(uint8_t *dest, size_t *size) { + //make sure buffer has data + if (*size < 64*2) return -2; + size_t startIdx = 0; + uint8_t preamble[] = {1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -4; //preamble not found + + uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ + bytebits_to_byte(dest+startIdx+8,8) ^ + bytebits_to_byte(dest+startIdx+16,8) ^ + bytebits_to_byte(dest+startIdx+24,8) ^ + bytebits_to_byte(dest+startIdx+32,8) ^ + bytebits_to_byte(dest+startIdx+40,8) ^ + bytebits_to_byte(dest+startIdx+48,8) ^ + bytebits_to_byte(dest+startIdx+56,8); + if ( checkCalc != 0xA8 ) return -5; + if (*size != 64) return -6; + //return start position + return (int)startIdx; +} + +//by marshmellow +//see ASKDemod for what args are accepted +int CmdVikingDemod(const char *Cmd) { + if (!ASKDemod(Cmd, false, false, 1)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Viking ASKDemod failed"); + return 0; + } + size_t size = DemodBufferLen; + + int ans = detectViking(DemodBuffer, &size); + if (ans < 0) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Viking Demod %d %s", ans, (ans == -5)?"[chksum error]":""); + return 0; + } + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32); + uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32); + uint8_t checksum = bytebits_to_byte(DemodBuffer+ans+32+24, 8); + PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, checksum); + PrintAndLog("Raw: %08X%08X", raw1,raw2); + setDemodBuf(DemodBuffer, 64, ans); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); + return 1; +} //by marshmellow //see ASKDemod for what args are accepted int CmdVikingRead(const char *Cmd) { - // read lf silently - CmdLFRead("s"); - // get samples silently - getSamples("12000", true); - // demod and output viking ID + lf_read(true, 10000); return CmdVikingDemod(Cmd); } @@ -120,7 +154,8 @@ int CmdVikingSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"read", CmdVikingRead, 0, "Attempt to read and Extract tag data"}, + {"demod", CmdVikingDemod, 1, "Demodulate a Viking tag from the GraphBuffer"}, + {"read", CmdVikingRead, 0, "Attempt to read and Extract tag data from the antenna"}, {"clone", CmdVikingClone, 0, "<8 digit ID number> clone viking tag"}, {"sim", CmdVikingSim, 0, "<8 digit ID number> simulate viking tag"}, {NULL, NULL, 0, NULL} diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h index e06428286..503534eaf 100644 --- a/client/cmdlfviking.h +++ b/client/cmdlfviking.h @@ -8,9 +8,29 @@ //----------------------------------------------------------------------------- #ifndef CMDLFVIKING_H__ #define CMDLFVIKING_H__ -int CmdLFViking(const char *Cmd); -int CmdVikingRead(const char *Cmd); -int CmdVikingClone(const char *Cmd); -int CmdVikingSim(const char *Cmd); +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "lfdemod.h" + +extern int CmdLFViking(const char *Cmd); + +extern int CmdVikingDemod(const char *Cmd); +extern int CmdVikingRead(const char *Cmd); +extern int CmdVikingClone(const char *Cmd); +extern int CmdVikingSim(const char *Cmd); + +extern int detectViking(uint8_t *dest, size_t *size); + +extern int usage_lf_viking_clone(void); +extern int usage_lf_viking_sim(void); #endif diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index cca47d3bf..6c909f803 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -67,6 +67,18 @@ static uint8_t visa_parity( uint32_t id) { return par; } +// by iceman +// find Visa2000 preamble in already demoded data +int detectVisa2k(uint8_t *dest, size_t *size) { + if (*size < 96) return -1; //make sure buffer has data + size_t startIdx = 0; + uint8_t preamble[] = {0,1,0,1,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,1,0}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -2; //preamble not found + if (*size != 96) return -3; //wrong demoded size + //return start position + return (int)startIdx; +} /** * @@ -95,7 +107,7 @@ int CmdVisa2kDemod(const char *Cmd) { return 0; } size_t size = DemodBufferLen; - int ans = Visa2kDemod_AM(DemodBuffer, &size); + int ans = detectVisa2k(DemodBuffer, &size); if (ans < 0){ if (g_debugMode){ if (ans == -1) @@ -111,7 +123,7 @@ int CmdVisa2kDemod(const char *Cmd) { return 0; } setDemodBuf(DemodBuffer, 96, ans); - setGrid_Clock(64); + setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); @@ -143,8 +155,7 @@ int CmdVisa2kDemod(const char *Cmd) { // 64*96*2=12288 samples just in case we just missed the first preamble we can still catch 2 of them int CmdVisa2kRead(const char *Cmd) { - CmdLFRead("s"); - getSamples("12500",true); + lf_read(true, 12500); return CmdVisa2kDemod(Cmd); } @@ -219,10 +230,10 @@ int CmdVisa2kSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdVisa2kDemod, 1, "Attempt to demod from GraphBuffer"}, - {"read", CmdVisa2kRead, 0, "Attempt to read and extract tag data"}, - {"clone", CmdVisa2kClone, 0, "clone Visa2000 tag"}, - {"sim", CmdVisa2kSim, 0, "simulate Visa2000 tag"}, + {"demod", CmdVisa2kDemod, 1, "Demodulate an VISA2000 tag from the GraphBuffer"}, + {"read", CmdVisa2kRead, 0, "Attempt to read and extract tag data from the antenna"}, + {"sim", CmdVisa2kSim, 0, "Visa2000 tag simulator"}, + {"clone", CmdVisa2kClone, 0, "clone Visa2000 to t55x7"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfvisa2000.h b/client/cmdlfvisa2000.h index 35159805d..a266fa76e 100644 --- a/client/cmdlfvisa2000.h +++ b/client/cmdlfvisa2000.h @@ -22,16 +22,18 @@ #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // parityTest extern int CmdLFVisa2k(const char *Cmd); + +extern int CmdVisa2kDemod(const char *Cmd); +extern int CmdVisa2kRead(const char *Cmd); extern int CmdVisa2kClone(const char *Cmd); extern int CmdVisa2kSim(const char *Cmd); -extern int CmdVisa2kRead(const char *Cmd); -extern int CmdVisa2kDemod(const char *Cmd); int getvisa2kBits(uint64_t fullcode, uint8_t *bits); +extern int detectVisa2k(uint8_t *dest, size_t *size); -int usage_lf_visa2k_clone(void); -int usage_lf_visa2k_sim(void); -int usage_lf_visa2k_read(void); -int usage_lf_visa2k_demod(void); +extern int usage_lf_visa2k_clone(void); +extern int usage_lf_visa2k_sim(void); +//extern int usage_lf_visa2k_read(void); +//extern int usage_lf_visa2k_demod(void); #endif diff --git a/client/cmdmain.c b/client/cmdmain.c index 058fc3ee7..2272a9d23 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -12,7 +12,7 @@ #include #include #include -#include "sleep.h" +#include "util_posix.h" #include "cmdparser.h" #include "proxmark3.h" #include "data.h" diff --git a/client/data.c b/client/data.c index 184a63b61..ba0ea47af 100644 --- a/client/data.c +++ b/client/data.c @@ -23,10 +23,20 @@ void GetFromBigBuf(uint8_t *dest, int bytes, int start_index) { clearCommandBuffer(); SendCommand(&c); } -void GetEMLFromBigBuf(uint8_t *dest, uint32_t bytes, uint32_t start_index) { +// this will download the EMULATOR memory part from device, +// inside the BigBuf EML zon. +bool GetEMLFromBigBuf(uint8_t *dest, uint32_t bytes, uint32_t start_index) { sample_buf = dest; UsbCommand c = {CMD_DOWNLOAD_EML_BIGBUF, {start_index, bytes, 0}}; clearCommandBuffer(); SendCommand(&c); + + // the download will be done inside cmdmain.c function UsbCommandReceived(UsbCommand *UC) + + // we are waiting for the ACK + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)) + return false; + + return true; } diff --git a/client/data.h b/client/data.h index df1f31de3..b8bbaa207 100644 --- a/client/data.h +++ b/client/data.h @@ -11,8 +11,12 @@ #ifndef DATA_H__ #define DATA_H__ #include +#include #include "util.h" + +#define FILE_PATH_SIZE 1000 + extern uint8_t* sample_buf; -void GetFromBigBuf(uint8_t *dest, int bytes, int start_index); -void GetEMLFromBigBuf(uint8_t *dest, uint32_t bytes, uint32_t start_index); +extern void GetFromBigBuf(uint8_t *dest, int bytes, int start_index); +extern bool GetEMLFromBigBuf(uint8_t *dest, uint32_t bytes, uint32_t start_index); #endif diff --git a/client/flash.c b/client/flash.c index a2a90e663..ec76d65d1 100644 --- a/client/flash.c +++ b/client/flash.c @@ -8,17 +8,7 @@ // ELF file flasher //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include "proxmark3.h" -#include "sleep.h" #include "flash.h" -#include "elf.h" -#include "proxendian.h" -#include "usb_cmd.h" -#include "at91sam7s512.h" void SendCommand(UsbCommand* txcmd); void ReceiveCommand(UsbCommand* rxcmd); diff --git a/client/flash.h b/client/flash.h index 3e9f77a7a..ec93a2787 100644 --- a/client/flash.h +++ b/client/flash.h @@ -10,7 +10,17 @@ #define __FLASH_H__ #include +#include +#include +#include +#include + +#include "proxmark3.h" #include "elf.h" +#include "proxendian.h" +#include "usb_cmd.h" +#include "at91sam7s512.h" +#include "util_posix.h" typedef struct { void *data; diff --git a/client/flasher.c b/client/flasher.c index 3adf98ad3..9bc52e946 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -10,7 +10,7 @@ #include #include #include -#include "sleep.h" +#include "util_posix.h" #include "proxmark3.h" #include "flash.h" #include "uart.h" diff --git a/client/fpga_compress.c b/client/fpga_compress.c index aac589afe..2212265ad 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -38,7 +38,8 @@ #define COMPRESS_MAX_CHAIN 8192 #define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression) -#define FPGA_CONFIG_SIZE 42336 // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE +#define FPGA_CONFIG_SIZE 42336L // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE +#define HARDNESTED_TABLE_SIZE (sizeof(uint32_t) * ((1L<<19)+1)) static void usage(void) { @@ -46,6 +47,8 @@ static void usage(void) fprintf(stderr, " Combine n FPGA bitstream files and compress them into one.\n\n"); fprintf(stderr, " fpga_compress -d "); fprintf(stderr, " Decompress . Write result to "); + fprintf(stderr, " fpga_compress -t "); + fprintf(stderr, " Compress hardnested table . Write result to "); } @@ -72,22 +75,29 @@ static bool all_feof(FILE *infile[], uint8_t num_infiles) } -int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile) +int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardnested_mode) { uint8_t *fpga_config; uint32_t i; - int ret; - int c; + int32_t ret; + uint8_t c; z_stream compressed_fpga_stream; + if (hardnested_mode) { + fpga_config = malloc(num_infiles * HARDNESTED_TABLE_SIZE); + } else { fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE); - + } // read the input files. Interleave them into fpga_config[] i = 0; do { - if (i >= num_infiles * FPGA_CONFIG_SIZE) { - fprintf(stderr, "Input files too big (total > %d bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); + if (i >= num_infiles * (hardnested_mode?HARDNESTED_TABLE_SIZE:FPGA_CONFIG_SIZE)) { + if (hardnested_mode) { + fprintf(stderr, "Input file too big (> %lu bytes). This is probably not a hardnested bitflip state table.\n", HARDNESTED_TABLE_SIZE); + } else { + fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles*FPGA_CONFIG_SIZE); + } for(uint16_t j = 0; j < num_infiles; j++) { fclose(infile[j]); } @@ -99,7 +109,7 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile) for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) { c = fgetc(infile[j]); if (!feof(infile[j])) { - fpga_config[i++] = c &0xFF; + fpga_config[i++] = c; } else if (num_infiles > 1) { fpga_config[i++] = '\0'; } @@ -123,7 +133,7 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile) COMPRESS_STRATEGY); // estimate the size of the compressed output - unsigned int outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in); + uint32_t outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in); uint8_t *outbuf = malloc(outsize_max); compressed_fpga_stream.next_out = outbuf; compressed_fpga_stream.avail_out = outsize_max; @@ -178,7 +188,7 @@ int zlib_decompress(FILE *infile, FILE *outfile) #define DECOMPRESS_BUF_SIZE 1024 uint8_t outbuf[DECOMPRESS_BUF_SIZE]; uint8_t inbuf[DECOMPRESS_BUF_SIZE]; - int ret; + int32_t ret; z_stream compressed_fpga_stream; @@ -198,9 +208,9 @@ int zlib_decompress(FILE *infile, FILE *outfile) compressed_fpga_stream.next_in = inbuf; uint16_t i = 0; do { - int c = fgetc(infile); + int32_t c = fgetc(infile); if (!feof(infile)) { - inbuf[i++] = c; + inbuf[i++] = c & 0xFF; compressed_fpga_stream.avail_in++; } else { break; @@ -272,11 +282,23 @@ int main(int argc, char **argv) } else { // Compress - infiles = calloc(argc-2, sizeof(FILE*)); - for (uint16_t i = 0; i < argc-2; i++) { - infiles[i] = fopen(argv[i+1], "rb"); + bool hardnested_mode = false; + int num_input_files = 0; + if (!strcmp(argv[1], "-t")) { // hardnested table + if (argc != 4) { + usage(); + return(EXIT_FAILURE); + } + hardnested_mode = true; + num_input_files = 1; + } else { + num_input_files = argc-2; + } + infiles = calloc(num_input_files, sizeof(FILE*)); + for (uint16_t i = 0; i < num_input_files; i++) { + infiles[i] = fopen(argv[i+hardnested_mode?2:1], "rb"); if (infiles[i] == NULL) { - fprintf(stderr, "Error. Cannot open input file %s", argv[i+1]); + fprintf(stderr, "Error. Cannot open input file %s", argv[i+hardnested_mode?2:1]); return(EXIT_FAILURE); } } @@ -285,6 +307,6 @@ int main(int argc, char **argv) fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]); return(EXIT_FAILURE); } - return zlib_compress(infiles, argc-2, outfile); + return zlib_compress(infiles, num_input_files, outfile, hardnested_mode); } } diff --git a/client/graph.c b/client/graph.c index ac3934018..aa22b36e9 100644 --- a/client/graph.c +++ b/client/graph.c @@ -147,13 +147,18 @@ int GetAskClock(const char str[], bool printAns, bool verbose) PrintAndLog("Failed to copy from graphbuffer"); return -1; } - bool st = DetectST(grph, &size, &clock); - int start = 0; - if (st == false) + //, size_t *ststart, size_t *stend + size_t ststart = 0, stend = 0; + bool st = DetectST(grph, &size, &clock, &ststart, &stend); + int start = stend; + if (st == false) { start = DetectASKClock(grph, size, &clock, 20); - - if (printAns) + } + setClockGrid(clock, start); + // Only print this message if we're not looping something + if (printAns || g_debugMode) { PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start); + } return clock; } @@ -167,11 +172,13 @@ uint8_t GetPskCarrier(const char str[], bool printAns, bool verbose) PrintAndLog("Failed to copy from graphbuffer"); return 0; } - carrier = countFC(grph, size, 0); + uint16_t fc = countFC(grph, size, 0); + carrier = fc & 0xFF; + if (carrier != 2 && carrier != 4 && carrier != 8) return 0; + if (( fc >> 8) == 10 && carrier == 8) return 0; // Only print this message if we're not looping something if (printAns) PrintAndLog("Auto-detected PSK carrier rate: %d", carrier); - return carrier; } @@ -190,12 +197,14 @@ int GetPskClock(const char str[], bool printAns, bool verbose) if (verbose) PrintAndLog("Failed to copy from graphbuffer"); return -1; } - int start = 0; - clock = DetectPSKClock_ext(grph, size, 0, &start); - - if (printAns) - PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start); - + size_t firstPhaseShiftLoc = 0; + uint8_t curPhase = 0, fc = 0; + clock = DetectPSKClock(grph, size, 0, &firstPhaseShiftLoc, &curPhase, &fc); + setClockGrid(clock, firstPhaseShiftLoc); + // Only print this message if we're not looping something + if (printAns){ + PrintAndLog("Auto-detected clock rate: %d", clock); + } return clock; } @@ -216,12 +225,13 @@ uint8_t GetNrzClock(const char str[], bool printAns, bool verbose) PrintAndLog("Failed to copy from graphbuffer"); return -1; } - int start = 0; - clock = DetectNRZClock_ext(grph, size, 0, &start); + size_t clkStartIdx = 0; + clock = DetectNRZClock(grph, size, 0, &clkStartIdx); + setClockGrid(clock, clkStartIdx); // Only print this message if we're not looping something - if (printAns) - PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start); - + if (printAns){ + PrintAndLog("Auto-detected clock rate: %d", clock); + } return clock; } //by marshmellow @@ -236,10 +246,12 @@ uint8_t GetFskClock(const char str[], bool printAns, bool verbose) uint8_t fc1=0, fc2=0, rf1=0; - uint8_t ans = fskClocks(&fc1, &fc2, &rf1, verbose); + int firstClockEdge = 0; + uint8_t ans = fskClocks(&fc1, &fc2, &rf1, verbose, &firstClockEdge); if (ans == 0) return 0; if ((fc1==10 && fc2==8) || (fc1==8 && fc2==5)){ if (printAns) PrintAndLog("Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); + setClockGrid(rf1, firstClockEdge); return rf1; } if (verbose){ @@ -248,7 +260,7 @@ uint8_t GetFskClock(const char str[], bool printAns, bool verbose) } return 0; } -uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose) +uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose, int *firstClockEdge) { uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(BitStream); @@ -260,9 +272,8 @@ uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose) } *fc1 = (ans >> 8) & 0xFF; *fc2 = ans & 0xFF; - - int start = 0; - *rf1 = detectFSKClk_ext(BitStream, size, *fc1, *fc2, &start); + //int firstClockEdge = 0; + *rf1 = detectFSKClk(BitStream, size, *fc1, *fc2, firstClockEdge); if (*rf1 == 0) { if (verbose || g_debugMode) PrintAndLog("DEBUG: Clock detect error"); return 0; @@ -271,13 +282,13 @@ uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose) } // test samples are not just noise -bool graphJustNoise(int *BitStream, int size) +bool graphJustNoise(int *bits, int size) { //might not be high enough for noisy environments #define THRESHOLD 15; bool isNoise = true; for(int i=0; i < size && isNoise; i++){ - isNoise = BitStream[i] < THRESHOLD; + isNoise = bits[i] < THRESHOLD; } return isNoise; } diff --git a/client/graph.h b/client/graph.h index d26e1909c..b20ae4e84 100644 --- a/client/graph.h +++ b/client/graph.h @@ -21,7 +21,8 @@ int GetPskClock(const char str[], bool printAns, bool verbose); uint8_t GetPskCarrier(const char str[], bool printAns, bool verbose); uint8_t GetNrzClock(const char str[], bool printAns, bool verbose); uint8_t GetFskClock(const char str[], bool printAns, bool verbose); -uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose); +uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose, int *firstClockEdge); +//uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose); bool graphJustNoise(int *BitStream, int size); void setGraphBuf(uint8_t *buff, size_t size); void save_restoreGB(uint8_t saveOpt); diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 718b7c5d5..255cd7d57 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -87,9 +87,9 @@ static uint32_t bucket_count = 0; static statelist_t* buckets[128]; static uint32_t keys_found = 0; static uint64_t num_keys_tested; +static uint64_t found_bs_key = 0; - -uint8_t trailing_zeros(uint8_t byte) +inline uint8_t trailing_zeros(uint8_t byte) { static const uint8_t trailing_zeros_LUT[256] = { 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, @@ -163,10 +163,12 @@ static void* crack_states_thread(void* x){ #endif const uint64_t key = crack_states_bitsliced(thread_arg->cuid, thread_arg->best_first_bytes, bucket, &keys_found, &num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, thread_arg->nonces); if(key != -1){ - __sync_fetch_and_add(&keys_found, 1); + __atomic_fetch_add(&keys_found, 1, __ATOMIC_SEQ_CST); + __atomic_fetch_add(&found_bs_key, key, __ATOMIC_SEQ_CST); + char progress_text[80]; sprintf(progress_text, "Brute force phase completed. Key found: %012" PRIx64, key); - hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); + hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); break; } else if(keys_found){ break; @@ -282,21 +284,17 @@ static void write_benchfile(statelist_t *candidates) { #endif -bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes) +bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *foundkey) { #if defined (WRITE_BENCH_FILE) write_benchfile(candidates); #endif bool silent = (bf_rate != NULL); - // if (!silent) { - // PrintAndLog("Brute force phase starting."); - // PrintAndLog("Using %u-bit bitslices", MAX_BITSLICES); - // } - keys_found = 0; num_keys_tested = 0; - + found_bs_key = 0; + bitslice_test_nonces(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par); // count number of states to go @@ -309,14 +307,6 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint } uint64_t start_time = msclock(); - // enumerate states using all hardware threads, each thread handles one bucket - // if (!silent) { - // PrintAndLog("Starting %u cracking threads to search %u buckets containing a total of %" PRIu64" states...\n", NUM_BRUTE_FORCE_THREADS, bucket_count, maximum_states); - // printf("Common bits of first 4 2nd nonce bytes: %u %u %u\n", - // trailing_zeros(bf_test_nonce_2nd_byte[1] ^ bf_test_nonce_2nd_byte[0]), - // trailing_zeros(bf_test_nonce_2nd_byte[2] ^ bf_test_nonce_2nd_byte[1]), - // trailing_zeros(bf_test_nonce_2nd_byte[3] ^ bf_test_nonce_2nd_byte[2])); - // } pthread_t threads[NUM_BRUTE_FORCE_THREADS]; struct args { @@ -345,18 +335,11 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint uint64_t elapsed_time = msclock() - start_time; - // if (!silent) { - // printf("Brute force completed after testing %" PRIu64" (2^%1.1f) keys in %1.1f seconds at a rate of %1.0f (2^%1.1f) keys per second.\n", - // num_keys_tested, - // log(num_keys_tested) / log(2.0), - // (float)elapsed_time/1000.0, - // (float)num_keys_tested / ((float)elapsed_time / 1000.0), - // log((float)num_keys_tested / ((float)elapsed_time/1000.0)) / log(2.0)); - // } - - if (bf_rate != NULL) { + if (bf_rate != NULL) *bf_rate = (float)num_keys_tested / ((float)elapsed_time / 1000.0); - } + + if ( keys_found > 0) + *foundkey = found_bs_key; return (keys_found != 0); } @@ -433,8 +416,7 @@ static bool read_bench_data(statelist_t *test_candidates) { } -float brute_force_benchmark() -{ +float brute_force_benchmark() { statelist_t test_candidates[NUM_BRUTE_FORCE_THREADS]; test_candidates[0].states[ODD_STATE] = malloc((TEST_BENCH_SIZE+1) * sizeof(uint32_t)); @@ -461,7 +443,8 @@ float brute_force_benchmark() uint64_t maximum_states = TEST_BENCH_SIZE*TEST_BENCH_SIZE*(uint64_t)NUM_BRUTE_FORCE_THREADS; float bf_rate; - brute_force_bs(&bf_rate, test_candidates, 0, 0, maximum_states, NULL, 0); + uint64_t found_key = 0; + brute_force_bs(&bf_rate, test_candidates, 0, 0, maximum_states, NULL, 0, &found_key); free(test_candidates[0].states[ODD_STATE]); free(test_candidates[0].states[EVEN_STATE]); diff --git a/client/hardnested/hardnested_bruteforce.h b/client/hardnested/hardnested_bruteforce.h index d4f6348d0..c978a82c3 100644 --- a/client/hardnested/hardnested_bruteforce.h +++ b/client/hardnested/hardnested_bruteforce.h @@ -28,7 +28,7 @@ typedef struct { } statelist_t; extern void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte); -extern bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes); +extern bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key); extern float brute_force_benchmark(); extern uint8_t trailing_zeros(uint8_t byte); extern bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, uint32_t odd, uint32_t even); diff --git a/client/hid-flasher/flash.c b/client/hid-flasher/flash.c index 6670d637d..e88e21218 100644 --- a/client/hid-flasher/flash.c +++ b/client/hid-flasher/flash.c @@ -11,7 +11,7 @@ #include #include #include -#include "sleep.h" +#include "util_posix.h" #include "proxusb.h" #include "flash.h" #include "elf.h" diff --git a/client/hid-flasher/flasher.c b/client/hid-flasher/flasher.c index a4a0e85e7..a7faf1713 100644 --- a/client/hid-flasher/flasher.c +++ b/client/hid-flasher/flasher.c @@ -9,7 +9,7 @@ #include #include #include -#include "sleep.h" +#include "util_posix.h" #include "proxusb.h" #include "flash.h" diff --git a/client/hid-flasher/proxusb.c b/client/hid-flasher/proxusb.c index 300333783..e69636aec 100644 --- a/client/hid-flasher/proxusb.c +++ b/client/hid-flasher/proxusb.c @@ -8,20 +8,7 @@ //----------------------------------------------------------------------------- // USB utilities //----------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sleep.h" #include "proxusb.h" -#include "proxmark3.h" -#include "usb_cmd.h" // It seems to be missing for mingw #ifndef ETIMEDOUT diff --git a/client/hid-flasher/proxusb.h b/client/hid-flasher/proxusb.h index 5845888a5..5d6f2b17e 100644 --- a/client/hid-flasher/proxusb.h +++ b/client/hid-flasher/proxusb.h @@ -13,8 +13,16 @@ #include #include +#include +#include +#include +#include #include +#include +#include +#include "proxmark3.h" #include "usb_cmd.h" +#include "util_posix.h" extern unsigned char return_on_error; extern unsigned char error_occured; diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index dadd2fc51..e65d0f706 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -24,7 +24,6 @@ Command = { self.__index = self o.cmd = o.cmd or _commands.CMD_UNKNOWN - --o.arg1 = "test" o.arg1 = o.arg1 or 0 o.arg2 = o.arg2 or 0 o.arg3 = o.arg3 or 0 @@ -47,13 +46,13 @@ Command = { print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data))) end o.data = data - return o end, parse = function (packet) - local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',packet) + local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet) return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data} - end, + end + } function Command:__tostring() local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format( diff --git a/client/lualibs/getopt.lua b/client/lualibs/getopt.lua index 538357f9d..add11842a 100644 --- a/client/lualibs/getopt.lua +++ b/client/lualibs/getopt.lua @@ -92,14 +92,14 @@ local function getopt(args, ostr) else table.remove(args, 1); if #args == 0 then -- an option requiring argument is the last one - place = 0; - if ostr:sub(1, 1) == ':' then return ':' end + place = 0; + if ostr:sub(1, 1) == ':' then return ':' end return '?'; else arg = args[1] end - end - table.remove(args, 1); - place = 0; - end + end + table.remove(args, 1); + place = 0; + end return optopt, arg; end end diff --git a/client/mifarehost.c b/client/mifarehost.c index 89a255b22..4e1d34bd5 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -109,7 +109,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) //flush queue while (ukbhit()) { - int gc = getchar(); (void) gc; + int gc = getchar(); (void)gc; } // wait cycle @@ -117,7 +117,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) printf("."); fflush(stdout); if (ukbhit()) { - int gc = getchar(); (void) gc; + int gc = getchar(); (void)gc; return -5; break; } diff --git a/client/mifarehost.h b/client/mifarehost.h index 636a644fa..b7d90f68b 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -58,9 +58,17 @@ typedef struct { typedef struct { uint64_t Key[2]; - int foundKey[2]; + uint8_t foundKey[2]; } sector_t; +typedef struct { + uint8_t keyA[6]; + uint8_t keyB[6]; + //uint8_t foundKey[2]; +} icesector_t; + + + extern char logHexFileName[FILE_PATH_SIZE]; extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index 3417d7f73..adece3e3e 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -47,15 +47,15 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_ } PrintAndLog("+----+--------+---+-----+---------------+"); - clock_t t1 = clock(); + uint64_t t1 = msclock(); state = lfsr_common_prefix(nr, rr, ks3x, par); lfsr_rollback_word(state, uid ^ nt, 0); crypto1_get_lfsr(state, key); crypto1_destroy(state); - t1 = clock() - t1; - if ( t1 > 0 ) PrintAndLog("Time in nonce2key: %.0f ticks", (float)t1); + t1 = msclock() - t1; + PrintAndLog("Time in nonce2key: %.0f ticks", (float)t1/1000.0); return 0; } @@ -182,7 +182,7 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui return retval; } -// 32 bit recover key from 2 nonces +// 32 bit recover key from 2 nonces, with same nonce bool tryMfk32(nonces_t data, uint64_t *outputkey, bool verbose) { struct Crypto1State *s,*t; uint64_t outkey = 0; @@ -193,7 +193,7 @@ bool tryMfk32(nonces_t data, uint64_t *outputkey, bool verbose) { uint32_t ar0_enc = data.ar; // first encrypted reader response uint32_t nr1_enc = data.nr2; // second encrypted reader challenge uint32_t ar1_enc = data.ar2; // second encrypted reader response - bool isSuccess = FALSE; + bool isSuccess = false; uint8_t counter = 0; clock_t t1 = clock(); @@ -248,7 +248,7 @@ bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey, bool verbose) { uint32_t nt1 = data.nonce2; // second tag challenge (nonce) uint32_t nr1_enc = data.nr2; // second encrypted reader challenge uint32_t ar1_enc = data.ar2; // second encrypted reader response - bool isSuccess = FALSE; + bool isSuccess = false; int counter = 0; clock_t t1 = clock(); @@ -296,6 +296,7 @@ bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey, bool verbose) { return isSuccess; } +// 64 bit recover key from a full authentication. (sniffed) int tryMfk64_ex(uint8_t *data, uint64_t *outputkey){ uint32_t uid = LE32TOH(data); uint32_t nt = LE32TOH(data+4); // tag challenge diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index 506b8138c..0779bb8df 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -97,10 +97,7 @@ void ProxGuiQT::MainLoop() plotapp->exec(); } -ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL), - argc(argc), argv(argv) -{ -} +ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL), argc(argc), argv(argv) {} ProxGuiQT::~ProxGuiQT(void) { diff --git a/client/proxguiqt.h b/client/proxguiqt.h index fa927ee5d..6e1f1b47e 100644 --- a/client/proxguiqt.h +++ b/client/proxguiqt.h @@ -128,7 +128,7 @@ class WorkerThread : public QThread { void run(); private: char *script_cmds_file = NULL; - bool usb_present; + bool usb_present = false; }; #endif // PROXGUI_QT diff --git a/client/proxmark3.c b/client/proxmark3.c index c2cf3e38a..caa20a272 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -68,7 +68,7 @@ byte_t* prx = rx; // printf("██████╔╝██╔████╔██║ ████╔╝\n"); // printf("██╔═══╝ ██║╚██╔╝██║ ══█║ iceman@icesql.net\n"); // printf("██║ ██║ ╚═╝ ██║ ████╔╝ https://github.com/iceman1001/proxmark3\n"); - // printf("╚═╝ ╚═╝ ╚═╝ ╚═══╝v1.7.2\n"); + // printf("╚═╝ ╚═╝ ╚═╝ ╚═══╝v3.0.2n"); // } diff --git a/client/scripting.c b/client/scripting.c index b1409567b..1216e2e80 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -47,6 +47,49 @@ static int l_SendCommand(lua_State *L){ SendCommand((UsbCommand* )data); return 0; // no return values } + +/** + * @brief The following params expected: + * uint8_t *dest + * int bytes + * int start_index + * @param L + * @return + */ +static int l_GetFromBigBuf(lua_State *L){ + + int len = 0; + int startindex = 0; + + //Check number of arguments + int n = lua_gettop(L); + if(n == 0) { + //signal error by returning Nil, errorstring + lua_pushnil(L); + lua_pushstring(L,"You need to supply number of len and startindex"); + return 2; // two return values + } + if(n >= 2) { + len = luaL_checknumber(L, 1); + startindex = luaL_checknumber(L, 2); + } + + uint8_t *data = malloc(len); + if ( data == NULL ) { + //signal error by returning Nil, errorstring + lua_pushnil(L); + lua_pushstring(L,"Allocating memory failed"); + return 2; // two return values + } + + GetFromBigBuf(data, len, startindex); + WaitForResponse(CMD_ACK, NULL); + //Push it as a string + lua_pushlstring(L,(const char *)data, len); + if (data) + free(data); + return 1;// return 1 to signal one return value +} /** * @brief The following params expected: * uint32_t cmd @@ -369,6 +412,33 @@ static int l_crc64(lua_State *L) return 1; } +static int l_crc64_ecma182(lua_State *L) +{ + //size_t size; + uint64_t crc = 0; + unsigned char outdata[8] = {0x00}; + //const char *p_str = luaL_checklstring(L, 1, &size); + + //init + //crc64_ecma182(NULL, 0, &crc); + crc = 0x338103260CC4; + + // calc hash + //crc64_ecma182((uint8_t*) p_str, size, &crc); + + outdata[0] = (uint8_t)(crc >> 56) & 0xff; + outdata[1] = (uint8_t)(crc >> 48) & 0xff; + outdata[2] = (uint8_t)(crc >> 40) & 0xff; + outdata[3] = (uint8_t)(crc >> 32) & 0xff; + outdata[4] = (uint8_t)(crc >> 24) & 0xff; + outdata[5] = (uint8_t)(crc >> 16) & 0xff; + outdata[6] = (uint8_t)(crc >> 8) & 0xff; + outdata[7] = crc & 0xff; + lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); + return 1; +} + + static int l_sha1(lua_State *L) { size_t size; @@ -496,8 +566,7 @@ static int l_hardnested(lua_State *L){ } uint64_t foundkey = 0; -// int retval = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, haveTarget ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey); - int retval = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, haveTarget ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests); + int retval = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, haveTarget ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey); //Push the retval on the stack lua_pushinteger(L,retval); @@ -511,6 +580,18 @@ static int l_hardnested(lua_State *L){ return 2; //Two return values } +/** + * @brief l_validate_prng is a function to test is a nonce is using the weak PRNG + * @param L + * @return + */ +static int l_detect_prng(lua_State *L) { + bool valid = detect_classic_prng(); + //Push the retval on the stack + lua_pushinteger(L, valid); + return 1; +} + /** * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be * able to do "require('foobar')" if foobar.lua is within lualibs folder. @@ -537,6 +618,7 @@ int setLuaPath( lua_State* L, const char* path ) { int set_pm3_libraries(lua_State *L) { static const luaL_Reg libs[] = { {"SendCommand", l_SendCommand}, + {"GetFromBigBuf", l_GetFromBigBuf}, {"WaitForResponseTimeout", l_WaitForResponseTimeout}, {"mfDarkside", l_mfDarkside}, //{"PrintAndLog", l_PrintAndLog}, @@ -553,10 +635,12 @@ int set_pm3_libraries(lua_State *L) { {"crc8legic", l_crc8legic}, {"crc16", l_crc16}, {"crc64", l_crc64}, + {"crc64_ecma182", l_crc64_ecma182}, {"sha1", l_sha1}, {"reveng_models", l_reveng_models}, {"reveng_runmodel", l_reveng_RunModel}, {"hardnested", l_hardnested}, + {"detect_prng", l_detect_prng}, {NULL, NULL} }; diff --git a/client/scripts/hard.lua b/client/scripts/hard.lua index 1d8177722..d59698eb0 100644 --- a/client/scripts/hard.lua +++ b/client/scripts/hard.lua @@ -17,7 +17,7 @@ Examples : local numBlocks = 64 local numSectors = 16 -local DEBUG = TRUE +local DEBUG = true --- -- A debug printout-function function dbg(args) diff --git a/client/scripts/legic.lua b/client/scripts/legic.lua index 69605781b..1b459dc40 100644 --- a/client/scripts/legic.lua +++ b/client/scripts/legic.lua @@ -317,8 +317,10 @@ end --- -- put a string into a bytes-table function str2bytes(s) + if (string.len(s)%2~=0) then + return print("stamp should be a even hexstring e.g.: deadbeef or 0badc0de") + end local res={} - if (string.len(s)%2~=0) then return print("stamp should be a even hexstring e.g.: deadbeef or 0badc0de") end for i=1, string.len(s), 2 do table.insert(res, string.sub(s,i,(i+1))) end @@ -384,7 +386,10 @@ end --- -- put bytes into tag-table function bytesToTag(bytes, tag) - if(istable(tag)) then + if ~istable(tag) then + return oops("tag is no table in: bytesToTag ("..type(tag)..")") + end + tag.MCD =bytes[1]; tag.MSN0=bytes[2]; tag.MSN1=bytes[3]; @@ -425,8 +430,7 @@ function bytesToTag(bytes, tag) end print(accyan..#bytes.." bytes for Tag processed"..acoff) return tag - end - return oops("tag is no table in: bytesToTag ("..type(tag)..")") + end --- @@ -452,7 +456,10 @@ end --- -- read Tag-Table in bytes-table function tagToBytes(tag) - if (istable(tag)) then + if ~istable(tag) then + return oops("tag is no table in tagToBytes ("..type(tag)..")") + end + local bytes = {} local i, i2 -- main token-data @@ -497,8 +504,6 @@ function tagToBytes(tag) end return bytes end - return oops("tag is no table in tagToBytes ("..type(tag)..")") -end --- PM3 I/O --- --- @@ -573,12 +578,12 @@ function writeToTag(tag) -- write pm3-buffer to Tag for i=0, WriteBytes do if ( i<5 or i>6) then - cmd = ('hf legic write 0x%02x 0x01'):format(i) + cmd = ('hf legic write o 0x%02x d 0x01'):format(i) core.console(cmd) --print(cmd) elseif (i == 6) then -- write DCF in reverse order (requires 'mosci-patch') - cmd = 'hf legic write 0x05 0x02' + cmd = 'hf legic write o 0x05 d 0x02' print(acgreen..cmd..acoff) core.console(cmd) --print(cmd) @@ -597,12 +602,12 @@ function readFile(filename) print(accyan) local bytes = {} local tag = {} - if (file_check(filename)==false) then - return oops("input file: "..filename.." not found") - else + if ~file_check(filename) then return oops("input file: "..filename.." not found") end + bytes = getInputBytes(filename) - if (bytes == false) then return oops('couldnt get input bytes') - else + + if ~bytes then return oops('couldnt get input bytes') end + -- make plain bytes bytes = xorBytes(bytes,bytes[5]) print("create virtual tag from ".. #bytes .. " bytes") @@ -611,8 +616,7 @@ function readFile(filename) -- load plain bytes to tag-table print(acoff) tag=bytesToTag(bytes, tag) - end - end + return tag end @@ -705,8 +709,11 @@ end --- -- toggle higligh function toggleHighlight(tbl) - if (tbl['highlight']) then tbl['highlight']=false - else tbl['highlight']=true end + if (tbl['highlight']) then + tbl['highlight'] = false + else + tbl['highlight'] = true + end return tbl end @@ -1300,8 +1307,11 @@ function dumpTable(tab, header, tstart, tend) for i=tstart, tend do res=res..tab[i].." " end - if (string.len(header)==0) then return res - else return (header.." #"..(tend-tstart+1).."\n"..res) end + if (#header == 0) then + return res + else + return (header.." #"..(tend-tstart+1).."\n"..res) + end end --- @@ -1346,7 +1356,9 @@ end --- -- dump Legic-Cash data function dumpLegicCash(tag, x) - if (istable(tag.SEG[x])) then + + if ~istable(tag.SEG[x]) then return end + io.write("in Segment "..tag.SEG[x].index.." :\n") print("--------------------------------\n\tLegic-Cash Values\n--------------------------------") local limit, curr, balance, rid, tcv @@ -1366,12 +1378,13 @@ function dumpLegicCash(tag, x) print("Transaction Counter:\t "..tcv) print("Reader-ID:\t\t "..rid.."\n--------------------------------\n") end -end --- -- raw 3rd-party function print3rdPartyCash1(tag, x) - if (istable(tag.SEG[x])) then + + if ~istable(tag.SEG[x]) then return end + local uid=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 print("\n\t\tStamp : "..dumpTable(tag.SEG[x].data, "", 0 , 2)) print("\t\tBlock 0: "..dumpTable(tag.SEG[x].data, "", 3 , 18)) @@ -1408,7 +1421,6 @@ function print3rdPartyCash1(tag, x) print() print("\t\tBlock 8: "..dumpTable(tag.SEG[x].data, "", 90, 94)) end -end --- Token related -- --- @@ -1687,17 +1699,20 @@ end --- -- edit Segment Data function editSegmentData(data) - local lc=check4LegicCash(data) io.write("\n") - if (istable(data)) then + if ~istable(data) then + print("no Segment-Data found") + end + + local lc = check4LegicCash(data) + for i=0, #data-1 do data[i]=input(accyan.."Data"..i..acoff..": ", data[i]) end - if (lc) then data=fixLegicCash(data) end - return data - else - print("no Segment-Data found") + if (lc) then + data = fixLegicCash(data) end + return data end --- @@ -2140,7 +2155,7 @@ function calcKghCrc(tag, segid) end --- --- check all segmnet-crc +-- check all segment-crc function checkAllSegCrc(tag) if (istable(tag.SEG[0])) then for i=0, #tag.SEG do @@ -2266,8 +2281,11 @@ function modifyMode() -- load file into mainTAG ["lf"] = function(x) - if (type(x)=='string' and file_check(x)) then filename=x - else filename=input("enter filename: ", "legic.temp") end + if (type(x)=='string' and file_check(x)) then + filename = x + else + filename = input("enter filename: ", "legic.temp") + end inTAG=readFile(filename) -- check for existing tagMap if (file_check(filename..".map")) then @@ -2369,8 +2387,11 @@ function modifyMode() --- -- dump single segment ["ds"] = function(x) - if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) - else sel=selectSegment(inTAG) end + if (type(x)=="string" and string.len(x)>0) then + sel = tonumber(x,10) + else + sel = selectSegment(inTAG) + end if (sel) then print("\n"..(dumpSegment(inTAG, sel) or acred.."no Segments available") ..acoff.."\n") end end, --- @@ -2382,7 +2403,9 @@ function modifyMode() if(istable(inTAG.SEG[0])) then inTAG=editSegment(inTAG, sel) inTAG.SEG[sel]=regenSegmentHeader(inTAG.SEG[sel]) - else print(acyellow.."no Segments in Tag"..acoff) end + else + print(acyellow.."no Segments in Tag"..acoff) + end end end, --- @@ -2437,10 +2460,16 @@ function modifyMode() -- toggle kgh-crc-flag on a single segment ["tk"] = function(x) if (istable(inTAG) and istable(inTAG.SEG[0])) then - if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) - else sel=selectSegment(inTAG) end - if(inTAG.SEG[sel].kgh) then inTAG.SEG[sel].kgh=false - else inTAG.SEG[sel].kgh=true end + if (type(x)=="string" and string.len(x)>0) then + sel = tonumber(x,10) + else + sel = selectSegment(inTAG) + end + if(inTAG.SEG[sel].kgh) then + inTAG.SEG[sel].kgh = false + else + inTAG.SEG[sel].kgh = true + end end end, --- @@ -2458,16 +2487,22 @@ function modifyMode() -- print string for LegicCrc8-calculation about single segment ["xc"] = function(x) if (istable(inTAG) and istable(inTAG.SEG[0])) then - if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) - else sel=selectSegment(inTAG) end + if (type(x)=="string" and string.len(x)>0) then + sel = tonumber(x,10) + else + sel = selectSegment(inTAG) + end print("k "..kghCrcCredentials(inTAG, sel)) end end, --- -- fix legic-cash checksums ["flc"] = function(x) - if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) - else x=selectSegment(inTAG) end + if (type(x)=="string" and string.len(x)>0) then + x = tonumber(x,10) + else + x = selectSegment(inTAG) + end inTAG.SEG[x].data=fixLegicCash(inTAG.SEG[x].data) end, --- @@ -2483,8 +2518,10 @@ function modifyMode() if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) + else -- or try to find match - else x=autoSelectSegment(inTAG, "legiccash") end + x = autoSelectSegment(inTAG, "legiccash") + end -- dump it dumpLegicCash(inTAG, x) end, @@ -2496,8 +2533,10 @@ function modifyMode() if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) + else -- or try to find match - else x=autoSelectSegment(inTAG, "3rdparty") end + x = autoSelectSegment(inTAG, "3rdparty") + end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 if (check43rdPartyCash1(uid, inTAG.SEG[x].data)) then @@ -2513,8 +2552,10 @@ function modifyMode() if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) + else -- or try to find match - else x=autoSelectSegment(inTAG, "3rdparty") end + x = autoSelectSegment(inTAG, "3rdparty") + end print3rdPartyCash1(inTAG, x) end, --- @@ -2525,8 +2566,11 @@ function modifyMode() if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) + + else -- or try to find match - else x=autoSelectSegment(inTAG, "3rdparty") end + x = autoSelectSegment(inTAG, "3rdparty") + end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then inTAG=edit3rdPartyCash1(inTAG, x) dump3rdPartyCash1(inTAG, x) @@ -2535,8 +2579,11 @@ function modifyMode() --- -- force fixing 3rd-party-checksums ["f3p"] = function(x) - if(type(x)=="string" and string.len(x)>=2) then x=tonumber(x, 10) - else x=selectSegment(inTAG) end + if(type(x)=="string" and string.len(x)>=2) then + x = tonumber(x, 10) + else + x = selectSegment(inTAG) + end if (istable(inTAG.SEG[x])) then local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 inTAG.SEG[x].data=fix3rdPartyCash1(uid, inTAG.SEG[x].data) @@ -2545,8 +2592,11 @@ function modifyMode() --- -- get stamp from single segment ["gs"] = function(x) - if(type(x)=="string" and string.len(x)>=2) then x=tonumber(x, 10) - else x=selectSegment(inTAG) end + if(type(x)=="string" and string.len(x)>=2) then + x = tonumber(x, 10) + else + x = selectSegment(inTAG) + end local stamp=getSegmentStamp(inTAG.SEG[x]) print("Stamp : "..stamp) stamp=str2bytes(stamp) @@ -2592,7 +2642,9 @@ function modifyMode() actions[string.lower(string.sub(ic,0,2))](string.sub(ic,4)) elseif (type(actions[string.lower(string.sub(ic,0,1))])=='function') then actions[string.lower(string.sub(ic,0,1))](string.sub(ic,3)) - else actions.h('') end + else + actions.h('') + end until (string.sub(ic,0,1)=="q") end @@ -2617,26 +2669,38 @@ function main(args) -- dump virtual-Tag if o == "d" then dfs=true end -- interacive modifying - if o == "m" then interactive=true; modifyMode() end + if o == "m" then + interactive = true + modifyMode() + end -- xor (e.g. for clone or plain file) - if o == "c" then cfs=true; crc=a end + if o == "c" then + cfs = true + crc = a + end -- output file - if o == "o" then outfile=a; ofs=true end + if o == "o" then + outfile = a + ofs = true + end end -- file conversion (output to file) - if (ofs) then + if ~ofs then return end + -- dump infile / tag-read if (dfs) then print("-----------------------------------------") print(dumpTag(inTAG)) end + bytes=tagToBytes(inTAG) if (cfs) then -- xor willl be done in function writeFile -- with the value of byte[5] bytes[5]=crc end + -- write to outfile if (bytes) then writeFile(bytes, outfile) @@ -2650,10 +2714,9 @@ function main(args) print(dumpTag(inTAG)) end end - end end --- -- script start -main(args) +main(args) \ No newline at end of file diff --git a/client/snooper.c b/client/snooper.c index 36c80ce65..e1a350e7b 100644 --- a/client/snooper.c +++ b/client/snooper.c @@ -8,9 +8,8 @@ // Snooper binary //----------------------------------------------------------------------------- -#include "sleep.h" +#include "util_posix.h" #include "ui.h" -//#include "proxusb.h" #include "cmdmain.h" #define HANDLE_ERROR if (error_occured) { \ diff --git a/client/util.c b/client/util.c index 6f9609888..436b6a060 100644 --- a/client/util.c +++ b/client/util.c @@ -30,16 +30,16 @@ #include int ukbhit(void) { - int cnt = 0; - int error; - static struct termios Otty, Ntty; + int cnt = 0; + int error; + static struct termios Otty, Ntty; - if ( tcgetattr(STDIN_FILENO, &Otty) == -1) return -1; + if ( tcgetattr(STDIN_FILENO, &Otty) == -1) return -1; - Ntty = Otty; + Ntty = Otty; - Ntty.c_iflag = 0x0000; // input mode - Ntty.c_oflag = 0x0000; // output mode + Ntty.c_iflag = 0x0000; // input mode + Ntty.c_oflag = 0x0000; // output mode Ntty.c_lflag &= ~ICANON; // control mode = raw Ntty.c_cc[VMIN] = 1; // return if at least 1 character is in the queue Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever @@ -47,9 +47,8 @@ int ukbhit(void) { if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) { // set new attributes error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters available error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes - } - - return ( error == 0 ? cnt : -1 ); + } + return ( error == 0 ? cnt : -1 ); } #else diff --git a/client/util_posix.c b/client/util_posix.c index dd3d714c5..42bfd6b6f 100644 --- a/client/util_posix.c +++ b/client/util_posix.c @@ -106,7 +106,7 @@ void msleep(uint32_t n) { // a milliseconds timer for performance measurement -uint64_t msclock() { +uint64_t msclock(void) { #if defined(_WIN32) #include diff --git a/common/default_version.c b/common/default_version.c index 9f818beda..b564681c7 100644 --- a/common/default_version.c +++ b/common/default_version.c @@ -2,7 +2,7 @@ /* This is the default version.c file that Makefile.common falls back to if perl is not available */ const struct version_information __attribute__((section(".version_information"))) version_information = { VERSION_INFORMATION_MAGIC, - 1, /* version version 1 */ + 1, /* version 1 */ 0, /* version information not present */ 2, /* cleanliness couldn't be determined */ /* Remaining fields: zero */ diff --git a/common/lfdemod.c b/common/lfdemod.c index c1a2e8a2f..91e59e087 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -20,12 +20,16 @@ // the source. // // There are 4 main sections of code below: +// // Utilities Section: // for general utilities used by multiple other functions +// // Clock / Bitrate Detection Section: // for clock detection functions for each modulation +// // Modulation Demods &/or Decoding Section: // for main general modulation demodulating and encoding decoding code. +// // Tag format detection section: // for detection of specific tag formats within demodulated data // @@ -47,7 +51,7 @@ //to allow debug print calls when used not on device void dummy(char *fmt, ...){} #ifndef ON_DEVICE -# include "ui.h" // plotclock, plotclockstartindex +#include "ui.h" # include "cmdparser.h" # include "cmddata.h" # define prnt PrintAndLog @@ -58,17 +62,16 @@ void dummy(char *fmt, ...){} //test samples are not just noise uint8_t justNoise(uint8_t *bits, size_t size) { - #define THRESHOLD 123 + uint8_t val = 1; for(size_t idx = 0; idx < size && val; idx++) - val = bits[idx] < THRESHOLD; + val = bits[idx] < FSK_PSK_THRESHOLD; return val; } //by marshmellow //get high and low values of a wave with passed in fuzz factor. also return noise test = 1 for passed or 0 for only noise -int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) -{ +int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { *high=0; *low=255; // get high and low thresholds @@ -92,30 +95,28 @@ bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType) { //by marshmellow // takes a array of binary values, start position, length of bits per parity (includes parity bit - MAX 32), // Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) -size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) -{ +size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) { uint32_t parityWd = 0; - size_t j = 0, bitCnt = 0; + size_t bitCnt = 0; for (int word = 0; word < (bLen); word += pLen){ for (int bit=0; bit < pLen; bit++){ if (word+bit >= bLen) break; parityWd = (parityWd << 1) | BitStream[startIdx+word+bit]; - BitStream[j++] = (BitStream[startIdx+word+bit]); + BitStream[bitCnt++] = (BitStream[startIdx+word+bit]); } if (word+pLen > bLen) break; - j--; // overwrite parity with next data + bitCnt--; // overwrite parity with next data // if parity fails then return 0 switch (pType) { - case 3: if (BitStream[j]==1) { return 0; } break; //should be 0 spacer bit - case 2: if (BitStream[j]==0) { return 0; } break; //should be 1 spacer bit + case 3: if (BitStream[bitCnt]==1) {return 0;} break; //should be 0 spacer bit + case 2: if (BitStream[bitCnt]==0) {return 0;} break; //should be 1 spacer bit default: if (parityTest(parityWd, pLen, pType) == 0) { return 0; } break; //test parity } - bitCnt += (pLen-1); parityWd = 0; } // if we got here then all the parities passed - //return ID start index and size + //return size return bitCnt; } @@ -123,8 +124,7 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p // takes a array of binary values, length of bits per parity (includes parity bit), // Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run) // Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added -size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) -{ +size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) { uint32_t parityWd = 0; size_t j = 0, bitCnt = 0; for (int word = 0; word < sourceLen; word+=pLen-1) { @@ -132,7 +132,6 @@ size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t p parityWd = (parityWd << 1) | BitSource[word+bit]; dest[j++] = (BitSource[word+bit]); } - // if parity fails then return 0 switch (pType) { case 3: dest[j++]=0; break; // marker bit which should be a 0 @@ -170,21 +169,20 @@ uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits) } //by marshmellow -// search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) +//search for given preamble in given BitStream and return success = TRUE or fail = FALSE and startIndex and length bool preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx){ return preambleSearchEx(BitStream, preamble, pLen, size, startIdx, false); } //by marshmellow -//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length -// param @findone: look for a repeating preamble or only the first. -// em4x05/4x69 only sends preamble once, so look for it once in the first pLen bits +// search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) and length if not fineone +// fineone does not look for a repeating preamble for em4x05/4x69 sends preamble once, so look for it once in the first pLen bits bool preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone) { // Sanity check. If preamble length is bigger than bitstream length. if ( *size <= pLen ) return false; uint8_t foundCnt = 0; - for (int idx = 0; idx < *size - pLen; idx++){ + for (size_t idx = 0; idx < *size - pLen; idx++) { if (memcmp(BitStream+idx, preamble, pLen) == 0){ if (g_debugMode) prnt("DEBUG: preamble found at %i", idx); //first index found @@ -203,18 +201,18 @@ bool preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t } // find start of modulating data (for fsk and psk) in case of beginning noise or slow chip startup. -size_t findModStart(uint8_t dest[], size_t size, uint8_t threshold_value, uint8_t expWaveSize) { +size_t findModStart(uint8_t dest[], size_t size, uint8_t expWaveSize) { size_t i = 0; size_t waveSizeCnt = 0; uint8_t thresholdCnt = 0; - bool isAboveThreshold = dest[i++] >= threshold_value; + bool isAboveThreshold = dest[i++] >= FSK_PSK_THRESHOLD; for (; i < size-20; i++ ) { - if(dest[i] < threshold_value && isAboveThreshold) { + if(dest[i] < FSK_PSK_THRESHOLD && isAboveThreshold) { thresholdCnt++; if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; isAboveThreshold = false; waveSizeCnt = 0; - } else if (dest[i] >= threshold_value && !isAboveThreshold) { + } else if (dest[i] >= FSK_PSK_THRESHOLD && !isAboveThreshold) { thresholdCnt++; if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; isAboveThreshold = true; @@ -228,1121 +226,1320 @@ size_t findModStart(uint8_t dest[], size_t size, uint8_t threshold_value, uint8_ return i; } -//by marshmellow -//takes 1s and 0s and searches for EM410x format - output EM ID -// actually, no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future -int Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo) -{ - // sanity check - if (*size < 64) return -3; - if (BitStream[1] > 1) return -1; - - uint8_t fmtlen; - *startIdx = 0; - - // preamble 0111111111 - // include 0 in front to help get start pos - uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1}; - if (!preambleSearch(BitStream, preamble, sizeof(preamble), size, startIdx)) - return -2; +int getClosestClock(int testclk) { + uint8_t clocks[] = {8,16,32,40,50,64,128}; - //XL and normal size. - if (*size != 64 && *size != 128) return -3; - - fmtlen = (*size == 128) ? 22 : 10; + for (uint8_t i = 0; i < 7; i++) + if ( testclk >= clocks[i] - (clocks[i]/8) && testclk <= clocks[i]+1 ) + return clocks[i]; - //skip last 4bit parity row for simplicity - *size = removeParity(BitStream, *startIdx + sizeof(preamble), 5, 0, fmtlen * 5); - - switch (*size) { - case 40: { - // std em410x format - *hi = 0; - *lo = ((uint64_t)(bytebits_to_byte(BitStream, 8)) << 32) | (bytebits_to_byte(BitStream + 8, 32)); - break; - } - case 88: { - // long em format - *hi = (bytebits_to_byte(BitStream, 24)); - *lo = ((uint64_t)(bytebits_to_byte(BitStream + 24, 32)) << 32) | (bytebits_to_byte(BitStream + 24 + 32, 32)); - break; - } - default: return -4; - } - return 1; + return 0; } -//by marshmellow -//demodulates strong heavily clipped samples -//RETURN: num of errors. if 0, is ok. -int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low) -{ - size_t bitCnt=0, smplCnt=0, errCnt=0; - uint8_t waveHigh = 0; - for (size_t i=0; i < *size; i++){ - if (BinStream[i] >= high && waveHigh){ - smplCnt++; - } else if (BinStream[i] <= low && !waveHigh){ - smplCnt++; - } else { //transition - if ((BinStream[i] >= high && !waveHigh) || (BinStream[i] <= low && waveHigh)){ - - if (smplCnt > clk-(clk/4)-1) { //full clock - if (smplCnt > clk + (clk/4)+1) { //too many samples - errCnt++; - if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i); - BinStream[bitCnt++] = 7; - } else if (waveHigh) { - BinStream[bitCnt++] = invert; - BinStream[bitCnt++] = invert; - } else if (!waveHigh) { - BinStream[bitCnt++] = invert ^ 1; - BinStream[bitCnt++] = invert ^ 1; - } - waveHigh ^= 1; - smplCnt = 0; - } else if (smplCnt > (clk/2) - (clk/4)-1) { - if (waveHigh) { - BinStream[bitCnt++] = invert; - } else if (!waveHigh) { - BinStream[bitCnt++] = invert ^ 1; - } - waveHigh ^= 1; - smplCnt = 0; - } else if (!bitCnt) { - //first bit - waveHigh = (BinStream[i] >= high); - smplCnt = 1; - } else { - smplCnt++; - //transition bit oops - } - } else { //haven't hit new high or new low yet - smplCnt++; - } - } - } - *size = bitCnt; - return errCnt; +void getNextLow(uint8_t samples[], size_t size, int low, size_t *i) { + while ((samples[*i] > low) && (*i < size)) + *i+=1; } -//by marshmellow -void askAmp(uint8_t *BitStream, size_t size) -{ - uint8_t last = 128; - for(size_t i = 1; i < size; ++i){ - if (BitStream[i]-BitStream[i-1] >= 30) //large jump up - last = 255; - else if(BitStream[i-1] - BitStream[i] >= 20) //large jump down - last = 0; - - BitStream[i] = last; - } +void getNextHigh(uint8_t samples[], size_t size, int high, size_t *i) { + while ((samples[*i] < high) && (*i < size)) + *i+=1; } -//by marshmellow -//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester -int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType) -{ - if (*size==0) return -1; - int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default - if (*clk==0 || start < 0) return -3; - if (*invert != 1) *invert = 0; - if (amp==1) askAmp(BinStream, *size); - if (g_debugMode==2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); - - uint8_t initLoopMax = 255; - if (initLoopMax > *size) initLoopMax = *size; - // Detect high and lows - //25% clip in case highs and lows aren't clipped [marshmellow] - int high, low; - if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) - return -2; //just noise +// load wave counters +bool loadWaveCounters(uint8_t samples[], size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low) { + size_t i=0, firstLow, firstHigh; + size_t testsize = (size < 512) ? size : 512; - size_t errCnt = 0; - // if clean clipped waves detected run alternate demod - if (DetectCleanAskWave(BinStream, *size, high, low)) { - if (g_debugMode==2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod"); - errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low); - if (askType) //askman - return manrawdecode(BinStream, size, 0); - //askraw - return errCnt; + if ( getHiLo(samples, testsize, high, low, 80, 80) == -1 ) { + if (g_debugMode==2) prnt("DEBUG STT: just noise detected - quitting"); + return false; //just noise } - if (g_debugMode==2) prnt("DEBUG ASK: Weak Wave Detected - using weak wave demod"); - int lastBit; //set first clock check - can go negative - size_t i, bitnum = 0; //output counter - uint8_t midBit = 0; - uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave - if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely - size_t MaxBits = 3072; //max bits to collect - lastBit = start - *clk; + // get to first full low to prime loop and skip incomplete first pulse + getNextHigh(samples, size, *high, &i); + getNextLow(samples, size, *low, &i); + *skip = i; - for (i = start; i < *size; ++i) { - if (i-lastBit >= *clk-tol){ - if (BinStream[i] >= high) { - BinStream[bitnum++] = *invert; - } else if (BinStream[i] <= low) { - BinStream[bitnum++] = *invert ^ 1; - } else if (i-lastBit >= *clk+tol) { - if (bitnum > 0) { - if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i); - BinStream[bitnum++]=7; - errCnt++; - } - } else { //in tolerance - looking for peak - continue; - } - midBit = 0; - lastBit += *clk; - } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){ - if (BinStream[i] >= high) { - BinStream[bitnum++] = *invert; - } else if (BinStream[i] <= low) { - BinStream[bitnum++] = *invert ^ 1; - } else if (i-lastBit >= *clk/2+tol) { - BinStream[bitnum] = BinStream[bitnum-1]; - bitnum++; - } else { //in tolerance - looking for peak - continue; - } - midBit = 1; + // populate tmpbuff buffer with pulse lengths + while (i < size) { + // measure from low to low + firstLow = i; + //find first high point for this wave + getNextHigh(samples, size, *high, &i); + firstHigh = i; + + getNextLow(samples, size, *low, &i); + + if (*waveCnt >= (size/LOWEST_DEFAULT_CLOCK)) + break; + + highToLowWaveLen[*waveCnt] = i - firstHigh; //first high to first low + lowToLowWaveLen[*waveCnt] = i - firstLow; + *waveCnt += 1; + if (i-firstLow < *minClk && i < size) { + *minClk = i - firstLow; } - if (bitnum >= MaxBits) break; } - *size = bitnum; - return errCnt; + return true; } -//by marshmellow -//take 10 and 01 and manchester decode -//run through 2 times and take least errCnt -int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert){ - // sanity check - if (*size < 16) return -1; - - int errCnt = 0, bestErr = 1000; - uint16_t bitnum = 0, MaxBits = 512, bestRun = 0; - size_t i, k; +size_t pskFindFirstPhaseShift(uint8_t samples[], size_t size, uint8_t *curPhase, size_t waveStart, uint16_t fc, uint16_t *fullWaveLen) { + uint16_t loopCnt = (size+3 < 4096) ? size : 4096; //don't need to loop through entire array... - //find correct start position [alignment] - for (k = 0; k < 2; ++k){ - for (i = k; i < *size-3; i += 2) { - if (BitStream[i] == BitStream[i+1]) - errCnt++; - } - if (bestErr > errCnt){ - bestErr = errCnt; - bestRun = k; + uint16_t avgWaveVal=0, lastAvgWaveVal=0; + size_t i = waveStart, waveEnd, waveLenCnt, firstFullWave; + for (; i= samples[i+2]){ + waveEnd = i+1; + if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u", waveEnd, waveStart); + waveLenCnt = waveEnd-waveStart; + if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+8)){ //not first peak and is a large wave but not out of whack + lastAvgWaveVal = avgWaveVal/(waveLenCnt); + firstFullWave = waveStart; + *fullWaveLen = waveLenCnt; + //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting) + if (lastAvgWaveVal > FSK_PSK_THRESHOLD) *curPhase ^= 1; + return firstFullWave; + } + waveStart = i+1; + avgWaveVal = 0; } - errCnt = 0; + avgWaveVal += samples[i+2]; } - - //decode - for (i = bestRun; i < *size-3; i += 2){ - if (BitStream[i] == 1 && (BitStream[i+1] == 0)){ - BitStream[bitnum++] = invert; - } else if ((BitStream[i] == 0) && BitStream[i+1] == 1){ - BitStream[bitnum++] = invert^1; - } else { - BitStream[bitnum++] = 7; - } - if (bitnum > MaxBits) break; + return 0; +} + +//by marshmellow +//amplify based on ask edge detection - not accurate enough to use all the time +void askAmp(uint8_t *bits, size_t size) { + uint8_t last = 128; + for(size_t i = 1; i < size; ++i){ + if ( bits[i] - bits[i-1] >= 30) //large jump up + last = 255; + else if ( bits[i-1] - bits[i] >= 20) //large jump down + last = 0; + + bits[i] = last; } - *size = bitnum; - return bestErr; } +// iceman, simplify this uint32_t manchesterEncode2Bytes(uint16_t datain) { uint32_t output = 0; uint8_t curBit = 0; - for (uint8_t i=0; i<16; i++) { + for (uint8_t i = 0; i < 16; i++) { curBit = (datain >> (15-i) & 1); - output |= (1<<(((15-i)*2)+curBit)); + output |= ( 1 << ( ( (15-i) * 2 ) + curBit)); } return output; } //by marshmellow //encode binary data into binary manchester -//NOTE: BitStream must have triple the size of "size" available in memory to do the swap -int ManchesterEncode(uint8_t *BitStream, size_t size) { - //allow up to 4K out (means BitStream must be at least 2048+4096 to handle the swap) - size = (size>2048) ? 2048 : size; +//NOTE: bitstream must have triple the size of "size" available in memory to do the swap +int ManchesterEncode(uint8_t *bits, size_t size) { + //allow up to 4096b out (means bits must be at least 2048+4096 to handle the swap) + size = (size > 2048) ? 2048 : size; size_t modIdx = size; size_t i; for (size_t idx=0; idx < size; idx++){ - BitStream[idx+modIdx++] = BitStream[idx]; - BitStream[idx+modIdx++] = BitStream[idx]^1; + bits[idx+modIdx++] = bits[idx]; + bits[idx+modIdx++] = bits[idx]^1; } - for (i=0; i<(size*2); i++){ - BitStream[i] = BitStream[i+size]; + for (i=0; i < (size*2); i++){ + bits[i] = bits[i+size]; } return i; } -//by marshmellow -//take 01 or 10 = 1 and 11 or 00 = 0 -//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010 -//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding -int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert) -{ - uint16_t bitnum = 0; - uint16_t errCnt = 0; - size_t i = offset; - uint16_t MaxBits=512; - //if not enough samples - error - if (*size < 51) return -1; - //check for phase change faults - skip one sample if faulty - uint8_t offsetA = 1, offsetB = 1; - for (; i<48; i+=2){ - if (BitStream[i+1]==BitStream[i+2]) offsetA=0; - if (BitStream[i+2]==BitStream[i+3]) offsetB=0; +// by marshmellow +// to detect a wave that has heavily clipped (clean) samples +uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low) { + bool allArePeaks = true; + uint16_t cntPeaks = 0; + size_t loopEnd = 512 + 160; + + // sanity check + if (loopEnd > size) loopEnd = size; + + for (size_t i = 160; i < loopEnd; i++){ + + if (dest[i] > low && dest[i] < high) + allArePeaks = false; + else + cntPeaks++; } - if (!offsetA && offsetB) offset++; - for (i=offset; i<*size-3; i+=2){ - //check for phase error - if (BitStream[i+1]==BitStream[i+2]) { - BitStream[bitnum++]=7; - errCnt++; - } - if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){ - BitStream[bitnum++]=1^invert; - } else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){ - BitStream[bitnum++]=invert; - } else { - BitStream[bitnum++]=7; - errCnt++; - } - if(bitnum>MaxBits) break; + if (!allArePeaks){ + if (cntPeaks > 300) return true; } - *size=bitnum; - return errCnt; + return allArePeaks; } -// by marshmellow -// demod gProxIIDemod -// error returns as -x -// success returns start position in BitStream -// BitStream must contain previously askrawdemod and biphasedemoded data -int gProxII_Demod(uint8_t BitStream[], size_t *size) -{ - size_t startIdx=0; - uint8_t preamble[] = {1,1,1,1,1,0}; - if (!preambleSearch(BitStream, preamble, sizeof(preamble), size, &startIdx)) - return -3; //preamble not found +//********************************************************************************************** +//-------------------Clock / Bitrate Detection Section------------------------------------------ +//********************************************************************************************** - if (*size != 96) return -2; //should have found 96 bits - - //check first 6 spacer bits to verify format - if (!BitStream[startIdx+5] && !BitStream[startIdx+10] && !BitStream[startIdx+15] && !BitStream[startIdx+20] && !BitStream[startIdx+25] && !BitStream[startIdx+30]){ - //confirmed proper separator bits found - //return start position - return (int) startIdx; - } - return -5; //spacer bits not found - not a valid gproxII -} - -//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq]) -size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow) -{ - size_t last_transition = 0; - size_t idx = 1; - if (fchigh==0) fchigh=10; - if (fclow==0) fclow=8; - //set the threshold close to 0 (graph) or 128 std to avoid static - uint8_t threshold_value = 123; - size_t preLastSample = 0; - size_t LastSample = 0; - size_t currSample = 0; - if ( size < 1024 ) return 0; // not enough samples - //find start of modulating data in trace - idx = findModStart(dest, size, threshold_value, fchigh); +// by marshmellow +// to help detect clocks on heavily clipped samples +// based on count of low to low +int DetectStrongAskClock(uint8_t dest[], size_t size, int high, int low, int *clock) { + size_t startwave; + size_t i = 100; + size_t minClk = 255; + int shortestWaveIdx = 0; - // Need to threshold first sample - if(dest[idx] < threshold_value) dest[0] = 0; - else dest[0] = 1; - idx++; + // get to first full low to prime loop and skip incomplete first pulse + getNextHigh(dest, size, high, &i); + getNextLow(dest, size, low, &i); - 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 anywhere - // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10 - // (could also be fc/5 && fc/7 for fsk1 = 4-9) - for(; idx < size-20; idx++) { - // threshold current value + // loop through all samples + while (i < size) { + // measure from low to low + startwave= i; - if (dest[idx] < threshold_value) dest[idx] = 0; - else dest[idx] = 1; + getNextHigh(dest, size, high, &i); + getNextLow(dest, size, low, &i); + + //get minimum measured distance + if (i-startwave < minClk && i < size) { + minClk = i - startwave; + shortestWaveIdx = startwave; + } + } + + // set clock + if (g_debugMode==2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d", minClk); + *clock = getClosestClock(minClk); + if (*clock == 0) + return 0; + + return shortestWaveIdx; +} - // Check for 0->1 transition - if (dest[idx-1] < dest[idx]) { - preLastSample = LastSample; - LastSample = currSample; - currSample = idx-last_transition; - if (currSample < (fclow-2)){ //0-5 = garbage noise (or 0-3) - //do nothing with extra garbage - } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5) - //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5) - if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){ - dest[numBits-1]=1; - } - dest[numBits++]=1; +// by marshmellow +// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping) +// maybe somehow adjust peak trimming value based on samples to fix? +// return start index of best starting position for that clock and return clock (by reference) +int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) { + size_t i = 1; + uint8_t clk[] = {255,8,16,32,40,50,64,100,128,255}; + uint8_t clkEnd = 9; + uint8_t loopCnt = 255; //don't need to loop through entire array... + if (size <= loopCnt + 60) return -1; //not enough samples + size -= 60; //sometimes there is a strange end wave - filter out this.... + //if we already have a valid clock + uint8_t clockFnd = 0; + for (; i < clkEnd; ++i) + if (clk[i] == *clock) clockFnd = i; + //clock found but continue to find best startpos - } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage - //do nothing with beginning garbage and reset.. should be rare.. - numBits = 0; - } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's) - dest[numBits++]=1; - } else { //9+ = 10 sample waves (or 6+ = 7) - dest[numBits++]=0; + //get high and low peak + int peak, low; + if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1; + + //test for large clean peaks + if (!clockFnd){ + if (DetectCleanAskWave(dest, size, peak, low)==1){ + int ans = DetectStrongAskClock(dest, size, peak, low, clock); + if (g_debugMode==2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i", clock ,ans); + if (ans > 0){ + return ans; //return shortest wave start position } - last_transition = idx; } } - return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0 -} + uint8_t ii; + uint8_t clkCnt, tol = 0; + uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000}; + uint8_t bestStart[]={0,0,0,0,0,0,0,0,0}; + size_t errCnt = 0; + size_t arrLoc, loopEnd; -//translate 11111100000 to 10 -//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock -size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen, - uint8_t invert, uint8_t fchigh, uint8_t fclow) -{ - uint8_t lastval=dest[0]; - size_t idx=0; - size_t numBits=0; - uint32_t n=1; - for( idx=1; idx < size; idx++) { - n++; - if (dest[idx]==lastval) continue; //skip until we hit a transition - - //find out how many bits (n) we collected - //if lastval was 1, we have a 1->0 crossing - if (dest[idx-1]==1) { - n = (n * fclow + rfLen/2) / rfLen; - } else {// 0->1 crossing - n = (n * fchigh + rfLen/2) / rfLen; - } - if (n == 0) n = 1; + if (clockFnd > 0) { + clkCnt = clockFnd; + clkEnd = clockFnd+1; + } else { + clkCnt = 1; + } - //add to our destination the bits we collected - memset(dest+numBits, dest[idx-1]^invert , n); - numBits += n; - n=0; - lastval=dest[idx]; - }//end for - // if valid extra bits at the end were all the same frequency - add them in - if (n > rfLen/fchigh) { - if (dest[idx-2]==1) { - n = (n * fclow + rfLen/2) / rfLen; + //test each valid clock from smallest to greatest to see which lines up + for (; clkCnt < clkEnd; clkCnt++) { + if (clk[clkCnt] <= 32) { + tol=1; } else { - n = (n * fchigh + rfLen/2) / rfLen; + tol=0; } - memset(dest+numBits, dest[idx-1]^invert , n); - numBits += n; - } - return numBits; -} - -//by marshmellow (from holiman's base) -// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod) -int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow) -{ - // FSK demodulator - size = fsk_wave_demod(dest, size, fchigh, fclow); - size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow); - return size; -} + //if no errors allowed - keep start within the first clock + if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt]<128) + loopCnt = clk[clkCnt] * 2; -// loop to get raw HID waveform then FSK demodulate the TAG ID from it -int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo) -{ - if (justNoise(dest, *size)) return -1; + bestErr[clkCnt] = 1000; - size_t numStart=0, size2 = *size, startIdx=0; - // FSK demodulator - *size = fskdemod(dest, size2,50,1,10,8); //fsk2a - if (*size < 96*2) return -2; - // 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 - uint8_t preamble[] = {0,0,0,1,1,1,0,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -3; //preamble not found + //try lining up the peaks by moving starting point (try first few clocks) + for (ii=0; ii < loopCnt; ii++){ + if (dest[ii] < peak && dest[ii] > low) continue; - numStart = startIdx + sizeof(preamble); - // final loop, go over previously decoded FSK data and manchester decode into usable tag ID - for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){ - if (dest[idx] == dest[idx+1]){ - return -4; //not manchester data + errCnt = 0; + // now that we have the first one lined up test rest of wave array + loopEnd = ((size-ii-tol) / clk[clkCnt]) - 1; + for (i=0; i < loopEnd; ++i){ + arrLoc = ii + (i * clk[clkCnt]); + if (dest[arrLoc] >= peak || dest[arrLoc] <= low){ + }else if (dest[arrLoc-tol] >= peak || dest[arrLoc-tol] <= low){ + }else if (dest[arrLoc+tol] >= peak || dest[arrLoc+tol] <= low){ + }else{ //error no peak detected + errCnt++; + } + } + //if we found no errors then we can stop here and a low clock (common clocks) + // this is correct one - return this clock + if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, ii, i); + if (errCnt==0 && clkCnt<7) { + if (!clockFnd) *clock = clk[clkCnt]; + return ii; + } + //if we found errors see if it is lowest so far and save it as best run + if (errCnt < bestErr[clkCnt]) { + bestErr[clkCnt] = errCnt; + bestStart[clkCnt] = ii; + } } - *hi2 = (*hi2<<1)|(*hi>>31); - *hi = (*hi<<1)|(*lo>>31); - //Then, shift in a 0 or one into low - *lo <<= 1; - if (dest[idx] && !dest[idx+1]) // 1 0 - *lo |= 1; - else // 0 1 - *lo |= 0; } - return (int)startIdx; + uint8_t k; + uint8_t best = 0; + for (k=1; k < clkEnd; ++k){ + if (bestErr[k] < bestErr[best]){ + if (bestErr[k] == 0) bestErr[k]=1; + // current best bit to error ratio vs new bit to error ratio + if ( (size/clk[best])/bestErr[best] < (size/clk[k])/bestErr[k] ){ + best = k; + } + } + if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); + } + if (!clockFnd) *clock = clk[best]; + + return bestStart[best]; } -// loop to get raw paradox waveform then FSK demodulate the TAG ID from it -int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo) -{ - if (justNoise(dest, *size)) return -1; - - size_t numStart=0, size2 = *size, startIdx=0; - // FSK demodulator - *size = fskdemod(dest, size2,50,1,10,8); //fsk2a - if (*size < 96) return -2; +int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low, bool *strong) { + //find shortest transition from high to low + *strong = false; + size_t i = 0; + size_t transition1 = 0; + int lowestTransition = 255; + bool lastWasHigh = false; + size_t transitionSampleCount = 0; + //find first valid beginning of a high or low wave + while ((dest[i] >= peak || dest[i] <= low) && (i < size)) + ++i; + while ((dest[i] < peak && dest[i] > low) && (i < size)) + ++i; + lastWasHigh = (dest[i] >= peak); - // 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 - uint8_t preamble[] = {0,0,0,0,1,1,1,1}; - if (preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -3; //preamble not found + if (i==size) return 0; + transition1 = i; - numStart = startIdx + sizeof(preamble); - // final loop, go over previously decoded FSK data and manchester decode into usable tag ID - for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){ - if (dest[idx] == dest[idx+1]) - return -4; //not manchester data - *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)|1; - else // 0 1 - *lo=(*lo<<1)|0; + for (;i < size; i++) { + if ((dest[i] >= peak && !lastWasHigh) || (dest[i] <= low && lastWasHigh)) { + lastWasHigh = (dest[i] >= peak); + if (i-transition1 < lowestTransition) lowestTransition = i-transition1; + transition1 = i; + } else if (dest[i] < peak && dest[i] > low) { + transitionSampleCount++; + } } - return (int)startIdx; -} + if (lowestTransition == 255) lowestTransition = 0; + if (g_debugMode==2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d",lowestTransition); + // if less than 10% of the samples were not peaks (or 90% were peaks) then we have a strong wave + if (transitionSampleCount / size < 10) { + *strong = true; + lowestTransition = getClosestClock(lowestTransition); + } + return lowestTransition; +} -int IOdemodFSK(uint8_t *dest, size_t size) -{ - if (justNoise(dest, size)) return -1; - //make sure buffer has data - if (size < 66*64) return -2; - // FSK demodulator - size = fskdemod(dest, size, 64, 1, 10, 8); // FSK2a RF/64 - if (size < 65) return -3; //did we get a good demod? - //Index map - //0 10 20 30 40 50 60 - //| | | | | | | - //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 - //----------------------------------------------------------------------------- - //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 - // - //XSF(version)facility:codeone+codetwo - //Handle the data - size_t startIdx = 0; - uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,1}; - if (! preambleSearch(dest, preamble, sizeof(preamble), &size, &startIdx)) - return -4; //preamble not found +//by marshmellow +//detect nrz clock by reading #peaks vs no peaks(or errors) +int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx) { + size_t i = 0; + uint8_t clk[] = {8,16,32,40,50,64,100,128,255}; + size_t loopCnt = 4096; //don't need to loop through entire array... - if (!dest[startIdx+8] && dest[startIdx+17]==1 && dest[startIdx+26]==1 && dest[startIdx+35]==1 && dest[startIdx+44]==1 && dest[startIdx+53]==1){ - //confirmed proper separator bits found - //return start position - return (int) startIdx; + //if we already have a valid clock quit + for (; i < 8; ++i) + if (clk[i] == clock) return clock; + + if (size < 20) return 0; + // size must be larger than 20 here + if (size < loopCnt) loopCnt = size-20; + + //get high and low peak + int peak, low; + if (getHiLo(dest, loopCnt, &peak, &low, 90, 90) < 1) return 0; + + bool strong = false; + int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low, &strong); + if (strong) return lowestTransition; + size_t ii; + uint8_t clkCnt; + uint8_t tol = 0; + uint16_t smplCnt = 0; + int16_t peakcnt = 0; + int16_t peaksdet[] = {0,0,0,0,0,0,0,0}; + uint16_t minPeak = 255; + bool firstpeak = true; + //test for large clipped waves - ignore first peak + for (i=0; i= peak || dest[i] <= low){ + if (firstpeak) continue; + smplCnt++; + } else { + firstpeak = false; + if (smplCnt > 0) { + if (minPeak > smplCnt && smplCnt > 7) minPeak = smplCnt; + peakcnt++; + if (g_debugMode == 2) prnt("DEBUG NRZ: minPeak: %d, smplCnt: %d, peakcnt: %d",minPeak,smplCnt,peakcnt); + smplCnt = 0; + } + } } - return -5; + if (minPeak < 8) return 0; + bool errBitHigh = 0; + bool bitHigh = 0; + uint8_t ignoreCnt = 0; + uint8_t ignoreWindow = 4; + bool lastPeakHigh = 0; + int lastBit = 0; + size_t bestStart[]={0,0,0,0,0,0,0,0,0}; + peakcnt = 0; + //test each valid clock from smallest to greatest to see which lines up + for(clkCnt=0; clkCnt < 8; ++clkCnt){ + //ignore clocks smaller than smallest peak + if (clk[clkCnt] < minPeak - (clk[clkCnt]/4)) continue; + //try lining up the peaks by moving starting point (try first 256) + for (ii=20; ii < loopCnt; ++ii){ + if ((dest[ii] >= peak) || (dest[ii] <= low)){ + peakcnt=0; + bitHigh = false; + ignoreCnt = 0; + lastBit = ii-clk[clkCnt]; + //loop through to see if this start location works + for (i = ii; i < size-20; ++i) { + //if we are at a clock bit + if ((i >= lastBit + clk[clkCnt] - tol) && (i <= lastBit + clk[clkCnt] + tol)) { + //test high/low + if (dest[i] >= peak || dest[i] <= low) { + //if same peak don't count it + if ((dest[i] >= peak && !lastPeakHigh) || (dest[i] <= low && lastPeakHigh)) { + peakcnt++; + } + lastPeakHigh = (dest[i] >= peak); + bitHigh = true; + errBitHigh = false; + ignoreCnt = ignoreWindow; + lastBit += clk[clkCnt]; + } else if (i == lastBit + clk[clkCnt] + tol) { + lastBit += clk[clkCnt]; + } + //else if not a clock bit and no peaks + } else if (dest[i] < peak && dest[i] > low){ + if (ignoreCnt == 0){ + bitHigh=false; + if (errBitHigh==true) peakcnt--; + errBitHigh=false; + } else { + ignoreCnt--; + } + // else if not a clock bit but we have a peak + } else if ((dest[i]>=peak || dest[i]<=low) && (!bitHigh)) { + //error bar found no clock... + errBitHigh=true; + } + } + if (peakcnt > peaksdet[clkCnt]) { + bestStart[clkCnt]=ii; + peaksdet[clkCnt] = peakcnt; + } + } + } + } + + uint8_t best = 0; + for (int m = 7; m > 0; m--){ + if ((peaksdet[m] >= (peaksdet[best]-1)) && (peaksdet[m] <= peaksdet[best]+1) && lowestTransition) { + if (clk[m] > (lowestTransition - (clk[m]/8)) && clk[m] < (lowestTransition + (clk[m]/8))) { + best = m; + } + } else if (peaksdet[m] > peaksdet[best]){ + best = m; + } + if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d", clk[m], peaksdet[m], minPeak, clk[best], lowestTransition); + } + *clockStartIdx = bestStart[best]; + return clk[best]; } -// by marshmellow -// find viking preamble 0xF200 in already demoded data -int VikingDemod_AM(uint8_t *dest, size_t *size) { - //make sure buffer has data - if (*size < 64*2) return -2; - size_t startIdx = 0; - uint8_t preamble[] = {1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -4; //preamble not found +//by marshmellow +//countFC is to detect the field clock lengths. +//counts and returns the 2 most common wave lengths +//mainly used for FSK field clock detection +uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj) { + uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t fcLensFnd = 0; + uint8_t lastFCcnt = 0; + uint8_t fcCounter = 0; + size_t i; + if (size < 180) return 0; + + // prime i to first up transition + for (i = 160; i < size-20; i++) + if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1]) + break; + + for (; i < size-20; i++){ + if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1]){ + // new up transition + fcCounter++; + if (fskAdj){ + //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8) + if (lastFCcnt==5 && fcCounter==9) fcCounter--; + //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5) + if ((fcCounter==9) || fcCounter==4) fcCounter++; + // save last field clock count (fc/xx) + lastFCcnt = fcCounter; + } + // find which fcLens to save it to: + for (int ii=0; ii<15; ii++){ + if (fcLens[ii]==fcCounter){ + fcCnts[ii]++; + fcCounter=0; + break; + } + } + if (fcCounter>0 && fcLensFnd<15){ + //add new fc length + fcCnts[fcLensFnd]++; + fcLens[fcLensFnd++]=fcCounter; + } + fcCounter=0; + } else { + // count sample + fcCounter++; + } + } - uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ - bytebits_to_byte(dest+startIdx+8,8) ^ - bytebits_to_byte(dest+startIdx+16,8) ^ - bytebits_to_byte(dest+startIdx+24,8) ^ - bytebits_to_byte(dest+startIdx+32,8) ^ - bytebits_to_byte(dest+startIdx+40,8) ^ - bytebits_to_byte(dest+startIdx+48,8) ^ - bytebits_to_byte(dest+startIdx+56,8); - if ( checkCalc != 0xA8 ) return -5; - if (*size != 64) return -6; - //return start position - return (int)startIdx; -} + uint8_t best1=14, best2=14, best3=14; + uint16_t maxCnt1=0; + // go through fclens and find which ones are bigest 2 + for (i=0; i<15; i++){ + // get the 3 best FC values + if (fcCnts[i]>maxCnt1) { + best3=best2; + best2=best1; + maxCnt1=fcCnts[i]; + best1=i; + } else if(fcCnts[i]>fcCnts[best2]){ + best3=best2; + best2=i; + } else if(fcCnts[i]>fcCnts[best3]){ + best3=i; + } + if (g_debugMode==2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]); + if (fcLens[i]==0) break; + } + if (fcLens[best1]==0) return 0; + uint8_t fcH=0, fcL=0; + if (fcLens[best1]>fcLens[best2]){ + fcH=fcLens[best1]; + fcL=fcLens[best2]; + } else{ + fcH=fcLens[best2]; + fcL=fcLens[best1]; + } + if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) { + if (g_debugMode==2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]); + return 0; //lots of waves not psk or fsk + } + // TODO: take top 3 answers and compare to known Field clocks to get top 2 -// by iceman -// find Visa2000 preamble in already demoded data -int Visa2kDemod_AM(uint8_t *dest, size_t *size) { - if (*size < 96) return -1; //make sure buffer has data - size_t startIdx = 0; - uint8_t preamble[] = {0,1,0,1,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,1,0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 96) return -3; //wrong demoded size - //return start position - return (int)startIdx; -} -// by iceman -// find Noralsy preamble in already demoded data -int NoralsyDemod_AM(uint8_t *dest, size_t *size) { - if (*size < 96) return -1; //make sure buffer has data - size_t startIdx = 0; - uint8_t preamble[] = {1,0,1,1,1,0,1,1,0,0,0,0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 96) return -3; //wrong demoded size - //return start position - return (int)startIdx; -} -// find presco preamble 0x10D in already demoded data -int PrescoDemod(uint8_t *dest, size_t *size) { - if (*size < 128*2) return -1; //make sure buffer has data - size_t startIdx = 0; - uint8_t preamble[] = {0,0,0,1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 128) return -3; //wrong demoded size - //return start position - return (int)startIdx; + uint16_t fcs = (((uint16_t)fcH)<<8) | fcL; + if (fskAdj) return fcs; + return (uint16_t)fcLens[best2] << 8 | fcLens[best1]; } -// Ask/Biphase Demod then try to locate an ISO 11784/85 ID -// BitStream must contain previously askrawdemod and biphasedemoded data -int FDXBdemodBI(uint8_t *dest, size_t *size) { - if (*size < 128*2) return -1; //make sure buffer has enough data - size_t startIdx = 0; - uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 128) return -3; //wrong demoded size - //return start position - return (int)startIdx; +//by marshmellow +//detect psk clock by reading each phase shift +// a phase shift is determined by measuring the sample length of each wave +int DetectPSKClock(uint8_t dest[], size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc) { + uint8_t clk[] = {255,16,32,40,50,64,100,128,255}; //255 is not a valid clock + uint16_t loopCnt = 4096; //don't need to loop through entire array... + + //if we already have a valid clock quit + size_t i=1; + for (; i < 8; ++i) + if (clk[i] == clock) return clock; + + if (size < 160+20) return 0; + // size must be larger than 20 here, and 160 later on. + if (size < loopCnt) loopCnt = size-20; + + uint16_t fcs = countFC(dest, size, 0); + *fc = fcs & 0xFF; + if (g_debugMode==2) prnt("DEBUG PSK: FC: %d, FC2: %d",*fc, fcs>>8); + if ((fcs>>8) == 10 && *fc == 8) return 0; + if (*fc!=2 && *fc!=4 && *fc!=8) return 0; + + + size_t waveStart=0, waveEnd=0, firstFullWave=0, lastClkBit=0; + + uint8_t clkCnt, tol=1; + uint16_t peakcnt=0, errCnt=0, waveLenCnt=0, fullWaveLen=0; + uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; + uint16_t peaksdet[] = {0,0,0,0,0,0,0,0,0}; + + //find start of modulating data in trace + i = findModStart(dest, size, *fc); + + firstFullWave = pskFindFirstPhaseShift(dest, size, curPhase, i, *fc, &fullWaveLen); + if (firstFullWave == 0) { + // no phase shift detected - could be all 1's or 0's - doesn't matter where we start + // so skip a little to ensure we are past any Start Signal + firstFullWave = 160; + fullWaveLen = 0; + } + + *firstPhaseShift = firstFullWave; + if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen); + + //test each valid clock from greatest to smallest to see which lines up + for (clkCnt=7; clkCnt >= 1 ; clkCnt--){ + tol = *fc/2; + lastClkBit = firstFullWave; //set end of wave as clock align + waveStart = 0; + errCnt=0; + peakcnt=0; + if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %d",clk[clkCnt],lastClkBit); + + for (i = firstFullWave+fullWaveLen-1; i < loopCnt-2; i++){ + //top edge of wave = start of new wave + if (dest[i] < dest[i+1] && dest[i+1] >= dest[i+2]){ + if (waveStart == 0) { + waveStart = i+1; + waveLenCnt=0; + } else { //waveEnd + waveEnd = i+1; + waveLenCnt = waveEnd-waveStart; + if (waveLenCnt > *fc){ + //if this wave is a phase shift + if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+clk[clkCnt]-tol,i+1,*fc); + if (i+1 >= lastClkBit + clk[clkCnt] - tol){ //should be a clock bit + peakcnt++; + lastClkBit+=clk[clkCnt]; + } else if (i lastClkBit + clk[clkCnt] + tol + *fc){ + lastClkBit+=clk[clkCnt]; //no phase shift but clock bit + } + waveStart=i+1; + } + } + } + if (errCnt == 0) return clk[clkCnt]; + if (errCnt <= bestErr[clkCnt]) bestErr[clkCnt] = errCnt; + if (peakcnt > peaksdet[clkCnt]) peaksdet[clkCnt] = peakcnt; + } + //all tested with errors + //return the highest clk with the most peaks found + uint8_t best = 7; + for (i=7; i >= 1; i--){ + if (peaksdet[i] > peaksdet[best]) + best = i; + + if (g_debugMode == 2) prnt("DEBUG PSK: Clk: %d, peaks: %d, errs: %d, bestClk: %d",clk[i],peaksdet[i],bestErr[i],clk[best]); + } + return clk[best]; } -// ASK/Diphase fc/64 (inverted Biphase) -// Note: this i s not a demod, this is only a detection -// the parameter *dest needs to be demoded before call -// 0xFFFF preamble, 64bits -int JablotronDemod(uint8_t *dest, size_t *size){ - if (*size < 64*2) return -1; //make sure buffer has enough data - size_t startIdx = 0; - uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 64) return -3; // wrong demoded size +//by marshmellow +//detects the bit clock for FSK given the high and low Field Clocks +uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge) { + uint8_t clk[] = {8,16,32,40,50,64,100,128,0}; + uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t rfLensFnd = 0; + uint8_t lastFCcnt = 0; + uint16_t fcCounter = 0; + uint16_t rfCounter = 0; + uint8_t firstBitFnd = 0; + size_t i; + if (size == 0) return 0; + + uint8_t fcTol = ((fcHigh*100 - fcLow*100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2); + rfLensFnd=0; + fcCounter=0; + rfCounter=0; + firstBitFnd=0; + //prnt("DEBUG: fcTol: %d",fcTol); + // prime i to first peak / up transition + for (i = 160; i < size-20; i++) + if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1]) + break; + + for (; i < size-20; i++){ + fcCounter++; + rfCounter++; + + if (BitStream[i] <= BitStream[i-1] || BitStream[i] < BitStream[i+1]) + continue; + // else new peak + // if we got less than the small fc + tolerance then set it to the small fc + // if it is inbetween set it to the last counter + if (fcCounter < fcHigh && fcCounter > fcLow) + fcCounter = lastFCcnt; + else if (fcCounter < fcLow+fcTol) + fcCounter = fcLow; + else //set it to the large fc + fcCounter = fcHigh; + + //look for bit clock (rf/xx) + if ((fcCounter < lastFCcnt || fcCounter > lastFCcnt)){ + //not the same size as the last wave - start of new bit sequence + if (firstBitFnd > 1){ //skip first wave change - probably not a complete bit + for (int ii=0; ii<15; ii++){ + if (rfLens[ii] >= (rfCounter-4) && rfLens[ii] <= (rfCounter+4)){ + rfCnts[ii]++; + rfCounter = 0; + break; + } + } + if (rfCounter > 0 && rfLensFnd < 15){ + //prnt("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter); + rfCnts[rfLensFnd]++; + rfLens[rfLensFnd++] = rfCounter; + } + } else { + *firstClockEdge = i; + firstBitFnd++; + } + rfCounter=0; + lastFCcnt=fcCounter; + } + fcCounter=0; + } + uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15; + + for (i=0; i<15; i++){ + //get highest 2 RF values (might need to get more values to compare or compare all?) + if (rfCnts[i]>rfCnts[rfHighest]){ + rfHighest3=rfHighest2; + rfHighest2=rfHighest; + rfHighest=i; + } else if(rfCnts[i]>rfCnts[rfHighest2]){ + rfHighest3=rfHighest2; + rfHighest2=i; + } else if(rfCnts[i]>rfCnts[rfHighest3]){ + rfHighest3=i; + } + if (g_debugMode==2) prnt("DEBUG FSK: RF %d, cnts %d",rfLens[i], rfCnts[i]); + } + // set allowed clock remainder tolerance to be 1 large field clock length+1 + // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off + uint8_t tol1 = fcHigh+1; - uint8_t checkchksum = 0; - for (int i=16; i < 56; i += 8) { - checkchksum += bytebits_to_byte(dest+startIdx+i,8); + if (g_debugMode==2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d",rfLens[rfHighest],rfLens[rfHighest2],rfLens[rfHighest3]); + + // loop to find the highest clock that has a remainder less than the tolerance + // compare samples counted divided by + // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less) + int ii=7; + for (; ii>=2; ii--){ + if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){ + if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){ + if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){ + if (g_debugMode==2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]); + break; + } + } + } } - checkchksum ^= 0x3A; - uint8_t crc = bytebits_to_byte(dest+startIdx+56, 8); - if ( checkchksum != crc ) return -5; - return (int)startIdx; -} -// by marshmellow -// FSK Demod then try to locate an AWID ID -int AWIDdemodFSK(uint8_t *dest, size_t *size) -{ - //make sure buffer has enough data - if (*size < 96*50) return -1; + if (ii<2) return 0; // oops we went too far - if (justNoise(dest, *size)) return -2; + return clk[ii]; +} - // FSK demodulator - *size = fskdemod(dest, *size, 50, 1, 10, 8); // fsk2a RF/50 - if (*size < 96) return -3; //did we get a good demod? - uint8_t preamble[] = {0,0,0,0,0,0,0,1}; - size_t startIdx = 0; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -4; //preamble not found - if (*size != 96) return -5; - return (int)startIdx; -} +//********************************************************************************************** +//--------------------Modulation Demods &/or Decoding Section----------------------------------- +//********************************************************************************************** -// by marshmellow -// FSK Demod then try to locate a Farpointe Data (pyramid) ID -int PyramiddemodFSK(uint8_t *dest, size_t *size) -{ - //make sure buffer has data - if (*size < 128*50) return -5; - //test samples are not just noise - if (justNoise(dest, *size)) return -1; +// look for Sequence Terminator - should be pulses of clk*(1 or 2), clk*2, clk*(1.5 or 2), by idx we mean graph position index... +bool findST(int *stStopLoc, int *stStartIdx, int lowToLowWaveLen[], int highToLowWaveLen[], int clk, int tol, int buffSize, size_t *i) { + if (buffSize < *i+4) return false; - // FSK demodulator - *size = fskdemod(dest, *size, 50, 1, 10, 8); // fsk2a RF/50 - if (*size < 128) return -2; //did we get a good demod? - size_t startIdx = 0; - uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -4; //preamble not found - if (*size != 128) return -3; - return (int)startIdx; + for (; *i < buffSize - 4; *i+=1) { + *stStartIdx += lowToLowWaveLen[*i]; //caution part of this wave may be data and part may be ST.... to be accounted for in main function for now... + if (lowToLowWaveLen[*i] >= clk*1-tol && lowToLowWaveLen[*i] <= (clk*2)+tol && highToLowWaveLen[*i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior + if (lowToLowWaveLen[*i+1] >= clk*2-tol && lowToLowWaveLen[*i+1] <= clk*2+tol && highToLowWaveLen[*i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2 + if (lowToLowWaveLen[*i+2] >= (clk*3)/2-tol && lowToLowWaveLen[*i+2] <= clk*2+tol && highToLowWaveLen[*i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave + if (lowToLowWaveLen[*i+3] >= clk*1-tol && lowToLowWaveLen[*i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit + *stStopLoc = *i + 3; + return true; + } + } + } + } + } + return false; } +//by marshmellow +//attempt to identify a Sequence Terminator in ASK modulated raw wave +bool DetectST(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend) { + size_t bufsize = *size; + //need to loop through all samples and identify our clock, look for the ST pattern + int clk = 0; + int tol = 0; + int j=0, high, low, skip=0, start=0, end=0, minClk=255; + size_t i = 0; + //probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow] + int tmpbuff[bufsize / LOWEST_DEFAULT_CLOCK]; // low to low wave count //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured + int waveLen[bufsize / LOWEST_DEFAULT_CLOCK]; // high to low wave count //if clock is larger then we waste memory in array size that is not needed... + //size_t testsize = (bufsize < 512) ? bufsize : 512; + int phaseoff = 0; + high = low = 128; + memset(tmpbuff, 0, sizeof(tmpbuff)); + memset(waveLen, 0, sizeof(waveLen)); -// find nedap preamble in already demoded data -int NedapDemod(uint8_t *dest, size_t *size) { - //make sure buffer has data - if (*size < 128) return -3; + if (!loadWaveCounters(buffer, bufsize, tmpbuff, waveLen, &j, &skip, &minClk, &high, &low)) return false; + // set clock - might be able to get this externally and remove this work... + clk = getClosestClock(minClk); + // clock not found - ERROR + if (!clk) { + if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting"); + return false; + } + *foundclock = clk; - size_t startIdx = 0; - //uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,0,0,0,1}; - uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -4; //preamble not found - return (int) startIdx; -} + tol = clk/8; + if (!findST(&start, &skip, tmpbuff, waveLen, clk, tol, j, &i)) { + // first ST not found - ERROR + if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting"); + return false; + } else { + if (g_debugMode==2) prnt("DEBUG STT: first STT found at wave: %i, skip: %i, j=%i", start, skip, j); + } + if (waveLen[i+2] > clk*1+tol) + phaseoff = 0; + else + phaseoff = clk/2; + + // skip over the remainder of ST + skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point -// Find IDTEC PSK1, RF Preamble == 0x4944544B, Demodsize 64bits -// by iceman -int IdteckDemodPSK(uint8_t *dest, size_t *size) { - //make sure buffer has data - if (*size < 64*2) return -1; - size_t startIdx = 0; - uint8_t preamble[] = {0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,1,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 64) return -3; // wrong demoded size - return (int) startIdx; + // now do it again to find the end + int dummy1 = 0; + end = skip; + i+=3; + if (!findST(&dummy1, &end, tmpbuff, waveLen, clk, tol, j, &i)) { + //didn't find second ST - ERROR + if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting"); + return false; + } + end -= phaseoff; + if (g_debugMode==2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff); + //now begin to trim out ST so we can use normal demod cmds + start = skip; + size_t datalen = end - start; + // check validity of datalen (should be even clock increments) - use a tolerance of up to 1/8th a clock + if ( clk - (datalen % clk) <= clk/8) { + // padd the amount off - could be problematic... but shouldn't happen often + datalen += clk - (datalen % clk); + } else if ( (datalen % clk) <= clk/8 ) { + // padd the amount off - could be problematic... but shouldn't happen often + datalen -= datalen % clk; + } else { + if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk); + return false; + } + // if datalen is less than one t55xx block - ERROR + if (datalen/clk < 8*4) { + if (g_debugMode==2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); + return false; + } + size_t dataloc = start; + if (buffer[dataloc-(clk*4)-(clk/4)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) { + //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start + for ( i=0; i <= (clk/4); ++i ) { + if ( buffer[dataloc - (clk*4) - i] <= low ) { + dataloc -= i; + break; + } + } + } + + size_t newloc = 0; + i=0; + if (g_debugMode==2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen); + bool firstrun = true; + // warning - overwriting buffer given with raw wave data with ST removed... + while ( dataloc < bufsize-(clk/2) ) { + //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part) + if (buffer[dataloc]low && buffer[dataloc+clk/4]low) { + for(i=0; i < clk/2-tol; ++i) { + buffer[dataloc+i] = high+5; + } + } //test for small spike outlier (high between two lows) in the case of very strong waves + if (buffer[dataloc] > low && buffer[dataloc+clk/4] <= low) { + for(i=0; i < clk/4; ++i) { + buffer[dataloc+i] = buffer[dataloc+clk/4]; + } + } + if (firstrun) { + *stend = dataloc; + *ststart = dataloc-(clk*4); + firstrun=false; + } + for (i=0; i size) loopEnd = size; - for (size_t i=160; ilow && dest[i] 300) return true; + // for now error if alignment not found. later add option to run it with multiple offsets... + if (alignCnt != 4) { + if (g_debugMode) prnt("ERROR MillerDecode: alignment not found so either your bitstream is not miller or your data does not have a 101 in it"); + return -1; } - return allArePeaks; -} + alignedIdx = (i-1) % 2; + for (i=alignedIdx; i < *size-3; i+=2) { + halfClkErr = (uint8_t)((halfClkErr << 1 | BitStream[i]) & 0xFF); + if ( (halfClkErr & 0x7) == 5 || (halfClkErr & 0x7) == 2 || (i > 2 && (halfClkErr & 0x7) == 0) || (halfClkErr & 0x1F) == 0x1F) { + errCnt++; + BitStream[bitCnt++] = 7; + continue; + } + BitStream[bitCnt++] = BitStream[i] ^ BitStream[i+1] ^ invert; -//********************************************************************************************** -//-------------------Clock / Bitrate Detection Section------------------------------------------ -//********************************************************************************************** + if (bitCnt > MaxBits) break; + } + *size = bitCnt; + return errCnt; +} -// by marshmellow -// to help detect clocks on heavily clipped samples -// based on count of low to low -int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low, int *clock) -{ - uint8_t clocks[] = {8,16,32,40,50,64,128}; - size_t startwave; - size_t i = 100; - size_t minClk = 255; - int shortestWaveIdx = 0; - // get to first full low to prime loop and skip incomplete first pulse - while ((dest[i] < high) && (i < size)) - ++i; - while ((dest[i] > low) && (i < size)) - ++i; +//by marshmellow +//take 01 or 10 = 1 and 11 or 00 = 0 +//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010 +//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding +int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) { + //sanity check + if (*size < 51) return -1; + + uint16_t bitnum = 0; + uint16_t errCnt = 0; + size_t i = *offset; + uint16_t maxbits = 512; - // loop through all samples - while (i < size) { - // measure from low to low - while ((dest[i] > low) && (i < size)) - ++i; - startwave= i; - while ((dest[i] < high) && (i < size)) - ++i; - while ((dest[i] > low) && (i < size)) - ++i; - //get minimum measured distance - if (i-startwave < minClk && i < size) { - minClk = i - startwave; - shortestWaveIdx = startwave; + //check for phase change faults - skip one sample if faulty + bool offsetA = true, offsetB = true; + for (; i < *offset+48; i += 2){ + if (bits[i+1] == bits[i+2]) offsetA = false; + if (bits[i+2] == bits[i+3]) offsetB = false; + } + if (!offsetA && offsetB) ++*offset; + + for (i = *offset; i < *size-3; i += 2){ + //check for phase error + if (bits[i+1] == bits[i+2]) { + bits[bitnum++] = 7; + errCnt++; } - } - // set clock - if (g_debugMode==2) prnt("DEBUG ASK: detectstrongASKclk smallest wave: %d",minClk); - for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) { - if (minClk >= clocks[clkCnt]-(clocks[clkCnt]/8) && minClk <= clocks[clkCnt]+1) { - *clock = clocks[clkCnt]; - return shortestWaveIdx; + if((bits[i]==1 && bits[i+1]==0) || (bits[i]==0 && bits[i+1]==1)){ + bits[bitnum++] = 1 ^ invert; + } else if((bits[i]==0 && bits[i+1]==0) || (bits[i]==1 && bits[i+1]==1)){ + bits[bitnum++] = invert; + } else { + bits[bitnum++] = 7; + errCnt++; } + if (bitnum > maxbits) break; } - return 0; + *size = bitnum; + return errCnt; } -// by marshmellow -// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping) -// maybe somehow adjust peak trimming value based on samples to fix? -// return start index of best starting position for that clock and return clock (by reference) -int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) -{ - size_t i = 1; - uint8_t clk[] = {255,8,16,32,40,50,64,100,128,255}; - uint8_t clkEnd = 9; - uint8_t loopCnt = 255; //don't need to loop through entire array... - if (size <= loopCnt + 60) return -1; //not enough samples - size -= 60; //sometimes there is a strange end wave - filter out this.... - //if we already have a valid clock - uint8_t clockFnd = 0; - for (; i < clkEnd; ++i) - if (clk[i] == *clock) clockFnd = i; - //clock found but continue to find best startpos +//by marshmellow +//take 10 and 01 and manchester decode +//run through 2 times and take least errCnt +int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert, uint8_t *alignPos){ - //get high and low peak - int peak, low; - if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1; + // sanity check + if (*size < 16) return -1; - //test for large clean peaks - if (!clockFnd){ - if (DetectCleanAskWave(dest, size, peak, low)==1){ - int ans = DetectStrongAskClock(dest, size, peak, low, clock); - if (g_debugMode==2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i", clock ,ans); - if (ans > 0){ - return ans; // return shortest wave start pos - } - } - } - uint8_t ii; - uint8_t clkCnt, tol = 0; - uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000}; - uint8_t bestStart[]={0,0,0,0,0,0,0,0,0}; - size_t errCnt = 0; - size_t arrLoc, loopEnd; + int errCnt = 0, bestErr = 1000; + uint16_t bitnum = 0, MaxBits = 512, bestRun = 0; + size_t i, k; - if (clockFnd > 0) { - clkCnt = clockFnd; - clkEnd = clockFnd+1; - } else { - clkCnt = 1; + //find correct start position [alignment] + for (k = 0; k < 2; ++k){ + for (i = k; i < *size-3; i += 2) { + if (BitStream[i] == BitStream[i+1]) + errCnt++; + } + if (bestErr > errCnt){ + bestErr = errCnt; + bestRun = k; + } + errCnt = 0; } - - //test each valid clock from smallest to greatest to see which lines up - for (; clkCnt < clkEnd; clkCnt++) { - if (clk[clkCnt] <= 32) { - tol=1; + *alignPos = bestRun; + //decode + for (i = bestRun; i < *size-3; i += 2){ + if (BitStream[i] == 1 && (BitStream[i+1] == 0)){ + BitStream[bitnum++] = invert; + } else if ((BitStream[i] == 0) && BitStream[i+1] == 1){ + BitStream[bitnum++] = invert^1; } else { - tol=0; + BitStream[bitnum++] = 7; } - //if no errors allowed - keep start within the first clock - if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt]<128) - loopCnt = clk[clkCnt] * 2; - - bestErr[clkCnt] = 1000; + if (bitnum > MaxBits) break; + } + *size = bitnum; + return bestErr; +} - //try lining up the peaks by moving starting point (try first few clocks) - for (ii=0; ii < loopCnt; ii++){ - if (dest[ii] < peak && dest[ii] > low) continue; +//by marshmellow +//demodulates strong heavily clipped samples +//RETURN: num of errors. if 0, is ok. +int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low, int *startIdx) { + *startIdx=0; + size_t bitCnt=0, smplCnt=1, errCnt=0; + bool waveHigh = (BinStream[0] >= high); + for (size_t i=1; i < *size; i++){ + if (BinStream[i] >= high && waveHigh){ + smplCnt++; + } else if (BinStream[i] <= low && !waveHigh){ + smplCnt++; + } else { //transition + if ((BinStream[i] >= high && !waveHigh) || (BinStream[i] <= low && waveHigh)){ - errCnt = 0; - // now that we have the first one lined up test rest of wave array - loopEnd = ((size-ii-tol) / clk[clkCnt]) - 1; - for (i=0; i < loopEnd; ++i){ - arrLoc = ii + (i * clk[clkCnt]); - if (dest[arrLoc] >= peak || dest[arrLoc] <= low){ - }else if (dest[arrLoc-tol] >= peak || dest[arrLoc-tol] <= low){ - }else if (dest[arrLoc+tol] >= peak || dest[arrLoc+tol] <= low){ - }else{ //error no peak detected - errCnt++; + if (smplCnt > clk-(clk/4)-1) { //full clock + if (smplCnt > clk + (clk/4)+1) { //too many samples + errCnt++; + if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i); + BinStream[bitCnt++] = 7; + } else if (waveHigh) { + BinStream[bitCnt++] = invert; + BinStream[bitCnt++] = invert; + } else if (!waveHigh) { + BinStream[bitCnt++] = invert ^ 1; + BinStream[bitCnt++] = invert ^ 1; + } + if (*startIdx==0) *startIdx = i-clk; + waveHigh = !waveHigh; + smplCnt = 0; + } else if (smplCnt > (clk/2) - (clk/4)-1) { //half clock + if (waveHigh) { + BinStream[bitCnt++] = invert; + } else if (!waveHigh) { + BinStream[bitCnt++] = invert ^ 1; + } + if (*startIdx==0) *startIdx = i-(clk/2); + waveHigh = !waveHigh; + smplCnt = 0; + } else { + smplCnt++; + //transition bit oops } - } - //if we found no errors then we can stop here and a low clock (common clocks) - // this is correct one - return this clock - if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, ii, i); - if (errCnt==0 && clkCnt<7) { - if (!clockFnd) *clock = clk[clkCnt]; - return ii; - } - //if we found errors see if it is lowest so far and save it as best run - if (errCnt < bestErr[clkCnt]) { - bestErr[clkCnt] = errCnt; - bestStart[clkCnt] = ii; - } - } - } - uint8_t k; - uint8_t best = 0; - for (k=1; k < clkEnd; ++k){ - if (bestErr[k] < bestErr[best]){ - if (bestErr[k] == 0) bestErr[k]=1; - // current best bit to error ratio vs new bit to error ratio - if ( (size/clk[best])/bestErr[best] < (size/clk[k])/bestErr[k] ){ - best = k; + } else { //haven't hit new high or new low yet + smplCnt++; } } - if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); } - if (!clockFnd) *clock = clk[best]; - - return bestStart[best]; -} - -int DetectPSKClock(uint8_t dest[], size_t size, int clock) { - int firstPhaseShift = 0; - return DetectPSKClock_ext(dest, size, clock, &firstPhaseShift); + *size = bitCnt; + return errCnt; } //by marshmellow -//detect psk clock by reading each phase shift -// a phase shift is determined by measuring the sample length of each wave -int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseShift) { - uint8_t clk[] = {255,16,32,40,50,64,100,128,255}; //255 is not a valid clock - uint16_t loopCnt = 4096; //don't need to loop through entire array... - - //if we already have a valid clock quit - size_t i=1; - for (; i < 8; ++i) - if (clk[i] == clock) return clock; - - if (size < 160+20) return 0; - // size must be larger than 20 here, and 160 later on. - if (size < loopCnt) loopCnt = size-20; - - size_t waveStart=0, waveEnd=0, firstFullWave=0, lastClkBit=0; - uint8_t clkCnt, fc=0, fullWaveLen=0, tol=1; - uint16_t peakcnt=0, errCnt=0, waveLenCnt=0; - uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; - uint16_t peaksdet[] = {0,0,0,0,0,0,0,0,0}; - fc = countFC(dest, size, 0); - if (fc!=2 && fc!=4 && fc!=8) return -1; - if (g_debugMode==2) prnt("DEBUG PSK: FC: %d",fc); +//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester +int askdemod_ext(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx) { + if (*size==0) return -1; + int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default + if (*clk==0 || start < 0) return -3; + if (*invert != 1) *invert = 0; + if (amp==1) askAmp(BinStream, *size); + if (g_debugMode==2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); + + //start pos from detect ask clock is 1/2 clock offset + // NOTE: can be negative (demod assumes rest of wave was there) + *startIdx = start - (*clk/2); + uint8_t initLoopMax = 255; + if (initLoopMax > *size) initLoopMax = *size; + // Detect high and lows + //25% clip in case highs and lows aren't clipped [marshmellow] + int high, low; + if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) + return -2; //just noise - //find first full wave - for (i=160; i < loopCnt; i++){ - if (dest[i] < dest[i+1] && dest[i+1] >= dest[i+2]){ - if (waveStart == 0) { - waveStart = i+1; - //prnt("DEBUG: waveStart: %d",waveStart); - } else { - waveEnd = i+1; - //prnt("DEBUG: waveEnd: %d",waveEnd); - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc){ - firstFullWave = waveStart; - fullWaveLen=waveLenCnt; - break; - } - waveStart=0; - } + size_t errCnt = 0; + // if clean clipped waves detected run alternate demod + if (DetectCleanAskWave(BinStream, *size, high, low)) { + if (g_debugMode==2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod"); + errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low, startIdx); + if (askType) { //askman + uint8_t alignPos = 0; + errCnt = manrawdecode(BinStream, size, 0, &alignPos); + *startIdx += *clk/2 * alignPos; + if (g_debugMode) prnt("DEBUG ASK CLEAN: startIdx %i, alignPos %u", *startIdx, alignPos); + return errCnt; + } else { //askraw + return errCnt; } } - *firstPhaseShift = firstFullWave; - if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen); - - //test each valid clock from greatest to smallest to see which lines up - for (clkCnt=7; clkCnt >= 1 ; clkCnt--){ - lastClkBit = firstFullWave; //set end of wave as clock align - waveStart = 0; - errCnt=0; - peakcnt=0; - if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %d",clk[clkCnt],lastClkBit); + if (g_debugMode) prnt("DEBUG ASK WEAK: startIdx %i", *startIdx); + if (g_debugMode==2) prnt("DEBUG ASK: Weak Wave Detected - using weak wave demod"); - for (i = firstFullWave+fullWaveLen-1; i < loopCnt-2; i++){ - //top edge of wave = start of new wave - if (dest[i] < dest[i+1] && dest[i+1] >= dest[i+2]){ - if (waveStart == 0) { - waveStart = i+1; - waveLenCnt=0; - } else { //waveEnd - waveEnd = i+1; - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc){ - //if this wave is a phase shift - if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+clk[clkCnt]-tol,i+1,fc); - if (i+1 >= lastClkBit + clk[clkCnt] - tol){ //should be a clock bit - peakcnt++; - lastClkBit+=clk[clkCnt]; - } else if (i lastClkBit + clk[clkCnt] + tol + fc){ - lastClkBit+=clk[clkCnt]; //no phase shift but clock bit - } - waveStart=i+1; - } + int lastBit; //set first clock check - can go negative + size_t i, bitnum = 0; //output counter + uint8_t midBit = 0; + uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave + if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely + size_t MaxBits = 3072; //max bits to collect + lastBit = start - *clk; + + for (i = start; i < *size; ++i) { + if (i-lastBit >= *clk-tol){ + if (BinStream[i] >= high) { + BinStream[bitnum++] = *invert; + } else if (BinStream[i] <= low) { + BinStream[bitnum++] = *invert ^ 1; + } else if (i-lastBit >= *clk+tol) { + if (bitnum > 0) { + if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i); + BinStream[bitnum++]=7; + errCnt++; + } + } else { //in tolerance - looking for peak + continue; + } + midBit = 0; + lastBit += *clk; + } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){ + if (BinStream[i] >= high) { + BinStream[bitnum++] = *invert; + } else if (BinStream[i] <= low) { + BinStream[bitnum++] = *invert ^ 1; + } else if (i-lastBit >= *clk/2+tol) { + BinStream[bitnum] = BinStream[bitnum-1]; + bitnum++; + } else { //in tolerance - looking for peak + continue; } + midBit = 1; } - if (errCnt == 0) return clk[clkCnt]; - if (errCnt <= bestErr[clkCnt]) bestErr[clkCnt] = errCnt; - if (peakcnt > peaksdet[clkCnt]) peaksdet[clkCnt] = peakcnt; - } - //all tested with errors - //return the highest clk with the most peaks found - uint8_t best = 7; - for (i=7; i >= 1; i--){ - if (peaksdet[i] > peaksdet[best]) - best = i; - - if (g_debugMode == 2) prnt("DEBUG PSK: Clk: %d, peaks: %d, errs: %d, bestClk: %d",clk[i],peaksdet[i],bestErr[i],clk[best]); + if (bitnum >= MaxBits) break; } - return clk[best]; + *size = bitnum; + return errCnt; } -int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low){ - //find shortest transition from high to low - size_t i = 0; - size_t transition1 = 0; - int lowestTransition = 255; - bool lastWasHigh = false; - - //find first valid beginning of a high or low wave - while ((dest[i] >= peak || dest[i] <= low) && (i < size)) - ++i; - while ((dest[i] < peak && dest[i] > low) && (i < size)) - ++i; - lastWasHigh = (dest[i] >= peak); +int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType) { + int start = 0; + return askdemod_ext(BinStream, size, clk, invert, maxErr, amp, askType, &start); +} - if (i==size) return 0; - transition1 = i; +// by marshmellow - demodulate NRZ wave - requires a read with strong signal +// peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak +int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx) { + if (justNoise(dest, *size)) return -1; + size_t clkStartIdx = 0; + *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx); + if (*clk==0) return -2; + size_t i, gLen = 4096; + if (gLen>*size) gLen = *size-20; + int high, low; + if (getHiLo(dest, gLen, &high, &low, 75, 75) < 1) return -3; //25% fuzz on high 25% fuzz on low - for (;i < size; i++) { - if ((dest[i] >= peak && !lastWasHigh) || (dest[i] <= low && lastWasHigh)) { - lastWasHigh = (dest[i] >= peak); - if (i-transition1 < lowestTransition) lowestTransition = i-transition1; - transition1 = i; + uint8_t bit=0; + //convert wave samples to 1's and 0's + for(i=20; i < *size-20; i++){ + if (dest[i] >= high) bit = 1; + if (dest[i] <= low) bit = 0; + dest[i] = bit; + } + //now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit) + size_t lastBit = 0; + size_t numBits = 0; + for(i=21; i < *size-20; i++) { + //if transition detected or large number of same bits - store the passed bits + if (dest[i] != dest[i-1] || (i-lastBit) == (10 * *clk)) { + memset(dest+numBits, dest[i-1] ^ *invert, (i - lastBit + (*clk/4)) / *clk); + numBits += (i - lastBit + (*clk/4)) / *clk; + if (lastBit == 0) { + *startIdx = i - (numBits * *clk); + if (g_debugMode==2) prnt("DEBUG NRZ: startIdx %i", *startIdx); + } + lastBit = i-1; } } - if (lowestTransition == 255) lowestTransition = 0; - if (g_debugMode==2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d",lowestTransition); - return lowestTransition; -} - -int DetectNRZClock(uint8_t dest[], size_t size, int clock) { - int bestStart = 0; - return DetectNRZClock_ext(dest, size, clock, &bestStart); + *size = numBits; + return 0; } -//by marshmellow -//detect nrz clock by reading #peaks vs no peaks(or errors) -int DetectNRZClock_ext(uint8_t dest[], size_t size, int clock, int *clockStartIdx) { - size_t i = 0; - uint8_t clk[] = {8,16,32,40,50,64,100,128,255}; - size_t loopCnt = 4096; //don't need to loop through entire array... +//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq]) +size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow, int *startIdx) { + size_t last_transition = 0; + size_t idx = 1; + if (fchigh==0) fchigh=10; + if (fclow==0) fclow=8; + //set the threshold close to 0 (graph) or 128 std to avoid static + size_t preLastSample = 0; + size_t LastSample = 0; + size_t currSample = 0; + if ( size < 1024 ) return 0; // not enough samples - //if we already have a valid clock quit - for (; i < 8; ++i) - if (clk[i] == clock) return clock; + //find start of modulating data in trace + idx = findModStart(dest, size, fchigh); + // Need to threshold first sample + if(dest[idx] < FSK_PSK_THRESHOLD) dest[0] = 0; + else dest[0] = 1; - if (size < 20) return 0; - // size must be larger than 20 here - if (size < loopCnt) loopCnt = size-20; - - //get high and low peak - int peak, low; - if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return 0; + last_transition = idx; + idx++; + 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 anywhere + // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10 + // (could also be fc/5 && fc/7 for fsk1 = 4-9) + for(; idx < size-20; idx++) { + // threshold current value + if (dest[idx] < FSK_PSK_THRESHOLD) dest[idx] = 0; + else dest[idx] = 1; - int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low); - size_t ii; - uint8_t clkCnt; - uint8_t tol = 0; - uint16_t smplCnt = 0; - int16_t peakcnt = 0; - int16_t peaksdet[] = {0,0,0,0,0,0,0,0}; - uint16_t maxPeak = 255; - bool firstpeak = false; - //test for large clipped waves - for (i=0; i= peak || dest[i] <= low){ - if (!firstpeak) continue; - smplCnt++; - } else { - firstpeak = true; - if (smplCnt > 6 ){ - if (maxPeak > smplCnt){ - maxPeak = smplCnt; - //prnt("maxPk: %d",maxPeak); + // Check for 0->1 transition + if (dest[idx-1] < dest[idx]) { + preLastSample = LastSample; + LastSample = currSample; + currSample = idx-last_transition; + if (currSample < (fclow-2)){ //0-5 = garbage noise (or 0-3) + //do nothing with extra garbage + } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5) + //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5) + if (numBits > 1 && LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){ + dest[numBits-1]=1; } - peakcnt++; - //prnt("maxPk: %d, smplCnt: %d, peakcnt: %d",maxPeak,smplCnt,peakcnt); - smplCnt = 0; + dest[numBits++]=1; + if (numBits > 0 && *startIdx==0) *startIdx = idx - fclow; + } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage + //do nothing with beginning garbage and reset.. should be rare.. + numBits = 0; + } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's) + dest[numBits++]=1; + if (numBits > 0 && *startIdx==0) *startIdx = idx - fclow; + } else { //9+ = 10 sample waves (or 6+ = 7) + dest[numBits++]=0; + if (numBits > 0 && *startIdx==0) *startIdx = idx - fchigh; } + last_transition = idx; } } - bool errBitHigh = 0; - bool bitHigh = 0; - uint8_t ignoreCnt = 0; - uint8_t ignoreWindow = 4; - bool lastPeakHigh = 0; - int lastBit = 0; - int bestStart[] = {0,0,0,0,0,0,0,0,0}; - peakcnt = 0; - //test each valid clock from smallest to greatest to see which lines up - for(clkCnt=0; clkCnt < 8; ++clkCnt){ - //ignore clocks smaller than smallest peak - if (clk[clkCnt] < maxPeak - (clk[clkCnt]/4)) continue; - //try lining up the peaks by moving starting point (try first 256) - for (ii=20; ii < loopCnt; ++ii){ - if ((dest[ii] >= peak) || (dest[ii] <= low)){ - peakcnt=0; - bitHigh = false; - ignoreCnt = 0; - lastBit = ii-clk[clkCnt]; - //loop through to see if this start location works - for (i = ii; i < size-20; ++i) { - //if we are at a clock bit - if ((i >= lastBit + clk[clkCnt] - tol) && (i <= lastBit + clk[clkCnt] + tol)) { - //test high/low - if (dest[i] >= peak || dest[i] <= low) { - //if same peak don't count it - if ((dest[i] >= peak && !lastPeakHigh) || (dest[i] <= low && lastPeakHigh)) { - peakcnt++; - } - lastPeakHigh = (dest[i] >= peak); - bitHigh = true; - errBitHigh = false; - ignoreCnt = ignoreWindow; - lastBit += clk[clkCnt]; - } else if (i == lastBit + clk[clkCnt] + tol) { - lastBit += clk[clkCnt]; - } - //else if not a clock bit and no peaks - } else if (dest[i] < peak && dest[i] > low){ - if (ignoreCnt == 0){ - bitHigh=false; - if (errBitHigh==true) - peakcnt--; - errBitHigh=false; - } else { - ignoreCnt--; - } - // else if not a clock bit but we have a peak - } else if ((dest[i]>=peak || dest[i]<=low) && (!bitHigh)) { - //error bar found no clock... - errBitHigh=true; - } - } - if (peakcnt > peaksdet[clkCnt]) { - bestStart[clkCnt]=ii; - peaksdet[clkCnt] = peakcnt; - } - } + return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0 +} + +//translate 11111100000 to 10 +//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock +size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx) { + uint8_t lastval = dest[0]; + size_t idx=0; + size_t numBits=0; + uint32_t n=1; + for( idx=1; idx < size; idx++) { + n++; + if (dest[idx]==lastval) continue; //skip until we hit a transition + + //find out how many bits (n) we collected (use 1/2 clk tolerance) + //if lastval was 1, we have a 1->0 crossing + if (dest[idx-1]==1) { + n = (n * fclow + rfLen/2) / rfLen; + } else {// 0->1 crossing + n = (n * fchigh + rfLen/2) / rfLen; } - } + if (n == 0) n = 1; - uint8_t best = 0; - for (int m = 7; m > 0; m--){ - if ((peaksdet[m] >= (peaksdet[best]-1)) && (peaksdet[m] <= peaksdet[best]+1) && lowestTransition) { - if (clk[m] > (lowestTransition - (clk[m]/8)) && clk[m] < (lowestTransition + (clk[m]/8))) { - best = m; + //first transition - save startidx + if (numBits == 0) { + if (lastval == 1) { //high to low + *startIdx += (fclow * idx) - (n*rfLen); + if (g_debugMode==2) prnt("DEBUG FSK: startIdx %i, fclow*idx %i, n*rflen %u", *startIdx, fclow*(idx), n*rfLen); + } else { + *startIdx += (fchigh * idx) - (n*rfLen); + if (g_debugMode==2) prnt("DEBUG FSK: startIdx %i, fchigh*idx %i, n*rflen %u", *startIdx, fchigh*(idx), n*rfLen); } - } else if (peaksdet[m] > peaksdet[best]){ - best = m; } - if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, maxPeak: %d, bestClk: %d, lowestTrs: %d", clk[m], peaksdet[m], maxPeak, clk[best], lowestTransition); + + //add to our destination the bits we collected + memset(dest+numBits, dest[idx-1]^invert , n); + numBits += n; + n=0; + lastval=dest[idx]; + }//end for + // if valid extra bits at the end were all the same frequency - add them in + if (n > rfLen/fchigh) { + if (dest[idx-2]==1) { + n = (n * fclow + rfLen/2) / rfLen; + } else { + n = (n * fchigh + rfLen/2) / rfLen; + } + memset(dest+numBits, dest[idx-1]^invert , n); + numBits += n; } - *clockStartIdx = bestStart[best]; - return clk[best]; + return numBits; +} + +//by marshmellow (from holiman's base) +// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod) +size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx) { + if (justNoise(dest, size)) return 0; + // FSK demodulator + size = fsk_wave_demod(dest, size, fchigh, fclow, startIdx); + size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow, startIdx); + return size; } // by marshmellow @@ -1376,311 +1573,31 @@ void psk2TOpsk1(uint8_t *bits, size_t size) { } } -// redesigned by marshmellow adjusted from existing decode functions -// indala id decoding - only tested on 26 bit tags, but attempted to make it work for more -int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert) -{ - //26 bit 40134 format (don't know other formats) - uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; - uint8_t preamble_i[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}; - size_t startidx = 0; - if (!preambleSearch(bitStream, preamble, sizeof(preamble), size, &startidx)){ - // if didn't find preamble try again inverting - if (!preambleSearch(bitStream, preamble_i, sizeof(preamble_i), size, &startidx)) return -1; - *invert ^= 1; - } - if (*size != 64 && *size != 224) return -2; - if (*invert==1) - for (size_t i = startidx; i < *size; i++) - bitStream[i] ^= 1; - - return (int) startidx; -} - -// by marshmellow - demodulate NRZ wave - requires a read with strong signal -// peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak -int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert){ - if (justNoise(dest, *size)) return -1; - *clk = DetectNRZClock(dest, *size, *clk); - if (*clk==0) return -2; - size_t i, gLen = 4096; - if (gLen>*size) gLen = *size-20; - int high, low; - if (getHiLo(dest, gLen, &high, &low, 75, 75) < 1) return -3; //25% fuzz on high 25% fuzz on low - - uint8_t bit=0; - //convert wave samples to 1's and 0's - for(i=20; i < *size-20; i++){ - if (dest[i] >= high) bit = 1; - if (dest[i] <= low) bit = 0; - dest[i] = bit; - } - //now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit) - size_t lastBit = 0; - size_t numBits = 0; - for(i=21; i < *size-20; i++) { - //if transition detected or large number of same bits - store the passed bits - if (dest[i] != dest[i-1] || (i-lastBit) == (10 * *clk)) { - memset(dest+numBits, dest[i-1] ^ *invert, (i - lastBit + (*clk/4)) / *clk); - numBits += (i - lastBit + (*clk/4)) / *clk; - lastBit = i-1; - } - } - *size = numBits; - return 0; -} - -uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow) { - int firstClockEdge = 0; - return detectFSKClk_ext(BitStream, size, fcHigh, fcLow, &firstClockEdge); -} - -//by marshmellow -//detects the bit clock for FSK given the high and low Field Clocks -uint8_t detectFSKClk_ext(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge) { - uint8_t clk[] = {8,16,32,40,50,64,100,128,0}; - uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t rfLensFnd = 0; - uint8_t lastFCcnt = 0; - uint16_t fcCounter = 0; - uint16_t rfCounter = 0; - uint8_t firstBitFnd = 0; - size_t i; - if (size == 0) return 0; - - uint8_t fcTol = ((fcHigh*100 - fcLow*100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2); - rfLensFnd=0; - fcCounter=0; - rfCounter=0; - firstBitFnd=0; - //prnt("DEBUG: fcTol: %d",fcTol); - // prime i to first peak / up transition - for (i = 160; i < size-20; i++) - if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1]) - break; - - for (; i < size-20; i++){ - fcCounter++; - rfCounter++; - - if (BitStream[i] <= BitStream[i-1] || BitStream[i] < BitStream[i+1]) - continue; - // else new peak - // if we got less than the small fc + tolerance then set it to the small fc - // if it is inbetween set it to the last counter - if (fcCounter < fcHigh && fcCounter > fcLow) - fcCounter = lastFCcnt; - else if (fcCounter < fcLow+fcTol) - fcCounter = fcLow; - else //set it to the large fc - fcCounter = fcHigh; - - //look for bit clock (rf/xx) - if ((fcCounter < lastFCcnt || fcCounter > lastFCcnt)){ - //not the same size as the last wave - start of new bit sequence - if (firstBitFnd > 1){ //skip first wave change - probably not a complete bit - for (int ii=0; ii<15; ii++){ - if (rfLens[ii] >= (rfCounter-4) && rfLens[ii] <= (rfCounter+4)){ - rfCnts[ii]++; - rfCounter = 0; - break; - } - } - if (rfCounter > 0 && rfLensFnd < 15){ - //prnt("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter); - rfCnts[rfLensFnd]++; - rfLens[rfLensFnd++] = rfCounter; - } - } else { - *firstClockEdge = i; - firstBitFnd++; - } - rfCounter=0; - lastFCcnt=fcCounter; - } - fcCounter=0; - } - uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15; - - for (i=0; i<15; i++){ - //get highest 2 RF values (might need to get more values to compare or compare all?) - if (rfCnts[i]>rfCnts[rfHighest]){ - rfHighest3=rfHighest2; - rfHighest2=rfHighest; - rfHighest=i; - } else if(rfCnts[i]>rfCnts[rfHighest2]){ - rfHighest3=rfHighest2; - rfHighest2=i; - } else if(rfCnts[i]>rfCnts[rfHighest3]){ - rfHighest3=i; - } - if (g_debugMode==2) prnt("DEBUG FSK: RF %d, cnts %d",rfLens[i], rfCnts[i]); - } - // set allowed clock remainder tolerance to be 1 large field clock length+1 - // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off - uint8_t tol1 = fcHigh+1; - - if (g_debugMode==2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d",rfLens[rfHighest],rfLens[rfHighest2],rfLens[rfHighest3]); - - // loop to find the highest clock that has a remainder less than the tolerance - // compare samples counted divided by - // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less) - int ii=7; - for (; ii>=2; ii--){ - if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){ - if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){ - if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){ - if (g_debugMode==2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]); - break; - } - } - } - } - - if (ii<2) return 0; // oops we went too far - - return clk[ii]; -} - -//by marshmellow -//countFC is to detect the field clock lengths. -//counts and returns the 2 most common wave lengths -//mainly used for FSK field clock detection -uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj) -{ - uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t fcLensFnd = 0; - uint8_t lastFCcnt = 0; - uint8_t fcCounter = 0; - size_t i; - if (size < 180) return 0; - - // prime i to first up transition - for (i = 160; i < size-20; i++) - if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1]) - break; - - for (; i < size-20; i++){ - if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1]){ - // new up transition - fcCounter++; - if (fskAdj){ - //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8) - if (lastFCcnt==5 && fcCounter==9) fcCounter--; - //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5) - if ((fcCounter==9) || fcCounter==4) fcCounter++; - // save last field clock count (fc/xx) - lastFCcnt = fcCounter; - } - // find which fcLens to save it to: - for (int ii=0; ii<15; ii++){ - if (fcLens[ii]==fcCounter){ - fcCnts[ii]++; - fcCounter=0; - break; - } - } - if (fcCounter>0 && fcLensFnd<15){ - //add new fc length - fcCnts[fcLensFnd]++; - fcLens[fcLensFnd++]=fcCounter; - } - fcCounter=0; - } else { - // count sample - fcCounter++; - } - } - - uint8_t best1=14, best2=14, best3=14; - uint16_t maxCnt1=0; - // go through fclens and find which ones are bigest 2 - for (i=0; i<15; i++){ - // get the 3 best FC values - if (fcCnts[i]>maxCnt1) { - best3=best2; - best2=best1; - maxCnt1=fcCnts[i]; - best1=i; - } else if(fcCnts[i]>fcCnts[best2]){ - best3=best2; - best2=i; - } else if(fcCnts[i]>fcCnts[best3]){ - best3=i; - } - if (g_debugMode==2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]); - if (fcLens[i]==0) break; - } - if (fcLens[best1]==0) return 0; - uint8_t fcH=0, fcL=0; - if (fcLens[best1]>fcLens[best2]){ - fcH=fcLens[best1]; - fcL=fcLens[best2]; - } else{ - fcH=fcLens[best2]; - fcL=fcLens[best1]; - } - if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) { - if (g_debugMode==2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]); - return 0; //lots of waves not psk or fsk - } - // TODO: take top 3 answers and compare to known Field clocks to get top 2 - - uint16_t fcs = (((uint16_t)fcH)<<8) | fcL; - if (fskAdj) return fcs; - return (uint16_t)fcLens[best2] << 8 | fcLens[best1]; -} - //by marshmellow - demodulate PSK1 wave //uses wave lengths (# Samples) -int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) -{ - if (size == 0) return -1; +int pskRawDemod_ext(uint8_t dest[], size_t *size, int *clock, int *invert, int *startIdx) { + + // sanity check + if (*size < 170) return -1; + uint16_t loopCnt = 4096; //don't need to loop through entire array... - if (*size> 8; - if (fc2 == 10) return -1; //fsk found - quit - fc = fc & 0xFF; - if (fc!=2 && fc!=4 && fc!=8) return -1; - //prnt("DEBUG: FC: %d",fc); - *clock = DetectPSKClock(dest, *size, *clock); - if (*clock == 0) return -1; - + uint8_t fc=0; + size_t i=0, numBits=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0; + uint16_t fullWaveLen=0, waveLenCnt=0, avgWaveVal; + uint16_t errCnt=0, errCnt2=0; + + *clock = DetectPSKClock(dest, *size, *clock, &firstFullWave, &curPhase, &fc); + if (*clock <= 0) return -1; + //if clock detect found firstfullwave... + uint16_t tol = fc/2; + if (firstFullWave == 0) { //find start of modulating data in trace - uint8_t threshold_value = 123; //-5 - i = findModStart(dest, *size, threshold_value, fc); - + i = findModStart(dest, *size, fc); //find first phase shift - int avgWaveVal=0, lastAvgWaveVal=0; - waveStart = i; - for (; i= dest[i+2]){ - waveEnd = i+1; - if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u",waveEnd, waveStart); - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+3)){ //not first peak and is a large wave but not out of whack - lastAvgWaveVal = avgWaveVal/(waveLenCnt); - firstFullWave = waveStart; - fullWaveLen=waveLenCnt; - //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting) - if (lastAvgWaveVal > threshold_value) curPhase ^= 1; - break; - } - waveStart = i+1; - avgWaveVal = 0; - } - avgWaveVal += dest[i+2]; - } + firstFullWave = pskFindFirstPhaseShift(dest, *size, &curPhase, i, fc, &fullWaveLen); if (firstFullWave == 0) { // no phase shift detected - could be all 1's or 0's - doesn't matter where we start // so skip a little to ensure we are past any Start Signal @@ -1689,11 +1606,15 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) } else { memset(dest, curPhase^1, firstFullWave / *clock); } + } else { + memset(dest, curPhase^1, firstFullWave / *clock); + } //advance bits numBits += (firstFullWave / *clock); + *startIdx = firstFullWave - (*clock * numBits)+2; //set start of wave as clock align lastClkBit = firstFullWave; - if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen); + if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i",firstFullWave,fullWaveLen, *startIdx); if (g_debugMode==2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc); waveStart = 0; dest[numBits++] = curPhase; //set first read bit @@ -1707,9 +1628,7 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) } else { //waveEnd waveEnd = i+1; waveLenCnt = waveEnd-waveStart; - lastAvgWaveVal = avgWaveVal/waveLenCnt; if (waveLenCnt > fc){ - //prnt("DEBUG: avgWaveVal: %d, waveSum: %d",lastAvgWaveVal,avgWaveVal); //this wave is a phase shift //prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc); if (i+1 >= lastClkBit + *clock - tol){ //should be a clock bit @@ -1728,6 +1647,8 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) } else if (waveLenCnt < fc - 1) { //wave is smaller than field clock (shouldn't happen often) errCnt2++; if(errCnt2 > 101) return errCnt2; + avgWaveVal += dest[i+1]; + continue; } avgWaveVal = 0; waveStart = i+1; @@ -1739,199 +1660,166 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) return errCnt; } -bool DetectST(uint8_t buffer[], size_t *size, int *foundclock) { - size_t ststart = 0, stend = 0; - return DetectST_ext(buffer, size, foundclock, &ststart, &stend); +int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) { + int startIdx = 0; + return pskRawDemod_ext(dest, size, clock, invert, &startIdx); +} + + +//********************************************************************************************** +//-----------------Tag format detection section------------------------------------------------- +//********************************************************************************************** + + +// by marshmellow +// FSK Demod then try to locate an AWID ID +int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx) { + //make sure buffer has enough data + if (*size < 96*50) return -1; + + if (justNoise(dest, *size)) return -2; + + // FSK demodulator + *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); // fsk2a RF/50 + if (*size < 96) return -3; //did we get a good demod? + + uint8_t preamble[] = {0,0,0,0,0,0,0,1}; + size_t startIdx = 0; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -4; //preamble not found + if (*size != 96) return -5; + return (int)startIdx; } //by marshmellow -//attempt to identify a Sequence Terminator in ASK modulated raw wave -bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend) { - size_t bufsize = *size; - //need to loop through all samples and identify our clock, look for the ST pattern - uint8_t fndClk[] = {8,16,32,40,50,64,128}; - int clk = 0; - int tol = 0; - int i, j, skip, start, end, low, high, minClk, waveStart; - bool complete = false; - int tmpbuff[bufsize / 32]; //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured - int waveLen[bufsize / 32]; // if clock is larger then we waste memory in array size that is not needed... - size_t testsize = (bufsize < 512) ? bufsize : 512; - int phaseoff = 0; - high = low = 128; - memset(tmpbuff, 0, sizeof(tmpbuff)); - memset(waveLen, 0, sizeof(waveLen)); +//takes 1s and 0s and searches for EM410x format - output EM ID +int Em410xDecode(uint8_t *bits, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo) { + // sanity check + if (*size < 64) return -3; + if (bits[1] > 1) return -1; + + uint8_t fmtlen; + *startIdx = 0; + + // preamble 0111111111 + // include 0 in front to help get start pos + uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1}; + if (!preambleSearch(bits, preamble, sizeof(preamble), size, startIdx)) + return -2; + //XL and normal size. + if (*size != 64 && *size != 128) return -3; - if ( getHiLo(buffer, testsize, &high, &low, 80, 80) == -1 ) { - if (g_debugMode==2) prnt("DEBUG STT: just noise detected - quitting"); - return false; //just noise - } - i = 0; - j = 0; - minClk = 255; - // get to first full low to prime loop and skip incomplete first pulse - while ((buffer[i] < high) && (i < bufsize)) - ++i; - while ((buffer[i] > low) && (i < bufsize)) - ++i; - skip = i; + fmtlen = (*size == 128) ? 22 : 10; - // populate tmpbuff buffer with pulse lengths - while (i < bufsize) { - // measure from low to low - while ((buffer[i] > low) && (i < bufsize)) - ++i; - start= i; - while ((buffer[i] < high) && (i < bufsize)) - ++i; - //first high point for this wave - waveStart = i; - while ((buffer[i] > low) && (i < bufsize)) - ++i; - if (j >= (bufsize/32)) { - break; - } - waveLen[j] = i - waveStart; //first high to first low - tmpbuff[j++] = i - start; - if (i-start < minClk && i < bufsize) { - minClk = i - start; - } + //skip last 4bit parity row for simplicity + *size = removeParity(bits, *startIdx + sizeof(preamble), 5, 0, fmtlen * 5); + + switch (*size) { + case 40: { + // std em410x format + *hi = 0; + *lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32)); + break; + } + case 88: { + // long em format + *hi = (bytebits_to_byte(bits, 24)); + *lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32)); + break; + } + default: return -4; } - // set clock - might be able to get this externally and remove this work... - if (!clk) { - for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) { - tol = fndClk[clkCnt]/8; - if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) { - clk=fndClk[clkCnt]; - break; - } - } - // clock not found - ERROR - if (!clk) { - if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting"); - return false; - } - } else tol = clk/8; + return 1; +} - *foundclock = clk; +// loop to get raw HID waveform then FSK demodulate the TAG ID from it +int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) { - // look for Sequence Terminator - should be pulses of clk*(1 or 1.5), clk*2, clk*(1.5 or 2) - start = -1; - for (i = 0; i < j - 4; ++i) { - skip += tmpbuff[i]; - if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol && waveLen[i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior - if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2 - if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave - if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit - start = i + 3; - break; - } - } - } - } - } - // first ST not found - ERROR - if (start < 0) { - if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting"); - return false; - } else { - if (g_debugMode==2) prnt("DEBUG STT: first STT found at: %d, j=%d",start, j); - } - if (waveLen[i+2] > clk*1+tol) - phaseoff = 0; - else - phaseoff = clk/2; - - // skip over the remainder of ST - skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point + if (justNoise(dest, *size)) return -1; - // now do it again to find the end - end = skip; - for (i += 3; i < j - 4; ++i) { - end += tmpbuff[i]; - if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol && waveLen[i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior - if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2 - if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave - if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit - complete = true; - break; - } - } - } - } - } - end -= phaseoff; - //didn't find second ST - ERROR - if (!complete) { - if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting"); - return false; - } - if (g_debugMode==2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff); - //now begin to trim out ST so we can use normal demod cmds - start = skip; - size_t datalen = end - start; - // check validity of datalen (should be even clock increments) - use a tolerance of up to 1/8th a clock - if ( clk - (datalen % clk) <= clk/8) { - // padd the amount off - could be problematic... but shouldn't happen often - datalen += clk - (datalen % clk); - } else if ( (datalen % clk) <= clk/8 ) { - // padd the amount off - could be problematic... but shouldn't happen often - datalen -= datalen % clk; - } else { - if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk); - return false; - } - // if datalen is less than one t55xx block - ERROR - if (datalen/clk < 8*4) { - if (g_debugMode==2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); - return false; - } - size_t dataloc = start; - if (buffer[dataloc-(clk*4)-(clk/8)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) { - //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start - for ( i=0; i <= (clk/8); ++i ) { - if ( buffer[dataloc - (clk*4) - i] <= low ) { - dataloc -= i; - break; - } + size_t numStart=0, startIdx=0; + // FSK demodulator fsk2a so invert and fc/10/8 + *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); + if (*size < 96*2) return -2; + // 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 + uint8_t preamble[] = {0,0,0,1,1,1,0,1}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -3; //preamble not found + + numStart = startIdx + sizeof(preamble); + // final loop, go over previously decoded FSK data and manchester decode into usable tag ID + for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){ + if (dest[idx] == dest[idx+1]){ + return -4; //not manchester data } + *hi2 = (*hi2<<1)|(*hi>>31); + *hi = (*hi<<1)|(*lo>>31); + //Then, shift in a 0 or one into low + *lo <<= 1; + if (dest[idx] && !dest[idx+1]) // 1 0 + *lo |= 1; + else // 0 1 + *lo |= 0; } - - size_t newloc = 0; - i=0; - if (g_debugMode==2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen); - bool firstrun = true; - // warning - overwriting buffer given with raw wave data with ST removed... - while ( dataloc < bufsize-(clk/2) ) { - //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part) - if (buffer[dataloc]low && buffer[dataloc+3]low) { - for(i=0; i < clk/2-tol; ++i) { - buffer[dataloc+i] = high+5; - } - } //test for single sample outlier (high between two lows) in the case of very strong waves - if (buffer[dataloc] >= high && buffer[dataloc+2] <= low) { - buffer[dataloc] = buffer[dataloc+2]; - buffer[dataloc+1] = buffer[dataloc+2]; - } - if (firstrun) { - *stend = dataloc; - *ststart = dataloc-(clk*4); - firstrun=false; - } - for (i=0; i // for bool #include // for strcmp #include // for +#include // for bool +#include "parity.h" // for parity test //generic -uint8_t justNoise(uint8_t *bits, size_t size); -size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType); -int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType); -void askAmp(uint8_t *BitStream, size_t size); -int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert); -uint32_t bytebits_to_byte(uint8_t* src, size_t numbits); -uint32_t bytebits_to_byteLSBF(uint8_t* src, size_t numbits); -uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj); -int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr); -uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low); -uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow); -uint8_t detectFSKClk_ext(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); -int DetectNRZClock(uint8_t dest[], size_t size, int clock); -int DetectNRZClock_ext(uint8_t dest[], size_t size, int clock, int *clockStartIdx); -int DetectPSKClock(uint8_t dest[], size_t size, int clock); -int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseShift); -int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low, int *clock); -bool DetectST(uint8_t buffer[], size_t *size, int *foundclock); -bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend); -int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow); -int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); -uint32_t manchesterEncode2Bytes(uint16_t datain); -int ManchesterEncode(uint8_t *BitStream, size_t size); -int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert); -int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert); +extern uint8_t justNoise(uint8_t *bits, size_t size); +extern size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType); +extern int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType); +extern int askdemod_ext(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx); +extern void askAmp(uint8_t *BitStream, size_t size); +extern int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int *offset, int invert); +extern uint32_t bytebits_to_byte(uint8_t* src, size_t numbits); +extern uint32_t bytebits_to_byteLSBF(uint8_t* src, size_t numbits); +extern uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj); +extern int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr); +extern uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low); +extern uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); +extern int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx); +extern int DetectPSKClock(uint8_t dest[], size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc); +extern int DetectStrongAskClock(uint8_t dest[], size_t size, int high, int low, int *clock); +extern bool DetectST(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend); +extern size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx); +extern int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); +extern uint32_t manchesterEncode2Bytes(uint16_t datain); +extern int ManchesterEncode(uint8_t *BitStream, size_t size); +extern int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert, uint8_t *alignPos); +extern int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx); extern bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); -bool preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); -bool preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone); -int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert); -void psk2TOpsk1(uint8_t *BitStream, size_t size); -void psk1TOpsk2(uint8_t *BitStream, size_t size); -size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen); +extern bool preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); +extern bool preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone); +extern int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert); +extern int pskRawDemod_ext(uint8_t dest[], size_t *size, int *clock, int *invert, int *startIdx); +extern void psk2TOpsk1(uint8_t *BitStream, size_t size); +extern void psk1TOpsk2(uint8_t *BitStream, size_t size); +extern size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen); //tag specific -int AWIDdemodFSK(uint8_t *dest, size_t *size); -int Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); -int FDXBdemodBI(uint8_t *dest, size_t *size); -int gProxII_Demod(uint8_t BitStream[], size_t *size); -int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); -int IOdemodFSK(uint8_t *dest, size_t size); -int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); -int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); -int PyramiddemodFSK(uint8_t *dest, size_t *size); -int VikingDemod_AM(uint8_t *dest, size_t *size); -int PrescoDemod(uint8_t *dest, size_t *size); -int NedapDemod(uint8_t *dest, size_t *size); -int JablotronDemod(uint8_t *dest, size_t *size); -int Visa2kDemod_AM(uint8_t *dest, size_t *size); -int NoralsyDemod_AM(uint8_t *dest, size_t *size); -int IdteckDemodPSK(uint8_t *dest, size_t *size); +extern int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx); +extern int Em410xDecode(uint8_t *dest, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); +extern int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); +extern int detectIdteck(uint8_t *dest, size_t *size); +extern int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx); +extern int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert); #endif diff --git a/common/parity.c b/common/parity.c index 66fcc5586..cd997ceb1 100644 --- a/common/parity.c +++ b/common/parity.c @@ -3,9 +3,10 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// parity functions +// parity functions (all defined in parity.h) //----------------------------------------------------------------------------- #include +#include const uint8_t OddByteParity[256] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, diff --git a/include/hitag2.h b/include/hitag2.h index 056a90e91..a2d592410 100644 --- a/include/hitag2.h +++ b/include/hitag2.h @@ -13,6 +13,12 @@ #ifndef _HITAG2_H_ #define _HITAG2_H_ +#ifdef _MSC_VER +#define PACKED +#else +#define PACKED __attribute__((packed)) +#endif + typedef enum { RHTSF_CHALLENGE = 01, RHTSF_KEY = 02, @@ -21,8 +27,9 @@ typedef enum { RHT2F_PASSWORD = 21, RHT2F_AUTHENTICATE = 22, RHT2F_CRYPTO = 23, + WHT2F_CRYPTO = 24, RHT2F_TEST_AUTH_ATTEMPTS = 25, - RHT2F_UID_ONLY = 26 + RHT2F_UID_ONLY = 26, } hitag_function; typedef struct { diff --git a/liblua/llex.c b/liblua/llex.c index d91f00f7d..81b8de9e3 100644 --- a/liblua/llex.c +++ b/liblua/llex.c @@ -199,7 +199,7 @@ static void buffreplace (LexState *ls, char from, char to) { #if ANDROID -#define getlocaledecpoint() '.' +#define getlocaldecpoint() '.' #elif !defined(getlocaledecpoint) #define getlocaledecpoint() (localeconv()->decimal_point[0]) #endif