]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge remote-tracking branch 'upstream/master'
authormarshmellow42 <marshmellowrf@gmail.com>
Tue, 21 Mar 2017 14:40:29 +0000 (10:40 -0400)
committermarshmellow42 <marshmellowrf@gmail.com>
Tue, 21 Mar 2017 14:40:29 +0000 (10:40 -0400)
20 files changed:
client/Makefile
client/cmddata.c
client/cmdhfmf.c
client/cmdlfcotag.c
client/graph.c
client/mifarehost.c
client/mifarehost.h
client/nonce2key.c [new file with mode: 0644]
client/nonce2key.h [new file with mode: 0644]
client/nonce2key/nonce2key.c [deleted file]
client/nonce2key/nonce2key.h [deleted file]
client/obj/nonce2key/.dummy [deleted file]
client/scripting.c
client/scripts/mifare_autopwn.lua
common/crapto1/crapto1.c
common/crapto1/crapto1.h
common/lfdemod.c
common/lfdemod.h
tools/nonce2key/Makefile [deleted file]
tools/nonce2key/nonce2key.c [deleted file]

index 79e0cc31d3a05c016c322c8135fb91949c4db33b..ac7e6f9804b51da30dc47472262d1e14be88ef07 100644 (file)
@@ -58,7 +58,7 @@ CORESRCS =    uart.c \
 
 CMDSRCS =      crapto1/crapto1.c\
                        crapto1/crypto1.c\
-                       nonce2key/nonce2key.c\
+                       nonce2key.c\
                        loclass/cipher.c \
                        loclass/cipherutils.c \
                        loclass/des.c \
index e07e72235a8c624d22880372e67c8468bb20bd92..983edd7217264472020ef5b1b28a39bd2eb2c609 100644 (file)
@@ -29,6 +29,9 @@
 uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
 uint8_t g_debugMode=0;
 size_t DemodBufferLen=0;
+//size_t g_demodStartIdx=0;
+//uint8_t g_demodClock=0;
+
 static int CmdHelp(const char *Cmd);
 
 //set the demod buffer with given array of binary (one bit per byte)
@@ -253,6 +256,7 @@ void printEM410x(uint32_t hi, uint64_t id)
        return;
 }
 
+//should be moved to cmdlfem4x.c
 int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo )
 {
        size_t idx = 0;
@@ -274,7 +278,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo )
        }
        return 0;
 }
-
+//should be moved to cmdlfem4x.c
 int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose)
 {
        bool st = true;
@@ -282,6 +286,7 @@ int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose)
        return AskEm410xDecode(verbose, hi, lo);
 }
 
+//should be moved to cmdlfem4x.c
 //by marshmellow
 //takes 3 arguments - clock, invert and maxErr as integers
 //attempts to demodulate ask while decoding manchester
@@ -451,7 +456,8 @@ int Cmdmandecoderaw(const char *Cmd)
 
        sscanf(Cmd, "%i %i", &invert, &maxErr);
        size=i;
-       errCnt=manrawdecode(BitStream, &size, invert);
+       uint8_t alignPos = 0;
+       errCnt=manrawdecode(BitStream, &size, invert, &alignPos);
        if (errCnt>=maxErr){
                PrintAndLog("Too many errors: %d",errCnt);
                return 0;
@@ -590,6 +596,7 @@ 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
@@ -655,6 +662,7 @@ int CmdG_Prox_II_Demod(const char *Cmd)
        return 1;
 }
 
+//could be moved to a viking file
 //by marshmellow
 //see ASKDemod for what args are accepted
 int CmdVikingDemod(const char *Cmd)
@@ -1038,6 +1046,7 @@ int CmdFSKrawdemod(const char *Cmd)
        return FSKrawDemod(Cmd, true);
 }
 
+//move to cmdlfhid.c
 //by marshmellow (based on existing demod + holiman's refactor)
 //HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
 //print full HID Prox ID and some bit format details if found
@@ -1124,6 +1133,7 @@ int CmdFSKdemodHID(const char *Cmd)
        return 1;
 }
 
+
 //by marshmellow
 //Paradox Prox demod - FSK RF/50 with preamble of 00001111 (then manchester encoded)
 //print full Paradox Prox ID and some bit format details if found
@@ -1751,7 +1761,8 @@ int NRZrawDemod(const char *Cmd, bool verbose)
        size_t BitLen = getFromGraphBuf(BitStream);
        if (BitLen==0) return 0;
        int errCnt=0;
-       errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert);
+       int clkStartIdx = 0;
+       errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert, &clkStartIdx);
        if (errCnt > maxErr){
                if (g_debugMode) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
                return 0;
@@ -2264,13 +2275,13 @@ int CmdDirectionalThreshold(const char *Cmd)
                if (GraphBuffer[i] >= upThres && GraphBuffer[i] > lastValue)
                {
                        lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
-                       GraphBuffer[i] = 1;
+                       GraphBuffer[i] = 127;
                }
                // Apply second threshold to samples heading down
                else if (GraphBuffer[i] <= downThres && GraphBuffer[i] < lastValue)
                {
                        lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
-                       GraphBuffer[i] = -1;
+                       GraphBuffer[i] = -127;
                }
                else
                {
index b3f7acb2a1e1d0f12a16e2dd7341fdfc172e4d7e..47660a6e2b3c4e4eb2e933ef91aba71c2eda694b 100644 (file)
 #include "ui.h"\r
 #include "mifarehost.h"\r
 #include "mifare.h"\r
-#include "nonce2key/nonce2key.h"\r
+#include "nonce2key.h"\r
 \r
 #define NESTED_SECTOR_RETRY     10                     // how often we try mfested() until we give up\r
 \r
 \r
 static int CmdHelp(const char *Cmd);\r
 \r
+\r
 int CmdHF14AMifare(const char *Cmd)\r
 {\r
-       uint32_t uid = 0;\r
-       uint32_t nt = 0, nr = 0;\r
-       uint64_t par_list = 0, ks_list = 0, r_key = 0;\r
-       int16_t isOK = 0;\r
-\r
-       UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}};\r
-\r
-       // message\r
-       printf("-------------------------------------------------------------------------\n");\r
-       printf("Executing command. Expected execution time: 25sec on average  :-)\n");\r
-       printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n");\r
-       printf("-------------------------------------------------------------------------\n");\r
-\r
-       \r
- start:\r
-    clearCommandBuffer();\r
-    SendCommand(&c);\r
-       \r
-       //flush queue\r
-       while (ukbhit()) {\r
-               int c = getchar(); (void) c;\r
-       }\r
-       \r
-       // wait cycle\r
-       while (true) {\r
-        printf(".");\r
-               fflush(stdout);\r
-               if (ukbhit()) {\r
-                       getchar();\r
-                       printf("\naborted via keyboard!\n");\r
-                       break;\r
-               }\r
-               \r
-               UsbCommand resp;\r
-               if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {\r
-                       isOK  = resp.arg[0];\r
-                       uid = (uint32_t)bytes_to_num(resp.d.asBytes +  0, 4);\r
-                       nt =  (uint32_t)bytes_to_num(resp.d.asBytes +  4, 4);\r
-                       par_list = bytes_to_num(resp.d.asBytes +  8, 8);\r
-                       ks_list = bytes_to_num(resp.d.asBytes +  16, 8);\r
-                       nr = bytes_to_num(resp.d.asBytes + 24, 4);\r
-                       printf("\n\n");\r
-                       switch (isOK) {\r
-                               case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;\r
-                               case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;\r
-                               case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;\r
-                               case -4 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown");\r
-                                                       PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break;\r
-                               default: ;\r
-                       }\r
-                       break;\r
-               }\r
-       }       \r
+       int isOK = 0;\r
+       uint64_t key = 0;\r
 \r
-       printf("\n");\r
-       \r
-       // error\r
-       if (isOK != 1) return 1;\r
-       \r
-       // execute original function from util nonce2key\r
-       if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key)) {\r
-               isOK = 2;\r
-               PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);    \r
-               PrintAndLog("Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce...");\r
-               c.arg[0] = false;\r
-               goto start;\r
-       } else {\r
-               isOK = 0;\r
-               printf("------------------------------------------------------------------\n");\r
-               PrintAndLog("Found valid key:%012" PRIx64 " \n", r_key);\r
+       isOK = mfDarkside(&key);\r
+       switch (isOK) {\r
+               case -1 : PrintAndLog("Button pressed. Aborted."); return 1;\r
+               case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests)."); return 1;\r
+               case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable)."); return 1;\r
+               case -4 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown");\r
+                                       PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour."); return 1;\r
+               case -5 : PrintAndLog("Aborted via keyboard.");  return 1;\r
+               default : PrintAndLog("Found valid key:%012" PRIx64 "\n", key);\r
        }\r
        \r
        PrintAndLog("");\r
        return 0;\r
 }\r
 \r
+\r
 int CmdHF14AMfWrBl(const char *Cmd)\r
 {\r
        uint8_t blockNo = 0;\r
@@ -1090,7 +1034,7 @@ void readerAttack(nonces_t ar_resp[], bool setEmulatorMem, bool doStandardAttack
                                                }\r
                                        }\r
                                }\r
-                       } else if (tryMfk32_moebius(ar_resp[i+ATTACK_KEY_COUNT], &key)) {\r
+                       } else if (mfkey32_moebius(ar_resp[i+ATTACK_KEY_COUNT], &key)) {\r
                                uint8_t sectorNum = ar_resp[i+ATTACK_KEY_COUNT].sector;\r
                                uint8_t keyType = ar_resp[i+ATTACK_KEY_COUNT].keytype;\r
 \r
index 0f68064e55e83063af045d603db51113c284cc9b..71f171157a4bcfea6f8d6edcf8c89db96e2e820a 100644 (file)
@@ -43,7 +43,8 @@ int CmdCOTAGDemod(const char *Cmd) {
        size_t bitlen = COTAG_BITS;
        memcpy(bits, DemodBuffer, COTAG_BITS);
        
-       int err = manrawdecode(bits, &bitlen, 1);
+       uint8_t alignPos = 0;
+       int err = manrawdecode(bits, &bitlen, 1, &alignPos);
        if (err){
                if (g_debugMode) PrintAndLog("DEBUG: Error - COTAG too many errors: %d", err);
                return -1;
index f40f093a38f4996f21e1b02f3393488932bfb59f..995a32da6a451cba3e57eb34ec8503f98c15c213 100644 (file)
@@ -218,7 +218,8 @@ uint8_t GetNrzClock(const char str[], bool printAns, bool verbose)
                        PrintAndLog("Failed to copy from graphbuffer");
                return -1;
        }
-       clock = DetectNRZClock(grph, size, 0);
+       size_t clkStartIdx = 0;
+       clock = DetectNRZClock(grph, size, 0, &clkStartIdx);
        // Only print this message if we're not looping something
        if (printAns){
                PrintAndLog("Auto-detected clock rate: %d", clock);
index 411a44c1ee82c8ac9dc79954e53b1c528be7d043..cbd79cf7536d5475288f1d02518f09075889de49 100644 (file)
 #define TRACE_ERROR                                            0xFF\r
 \r
 \r
-// MIFARE\r
+static int compare_uint64(const void *a, const void *b) {\r
+       // didn't work: (the result is truncated to 32 bits)\r
+       //return (*(int64_t*)b - *(int64_t*)a);\r
+\r
+       // better:\r
+       if (*(uint64_t*)b == *(uint64_t*)a) return 0;\r
+       else if (*(uint64_t*)b < *(uint64_t*)a) return 1;\r
+       else return -1;\r
+}\r
+\r
+\r
+// create the intersection (common members) of two sorted lists. Lists are terminated by -1. Result will be in list1. Number of elements is returned.\r
+static uint32_t intersection(uint64_t *list1, uint64_t *list2)\r
+{\r
+       if (list1 == NULL || list2 == NULL) {\r
+               return 0;\r
+       }\r
+       uint64_t *p1, *p2, *p3;\r
+       p1 = p3 = list1; \r
+       p2 = list2;\r
+\r
+       while ( *p1 != -1 && *p2 != -1 ) {\r
+               if (compare_uint64(p1, p2) == 0) {\r
+                       *p3++ = *p1++;\r
+                       p2++;\r
+               }\r
+               else {\r
+                       while (compare_uint64(p1, p2) < 0) ++p1;\r
+                       while (compare_uint64(p1, p2) > 0) ++p2;\r
+               }\r
+       }\r
+       *p3 = -1;\r
+       return p3 - list1;\r
+}\r
+\r
+\r
+// Darkside attack (hf mf mifare)\r
+static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {\r
+       struct Crypto1State *states;\r
+       uint32_t i, pos, rr; //nr_diff;\r
+       uint8_t bt, ks3x[8], par[8][8];\r
+       uint64_t key_recovered;\r
+       static uint64_t *keylist;\r
+       rr = 0;\r
+\r
+       // Reset the last three significant bits of the reader nonce\r
+       nr &= 0xffffff1f;\r
+\r
+       for (pos=0; pos<8; pos++) {\r
+               ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;\r
+               bt = (par_info >> (pos*8)) & 0xff;\r
+               for (i=0; i<8; i++)     {\r
+                               par[7-pos][i] = (bt >> i) & 0x01;\r
+               }\r
+       }\r
+\r
+       states = lfsr_common_prefix(nr, rr, ks3x, par, (par_info == 0));\r
+\r
+       if (states == NULL) {\r
+               *keys = NULL;\r
+               return 0;\r
+       }\r
+\r
+       keylist = (uint64_t*)states;\r
+       \r
+       for (i = 0; keylist[i]; i++) {\r
+               lfsr_rollback_word(states+i, uid^nt, 0);\r
+               crypto1_get_lfsr(states+i, &key_recovered);\r
+               keylist[i] = key_recovered;\r
+       }\r
+       keylist[i] = -1;\r
+\r
+       *keys = keylist;\r
+       return i;\r
+}\r
+\r
+\r
+int mfDarkside(uint64_t *key)\r
+{\r
+       uint32_t uid = 0;\r
+       uint32_t nt = 0, nr = 0;\r
+       uint64_t par_list = 0, ks_list = 0;\r
+       uint64_t *keylist = NULL, *last_keylist = NULL;\r
+       uint32_t keycount = 0;\r
+       int16_t isOK = 0;\r
+\r
+       UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}};\r
+\r
+       // message\r
+       printf("-------------------------------------------------------------------------\n");\r
+       printf("Executing command. Expected execution time: 25sec on average\n");\r
+       printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n");\r
+       printf("-------------------------------------------------------------------------\n");\r
+\r
+       \r
+       while (true) {\r
+               clearCommandBuffer();\r
+               SendCommand(&c);\r
+               \r
+               //flush queue\r
+               while (ukbhit()) {\r
+                       int c = getchar(); (void) c;\r
+               }\r
+               \r
+               // wait cycle\r
+               while (true) {\r
+                       printf(".");\r
+                       fflush(stdout);\r
+                       if (ukbhit()) {\r
+                               return -5;\r
+                               break;\r
+                       }\r
+                       \r
+                       UsbCommand resp;\r
+                       if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {\r
+                               isOK  = resp.arg[0];\r
+                               if (isOK < 0) {\r
+                                       return isOK;\r
+                               }\r
+                               uid = (uint32_t)bytes_to_num(resp.d.asBytes +  0, 4);\r
+                               nt =  (uint32_t)bytes_to_num(resp.d.asBytes +  4, 4);\r
+                               par_list = bytes_to_num(resp.d.asBytes +  8, 8);\r
+                               ks_list = bytes_to_num(resp.d.asBytes +  16, 8);\r
+                               nr = bytes_to_num(resp.d.asBytes + 24, 4);\r
+                               break;\r
+                       }\r
+               }       \r
+\r
+               if (par_list == 0 && c.arg[0] == true) {\r
+                       PrintAndLog("Parity is all zero. Most likely this card sends NACK on every failed authentication.");\r
+                       PrintAndLog("Attack will take a few seconds longer because we need two consecutive successful runs.");\r
+               }\r
+               c.arg[0] = false;\r
+\r
+               keycount = nonce2key(uid, nt, nr, par_list, ks_list, &keylist);\r
+\r
+               if (keycount == 0) {\r
+                       PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);    \r
+                       PrintAndLog("This is expected to happen in 25%% of all cases. Trying again with a different reader nonce...");\r
+                       continue;\r
+               }\r
+\r
+               qsort(keylist, keycount, sizeof(*keylist), compare_uint64);\r
+               keycount = intersection(last_keylist, keylist);\r
+               if (keycount == 0) {\r
+                       free(last_keylist);\r
+                       last_keylist = keylist;\r
+                       continue;\r
+               }\r
+\r
+               if (keycount > 1) {\r
+                       PrintAndLog("Found %u possible keys. Trying to authenticate with each of them ...\n", keycount);\r
+               } else {\r
+                       PrintAndLog("Found a possible key. Trying to authenticate...\n");\r
+               }               \r
+\r
+               *key = -1;\r
+               uint8_t keyBlock[USB_CMD_DATA_SIZE];\r
+               int max_keys = USB_CMD_DATA_SIZE/6;\r
+               for (int i = 0; i < keycount; i += max_keys) {\r
+                       int size = keycount - i > max_keys ? max_keys : keycount - i;\r
+                       for (int j = 0; j < size; j++) {\r
+                               if (last_keylist == NULL) {\r
+                                       num_to_bytes(keylist[i*max_keys + j], 6, keyBlock);\r
+                               } else {\r
+                                       num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock);\r
+                               }\r
+                       }\r
+                       if (!mfCheckKeys(0, 0, false, size, keyBlock, key)) {\r
+                               break;\r
+                       }\r
+               }       \r
+               \r
+               if (*key != -1) {\r
+                       free(last_keylist);\r
+                       free(keylist);\r
+                       break;\r
+               } else {\r
+                       PrintAndLog("Authentication failed. Trying again...");\r
+                       free(last_keylist);\r
+                       last_keylist = keylist;\r
+               }\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
 int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){\r
 \r
        *key = 0;\r
@@ -49,16 +236,6 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
        return 0;\r
 }\r
 \r
-int compar_int(const void * a, const void * b) {\r
-       // didn't work: (the result is truncated to 32 bits)\r
-       //return (*(uint64_t*)b - *(uint64_t*)a);\r
-\r
-       // better:\r
-       if (*(uint64_t*)b == *(uint64_t*)a) return 0;\r
-       else if (*(uint64_t*)b > *(uint64_t*)a) return 1;\r
-       else return -1;\r
-}\r
-\r
 // Compare 16 Bits out of cryptostate\r
 int Compare16Bits(const void * a, const void * b) {\r
        if ((*(uint64_t*)b & 0x00ff000000ff0000) == (*(uint64_t*)a & 0x00ff000000ff0000)) return 0;\r
@@ -100,7 +277,7 @@ void* nested_worker_thread(void *arg)
        return statelist->head.slhead;\r
 }\r
 \r
-int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate) \r
+int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) \r
 {\r
        uint16_t i;\r
        uint32_t uid;\r
@@ -178,8 +355,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
                        while (Compare16Bits(p1, p2) == 1) p2++;\r
                }\r
        }\r
-       p3->even = 0; p3->odd = 0;\r
-       p4->even = 0; p4->odd = 0;\r
+       *(uint64_t*)p3 = -1;\r
+       *(uint64_t*)p4 = -1;\r
        statelists[0].len = p3 - statelists[0].head.slhead;\r
        statelists[1].len = p4 - statelists[1].head.slhead;\r
        statelists[0].tail.sltail=--p3;\r
@@ -187,24 +364,9 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
 \r
        // the statelists now contain possible keys. The key we are searching for must be in the\r
        // intersection of both lists. Create the intersection:\r
-       qsort(statelists[0].head.keyhead, statelists[0].len, sizeof(uint64_t), compar_int);\r
-       qsort(statelists[1].head.keyhead, statelists[1].len, sizeof(uint64_t), compar_int);\r
-\r
-       uint64_t *p5, *p6, *p7;\r
-       p5 = p7 = statelists[0].head.keyhead; \r
-       p6 = statelists[1].head.keyhead;\r
-       while (p5 <= statelists[0].tail.keytail && p6 <= statelists[1].tail.keytail) {\r
-               if (compar_int(p5, p6) == 0) {\r
-                       *p7++ = *p5++;\r
-                       p6++;\r
-               }\r
-               else {\r
-                       while (compar_int(p5, p6) == -1) p5++;\r
-                       while (compar_int(p5, p6) == 1) p6++;\r
-               }\r
-       }\r
-       statelists[0].len = p7 - statelists[0].head.keyhead;\r
-       statelists[0].tail.keytail=--p7;\r
+       qsort(statelists[0].head.keyhead, statelists[0].len, sizeof(uint64_t), compare_uint64);\r
+       qsort(statelists[1].head.keyhead, statelists[1].len, sizeof(uint64_t), compare_uint64);\r
+       statelists[0].len = intersection(statelists[0].head.keyhead, statelists[1].head.keyhead);\r
 \r
        memset(resultKey, 0, 6);\r
        // The list may still contain several key candidates. Test each of them with mfCheckKeys\r
