]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdlfem4x.c
making USB CDC branch
[proxmark3-svn] / client / cmdlfem4x.c
CommitLineData
a553f267 1//-----------------------------------------------------------------------------
2// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3//
4// This code is licensed to you under the terms of the GNU GPL, version 2 or,
5// at your option, any later version. See the LICENSE.txt file for the text of
6// the license.
7//-----------------------------------------------------------------------------
8// Low frequency EM4x commands
9//-----------------------------------------------------------------------------
10
7fe9b0b7 11#include <stdio.h>
9e13f875 12#include <string.h>
ec564290 13#include <inttypes.h>
7fe9b0b7 14#include "proxusb.h"
15#include "ui.h"
16#include "graph.h"
17#include "cmdparser.h"
18#include "cmddata.h"
19#include "cmdlf.h"
20#include "cmdlfem4x.h"
21
22static int CmdHelp(const char *Cmd);
23
24/* Read the ID of an EM410x tag.
25 * Format:
26 * 1111 1111 1 <-- standard non-repeatable header
27 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
28 * ....
29 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
30 * 0 <-- stop bit, end of tag
31 */
32int CmdEM410xRead(const char *Cmd)
33{
34 int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low;
35 int parity[4];
36 char id[11];
37 int retested = 0;
15cdabd4 38 uint8_t BitStream[MAX_GRAPH_TRACE_LEN];
7fe9b0b7 39 high = low = 0;
40
41 /* Detect high and lows and clock */
42 for (i = 0; i < GraphTraceLen; i++)
43 {
44 if (GraphBuffer[i] > high)
45 high = GraphBuffer[i];
46 else if (GraphBuffer[i] < low)
47 low = GraphBuffer[i];
48 }
49
50 /* get clock */
51 clock = GetClock(Cmd, high, 0);
52
53 /* parity for our 4 columns */
54 parity[0] = parity[1] = parity[2] = parity[3] = 0;
55 header = rows = 0;
56
57 /* manchester demodulate */
58 bit = bit2idx = 0;
59 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
60 {
61 hithigh = 0;
62 hitlow = 0;
63 first = 1;
64
65 /* Find out if we hit both high and low peaks */
66 for (j = 0; j < clock; j++)
67 {
68 if (GraphBuffer[(i * clock) + j] == high)
69 hithigh = 1;
70 else if (GraphBuffer[(i * clock) + j] == low)
71 hitlow = 1;
72
73 /* it doesn't count if it's the first part of our read
74 because it's really just trailing from the last sequence */
75 if (first && (hithigh || hitlow))
76 hithigh = hitlow = 0;
77 else
78 first = 0;
79
80 if (hithigh && hitlow)
81 break;
82 }
83
84 /* If we didn't hit both high and low peaks, we had a bit transition */
85 if (!hithigh || !hitlow)
86 bit ^= 1;
87
88 BitStream[bit2idx++] = bit;
89 }
90
91retest:
92 /* We go till 5 before the graph ends because we'll get that far below */
93 for (i = 1; i < bit2idx - 5; i++)
94 {
95 /* Step 2: We have our header but need our tag ID */
96 if (header == 9 && rows < 10)
97 {
98 /* Confirm parity is correct */
99 if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
100 {
101 /* Read another byte! */
102 sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
103 rows++;
104
105 /* Keep parity info */
106 parity[0] ^= BitStream[i];
107 parity[1] ^= BitStream[i+1];
108 parity[2] ^= BitStream[i+2];
109 parity[3] ^= BitStream[i+3];
110
111 /* Move 4 bits ahead */
112 i += 4;
113 }
114
115 /* Damn, something wrong! reset */
116 else
117 {
118 PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);
119
120 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
121 i -= 9 + (5 * rows) - 5;
122
123 rows = header = 0;
124 }
125 }
126
127 /* Step 3: Got our 40 bits! confirm column parity */
128 else if (rows == 10)
129 {
130 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
131 if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] &&
132 BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] &&
133 BitStream[i+4] == 0)
134 {
135 /* Sweet! */
136 PrintAndLog("EM410x Tag ID: %s", id);
137
138 /* Stop any loops */
139 return 1;
140 }
141
142 /* Crap! Incorrect parity or no stop bit, start all over */
143 else
144 {
145 rows = header = 0;
146
147 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
148 i -= 59;
149 }
150 }
151
152 /* Step 1: get our header */
153 else if (header < 9)
154 {
155 /* Need 9 consecutive 1's */
156 if (BitStream[i] == 1)
157 header++;
158
159 /* We don't have a header, not enough consecutive 1 bits */
160 else
161 header = 0;
162 }
163 }
164
165 /* if we've already retested after flipping bits, return */
166 if (retested++)
167 return 0;
168
169 /* if this didn't work, try flipping bits */
170 for (i = 0; i < bit2idx; i++)
171 BitStream[i] ^= 1;
172
173 goto retest;
174}
175
176/* emulate an EM410X tag
177 * Format:
178 * 1111 1111 1 <-- standard non-repeatable header
179 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
180 * ....
181 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
182 * 0 <-- stop bit, end of tag
183 */
184int CmdEM410xSim(const char *Cmd)
185{
186 int i, n, j, h, binary[4], parity[4];
187
188 /* clock is 64 in EM410x tags */
189 int clock = 64;
190
191 /* clear our graph */
192 ClearGraph(0);
193
194 /* write it out a few times */
195 for (h = 0; h < 4; h++)
196 {
197 /* write 9 start bits */
198 for (i = 0; i < 9; i++)
199 AppendGraph(0, clock, 1);
200
201 /* for each hex char */
202 parity[0] = parity[1] = parity[2] = parity[3] = 0;
203 for (i = 0; i < 10; i++)
204 {
205 /* read each hex char */
206 sscanf(&Cmd[i], "%1x", &n);
207 for (j = 3; j >= 0; j--, n/= 2)
208 binary[j] = n % 2;
209
210 /* append each bit */
211 AppendGraph(0, clock, binary[0]);
212 AppendGraph(0, clock, binary[1]);
213 AppendGraph(0, clock, binary[2]);
214 AppendGraph(0, clock, binary[3]);
215
216 /* append parity bit */
217 AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
218
219 /* keep track of column parity */
220 parity[0] ^= binary[0];
221 parity[1] ^= binary[1];
222 parity[2] ^= binary[2];
223 parity[3] ^= binary[3];
224 }
225
226 /* parity columns */
227 AppendGraph(0, clock, parity[0]);
228 AppendGraph(0, clock, parity[1]);
229 AppendGraph(0, clock, parity[2]);
230 AppendGraph(0, clock, parity[3]);
231
232 /* stop bit */
233 AppendGraph(0, clock, 0);
234 }
235
236 /* modulate that biatch */
237 CmdManchesterMod("");
238
239 /* booyah! */
240 RepaintGraphWindow();
241
242 CmdLFSim("");
243 return 0;
244}
245
246/* Function is equivalent of loread + losamples + em410xread
247 * looped until an EM410x tag is detected */
248int CmdEM410xWatch(const char *Cmd)
249{
7fe9b0b7 250 do
251 {
ab2fd3d6 252 CmdLFRead("");
253 CmdSamples("2000");
254 } while ( ! CmdEM410xRead(""));
7fe9b0b7 255 return 0;
256}
257
258/* Read the transmitted data of an EM4x50 tag
259 * Format:
260 *
261 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
262 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
263 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
264 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
265 * CCCCCCCC <- column parity bits
266 * 0 <- stop bit
267 * LW <- Listen Window
268 *
269 * This pattern repeats for every block of data being transmitted.
270 * Transmission starts with two Listen Windows (LW - a modulated
271 * pattern of 320 cycles each (32/32/128/64/64)).
272 *
273 * Note that this data may or may not be the UID. It is whatever data
274 * is stored in the blocks defined in the control word First and Last
275 * Word Read values. UID is stored in block 32.
276 */
277int CmdEM4x50Read(const char *Cmd)
278{
31b6e9af 279 int i, j, startblock, skip, block, start, end, low, high;
7fe9b0b7 280 bool complete= false;
281 int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
282 char tmp[6];
283
284 high= low= 0;
913d23c6 285 memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
7fe9b0b7 286
287 /* first get high and low values */
288 for (i = 0; i < GraphTraceLen; i++)
289 {
290 if (GraphBuffer[i] > high)
291 high = GraphBuffer[i];
292 else if (GraphBuffer[i] < low)
293 low = GraphBuffer[i];
294 }
295
296 /* populate a buffer with pulse lengths */
297 i= 0;
298 j= 0;
299 while (i < GraphTraceLen)
300 {
301 // measure from low to low
302 while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
303 ++i;
304 start= i;
305 while ((GraphBuffer[i] < high) && (i<GraphTraceLen))
306 ++i;
307 while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
308 ++i;
309 if (j>(MAX_GRAPH_TRACE_LEN/64)) {
310 break;
311 }
312 tmpbuff[j++]= i - start;
313 }
314
315 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
316 start= -1;
317 skip= 0;
318 for (i= 0; i < j - 4 ; ++i)
319 {
320 skip += tmpbuff[i];
321 if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
322 if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
323 if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
324 if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
325 {
326 start= i + 3;
327 break;
328 }
329 }
330 startblock= i + 3;
331
332 /* skip over the remainder of the LW */
333 skip += tmpbuff[i+1]+tmpbuff[i+2];
334 while (skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low)
335 ++skip;
336 skip += 8;
337
338 /* now do it again to find the end */
339 end= start;
340 for (i += 3; i < j - 4 ; ++i)
341 {
342 end += tmpbuff[i];
343 if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
344 if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
345 if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
346 if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
347 {
348 complete= true;
349 break;
350 }
351 }
352
353 if (start >= 0)
354 PrintAndLog("Found data at sample: %i",skip);
355 else
356 {
357 PrintAndLog("No data found!");
358 PrintAndLog("Try again with more samples.");
359 return 0;
360 }
361
362 if (!complete)
363 {
364 PrintAndLog("*** Warning!");
365 PrintAndLog("Partial data - no end found!");
366 PrintAndLog("Try again with more samples.");
367 }
368
369 /* get rid of leading crap */
370 sprintf(tmp,"%i",skip);
371 CmdLtrim(tmp);
372
373 /* now work through remaining buffer printing out data blocks */
374 block= 0;
375 i= startblock;
376 while (block < 6)
377 {
378 PrintAndLog("Block %i:", block);
379 // mandemod routine needs to be split so we can call it for data
380 // just print for now for debugging
381 CmdManchesterDemod("i 64");
382 skip= 0;
383 /* look for LW before start of next block */
384 for ( ; i < j - 4 ; ++i)
385 {
386 skip += tmpbuff[i];
387 if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
388 if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
389 break;
390 }
391 while (GraphBuffer[skip] > low)
392 ++skip;
393 skip += 8;
394 sprintf(tmp,"%i",skip);
395 CmdLtrim(tmp);
396 start += skip;
397 block++;
398 }
399 return 0;
400}
401
2d4eae76 402int CmdEM410xWrite(const char *Cmd)
403{
404 uint64_t id = 0;
405 unsigned int card;
406
ec564290 407 sscanf(Cmd, "%" PRIx64 " %d", &id, &card);
2d4eae76 408
409 if (id >= 0x10000000000) {
410 PrintAndLog("Error! Given EM410x ID is longer than 40 bits.\n");
411 return 0;
412 }
413
414 if (card > 1) {
415 PrintAndLog("Error! Bad card type selected.\n");
416 return 0;
417 }
418
ec564290 419 PrintAndLog("Writing %s tag with UID 0x%010" PRIx64, card ? "T55x7":"T5555", id);
2d4eae76 420 UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}};
421 SendCommand(&c);
422
423 return 0;
424}
425
426static command_t CommandTable[] =
7fe9b0b7 427{
428 {"help", CmdHelp, 1, "This help"},
429 {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
430 {"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
431 {"em410xwatch", CmdEM410xWatch, 0, "Watches for EM410x tags"},
2d4eae76 432 {"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> -- Write EM410x UID to T5555(Q5) or T55x7 tag"},
7fe9b0b7 433 {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
434 {NULL, NULL, 0, NULL}
435};
436
437int CmdLFEM4X(const char *Cmd)
438{
439 CmdsParse(CommandTable, Cmd);
440 return 0;
441}
442
443int CmdHelp(const char *Cmd)
444{
445 CmdsHelp(CommandTable);
446 return 0;
447}
Impressum, Datenschutz