]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdlfti.c
CHG: Nedap demod, now verifes with first parity.
[proxmark3-svn] / client / cmdlfti.c
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 TI commands
9 //-----------------------------------------------------------------------------
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include "crc16.h"
14 #include "proxmark3.h"
15 #include "data.h"
16 #include "ui.h"
17 #include "graph.h"
18 #include "cmdparser.h"
19 #include "cmdlfti.h"
20 #include "cmdmain.h"
21
22 static int CmdHelp(const char *Cmd);
23
24 int CmdTIDemod(const char *Cmd)
25 {
26 /* MATLAB as follows:
27 f_s = 2000000; % sampling frequency
28 f_l = 123200; % low FSK tone
29 f_h = 134200; % high FSK tone
30
31 T_l = 119e-6; % low bit duration
32 T_h = 130e-6; % high bit duration
33
34 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
35 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
36
37 l = sign(sin(cumsum(l)));
38 h = sign(sin(cumsum(h)));
39 */
40
41 // 2M*16/134.2k = 238
42 static const int LowTone[] = {
43 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
44 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
45 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
46 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
47 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
48 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
49 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
50 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
51 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
52 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
53 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
54 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
55 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
56 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
57 1, 1, 1, 1, 1, 1, 1, 1, -1, -1
58 };
59 // 2M*16/123.2k = 260
60 static const int HighTone[] = {
61 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
62 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
63 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
64 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
65 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
66 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
67 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
68 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
69 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
70 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
71 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
72 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
73 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
74 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
75 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
76 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
77 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
78 1, 1, 1, 1, 1, 1, 1, 1
79 };
80 int lowLen = sizeof(LowTone)/sizeof(int);
81 int highLen = sizeof(HighTone)/sizeof(int);
82 int convLen = (highLen>lowLen)?highLen:lowLen;
83 uint16_t crc;
84 int i, j, TagType;
85 int lowSum = 0, highSum = 0;;
86 int lowTot = 0, highTot = 0;
87
88 for (i = 0; i < GraphTraceLen - convLen; i++) {
89 lowSum = 0;
90 highSum = 0;;
91
92 for (j = 0; j < lowLen; j++) {
93 lowSum += LowTone[j]*GraphBuffer[i+j];
94 }
95 for (j = 0; j < highLen; j++) {
96 highSum += HighTone[j]*GraphBuffer[i+j];
97 }
98 lowSum = abs((100*lowSum) / lowLen);
99 highSum = abs((100*highSum) / highLen);
100 lowSum = (lowSum<0)?-lowSum:lowSum;
101 highSum = (highSum<0)?-highSum:highSum;
102
103 GraphBuffer[i] = (highSum << 16) | lowSum;
104 }
105
106 for (i = 0; i < GraphTraceLen - convLen - 16; i++) {
107 lowTot = 0;
108 highTot = 0;
109 // 16 and 15 are f_s divided by f_l and f_h, rounded
110 for (j = 0; j < 16; j++) {
111 lowTot += (GraphBuffer[i+j] & 0xffff);
112 }
113 for (j = 0; j < 15; j++) {
114 highTot += (GraphBuffer[i+j] >> 16);
115 }
116 GraphBuffer[i] = lowTot - highTot;
117 }
118
119 GraphTraceLen -= (convLen + 16);
120
121 RepaintGraphWindow();
122
123 // TI tag data format is 16 prebits, 8 start bits, 64 data bits,
124 // 16 crc CCITT bits, 8 stop bits, 15 end bits
125
126 // the 16 prebits are always low
127 // the 8 start and stop bits of a tag must match
128 // the start/stop prebits of a ro tag are 01111110
129 // the start/stop prebits of a rw tag are 11111110
130 // the 15 end bits of a ro tag are all low
131 // the 15 end bits of a rw tag match bits 15-1 of the data bits
132
133 // Okay, so now we have unsliced soft decisions;
134 // find bit-sync, and then get some bits.
135 // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags)
136 int max = 0, maxPos = 0;
137 for (i = 0; i < 6000; i++) {
138 int j;
139 int dec = 0;
140 // searching 17 consecutive lows
141 for (j = 0; j < 17*lowLen; j++) {
142 dec -= GraphBuffer[i+j];
143 }
144 // searching 7 consecutive highs
145 for (; j < 17*lowLen + 6*highLen; j++) {
146 dec += GraphBuffer[i+j];
147 }
148 if (dec > max) {
149 max = dec;
150 maxPos = i;
151 }
152 }
153
154 // place a marker in the buffer to visually aid location
155 // of the start of sync
156 GraphBuffer[maxPos] = 800;
157 GraphBuffer[maxPos+1] = -800;
158
159 // advance pointer to start of actual data stream (after 16 pre and 8 start bits)
160 maxPos += 17*lowLen;
161 maxPos += 6*highLen;
162
163 // place a marker in the buffer to visually aid location
164 // of the end of sync
165 GraphBuffer[maxPos] = 800;
166 GraphBuffer[maxPos+1] = -800;
167
168 PrintAndLog("actual data bits start at sample %d", maxPos);
169
170 PrintAndLog("length %d/%d", highLen, lowLen);
171
172 uint8_t bits[1+64+16+8+16];
173 bits[sizeof(bits)-1] = '\0';
174
175 uint32_t shift3 = 0x7e000000, shift2 = 0, shift1 = 0, shift0 = 0;
176
177 for (i = 0; i < arraylen(bits)-1; i++) {
178 int high = 0;
179 int low = 0;
180 int j;
181 for (j = 0; j < lowLen; j++) {
182 low -= GraphBuffer[maxPos+j];
183 }
184 for (j = 0; j < highLen; j++) {
185 high += GraphBuffer[maxPos+j];
186 }
187
188 if (high > low) {
189 bits[i] = '1';
190 maxPos += highLen;
191 // bitstream arrives lsb first so shift right
192 shift3 |= (1<<31);
193 } else {
194 bits[i] = '.';
195 maxPos += lowLen;
196 }
197
198 // 128 bit right shift register
199 shift0 = (shift0>>1) | (shift1 << 31);
200 shift1 = (shift1>>1) | (shift2 << 31);
201 shift2 = (shift2>>1) | (shift3 << 31);
202 shift3 >>= 1;
203
204 // place a marker in the buffer between bits to visually aid location
205 GraphBuffer[maxPos] = 800;
206 GraphBuffer[maxPos+1] = -800;
207 }
208 PrintAndLog("Info: raw tag bits = %s", bits);
209
210 TagType = (shift3>>8)&0xff;
211 if ( TagType != ((shift0>>16)&0xff) ) {
212 PrintAndLog("Error: start and stop bits do not match!");
213 return 0;
214 }
215 else if (TagType == 0x7e) {
216 PrintAndLog("Info: Readonly TI tag detected.");
217 return 0;
218 }
219 else if (TagType == 0xfe) {
220 PrintAndLog("Info: Rewriteable TI tag detected.");
221
222 // put 64 bit data into shift1 and shift0
223 shift0 = (shift0>>24) | (shift1 << 8);
224 shift1 = (shift1>>24) | (shift2 << 8);
225
226 // align 16 bit crc into lower half of shift2
227 shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff;
228
229 // align 16 bit "end bits" or "ident" into lower half of shift3
230 shift3 >>= 16;
231
232 // only 15 bits compare, last bit of ident is not valid
233 if ( (shift3^shift0)&0x7fff ) {
234 PrintAndLog("Error: Ident mismatch!");
235 }
236 // WARNING the order of the bytes in which we calc crc below needs checking
237 // i'm 99% sure the crc algorithm is correct, but it may need to eat the
238 // bytes in reverse or something
239 // calculate CRC
240 crc=0;
241 crc = update_crc16(crc, (shift0)&0xff);
242 crc = update_crc16(crc, (shift0>>8)&0xff);
243 crc = update_crc16(crc, (shift0>>16)&0xff);
244 crc = update_crc16(crc, (shift0>>24)&0xff);
245 crc = update_crc16(crc, (shift1)&0xff);
246 crc = update_crc16(crc, (shift1>>8)&0xff);
247 crc = update_crc16(crc, (shift1>>16)&0xff);
248 crc = update_crc16(crc, (shift1>>24)&0xff);
249
250 //crc = crc16_ccitt(message, sizeof(message);
251
252 char *crcStr = (crc == (shift2&0xffff) ) ? "Passed" : "Failed";
253
254 PrintAndLog("Tag data = %08X%08X [Crc %04X %s]", shift1, shift0, crc, crcStr );
255
256 if (crc != (shift2&0xffff))
257 PrintAndLog("Error: CRC mismatch, calculated %04X, got ^04X", crc, shift2&0xffff);
258
259 }
260 else {
261 PrintAndLog("Unknown tag type.");
262 }
263 return 0;
264 }
265
266 // read a TI tag and return its ID
267 int CmdTIRead(const char *Cmd)
268 {
269 UsbCommand c = {CMD_READ_TI_TYPE};
270 clearCommandBuffer();
271 SendCommand(&c);
272 return 0;
273 }
274
275 // write new data to a r/w TI tag
276 int CmdTIWrite(const char *Cmd)
277 {
278 int res = 0;
279 UsbCommand c = {CMD_WRITE_TI_TYPE};
280 res = sscanf(Cmd, "%012"llx" %012"llx" %012"llx"", &c.arg[0], &c.arg[1], &c.arg[2]);
281
282 if (res == 2) c.arg[2]=0;
283 if (res < 2) {
284 PrintAndLog("Please specify the data as two hex strings, optionally the CRC as a third");
285 return 1;
286 }
287 clearCommandBuffer();
288 SendCommand(&c);
289 return 0;
290 }
291
292 static command_t CommandTable[] = {
293 {"help", CmdHelp, 1, "This help"},
294 {"demod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF tag"},
295 {"read", CmdTIRead, 0, "Read and decode a TI 134 kHz tag"},
296 {"write", CmdTIWrite, 0, "Write new data to a r/w TI 134 kHz tag"},
297 {NULL, NULL, 0, NULL}
298 };
299
300 int CmdLFTI(const char *Cmd){
301 clearCommandBuffer();
302 CmdsParse(CommandTable, Cmd);
303 return 0;
304 }
305
306 int CmdHelp(const char *Cmd){
307 CmdsHelp(CommandTable);
308 return 0;
309 }
Impressum, Datenschutz