index e628ba3ab0ba9d2c51abf9ca3004e8acdc848d32..a9db4ec384a7c950e9c57a12d9d21cb9861cf913 100644 (file)
@@ -22,8 +22,9 @@
 \r
 extern char logHexFileName[FILE_PATH_SIZE];\r
 \r
-extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);\r
-extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);\r
+extern int mfDarkside(uint64_t *key);\r
+extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *ResultKeys, bool calibrate);\r
+extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key);\r
 \r
 extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);\r
 extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);\r
diff --git a/client/nonce2key.c b/client/nonce2key.c
new file mode 100644 (file)
index 0000000..acd551e
--- /dev/null
@@ -0,0 +1,137 @@
+//-----------------------------------------------------------------------------
+// Merlok - June 2011
+// Roel - Dec 2009
+// Unknown author
+//
+// 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.
+//-----------------------------------------------------------------------------
+// MIFARE Darkside hack
+//-----------------------------------------------------------------------------
+
+#include "nonce2key.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mifarehost.h"
+#include "util.h"
+#include "crapto1/crapto1.h"
+
+// recover key from 2 different reader responses on same tag challenge
+bool mfkey32(nonces_t data, uint64_t *outputkey) {
+       struct Crypto1State *s,*t;
+       uint64_t outkey = 0;
+       uint64_t key = 0;     // recovered key
+       bool isSuccess = false;
+       uint8_t counter = 0;
+
+       uint64_t t1 = msclock();
+
+       s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
+
+       for(t = s; t->odd | t->even; ++t) {
+               lfsr_rollback_word(t, 0, 0);
+               lfsr_rollback_word(t, data.nr, 1);
+               lfsr_rollback_word(t, data.cuid ^ data.nonce, 0);
+               crypto1_get_lfsr(t, &key);
+               crypto1_word(t, data.cuid ^ data.nonce, 0);
+               crypto1_word(t, data.nr2, 1);
+               if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce, 64))) {
+                       //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
+                       outkey = key;
+                       counter++;
+                       if (counter == 20) break;
+               }
+       }
+       isSuccess = (counter == 1);
+       t1 = msclock() - t1;
+       //if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter);
+       *outputkey = ( isSuccess ) ? outkey : 0;
+       crypto1_destroy(s);
+       /* //un-comment to save all keys to a stats.txt file 
+       FILE *fout;
+       if ((fout = fopen("stats.txt","ab")) == NULL) { 
+               PrintAndLog("Could not create file name stats.txt");
+               return 1;
+       }
+       fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
+       fclose(fout);
+       */
+       return isSuccess;
+}
+
+// recover key from 2 reader responses on 2 different tag challenges
+bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) {
+       struct Crypto1State *s, *t;
+       uint64_t outkey  = 0;
+       uint64_t key       = 0;                 // recovered key
+       bool isSuccess = false;
+       int counter = 0;
+       
+       //PrintAndLog("Enter mfkey32_moebius");
+       uint64_t t1 = msclock();
+
+       s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
+  
+       for(t = s; t->odd | t->even; ++t) {
+               lfsr_rollback_word(t, 0, 0);
+               lfsr_rollback_word(t, data.nr, 1);
+               lfsr_rollback_word(t, data.cuid ^ data.nonce, 0);
+               crypto1_get_lfsr(t, &key);
+               
+               crypto1_word(t, data.cuid ^ data.nonce2, 0);
+               crypto1_word(t, data.nr2, 1);
+               if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce2, 64))) {
+                       //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
+                       outkey=key;
+                       ++counter;
+                       if (counter==20)
+                               break;
+               }
+       }
+       isSuccess       = (counter == 1);
+       t1 = msclock() - t1;
+       // PrintAndLog("Time in mfkey32_moebius: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter);
+       *outputkey = ( isSuccess ) ? outkey : 0;
+       crypto1_destroy(s);
+       /* // un-comment to output all keys to stats.txt
+       FILE *fout;
+       if ((fout = fopen("stats.txt","ab")) == NULL) { 
+               PrintAndLog("Could not create file name stats.txt");
+               return 1;
+       }
+       fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
+       fclose(fout);
+       */
+       return isSuccess;
+}
+
+// recover key from reader response and tag response of one authentication sequence
+int mfkey64(nonces_t data, uint64_t *outputkey){
+       uint64_t key    = 0;                            // recovered key
+       uint32_t ks2;                                           // keystream used to encrypt reader response
+       uint32_t ks3;                                           // keystream used to encrypt tag response
+       struct Crypto1State *revstate;
+       
+       // PrintAndLog("Enter mfkey64");
+       uint64_t t1 = msclock();
+       
+       // Extract the keystream from the messages
+       ks2 = data.ar ^ prng_successor(data.nonce, 64);
+       ks3 = data.at ^ prng_successor(data.nonce, 96);
+       revstate = lfsr_recovery64(ks2, ks3);
+       lfsr_rollback_word(revstate, 0, 0);
+       lfsr_rollback_word(revstate, 0, 0);
+       lfsr_rollback_word(revstate, data.nr, 1);
+       lfsr_rollback_word(revstate, data.cuid ^ data.nonce, 0);
+       crypto1_get_lfsr(revstate, &key);
+       // PrintAndLog("Found Key: [%012" PRIx64 "]", key);
+       crypto1_destroy(revstate);
+       *outputkey = key;
+       
+       t1 = msclock() - t1;
+       // PrintAndLog("Time in mfkey64: %.1f seconds \n", (float)t1/1000.0);
+       return 0;
+}
diff --git a/client/nonce2key.h b/client/nonce2key.h
new file mode 100644 (file)
index 0000000..795f239
--- /dev/null
@@ -0,0 +1,36 @@
+//-----------------------------------------------------------------------------
+// Merlok - June 2011
+// Roel - Dec 2009
+// Unknown author
+//
+// 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.
+//-----------------------------------------------------------------------------
+// MIFARE Darkside hack
+//-----------------------------------------------------------------------------
+
+#ifndef __NONCE2KEY_H
+#define __NONCE2KEY_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct {
+                         uint32_t cuid;
+                         uint8_t  sector;
+                         uint8_t  keytype;
+                         uint32_t nonce;
+                         uint32_t ar;
+                         uint32_t nr;
+                         uint32_t at;
+                         uint32_t nonce2;
+                         uint32_t ar2;
+                         uint32_t nr2;
+                       } nonces_t;
+
+bool mfkey32(nonces_t data, uint64_t *outputkey);
+bool mfkey32_moebius(nonces_t data, uint64_t *outputkey);
+int mfkey64(nonces_t data, uint64_t *outputkey);
+
+#endif
diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c
deleted file mode 100644 (file)
index d146b72..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011
-// Roel - Dec 2009
-// Unknown author
-//
-// 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.
-//-----------------------------------------------------------------------------
-// MIFARE Darkside hack
-//-----------------------------------------------------------------------------
-
-#include "nonce2key.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "mifarehost.h"
-#include "ui.h"
-#include "util.h"
-#include "crapto1/crapto1.h"
-
-int compar_state(const void * a, const void * b) {
-       // didn't work: (the result is truncated to 32 bits)
-       //return (*(int64_t*)b - *(int64_t*)a);
-
-       // better:
-       if (*(int64_t*)b == *(int64_t*)a) return 0;
-       else if (*(int64_t*)b > *(int64_t*)a) return 1;
-       else return -1;
-}
-
-int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key) {
-  struct Crypto1State *state;
-  uint32_t i, pos, rr, nr_diff, key_count;//, ks1, ks2;
-  uint8_t bt, ks3x[8], par[8][8];
-  uint64_t key_recovered;
-  int64_t *state_s;
-  static uint32_t last_uid;
-  static int64_t *last_keylist;
-  rr = 0;
-  
-  if (last_uid != uid && last_keylist != NULL)
-  {
-       free(last_keylist);
-       last_keylist = NULL;
-  }
-  last_uid = uid;
-
-  // Reset the last three significant bits of the reader nonce
-  nr &= 0xffffff1f;
-  
-  PrintAndLog("\nuid(%08x) nt(%08x) par(%016" PRIx64") ks(%016" PRIx64") nr(%08" PRIx32")\n\n",uid,nt,par_info,ks_info,nr);
-
-  for (pos=0; pos<8; pos++)
-  {
-    ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
-    bt = (par_info >> (pos*8)) & 0xff;
-    for (i=0; i<8; i++)
-    {
-      par[7-pos][i] = (bt >> i) & 0x01;
-    }
-  }
-
-  printf("|diff|{nr}    |ks3|ks3^5|parity         |\n");
-  printf("+----+--------+---+-----+---------------+\n");
-  for (i=0; i<8; i++)
-  {
-    nr_diff = nr | i << 5;
-    printf("| %02x |%08x|",i << 5, nr_diff);
-    printf(" %01x |  %01x  |",ks3x[i], ks3x[i]^5);
-    for (pos=0; pos<7; pos++) printf("%01x,", par[i][pos]);
-    printf("%01x|\n", par[i][7]);
-  }
-  
-       if (par_info == 0)
-               PrintAndLog("Parity is all zero, trying special attack! Just wait for few more seconds...");
-  
-       state = lfsr_common_prefix(nr, rr, ks3x, par);
-       state_s = (int64_t*)state;
-       
-       //char filename[50] ;
-    //sprintf(filename, "nt_%08x_%d.txt", nt, nr);
-    //printf("name %s\n", filename);
-       //FILE* fp = fopen(filename,"w");
-       for (i = 0; (state) && *(state_s + i); i++)
-       {
-               lfsr_rollback_word(state+i, uid^nt, 0);
-               crypto1_get_lfsr(state + i, &key_recovered);
-               *(state_s + i) = key_recovered;
-               //fprintf(fp, "%012" PRIx64 "\n",key_recovered);
-       }
-       //fclose(fp);
-       
-       if(!state)
-               return 1;
-       
-       qsort(state_s, i, sizeof(*state_s), compar_state);
-       *(state_s + i) = -1;
-       
-       //Create the intersection:
-       if (par_info == 0 ) {
-               if (last_keylist != NULL) {
-                       int64_t *p1, *p2, *p3;
-                       p1 = p3 = last_keylist; 
-                       p2 = state_s;
-                       while ( *p1 != -1 && *p2 != -1 ) {
-                               if (compar_state(p1, p2) == 0) {
-                                       printf("p1:%" PRIx64" p2:%" PRIx64 " p3:%" PRIx64" key:%012" PRIx64 "\n",(uint64_t)(p1-last_keylist),(uint64_t)(p2-state_s),(uint64_t)(p3-last_keylist),*p1);
-                                       *p3++ = *p1++;
-                                       p2++;
-                               }
-                               else {
-                                       while (compar_state(p1, p2) == -1) ++p1;
-                                       while (compar_state(p1, p2) == 1) ++p2;
-                               }
-                       }
-                       key_count = p3 - last_keylist;
-               } else {
-                       key_count = 0;
-               }
-       } else {
-               last_keylist = state_s;
-               key_count = i;
-       }
-       
-       printf("key_count:%d\n", key_count);
-
-       // The list may still contain several key candidates. Test each of them with mfCheckKeys
-       for (i = 0; i < key_count; i++) {
-               uint8_t keyBlock[6];
-               uint64_t key64;
-               key64 = *(last_keylist + i);
-               num_to_bytes(key64, 6, keyBlock);
-               key64 = 0;
-               if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) {
-                       *key = key64;
-                       free(last_keylist);
-                       last_keylist = NULL;
-                       if (par_info == 0)
-                               free(state);
-                       return 0;
-               }
-       }       
-
-       
-       free(last_keylist);
-       last_keylist = state_s;
-       
-       return 1;
-}
-
-// 32 bit recover key from 2 nonces
-bool mfkey32(nonces_t data, uint64_t *outputkey) {
-       struct Crypto1State *s,*t;
-       uint64_t outkey = 0;
-       uint64_t key=0;     // recovered key
-       uint32_t uid     = data.cuid;
-       uint32_t nt      = data.nonce;  // first tag challenge (nonce)
-       uint32_t nr0_enc = data.nr;  // first encrypted reader challenge
-       uint32_t ar0_enc = data.ar;  // first encrypted reader response
-       uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
-       uint32_t ar1_enc = data.ar2; // second encrypted reader response
-       uint64_t t1 = msclock();
-       bool isSuccess = false;
-       uint8_t counter=0;
-
-       s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
-
-       for(t = s; t->odd | t->even; ++t) {
-               lfsr_rollback_word(t, 0, 0);
-               lfsr_rollback_word(t, nr0_enc, 1);
-               lfsr_rollback_word(t, uid ^ nt, 0);
-               crypto1_get_lfsr(t, &key);
-               crypto1_word(t, uid ^ nt, 0);
-               crypto1_word(t, nr1_enc, 1);
-               if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
-                       //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
-                       outkey = key;
-                       counter++;
-                       if (counter==20) break;
-               }
-       }
-       isSuccess = (counter == 1);
-       t1 = msclock() - t1;
-       //if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter);
-       *outputkey = ( isSuccess ) ? outkey : 0;
-       crypto1_destroy(s);
-       /* //un-comment to save all keys to a stats.txt file 
-       FILE *fout;
-       if ((fout = fopen("stats.txt","ab")) == NULL) { 
-               PrintAndLog("Could not create file name stats.txt");
-               return 1;
-       }
-       fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
-       fclose(fout);
-       */
-       return isSuccess;
-}
-
-bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey) {
-       struct Crypto1State *s, *t;
-       uint64_t outkey  = 0;
-       uint64_t key       = 0;                      // recovered key
-       uint32_t uid     = data.cuid;
-       uint32_t nt0     = data.nonce;  // first tag challenge (nonce)
-       uint32_t nr0_enc = data.nr;  // first encrypted reader challenge
-       uint32_t ar0_enc = data.ar; // first encrypted reader response
-       uint32_t nt1     = data.nonce2; // second tag challenge (nonce)
-       uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
-       uint32_t ar1_enc = data.ar2; // second encrypted reader response        
-       bool isSuccess = false;
-       int counter = 0;
-       
-       //PrintAndLog("Enter mfkey32_moebius");
-       uint64_t t1 = msclock();
-
-       s = lfsr_recovery32(ar0_enc ^ prng_successor(nt0, 64), 0);
-  
-       for(t = s; t->odd | t->even; ++t) {
-               lfsr_rollback_word(t, 0, 0);
-               lfsr_rollback_word(t, nr0_enc, 1);
-               lfsr_rollback_word(t, uid ^ nt0, 0);
-               crypto1_get_lfsr(t, &key);
-               
-               crypto1_word(t, uid ^ nt1, 0);
-               crypto1_word(t, nr1_enc, 1);
-               if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt1, 64))) {
-                       //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
-                       outkey=key;
-                       ++counter;
-                       if (counter==20)
-                               break;
-               }
-       }
-       isSuccess       = (counter == 1);
-       t1 = msclock() - t1;
-       //if ( t1 > 0 ) PrintAndLog("Time in mfkey32_moebius: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter);
-       *outputkey = ( isSuccess ) ? outkey : 0;
-       crypto1_destroy(s);
-       /* // un-comment to output all keys to stats.txt
-       FILE *fout;
-       if ((fout = fopen("stats.txt","ab")) == NULL) { 
-               PrintAndLog("Could not create file name stats.txt");
-               return 1;
-       }
-       fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
-       fclose(fout);
-       */
-       return isSuccess;
-}
-
-int tryMfk64_ex(uint8_t *data, uint64_t *outputkey){
-       uint32_t uid    = le32toh(data);
-       uint32_t nt     = le32toh(data+4);  // tag challenge
-       uint32_t nr_enc = le32toh(data+8);  // encrypted reader challenge
-       uint32_t ar_enc = le32toh(data+12); // encrypted reader response        
-       uint32_t at_enc = le32toh(data+16);     // encrypted tag response
-       return tryMfk64(uid, nt, nr_enc, ar_enc, at_enc, outputkey);
-}
-
-int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey){
-       uint64_t key    = 0;                            // recovered key
-       uint32_t ks2;                                           // keystream used to encrypt reader response
-       uint32_t ks3;                                           // keystream used to encrypt tag response
-       struct Crypto1State *revstate;
-       
-       PrintAndLog("Enter mfkey64");
-       uint64_t t1 = msclock();
-       
-       // Extract the keystream from the messages
-       ks2 = ar_enc ^ prng_successor(nt, 64);
-       ks3 = at_enc ^ prng_successor(nt, 96);
-       revstate = lfsr_recovery64(ks2, ks3);
-       lfsr_rollback_word(revstate, 0, 0);
-       lfsr_rollback_word(revstate, 0, 0);
-       lfsr_rollback_word(revstate, nr_enc, 1);
-       lfsr_rollback_word(revstate, uid ^ nt, 0);
-       crypto1_get_lfsr(revstate, &key);
-       PrintAndLog("Found Key: [%012" PRIx64 "]", key);
-       crypto1_destroy(revstate);
-       *outputkey = key;
-       
-       t1 = msclock() - t1;
-       if ( t1 > 0 ) PrintAndLog("Time in mfkey64: %.1f seconds \n", (float)t1/1000.0);
-       return 0;
-}
-
diff --git a/client/nonce2key/nonce2key.h b/client/nonce2key/nonce2key.h
deleted file mode 100644 (file)
index 07ad18c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-//-----------------------------------------------------------------------------
-// Merlok - June 2011
-// Roel - Dec 2009
-// Unknown author
-//
-// 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.
-//-----------------------------------------------------------------------------
-// MIFARE Darkside hack
-//-----------------------------------------------------------------------------
-
-#ifndef __NONCE2KEY_H
-#define __NONCE2KEY_H
-
-#include <stdint.h>
-#include <stdbool.h>
-
-typedef struct {
-                         uint32_t cuid;
-                         uint8_t  sector;
-                         uint8_t  keytype;
-                         uint32_t nonce;
-                         uint32_t ar;
-                         uint32_t nr;
-                         uint32_t nonce2;
-                         uint32_t ar2;
-                         uint32_t nr2;
-                       } nonces_t;
-
-int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key); 
-bool mfkey32(nonces_t data, uint64_t *outputkey);
-bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey);
-int tryMfk64_ex(uint8_t *data, uint64_t *outputkey);
-int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey);
-
-//uint64_t mfkey32(uint32_t uid, uint32_t nt, uint32_t nr0_enc, uint32_t ar0_enc, uint32_t nr1_enc, uint32_t ar1_enc);
-
-#endif
diff --git a/client/obj/nonce2key/.dummy b/client/obj/nonce2key/.dummy
deleted file mode 100644 (file)
index e69de29..0000000
index 0d491df76ab92f6d3560da1e2e36af890f0af158..d68adb3ee66ab82406bd448f147b315d8eb83832 100644 (file)
@@ -8,6 +8,8 @@
 // Some lua scripting glue to proxmark core.
 //-----------------------------------------------------------------------------
 
+#include "scripting.h"
+
 #include <stdlib.h>
 #include <lua.h>
 #include <lualib.h>
@@ -15,9 +17,8 @@
 #include "proxmark3.h"
 #include "usb_cmd.h"
 #include "cmdmain.h"
-#include "scripting.h"
 #include "util.h"
-#include "nonce2key/nonce2key.h"
+#include "mifarehost.h"
 #include "../common/iso15693tools.h"
 #include "iso14443crc.h"
 #include "../common/crc16.h"
@@ -125,49 +126,27 @@ static int returnToLuaWithError(lua_State *L, const char* fmt, ...)
        return 2;
 }
 
