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