From: Iceman Date: Wed, 29 Mar 2017 15:36:37 +0000 (+0200) Subject: Merge pull request #256 from pwpiwi/fast_select X-Git-Tag: v3.0.0~24 X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/f25c62c5ec53de4f0657fb14379bf3098dab9148?hp=de77d4acde77e4a7fbd36295dfb54a31353eb0d8 Merge pull request #256 from pwpiwi/fast_select add: iceman1001's idea to reuse @pwpiwi's fast select without anticol… --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 7994c987..eb4a62de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,15 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added +- Added lf noralsy demod, read, clone, sim commands (iceman) +- Added lf jablotron demod, read, clone, sim commands (iceman) +- Added lf nexwatch read - reads a nexwatch tag from the antenna +- Added lf paradox read - reads a paradox tag from the antenna - Added lf fdx sim (iceman) -- Added lf fdx clone - clones an fdx-b animal tag to t55x7 or q5 (iceman) -- Added lf fdx read - reads a fdx-b tag from the antenna (iceman) -- Added lf gproxii read - reads a gproxii tag from the antenna (marshmellow) -- Added lf indala read - reads an indala tag from the antenna (marshmellow) +- Added lf fdx clone - clones an fdx-b animal tag to t55x7 or q5 (iceman) +- Added lf fdx read - reads a fdx-b tag from the antenna (iceman) +- Added lf gproxii read - reads a gproxii tag from the antenna (marshmellow) +- Added lf indala read - reads an indala tag from the antenna (marshmellow) - Added lf visa2000 demod, read, clone, sim commands (iceman) - Added markers in the graph around found Sequence Terminator after askmandemod. - Added data mtrim command to trim out samples between start and stop @@ -50,6 +54,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added option c to 'hf list' (mark CRC bytes) (piwi) ### Changed +- `data psknexwatchdemod` has been moved to `lf nexwatch demod` (reads from graphbuffer) +- `data fskparadoxdemod` has been moved to `lf paradox demod` (reads from graphbuffer) - `data fdxdemod` has been moved to `lf fdx demod` (reads from graphbuffer) - `data askgproxiidemod has been moved to `lf gproxii demod` (reads from graphbuffer) - `lf indalaclone` has been moved to `lf indala clone` diff --git a/client/Makefile b/client/Makefile index d5bfb086..a6b1942f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -99,9 +99,14 @@ CMDSRCS = crapto1/crapto1.c\ cmdlfhitag.c \ cmdlfio.c \ cmdlfindala.c \ - cmdlfpcf7931.c\ - cmdlfpresco.c\ - cmdlfpyramid.c\ + cmdlfjablotron.c \ + cmdlfnexwatch.c \ + cmdlfnoralsy.c \ + cmdlfparadox.c \ + cmdlfpcf7931.c \ + cmdlfpresco.c \ + cmdlfpyramid.c \ + cmdlfsecurakey.c \ cmdlft55xx.c \ cmdlfti.c \ cmdlfviking.c\ diff --git a/client/cmddata.c b/client/cmddata.c index 2444fb32..ef1229c2 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -801,55 +801,6 @@ int CmdFSKrawdemod(const char *Cmd) return FSKrawDemod(Cmd, true); } -//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: Just Noise Detected"); - } else if (idx == -2) { - PrintAndLog("DEBUG: Error demoding fsk"); - } else if (idx == -3) { - PrintAndLog("DEBUG: Preamble not found"); - } else if (idx == -4) { - PrintAndLog("DEBUG: Error in Manchester data"); - } else { - PrintAndLog("DEBUG: Error demoding fsk %d", idx); - } - } - return 0; - } - if (hi2==0 && hi==0 && lo==0){ - if (g_debugMode) PrintAndLog("DEBUG: Error - 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: idx: %d, len: %d, Printing Demod Buffer:", idx, BitLen); - printDemodBuff(); - } - return 1; -} - //by marshmellow //attempt to psk1 demod graph buffer int PSKDemod(const char *Cmd, bool verbose) @@ -898,45 +849,6 @@ int PSKDemod(const char *Cmd, bool verbose) return 1; } -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; - bool invert = false; - 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 (size != 128) return 0; - setDemodBuf(DemodBuffer, size, startIdx+4); - startIdx = 8+32; //4 = extra i added, 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)]; - } - } - //parity check (TBD) - - //checksum check (TBD) - - //output - PrintAndLog("NexWatch ID: %d", ID); - if (invert){ - PrintAndLog("Had to Invert - probably NexKey"); - for (uint8_t idx=0; idx=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"}, @@ -1641,7 +1552,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"}, - {"psknexwatchdemod",CmdPSKNexWatch, 1, "Demodulate a NexWatch tag (nexkey, quadrakey) (PSK1) from GraphBuffer"}, {"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 86d905b1..e03ab02c 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -32,12 +32,9 @@ 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 CmdFSKdemodParadox(const char *Cmd); int CmdFSKrawdemod(const char *Cmd); int CmdPSK1rawDemod(const char *Cmd); int CmdPSK2rawDemod(const char *Cmd); -int CmdPSKNexWatch(const char *Cmd); int CmdGrid(const char *Cmd); int CmdGetBitStream(const char *Cmd); int CmdHexsamples(const char *Cmd); diff --git a/client/cmdlf.c b/client/cmdlf.c index d8e78be1..005aa0e2 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -38,6 +38,11 @@ #include "cmdlfindala.h" // for indala menu #include "cmdlfgproxii.h"// for gproxii menu #include "cmdlffdx.h" // for fdx-b menu +#include "cmdlfparadox.h"// for paradox menu +#include "cmdlfnexwatch.h"//for nexwatch menu +#include "cmdlfjablotron.h" //for jablotron menu +#include "cmdlfnoralsy.h"// for noralsy menu +#include "cmdlfsecurakey.h"//for securakey menu bool g_lf_threshold_set = false; static int CmdHelp(const char *Cmd); @@ -985,13 +990,31 @@ int CmdLFfind(const char *Cmd) if (ans>0) { PrintAndLog("\nValid EM4x50 ID Found!"); return 1; - } + } + + ans=CmdJablotronDemod(""); + if (ans>0) { + PrintAndLog("\nValid Jablotron ID Found!"); + return CheckChipType(cmdp); + } + + ans=CmdNoralsyDemod(""); + if (ans>0) { + PrintAndLog("\nValid Noralsy ID Found!"); + return CheckChipType(cmdp); + } + + ans=CmdSecurakeyDemod(""); + if (ans>0) { + PrintAndLog("\nValid Securakey ID Found!"); + return CheckChipType(cmdp); + } ans=CmdVikingDemod(""); if (ans>0) { PrintAndLog("\nValid Viking ID Found!"); return CheckChipType(cmdp); - } + } ans=CmdIndalaDecode(""); if (ans>0) { @@ -1051,9 +1074,14 @@ static command_t CommandTable[] = {"hitag", CmdLFHitag, 1, "{ Hitag CHIPs... }"}, {"io", CmdLFIO, 1, "{ ioProx RFIDs... }"}, {"indala", CmdLFINDALA, 1, "{ Indala RFIDs... }"}, + {"jablotron", CmdLFJablotron, 1, "{ Jablotron RFIDs... }"}, + {"nexwatch", CmdLFNexWatch, 1, "{ NexWatch RFIDs... }"}, + {"noralsy", CmdLFNoralsy, 1, "{ Noralsy RFIDs... }"}, + {"paradox", CmdLFParadox, 1, "{ Paradox RFIDs... }"}, {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"}, {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 CHIPs... }"}, {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, + {"securakey", CmdLFSecurakey, 1, "{ Securakey RFIDs... }"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx CHIPs... }"}, {"ti", CmdLFTI, 1, "{ TI CHIPs... }"}, {"viking", CmdLFViking, 1, "{ Viking RFIDs... }"}, diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c new file mode 100644 index 00000000..0b7d2811 --- /dev/null +++ b/client/cmdlfjablotron.c @@ -0,0 +1,253 @@ +//----------------------------------------------------------------------------- +// +// 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 jablotron tag commands +// Differential Biphase, RF/64, 64 bits long +//----------------------------------------------------------------------------- + +#include "cmdlfjablotron.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" // parityTest + +static int CmdHelp(const char *Cmd); + +int usage_lf_jablotron_clone(void) { + PrintAndLog("clone a Jablotron tag to a T55x7 tag."); + PrintAndLog("Usage: lf jablotron clone [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : jablotron card ID"); + PrintAndLog(" : specify write to Q5 (t5555 instead of t55x7)"); + PrintAndLog(""); + PrintAndLog("Sample: lf jablotron clone 112233"); + return 0; +} + +int usage_lf_jablotron_sim(void) { + PrintAndLog("Enables simulation of jablotron card with specified card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog(""); + PrintAndLog("Usage: lf jablotron sim [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : jablotron card ID"); + PrintAndLog(""); + PrintAndLog("Sample: lf jablotron sim 112233"); + return 0; +} + +static uint8_t jablontron_chksum(uint8_t *bits) { + uint8_t chksum = 0; + for (int i=16; i < 56; i += 8) { + chksum += bytebits_to_byte(bits+i,8); + } + chksum ^= 0x3A; + return chksum; +} + +int getJablotronBits(uint64_t fullcode, uint8_t *bits) { + //preamp + num_to_bytebits(0xFFFF, 16, bits); + + //fullcode + num_to_bytebits(fullcode, 40, bits+16); + + //chksum byte + uint8_t chksum = jablontron_chksum(bits); + num_to_bytebits(chksum, 8, bits+56); + 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 JablotronDetect(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; +} + +//see ASKDemod for what args are accepted +int CmdJablotronDemod(const char *Cmd) { + + //Differential Biphase / di-phase (inverted biphase) + //get binary from ask wave + if (!ASKbiphaseDemod("0 64 1 0", false)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Jablotron ASKbiphaseDemod failed"); + return 0; + } + size_t size = DemodBufferLen; + int ans = JablotronDetect(DemodBuffer, &size); + if (ans < 0) { + if (g_debugMode) { + if (ans == -1) + PrintAndLog("DEBUG: Error - Jablotron too few bits found"); + else if (ans == -2) + PrintAndLog("DEBUG: Error - Jablotron preamble not found"); + else if (ans == -3) + PrintAndLog("DEBUG: Error - Jablotron size not correct: %d", size); + else if (ans == -5) + PrintAndLog("DEBUG: Error - Jablotron checksum failed"); + else + PrintAndLog("DEBUG: Error - Jablotron ans: %d", ans); + } + return 0; + } + + setDemodBuf(DemodBuffer+ans, 64, 0); + //setGrid_Clock(64); + + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + + uint64_t id = (( (uint64_t)bytebits_to_byte(DemodBuffer+16, 8) )<< 32) | bytebits_to_byte(DemodBuffer+24,32); + + PrintAndLog("Jablotron Tag Found: Card ID: %"PRIx64" :: Raw: %08X%08X", id, raw1, raw2); + + uint8_t chksum = raw2 & 0xFF; + PrintAndLog("Checksum: %02X [OK]", chksum); + + // Printed format: 1410-nn-nnnn-nnnn + PrintAndLog("Printed: 1410-%02X-%04X-%04X", + (uint8_t)(id >> 32) & 0xFF, + (uint16_t)(id >> 16) & 0xFFFF, + (uint16_t)id & 0xFFFF + ); + return 1; +} + +int CmdJablotronRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("10000", true); + return CmdJablotronDemod(Cmd); +} + +int CmdJablotronClone(const char *Cmd) { + + uint64_t fullcode = 0; + uint32_t blocks[3] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0}; + + uint8_t bits[64]; + uint8_t *bs = bits; + memset(bs, 0, sizeof(bits)); + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_clone(); + + fullcode = param_get64ex(Cmd, 0, 0, 16); + + //Q5 + if (param_getchar(Cmd, 1) == 'Q' || param_getchar(Cmd, 1) == 'q') { + //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) + blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | ((64-2)>>1) << T5555_BITRATE_SHIFT | 2 << T5555_MAXBLOCK_SHIFT; + } + + // clearing the topbit needed for the preambl detection. + if ((fullcode & 0x7FFFFFFFFF) != fullcode) { + fullcode &= 0x7FFFFFFFFF; + PrintAndLog("Card Number Truncated to 39bits: %"PRIx64, fullcode); + } + + if ( !getJablotronBits(fullcode, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return 1; + } + + blocks[1] = bytebits_to_byte(bs,32); + blocks[2] = bytebits_to_byte(bs+32,32); + + PrintAndLog("Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode); + PrintAndLog("Blk | Data "); + PrintAndLog("----+------------"); + PrintAndLog(" 00 | 0x%08x", blocks[0]); + PrintAndLog(" 01 | 0x%08x", blocks[1]); + PrintAndLog(" 02 | 0x%08x", blocks[2]); + + UsbCommand resp; + UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; + + for (int i = 2; i >= 0; --i) { + c.arg[0] = blocks[i]; + c.arg[1] = i; + clearCommandBuffer(); + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, T55XX_WRITE_TIMEOUT)) { + PrintAndLog("Error occurred, device did not respond during write operation."); + return -1; + } + } + return 0; +} + +int CmdJablotronSim(const char *Cmd) { + uint64_t fullcode = 0; + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_sim(); + + fullcode = param_get64ex(Cmd, 0, 0, 16); + + // clearing the topbit needed for the preambl detection. + if ((fullcode & 0x7FFFFFFFFF) != fullcode) { + fullcode &= 0x7FFFFFFFFF; + PrintAndLog("Card Number Truncated to 39bits: %"PRIx64, fullcode); + } + + uint8_t clk = 64, encoding = 2, separator = 0, invert = 1; + uint16_t arg1, arg2; + size_t size = 64; + arg1 = clk << 8 | encoding; + arg2 = invert << 8 | separator; + + PrintAndLog("Simulating Jablotron - FullCode: %"PRIx64, fullcode); + + UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; + getJablotronBits(fullcode, c.d.asBytes); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdJablotronDemod, 1, "Attempt to read and extract tag data 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} +}; + +int CmdLFJablotron(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfjablotron.h b/client/cmdlfjablotron.h new file mode 100644 index 00000000..8e1e3364 --- /dev/null +++ b/client/cmdlfjablotron.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// +// 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 jablotron tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFJABLOTRON_H__ +#define CMDLFJABLOTRON_H__ + +extern int CmdLFJablotron(const char *Cmd); +extern int CmdJablotronClone(const char *Cmd); +extern int CmdJablotronSim(const char *Cmd); +extern int CmdJablotronRead(const char *Cmd); +extern int CmdJablotronDemod(const char *Cmd); + +#endif + diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c new file mode 100644 index 00000000..030c61c7 --- /dev/null +++ b/client/cmdlfnexwatch.c @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------------- +// +// 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 Honeywell NexWatch tag commands +// PSK1 RF/16, RF/2, 128 bits long +//----------------------------------------------------------------------------- +#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; + bool invert = false; + 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 (size != 128) return 0; + setDemodBuf(DemodBuffer, size, startIdx+4); + startIdx = 8+32; //4 = extra i added, 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)]; + } + } + //parity check (TBD) + + //checksum check (TBD) + + //output + PrintAndLog("NexWatch ID: %d", ID); + if (invert){ + PrintAndLog("Had to Invert - probably NexKey"); + for (uint8_t idx=0; idx +#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" // parityTest + +static int CmdHelp(const char *Cmd); + +int usage_lf_noralsy_clone(void){ + PrintAndLog("clone a Noralsy tag to a T55x7 tag."); + PrintAndLog("Usage: lf noralsy clone [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : Noralsy card ID"); + PrintAndLog(" : Tag allocation year"); + PrintAndLog(" : specify write to Q5 (t5555 instead of t55x7)"); + PrintAndLog(""); + PrintAndLog("Sample: lf noralsy clone 112233"); + return 0; +} + +int usage_lf_noralsy_sim(void) { + PrintAndLog("Enables simulation of Noralsy card with specified card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog(""); + PrintAndLog("Usage: lf noralsy sim [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : Noralsy card ID"); + PrintAndLog(" : Tag allocation year"); + PrintAndLog(""); + PrintAndLog("Sample: lf noralsy sim 112233"); + return 0; +} + +static uint8_t noralsy_chksum( uint8_t* bits, uint8_t len) { + uint8_t sum = 0; + for (uint8_t i = 0; i < len; i += 4) + sum ^= bytebits_to_byte(bits+i, 4); + return sum & 0x0F ; +} +int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits) { + //preamp + num_to_bytebits(0xBB0214FF, 32, bits); // --> Have seen 0xBB0214FF / 0xBB0314FF UNKNOWN + + year &= 0xFF; + + uint16_t sub1 = (id & 0xFFF0000) >> 16; + uint8_t sub2 = (id & 0x000FF00) >> 8; + uint8_t sub3 = (id & 0x00000FF); + + num_to_bytebits(sub1, 12, bits+32); + num_to_bytebits(year, 8, bits+44); + num_to_bytebits(0, 4, bits+52); // --> UNKNOWN. Flag? + + num_to_bytebits(sub2, 8, bits+56); + num_to_bytebits(sub3, 8, bits+64); + + //chksum byte + uint8_t chksum = noralsy_chksum(bits+32, 40); + num_to_bytebits(chksum, 4, bits+72); + chksum = noralsy_chksum(bits, 76); + num_to_bytebits(chksum, 4, bits+76); + return 1; +} + +// 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; +} + +/* +* +* 2520116 | BB0214FF2529900116360000 | 10111011 00000011 00010100 11111111 00100101 00101001 10010000 00000001 00010110 00110110 00000000 00000000 +* aaaaaaaaiii***iiiicc---- iiiiiiii iiiiYYYY YYYY**** iiiiiiii iiiiiiii cccccccc +* +* a = fixed value BB0314FF +* i = printed id, BCD-format +* Y = year +* c = checksum +* +**/ + +//see ASKDemod for what args are accepted +int CmdNoralsyDemod(const char *Cmd) { + + //ASK / Manchester + bool st = false; + if (!ASKDemod_ext("32 0 0", false, false, 1, &st)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: ASK/Manchester Demod failed"); + return 0; + } + if (!st) return 0; + + size_t size = DemodBufferLen; + int ans = NoralsyDemod_AM(DemodBuffer, &size); + if (ans < 0){ + if (g_debugMode){ + if (ans == -1) + PrintAndLog("DEBUG: Error - Noralsy: too few bits found"); + else if (ans == -2) + PrintAndLog("DEBUG: Error - Noralsy: preamble not found"); + else if (ans == -3) + PrintAndLog("DEBUG: Error - Noralsy: Size not correct: %d", size); + else + PrintAndLog("DEBUG: Error - Noralsy: ans: %d", ans); + } + return 0; + } + setDemodBuf(DemodBuffer, 96, ans); + //setGrid_Clock(32); + + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32); + + uint32_t cardid = (bytebits_to_byte(DemodBuffer+32, 12)<<16) | bytebits_to_byte(DemodBuffer+32+24, 16); + + uint16_t year = (raw2 & 0x000ff000) >> 12; + year += ( year > 0x60 ) ? 0x1900: 0x2000; + + // calc checksums + uint8_t calc1 = noralsy_chksum(DemodBuffer+32, 40); + uint8_t calc2 = noralsy_chksum(DemodBuffer, 76); + uint8_t chk1 = 0, chk2 = 0; + chk1 = bytebits_to_byte(DemodBuffer+72, 4); + chk2 = bytebits_to_byte(DemodBuffer+76, 4); + // test checksums + if ( chk1 != calc1 ) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: checksum 1 failed %x - %x\n", chk1, calc1); + return 0; + } + if ( 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 %X, Year: %X 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); + return CmdNoralsyDemod(Cmd); +} + +int CmdNoralsyClone(const char *Cmd) { + + uint16_t year = 0; + uint32_t id = 0; + uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0}; + uint8_t bits[96]; + uint8_t *bs = bits; + memset(bs, 0, sizeof(bits)); + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_noralsy_clone(); + + id = param_get32ex(Cmd, 0, 0, 16); + year = param_get32ex(Cmd, 1, 2000, 16); + + //Q5 + if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q') { + //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) + blocks[0] = T5555_MODULATION_MANCHESTER | ((32-2)>>1) << T5555_BITRATE_SHIFT | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; + } + + if ( !getnoralsyBits(id, year, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return 1; + } + + // + blocks[1] = bytebits_to_byte(bs,32); + blocks[2] = bytebits_to_byte(bs+32,32); + blocks[3] = bytebits_to_byte(bs+64,32); + + PrintAndLog("Preparing to clone Noralsy to T55x7 with CardId: %x", id); + PrintAndLog("Blk | Data "); + PrintAndLog("----+------------"); + PrintAndLog(" 00 | 0x%08x", blocks[0]); + PrintAndLog(" 01 | 0x%08x", blocks[1]); + PrintAndLog(" 02 | 0x%08x", blocks[2]); + PrintAndLog(" 03 | 0x%08x", blocks[3]); + + UsbCommand resp; + UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; + + for (int i = 3; i >= 0; --i) { + c.arg[0] = blocks[i]; + c.arg[1] = i; + clearCommandBuffer(); + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, T55XX_WRITE_TIMEOUT)){ + PrintAndLog("Error occurred, device did not respond during write operation."); + return -1; + } + } + return 0; +} + +int CmdNoralsySim(const char *Cmd) { + + uint8_t bits[96]; + uint8_t *bs = bits; + memset(bs, 0, sizeof(bits)); + + uint16_t year = 0; + uint32_t id = 0; + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_noralsy_sim(); + + id = param_get32ex(Cmd, 0, 0, 16); + year = param_get32ex(Cmd, 1, 2000, 16); + + uint8_t clk = 32, encoding = 1, separator = 1, invert = 0; + uint16_t arg1, arg2; + size_t size = 96; + arg1 = clk << 8 | encoding; + arg2 = invert << 8 | separator; + + if ( !getnoralsyBits(id, year, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return 1; + } + + PrintAndLog("Simulating Noralsy - CardId: %x", id); + + UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; + memcpy(c.d.asBytes, bs, size); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdNoralsyDemod,1, "Attempt to read and extract tag data from the GraphBuffer"}, + {"read", CmdNoralsyRead, 0, "Attempt to read and extract tag data from the antenna"}, + {"clone", CmdNoralsyClone,0, "clone Noralsy tag"}, + {"sim", CmdNoralsySim, 0, "simulate Noralsy tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFNoralsy(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfnoralsy.h b/client/cmdlfnoralsy.h new file mode 100644 index 00000000..743c14ec --- /dev/null +++ b/client/cmdlfnoralsy.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// +// 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 Noralsy tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFNORALSY_H__ +#define CMDLFNORALSY_H__ + +extern int CmdLFNoralsy(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); + +#endif + diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c new file mode 100644 index 00000000..5225820b --- /dev/null +++ b/client/cmdlfparadox.c @@ -0,0 +1,97 @@ +//----------------------------------------------------------------------------- +// +// 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 +//----------------------------------------------------------------------------- +#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); + +//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: Just Noise Detected"); + } else if (idx == -2) { + PrintAndLog("DEBUG: Error demoding fsk"); + } else if (idx == -3) { + PrintAndLog("DEBUG: Preamble not found"); + } else if (idx == -4) { + PrintAndLog("DEBUG: Error in Manchester data"); + } else { + PrintAndLog("DEBUG: Error demoding fsk %d", idx); + } + } + return 0; + } + if (hi2==0 && hi==0 && lo==0){ + if (g_debugMode) PrintAndLog("DEBUG: Error - 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: 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) { + // read lf silently + CmdLFRead("s"); + // get samples silently + getSamples("10000",false); + // demod and output viking ID + return CmdFSKdemodParadox(Cmd); +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdFSKdemodParadox, 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 00000000..997787f2 --- /dev/null +++ b/client/cmdlfparadox.h @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------------- +// +// 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 CmdFSKdemodParadox(const char *Cmd); +extern int CmdParadoxRead(const char *Cmd); +#endif diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c new file mode 100644 index 00000000..1e3899db --- /dev/null +++ b/client/cmdlfsecurakey.c @@ -0,0 +1,147 @@ +//----------------------------------------------------------------------------- +// +// 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 Securakey tag commands +// ASK/Manchester, RF/40, 96 bits long +//----------------------------------------------------------------------------- +#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) { + 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}; + 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; +} + +//see ASKDemod for what args are accepted +int CmdSecurakeyDemod(const char *Cmd) { + + //ASK / Manchester + bool st = false; + if (!ASKDemod_ext("40 0 0", false, false, 1, &st)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: ASK/Manchester Demod failed"); + return 0; + } + if (st) return 0; + size_t size = DemodBufferLen; + int ans = SecurakeyFind(DemodBuffer, &size); + if (ans < 0) { + if (g_debugMode) { + if (ans == -1) + PrintAndLog("DEBUG: Error - Securakey: too few bits found"); + else if (ans == -2) + PrintAndLog("DEBUG: Error - Securakey: preamble not found"); + else if (ans == -3) + PrintAndLog("DEBUG: Error - Securakey: Size not correct: %d", size); + else + PrintAndLog("DEBUG: Error - Securakey: ans: %d", ans); + } + return 0; + } + setDemodBuf(DemodBuffer, 96, ans); + //setGrid_Clock(40); + + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer , 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32); + + // 26 bit format + // preamble ??bitlen reserved EPx xxxxxxxy yyyyyyyy yyyyyyyOP CS? CS2? + // 0111111111 0 01011010 0 00000000 0 00000010 0 00110110 0 00111110 0 01100010 0 00001111 0 01100000 0 00000000 0 0000 + + // 32 bit format + // preamble ??bitlen reserved EPxxxxxxx xxxxxxxy yyyyyyyy yyyyyyyOP CS? CS2? + // 0111111111 0 01100000 0 00000000 0 10000100 0 11001010 0 01011011 0 01010110 0 00010110 0 11100000 0 00000000 0 0000 + + // x = FC? + // y = card # + // standard wiegand parities. + // unknown checksum 11 bits? at the end + uint8_t bits_no_spacer[85]; + memcpy(bits_no_spacer, DemodBuffer + 11, 85); + + // remove marker bits (0's every 9th digit after preamble) (pType = 3 (always 0s)) + size = removeParity(bits_no_spacer, 0, 9, 3, 85); + if ( size != 85-9 ) { + if (g_debugMode) PrintAndLog("DEBUG: Error removeParity: %d", size); + return 0; + } + + uint8_t bitLen = (uint8_t)bytebits_to_byte(bits_no_spacer+2, 6); + uint32_t fc=0, lWiegand=0, rWiegand=0; + if (bitLen > 40) { //securakey's max bitlen is 40 bits... + if (g_debugMode) PrintAndLog("DEBUG: Error bitLen too long: %u", bitLen); + return 0; + } + // get left 1/2 wiegand & right 1/2 wiegand (for parity test and wiegand print) + lWiegand = bytebits_to_byte(bits_no_spacer + 48 - bitLen, bitLen/2); + rWiegand = bytebits_to_byte(bits_no_spacer + 48 - bitLen + bitLen/2, bitLen/2); + // get FC + fc = bytebits_to_byte(bits_no_spacer+49-bitLen, bitLen-2-16); + + // test bitLen + if (bitLen != 26 && bitLen != 32) + PrintAndLog("***unknown securakey bitLen - share with forum***"); + + uint32_t cardid = bytebits_to_byte(bits_no_spacer+8+23, 16); + // test parities - evenparity32 looks to add an even parity returns 0 if already even... + bool parity = !evenparity32(lWiegand) && !oddparity32(rWiegand); + + PrintAndLog("Securakey Tag Found--BitLen: %u, Card ID: %u, FC: 0x%X, Raw: %08X%08X%08X", bitLen, cardid, fc, raw1 ,raw2, raw3); + if (bitLen <= 32) + PrintAndLog("Wiegand: %08X, Parity: %s", (lWiegand<<(bitLen/2)) | rWiegand, parity ? "Passed" : "Failed"); + PrintAndLog("\nHow the FC translates to printed FC is unknown"); + PrintAndLog("How the checksum is calculated is unknown"); + PrintAndLog("Help the community identify this format further\n by sharing your tag on the pm3 forum or with forum members"); + return 1; +} + +int CmdSecurakeyRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("8000",true); + 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"}, + {"read", CmdSecurakeyRead, 0, "Attempt to read and extract tag data from the antenna"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFSecurakey(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfsecurakey.h b/client/cmdlfsecurakey.h new file mode 100644 index 00000000..f3c0cf88 --- /dev/null +++ b/client/cmdlfsecurakey.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// +// 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 Securakey tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFSECURAKEY_H__ +#define CMDLFSECURAKEY_H__ + +extern int CmdLFSecurakey(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); + +#endif + diff --git a/common/lfdemod.c b/common/lfdemod.c index eb84203e..c56301c0 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -35,6 +35,7 @@ #include // for memset, memcmp and size_t #include // for uint_32+ #include // for bool +#include "parity.h" // for parity test //********************************************************************************************** //---------------------------------Utilities Section-------------------------------------------- @@ -82,40 +83,35 @@ int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi // by marshmellow // pass bits to be tested in bits, length bits passed in bitLen, and parity type (even=0 | odd=1) in pType // returns 1 if passed -uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType) { - uint8_t ans = 0; - for (uint8_t i = 0; i < bitLen; i++){ - ans ^= ((bits >> i) & 1); - } - if (g_debugMode) prnt("DEBUG: ans: %d, ptype: %d, bits: %08X",ans,pType,bits); - return (ans == pType); +bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType) { + return oddparity32(bits) ^ pType; } // by marshmellow -// takes a array of binary values, start position, length of bits per parity (includes parity bit), -// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) +// 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) { 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; } @@ -1687,6 +1683,7 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_ *hi = (bytebits_to_byte(BitStream, 24)); *lo = ((uint64_t)(bytebits_to_byte(BitStream + 24, 32)) << 32) | (bytebits_to_byte(BitStream + 24 + 32, 32)); } else { + if (g_debugMode) prnt("Error removing parity: %u", *size); return 0; } return 1;