-static int l_nonce2key(lua_State *L){
-
-       size_t size;
-       const char *p_uid = luaL_checklstring(L, 1, &size);
-       if(size != 4)  return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
-
-       const char *p_nt = luaL_checklstring(L, 2, &size);
-       if(size != 4)  return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
-
-       const char *p_nr = luaL_checklstring(L, 3, &size);
-       if(size != 4)  return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
-
-       const char *p_par_info = luaL_checklstring(L, 4, &size);
-       if(size != 8)  return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
-
-       const char *p_pks_info = luaL_checklstring(L, 5, &size);
-       if(size != 8)  return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
-
-
-       uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
-       uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
-
-       uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
-       uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
-       uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
-
-       uint64_t key = 0;
-
-       int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
+static int l_mfDarkside(lua_State *L){
 
+       uint64_t key;
+       
+       int retval = mfDarkside(&key);
+       
        //Push the retval on the stack
-       lua_pushinteger(L,retval);
+       lua_pushinteger(L, retval);
 
        //Push the key onto the stack
        uint8_t dest_key[8];
-       num_to_bytes(key,sizeof(dest_key),dest_key);
+       num_to_bytes(key, sizeof(dest_key), dest_key);
 
        //printf("Pushing to lua stack: %012" PRIx64 "\n",key);
-       lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
+       lua_pushlstring(L,(const char *)dest_key, sizeof(dest_key));
 
        return 2; //Two return values
 }
+
 //static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));}
+
 static int l_clearCommandBuffer(lua_State *L){
        clearCommandBuffer();
        return 0;
@@ -499,7 +478,7 @@ int set_pm3_libraries(lua_State *L)
        static const luaL_Reg libs[] = {
                {"SendCommand",                 l_SendCommand},
                {"WaitForResponseTimeout",      l_WaitForResponseTimeout},
-               {"nonce2key",                   l_nonce2key},
+               {"mfDarkside",                  l_mfDarkside},
                //{"PrintAndLog",                 l_PrintAndLog},
                {"foobar",                      l_foobar},
                {"ukbhit",                      l_ukbhit},
index ce6db3c00767091c2ab5cd3a61e7d643bcea8d5a..e68f7a75d188d915e142bb9b10e63341203f3b22 100644 (file)
@@ -8,7 +8,7 @@ author = "Martin Holst Swende"
 
 desc =
 [[
-This is a which automates cracking and dumping mifare classic cards. It sets itself into 
+This is a script which automates cracking and dumping mifare classic cards. It sets itself into 
 'listening'-mode, after which it cracks and dumps any mifare classic card that you 
 place by the device. 
 
@@ -63,91 +63,6 @@ function wait_for_mifare()
        return nil, "Aborted by user"
 end
 
-function mfcrack()
-       core.clearCommandBuffer()
-       -- Build the mifare-command
-       local cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 1}
-       
-       local retry = true
-       while retry do
-               core.SendCommand(cmd:getBytes())
-               local key, errormessage = mfcrack_inner()
-               -- Success?
-               if key then return key end
-               -- Failure? 
-               if errormessage then return nil, errormessage end
-               -- Try again..set arg1 to 0 this time. 
-
-               cmd = Command:new{cmd = cmds.CMD_READER_MIFARE, arg1 = 0}
-       end     
-       return nil, "Aborted by user"
-end
-
-
-function mfcrack_inner()
-       while not core.ukbhit() do              
-               local result = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
-               if result then
-
-                       --[[
-                       I don't understand, they cmd and args are defined as uint32_t, however, 
-                       looking at the returned data, they all look like 64-bit things: 
-
-                       print("result", bin.unpack("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH", result))
-
-                       FF      00      00      00      00      00      00      00      <-- 64 bits of data
-                       FE      FF      FF      FF      00      00      00      00      <-- 64 bits of data
-                       00      00      00      00      00      00      00      00      <-- 64 bits of data
-                       00      00      00      00      00      00      00      00      <-- 64 bits of data
-                       04      7F      12      E2      00             <-- this is where 'data' starts
-
-                       So below I use LI to pick out the "FEFF FFFF", don't know why it works.. 
-                       --]]
-                       -- Unpacking the arg-parameters
-                       local count,cmd,isOK = bin.unpack('LI',result)
-                       --print("response", isOK)--FF FF FF FF
-                       if isOK == 0xFFFFFFFF then
-                               return nil, "Button pressed. Aborted."
-                       elseif isOK == 0xFFFFFFFE then
-                               return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
-                       elseif isOK == 0xFFFFFFFD then
-                               return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
-                       elseif isOK == 0xFFFFFFFC then
-                               return nil, "The card's random number generator behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
-                       elseif isOK ~= 1 then 
-                               return nil, "Error occurred" 
-                       end
-
-
-                       -- The data-part is left
-                       -- Starts 32 bytes in, at byte 33
-                       local data = result:sub(33)
-
-                       -- A little helper
-                       local get = function(num)
-                               local x = data:sub(1,num)
-                               data = data:sub(num+1)
-                               return x
-                       end
-
-                       local uid,nt,pl = get(4),get(4),get(8)
-                       local ks,nr = get(8),get(4)
-
-                       local status, key = core.nonce2key(uid,nt, nr, pl,ks)
-                       if not status then return status,key end
-
-                       if status > 0 then 
-                               print("Key not found (lfsr_common_prefix problem)")
-                               -- try again
-                               return nil,nil
-                       else
-                               return key
-                       end
-               end
-       end
-       return nil, "Aborted by user"
-end
-
 function nested(key,sak)
        local typ = 1
        if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k
@@ -209,8 +124,15 @@ function main(args)
                        print("Card found, commencing crack", uid)
                        -- Crack it
                        local key, cnt
-                       res,err = mfcrack()
-                       if not res then return oops(err) end
+                       err, res = core.mfDarkside()
+                       if     err == -1 then return oops("Button pressed. Aborted.") 
+                       elseif err == -2 then return oops("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).")
+                       elseif err == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).")
+                       elseif err == -4 then return oops([[
+Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown
+generating polynomial with 16 effective bits only, but shows unexpected behaviour.]])
+                       elseif err == -5 then return oops("Aborted via keyboard.")
+                       end
                        -- The key is actually 8 bytes, so a 
                        -- 6-byte key is sent as 00XXXXXX
                        -- This means we unpack it as first
index 82c5b65bc2a8e32ca5e38e117192cefa24a0f59c..013517310eda970204fe2a25f834f63439fa809b 100644 (file)
@@ -465,18 +465,9 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
  */
 static struct Crypto1State*
 check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
-               uint32_t odd, uint32_t even, struct Crypto1State* sl)
+               uint32_t odd, uint32_t even, struct Crypto1State* sl, uint32_t no_par)
 {
-       uint32_t ks1, nr, ks2, rr, ks3, c, good = 1, no_par = 1;
-
-       for (int i = 0; i < 8; i++) {
-               for (int j = 0; j < 8; j++) {
-                       if (parities[i][j] != 0) {
-                               no_par = 0;
-                               break;
-                       }
-               }
-       }
+       uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;
 
        for(c = 0; good && c < 8; ++c) {
                sl->odd = odd ^ fastfwd[1][c];
@@ -510,7 +501,7 @@ check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
  * Implentation of the common prefix attack.
  */
 struct Crypto1State*
-lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8])
+lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint32_t no_par)
 {
        struct Crypto1State *statelist, *s;
        uint32_t *odd, *even, *o, *e, top;
@@ -518,7 +509,7 @@ lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8])
        odd = lfsr_prefix_ks(ks, 1);
        even = lfsr_prefix_ks(ks, 0);
 
-       s = statelist = malloc((sizeof *statelist) << 20);
+       s = statelist = malloc((sizeof *statelist) << 22); // was << 20. Need more for no_par special attack. Enough???
        if(!s || !odd || !even) {
                free(statelist);
                statelist = 0;
@@ -530,7 +521,7 @@ lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8])
                        for(top = 0; top < 64; ++top) {
                                *o += 1 << 21;
                                *e += (!(top & 7) + 1) << 21;
-                               s = check_pfx_parity(pfx, rr, par, *o, *e, s);
+                               s = check_pfx_parity(pfx, rr, par, *o, *e, s, no_par);
                        }
 
        s->odd = s->even = 0;
index aef59b03d8215747cd044eeb2e59b141301b3716..e718b1f2f278d9f8cc7adfd7693021724524c6ac 100644 (file)
@@ -41,7 +41,7 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in);
 struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3);
 uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd);
 struct Crypto1State*
-lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]);
+lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint32_t no_par);
 
 
 uint8_t lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb);
index 1b53c44560fac2c7722903cd5d8f89fd90be1191..8307a89088f57c5e468665c602dea7effcc0e984 100644 (file)
@@ -5,16 +5,45 @@
 // at your option, any later version. See the LICENSE.txt file for the text of
 // the license.
 //-----------------------------------------------------------------------------
-// Low frequency demod/decode commands
+// Low frequency demod/decode commands   - by marshmellow, holiman, iceman and
+//                                         many others who came before
+//
+// NOTES: 
+// LF Demod functions are placed here to allow the flexability to use client or
+// device side. Most BUT NOT ALL of these functions are currenlty safe for 
+// device side use currently. (DetectST for example...)
+//
+// There are likely many improvements to the code that could be made, please
+// make suggestions...
+//
+// we tried to include author comments so any questions could be directed to 
+// the source.
+//
+// There are 4 main sections of code below:
+// Utilities Section: 
+//    for general utilities used by multiple other functions
+// Clock / Bitrate Detection Section:
+//    for clock detection functions for each modulation
+// Modulation Demods &/or Decoding Section:
+//    for main general modulation demodulating and encoding decoding code.
+// Tag format detection section:
+//    for detection of specific tag formats within demodulated data
+//
+// marshmellow
 //-----------------------------------------------------------------------------
 
-#include <stdlib.h>
-#include "lfdemod.h"
-#include <string.h>
+#include <string.h>  // for memset, memcmp and size_t
+#include <stdint.h>  // for uint_32+
+#include <stdbool.h> // for bool
+
+//**********************************************************************************************
+//---------------------------------Utilities Section--------------------------------------------
+//**********************************************************************************************
+#define LOWEST_DEFAULT_CLOCK 32
+#define FSK_PSK_THRESHOLD   123
 
 //to allow debug print calls when used not on device
 void dummy(char *fmt, ...){}
-
 #ifndef ON_DEVICE
 #include "ui.h"
 #include "cmdparser.h"
@@ -25,21 +54,18 @@ void dummy(char *fmt, ...){}
 #define prnt dummy
 #endif
 
-uint8_t justNoise(uint8_t *BitStream, size_t size)
-{
-       static const uint8_t THRESHOLD = 123;
+uint8_t justNoise(uint8_t *BitStream, size_t size) {
        //test samples are not just noise
        uint8_t justNoise1 = 1;
        for(size_t idx=0; idx < size && justNoise1 ;idx++){
-               justNoise1 = BitStream[idx] < THRESHOLD;
+               justNoise1 = BitStream[idx] < FSK_PSK_THRESHOLD;
        }
        return justNoise1;
 }
 
 //by marshmellow
 //get high and low values of a wave with passed in fuzz factor. also return noise test = 1 for passed or 0 for only noise
-int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo)
-{
+int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) {
        *high=0;
        *low=255;
        // get high and low thresholds 
@@ -47,7 +73,7 @@ int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi
                if (BitStream[i] > *high) *high = BitStream[i];
                if (BitStream[i] < *low) *low = BitStream[i];
        }
-       if (*high < 123) return -1; // just noise
+       if (*high < FSK_PSK_THRESHOLD) return -1; // just noise
        *high = ((*high-128)*fuzzHi + 12800)/100;
        *low = ((*low-128)*fuzzLo + 12800)/100;
        return 1;
@@ -56,8 +82,7 @@ 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 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);
@@ -69,8 +94,7 @@ uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType)
 // by marshmellow
 // takes a array of binary values, start position, length of bits per parity (includes parity bit),
 //   Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) 
