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