]> cvs.zerfleddert.de Git - proxmark3-svn/blame - client/cmdlfindala.c
split fdx-b demod to its own file
[proxmark3-svn] / client / cmdlfindala.c
CommitLineData
0fb65a26 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 Indala commands
8//-----------------------------------------------------------------------------
9
10#include <stdio.h>
11#include <string.h>
12#include "cmdlfindala.h"
13#include "proxmark3.h"
14#include "ui.h"
15#include "graph.h"
16#include "cmdparser.h"
17#include "cmddata.h" //for g_debugMode, demodbuff cmds
18#include "lfdemod.h" //for indala26decode
19#include "util.h" //for sprint_bin_break
20#include "cmdlf.h" //for CmdLFRead
21#include "cmdmain.h" //for clearCommandBuffer
22
23static int CmdHelp(const char *Cmd);
24
25// Indala 26 bit decode
26// by marshmellow
27// optional arguments - same as PSKDemod (clock & invert & maxerr)
28int CmdIndalaDecode(const char *Cmd) {
29 int ans;
30 if (strlen(Cmd)>0) {
31 ans = PSKDemod(Cmd, 0);
32 } else { //default to RF/32
33 ans = PSKDemod("32", 0);
34 }
35
36 if (!ans) {
37 if (g_debugMode)
38 PrintAndLog("Error1: %i",ans);
39 return 0;
40 }
41 uint8_t invert=0;
42 size_t size = DemodBufferLen;
43 int startIdx = indala26decode(DemodBuffer, &size, &invert);
44 if (startIdx < 0 || size > 224) {
45 if (g_debugMode)
46 PrintAndLog("Error2: %i",startIdx);
47 return -1;
48 }
49 setDemodBuf(DemodBuffer, size, (size_t)startIdx);
50 if (invert)
51 if (g_debugMode)
52 PrintAndLog("Had to invert bits");
53
54 PrintAndLog("BitLen: %d",DemodBufferLen);
55 //convert UID to HEX
56 uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
57 uid1=bytebits_to_byte(DemodBuffer,32);
58 uid2=bytebits_to_byte(DemodBuffer+32,32);
59 if (DemodBufferLen==64) {
60 PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2);
61 } else if (DemodBufferLen==224) {
62 uid3=bytebits_to_byte(DemodBuffer+64,32);
63 uid4=bytebits_to_byte(DemodBuffer+96,32);
64 uid5=bytebits_to_byte(DemodBuffer+128,32);
65 uid6=bytebits_to_byte(DemodBuffer+160,32);
66 uid7=bytebits_to_byte(DemodBuffer+192,32);
67 PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)",
68 sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7);
69 }
70 if (g_debugMode) {
71 PrintAndLog("DEBUG: printing demodbuffer:");
72 printDemodBuff();
73 }
74 return 1;
75}
76
77int CmdIndalaRead(const char *Cmd) {
78 CmdLFRead("s");
79 getSamples("30000",false);
80 return CmdIndalaDecode("");
81}
82
83// older alternative indala demodulate (has some positives and negatives)
84// returns false positives more often - but runs against more sets of samples
85// poor psk signal can be difficult to demod this approach might succeed when the other fails
86// but the other appears to currently be more accurate than this approach most of the time.
87int CmdIndalaDemod(const char *Cmd) {
88 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
89
90 int state = -1;
91 int count = 0;
92 int i, j;
93
94 // worst case with GraphTraceLen=64000 is < 4096
95 // under normal conditions it's < 2048
96
97 uint8_t rawbits[4096];
98 int rawbit = 0;
99 int worst = 0, worstPos = 0;
100 // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
101
102 // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2)
103 for (i = 0; i < GraphTraceLen-1; i += 2) {
104 count += 1;
105 if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
106 // appears redundant - marshmellow
107 if (state == 0) {
108 for (j = 0; j < count - 8; j += 16) {
109 rawbits[rawbit++] = 0;
110 }
111 if ((abs(count - j)) > worst) {
112 worst = abs(count - j);
113 worstPos = i;
114 }
115 }
116 state = 1;
117 count = 0;
118 } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
119 //appears redundant
120 if (state == 1) {
121 for (j = 0; j < count - 8; j += 16) {
122 rawbits[rawbit++] = 1;
123 }
124 if ((abs(count - j)) > worst) {
125 worst = abs(count - j);
126 worstPos = i;
127 }
128 }
129 state = 0;
130 count = 0;
131 }
132 }
133
134 if (rawbit>0){
135 PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
136 PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
137 } else {
138 return 0;
139 }
140
141 // Finding the start of a UID
142 int uidlen, long_wait;
143 if (strcmp(Cmd, "224") == 0) {
144 uidlen = 224;
145 long_wait = 30;
146 } else {
147 uidlen = 64;
148 long_wait = 29;
149 }
150
151 int start;
152 int first = 0;
153 for (start = 0; start <= rawbit - uidlen; start++) {
154 first = rawbits[start];
155 for (i = start; i < start + long_wait; i++) {
156 if (rawbits[i] != first) {
157 break;
158 }
159 }
160 if (i == (start + long_wait)) {
161 break;
162 }
163 }
164
165 if (start == rawbit - uidlen + 1) {
166 PrintAndLog("nothing to wait for");
167 return 0;
168 }
169
170 // Inverting signal if needed
171 if (first == 1) {
172 for (i = start; i < rawbit; i++) {
173 rawbits[i] = !rawbits[i];
174 }
175 }
176
177 // Dumping UID
178 uint8_t bits[224] = {0x00};
179 char showbits[225] = {0x00};
180 int bit;
181 i = start;
182 int times = 0;
183
184 if (uidlen > rawbit) {
185 PrintAndLog("Warning: not enough raw bits to get a full UID");
186 for (bit = 0; bit < rawbit; bit++) {
187 bits[bit] = rawbits[i++];
188 // As we cannot know the parity, let's use "." and "/"
189 showbits[bit] = '.' + bits[bit];
190 }
191 showbits[bit+1]='\0';
192 PrintAndLog("Partial UID=%s", showbits);
193 return 0;
194 } else {
195 for (bit = 0; bit < uidlen; bit++) {
196 bits[bit] = rawbits[i++];
197 showbits[bit] = '0' + bits[bit];
198 }
199 times = 1;
200 }
201
202 //convert UID to HEX
203 uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
204 int idx;
205 uid1 = uid2 = 0;
206
207 if (uidlen==64){
208 for( idx=0; idx<64; idx++) {
209 if (showbits[idx] == '0') {
210 uid1=(uid1<<1)|(uid2>>31);
211 uid2=(uid2<<1)|0;
212 } else {
213 uid1=(uid1<<1)|(uid2>>31);
214 uid2=(uid2<<1)|1;
215 }
216 }
217 PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
218 }
219 else {
220 uid3 = uid4 = uid5 = uid6 = uid7 = 0;
221
222 for( idx=0; idx<224; idx++) {
223 uid1=(uid1<<1)|(uid2>>31);
224 uid2=(uid2<<1)|(uid3>>31);
225 uid3=(uid3<<1)|(uid4>>31);
226 uid4=(uid4<<1)|(uid5>>31);
227 uid5=(uid5<<1)|(uid6>>31);
228 uid6=(uid6<<1)|(uid7>>31);
229
230 if (showbits[idx] == '0')
231 uid7 = (uid7<<1) | 0;
232 else
233 uid7 = (uid7<<1) | 1;
234 }
235 PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
236 }
237
238 // Checking UID against next occurrences
239 int failed = 0;
240 for (; i + uidlen <= rawbit;) {
241 failed = 0;
242 for (bit = 0; bit < uidlen; bit++) {
243 if (bits[bit] != rawbits[i++]) {
244 failed = 1;
245 break;
246 }
247 }
248 if (failed == 1) {
249 break;
250 }
251 times += 1;
252 }
253
254 PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
255
256 // Remodulating for tag cloning
257 // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod)
258 // since this changes graphbuffer data.
259 GraphTraceLen = 32*uidlen;
260 i = 0;
261 int phase = 0;
262 for (bit = 0; bit < uidlen; bit++) {
263 if (bits[bit] == 0) {
264 phase = 0;
265 } else {
266 phase = 1;
267 }
268 int j;
269 for (j = 0; j < 32; j++) {
270 GraphBuffer[i++] = phase;
271 phase = !phase;
272 }
273 }
274
275 RepaintGraphWindow();
276 return 1;
277}
278
279int CmdIndalaClone(const char *Cmd) {
280 UsbCommand c;
281 unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
282
283 uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
284 int n = 0, i = 0;
285
286 if (strchr(Cmd,'l') != 0) {
287 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
288 uid1 = (uid1 << 4) | (uid2 >> 28);
289 uid2 = (uid2 << 4) | (uid3 >> 28);
290 uid3 = (uid3 << 4) | (uid4 >> 28);
291 uid4 = (uid4 << 4) | (uid5 >> 28);
292 uid5 = (uid5 << 4) | (uid6 >> 28);
293 uid6 = (uid6 << 4) | (uid7 >> 28);
294 uid7 = (uid7 << 4) | (n & 0xf);
295 }
296 PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
297 c.cmd = CMD_INDALA_CLONE_TAG_L;
298 c.d.asDwords[0] = uid1;
299 c.d.asDwords[1] = uid2;
300 c.d.asDwords[2] = uid3;
301 c.d.asDwords[3] = uid4;
302 c.d.asDwords[4] = uid5;
303 c.d.asDwords[5] = uid6;
304 c.d.asDwords[6] = uid7;
305 } else {
306 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
307 uid1 = (uid1 << 4) | (uid2 >> 28);
308 uid2 = (uid2 << 4) | (n & 0xf);
309 }
310 PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
311 c.cmd = CMD_INDALA_CLONE_TAG;
312 c.arg[0] = uid1;
313 c.arg[1] = uid2;
314 }
315
316 clearCommandBuffer();
317 SendCommand(&c);
318 return 0;
319}
320
321static command_t CommandTable[] = {
322 {"help", CmdHelp, 1, "This help"},
323 {"demod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"},
324 {"read", CmdIndalaRead, 0, "Read an Indala Prox tag from the antenna"},
325 {"clone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be on antenna)(UID in HEX)(option 'l' for 224 UID"},
326 {"altdemod", CmdIndalaDemod, 1, "['224'] -- Alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
327 //{"sim", CmdIndalaSim, 0, "<ID> -- indala tag simulator"},
328 {NULL, NULL, 0, NULL}
329};
330
331int CmdLFINDALA(const char *Cmd) {
332 CmdsParse(CommandTable, Cmd);
333 return 0;
334}
335
336int CmdHelp(const char *Cmd) {
337 CmdsHelp(CommandTable);
338 return 0;
339}
Impressum, Datenschutz