-size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
-{
+size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) {
        uint32_t parityWd = 0;
        size_t j = 0, bitCnt = 0;
        for (int word = 0; word < (bLen); word+=pLen) {
@@ -99,8 +123,7 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
 // takes a array of binary values, length of bits per parity (includes parity bit),
 //   Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
 //   Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
-size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType)
-{
+size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) {
        uint32_t parityWd = 0;
        size_t j = 0, bitCnt = 0;
        for (int word = 0; word < sourceLen; word+=pLen-1) {
@@ -124,8 +147,7 @@ size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t p
        return bitCnt;
 }
 
-uint32_t bytebits_to_byte(uint8_t *src, size_t numbits)
-{
+uint32_t bytebits_to_byte(uint8_t *src, size_t numbits) {
        uint32_t num = 0;
        for(int i = 0 ; i < numbits ; i++)
        {
@@ -136,8 +158,7 @@ uint32_t bytebits_to_byte(uint8_t *src, size_t numbits)
 }
 
 //least significant bit first
-uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
-{
+uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits) {
        uint32_t num = 0;
        for(int i = 0 ; i < numbits ; i++)
        {
@@ -146,13 +167,6 @@ uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
        return num;
 }
 
-//by marshmellow
-//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length
-uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx)
-{
-       return (preambleSearchEx(BitStream, preamble, pLen, size, startIdx, false)) ? 1 : 0;
-}
-
 // search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) and length if not fineone 
 // fineone does not look for a repeating preamble for em4x05/4x69 sends preamble once, so look for it once in the first pLen bits
 bool preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone) {
@@ -177,19 +191,25 @@ bool preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t
        return false;
 }
 
+//by marshmellow
+//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length
+uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx) {
+       return (preambleSearchEx(BitStream, preamble, pLen, size, startIdx, false)) ? 1 : 0;
+}
+
 // find start of modulating data (for fsk and psk) in case of beginning noise or slow chip startup.
-size_t findModStart(uint8_t dest[], size_t size, uint8_t threshold_value, uint8_t expWaveSize) {
+size_t findModStart(uint8_t dest[], size_t size, uint8_t expWaveSize) {
        size_t i = 0;
        size_t waveSizeCnt = 0;
        uint8_t thresholdCnt = 0;
-       bool isAboveThreshold = dest[i++] >= threshold_value;
+       bool isAboveThreshold = dest[i++] >= FSK_PSK_THRESHOLD;
        for (; i < size-20; i++ ) {
-               if(dest[i] < threshold_value && isAboveThreshold) {
+               if(dest[i] < FSK_PSK_THRESHOLD && isAboveThreshold) {
                        thresholdCnt++;
                        if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break;                     
                        isAboveThreshold = false;
                        waveSizeCnt = 0;
-               } else if (dest[i] >= threshold_value && !isAboveThreshold) {
+               } else if (dest[i] >= FSK_PSK_THRESHOLD && !isAboveThreshold) {
                        thresholdCnt++;
                        if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break;                     
                        isAboveThreshold = true;
@@ -203,215 +223,77 @@ size_t findModStart(uint8_t dest[], size_t size, uint8_t threshold_value, uint8_
        return i;
 }
 
-//by marshmellow
-//takes 1s and 0s and searches for EM410x format - output EM ID
-uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo)
-{
-       //sanity checks
-       if (*size < 64) return 0;
-       if (BitStream[1]>1) return 0;  //allow only 1s and 0s
+int getClosestClock(int testclk) {
+       uint8_t fndClk[] = {8,16,32,40,50,64,128};
 
-       // 111111111 bit pattern represent start of frame
-       //  include 0 in front to help get start pos
-       uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1};
-       uint8_t errChk = 0;
-       uint8_t FmtLen = 10; // sets of 4 bits = end data 
-       *startIdx = 0;
-       errChk = preambleSearch(BitStream, preamble, sizeof(preamble), size, startIdx);
-       if ( errChk == 0 || (*size != 64 && *size != 128) ) return 0;
-       if (*size == 128) FmtLen = 22; // 22 sets of 4 bits
+       for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++)
+               if (testclk >= fndClk[clkCnt]-(fndClk[clkCnt]/8) && testclk <= fndClk[clkCnt]+1)
+                       return fndClk[clkCnt];
 
-       //skip last 4bit parity row for simplicity
-       *size = removeParity(BitStream, *startIdx + sizeof(preamble), 5, 0, FmtLen * 5);
-       if (*size == 40) { // std em410x format
-               *hi = 0;
-               *lo = ((uint64_t)(bytebits_to_byte(BitStream, 8)) << 32) | (bytebits_to_byte(BitStream + 8, 32));
-       } else if (*size == 88) { // long em format
-               *hi = (bytebits_to_byte(BitStream, 24)); 
-               *lo = ((uint64_t)(bytebits_to_byte(BitStream + 24, 32)) << 32) | (bytebits_to_byte(BitStream + 24 + 32, 32));
-       } else {
-               return 0;
-       }
-       return 1;
+       return 0;
 }
 
-//by marshmellow
-//demodulates strong heavily clipped samples
-int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low)
-{
-       size_t bitCnt=0, smplCnt=0, errCnt=0;
-       uint8_t waveHigh = 0;
-       for (size_t i=0; i < *size; i++){
-               if (BinStream[i] >= high && waveHigh){
-                       smplCnt++;
-               } else if (BinStream[i] <= low && !waveHigh){
-                       smplCnt++;
-               } else { //transition
-                       if ((BinStream[i] >= high && !waveHigh) || (BinStream[i] <= low && waveHigh)){
-                               if (smplCnt > clk-(clk/4)-1) { //full clock
-                                       if (smplCnt > clk + (clk/4)+1) { //too many samples
-                                               errCnt++;
-                                               if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
-                                               BinStream[bitCnt++]=7;
-                                       } else if (waveHigh) {
-                                               BinStream[bitCnt++] = invert;
-                                               BinStream[bitCnt++] = invert;
-                                       } else if (!waveHigh) {
-                                               BinStream[bitCnt++] = invert ^ 1;
-                                               BinStream[bitCnt++] = invert ^ 1;
-                                       }
-                                       waveHigh ^= 1;  
-                                       smplCnt = 0;
-                               } else if (smplCnt > (clk/2) - (clk/4)-1) {
-                                       if (waveHigh) {
-                                               BinStream[bitCnt++] = invert;
-                                       } else if (!waveHigh) {
-                                               BinStream[bitCnt++] = invert ^ 1;
-                                       }
-                                       waveHigh ^= 1;  
-                                       smplCnt = 0;
-                               } else if (!bitCnt) {
-                                       //first bit
-                                       waveHigh = (BinStream[i] >= high);
-                                       smplCnt = 1;
-                               } else {
-                                       smplCnt++;
-                                       //transition bit oops
-                               }
-                       } else { //haven't hit new high or new low yet
-                               smplCnt++;
-                       }
-               }
-       }
-       *size = bitCnt;
-       return errCnt;
+void getNextLow(uint8_t samples[], size_t size, int low, size_t *i) {
+       while ((samples[*i] > low) && (*i < size))
+               *i+=1;
 }
 
-//by marshmellow
-//amplify based on ask edge detection
-void askAmp(uint8_t *BitStream, size_t size)
-{
-       uint8_t Last = 128;
-       for(size_t i = 1; i<size; i++){
-               if (BitStream[i]-BitStream[i-1]>=30) //large jump up
-                       Last = 255;
-               else if(BitStream[i-1]-BitStream[i]>=20) //large jump down
-                       Last = 0;
-
-               BitStream[i-1] = Last;
-       }
-       return;
+void getNextHigh(uint8_t samples[], size_t size, int high, size_t *i) {
+       while ((samples[*i] < high) && (*i < size))
+               *i+=1;
 }
-//by marshmellow
-//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester
-int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType)
-{
-       if (*size==0) return -1;
-       int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default
-       if (*clk==0 || start < 0) return -3;
-       if (*invert != 1) *invert = 0;
-       if (amp==1) askAmp(BinStream, *size);
-       if (g_debugMode==2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp);
 
-       uint8_t initLoopMax = 255;
-       if (initLoopMax > *size) initLoopMax = *size;
-       // Detect high and lows
-       //25% clip in case highs and lows aren't clipped [marshmellow]
-       int high, low;
-       if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) 
-               return -2; //just noise
+// load wave counters
+bool loadWaveCounters(uint8_t samples[], size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low) {
+       size_t i=0, firstLow, firstHigh;
+       size_t testsize = (size < 512) ? size : 512;
 
-       size_t errCnt = 0;
-       // if clean clipped waves detected run alternate demod
-       if (DetectCleanAskWave(BinStream, *size, high, low)) {
-               if (g_debugMode==2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod");
-               errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
-               if (askType) //askman
-                       return manrawdecode(BinStream, size, 0);        
-               else //askraw
-                       return errCnt;
+       if ( getHiLo(samples, testsize, high, low, 80, 80) == -1 ) {
+               if (g_debugMode==2) prnt("DEBUG STT: just noise detected - quitting");
+               return false; //just noise
        }
-       if (g_debugMode==2) prnt("DEBUG ASK: Weak Wave Detected - using weak wave demod");
 
-       int lastBit;              //set first clock check - can go negative
-       size_t i, bitnum = 0;     //output counter
-       uint8_t midBit = 0;
-       uint8_t tol = 0;          //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
-       if (*clk <= 32) tol = 1;  //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
-       size_t MaxBits = 3072;    //max bits to collect
-       lastBit = start - *clk;
+       // get to first full low to prime loop and skip incomplete first pulse
+       getNextHigh(samples, size, *high, &i);
+       getNextLow(samples, size, *low, &i);
+       *skip = i;
 
-       for (i = start; i < *size; ++i) {
-               if (i-lastBit >= *clk-tol){
-                       if (BinStream[i] >= high) {
-                               BinStream[bitnum++] = *invert;
-                       } else if (BinStream[i] <= low) {
-                               BinStream[bitnum++] = *invert ^ 1;
-                       } else if (i-lastBit >= *clk+tol) {
-                               if (bitnum > 0) {
-                                       if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
-                                       BinStream[bitnum++]=7;
-                                       errCnt++;                                               
-                               } 
-                       } else { //in tolerance - looking for peak
-                               continue;
-                       }
-                       midBit = 0;
-                       lastBit += *clk;
-               } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){
-                       if (BinStream[i] >= high) {
-                               BinStream[bitnum++] = *invert;
-                       } else if (BinStream[i] <= low) {
-                               BinStream[bitnum++] = *invert ^ 1;
-                       } else if (i-lastBit >= *clk/2+tol) {
-                               BinStream[bitnum] = BinStream[bitnum-1];
-                               bitnum++;
-                       } else { //in tolerance - looking for peak
-                               continue;
-                       }
-                       midBit = 1;
+       // populate tmpbuff buffer with pulse lengths
+       while (i < size) {
+               // measure from low to low
+               firstLow = i;
+               //find first high point for this wave
+               getNextHigh(samples, size, *high, &i);
+               firstHigh = i;
+
+               getNextLow(samples, size, *low, &i);
+
+               if (*waveCnt >= (size/LOWEST_DEFAULT_CLOCK))
+                       break;
+
+               highToLowWaveLen[*waveCnt] = i - firstHigh; //first high to first low
+               lowToLowWaveLen[*waveCnt] = i - firstLow;
+               *waveCnt += 1;
+               if (i-firstLow < *minClk && i < size) {
+                       *minClk = i - firstLow;
                }
-               if (bitnum >= MaxBits) break;
        }
-       *size = bitnum;
-       return errCnt;
+       return true;
 }
 
 //by marshmellow
-//take 10 and 01 and manchester decode
-//run through 2 times and take least errCnt
-int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert)
-{
-       uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
-       size_t i, ii;
-       uint16_t bestErr = 1000, bestRun = 0;
-       if (*size < 16) return -1;
-       //find correct start position [alignment]
-       for (ii=0;ii<2;++ii){
-               for (i=ii; i<*size-3; i+=2)
-                       if (BitStream[i]==BitStream[i+1])
-                               errCnt++;
+//amplify based on ask edge detection  -  not accurate enough to use all the time
+void askAmp(uint8_t *BitStream, size_t size) {
+       uint8_t Last = 128;
+       for(size_t i = 1; i<size; i++){
+               if (BitStream[i]-BitStream[i-1]>=30) //large jump up
+                       Last = 255;
+               else if(BitStream[i-1]-BitStream[i]>=20) //large jump down
+                       Last = 0;
 
-               if (bestErr>errCnt){
-                       bestErr=errCnt;
-                       bestRun=ii;
-               }
-               errCnt=0;
-       }
-       //decode
-       for (i=bestRun; i < *size-3; i+=2){
-               if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
-                       BitStream[bitnum++]=invert;
-               } else if((BitStream[i] == 0) && BitStream[i+1] == 1){
-                       BitStream[bitnum++]=invert^1;
-               } else {
-                       BitStream[bitnum++]=7;
-               }
-               if(bitnum>MaxBits) break;
+               BitStream[i-1] = Last;
        }
-       *size=bitnum;
-       return bestErr;
+       return;
 }
 
 uint32_t manchesterEncode2Bytes(uint16_t datain) {
@@ -426,543 +308,412 @@ uint32_t manchesterEncode2Bytes(uint16_t datain) {
 
 //by marshmellow
 //encode binary data into binary manchester 
-int ManchesterEncode(uint8_t *BitStream, size_t size)
-{
-       size_t modIdx=20000, i=0;
-       if (size>modIdx) return -1;
+//NOTE: BitStream must have triple the size of "size" available in memory to do the swap
+int ManchesterEncode(uint8_t *BitStream, size_t size) {
+       //allow up to 4K out (means BitStream must be at least 2048+4096 to handle the swap)
+       size = (size>2048) ? 2048 : size;
+       size_t modIdx = size;
+       size_t i;
        for (size_t idx=0; idx < size; idx++){
                BitStream[idx+modIdx++] = BitStream[idx];
                BitStream[idx+modIdx++] = BitStream[idx]^1;
        }
-       for (; i<(size*2); i++){
-               BitStream[i] = BitStream[i+20000];
+       for (i=0; i<(size*2); i++){
+               BitStream[i] = BitStream[i+size];
        }
        return i;
 }
 
-//by marshmellow
-//take 01 or 10 = 1 and 11 or 00 = 0
-//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
-//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
-int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert)
-{
-       uint16_t bitnum = 0;
-       uint16_t errCnt = 0;
-       size_t i = offset;
-       uint16_t MaxBits=512;
-       //if not enough samples - error
-       if (*size < 51) return -1;
-       //check for phase change faults - skip one sample if faulty
-       uint8_t offsetA = 1, offsetB = 1;
-       for (; i<48; i+=2){
-               if (BitStream[i+1]==BitStream[i+2]) offsetA=0; 
-               if (BitStream[i+2]==BitStream[i+3]) offsetB=0;                                  
-       }
-       if (!offsetA && offsetB) offset++;
-       for (i=offset; i<*size-3; i+=2){
-               //check for phase error
-               if (BitStream[i+1]==BitStream[i+2]) {
-                       BitStream[bitnum++]=7;
-                       errCnt++;
-               }
-               if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){
-                       BitStream[bitnum++]=1^invert;
-               } else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){
-                       BitStream[bitnum++]=invert;
-               } else {
-                       BitStream[bitnum++]=7;
-                       errCnt++;
-               }
-               if(bitnum>MaxBits) break;
-       }
-       *size=bitnum;
-       return errCnt;
-}
-
 // by marshmellow
-// demod gProxIIDemod 
-// error returns as -x 
-// success returns start position in BitStream
-// BitStream must contain previously askrawdemod and biphasedemoded data
-int gProxII_Demod(uint8_t BitStream[], size_t *size)
-{
-       size_t startIdx=0;
-       uint8_t preamble[] = {1,1,1,1,1,0};
-
-       uint8_t errChk = preambleSearch(BitStream, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -3; //preamble not found
-       if (*size != 96) return -2; //should have found 96 bits
-       //check first 6 spacer bits to verify format
-       if (!BitStream[startIdx+5] && !BitStream[startIdx+10] && !BitStream[startIdx+15] && !BitStream[startIdx+20] && !BitStream[startIdx+25] && !BitStream[startIdx+30]){
-               //confirmed proper separator bits found
-               //return start position
-               return (int) startIdx;
+// to detect a wave that has heavily clipped (clean) samples
+uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low) {
+       bool allArePeaks = true;
+       uint16_t cntPeaks=0;
+       size_t loopEnd = 512+160;
+       if (loopEnd > size) loopEnd = size;
+       for (size_t i=160; i<loopEnd; i++){
+               if (dest[i]>low && dest[i]<high) 
+                       allArePeaks = false;
+               else
+                       cntPeaks++;
        }
-       return -5; //spacer bits not found - not a valid gproxII
+       if (!allArePeaks){
+               if (cntPeaks > 300) return true;
+       }
+       return allArePeaks;
 }
 
-//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
-size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow)
-{
-       size_t last_transition = 0;
-       size_t idx = 1;
-       if (fchigh==0) fchigh=10;
-       if (fclow==0) fclow=8;
-       //set the threshold close to 0 (graph) or 128 std to avoid static
-       uint8_t threshold_value = 123; 
-       size_t preLastSample = 0;
-       size_t LastSample = 0;
-       size_t currSample = 0;
-       if ( size < 1024 ) return 0; // not enough samples
+//**********************************************************************************************
+//-------------------Clock / Bitrate Detection Section------------------------------------------
+//**********************************************************************************************
 
-       //find start of modulating data in trace 
-       idx = findModStart(dest, size, threshold_value, fchigh);
+// by marshmellow
+// to help detect clocks on heavily clipped samples
+// based on count of low to low
+int DetectStrongAskClock(uint8_t dest[], size_t size, int high, int low, int *clock) {
+       size_t startwave;
+       size_t i = 100;
+       size_t minClk = 255;
+       int shortestWaveIdx = 0;
+               // get to first full low to prime loop and skip incomplete first pulse
+       getNextHigh(dest, size, high, &i);
+       getNextLow(dest, size, low, &i);
 
-       // Need to threshold first sample
-       if(dest[idx] < threshold_value) dest[0] = 0;
-       else dest[0] = 1;
-       idx++;
-       
-       size_t numBits = 0;
-       // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
-       // or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
-       // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
-       //  (could also be fc/5 && fc/7 for fsk1 = 4-9)
-       for(; idx < size-20; idx++) {
-               // threshold current value
+       // loop through all samples
+       while (i < size) {
+               // measure from low to low
+               startwave = i;
 
-               if (dest[idx] < threshold_value) dest[idx] = 0;
-               else dest[idx] = 1;
+               getNextHigh(dest, size, high, &i);
+               getNextLow(dest, size, low, &i);
+               //get minimum measured distance
+               if (i-startwave < minClk && i < size) {
+                       minClk = i - startwave;
+                       shortestWaveIdx = startwave;
+               }
+       }
+       // set clock
+       if (g_debugMode==2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d",minClk);
+       *clock = getClosestClock(minClk);
+       if (*clock == 0) 
+               return 0;
+       
+       return shortestWaveIdx;
+}
 
-               // Check for 0->1 transition
-               if (dest[idx-1] < dest[idx]) {
-                       preLastSample = LastSample;
-                       LastSample = currSample;
-                       currSample = idx-last_transition;
-                       if (currSample < (fclow-2)) {                   //0-5 = garbage noise (or 0-3)
-                               //do nothing with extra garbage
-                       } else if (currSample < (fchigh-1)) {           //6-8 = 8 sample waves  (or 3-6 = 5)
-                               //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
-                               if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){
-                                       dest[numBits-1]=1;
-                               }
-                               dest[numBits++]=1;
+// by marshmellow
+// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
+// maybe somehow adjust peak trimming value based on samples to fix?
+// return start index of best starting position for that clock and return clock (by reference)
+int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) {
+       size_t i=1;
+       uint8_t clk[] = {255,8,16,32,40,50,64,100,128,255};
+       uint8_t clkEnd = 9;
+       uint8_t loopCnt = 255;  //don't need to loop through entire array...
+       if (size <= loopCnt+60) return -1; //not enough samples
+       size -= 60; //sometimes there is a strange end wave - filter out this....
+       //if we already have a valid clock
+       uint8_t clockFnd=0;
+       for (;i<clkEnd;++i)
+               if (clk[i] == *clock) clockFnd = i;
+               //clock found but continue to find best startpos
 
-                       } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage
-                               //do nothing with beginning garbage and reset..  should be rare..
-                               numBits = 0; 
-                       } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
-                               dest[numBits++]=1;
-                       } else {                                        //9+ = 10 sample waves (or 6+ = 7)
-                               dest[numBits++]=0;
+       //get high and low peak
+       int peak, low;
+       if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1;
+       
+       //test for large clean peaks
+       if (!clockFnd){
+               if (DetectCleanAskWave(dest, size, peak, low)==1){
+                       int ans = DetectStrongAskClock(dest, size, peak, low, clock);
+                       if (g_debugMode==2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i",clock, ans);
+                       if (ans > 0) {
+                               return ans; //return shortest wave start position
                        }
-                       last_transition = idx;
                }
        }
-       return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
-}
+       uint8_t ii;
+       uint8_t clkCnt, tol = 0;
+       uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000};
+       uint8_t bestStart[]={0,0,0,0,0,0,0,0,0};
+       size_t errCnt = 0;
+       size_t arrLoc, loopEnd;
 
-//translate 11111100000 to 10
-//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
-size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
-               uint8_t invert, uint8_t fchigh, uint8_t fclow)
-{
-       uint8_t lastval=dest[0];
-       size_t idx=0;
-       size_t numBits=0;
-       uint32_t n=1;
-       for( idx=1; idx < size; idx++) {
-               n++;
-               if (dest[idx]==lastval) continue; //skip until we hit a transition
-               
-               //find out how many bits (n) we collected
-               //if lastval was 1, we have a 1->0 crossing
-               if (dest[idx-1]==1) {
-                       n = (n * fclow + rfLen/2) / rfLen;
-               } else {// 0->1 crossing 
-                       n = (n * fchigh + rfLen/2) / rfLen; 
+       if (clockFnd>0) {
+               clkCnt = clockFnd;
+               clkEnd = clockFnd+1;
+       }
+       else clkCnt=1;
+
+       //test each valid clock from smallest to greatest to see which lines up
+       for(; clkCnt < clkEnd; clkCnt++){
+               if (clk[clkCnt] <= 32){
+                       tol=1;
+               }else{
+                       tol=0;
                }
-               if (n == 0) n = 1;
+               //if no errors allowed - keep start within the first clock
+               if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt]<128) loopCnt=clk[clkCnt]*2;
+               bestErr[clkCnt]=1000;
+               //try lining up the peaks by moving starting point (try first few clocks)
+               for (ii=0; ii < loopCnt; ii++){
+                       if (dest[ii] < peak && dest[ii] > low) continue;
 
-               //add to our destination the bits we collected          
-               memset(dest+numBits, dest[idx-1]^invert , n);
-               numBits += n;
-               n=0;
-               lastval=dest[idx];
-       }//end for
-       // if valid extra bits at the end were all the same frequency - add them in
-       if (n > rfLen/fchigh) {
-               if (dest[idx-2]==1) {
-                       n = (n * fclow + rfLen/2) / rfLen;
-               } else {
-                       n = (n * fchigh + rfLen/2) / rfLen;
+                       errCnt=0;
+                       // now that we have the first one lined up test rest of wave array
+                       loopEnd = ((size-ii-tol) / clk[clkCnt]) - 1;
+                       for (i=0; i < loopEnd; ++i){
+                               arrLoc = ii + (i * clk[clkCnt]);
+                               if (dest[arrLoc] >= peak || dest[arrLoc] <= low){
+                               }else if (dest[arrLoc-tol] >= peak || dest[arrLoc-tol] <= low){
+                               }else if (dest[arrLoc+tol] >= peak || dest[arrLoc+tol] <= low){
+                               }else{  //error no peak detected
+                                       errCnt++;
+                               }
+                       }
+                       //if we found no errors then we can stop here and a low clock (common clocks)
+                       //  this is correct one - return this clock
+                       if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d",clk[clkCnt],errCnt,ii,i);
+                       if(errCnt==0 && clkCnt<7) { 
+                               if (!clockFnd) *clock = clk[clkCnt];
+                               return ii;
+                       }
+                       //if we found errors see if it is lowest so far and save it as best run
+                       if(errCnt<bestErr[clkCnt]){
+                               bestErr[clkCnt]=errCnt;
+                               bestStart[clkCnt]=ii;
+                       }
                }
-               memset(dest+numBits, dest[idx-1]^invert , n);
-               numBits += n;
        }
-       return numBits;
+       uint8_t iii;
+       uint8_t best=0;
+       for (iii=1; iii<clkEnd; ++iii){
+               if (bestErr[iii] < bestErr[best]){
+                       if (bestErr[iii] == 0) bestErr[iii]=1;
+                       // current best bit to error ratio     vs  new bit to error ratio
+                       if ( (size/clk[best])/bestErr[best] < (size/clk[iii])/bestErr[iii] ){
+                               best = iii;
+                       }
+               }
+               if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d",clk[iii],bestErr[iii],clk[best],bestStart[best]);
+       }
+       if (!clockFnd) *clock = clk[best];
+       return bestStart[best];
 }
 
-//by marshmellow  (from holiman's base)
-// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod)
-int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow)
-{
-       // FSK demodulator
-       size = fsk_wave_demod(dest, size, fchigh, fclow);
-       size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow);
-       return size;
-}
+int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low){
+       //find shortest transition from high to low
+       size_t i = 0;
+       size_t transition1 = 0;
+       int lowestTransition = 255;
+       bool lastWasHigh = false;
 
-// loop to get raw HID waveform then FSK demodulate the TAG ID from it
-int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo)
-{
-       if (justNoise(dest, *size)) return -1;
+       //find first valid beginning of a high or low wave
+       while ((dest[i] >= peak || dest[i] <= low) && (i < size))
+               ++i;
+       while ((dest[i] < peak && dest[i] > low) && (i < size))
+               ++i;
+       lastWasHigh = (dest[i] >= peak);
 
-       size_t numStart=0, size2=*size, startIdx=0; 
-       // FSK demodulator
-       *size = fskdemod(dest, size2,50,1,10,8); //fsk2a
-       if (*size < 96*2) return -2;
-       // 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
-       uint8_t preamble[] = {0,0,0,1,1,1,0,1};
-       // find bitstring in array  
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -3; //preamble not found
+       if (i==size) return 0;
+       transition1 = i;
 
-       numStart = startIdx + sizeof(preamble);
-       // final loop, go over previously decoded FSK data and manchester decode into usable tag ID
-       for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){
-               if (dest[idx] == dest[idx+1]){
-                       return -4; //not manchester data
-               }
-               *hi2 = (*hi2<<1)|(*hi>>31);
-               *hi = (*hi<<1)|(*lo>>31);
-               //Then, shift in a 0 or one into low
-               if (dest[idx] && !dest[idx+1])  // 1 0
-                       *lo=(*lo<<1)|1;
-               else // 0 1
-                       *lo=(*lo<<1)|0;
-       }
-       return (int)startIdx;
-}
-
-// loop to get raw paradox waveform then FSK demodulate the TAG ID from it
-int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo)
-{
-       if (justNoise(dest, *size)) return -1;
-       
-       size_t numStart=0, size2=*size, startIdx=0;
-       // FSK demodulator
-       *size = fskdemod(dest, size2,50,1,10,8); //fsk2a
-       if (*size < 96) return -2;
-
-       // 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
-       uint8_t preamble[] = {0,0,0,0,1,1,1,1};
-
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -3; //preamble not found
-
-       numStart = startIdx + sizeof(preamble);
-       // final loop, go over previously decoded FSK data and manchester decode into usable tag ID
-       for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){
-               if (dest[idx] == dest[idx+1]) 
-                       return -4; //not manchester data
-               *hi2 = (*hi2<<1)|(*hi>>31);
-               *hi = (*hi<<1)|(*lo>>31);
-               //Then, shift in a 0 or one into low
-               if (dest[idx] && !dest[idx+1])  // 1 0
-                       *lo=(*lo<<1)|1;
-               else // 0 1
-                       *lo=(*lo<<1)|0;
-       }
-       return (int)startIdx;
-}
-
-int IOdemodFSK(uint8_t *dest, size_t size)
-{
-       if (justNoise(dest, size)) return -1;
-       //make sure buffer has data
-       if (size < 66*64) return -2;
-       // FSK demodulator
-       size = fskdemod(dest, size, 64, 1, 10, 8);  // FSK2a RF/64 
-       if (size < 65) return -3;  //did we get a good demod?
-       //Index map
-       //0           10          20          30          40          50          60
-       //|           |           |           |           |           |           |
-       //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
-       //-----------------------------------------------------------------------------
-       //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
-       //
-       //XSF(version)facility:codeone+codetwo
-       //Handle the data
-       size_t startIdx = 0;
-       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,1};
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), &size, &startIdx);
-       if (errChk == 0) return -4; //preamble not found
-
-       if (!dest[startIdx+8] && dest[startIdx+17]==1 && dest[startIdx+26]==1 && dest[startIdx+35]==1 && dest[startIdx+44]==1 && dest[startIdx+53]==1){
-               //confirmed proper separator bits found
-               //return start position
-               return (int) startIdx;
+       for (;i < size; i++) {
+               if ((dest[i] >= peak && !lastWasHigh) || (dest[i] <= low && lastWasHigh)) {
+                       lastWasHigh = (dest[i] >= peak);
+                       if (i-transition1 < lowestTransition) lowestTransition = i-transition1;
+                       transition1 = i;
+               }
        }
-       return -5;
-} 
-
-// by marshmellow
-// find viking preamble 0xF200 in already demoded data
-int VikingDemod_AM(uint8_t *dest, size_t *size) {
-       //make sure buffer has data
-       if (*size < 64*2) return -2;
-
-       size_t startIdx = 0;
-       uint8_t preamble[] = {1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -4; //preamble not found
-       uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ bytebits_to_byte(dest+startIdx+8,8) ^ bytebits_to_byte(dest+startIdx+16,8)
-           ^ bytebits_to_byte(dest+startIdx+24,8) ^ bytebits_to_byte(dest+startIdx+32,8) ^ bytebits_to_byte(dest+startIdx+40,8) 
-           ^ bytebits_to_byte(dest+startIdx+48,8) ^ bytebits_to_byte(dest+startIdx+56,8);
-       if ( checkCalc != 0xA8 ) return -5;
-       if (*size != 64) return -6;
-       //return start position
-       return (int) startIdx;
-}
-
-// find presco preamble 0x10D in already demoded data
-int PrescoDemod(uint8_t *dest, size_t *size) {
-       //make sure buffer has data
-       if (*size < 64*2) return -2;
-
-       size_t startIdx = 0;
-       uint8_t preamble[] = {1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0};
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -4; //preamble not found
-       //return start position
-       return (int) startIdx;
-}
-
-// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
-// BitStream must contain previously askrawdemod and biphasedemoded data
-int FDXBdemodBI(uint8_t *dest, size_t *size)
-{
-       //make sure buffer has enough data
-       if (*size < 128) return -1;
-
-       size_t startIdx = 0;
-       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,1};
-
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -2; //preamble not found
-       return (int)startIdx;
-}
-
-// by marshmellow
-// FSK Demod then try to locate an AWID ID
-int AWIDdemodFSK(uint8_t *dest, size_t *size)
-{
-       //make sure buffer has enough data
-       if (*size < 96*50) return -1;
-
-       if (justNoise(dest, *size)) return -2;
-
-       // FSK demodulator
-       *size = fskdemod(dest, *size, 50, 1, 10, 8);  // fsk2a RF/50 
-       if (*size < 96) return -3;  //did we get a good demod?
-
-       uint8_t preamble[] = {0,0,0,0,0,0,0,1};
-       size_t startIdx = 0;
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -4; //preamble not found
-       if (*size != 96) return -5;
-       return (int)startIdx;
+       if (lowestTransition == 255) lowestTransition = 0;
+       if (g_debugMode==2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d",lowestTransition);
+       return lowestTransition;
 }
 
-// by marshmellow
-// FSK Demod then try to locate a Farpointe Data (pyramid) ID
-int PyramiddemodFSK(uint8_t *dest, size_t *size)
-{
-       //make sure buffer has data
-       if (*size < 128*50) return -5;
-
-       //test samples are not just noise
-       if (justNoise(dest, *size)) return -1;
-
-       // FSK demodulator
-       *size = fskdemod(dest, *size, 50, 1, 10, 8);  // fsk2a RF/50 
-       if (*size < 128) return -2;  //did we get a good demod?
-
-       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
-       size_t startIdx = 0;
-       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
-       if (errChk == 0) return -4; //preamble not found
-       if (*size != 128) return -3;
-       return (int)startIdx;
-}
+//by marshmellow
+//detect nrz clock by reading #peaks vs no peaks(or errors)
+int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx) {
+       size_t i=0;
+       uint8_t clk[]={8,16,32,40,50,64,100,128,255};
+       size_t loopCnt = 4096;  //don't need to loop through entire array...
+       if (size == 0) return 0;
+       if (size<loopCnt) loopCnt = size-20;
+       //if we already have a valid clock quit
+       for (; i < 8; ++i)
+               if (clk[i] == clock) return clock;
 
-// by marshmellow
-// to detect a wave that has heavily clipped (clean) samples
-uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low)
-{
-       bool allArePeaks = true;
-       uint16_t cntPeaks=0;
-       size_t loopEnd = 512+160;
-       if (loopEnd > size) loopEnd = size;
-       for (size_t i=160; i<loopEnd; i++){
-               if (dest[i]>low && dest[i]<high) 
-                       allArePeaks = false;
-               else
-                       cntPeaks++;
-       }
-       if (!allArePeaks){
-               if (cntPeaks > 300) return true;
-       }
-       return allArePeaks;
-}
-// by marshmellow
-// to help detect clocks on heavily clipped samples
-// based on count of low to low
-int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low, int *clock) {
-       uint8_t fndClk[] = {8,16,32,40,50,64,128};
-       size_t startwave;
-       size_t i = 100;
-       size_t minClk = 255;
-       int shortestWaveIdx = 0;
-               // get to first full low to prime loop and skip incomplete first pulse
-       while ((dest[i] < high) && (i < size))
-               ++i;
-       while ((dest[i] > low) && (i < size))
-               ++i;
+       //get high and low peak
+       int peak, low;
+       if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return 0;
 
-       // loop through all samples
-       while (i < size) {
-               // measure from low to low
-               while ((dest[i] > low) && (i < size))
-                       ++i;
-               startwave = i;
-               while ((dest[i] < high) && (i < size))
-                       ++i;
-               while ((dest[i] > low) && (i < size))
-                       ++i;
-               //get minimum measured distance
-               if (i-startwave < minClk && i < size) {
-                       minClk = i - startwave;
-                       shortestWaveIdx = startwave;
+       int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low);
+       size_t ii;
+       uint8_t clkCnt;
+       uint8_t tol = 0;
+       uint16_t smplCnt = 0;
+       int16_t peakcnt = 0;
+       int16_t peaksdet[] = {0,0,0,0,0,0,0,0};
+       uint16_t maxPeak = 255;
+       bool firstpeak = false;
+       //test for large clipped waves
+       for (i=0; i<loopCnt; i++){
+               if (dest[i] >= peak || dest[i] <= low){
+                       if (!firstpeak) continue;
+                       smplCnt++;
+               } else {
+                       firstpeak=true;
+                       if (smplCnt > 6 ){
+                               if (maxPeak > smplCnt){
+                                       maxPeak = smplCnt;
+                                       //prnt("maxPk: %d",maxPeak);
+                               }
+                               peakcnt++;
+                               //prnt("maxPk: %d, smplCnt: %d, peakcnt: %d",maxPeak,smplCnt,peakcnt);
+                               smplCnt=0;
+                       }
                }
        }
-       // set clock
-       if (g_debugMode==2) prnt("DEBUG ASK: detectstrongASKclk smallest wave: %d",minClk);
-       for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
-               if (minClk >= fndClk[clkCnt]-(fndClk[clkCnt]/8) && minClk <= fndClk[clkCnt]+1) {
-                       *clock = fndClk[clkCnt];
-                       return shortestWaveIdx;
+       bool errBitHigh = 0;
+       bool bitHigh = 0;
+       uint8_t ignoreCnt = 0;
+       uint8_t ignoreWindow = 4;
+       bool lastPeakHigh = 0;
+       int lastBit = 0; 
+       size_t bestStart[]={0,0,0,0,0,0,0,0,0};
+       peakcnt=0;
+       //test each valid clock from smallest to greatest to see which lines up
+       for(clkCnt=0; clkCnt < 8; ++clkCnt){
+               //ignore clocks smaller than smallest peak
+               if (clk[clkCnt] < maxPeak - (clk[clkCnt]/4)) continue;
+               //try lining up the peaks by moving starting point (try first 256)
+               for (ii=20; ii < loopCnt; ++ii){
+                       if ((dest[ii] >= peak) || (dest[ii] <= low)){
+                               peakcnt = 0;
+                               bitHigh = false;
+                               ignoreCnt = 0;
+                               lastBit = ii-clk[clkCnt]; 
+                               //loop through to see if this start location works
+                               for (i = ii; i < size-20; ++i) {
+                                       //if we are at a clock bit
+                                       if ((i >= lastBit + clk[clkCnt] - tol) && (i <= lastBit + clk[clkCnt] + tol)) {
+                                               //test high/low
+                                               if (dest[i] >= peak || dest[i] <= low) {
+                                                       //if same peak don't count it
+                                                       if ((dest[i] >= peak && !lastPeakHigh) || (dest[i] <= low && lastPeakHigh)) {
+                                                               peakcnt++;
+                                                       }
+                                                       lastPeakHigh = (dest[i] >= peak);
+                                                       bitHigh = true;
+                                                       errBitHigh = false;
+                                                       ignoreCnt = ignoreWindow;
+                                                       lastBit += clk[clkCnt];
+                                               } else if (i == lastBit + clk[clkCnt] + tol) {
+                                                       lastBit += clk[clkCnt];
+                                               }
+                                       //else if not a clock bit and no peaks
+                                       } else if (dest[i] < peak && dest[i] > low){
+                                               if (ignoreCnt==0){
+                                                       bitHigh=false;
+                                                       if (errBitHigh==true) peakcnt--;
+                                                       errBitHigh=false;
+                                               } else {
+                                                       ignoreCnt--;
+                                               }
+                                               // else if not a clock bit but we have a peak
+                                       } else if ((dest[i]>=peak || dest[i]<=low) && (!bitHigh)) {
+                                               //error bar found no clock...
+                                               errBitHigh=true;
+                                       }
+                               }
+                               if(peakcnt>peaksdet[clkCnt]) {
+                                       bestStart[clkCnt]=ii;
+                                       peaksdet[clkCnt]=peakcnt;
+                               }
+                       }
                }
        }
-       return 0;
-}
-
-// by marshmellow
-// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
-// maybe somehow adjust peak trimming value based on samples to fix?
-// return start index of best starting position for that clock and return clock (by reference)
-int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
-{
-       size_t i=1;
-       uint8_t clk[] = {255,8,16,32,40,50,64,100,128,255};
-       uint8_t clkEnd = 9;
-       uint8_t loopCnt = 255;  //don't need to loop through entire array...
-       if (size <= loopCnt+60) return -1; //not enough samples
-       size -= 60; //sometimes there is a strange end wave - filter out this....
-       //if we already have a valid clock
-       uint8_t clockFnd=0;
-       for (;i<clkEnd;++i)
-               if (clk[i] == *clock) clockFnd = i;
-               //clock found but continue to find best startpos
-
-       //get high and low peak
-       int peak, low;
-       if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1;
-       
-       //test for large clean peaks
-       if (!clockFnd){
-               if (DetectCleanAskWave(dest, size, peak, low)==1){
-                       int ans = DetectStrongAskClock(dest, size, peak, low, clock);
-                       if (g_debugMode==2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i",clock, ans);
-                       if (ans > 0) {
-                               return ans; //return shortest wave start position
+       int iii=7;
+       uint8_t best=0;
+       for (iii=7; iii > 0; iii--){
+               if ((peaksdet[iii] >= (peaksdet[best]-1)) && (peaksdet[iii] <= peaksdet[best]+1) && lowestTransition) {
+                       if (clk[iii] > (lowestTransition - (clk[iii]/8)) && clk[iii] < (lowestTransition + (clk[iii]/8))) {
+                               best = iii;
                        }
+               } else if (peaksdet[iii] > peaksdet[best]){
+                       best = iii;
                }
+               if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, maxPeak: %d, bestClk: %d, lowestTrs: %d",clk[iii],peaksdet[iii],maxPeak, clk[best], lowestTransition);
        }
-       uint8_t ii;
-       uint8_t clkCnt, tol = 0;
-       uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000};
-       uint8_t bestStart[]={0,0,0,0,0,0,0,0,0};
-       size_t errCnt = 0;
-       size_t arrLoc, loopEnd;
+       *clockStartIdx  = bestStart[best];
+       return clk[best];
+}
 
-       if (clockFnd>0) {
-               clkCnt = clockFnd;
-               clkEnd = clockFnd+1;
-       }
-       else clkCnt=1;
+//by marshmellow
+//countFC is to detect the field clock lengths.
+//counts and returns the 2 most common wave lengths
+//mainly used for FSK field clock detection
+uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj) {
+       uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+       uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+       uint8_t fcLensFnd = 0;
+       uint8_t lastFCcnt = 0;
+       uint8_t fcCounter = 0;
+       size_t i;
+       if (size < 180) return 0;
 
-       //test each valid clock from smallest to greatest to see which lines up
-       for(; clkCnt < clkEnd; clkCnt++){
-               if (clk[clkCnt] <= 32){
-                       tol=1;
-               }else{
-                       tol=0;
-               }
-               //if no errors allowed - keep start within the first clock
-               if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt]<128) loopCnt=clk[clkCnt]*2;
-               bestErr[clkCnt]=1000;
-               //try lining up the peaks by moving starting point (try first few clocks)
-               for (ii=0; ii < loopCnt; ii++){
-                       if (dest[ii] < peak && dest[ii] > low) continue;
+       // prime i to first up transition
+       for (i = 160; i < size-20; i++)
+               if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1])
+                       break;
 
-                       errCnt=0;
-                       // now that we have the first one lined up test rest of wave array
-                       loopEnd = ((size-ii-tol) / clk[clkCnt]) - 1;
-                       for (i=0; i < loopEnd; ++i){
-                               arrLoc = ii + (i * clk[clkCnt]);
-                               if (dest[arrLoc] >= peak || dest[arrLoc] <= low){
-                               }else if (dest[arrLoc-tol] >= peak || dest[arrLoc-tol] <= low){
-                               }else if (dest[arrLoc+tol] >= peak || dest[arrLoc+tol] <= low){
-                               }else{  //error no peak detected
-                                       errCnt++;
-                               }
+       for (; i < size-20; i++){
+               if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1]){
+                       // new up transition
+                       fcCounter++;
+                       if (fskAdj){
+                               //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8)
+                               if (lastFCcnt==5 && fcCounter==9) fcCounter--;
+                               //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5)
+                               if ((fcCounter==9) || fcCounter==4) fcCounter++;
+                       // save last field clock count  (fc/xx)
+                       lastFCcnt = fcCounter;
                        }
-                       //if we found no errors then we can stop here and a low clock (common clocks)
-                       //  this is correct one - return this clock
-                       if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d",clk[clkCnt],errCnt,ii,i);
-                       if(errCnt==0 && clkCnt<7) { 
-                               if (!clockFnd) *clock = clk[clkCnt];
-                               return ii;
+                       // find which fcLens to save it to:
+                       for (int ii=0; ii<15; ii++){
+                               if (fcLens[ii]==fcCounter){
+                                       fcCnts[ii]++;
+                                       fcCounter=0;
+                                       break;
+                               }
                        }
-                       //if we found errors see if it is lowest so far and save it as best run
-                       if(errCnt<bestErr[clkCnt]){
-                               bestErr[clkCnt]=errCnt;
-                               bestStart[clkCnt]=ii;
+                       if (fcCounter>0 && fcLensFnd<15){
+                               //add new fc length 
+                               fcCnts[fcLensFnd]++;
+                               fcLens[fcLensFnd++]=fcCounter;
                        }
+                       fcCounter=0;
+               } else {
+                       // count sample
+                       fcCounter++;
                }
        }
-       uint8_t iii;
-       uint8_t best=0;
-       for (iii=1; iii<clkEnd; ++iii){
-               if (bestErr[iii] < bestErr[best]){
-                       if (bestErr[iii] == 0) bestErr[iii]=1;
-                       // current best bit to error ratio     vs  new bit to error ratio
-                       if ( (size/clk[best])/bestErr[best] < (size/clk[iii])/bestErr[iii] ){
-                               best = iii;
-                       }
+       
+       uint8_t best1=14, best2=14, best3=14;
+       uint16_t maxCnt1=0;
+       // go through fclens and find which ones are bigest 2  
+       for (i=0; i<15; i++){
+               // get the 3 best FC values
+               if (fcCnts[i]>maxCnt1) {
+                       best3=best2;
+                       best2=best1;
+                       maxCnt1=fcCnts[i];
+                       best1=i;
+               } else if(fcCnts[i]>fcCnts[best2]){
+                       best3=best2;
+                       best2=i;
+               } else if(fcCnts[i]>fcCnts[best3]){
+                       best3=i;
                }
-               if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d",clk[iii],bestErr[iii],clk[best],bestStart[best]);
+               if (g_debugMode==2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]);
        }
-       if (!clockFnd) *clock = clk[best];
-       return bestStart[best];
-}
-
+       if (fcLens[best1]==0) return 0;
+       uint8_t fcH=0, fcL=0;
+       if (fcLens[best1]>fcLens[best2]){
+               fcH=fcLens[best1];
+               fcL=fcLens[best2];
+       } else{
+               fcH=fcLens[best2];
+               fcL=fcLens[best1];
+       }
+       if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) {
+               if (g_debugMode==2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]);
+               return 0; //lots of waves not psk or fsk
+       }
+       // TODO: take top 3 answers and compare to known Field clocks to get top 2
 
-int DetectPSKClock(uint8_t dest[], size_t size, int clock) {
-       int firstPhaseShift = 0;
-       return DetectPSKClock_ext(dest, size, clock, &firstPhaseShift);
+       uint16_t fcs = (((uint16_t)fcH)<<8) | fcL;
+       if (fskAdj) return fcs; 
+       return fcLens[best1];
 }
 
 //by marshmellow
@@ -1062,220 +813,529 @@ int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseSh
        return clk[best];
 }
 
-int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low){
-       //find shortest transition from high to low
+int DetectPSKClock(uint8_t dest[], size_t size, int clock) {
+       int firstPhaseShift = 0;
+       return DetectPSKClock_ext(dest, size, clock, &firstPhaseShift);
+}
+
+//by marshmellow
+//detects the bit clock for FSK given the high and low Field Clocks
+uint8_t detectFSKClk_ext(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge) {
+       uint8_t clk[] = {8,16,32,40,50,64,100,128,0};
+       uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+       uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+       uint8_t rfLensFnd = 0;
+       uint8_t lastFCcnt = 0;
+       uint16_t fcCounter = 0;
+       uint16_t rfCounter = 0;
+       uint8_t firstBitFnd = 0;
+       size_t i;
+       if (size == 0) return 0;
+
+       uint8_t fcTol = ((fcHigh*100 - fcLow*100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2);
+       rfLensFnd=0;
+       fcCounter=0;
+       rfCounter=0;
+       firstBitFnd=0;
+       //PrintAndLog("DEBUG: fcTol: %d",fcTol);
+       // prime i to first peak / up transition
+       for (i = 160; i < size-20; i++)
+               if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1])
+                       break;
+
+       for (; i < size-20; i++){
+               fcCounter++;
+               rfCounter++;
+
+               if (BitStream[i] <= BitStream[i-1] || BitStream[i] < BitStream[i+1]) 
+                       continue;               
+               // else new peak 
+               // if we got less than the small fc + tolerance then set it to the small fc
+               // if it is inbetween set it to the last counter
+               if (fcCounter < fcHigh && fcCounter > fcLow)
+                       fcCounter = lastFCcnt;
+               else if (fcCounter < fcLow+fcTol) 
+                       fcCounter = fcLow;
+               else //set it to the large fc
+                       fcCounter = fcHigh;
+
+               //look for bit clock  (rf/xx)
+               if ((fcCounter < lastFCcnt || fcCounter > lastFCcnt)){
+                       //not the same size as the last wave - start of new bit sequence
+                       if (firstBitFnd > 1){ //skip first wave change - probably not a complete bit
+                               for (int ii=0; ii<15; ii++){
+                                       if (rfLens[ii] >= (rfCounter-4) && rfLens[ii] <= (rfCounter+4)){
+                                               rfCnts[ii]++;
+                                               rfCounter = 0;
+                                               break;
+                                       }
+                               }
+                               if (rfCounter > 0 && rfLensFnd < 15){
+                                       //PrintAndLog("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter);
+                                       rfCnts[rfLensFnd]++;
+                                       rfLens[rfLensFnd++] = rfCounter;
+                               }
+                       } else {
+                               *firstClockEdge = i;
+                               firstBitFnd++;
+                       }
+                       rfCounter=0;
+                       lastFCcnt=fcCounter;
+               }
+               fcCounter=0;
+       }
+       uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15;
+
+       for (i=0; i<15; i++){
+               //get highest 2 RF values  (might need to get more values to compare or compare all?)
+               if (rfCnts[i]>rfCnts[rfHighest]){
+                       rfHighest3=rfHighest2;
+                       rfHighest2=rfHighest;
+                       rfHighest=i;
+               } else if(rfCnts[i]>rfCnts[rfHighest2]){
+                       rfHighest3=rfHighest2;
+                       rfHighest2=i;
+               } else if(rfCnts[i]>rfCnts[rfHighest3]){
+                       rfHighest3=i;
+               }
+               if (g_debugMode==2) prnt("DEBUG FSK: RF %d, cnts %d",rfLens[i], rfCnts[i]);
+       }  
+       // set allowed clock remainder tolerance to be 1 large field clock length+1 
+       //   we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off  
+       uint8_t tol1 = fcHigh+1; 
+       
+       if (g_debugMode==2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d",rfLens[rfHighest],rfLens[rfHighest2],rfLens[rfHighest3]);
+
+       // loop to find the highest clock that has a remainder less than the tolerance
+       //   compare samples counted divided by
+       // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less)
+       int ii=7;
+       for (; ii>=2; ii--){
+               if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){
+                       if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){
+                               if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){
+                                       if (g_debugMode==2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]);
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (ii<2) return 0; // oops we went too far
+
+       return clk[ii];
+}
+
+uint8_t        detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow) {
+       int firstClockEdge = 0;
+       return detectFSKClk_ext(BitStream, size, fcHigh, fcLow, &firstClockEdge);
+}
+
+//**********************************************************************************************
+//--------------------Modulation Demods &/or Decoding Section-----------------------------------
+//**********************************************************************************************
+
+// look for Sequence Terminator - should be pulses of clk*(1 or 2), clk*2, clk*(1.5 or 2), by idx we mean graph position index...
+bool findST(int *stStopLoc, int *stStartIdx, int lowToLowWaveLen[], int highToLowWaveLen[], int clk, int tol, int buffSize, size_t *i) {
+       for (; *i < buffSize - 4; *i+=1) {
+               *stStartIdx += lowToLowWaveLen[*i]; //caution part of this wave may be data and part may be ST....  to be accounted for in main function for now...
+               if (lowToLowWaveLen[*i] >= clk*1-tol && lowToLowWaveLen[*i] <= (clk*2)+tol && highToLowWaveLen[*i] < clk+tol) {           //1 to 2 clocks depending on 2 bits prior
+                       if (lowToLowWaveLen[*i+1] >= clk*2-tol && lowToLowWaveLen[*i+1] <= clk*2+tol && highToLowWaveLen[*i+1] > clk*3/2-tol) {       //2 clocks and wave size is 1 1/2
+                               if (lowToLowWaveLen[*i+2] >= (clk*3)/2-tol && lowToLowWaveLen[*i+2] <= clk*2+tol && highToLowWaveLen[*i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
+                                       if (lowToLowWaveLen[*i+3] >= clk*1-tol && lowToLowWaveLen[*i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
+                                               *stStopLoc = *i + 3;
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+       }
+       return false;
+}
+//by marshmellow
+//attempt to identify a Sequence Terminator in ASK modulated raw wave
+bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend) {
+       size_t bufsize = *size;
+       //need to loop through all samples and identify our clock, look for the ST pattern
+       int clk = 0; 
+       int tol = 0;
+       int j, high, low, skip, start, end, minClk=255;
        size_t i = 0;
-       size_t transition1 = 0;
-       int lowestTransition = 255;
-       bool lastWasHigh = false;
+       //probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow]
+       int tmpbuff[bufsize / LOWEST_DEFAULT_CLOCK]; // low to low wave count //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured
+       int waveLen[bufsize / LOWEST_DEFAULT_CLOCK]; // high to low wave count //if clock is larger then we waste memory in array size that is not needed...
+       //size_t testsize = (bufsize < 512) ? bufsize : 512;
+       int phaseoff = 0;
+       high = low = 128;
+       memset(tmpbuff, 0, sizeof(tmpbuff));
+       memset(waveLen, 0, sizeof(waveLen));
 
-       //find first valid beginning of a high or low wave
-       while ((dest[i] >= peak || dest[i] <= low) && (i < size))
-               ++i;
-       while ((dest[i] < peak && dest[i] > low) && (i < size))
-               ++i;
-       lastWasHigh = (dest[i] >= peak);
+       if (!loadWaveCounters(buffer, bufsize, tmpbuff, waveLen, &j, &skip, &minClk, &high, &low)) return false;
+       // set clock  - might be able to get this externally and remove this work...
+       clk = getClosestClock(minClk);
+       // clock not found - ERROR
+       if (clk == 0) {
+               if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting");
+               return false;
+       }
+       *foundclock = clk;
 
-       if (i==size) return 0;
-       transition1 = i;
+       tol = clk/8;
+       if (!findST(&start, &skip, tmpbuff, waveLen, clk, tol, j, &i)) {
+               // first ST not found - ERROR
+               if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting");
+               return false;
+       } else {
+               if (g_debugMode==2) prnt("DEBUG STT: first STT found at wave: %i, skip: %i, j=%i", start, skip, j);
+       }
+       if (waveLen[i+2] > clk*1+tol)
+               phaseoff = 0;
+       else
+               phaseoff = clk/2;
+       
+       // skip over the remainder of ST
+       skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point
 
-       for (;i < size; i++) {
-               if ((dest[i] >= peak && !lastWasHigh) || (dest[i] <= low && lastWasHigh)) {
-                       lastWasHigh = (dest[i] >= peak);
-                       if (i-transition1 < lowestTransition) lowestTransition = i-transition1;
-                       transition1 = i;
+       // now do it again to find the end
+       int dummy1 = 0;
+       end = skip;
+       i+=3;
+       if (!findST(&dummy1, &end, tmpbuff, waveLen, clk, tol, j, &i)) {
+               //didn't find second ST - ERROR
+               if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting");
+               return false;
+       }
+       end -= phaseoff;
+       if (g_debugMode==2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff);
+       //now begin to trim out ST so we can use normal demod cmds
+       start = skip;
+       size_t datalen = end - start;
+       // check validity of datalen (should be even clock increments)  - use a tolerance of up to 1/8th a clock
+       if ( clk - (datalen % clk) <= clk/8) {
+               // padd the amount off - could be problematic...  but shouldn't happen often
+               datalen += clk - (datalen % clk);
+       } else if ( (datalen % clk) <= clk/8 ) {
+               // padd the amount off - could be problematic...  but shouldn't happen often
+               datalen -= datalen % clk;
+       } else {
+               if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk);
+               return false;
+       }
+       // if datalen is less than one t55xx block - ERROR
+       if (datalen/clk < 8*4) {
+               if (g_debugMode==2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting");              
+               return false;
+       }
+       size_t dataloc = start;
+       if (buffer[dataloc-(clk*4)-(clk/8)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) {
+               //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start 
+               for ( i=0; i <= (clk/8); ++i ) {
+                       if ( buffer[dataloc - (clk*4) - i] <= low ) {
+                               dataloc -= i;
+                               break;
+                       }
+               }
+       }
+       
+       size_t newloc = 0;
+       i=0;
+       if (g_debugMode==2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen);            
+       bool firstrun = true;
+       // warning - overwriting buffer given with raw wave data with ST removed...
+       while ( dataloc < bufsize-(clk/2) ) {
+               //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part)
+               if (buffer[dataloc]<high && buffer[dataloc]>low && buffer[dataloc+3]<high && buffer[dataloc+3]>low) {
+                       for(i=0; i < clk/2-tol; ++i) {
+                               buffer[dataloc+i] = high+5;
+                       }
+               } //test for single sample outlier (high between two lows) in the case of very strong waves
+               if (buffer[dataloc] >= high && buffer[dataloc+2] <= low) {
+                       buffer[dataloc] = buffer[dataloc+2];
+                       buffer[dataloc+1] = buffer[dataloc+2];
+               }
+               if (firstrun) {
+                       *stend = dataloc;
+                       *ststart = dataloc-(clk*4);
+                       firstrun=false;
+               }
+               for (i=0; i<datalen; ++i) {
+                       if (i+newloc < bufsize) {
+                               if (i+newloc < dataloc)
+                                       buffer[i+newloc] = buffer[dataloc];
+
+                               dataloc++;
+                       }
                }
+               newloc += i;
+               //skip next ST  -  we just assume it will be there from now on...
+               if (g_debugMode==2) prnt("DEBUG STT: skipping STT at %d to %d", dataloc, dataloc+(clk*4));
+               dataloc += clk*4;
        }
-       if (lowestTransition == 255) lowestTransition = 0;
-       if (g_debugMode==2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d",lowestTransition);
-       return lowestTransition;
+       *size = newloc;
+       return true;
 }
-
-int DetectNRZClock(uint8_t dest[], size_t size, int clock) {
-       size_t bestStart=0;
-       return DetectNRZClock_ext(dest, size, clock, &bestStart);
+bool DetectST(uint8_t  buffer[], size_t *size, int *foundclock) {
+       size_t ststart = 0, stend = 0;
+       return DetectST_ext(buffer, size, foundclock, &ststart, &stend);
 }
 
+//by marshmellow
+//take 11 10 01 11 00 and make 01100 ... miller decoding 
+//check for phase errors - should never have half a 1 or 0 by itself and should never exceed 1111 or 0000 in a row
+//decodes miller encoded binary
+//NOTE  askrawdemod will NOT demod miller encoded ask unless the clock is manually set to 1/2 what it is detected as!
+int millerRawDecode(uint8_t *BitStream, size_t *size, int invert) {
+       if (*size < 16) return -1;
+       uint16_t MaxBits = 512, errCnt = 0;
+       size_t i, bitCnt=0;
+       uint8_t alignCnt = 0, curBit = BitStream[0], alignedIdx = 0;
+       uint8_t halfClkErr = 0;
+       //find alignment, needs 4 1s or 0s to properly align
+       for (i=1; i < *size-1; i++) {
+               alignCnt = (BitStream[i] == curBit) ? alignCnt+1 : 0;
+               curBit = BitStream[i];
+               if (alignCnt == 4) break;
+       }
+       // for now error if alignment not found.  later add option to run it with multiple offsets...
+       if (alignCnt != 4) {
+               if (g_debugMode) prnt("ERROR MillerDecode: alignment not found so either your bitstream is not miller or your data does not have a 101 in it");
+               return -1;
+       }
+       alignedIdx = (i-1) % 2;
+       for (i=alignedIdx; i < *size-3; i+=2) {
+               halfClkErr = (uint8_t)((halfClkErr << 1 | BitStream[i]) & 0xFF);
+               if ( (halfClkErr & 0x7) == 5 || (halfClkErr & 0x7) == 2 || (i > 2 && (halfClkErr & 0x7) == 0) || (halfClkErr & 0x1F) == 0x1F) {
+                       errCnt++;
+                       BitStream[bitCnt++] = 7;
+                       continue;
+               }
+               BitStream[bitCnt++] = BitStream[i] ^ BitStream[i+1] ^ invert;
+
+               if (bitCnt > MaxBits) break;
+       }
+       *size = bitCnt;
+       return errCnt;
+}
 
 //by marshmellow
-//detect nrz clock by reading #peaks vs no peaks(or errors)
-int DetectNRZClock_ext(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx) {
-       size_t i=0;
-       uint8_t clk[]={8,16,32,40,50,64,100,128,255};
-       size_t loopCnt = 4096;  //don't need to loop through entire array...
-       if (size == 0) return 0;
-       if (size<loopCnt) loopCnt = size-20;
-       //if we already have a valid clock quit
-       for (; i < 8; ++i)
-               if (clk[i] == clock) return clock;
+//take 01 or 10 = 1 and 11 or 00 = 0
+//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
+//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
+int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert) {
+       uint16_t bitnum = 0;
+       uint16_t errCnt = 0;
+       size_t i = offset;
+       uint16_t MaxBits=512;
+       //if not enough samples - error
+       if (*size < 51) return -1;
+       //check for phase change faults - skip one sample if faulty
+       uint8_t offsetA = 1, offsetB = 1;
+       for (; i<48; i+=2){
+               if (BitStream[i+1]==BitStream[i+2]) offsetA=0; 
+               if (BitStream[i+2]==BitStream[i+3]) offsetB=0;                                  
+       }
+       if (!offsetA && offsetB) offset++;
+       for (i=offset; i<*size-3; i+=2){
+               //check for phase error
+               if (BitStream[i+1]==BitStream[i+2]) {
+                       BitStream[bitnum++]=7;
+                       errCnt++;
+               }
+               if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){
+                       BitStream[bitnum++]=1^invert;
+               } else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){
+                       BitStream[bitnum++]=invert;
+               } else {
+                       BitStream[bitnum++]=7;
+                       errCnt++;
+               }
+               if(bitnum>MaxBits) break;
+       }
+       *size=bitnum;
+       return errCnt;
+}
 
-       //get high and low peak
-       int peak, low;
-       if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return 0;
+//by marshmellow
+//take 10 and 01 and manchester decode
+//run through 2 times and take least errCnt
+int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert, uint8_t *alignPos) {
+       uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
+       size_t i, ii;
+       uint16_t bestErr = 1000, bestRun = 0;
+       if (*size < 16) return -1;
+       //find correct start position [alignment]
+       for (ii=0;ii<2;++ii){
+               for (i=ii; i<*size-3; i+=2)
+                       if (BitStream[i]==BitStream[i+1])
+                               errCnt++;
 
-       int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low);
-       size_t ii;
-       uint8_t clkCnt;
-       uint8_t tol = 0;
-       uint16_t smplCnt = 0;
-       int16_t peakcnt = 0;
-       int16_t peaksdet[] = {0,0,0,0,0,0,0,0};
-       uint16_t maxPeak = 255;
-       bool firstpeak = false;
-       //test for large clipped waves
-       for (i=0; i<loopCnt; i++){
-               if (dest[i] >= peak || dest[i] <= low){
-                       if (!firstpeak) continue;
-                       smplCnt++;
+               if (bestErr>errCnt){
+                       bestErr=errCnt;
+                       bestRun=ii;
+               }
+               errCnt=0;
+       }
+       *alignPos=bestRun;
+       //decode
+       for (i=bestRun; i < *size-3; i+=2){
+               if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
+                       BitStream[bitnum++]=invert;
+               } else if((BitStream[i] == 0) && BitStream[i+1] == 1){
+                       BitStream[bitnum++]=invert^1;
                } else {
-                       firstpeak=true;
-                       if (smplCnt > 6 ){
-                               if (maxPeak > smplCnt){
-                                       maxPeak = smplCnt;
-                                       //prnt("maxPk: %d",maxPeak);
-                               }
-                               peakcnt++;
-                               //prnt("maxPk: %d, smplCnt: %d, peakcnt: %d",maxPeak,smplCnt,peakcnt);
-                               smplCnt=0;
-                       }
+                       BitStream[bitnum++]=7;
                }
+               if(bitnum>MaxBits) break;
        }
-       bool errBitHigh = 0;
-       bool bitHigh = 0;
-       uint8_t ignoreCnt = 0;
-       uint8_t ignoreWindow = 4;
-       bool lastPeakHigh = 0;
-       int lastBit = 0; 
-       size_t bestStart[]={0,0,0,0,0,0,0,0,0};
-       peakcnt=0;
-       //test each valid clock from smallest to greatest to see which lines up
-       for(clkCnt=0; clkCnt < 8; ++clkCnt){
-               //ignore clocks smaller than smallest peak
-               if (clk[clkCnt] < maxPeak - (clk[clkCnt]/4)) continue;
-               //try lining up the peaks by moving starting point (try first 256)
-               for (ii=20; ii < loopCnt; ++ii){
-                       if ((dest[ii] >= peak) || (dest[ii] <= low)){
-                               peakcnt = 0;
-                               bitHigh = false;
-                               ignoreCnt = 0;
-                               lastBit = ii-clk[clkCnt]; 
-                               //loop through to see if this start location works
-                               for (i = ii; i < size-20; ++i) {
-                                       //if we are at a clock bit
-                                       if ((i >= lastBit + clk[clkCnt] - tol) && (i <= lastBit + clk[clkCnt] + tol)) {
-                                               //test high/low
-                                               if (dest[i] >= peak || dest[i] <= low) {
-                                                       //if same peak don't count it
-                                                       if ((dest[i] >= peak && !lastPeakHigh) || (dest[i] <= low && lastPeakHigh)) {
-                                                               peakcnt++;
-                                                       }
-                                                       lastPeakHigh = (dest[i] >= peak);
-                                                       bitHigh = true;
-                                                       errBitHigh = false;
-                                                       ignoreCnt = ignoreWindow;
-                                                       lastBit += clk[clkCnt];
-                                               } else if (i == lastBit + clk[clkCnt] + tol) {
-                                                       lastBit += clk[clkCnt];
-                                               }
-                                       //else if not a clock bit and no peaks
-                                       } else if (dest[i] < peak && dest[i] > low){
-                                               if (ignoreCnt==0){
-                                                       bitHigh=false;
-                                                       if (errBitHigh==true) peakcnt--;
-                                                       errBitHigh=false;
-                                               } else {
-                                                       ignoreCnt--;
-                                               }
-                                               // else if not a clock bit but we have a peak
-                                       } else if ((dest[i]>=peak || dest[i]<=low) && (!bitHigh)) {
-                                               //error bar found no clock...
-                                               errBitHigh=true;
+       *size=bitnum;
+       return bestErr;
+}
+
+//by marshmellow
+//demodulates strong heavily clipped samples
+int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low, int *startIdx)
+{
+       *startIdx=0;
+       size_t bitCnt=0, smplCnt=1, errCnt=0;
+       bool waveHigh = (BinStream[0] >= high);
+       for (size_t i=1; i < *size; i++){
+               if (BinStream[i] >= high && waveHigh){
+                       smplCnt++;
+               } else if (BinStream[i] <= low && !waveHigh){
+                       smplCnt++;
+               } else { //transition
+                       if ((BinStream[i] >= high && !waveHigh) || (BinStream[i] <= low && waveHigh)){
+                               if (smplCnt > clk-(clk/4)-1) { //full clock
+                                       if (smplCnt > clk + (clk/4)+1) { //too many samples
+                                               errCnt++;
+                                               if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
+                                               BinStream[bitCnt++] = 7;
+                                       } else if (waveHigh) {
+                                               BinStream[bitCnt++] = invert;
+                                               BinStream[bitCnt++] = invert;
+                                       } else if (!waveHigh) {
+                                               BinStream[bitCnt++] = invert ^ 1;
+                                               BinStream[bitCnt++] = invert ^ 1;
                                        }
+                                       if (*startIdx==0) *startIdx = i-clk;
+                                       waveHigh = !waveHigh;  
+                                       smplCnt = 0;
+                               } else if (smplCnt > (clk/2) - (clk/4)-1) { //half clock
+                                       if (waveHigh) {
+                                               BinStream[bitCnt++] = invert;
+                                       } else if (!waveHigh) {
+                                               BinStream[bitCnt++] = invert ^ 1;
+                                       }
+                                       if (*startIdx==0) *startIdx = i-(clk/2);
+                                       waveHigh = !waveHigh;  
+                                       smplCnt = 0;
+                               } else {
+                                       smplCnt++;
+                                       //transition bit oops
                                }
-                               if(peakcnt>peaksdet[clkCnt]) {
-                                       bestStart[clkCnt]=ii;
-                                       peaksdet[clkCnt]=peakcnt;
-                               }
-                       }
-               }
-       }
-       int iii=7;
-       uint8_t best=0;
-       for (iii=7; iii > 0; iii--){
-               if ((peaksdet[iii] >= (peaksdet[best]-1)) && (peaksdet[iii] <= peaksdet[best]+1) && lowestTransition) {
-                       if (clk[iii] > (lowestTransition - (clk[iii]/8)) && clk[iii] < (lowestTransition + (clk[iii]/8))) {
-                               best = iii;
+                       } else { //haven't hit new high or new low yet
+                               smplCnt++;
                        }
-               } else if (peaksdet[iii] > peaksdet[best]){
-                       best = iii;
                }
-               if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, maxPeak: %d, bestClk: %d, lowestTrs: %d",clk[iii],peaksdet[iii],maxPeak, clk[best], lowestTransition);
        }
-       *clockStartIdx  = bestStart[best];
-       return clk[best];
+       *size = bitCnt;
+       return errCnt;
 }
 
-// by marshmellow
-// convert psk1 demod to psk2 demod
-// only transition waves are 1s
-void psk1TOpsk2(uint8_t *BitStream, size_t size)
-{
-       size_t i=1;
-       uint8_t lastBit=BitStream[0];
-       for (; i<size; i++){
-               if (BitStream[i]==7){
-                       //ignore errors
-               } else if (lastBit!=BitStream[i]){
-                       lastBit=BitStream[i];
-                       BitStream[i]=1;
-               } else {
-                       BitStream[i]=0;
+//by marshmellow
+//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester
+int askdemod_ext(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx) {
+       if (*size==0) return -1;
+       int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default
+       if (*clk==0 || start < 0) return -3;
+       if (*invert != 1) *invert = 0;
+       if (amp==1) askAmp(BinStream, *size);
+       if (g_debugMode==2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp);
+
+       //start pos from detect ask clock is 1/2 clock offset
+       // NOTE: can be negative (demod assumes rest of wave was there)
+       *startIdx = start - (*clk/2); 
+       uint8_t initLoopMax = 255;
+       if (initLoopMax > *size) initLoopMax = *size;
+       // Detect high and lows
+       //25% clip in case highs and lows aren't clipped [marshmellow]
+       int high, low;
+       if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) 
+               return -2; //just noise
+
+       size_t errCnt = 0;
+       // if clean clipped waves detected run alternate demod
+       if (DetectCleanAskWave(BinStream, *size, high, low)) {
+               if (g_debugMode==2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod");
+               errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low, startIdx);
+               if (askType) { //askman
+                       uint8_t alignPos = 0;
+                       errCnt = manrawdecode(BinStream, size, 0, &alignPos);
+                       *startIdx += *clk/2 * alignPos;
+                       if (g_debugMode) prnt("DEBUG ASK CLEAN: startIdx %i, alignPos %u", *startIdx, alignPos);
+                       return errCnt;
+               } else { //askraw
+                       return errCnt;
                }
        }
-       return;
-}
+       if (g_debugMode) prnt("DEBUG ASK WEAK: startIdx %i", *startIdx);
+       if (g_debugMode==2) prnt("DEBUG ASK: Weak Wave Detected - using weak wave demod");
 
-// by marshmellow
-// convert psk2 demod to psk1 demod
-// from only transition waves are 1s to phase shifts change bit
-void psk2TOpsk1(uint8_t *BitStream, size_t size)
-{
-       uint8_t phase=0;
-       for (size_t i=0; i<size; i++){
-               if (BitStream[i]==1){
-                       phase ^=1;
+       int lastBit;              //set first clock check - can go negative
+       size_t i, bitnum = 0;     //output counter
+       uint8_t midBit = 0;
+       uint8_t tol = 0;          //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
+       if (*clk <= 32) tol = 1;  //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
+       size_t MaxBits = 3072;    //max bits to collect
+       lastBit = start - *clk;
+
+       for (i = start; i < *size; ++i) {
+               if (i-lastBit >= *clk-tol){
+                       if (BinStream[i] >= high) {
+                               BinStream[bitnum++] = *invert;
+                       } else if (BinStream[i] <= low) {
+                               BinStream[bitnum++] = *invert ^ 1;
+                       } else if (i-lastBit >= *clk+tol) {
+                               if (bitnum > 0) {
+                                       if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
+                                       BinStream[bitnum++]=7;
+                                       errCnt++;                                               
+                               } 
+                       } else { //in tolerance - looking for peak
+                               continue;
+                       }
+                       midBit = 0;
+                       lastBit += *clk;
+               } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){
+                       if (BinStream[i] >= high) {
+                               BinStream[bitnum++] = *invert;
+                       } else if (BinStream[i] <= low) {
+                               BinStream[bitnum++] = *invert ^ 1;
+                       } else if (i-lastBit >= *clk/2+tol) {
+                               BinStream[bitnum] = BinStream[bitnum-1];
+                               bitnum++;
+                       } else { //in tolerance - looking for peak
+                               continue;
+                       }
+                       midBit = 1;
                }
-               BitStream[i]=phase;
+               if (bitnum >= MaxBits) break;
        }
-       return;
+       *size = bitnum;
+       return errCnt;
 }
 
-// redesigned by marshmellow adjusted from existing decode functions
-// indala id decoding - only tested on 26 bit tags, but attempted to make it work for more
-int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert)
-{
-       //26 bit 40134 format  (don't know other formats)
-       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
-       uint8_t preamble_i[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0};
-       size_t startidx = 0; 
-       if (!preambleSearch(bitStream, preamble, sizeof(preamble), size, &startidx)){
-               // if didn't find preamble try again inverting
-               if (!preambleSearch(bitStream, preamble_i, sizeof(preamble_i), size, &startidx)) return -1;
-               *invert ^= 1;
-       } 
-       if (*size != 64 && *size != 224) return -2;
-       if (*invert==1)
-               for (size_t i = startidx; i < *size; i++)
-                       bitStream[i] ^= 1;
-
-       return (int) startidx;
+int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType) {
+       int start = 0;
+       return askdemod_ext(BinStream, size, clk, invert, maxErr, amp, askType, &start);
 }
 
 // by marshmellow - demodulate NRZ wave - requires a read with strong signal
 // peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak
-int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert){
+int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx) {
        if (justNoise(dest, *size)) return -1;
-       *clk = DetectNRZClock(dest, *size, *clk);
+       size_t clkStartIdx = 0;
+       *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx);
        if (*clk==0) return -2;
        size_t i, gLen = 4096;
        if (gLen>*size) gLen = *size-20;
@@ -1297,6 +1357,10 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert){
                if (dest[i] != dest[i-1] || (i-lastBit) == (10 * *clk)) {
                        memset(dest+numBits, dest[i-1] ^ *invert, (i - lastBit + (*clk/4)) / *clk);
                        numBits += (i - lastBit + (*clk/4)) / *clk;
+                       if (lastBit == 0) {
+                               *startIdx = i - (numBits * *clk);
+                               if (g_debugMode==2) prnt("DEBUG NRZ: startIdx %i", *startIdx);
+                       }
                        lastBit = i-1;
                }
        }
@@ -1304,256 +1368,212 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert){
        return 0;
 }
 
-uint8_t        detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow) {
-       int firstClockEdge = 0;
-       return detectFSKClk_ext(BitStream, size, fcHigh, fcLow, &firstClockEdge);
-}
-
-//by marshmellow
-//detects the bit clock for FSK given the high and low Field Clocks
-uint8_t detectFSKClk_ext(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge) {
-       uint8_t clk[] = {8,16,32,40,50,64,100,128,0};
-       uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-       uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-       uint8_t rfLensFnd = 0;
-       uint8_t lastFCcnt = 0;
-       uint16_t fcCounter = 0;
-       uint16_t rfCounter = 0;
-       uint8_t firstBitFnd = 0;
-       size_t i;
-       if (size == 0) return 0;
-
-       uint8_t fcTol = ((fcHigh*100 - fcLow*100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2);
-       rfLensFnd=0;
-       fcCounter=0;
-       rfCounter=0;
-       firstBitFnd=0;
-       //PrintAndLog("DEBUG: fcTol: %d",fcTol);
-       // prime i to first peak / up transition
-       for (i = 160; i < size-20; i++)
-               if (BitStream[i] > BitStream[i-1] && BitStream[i]>=BitStream[i+1])
-                       break;
-
-       for (; i < size-20; i++){
-               fcCounter++;
-               rfCounter++;
+//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
+size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow, int *startIdx) {
+       size_t last_transition = 0;
+       size_t idx = 1;
+       if (fchigh==0) fchigh=10;
+       if (fclow==0) fclow=8;
+       //set the threshold close to 0 (graph) or 128 std to avoid static
+       size_t preLastSample = 0;
+       size_t LastSample = 0;
+       size_t currSample = 0;
+       if ( size < 1024 ) return 0; // not enough samples
 
-               if (BitStream[i] <= BitStream[i-1] || BitStream[i] < BitStream[i+1]) 
-                       continue;               
-               // else new peak 
-               // if we got less than the small fc + tolerance then set it to the small fc
-               // if it is inbetween set it to the last counter
-               if (fcCounter < fcHigh && fcCounter > fcLow)
-                       fcCounter = lastFCcnt;
-               else if (fcCounter < fcLow+fcTol) 
-                       fcCounter = fcLow;
-               else //set it to the large fc
-                       fcCounter = fcHigh;
+       //find start of modulating data in trace 
+       idx = findModStart(dest, size, fchigh);
+       // Need to threshold first sample
+       if(dest[idx] < FSK_PSK_THRESHOLD) dest[0] = 0;
+       else dest[0] = 1;
+       
+       last_transition = idx;
+       idx++;
+       size_t numBits = 0;
+       // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
+       // or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
+       // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
+       //  (could also be fc/5 && fc/7 for fsk1 = 4-9)
+       for(; idx < size; idx++) {
+               // threshold current value
+               if (dest[idx] < FSK_PSK_THRESHOLD) dest[idx] = 0;
+               else dest[idx] = 1;
 
-               //look for bit clock  (rf/xx)
-               if ((fcCounter < lastFCcnt || fcCounter > lastFCcnt)){
-                       //not the same size as the last wave - start of new bit sequence
-                       if (firstBitFnd > 1){ //skip first wave change - probably not a complete bit
-                               for (int ii=0; ii<15; ii++){
-                                       if (rfLens[ii] >= (rfCounter-4) && rfLens[ii] <= (rfCounter+4)){
-                                               rfCnts[ii]++;
-                                               rfCounter = 0;
-                                               break;
-                                       }
-                               }
-                               if (rfCounter > 0 && rfLensFnd < 15){
-                                       //PrintAndLog("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter);
-                                       rfCnts[rfLensFnd]++;
-                                       rfLens[rfLensFnd++] = rfCounter;
+               // Check for 0->1 transition
+               if (dest[idx-1] < dest[idx]) {
+                       preLastSample = LastSample;
+                       LastSample = currSample;
+                       currSample = idx-last_transition;
+                       if (currSample < (fclow-2)) {                   //0-5 = garbage noise (or 0-3)
+                               //do nothing with extra garbage
+                       } else if (currSample < (fchigh-1)) {           //6-8 = 8 sample waves  (or 3-6 = 5)
+                               //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
+                               if (numBits > 1 && LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){
+                                       dest[numBits-1]=1;
                                }
-                       } else {
-                               *firstClockEdge = i;
-                               firstBitFnd++;
+                               dest[numBits++]=1;
+                       if (numBits > 0 && *startIdx==0) *startIdx = idx - fclow;
+                       } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage
+                               //do nothing with beginning garbage and reset..  should be rare..
+                               numBits = 0; 
+                       } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
+                               dest[numBits++]=1;
+                       if (numBits > 0 && *startIdx==0) *startIdx = idx - fclow;
+                       } else {                                        //9+ = 10 sample waves (or 6+ = 7)
+                               dest[numBits++]=0;
+                       if (numBits > 0 && *startIdx==0) *startIdx = idx - fchigh;
                        }
-                       rfCounter=0;
-                       lastFCcnt=fcCounter;
+                       last_transition = idx;
                }
-               fcCounter=0;
        }
-       uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15;
+       return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
+}
 
-       for (i=0; i<15; i++){
-               //get highest 2 RF values  (might need to get more values to compare or compare all?)
-               if (rfCnts[i]>rfCnts[rfHighest]){
-                       rfHighest3=rfHighest2;
-                       rfHighest2=rfHighest;
-                       rfHighest=i;
-               } else if(rfCnts[i]>rfCnts[rfHighest2]){
-                       rfHighest3=rfHighest2;
-                       rfHighest2=i;
-               } else if(rfCnts[i]>rfCnts[rfHighest3]){
-                       rfHighest3=i;
+//translate 11111100000 to 10
+//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
+size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx) {
+       uint8_t lastval=dest[0];
+       size_t idx=0;
+       size_t numBits=0;
+       uint32_t n=1;
+       for( idx=1; idx < size; idx++) {
+               n++;
+               if (dest[idx]==lastval) continue; //skip until we hit a transition
+               
+               //find out how many bits (n) we collected (use 1/2 clk tolerance)
+               //if lastval was 1, we have a 1->0 crossing
+               if (dest[idx-1]==1) {
+                       n = (n * fclow + rfLen/2) / rfLen;
+               } else {// 0->1 crossing 
+                       n = (n * fchigh + rfLen/2) / rfLen; 
                }
-               if (g_debugMode==2) prnt("DEBUG FSK: RF %d, cnts %d",rfLens[i], rfCnts[i]);
-       }  
-       // set allowed clock remainder tolerance to be 1 large field clock length+1 
-       //   we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off  
-       uint8_t tol1 = fcHigh+1; 
-       
-       if (g_debugMode==2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d",rfLens[rfHighest],rfLens[rfHighest2],rfLens[rfHighest3]);
-
-       // loop to find the highest clock that has a remainder less than the tolerance
-       //   compare samples counted divided by
-       // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less)
-       int ii=7;
-       for (; ii>=2; ii--){
-               if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){
-                       if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){
-                               if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){
-                                       if (g_debugMode==2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]);
-                                       break;
-                               }
+               if (n == 0) n = 1;
+               
+               //first transition - save startidx
+               if (numBits == 0) {
+                       if (lastval == 1) {  //high to low
+                               *startIdx += (fclow * idx) - (n*rfLen);
+                               if (g_debugMode==2) prnt("DEBUG FSK: startIdx %i, fclow*idx %i, n*rflen %u", *startIdx, fclow*(idx), n*rfLen);
+                       } else {
+                               *startIdx += (fchigh * idx) - (n*rfLen);
+                               if (g_debugMode==2) prnt("DEBUG FSK: startIdx %i, fchigh*idx %i, n*rflen %u", *startIdx, fchigh*(idx), n*rfLen);
                        }
                }
-       }
 
-       if (ii<2) return 0; // oops we went too far
-
-       return clk[ii];
+               //add to our destination the bits we collected          
+               memset(dest+numBits, dest[idx-1]^invert , n);
+               numBits += n;
+               n=0;
+               lastval=dest[idx];
+       }//end for
+       // if valid extra bits at the end were all the same frequency - add them in
+       if (n > rfLen/fchigh) {
+               if (dest[idx-2]==1) {
+                       n = (n * fclow + rfLen/2) / rfLen;
+               } else {
+                       n = (n * fchigh + rfLen/2) / rfLen;
+               }
+               memset(dest+numBits, dest[idx-1]^invert , n);
+               numBits += n;
+       }
+       return numBits;
 }
 
-//by marshmellow
-//countFC is to detect the field clock lengths.
-//counts and returns the 2 most common wave lengths
-//mainly used for FSK field clock detection
-uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj)
-{
-       uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-       uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-       uint8_t fcLensFnd = 0;
-       uint8_t lastFCcnt = 0;
-       uint8_t fcCounter = 0;
-       size_t i;
-       if (size < 180) return 0;
+//by marshmellow  (from holiman's base)
+// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod)
+int fskdemod_ext(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx) {
+       // FSK demodulator
+       size = fsk_wave_demod(dest, size, fchigh, fclow, startIdx);
+       size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow, startIdx);
+       return size;
+}
 
-       // prime i to first up transition
-       for (i = 160; i < size-20; i++)
-               if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1])
-                       break;
+int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow) {
+       int startIdx=0;
+       return fskdemod_ext(dest, size, rfLen, invert, fchigh, fclow, &startIdx);
+}
 
-       for (; i < size-20; i++){
-               if (BitStream[i] > BitStream[i-1] && BitStream[i] >= BitStream[i+1]){
-                       // new up transition
-                       fcCounter++;
-                       if (fskAdj){
-                               //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8)
-                               if (lastFCcnt==5 && fcCounter==9) fcCounter--;
-                               //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5)
-                               if ((fcCounter==9) || fcCounter==4) fcCounter++;
-                       // save last field clock count  (fc/xx)
-                       lastFCcnt = fcCounter;
-                       }
-                       // find which fcLens to save it to:
-                       for (int ii=0; ii<15; ii++){
-                               if (fcLens[ii]==fcCounter){
-                                       fcCnts[ii]++;
-                                       fcCounter=0;
-                                       break;
-                               }
-                       }
-                       if (fcCounter>0 && fcLensFnd<15){
-                               //add new fc length 
-                               fcCnts[fcLensFnd]++;
-                               fcLens[fcLensFnd++]=fcCounter;
-                       }
-                       fcCounter=0;
+// by marshmellow
+// convert psk1 demod to psk2 demod
+// only transition waves are 1s
+void psk1TOpsk2(uint8_t *BitStream, size_t size) {
+       size_t i=1;
+       uint8_t lastBit=BitStream[0];
+       for (; i<size; i++){
+               if (BitStream[i]==7){
+                       //ignore errors
+               } else if (lastBit!=BitStream[i]){
+                       lastBit=BitStream[i];
+                       BitStream[i]=1;
                } else {
-                       // count sample
-                       fcCounter++;
+                       BitStream[i]=0;
                }
        }
-       
-       uint8_t best1=14, best2=14, best3=14;
-       uint16_t maxCnt1=0;
-       // go through fclens and find which ones are bigest 2  
-       for (i=0; i<15; i++){
-               // get the 3 best FC values
-               if (fcCnts[i]>maxCnt1) {
-                       best3=best2;
-                       best2=best1;
-                       maxCnt1=fcCnts[i];
-                       best1=i;
-               } else if(fcCnts[i]>fcCnts[best2]){
-                       best3=best2;
-                       best2=i;
-               } else if(fcCnts[i]>fcCnts[best3]){
-                       best3=i;
+       return;
+}
+
+// by marshmellow
+// convert psk2 demod to psk1 demod
+// from only transition waves are 1s to phase shifts change bit
+void psk2TOpsk1(uint8_t *BitStream, size_t size) {
+       uint8_t phase=0;
+       for (size_t i=0; i<size; i++){
+               if (BitStream[i]==1){
+                       phase ^=1;
                }
-               if (g_debugMode==2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]);
-       }
-       if (fcLens[best1]==0) return 0;
-       uint8_t fcH=0, fcL=0;
-       if (fcLens[best1]>fcLens[best2]){
-               fcH=fcLens[best1];
-               fcL=fcLens[best2];
-       } else{
-               fcH=fcLens[best2];
-               fcL=fcLens[best1];
-       }
-       if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) {
-               if (g_debugMode==2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]);
-               return 0; //lots of waves not psk or fsk
+               BitStream[i]=phase;
        }
-       // TODO: take top 3 answers and compare to known Field clocks to get top 2
+       return;
+}
 
-       uint16_t fcs = (((uint16_t)fcH)<<8) | fcL;
-       if (fskAdj) return fcs; 
-       return fcLens[best1];
+size_t pskFindFirstPhaseShift(uint8_t samples[], size_t size, uint8_t *curPhase, size_t waveStart, uint16_t fc, uint16_t *fullWaveLen) {
+       uint16_t loopCnt = (size+3 < 4096) ? size : 4096;  //don't need to loop through entire array...
+
+       uint16_t avgWaveVal=0, lastAvgWaveVal=0;
+       size_t i = waveStart, waveEnd, waveLenCnt, firstFullWave;
+       for (; i<loopCnt; i++) {
+               // find peak 
+               if (samples[i]+fc < samples[i+1] && samples[i+1] >= samples[i+2]){
+                       waveEnd = i+1;
+                       if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u", waveEnd, waveStart);
+                       waveLenCnt = waveEnd-waveStart;
+                       if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+8)){ //not first peak and is a large wave but not out of whack
+                               lastAvgWaveVal = avgWaveVal/(waveLenCnt);
+                               firstFullWave = waveStart;
+                               *fullWaveLen = waveLenCnt;
+                               //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting)
+                               if (lastAvgWaveVal > FSK_PSK_THRESHOLD) *curPhase ^= 1;
+                               return firstFullWave;
+                       }
+                       waveStart = i+1;
+                       avgWaveVal = 0;
+               }
+               avgWaveVal += samples[i+2];
+       }
+       return 0;
 }
 
 //by marshmellow - demodulate PSK1 wave 
 //uses wave lengths (# Samples) 
-int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
-{
-       if (size == 0) return -1;
-       uint16_t loopCnt = 4096;  //don't need to loop through entire array...
-       if (*size<loopCnt) loopCnt = *size;
+int pskRawDemod_ext(uint8_t dest[], size_t *size, int *clock, int *invert, int *startIdx) {
+       if (*size < 170) return -1;
 
-       size_t numBits=0;
        uint8_t curPhase = *invert;
-       size_t i=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0;
-       uint16_t fc=0, fullWaveLen=0, tol=1;
-       uint16_t errCnt=0, waveLenCnt=0, errCnt2=0;
+       size_t i=0, numBits=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0;
+       uint16_t fc=0, fullWaveLen=0, waveLenCnt=0, avgWaveVal, tol=1;
+       uint16_t errCnt=0, errCnt2=0;
+       
        fc = countFC(dest, *size, 1);
-       uint8_t fc2 = fc >> 8;
-       if (fc2 == 10) return -1; //fsk found - quit
+       if ((fc >> 8) == 10) return -1; //fsk found - quit
        fc = fc & 0xFF;
        if (fc!=2 && fc!=4 && fc!=8) return -1;
-       //PrintAndLog("DEBUG: FC: %d",fc);
        *clock = DetectPSKClock(dest, *size, *clock);
        if (*clock == 0) return -1;
 
        //find start of modulating data in trace 
-       uint8_t threshold_value = 123; //-5
-       i = findModStart(dest, *size, threshold_value, fc);
+       i = findModStart(dest, *size, fc);
 
        //find first phase shift
-       int avgWaveVal=0, lastAvgWaveVal=0;
-       waveStart = i;
-       for (; i<loopCnt; i++) {
-               // find peak 
-               if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){
-                       waveEnd = i+1;
-                       if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u",waveEnd, waveStart);
-                       waveLenCnt = waveEnd-waveStart;
-                       if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+3)){ //not first peak and is a large wave but not out of whack
-                               lastAvgWaveVal = avgWaveVal/(waveLenCnt);
-                               firstFullWave = waveStart;
-                               fullWaveLen=waveLenCnt;
-                               //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting)
-                               if (lastAvgWaveVal > threshold_value) curPhase ^= 1;
-                               break;
-                       } 
-                       waveStart = i+1;
-                       avgWaveVal = 0;
-               }
-               avgWaveVal += dest[i+2];
-       }
+       firstFullWave = pskFindFirstPhaseShift(dest, *size, &curPhase, i, fc, &fullWaveLen);
        if (firstFullWave == 0) {
                // no phase shift detected - could be all 1's or 0's - doesn't matter where we start
                // so skip a little to ensure we are past any Start Signal
@@ -1564,9 +1584,10 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
        }
        //advance bits
        numBits += (firstFullWave / *clock);
+       *startIdx = firstFullWave - (*clock * numBits)+2;
        //set start of wave as clock align
        lastClkBit = firstFullWave;
-       if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen);  
+       if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i",firstFullWave,fullWaveLen, *startIdx);
        if (g_debugMode==2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc);
        waveStart = 0;
        dest[numBits++] = curPhase; //set first read bit
@@ -1580,9 +1601,7 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
                        } else { //waveEnd
                                waveEnd = i+1;
                                waveLenCnt = waveEnd-waveStart;
-                               lastAvgWaveVal = avgWaveVal/waveLenCnt;
-                               if (waveLenCnt > fc){  
-                                       //PrintAndLog("DEBUG: avgWaveVal: %d, waveSum: %d",lastAvgWaveVal,avgWaveVal);
+                               if (waveLenCnt > fc){
                                        //this wave is a phase shift
                                        //PrintAndLog("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc);
                                        if (i+1 >= lastClkBit + *clock - tol){ //should be a clock bit
@@ -1606,205 +1625,270 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
                                waveStart = i+1;
                        }
                }
-               avgWaveVal += dest[i+1];
+               avgWaveVal += dest[i+1];
+       }
+       *size = numBits;
+       return errCnt;
+}
+
+int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) {
+       int startIdx = 0;
+       return pskRawDemod_ext(dest, size, clock, invert, &startIdx);
+}
+
+//**********************************************************************************************
+//-----------------Tag format detection section-------------------------------------------------
+//**********************************************************************************************
+
+// by marshmellow
+// FSK Demod then try to locate an AWID ID
+int AWIDdemodFSK(uint8_t *dest, size_t *size) {
+       //make sure buffer has enough data
+       if (*size < 96*50) return -1;
+
+       if (justNoise(dest, *size)) return -2;
+
+       // FSK demodulator
+       *size = fskdemod(dest, *size, 50, 1, 10, 8);  // fsk2a RF/50 
+       if (*size < 96) return -3;  //did we get a good demod?
+
+       uint8_t preamble[] = {0,0,0,0,0,0,0,1};
+       size_t startIdx = 0;
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -4; //preamble not found
+       if (*size != 96) return -5;
+       return (int)startIdx;
+}
+
+//by marshmellow
+//takes 1s and 0s and searches for EM410x format - output EM ID
+uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo)
+{
+       //sanity checks
+       if (*size < 64) return 0;
+       if (BitStream[1]>1) return 0;  //allow only 1s and 0s
+
+       // 111111111 bit pattern represent start of frame
+       //  include 0 in front to help get start pos
+       uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1};
+       uint8_t errChk = 0;
+       uint8_t FmtLen = 10; // sets of 4 bits = end data 
+       *startIdx = 0;
+       errChk = preambleSearch(BitStream, preamble, sizeof(preamble), size, startIdx);
+       if ( errChk == 0 || (*size != 64 && *size != 128) ) return 0;
+       if (*size == 128) FmtLen = 22; // 22 sets of 4 bits
+
+       //skip last 4bit parity row for simplicity
+       *size = removeParity(BitStream, *startIdx + sizeof(preamble), 5, 0, FmtLen * 5);
+       if (*size == 40) { // std em410x format
+               *hi = 0;
+               *lo = ((uint64_t)(bytebits_to_byte(BitStream, 8)) << 32) | (bytebits_to_byte(BitStream + 8, 32));
+       } else if (*size == 88) { // long em format
+               *hi = (bytebits_to_byte(BitStream, 24)); 
+               *lo = ((uint64_t)(bytebits_to_byte(BitStream + 24, 32)) << 32) | (bytebits_to_byte(BitStream + 24 + 32, 32));
+       } else {
+               return 0;
+       }
+       return 1;
+}
+
+// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
+// BitStream must contain previously askrawdemod and biphasedemoded data
+int FDXBdemodBI(uint8_t *dest, size_t *size) {
+       //make sure buffer has enough data
+       if (*size < 128) return -1;
+
+       size_t startIdx = 0;
+       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,1};
+
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -2; //preamble not found
+       return (int)startIdx;
+}
+
+// by marshmellow
+// demod gProxIIDemod 
+// error returns as -x 
+// success returns start position in BitStream
+// BitStream must contain previously askrawdemod and biphasedemoded data
+int gProxII_Demod(uint8_t BitStream[], size_t *size) {
+       size_t startIdx=0;
+       uint8_t preamble[] = {1,1,1,1,1,0};
+
+       uint8_t errChk = preambleSearch(BitStream, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -3; //preamble not found
+       if (*size != 96) return -2; //should have found 96 bits
+       //check first 6 spacer bits to verify format
+       if (!BitStream[startIdx+5] && !BitStream[startIdx+10] && !BitStream[startIdx+15] && !BitStream[startIdx+20] && !BitStream[startIdx+25] && !BitStream[startIdx+30]){
+               //confirmed proper separator bits found
+               //return start position
+               return (int) startIdx;
+       }
+       return -5; //spacer bits not found - not a valid gproxII
+}
+
+// loop to get raw HID waveform then FSK demodulate the TAG ID from it
+int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo) {
+       if (justNoise(dest, *size)) return -1;
+
+       size_t numStart=0, size2=*size, startIdx=0; 
+       // FSK demodulator
+       *size = fskdemod(dest, size2,50,1,10,8); //fsk2a
+       if (*size < 96*2) return -2;
+       // 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
+       uint8_t preamble[] = {0,0,0,1,1,1,0,1};
+       // find bitstring in array  
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -3; //preamble not found
+
+       numStart = startIdx + sizeof(preamble);
+       // final loop, go over previously decoded FSK data and manchester decode into usable tag ID
+       for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){
+               if (dest[idx] == dest[idx+1]){
+                       return -4; //not manchester data
+               }
+               *hi2 = (*hi2<<1)|(*hi>>31);
+               *hi = (*hi<<1)|(*lo>>31);
+               //Then, shift in a 0 or one into low
+               if (dest[idx] && !dest[idx+1])  // 1 0
+                       *lo=(*lo<<1)|1;
+               else // 0 1
+                       *lo=(*lo<<1)|0;
        }
-       *size = numBits;
-       return errCnt;
-}
-
-bool DetectST(uint8_t  buffer[], size_t *size, int *foundclock) {
-       size_t ststart = 0, stend = 0;
-       return DetectST_ext(buffer, size, foundclock, &ststart, &stend);
+       return (int)startIdx;
 }
 
