From: Iceman Date: Sun, 26 Mar 2017 11:05:26 +0000 (+0200) Subject: Merge pull request #250 from pwpiwi/fix_mfkey X-Git-Tag: v3.0.0~32 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/7cd25ae5a3dc3ad26b584803ff397b63d9c62120?hp=dc2349ae7752f9da5337c515f9f5b71292f812e7 Merge pull request #250 from pwpiwi/fix_mfkey fix mfkey tools (issue #247) --- diff --git a/CHANGELOG.md b/CHANGELOG.md index abd2dd37..ef9c316c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added +- Added lf gproxii read - reads a gproxii tag from the antenna +- Added lf indala read - reads an indala tag from the antenna - 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 @@ -45,6 +47,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added option c to 'hf list' (mark CRC bytes) (piwi) ### Changed +- `data askgproxiidemod has been moved to `lf gproxii demod` (reads from graphbuffer) +- `lf indalaclone` has been moved to `lf indala clone` +- `lf indalademod` has been moved to `lf indala altdemod` (reads from graphbuffer) +- `data pskindalademod` has been moved to `lf indala demod` (reads from graphbuffer) - `data askvikingdemod` has been moved to `lf viking demod` (reads from graphbuffer) - `data fskpyramiddemod` has been moved to `lf pyramid demod` (reads from graphbuffer) - `data fskiodemod` has been moved to `lf io demod` (reads from graphbuffer) diff --git a/armsrc/Makefile b/armsrc/Makefile index b698d1f2..73c2290e 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -20,7 +20,7 @@ SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443b = iso14443b.c SRC_CRAPTO1 = crypto1.c des.c aes.c -SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c +SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c #the FPGA bitstream files. Note: order matters! FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 6a072bf4..dd0211da 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -993,7 +993,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 58e09a45..dc2281b9 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1023,8 +1023,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 76b82141..bd3bd845 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -21,6 +21,8 @@ #include "mifareutil.h" #include "BigBuf.h" #include "protocols.h" +#include "parity.h" + static uint32_t iso14a_timeout; int rsamples = 0; @@ -123,25 +125,6 @@ static uint32_t LastProxToAirDuration; #define SEC_Y 0x00 #define SEC_Z 0xc0 -const uint8_t OddByteParity[256] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 -}; - void iso14a_set_trigger(bool enable) { trigger = enable; @@ -180,11 +163,6 @@ void iso14a_set_ATS_timeout(uint8_t *ats) { // Generate the parity value for a byte sequence // //----------------------------------------------------------------------------- -byte_t oddparity (const byte_t bt) -{ - return OddByteParity[bt]; -} - void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) { uint16_t paritybit_cnt = 0; @@ -193,7 +171,7 @@ void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) for (uint16_t i = 0; i < iLen; i++) { // Generate the parity bits - parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt)); + parityBits |= ((oddparity8(pbtCmd[i])) << (7-paritybit_cnt)); if (paritybit_cnt == 7) { par[paritybyte_cnt] = parityBits; // save 8 Bits parity parityBits = 0; // and advance to next Parity Byte diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index ec99ab99..60833f18 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -12,6 +12,7 @@ #ifndef __ISO14443A_H #define __ISO14443A_H + #include "common.h" #include "mifaresniff.h" @@ -70,8 +71,6 @@ typedef struct { } tUart; - -extern byte_t oddparity (const byte_t bt); extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); extern void AppendCrc14443a(uint8_t *data, int len); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index a3d6609d..8f141d65 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -16,6 +16,7 @@ #include "mifarecmd.h" #include "apps.h" #include "util.h" +#include "parity.h" #include "crc.h" // the block number for the ISO14443-4 PCB @@ -595,9 +596,9 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ // Return 1 if the nonce is invalid else return 0 int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { - return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ - (oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ - (oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; + return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ + (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ + (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; } @@ -770,7 +771,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // Parity validity check for (j = 0; j < 4; j++) { - par_array[j] = (oddparity(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); + par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); } ncount = 0; diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 48fcd57a..6c843778 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -13,6 +13,7 @@ #include "proxmark3.h" #include "apps.h" #include "util.h" +#include "parity.h" #include "string.h" #include "iso14443crc.h" @@ -50,7 +51,7 @@ void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, u data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; if((i&0x0007) == 0) par[i>>3] = 0; - par[i>>3] |= (((filter(pcs->odd) ^ oddparity(bt)) & 0x01)<<(7-(i&0x0007))); + par[i>>3] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007))); } return; } @@ -99,7 +100,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, for (pos = 0; pos < 4; pos++) { ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; - par[0] |= (((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) << (7-pos)); + par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos)); } ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); @@ -193,7 +194,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN for (pos = 0; pos < 4; pos++) { mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; - par[0] |= (((filter(pcs->odd) ^ oddparity(nr[pos])) & 0x01) << (7-pos)); + par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos)); } // Skip 32 bits in pseudo random generator @@ -204,7 +205,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN { nt = prng_successor(nt,8); mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); - par[0] |= (((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) << (7-pos)); + par[0] |= (((filter(pcs->odd) ^ oddparity8(nt)) & 0x01) << (7-pos)); } // Transmit reader nonce and reader answer @@ -427,7 +428,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl for (pos = 0; pos < 18; pos++) { d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; - par[pos>>3] |= (((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); + par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); } ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); diff --git a/client/Makefile b/client/Makefile index 1df870b5..36d0c994 100644 --- a/client/Makefile +++ b/client/Makefile @@ -67,6 +67,7 @@ CMDSRCS = crapto1/crapto1.c\ loclass/fileutils.c\ whereami.c\ mifarehost.c\ + parity.c\ crc.c \ crc16.c \ crc64.c \ @@ -92,9 +93,11 @@ CMDSRCS = crapto1/crapto1.c\ cmdlfawid.c \ cmdlfcotag.c\ cmdlfem4x.c \ + cmdlfgproxii.c \ cmdlfhid.c \ cmdlfhitag.c \ cmdlfio.c \ + cmdlfindala.c \ cmdlfpcf7931.c\ cmdlfpresco.c\ cmdlfpyramid.c\ diff --git a/client/cmddata.c b/client/cmddata.c index 49c94674..1acce2ed 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -444,72 +444,6 @@ int Cmdaskbiphdemod(const char *Cmd) return ASKbiphaseDemod(Cmd, true); } -//could be split to a gProxII file -//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("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("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("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("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]); - } - //now 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); - - if (fmtLen==36){ - FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); - Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); - PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); - } else if(fmtLen==26){ - FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7); - Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7); - PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); - } else { - PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen); - PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8)); - } - PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3); - setDemodBuf(DemodBuffer+ans, 96, 0); - return 1; -} - //by marshmellow - see ASKDemod int Cmdaskrawdemod(const char *Cmd) { @@ -1056,59 +990,6 @@ int PSKDemod(const char *Cmd, bool verbose) 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("Error1: %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("Error2: %d",ans); - return -1; - } - setDemodBuf(DemodBuffer, size, (size_t)startIdx); - if (invert) - if (g_debugMode) - PrintAndLog("Had to invert bits"); - - PrintAndLog("BitLen: %d",DemodBufferLen); - //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 UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2); - } 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 UID=%s (%x%08x%08x%08x%08x%08x%08x)", - sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7); - } - if (g_debugMode){ - PrintAndLog("DEBUG: printing demodbuffer:"); - printDemodBuff(); - } - return 1; -} - int CmdPSKNexWatch(const char *Cmd) { if (!PSKDemod("", false)) return 0; @@ -1829,7 +1710,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)"}, - {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II 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, "bin2hex -- Converts binary to hexadecimal"}, @@ -1854,7 +1734,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)"}, {"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)"}, diff --git a/client/cmddata.h b/client/cmddata.h index 552a37a1..86d905b1 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -23,7 +23,6 @@ int CmdData(const char *Cmd); void printDemodBuff(void); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); int CmdPrintDemodBuff(const char *Cmd); -int CmdG_Prox_II_Demod(const char *Cmd); int Cmdaskrawdemod(const char *Cmd); int Cmdaskmandemod(const char *Cmd); int AutoCorrelate(int window, bool SaveGrph, bool verbose); @@ -59,7 +58,6 @@ 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 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); diff --git a/client/cmdhf.c b/client/cmdhf.c index cb71b93b..dcfb1bdd 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -16,6 +16,7 @@ #include "data.h" #include "ui.h" #include "iso14443crc.h" +#include "parity.h" #include "cmdmain.h" #include "cmdparser.h" #include "cmdhf.h" @@ -481,14 +482,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 != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + if (protocol != ISO_14443B && (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]); diff --git a/client/cmdlf.c b/client/cmdlf.c index f34637db..10a70d7c 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -35,6 +35,8 @@ #include "cmdlfviking.h" // for viking menu #include "cmdlfcotag.h" // for COTAG menu #include "cmdlfvisa2000.h" // for VISA2000 menu +#include "cmdlfindala.h" // for indala menu +#include "cmdlfgproxii.h"// for gproxii menu bool g_lf_threshold_set = false; static int CmdHelp(const char *Cmd); @@ -195,243 +197,7 @@ int CmdFlexdemod(const char *Cmd) RepaintGraphWindow(); return 0; -} - -int CmdIndalaDemod(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; - // 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 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 usage_lf_read(void) { @@ -1278,9 +1044,11 @@ static command_t CommandTable[] = {"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"}, {"cotag", CmdLFCOTAG, 1, "{ COTAG RFIDs... }"}, {"em", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, + {"gproxii", CmdLF_G_Prox_II, 1, "{ G Prox II tags... }"}, {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, {"io", CmdLFIO, 1, "{ ioProx tags... }"}, + {"indala", CmdLFINDALA, 1, "{ Indala tags... }"}, {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"}, {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"}, {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, @@ -1291,8 +1059,6 @@ static command_t CommandTable[] = {"cmdread", CmdLFCommandRead, 0, " ['H'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'H' for 134)"}, {"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"}, {"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) - 'u' to search for unknown tags"}, {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, diff --git a/client/cmdlfgproxii.c b/client/cmdlfgproxii.c new file mode 100644 index 00000000..06bd53eb --- /dev/null +++ b/client/cmdlfgproxii.c @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// +// 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 G Prox II tag commands +//----------------------------------------------------------------------------- +#include +#include +#include +#include "cmdlfgproxii.h" +#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" +static int CmdHelp(const char *Cmd); + +//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("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("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("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("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]); + } + //now 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); + + if (fmtLen==36){ + FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); + Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); + PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); + } else if(fmtLen==26){ + FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7); + Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7); + PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); + } else { + PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen); + PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8)); + } + PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3); + setDemodBuf(DemodBuffer+ans, 96, 0); + return 1; +} +//by marshmellow +//see ASKDemod for what args are accepted +int CmdG_Prox_II_Read(const char *Cmd) { + // read lf silently + CmdLFRead("s"); + // get samples silently + getSamples("10000",false); + // demod and output viking ID + return CmdG_Prox_II_Demod(Cmd); +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from the GraphBuffer"}, + {"read", CmdG_Prox_II_Read, 0, "Attempt to read and Extract tag data from the antenna"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLF_G_Prox_II(const char *Cmd) { + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfgproxii.h b/client/cmdlfgproxii.h new file mode 100644 index 00000000..35d982f4 --- /dev/null +++ b/client/cmdlfgproxii.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 G Prox II tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFGPROXII_H__ +#define CMDLFGPROXII_H__ +extern int CmdLF_G_Prox_II(const char *Cmd); +extern int CmdG_Prox_II_Demod(const char *Cmd); +extern int CmdG_Prox_II_Read(const char *Cmd); +#endif diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 47a85a1a..718cb703 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -17,6 +17,7 @@ #include "cmdparser.h" #include "common.h" #include "util.h" +#include "parity.h" #include "hitag2.h" #include "hitagS.h" #include "cmdmain.h" @@ -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 { diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c new file mode 100644 index 00000000..1a1d2a06 --- /dev/null +++ b/client/cmdlfindala.c @@ -0,0 +1,339 @@ +//----------------------------------------------------------------------------- +// +// 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 +//----------------------------------------------------------------------------- + +#include +#include +#include "cmdlfindala.h" +#include "proxmark3.h" +#include "ui.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" //for g_debugMode, demodbuff cmds +#include "lfdemod.h" //for indala26decode +#include "util.h" //for sprint_bin_break +#include "cmdlf.h" //for CmdLFRead +#include "cmdmain.h" //for clearCommandBuffer + +static int CmdHelp(const char *Cmd); + +// Indala 26 bit decode +// by marshmellow +// optional arguments - same as PSKDemod (clock & invert & maxerr) +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("Error1: %i",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("Error2: %i",startIdx); + return -1; + } + setDemodBuf(DemodBuffer, size, (size_t)startIdx); + if (invert) + if (g_debugMode) + PrintAndLog("Had to invert bits"); + + PrintAndLog("BitLen: %d",DemodBufferLen); + //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 UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2); + } else if (DemodBufferLen==224) { + 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 UID=%s (%x%08x%08x%08x%08x%08x%08x)", + sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7); + } + if (g_debugMode) { + PrintAndLog("DEBUG: printing demodbuffer:"); + printDemodBuff(); + } + return 1; +} + +int CmdIndalaRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("30000",false); + return CmdIndalaDecode(""); +} + +// 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 CmdIndalaDemod(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; + // 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 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; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"}, + {"read", CmdIndalaRead, 0, "Read an Indala Prox tag from the antenna"}, + {"clone", CmdIndalaClone, 0, " ['l']-- Clone Indala to T55x7 (tag must be on antenna)(UID in HEX)(option 'l' for 224 UID"}, + {"altdemod", CmdIndalaDemod, 1, "['224'] -- Alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, + //{"sim", CmdIndalaSim, 0, " -- indala tag simulator"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFINDALA(const char *Cmd) { + 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 00000000..78502419 --- /dev/null +++ b/client/cmdlfindala.h @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// +// 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__ + +extern int CmdLFINDALA(const char *Cmd); +extern int CmdIndalaDecode(const char *Cmd); +extern int CmdIndalaRead(const char *Cmd); +extern int CmdIndalaClone(const char *Cmd); + +#endif diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h index 801df8a9..5e80fbb1 100644 --- a/client/cmdlfpresco.h +++ b/client/cmdlfpresco.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 Presco tag commands //----------------------------------------------------------------------------- #ifndef CMDLFPRESCO_H__ #define CMDLFPRESCO_H__ diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h index 80d81d2a..786e5db8 100644 --- a/client/cmdlfpyramid.h +++ b/client/cmdlfpyramid.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 Farpoint / Pyramid commands //----------------------------------------------------------------------------- #ifndef CMDLFPYRAMID_H__ #define CMDLFPYRAMID_H__ diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 601c29f2..838bf79d 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -51,7 +51,6 @@ uint64_t getVikingBits(uint32_t id) { return ((uint64_t)0xF2 << 56) | ((uint64_t)id << 8) | checksum; } -//could be moved to a viking file //by marshmellow //see ASKDemod for what args are accepted int CmdVikingDemod(const char *Cmd) { diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h index cdaad26f..a45dd9a8 100644 --- a/client/cmdlfviking.h +++ b/client/cmdlfviking.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 viking tag commands //----------------------------------------------------------------------------- #ifndef CMDLFVIKING_H__ #define CMDLFVIKING_H__ @@ -14,4 +14,3 @@ extern int CmdVikingRead(const char *Cmd); extern int CmdVikingClone(const char *Cmd); extern int CmdVikingSim(const char *Cmd); #endif - diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 292fa1a3..61669035 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -4,7 +4,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency visa 200 tag commands +// Low frequency visa 2000 tag commands // by iceman //----------------------------------------------------------------------------- diff --git a/client/cmdlfvisa2000.h b/client/cmdlfvisa2000.h index 611768b2..e54ded3b 100644 --- a/client/cmdlfvisa2000.h +++ b/client/cmdlfvisa2000.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 visa 2000 commands //----------------------------------------------------------------------------- #ifndef CMDLFVISA2000_H__ #define CMDLFVISA2000_H__ diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index 01351731..9187460b 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -18,7 +18,9 @@ Copyright (C) 2008-2014 bla */ #include "crapto1.h" + #include +#include "parity.h" #if !defined LOWMEM && defined __GNUC__ static uint8_t filterlut[1 << 20]; @@ -117,8 +119,8 @@ update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) { uint32_t p = *item >> 25; - p = p << 1 | parity(*item & mask1); - p = p << 1 | parity(*item & mask2); + p = p << 1 | evenparity32(*item & mask1); + p = p << 1 | evenparity32(*item & mask2); *item = p << 24 | (*item & 0xffffff); } @@ -174,10 +176,10 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, if(rem == -1) { for(e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); + *e = *e << 1 ^ evenparity32(*e & LF_POLY_EVEN) ^ !!(in & 4); for(o = o_head; o <= o_tail; ++o, ++sl) { sl->even = *o; - sl->odd = *e ^ parity(*o & LF_POLY_ODD); + sl->odd = *e ^ evenparity32(*o & LF_POLY_ODD); sl[1].odd = sl[1].even = 0; } } @@ -329,30 +331,30 @@ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) continue; for(j = 0; j < 19; ++j) - low = low << 1 | parity(i & S1[j]); + low = low << 1 | evenparity32(i & S1[j]); for(j = 0; j < 32; ++j) - hi[j] = parity(i & T1[j]); + hi[j] = evenparity32(i & T1[j]); for(; tail >= table; --tail) { for(j = 0; j < 3; ++j) { *tail = *tail << 1; - *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); + *tail |= evenparity32((i & C1[j]) ^ (*tail & C2[j])); if(filter(*tail) != oks[29 + j]) goto continue2; } for(j = 0; j < 19; ++j) - win = win << 1 | parity(*tail & S2[j]); + win = win << 1 | evenparity32(*tail & S2[j]); win ^= low; for(j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); + win = win << 1 ^ hi[j] ^ evenparity32(*tail & T2[j]); if(filter(win) != eks[j]) goto continue2; } - *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ parity(LF_POLY_ODD & win); + *tail = *tail << 1 | evenparity32(LF_POLY_EVEN & *tail); + sl->odd = *tail ^ evenparity32(LF_POLY_ODD & win); sl->even = win; ++sl; sl->odd = sl->even = 0; @@ -380,7 +382,7 @@ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) out ^= !!in; out ^= (ret = filter(s->odd)) & !!fb; - s->even |= parity(out) << 23; + s->even |= evenparity32(out) << 23; return ret; } /** lfsr_rollback_byte @@ -486,11 +488,11 @@ check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], nr = ks1 ^ (prefix | c << 5); rr = ks2 ^ rresp; - good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; + good &= evenparity32(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); + good &= evenparity32(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); + good &= evenparity32(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); + good &= evenparity32(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); + good &= evenparity32(rr & 0x000000ff) ^ parities[c][7] ^ ks3; } return sl + good; diff --git a/common/crapto1/crapto1.h b/common/crapto1/crapto1.h index 96ab96a2..8e79d224 100644 --- a/common/crapto1/crapto1.h +++ b/common/crapto1/crapto1.h @@ -53,7 +53,7 @@ int nonce_distance(uint32_t from, uint32_t to); int __i;\ for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ for(__i = FSIZE - 1; __i >= 0; __i--)\ - if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ + if(BIT(FILTER, __i) ^ evenparity32(__M & 0xFF01))\ break;\ else if(__i)\ __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ @@ -63,24 +63,6 @@ int nonce_distance(uint32_t from, uint32_t to); #define LF_POLY_EVEN (0x870804) #define BIT(x, n) ((x) >> (n) & 1) #define BEBIT(x, n) BIT(x, (n) ^ 24) -static inline int parity(uint32_t x) -{ -#if !defined __i386__ || !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return BIT(0x6996, x & 0xf); -#else - __asm( "movl %1, %%eax\n" - "mov %%ax, %%cx\n" - "shrl $0x10, %%eax\n" - "xor %%ax, %%cx\n" - "xor %%ch, %%cl\n" - "setpo %%al\n" - "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx"); - return x; -#endif -} static inline int filter(uint32_t const x) { uint32_t f; diff --git a/common/crapto1/crypto1.c b/common/crapto1/crypto1.c index 61f6fe66..19b71cbb 100644 --- a/common/crapto1/crypto1.c +++ b/common/crapto1/crypto1.c @@ -18,7 +18,9 @@ Copyright (C) 2008-2008 bla */ #include "crapto1.h" + #include +#include "parity.h" #define SWAPENDIAN(x)\ (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) @@ -73,7 +75,7 @@ uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) feedin ^= !!in; feedin ^= LF_POLY_ODD & s->odd; feedin ^= LF_POLY_EVEN & s->even; - s->even = s->even << 1 | parity(feedin); + s->even = s->even << 1 | evenparity32(feedin); t = s->odd, s->odd = s->even, s->even = t; diff --git a/common/parity.c b/common/parity.c new file mode 100644 index 00000000..5eabd3ef --- /dev/null +++ b/common/parity.c @@ -0,0 +1,28 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +// parity functions (all defined in parity.h) +//----------------------------------------------------------------------------- + +#include + +const uint8_t OddByteParity[256] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 +}; diff --git a/common/parity.h b/common/parity.h new file mode 100644 index 00000000..615fdeee --- /dev/null +++ b/common/parity.h @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +// Parity functions +//----------------------------------------------------------------------------- + +// all functions defined in header file by purpose. Allows compiler optimizations. + +#ifndef __PARITY_H +#define __PARITY_H + +#include +#include + +extern const uint8_t OddByteParity[256]; + + +static inline bool oddparity8(const uint8_t x) { + return OddByteParity[x]; +} + + +static inline bool evenparity8(const uint8_t x) { + return !OddByteParity[x]; +} + + +static inline bool evenparity32(uint32_t x) +{ +#if !defined __GNUC__ + x ^= x >> 16; + x ^= x >> 8; + return evenparity8(x); +#else + return __builtin_parity(x); +#endif +} + + +static inline bool oddparity32(uint32_t x) +{ +#if !defined __GNUC__ + x ^= x >> 16; + x ^= x >> 8; + return oddparity8(x); +#else + return !__builtin_parity(x); +#endif +} + +#endif /* __PARITY_H */ diff --git a/tools/mfkey/Makefile b/tools/mfkey/Makefile index 1744e35a..fc6170e4 100755 --- a/tools/mfkey/Makefile +++ b/tools/mfkey/Makefile @@ -1,10 +1,10 @@ -VPATH = ../../common/crapto1 ../../client +VPATH = ../../common ../../common/crapto1 ../../client CC = gcc LD = gcc CFLAGS = -std=c99 -D_ISOC99_SOURCE -I../../common -I../../client -Wall -O3 LDFLAGS = -OBJS = crypto1.o crapto1.o util.o mfkey.o +OBJS = crypto1.o crapto1.o parity.o util.o mfkey.o EXES = mfkey32 mfkey64 WINEXES = $(patsubst %, %.exe, $(EXES))