]>
Commit | Line | Data |
---|---|---|
1 | //----------------------------------------------------------------------------- | |
2 | // | |
3 | // This code is licensed to you under the terms of the GNU GPL, version 2 or, | |
4 | // at your option, any later version. See the LICENSE.txt file for the text of | |
5 | // the license. | |
6 | //----------------------------------------------------------------------------- | |
7 | // Low frequency Securakey tag commands | |
8 | // ASK/Manchester, RF/40, 96 bits long (unknown cs) | |
9 | //----------------------------------------------------------------------------- | |
10 | ||
11 | #include "cmdlfsecurakey.h" | |
12 | ||
13 | #include <string.h> | |
14 | #include <inttypes.h> | |
15 | #include <math.h> | |
16 | #include "comms.h" | |
17 | #include "ui.h" | |
18 | #include "util.h" | |
19 | #include "graph.h" | |
20 | #include "cmdparser.h" | |
21 | #include "cmddata.h" | |
22 | #include "cmdmain.h" | |
23 | #include "cmdlf.h" | |
24 | #include "protocols.h" // for T55xx config register definitions | |
25 | #include "lfdemod.h" // preamble test | |
26 | #include "parity.h" // for wiegand parity test | |
27 | ||
28 | static int CmdHelp(const char *Cmd); | |
29 | ||
30 | // by marshmellow | |
31 | // find Securakey preamble in already demoded data | |
32 | int SecurakeyFind(uint8_t *dest, size_t *size) { | |
33 | if (*size < 96) return -1; //make sure buffer has data | |
34 | size_t startIdx = 0; | |
35 | uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1,0,0,1}; | |
36 | if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) | |
37 | return -2; //preamble not found | |
38 | if (*size != 96) return -3; //wrong demoded size | |
39 | //return start position | |
40 | return (int)startIdx; | |
41 | } | |
42 | ||
43 | //see ASKDemod for what args are accepted | |
44 | int CmdSecurakeyDemod(const char *Cmd) { | |
45 | ||
46 | //ASK / Manchester | |
47 | bool st = false; | |
48 | if (!ASKDemod_ext("40 0 0", false, false, 1, &st)) { | |
49 | if (g_debugMode) PrintAndLog("DEBUG: Error - Securakey: ASK/Manchester Demod failed"); | |
50 | return 0; | |
51 | } | |
52 | if (st) return 0; | |
53 | size_t size = DemodBufferLen; | |
54 | int ans = SecurakeyFind(DemodBuffer, &size); | |
55 | if (ans < 0) { | |
56 | if (g_debugMode) { | |
57 | if (ans == -1) | |
58 | PrintAndLog("DEBUG: Error - Securakey: too few bits found"); | |
59 | else if (ans == -2) | |
60 | PrintAndLog("DEBUG: Error - Securakey: preamble not found"); | |
61 | else if (ans == -3) | |
62 | PrintAndLog("DEBUG: Error - Securakey: Size not correct: %d", size); | |
63 | else | |
64 | PrintAndLog("DEBUG: Error - Securakey: ans: %d", ans); | |
65 | } | |
66 | return 0; | |
67 | } | |
68 | setDemodBuf(DemodBuffer, 96, ans); | |
69 | setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); | |
70 | ||
71 | //got a good demod | |
72 | uint32_t raw1 = bytebits_to_byte(DemodBuffer , 32); | |
73 | uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); | |
74 | uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32); | |
75 | ||
76 | // 26 bit format | |
77 | // preamble ??bitlen reserved EPx xxxxxxxy yyyyyyyy yyyyyyyOP CS? CS2? | |
78 | // 0111111111 0 01011010 0 00000000 0 00000010 0 00110110 0 00111110 0 01100010 0 00001111 0 01100000 0 00000000 0 0000 | |
79 | ||
80 | // 32 bit format | |
81 | // preamble ??bitlen reserved EPxxxxxxx xxxxxxxy yyyyyyyy yyyyyyyOP CS? CS2? | |
82 | // 0111111111 0 01100000 0 00000000 0 10000100 0 11001010 0 01011011 0 01010110 0 00010110 0 11100000 0 00000000 0 0000 | |
83 | ||
84 | // x = FC? | |
85 | // y = card # | |
86 | // standard wiegand parities. | |
87 | // unknown checksum 11 bits? at the end | |
88 | uint8_t bits_no_spacer[85]; | |
89 | memcpy(bits_no_spacer, DemodBuffer + 11, 85); | |
90 | ||
91 | // remove marker bits (0's every 9th digit after preamble) (pType = 3 (always 0s)) | |
92 | size = removeParity(bits_no_spacer, 0, 9, 3, 85); | |
93 | if ( size != 85-9 ) { | |
94 | if (g_debugMode) PrintAndLog("DEBUG: Error removeParity: %d", size); | |
95 | return 0; | |
96 | } | |
97 | ||
98 | uint8_t bitLen = (uint8_t)bytebits_to_byte(bits_no_spacer+2, 6); | |
99 | uint32_t fc=0, lWiegand=0, rWiegand=0; | |
100 | if (bitLen > 40) { //securakey's max bitlen is 40 bits... | |
101 | if (g_debugMode) PrintAndLog("DEBUG: Error bitLen too long: %u", bitLen); | |
102 | return 0; | |
103 | } | |
104 | // get left 1/2 wiegand & right 1/2 wiegand (for parity test and wiegand print) | |
105 | lWiegand = bytebits_to_byte(bits_no_spacer + 48 - bitLen, bitLen/2); | |
106 | rWiegand = bytebits_to_byte(bits_no_spacer + 48 - bitLen + bitLen/2, bitLen/2); | |
107 | // get FC | |
108 | fc = bytebits_to_byte(bits_no_spacer+49-bitLen, bitLen-2-16); | |
109 | ||
110 | // test bitLen | |
111 | if (bitLen != 26 && bitLen != 32) | |
112 | PrintAndLog("***unknown securakey bitLen - share with forum***"); | |
113 | ||
114 | uint32_t cardid = bytebits_to_byte(bits_no_spacer+8+23, 16); | |
115 | // test parities - evenparity32 looks to add an even parity returns 0 if already even... | |
116 | bool parity = !evenparity32(lWiegand) && !oddparity32(rWiegand); | |
117 | ||
118 | PrintAndLog("Securakey Tag Found--BitLen: %u, Card ID: %u, FC: 0x%X, Raw: %08X%08X%08X", bitLen, cardid, fc, raw1 ,raw2, raw3); | |
119 | if (bitLen <= 32) | |
120 | PrintAndLog("Wiegand: %08X, Parity: %s", (lWiegand<<(bitLen/2)) | rWiegand, parity ? "Passed" : "Failed"); | |
121 | PrintAndLog("\nHow the FC translates to printed FC is unknown"); | |
122 | PrintAndLog("How the checksum is calculated is unknown"); | |
123 | PrintAndLog("Help the community identify this format further\n by sharing your tag on the pm3 forum or with forum members"); | |
124 | return 1; | |
125 | } | |
126 | ||
127 | int CmdSecurakeyRead(const char *Cmd) { | |
128 | lf_read(true, 8000); | |
129 | return CmdSecurakeyDemod(Cmd); | |
130 | } | |
131 | ||
132 | static command_t CommandTable[] = { | |
133 | {"help", CmdHelp, 1, "This help"}, | |
134 | {"demod", CmdSecurakeyDemod,1, "Attempt to read and extract tag data from the GraphBuffer"}, | |
135 | {"read", CmdSecurakeyRead, 0, "Attempt to read and extract tag data from the antenna"}, | |
136 | {NULL, NULL, 0, NULL} | |
137 | }; | |
138 | ||
139 | int CmdLFSecurakey(const char *Cmd) { | |
140 | clearCommandBuffer(); | |
141 | CmdsParse(CommandTable, Cmd); | |
142 | return 0; | |
143 | } | |
144 | ||
145 | int CmdHelp(const char *Cmd) { | |
146 | CmdsHelp(CommandTable); | |
147 | return 0; | |
148 | } |