-//by marshmellow
-//attempt to identify a Sequence Terminator in ASK modulated raw wave
-bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend) {
-       size_t bufsize = *size;
-       //need to loop through all samples and identify our clock, look for the ST pattern
-       uint8_t fndClk[] = {8,16,32,40,50,64,128};
-       int clk = 0; 
-       int tol = 0;
-       int i, j, skip, start, end, low, high, minClk, waveStart;
-       bool complete = false;
-       int tmpbuff[bufsize / 32]; //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured
-       int waveLen[bufsize / 32]; //  if clock is larger then we waste memory in array size that is not needed...
-       size_t testsize = (bufsize < 512) ? bufsize : 512;
-       int phaseoff = 0;
-       high = low = 128;
-       memset(tmpbuff, 0, sizeof(tmpbuff));
+int IOdemodFSK(uint8_t *dest, size_t size) {
+       if (justNoise(dest, size)) return -1;
+       //make sure buffer has data
+       if (size < 66*64) return -2;
+       // FSK demodulator
+       size = fskdemod(dest, size, 64, 1, 10, 8);  // FSK2a RF/64 
+       if (size < 65) return -3;  //did we get a good demod?
+       //Index map
+       //0           10          20          30          40          50          60
+       //|           |           |           |           |           |           |
+       //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
+       //-----------------------------------------------------------------------------
+       //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
+       //
+       //XSF(version)facility:codeone+codetwo
+       //Handle the data
+       size_t startIdx = 0;
+       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,1};
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), &size, &startIdx);
+       if (errChk == 0) return -4; //preamble not found
 
