]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdlfem4x.c
52d407ab49271ae85221019e801e5fb4c596361b
10 static int CmdHelp(const char *Cmd
);
12 /* Read the ID of an EM410x tag.
14 * 1111 1111 1 <-- standard non-repeatable header
15 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
17 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
18 * 0 <-- stop bit, end of tag
20 int CmdEM410xRead(const char *Cmd
)
22 int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
;
26 int BitStream
[MAX_GRAPH_TRACE_LEN
];
29 /* Detect high and lows and clock */
30 for (i
= 0; i
< GraphTraceLen
; i
++)
32 if (GraphBuffer
[i
] > high
)
33 high
= GraphBuffer
[i
];
34 else if (GraphBuffer
[i
] < low
)
39 clock
= GetClock(Cmd
, high
, 0);
41 /* parity for our 4 columns */
42 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
45 /* manchester demodulate */
47 for (i
= 0; i
< (int)(GraphTraceLen
/ clock
); i
++)
53 /* Find out if we hit both high and low peaks */
54 for (j
= 0; j
< clock
; j
++)
56 if (GraphBuffer
[(i
* clock
) + j
] == high
)
58 else if (GraphBuffer
[(i
* clock
) + j
] == low
)
61 /* it doesn't count if it's the first part of our read
62 because it's really just trailing from the last sequence */
63 if (first
&& (hithigh
|| hitlow
))
68 if (hithigh
&& hitlow
)
72 /* If we didn't hit both high and low peaks, we had a bit transition */
73 if (!hithigh
|| !hitlow
)
76 BitStream
[bit2idx
++] = bit
;
80 /* We go till 5 before the graph ends because we'll get that far below */
81 for (i
= 1; i
< bit2idx
- 5; i
++)
83 /* Step 2: We have our header but need our tag ID */
84 if (header
== 9 && rows
< 10)
86 /* Confirm parity is correct */
87 if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4])
89 /* Read another byte! */
90 sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3]));
93 /* Keep parity info */
94 parity
[0] ^= BitStream
[i
];
95 parity
[1] ^= BitStream
[i
+1];
96 parity
[2] ^= BitStream
[i
+2];
97 parity
[3] ^= BitStream
[i
+3];
99 /* Move 4 bits ahead */
103 /* Damn, something wrong! reset */
106 PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows
+ 1, i
);
108 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
109 i
-= 9 + (5 * rows
) - 5;
115 /* Step 3: Got our 40 bits! confirm column parity */
118 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
119 if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] &&
120 BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] &&
124 PrintAndLog("EM410x Tag ID: %s", id
);
130 /* Crap! Incorrect parity or no stop bit, start all over */
135 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
140 /* Step 1: get our header */
143 /* Need 9 consecutive 1's */
144 if (BitStream
[i
] == 1)
147 /* We don't have a header, not enough consecutive 1 bits */
153 /* if we've already retested after flipping bits, return */
157 /* if this didn't work, try flipping bits */
158 for (i
= 0; i
< bit2idx
; i
++)
164 /* emulate an EM410X tag
166 * 1111 1111 1 <-- standard non-repeatable header
167 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
169 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
170 * 0 <-- stop bit, end of tag
172 int CmdEM410xSim(const char *Cmd
)
174 int i
, n
, j
, h
, binary
[4], parity
[4];
176 /* clock is 64 in EM410x tags */
179 /* clear our graph */
182 /* write it out a few times */
183 for (h
= 0; h
< 4; h
++)
185 /* write 9 start bits */
186 for (i
= 0; i
< 9; i
++)
187 AppendGraph(0, clock
, 1);
189 /* for each hex char */
190 parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0;
191 for (i
= 0; i
< 10; i
++)
193 /* read each hex char */
194 sscanf(&Cmd
[i
], "%1x", &n
);
195 for (j
= 3; j
>= 0; j
--, n
/= 2)
198 /* append each bit */
199 AppendGraph(0, clock
, binary
[0]);
200 AppendGraph(0, clock
, binary
[1]);
201 AppendGraph(0, clock
, binary
[2]);
202 AppendGraph(0, clock
, binary
[3]);
204 /* append parity bit */
205 AppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]);
207 /* keep track of column parity */
208 parity
[0] ^= binary
[0];
209 parity
[1] ^= binary
[1];
210 parity
[2] ^= binary
[2];
211 parity
[3] ^= binary
[3];
215 AppendGraph(0, clock
, parity
[0]);
216 AppendGraph(0, clock
, parity
[1]);
217 AppendGraph(0, clock
, parity
[2]);
218 AppendGraph(0, clock
, parity
[3]);
221 AppendGraph(0, clock
, 0);
224 /* modulate that biatch */
225 CmdManchesterMod("");
228 RepaintGraphWindow();
234 /* Function is equivalent of loread + losamples + em410xread
235 * looped until an EM410x tag is detected */
236 int CmdEM410xWatch(const char *Cmd
)
246 stop
= CmdEM410xRead(zero
);
251 /* Read the transmitted data of an EM4x50 tag
254 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
255 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
256 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
257 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
258 * CCCCCCCC <- column parity bits
260 * LW <- Listen Window
262 * This pattern repeats for every block of data being transmitted.
263 * Transmission starts with two Listen Windows (LW - a modulated
264 * pattern of 320 cycles each (32/32/128/64/64)).
266 * Note that this data may or may not be the UID. It is whatever data
267 * is stored in the blocks defined in the control word First and Last
268 * Word Read values. UID is stored in block 32.
270 int CmdEM4x50Read(const char *Cmd
)
272 int i
, j
, startblock
, clock
, skip
, block
, start
, end
, low
, high
;
273 bool complete
= false;
274 int tmpbuff
[MAX_GRAPH_TRACE_LEN
/ 64];
280 /* first get high and low values */
281 for (i
= 0; i
< GraphTraceLen
; i
++)
283 if (GraphBuffer
[i
] > high
)
284 high
= GraphBuffer
[i
];
285 else if (GraphBuffer
[i
] < low
)
286 low
= GraphBuffer
[i
];
289 /* populate a buffer with pulse lengths */
292 while (i
< GraphTraceLen
)
294 // measure from low to low
295 while ((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
298 while ((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
))
300 while ((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
))
302 if (j
>(MAX_GRAPH_TRACE_LEN
/64)) {
305 tmpbuff
[j
++]= i
- start
;
308 /* look for data start - should be 2 pairs of LW (pulses of 192,128) */
311 for (i
= 0; i
< j
- 4 ; ++i
)
314 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
315 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
316 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
317 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
325 /* skip over the remainder of the LW */
326 skip
+= tmpbuff
[i
+1]+tmpbuff
[i
+2];
327 while (skip
< MAX_GRAPH_TRACE_LEN
&& GraphBuffer
[skip
] > low
)
331 /* now do it again to find the end */
333 for (i
+= 3; i
< j
- 4 ; ++i
)
336 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
337 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
338 if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194)
339 if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130)
347 PrintAndLog("Found data at sample: %i",skip
);
350 PrintAndLog("No data found!");
351 PrintAndLog("Try again with more samples.");
357 PrintAndLog("*** Warning!");
358 PrintAndLog("Partial data - no end found!");
359 PrintAndLog("Try again with more samples.");
362 /* get rid of leading crap */
363 sprintf(tmp
,"%i",skip
);
366 /* now work through remaining buffer printing out data blocks */
371 PrintAndLog("Block %i:", block
);
372 // mandemod routine needs to be split so we can call it for data
373 // just print for now for debugging
374 CmdManchesterDemod("i 64");
376 /* look for LW before start of next block */
377 for ( ; i
< j
- 4 ; ++i
)
380 if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194)
381 if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130)
384 while (GraphBuffer
[skip
] > low
)
387 sprintf(tmp
,"%i",skip
);
395 static command_t CommandTable
[] =
397 {"help", CmdHelp
, 1, "This help"},
398 {"em410xread", CmdEM410xRead
, 1, "[clock rate] -- Extract ID from EM410x tag"},
399 {"em410xsim", CmdEM410xSim
, 0, "<UID> -- Simulate EM410x tag"},
400 {"em410xwatch", CmdEM410xWatch
, 0, "Watches for EM410x tags"},
401 {"em4x50read", CmdEM4x50Read
, 1, "Extract data from EM4x50 tag"},
402 {NULL
, NULL
, 0, NULL
}
405 int CmdLFEM4X(const char *Cmd
)
407 CmdsParse(CommandTable
, Cmd
);
411 int CmdHelp(const char *Cmd
)
413 CmdsHelp(CommandTable
);