-       if ( getHiLo(buffer, testsize, &high, &low, 80, 80) == -1 ) {
-               if (g_debugMode==2) prnt("DEBUG STT: just noise detected - quitting");
-               return false; //just noise
+       if (!dest[startIdx+8] && dest[startIdx+17]==1 && dest[startIdx+26]==1 && dest[startIdx+35]==1 && dest[startIdx+44]==1 && dest[startIdx+53]==1){
+               //confirmed proper separator bits found
+               //return start position
+               return (int) startIdx;
        }
-       i = 0;
-       j = 0;
-       minClk = 255;
-       // get to first full low to prime loop and skip incomplete first pulse
-       while ((buffer[i] < high) && (i < bufsize))
-               ++i;
-       while ((buffer[i] > low) && (i < bufsize))
-               ++i;
-       skip = i;
+       return -5;
+} 
 
-       // populate tmpbuff buffer with pulse lengths
-       while (i < bufsize) {
-               // measure from low to low
-               while ((buffer[i] > low) && (i < bufsize))
-                       ++i;
-               start= i;
-               while ((buffer[i] < high) && (i < bufsize))
-                       ++i;
-               //first high point for this wave
-               waveStart = i;
-               while ((buffer[i] > low) && (i < bufsize))
-                       ++i;
-               if (j >= (bufsize/32)) {
-                       break;
-               }
-               waveLen[j] = i - waveStart; //first high to first low
-               tmpbuff[j++] = i - start;
-               if (i-start < minClk && i < bufsize) {
-                       minClk = i - start;
-               }
-       }
-       // set clock  - might be able to get this externally and remove this work...
-       if (!clk) {
-               for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
-                       tol = fndClk[clkCnt]/8;
-                       if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) { 
-                               clk=fndClk[clkCnt];
-                               break;
-                       }
-               }
-               // clock not found - ERROR
-               if (!clk) {
-                       if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting");
-                       return false;
-               }
-       } else tol = clk/8;
+// redesigned by marshmellow adjusted from existing decode functions
+// indala id decoding - only tested on 26 bit tags, but attempted to make it work for more
+int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert) {
+       //26 bit 40134 format  (don't know other formats)
+       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+       uint8_t preamble_i[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0};
+       size_t startidx = 0; 
+       if (!preambleSearch(bitStream, preamble, sizeof(preamble), size, &startidx)){
+               // if didn't find preamble try again inverting
+               if (!preambleSearch(bitStream, preamble_i, sizeof(preamble_i), size, &startidx)) return -1;
+               *invert ^= 1;
+       } 
+       if (*size != 64 && *size != 224) return -2;
+       if (*invert==1)
+               for (size_t i = startidx; i < *size; i++)
+                       bitStream[i] ^= 1;
 
-       *foundclock = clk;
+       return (int) startidx;
+}
 
-       // look for Sequence Terminator - should be pulses of clk*(1 or 1.5), clk*2, clk*(1.5 or 2)
-       start = -1;
-       for (i = 0; i < j - 4; ++i) {
-               skip += tmpbuff[i];
-               if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol && waveLen[i] < clk+tol) {           //1 to 2 clocks depending on 2 bits prior
-                       if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) {       //2 clocks and wave size is 1 1/2
-                               if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
-                                       if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
-                                               start = i + 3;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-       }
-       // first ST not found - ERROR
-       if (start < 0) {
-               if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting");
-               return false;
-       } else {
-               if (g_debugMode==2) prnt("DEBUG STT: first STT found at: %d, j=%d",start, j);
-       }
-       if (waveLen[i+2] > clk*1+tol)
-               phaseoff = 0;
-       else
-               phaseoff = clk/2;
+// loop to get raw paradox waveform then FSK demodulate the TAG ID from it
+int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo) {
+       if (justNoise(dest, *size)) return -1;
        
-       // skip over the remainder of ST
-       skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point
+       size_t numStart=0, size2=*size, startIdx=0;
+       // FSK demodulator
+       *size = fskdemod(dest, size2,50,1,10,8); //fsk2a
+       if (*size < 96) return -2;
 
-       // now do it again to find the end
-       end = skip;
-       for (i += 3; i < j - 4; ++i) {
-               end += tmpbuff[i];
-               if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol && waveLen[i] < clk+tol) {           //1 to 2 clocks depending on 2 bits prior
-                       if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) {       //2 clocks and wave size is 1 1/2
-                               if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
-                                       if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
-                                               complete = true;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-       }
-       end -= phaseoff;
-       //didn't find second ST - ERROR
-       if (!complete) {
-               if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting");
-               return false;
-       }
-       if (g_debugMode==2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff);
-       //now begin to trim out ST so we can use normal demod cmds
-       start = skip;
-       size_t datalen = end - start;
-       // check validity of datalen (should be even clock increments)  - use a tolerance of up to 1/8th a clock
-       if ( clk - (datalen % clk) <= clk/8) {
-               // padd the amount off - could be problematic...  but shouldn't happen often
-               datalen += clk - (datalen % clk);
-       } else if ( (datalen % clk) <= clk/8 ) {
-               // padd the amount off - could be problematic...  but shouldn't happen often
-               datalen -= datalen % clk;
-       } else {
-               if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk);
-               return false;
-       }
-       // if datalen is less than one t55xx block - ERROR
-       if (datalen/clk < 8*4) {
-               if (g_debugMode==2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting");              
-               return false;
-       }
-       size_t dataloc = start;
-       if (buffer[dataloc-(clk*4)-(clk/8)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) {
-               //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start 
-               for ( i=0; i <= (clk/8); ++i ) {
-                       if ( buffer[dataloc - (clk*4) - i] <= low ) {
-                               dataloc -= i;
-                               break;
-                       }
-               }
-       }
-       
-       size_t newloc = 0;
-       i=0;
-       if (g_debugMode==2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen);            
-       bool firstrun = true;
-       // warning - overwriting buffer given with raw wave data with ST removed...
-       while ( dataloc < bufsize-(clk/2) ) {
-               //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part)
-               if (buffer[dataloc]<high && buffer[dataloc]>low && buffer[dataloc+3]<high && buffer[dataloc+3]>low) {
-                       for(i=0; i < clk/2-tol; ++i) {
-                               buffer[dataloc+i] = high+5;
-                       }
-               } //test for single sample outlier (high between two lows) in the case of very strong waves
-               if (buffer[dataloc] >= high && buffer[dataloc+2] <= low) {
-                       buffer[dataloc] = buffer[dataloc+2];
-                       buffer[dataloc+1] = buffer[dataloc+2];
-               }
-               if (firstrun) {
-                       *stend = dataloc;
-                       *ststart = dataloc-(clk*4);
-                       firstrun=false;
-               }
-               for (i=0; i<datalen; ++i) {
-                       if (i+newloc < bufsize) {
-                               if (i+newloc < dataloc)
-                                       buffer[i+newloc] = buffer[dataloc];
+       // 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
+       uint8_t preamble[] = {0,0,0,0,1,1,1,1};
 
-                               dataloc++;
-                       }
-               }
-               newloc += i;
-               //skip next ST  -  we just assume it will be there from now on...
-               if (g_debugMode==2) prnt("DEBUG STT: skipping STT at %d to %d", dataloc, dataloc+(clk*4));
-               dataloc += clk*4;
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -3; //preamble not found
+
+       numStart = startIdx + sizeof(preamble);
+       // final loop, go over previously decoded FSK data and manchester decode into usable tag ID
+       for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){
+               if (dest[idx] == dest[idx+1]) 
+                       return -4; //not manchester data
+               *hi2 = (*hi2<<1)|(*hi>>31);
+               *hi = (*hi<<1)|(*lo>>31);
+               //Then, shift in a 0 or one into low
+               if (dest[idx] && !dest[idx+1])  // 1 0
+                       *lo=(*lo<<1)|1;
+               else // 0 1
+                       *lo=(*lo<<1)|0;
        }
-       *size = newloc;
-       return true;
+       return (int)startIdx;
+}
+
+// find presco preamble 0x10D in already demoded data
+int PrescoDemod(uint8_t *dest, size_t *size) {
+       //make sure buffer has data
+       if (*size < 64*2) return -2;
+
+       size_t startIdx = 0;
+       uint8_t preamble[] = {1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0};
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -4; //preamble not found
+       //return start position
+       return (int) startIdx;
+}
+
+// by marshmellow
+// FSK Demod then try to locate a Farpointe Data (pyramid) ID
+int PyramiddemodFSK(uint8_t *dest, size_t *size) {
+       //make sure buffer has data
+       if (*size < 128*50) return -5;
+
+       //test samples are not just noise
+       if (justNoise(dest, *size)) return -1;
+
+       // FSK demodulator
+       *size = fskdemod(dest, *size, 50, 1, 10, 8);  // fsk2a RF/50 
+       if (*size < 128) return -2;  //did we get a good demod?
+
+       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+       size_t startIdx = 0;
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -4; //preamble not found
+       if (*size != 128) return -3;
+       return (int)startIdx;
+}
+
+// by marshmellow
+// find viking preamble 0xF200 in already demoded data
+int VikingDemod_AM(uint8_t *dest, size_t *size) {
+       //make sure buffer has data
+       if (*size < 64*2) return -2;
+
+       size_t startIdx = 0;
+       uint8_t preamble[] = {1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -4; //preamble not found
+       uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ bytebits_to_byte(dest+startIdx+8,8) ^ bytebits_to_byte(dest+startIdx+16,8)
+           ^ bytebits_to_byte(dest+startIdx+24,8) ^ bytebits_to_byte(dest+startIdx+32,8) ^ bytebits_to_byte(dest+startIdx+40,8) 
+           ^ bytebits_to_byte(dest+startIdx+48,8) ^ bytebits_to_byte(dest+startIdx+56,8);
+       if ( checkCalc != 0xA8 ) return -5;
+       if (*size != 64) return -6;
+       //return start position
+       return (int) startIdx;
 }
 
 // by iceman
index b465a6594e03fbda7044cae261f04b6c89592919..a881fa181d0649f150729a306e0bb1064e17169d 100644 (file)
@@ -19,6 +19,7 @@
 //generic
 extern size_t   addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType);
 extern int      askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType);
+extern int      askdemod_ext(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx);
 extern void     askAmp(uint8_t *BitStream, size_t size);
 extern int      BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
 extern uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
@@ -28,23 +29,24 @@ extern int      DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxE
 extern uint8_t  DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
 extern uint8_t  detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow);
 extern uint8_t  detectFSKClk_ext(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge);
-extern int      DetectNRZClock(uint8_t dest[], size_t size, int clock);
-extern int      DetectNRZClock_ext(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx);
+extern int      DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx);
 extern int      DetectPSKClock(uint8_t dest[], size_t size, int clock);
 extern int      DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseShift);
-extern int      DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low, int *clock);
+extern int      DetectStrongAskClock(uint8_t dest[], size_t size, int high, int low, int *clock);
 extern bool     DetectST(uint8_t buffer[], size_t *size, int *foundclock);
 extern bool     DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend);
 extern int      fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
+extern int      fskdemod_ext(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx);
 extern int      getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
 extern uint32_t manchesterEncode2Bytes(uint16_t datain);
 extern int      ManchesterEncode(uint8_t *BitStream, size_t size);
-extern int      manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert);
-extern int      nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert);
+extern int      manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert, uint8_t *alignPos);
+extern int      nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx);
 extern uint8_t  parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
 extern uint8_t  preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
 extern bool     preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone);
 extern int      pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
+extern int      pskRawDemod_ext(uint8_t dest[], size_t *size, int *clock, int *invert, int *startIdx);
 extern void     psk2TOpsk1(uint8_t *BitStream, size_t size);
 extern void     psk1TOpsk2(uint8_t *BitStream, size_t size);
 extern size_t   removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
diff --git a/tools/nonce2key/Makefile b/tools/nonce2key/Makefile
deleted file mode 100644 (file)
index 11e019d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-VPATH = ../../common/crapto1
-CC = gcc
-LD = gcc
-CFLAGS = -I../../common -Wall -O4
-LDFLAGS =
-
-OBJS = crypto1.o crapto1.o
-HEADERS = crapto1.h
-EXES = nonce2key
-WINEXES = $(patsubst %, %.exe, $(EXES))
-
-all: $(OBJS) $(EXES)
-
-%.o : %.c
-       $(CC) $(CFLAGS) -c -o $@ $<
-
-% : %.c
-       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $<
-
-clean: 
-       rm -f $(OBJS) $(EXES) $(WINEXES)
diff --git a/tools/nonce2key/nonce2key.c b/tools/nonce2key/nonce2key.c
deleted file mode 100644 (file)
index b789dca..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "crapto1/crapto1.h"
-#include <inttypes.h>
-#include <stdio.h>
-typedef unsigned char byte_t;
-
-int main(const int argc, const char* argv[]) {
-  struct Crypto1State *state;
-  uint32_t pos, uid, nt, nr, rr, nr_diff;
-  byte_t bt, i, ks3x[8], par[8][8];
-  uint64_t key_recovered;
-  uint64_t par_info;
-  uint64_t ks_info;
-  nr = rr = 0;
-  
-  if (argc < 5) {
-    printf("\nsyntax: %s <uid> <nt> <par> <ks>\n\n",argv[0]);
-    return 1;
-  }
-  sscanf(argv[1],"%08x",&uid);
-  sscanf(argv[2],"%08x",&nt);
-  sscanf(argv[3],"%016" SCNx64,&par_info);
-  sscanf(argv[4],"%016" SCNx64,&ks_info);
-  
-  // Reset the last three significant bits of the reader nonce
-  nr &= 0xffffff1f;
-  
-  printf("\nuid(%08x) nt(%08x) par(%016" PRIx64 ") ks(%016" PRIx64 ")\n\n",uid,nt,par_info,ks_info);
-
-  for (pos=0; pos<8; pos++)
-  {
-    ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
-    bt = (par_info >> (pos*8)) & 0xff;
-    for (i=0; i<8; i++)
-    {
-      par[7-pos][i] = (bt >> i) & 0x01;
-    }
-  }
-
-  printf("|diff|{nr}    |ks3|ks3^5|parity         |\n");
-  printf("+----+--------+---+-----+---------------+\n");
-  for (i=0; i<8; i++)
-  {
-    nr_diff = nr | i << 5;
-    printf("| %02x |%08x|",i << 5, nr_diff);
-    printf(" %01x |  %01x  |",ks3x[i], ks3x[i]^5);
-    for (pos=0; pos<7; pos++) printf("%01x,",par[i][pos]);
-    printf("%01x|\n",par[i][7]);
-  }
-  
-  state = lfsr_common_prefix(nr,rr,ks3x,par);
-  lfsr_rollback_word(state,uid^nt,0);
-  crypto1_get_lfsr(state,&key_recovered);
-  printf("\nkey recovered: %012" PRIx64 "\n\n",key_recovered);
-  crypto1_destroy(state);
-  
-  return 0;
-}
Impressum, Datenschutz