]> cvs.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhf14b.c
add: a .gitignore to be able to add the folder client/obj/reveng.
[proxmark3-svn] / client / cmdhf14b.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// High frequency ISO14443B commands
9//-----------------------------------------------------------------------------
10
7fe9b0b7 11#include <stdio.h>
12#include <stdlib.h>
13#include <stdbool.h>
14#include <string.h>
15#include <stdint.h>
16#include "iso14443crc.h"
902cb3c0 17#include "proxmark3.h"
7fe9b0b7 18#include "data.h"
19#include "graph.h"
3fe4ff4f 20#include "util.h"
7fe9b0b7 21#include "ui.h"
22#include "cmdparser.h"
23#include "cmdhf14b.h"
7cf3ef20 24#include "cmdmain.h"
7fe9b0b7 25
26static int CmdHelp(const char *Cmd);
27
28int CmdHF14BDemod(const char *Cmd)
29{
30 int i, j, iold;
31 int isum, qsum;
32 int outOfWeakAt;
33 bool negateI, negateQ;
34
35 uint8_t data[256];
36 int dataLen = 0;
37
38 // As received, the samples are pairs, correlations against I and Q
39 // square waves. So estimate angle of initial carrier (or just
40 // quadrant, actually), and then do the demod.
41
42 // First, estimate where the tag starts modulating.
43 for (i = 0; i < GraphTraceLen; i += 2) {
44 if (abs(GraphBuffer[i]) + abs(GraphBuffer[i + 1]) > 40) {
45 break;
46 }
47 }
48 if (i >= GraphTraceLen) {
49 PrintAndLog("too weak to sync");
50 return 0;
51 }
52 PrintAndLog("out of weak at %d", i);
53 outOfWeakAt = i;
54
55 // Now, estimate the phase in the initial modulation of the tag
56 isum = 0;
57 qsum = 0;
58 for (; i < (outOfWeakAt + 16); i += 2) {
59 isum += GraphBuffer[i + 0];
60 qsum += GraphBuffer[i + 1];
61 }
62 negateI = (isum < 0);
63 negateQ = (qsum < 0);
64
65 // Turn the correlation pairs into soft decisions on the bit.
66 j = 0;
67 for (i = 0; i < GraphTraceLen / 2; i++) {
68 int si = GraphBuffer[j];
69 int sq = GraphBuffer[j + 1];
70 if (negateI) si = -si;
71 if (negateQ) sq = -sq;
72 GraphBuffer[i] = si + sq;
73 j += 2;
74 }
75 GraphTraceLen = i;
76
77 i = outOfWeakAt / 2;
78 while (GraphBuffer[i] > 0 && i < GraphTraceLen)
79 i++;
80 if (i >= GraphTraceLen) goto demodError;
81
82 iold = i;
83 while (GraphBuffer[i] < 0 && i < GraphTraceLen)
84 i++;
85 if (i >= GraphTraceLen) goto demodError;
86 if ((i - iold) > 23) goto demodError;
87
88 PrintAndLog("make it to demod loop");
89
90 for (;;) {
91 iold = i;
92 while (GraphBuffer[i] >= 0 && i < GraphTraceLen)
93 i++;
94 if (i >= GraphTraceLen) goto demodError;
95 if ((i - iold) > 6) goto demodError;
96
97 uint16_t shiftReg = 0;
98 if (i + 20 >= GraphTraceLen) goto demodError;
99
100 for (j = 0; j < 10; j++) {
101 int soft = GraphBuffer[i] + GraphBuffer[i + 1];
102
103 if (abs(soft) < (abs(isum) + abs(qsum)) / 20) {
104 PrintAndLog("weak bit");
105 }
106
107 shiftReg >>= 1;
108 if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
109 shiftReg |= 0x200;
110 }
111
112 i+= 2;
113 }
114
115 if ((shiftReg & 0x200) && !(shiftReg & 0x001))
116 {
117 // valid data byte, start and stop bits okay
118 PrintAndLog(" %02x", (shiftReg >> 1) & 0xff);
119 data[dataLen++] = (shiftReg >> 1) & 0xff;
120 if (dataLen >= sizeof(data)) {
121 return 0;
122 }
123 } else if (shiftReg == 0x000) {
124 // this is EOF
125 break;
126 } else {
127 goto demodError;
128 }
129 }
130
131 uint8_t first, second;
132 ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
133 PrintAndLog("CRC: %02x %02x (%s)\n", first, second,
134 (first == data[dataLen-2] && second == data[dataLen-1]) ?
135 "ok" : "****FAIL****");
136
137 RepaintGraphWindow();
138 return 0;
139
140demodError:
141 PrintAndLog("demod error");
142 RepaintGraphWindow();
143 return 0;
144}
145
146int CmdHF14BList(const char *Cmd)
147{
388c92bd 148 PrintAndLog("Deprecated command, use 'hf list 14b' instead");
7fe9b0b7 149
388c92bd 150 return 0;
7fe9b0b7 151}
7fe9b0b7 152
153int CmdHF14Sim(const char *Cmd)
154{
155 UsbCommand c={CMD_SIMULATE_TAG_ISO_14443};
156 SendCommand(&c);
157 return 0;
158}
159
160int CmdHFSimlisten(const char *Cmd)
161{
162 UsbCommand c = {CMD_SIMULATE_TAG_HF_LISTEN};
163 SendCommand(&c);
164 return 0;
165}
166
167int CmdHF14BSnoop(const char *Cmd)
168{
169 UsbCommand c = {CMD_SNOOP_ISO_14443};
170 SendCommand(&c);
171 return 0;
172}
173
174/* New command to read the contents of a SRI512 tag
175 * SRI512 tags are ISO14443-B modulated memory tags,
176 * this command just dumps the contents of the memory
177 */
178int CmdSri512Read(const char *Cmd)
179{
180 UsbCommand c = {CMD_READ_SRI512_TAG, {strtol(Cmd, NULL, 0), 0, 0}};
181 SendCommand(&c);
182 return 0;
183}
184
185/* New command to read the contents of a SRIX4K tag
186 * SRIX4K tags are ISO14443-B modulated memory tags,
187 * this command just dumps the contents of the memory/
188 */
189int CmdSrix4kRead(const char *Cmd)
190{
191 UsbCommand c = {CMD_READ_SRIX4K_TAG, {strtol(Cmd, NULL, 0), 0, 0}};
192 SendCommand(&c);
193 return 0;
194}
195
1299c798 196int HF14BCmdRaw(bool reply, bool *crc, bool power, uint8_t *data, uint8_t *datalen, bool verbose){
7cf3ef20 197 UsbCommand resp;
7cf3ef20 198 UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; // len,recv?
1299c798 199 if(*crc)
200 {
201 uint8_t first, second;
202 ComputeCrc14443(CRC_14443_B, data, *datalen, &first, &second);
203 data[*datalen] = first;
204 data[*datalen + 1] = second;
205 *datalen += 2;
206 }
207
208 c.arg[0] = *datalen;
209 c.arg[1] = reply;
210 c.arg[2] = power;
211 memcpy(c.d.asBytes,data,*datalen);
212 SendCommand(&c);
213
214 if (!reply) return 1;
215
216 if (!WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
217 if (verbose) PrintAndLog("timeout while waiting for reply.");
218 return 0;
219 }
220 *datalen = resp.arg[0];
221 if (verbose) PrintAndLog("received %i octets", *datalen);
222 if(!*datalen)
223 return 0;
224
225 memcpy(data, resp.d.asBytes, *datalen);
226 if (verbose) PrintAndLog("%s", sprint_hex(data, *datalen));
227
228 uint8_t first, second;
229 ComputeCrc14443(CRC_14443_B, data, *datalen-2, &first, &second);
230 if(data[*datalen-2] == first && data[*datalen-1] == second) {
231 if (verbose) PrintAndLog("CRC OK");
232 *crc = true;
233 } else {
234 if (verbose) PrintAndLog("CRC failed");
235 *crc = false;
236 }
237 return 1;
238}
239
240int CmdHF14BCmdRaw (const char *Cmd) {
241 bool reply = true;
242 bool crc = false;
243 bool power = false;
7cf3ef20 244 char buf[5]="";
5ee70129 245 uint8_t data[100] = {0x00};
1299c798 246 uint8_t datalen = 0;
247 unsigned int temp;
248 int i = 0;
249 if (strlen(Cmd)<3) {
7cf3ef20 250 PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>");
251 PrintAndLog(" -r do not read response");
252 PrintAndLog(" -c calculate and append CRC");
253 PrintAndLog(" -p leave the field on after receive");
254 return 0;
255 }
256
257 // strip
1299c798 258 while (*Cmd==' ' || *Cmd=='\t') Cmd++;
7cf3ef20 259
1299c798 260 while (Cmd[i]!='\0') {
261 if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; }
262 if (Cmd[i]=='-') {
263 switch (Cmd[i+1]) {
7cf3ef20 264 case 'r':
265 case 'R':
1299c798 266 reply = false;
7cf3ef20 267 break;
268 case 'c':
269 case 'C':
1299c798 270 crc = true;
7cf3ef20 271 break;
272 case 'p':
273 case 'P':
1299c798 274 power = true;
7cf3ef20 275 break;
276 default:
277 PrintAndLog("Invalid option");
278 return 0;
279 }
280 i+=2;
281 continue;
282 }
1299c798 283 if ((Cmd[i]>='0' && Cmd[i]<='9') ||
284 (Cmd[i]>='a' && Cmd[i]<='f') ||
285 (Cmd[i]>='A' && Cmd[i]<='F') ) {
7cf3ef20 286 buf[strlen(buf)+1]=0;
1299c798 287 buf[strlen(buf)]=Cmd[i];
7cf3ef20 288 i++;
289
290 if (strlen(buf)>=2) {
291 sscanf(buf,"%x",&temp);
1299c798 292 data[datalen++]=(uint8_t)(temp & 0xff);
7cf3ef20 293 *buf=0;
294 }
295 continue;
296 }
297 PrintAndLog("Invalid char on input");
5ee70129 298 return 1;
7cf3ef20 299 }
06b82e6a 300 if (datalen == 0)
301 {
302 PrintAndLog("Missing data input");
303 return 0;
304 }
1299c798 305
306 return HF14BCmdRaw(reply, &crc, power, data, &datalen, true);
307}
308
309
310void print_atqb_resp(uint8_t *data){
311 PrintAndLog (" UID: %s", sprint_hex(data+1,4));
312 PrintAndLog (" App Data: %s", sprint_hex(data+5,4));
313 PrintAndLog (" Protocol: %s", sprint_hex(data+9,3));
314 uint8_t BitRate = data[9];
315 if (!BitRate)
316 PrintAndLog (" Bit Rate: 106 kbit/s only PICC <-> PCD");
317 if (BitRate & 0x10)
318 PrintAndLog (" Bit Rate: 212 kbit/s PICC -> PCD supported");
319 if (BitRate & 0x20)
320 PrintAndLog (" Bit Rate: 424 kbit/s PICC -> PCD supported");
321 if (BitRate & 0x40)
322 PrintAndLog (" Bit Rate: 847 kbit/s PICC -> PCD supported");
323 if (BitRate & 0x01)
324 PrintAndLog (" Bit Rate: 212 kbit/s PICC <- PCD supported");
325 if (BitRate & 0x02)
326 PrintAndLog (" Bit Rate: 424 kbit/s PICC <- PCD supported");
327 if (BitRate & 0x04)
328 PrintAndLog (" Bit Rate: 847 kbit/s PICC <- PCD supported");
329 if (BitRate & 0x80)
330 PrintAndLog (" Same bit rate <-> required");
331
332 uint16_t maxFrame = data[10]>>4;
333 if (maxFrame < 5)
334 maxFrame = 8*maxFrame + 16;
335 else if (maxFrame == 5)
336 maxFrame = 64;
337 else if (maxFrame == 6)
338 maxFrame = 96;
339 else if (maxFrame == 7)
340 maxFrame = 128;
341 else if (maxFrame == 8)
342 maxFrame = 256;
343 else
344 maxFrame = 257;
345
346 PrintAndLog ("Max Frame Size: %d%s",maxFrame, (maxFrame == 257) ? "+ RFU" : "");
347
348 uint8_t protocolT = data[10] & 0xF;
349 PrintAndLog (" Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " );
350 PrintAndLog ("Frame Wait Int: %d", data[11]>>4);
351 PrintAndLog (" App Data Code: Application is %s",(data[11]&4) ? "Standard" : "Proprietary");
352 PrintAndLog (" Frame Options: NAD is %ssupported",(data[11]&2) ? "" : "not ");
353 PrintAndLog (" Frame Options: CID is %ssupported",(data[11]&1) ? "" : "not ");
354
355 return;
356}
357
358int HF14BStdRead(uint8_t *data, uint8_t *datalen){
359 bool crc = true;
360 *datalen = 3;
361 //std read cmd
362 data[0] = 0x05;
363 data[1] = 0x00;
364 data[2] = 0x08;
365 //data[3] = 0x39;
366 //data[4] = 0x73;
367
368 int ans = HF14BCmdRaw(true, &crc, false, data, datalen, false);
369
370 if (!ans) return 0;
371 if (data[0] != 0x50 || *datalen < 14 || !crc) return 0;
372
373 PrintAndLog ("\n14443-3b tag found:");
374 print_atqb_resp(data);
375
376 return 1;
377}
378
379int HF14B_ST_Read(uint8_t *data, uint8_t *datalen){
380 bool crc = true;
381 *datalen = 2;
382 //std read cmd
383 data[0] = 0x06;
384 data[1] = 0x00;
385 int ans = HF14BCmdRaw(true, &crc, true, data, datalen, false);
386
387 if (!ans) return 0;
388 if (*datalen < 3 || !crc) return 0;
389
390 uint8_t chipID = data[0];
391 data[0] = 0x0E;
392 data[1] = chipID;
393 *datalen = 2;
394 ans = HF14BCmdRaw(true, &crc, true, data, datalen, false);
395
396 if (!ans) return 0;
397 if (*datalen < 3 || !crc) return 0;
398
399 data[0] = 0x0B;
400 *datalen = 1;
401 ans = HF14BCmdRaw(true, &crc, false, data, datalen, false);
402
403 if (!ans) return 0;
404 if (*datalen < 10 || !crc) return 0;
405
406 PrintAndLog ("14443-3b ST tag found");
407 //uid = first 8 bytes in data
408 PrintAndLog ("UID: %s", sprint_hex(data,8));
409 return 1;
410
411}
412
413int CmdHF14BReader(const char *Cmd)
7cf3ef20 414 {
1299c798 415 uint8_t data[100];
416 uint8_t datalen = 5;
417
418 // try std 14b (atqb)
419 int ans = HF14BStdRead(data, &datalen);
420 if (ans) return 1;
421
422 // try st 14b
423 ans = HF14B_ST_Read(data, &datalen);
424 if (ans) return 1;
425
426 //UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(Cmd, NULL, 0), 0, 0}};
427 //SendCommand(&c);
7cf3ef20 428 return 0;
429}
430
3fe4ff4f 431int CmdHF14BWrite( const char *Cmd){
432
433/*
434 * For SRIX4K blocks 00 - 7F
435 * hf 14b raw -c -p 09 $srix4kwblock $srix4kwdata
436 *
437 * For SR512 blocks 00 - 0F
438 * hf 14b raw -c -p 09 $sr512wblock $sr512wdata
439 *
440 * Special block FF = otp_lock_reg block.
441 * Data len 4 bytes-
442 */
443 char cmdp = param_getchar(Cmd, 0);
444 uint8_t blockno = -1;
445 uint8_t data[4] = {0x00};
446 bool isSrix4k = true;
447 char str[20];
448
b5be31f9 449 if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
3fe4ff4f 450 PrintAndLog("Usage: hf 14b write <1|2> <BLOCK> <DATA>");
b5be31f9 451 PrintAndLog(" [1 = SRIX4K]");
452 PrintAndLog(" [2 = SRI512]");
453 PrintAndLog(" [BLOCK number depends on tag, special block == FF]");
454 PrintAndLog(" sample: hf 14b write 1 7F 11223344");
455 PrintAndLog(" : hf 14b write 1 FF 11223344");
456 PrintAndLog(" : hf 14b write 2 15 11223344");
457 PrintAndLog(" : hf 14b write 2 FF 11223344");
3fe4ff4f 458 return 0;
459 }
460
b5be31f9 461 if ( cmdp == '2' )
3fe4ff4f 462 isSrix4k = false;
463
b5be31f9 464 //blockno = param_get8(Cmd, 1);
465
466 if ( param_gethex(Cmd,1, &blockno, 2) ) {
467 PrintAndLog("Block number must include 2 HEX symbols");
468 return 0;
469 }
3fe4ff4f 470
471 if ( isSrix4k ){
472 if ( blockno > 0x7f && blockno != 0xff ){
473 PrintAndLog("Block number out of range");
474 return 0;
475 }
476 } else {
477 if ( blockno > 0x0f && blockno != 0xff ){
478 PrintAndLog("Block number out of range");
479 return 0;
480 }
481 }
482
483 if (param_gethex(Cmd, 2, data, 8)) {
484 PrintAndLog("Data must include 8 HEX symbols");
485 return 0;
486 }
487
488 if ( blockno == 0xff)
b5be31f9 489 PrintAndLog("[%s] Write special block %02X [ %s ]", (isSrix4k)?"SRIX4K":"SRI512" , blockno, sprint_hex(data,4) );
3fe4ff4f 490 else
b5be31f9 491 PrintAndLog("[%s] Write block %02X [ %s ]", (isSrix4k)?"SRIX4K":"SRI512", blockno, sprint_hex(data,4) );
3fe4ff4f 492
fe5b3a44 493 sprintf(str, "-c 09 %02x %02x%02x%02x%02x", blockno, data[0], data[1], data[2], data[3]);
b5be31f9 494
3fe4ff4f 495 CmdHF14BCmdRaw(str);
496 return 0;
497}
498
7fe9b0b7 499static command_t CommandTable[] =
500{
501 {"help", CmdHelp, 1, "This help"},
502 {"demod", CmdHF14BDemod, 1, "Demodulate ISO14443 Type B from tag"},
388c92bd 503 {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"},
1299c798 504 {"reader", CmdHF14BReader, 0, "Find 14b tag (HF ISO 14443b)"},
7fe9b0b7 505 {"sim", CmdHF14Sim, 0, "Fake ISO 14443 tag"},
506 {"simlisten", CmdHFSimlisten, 0, "Get HF samples as fake tag"},
507 {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443"},
7cf3ef20 508 {"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"},
509 {"srix4kread", CmdSrix4kRead, 0, "Read contents of a SRIX4K tag"},
510 {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"},
3fe4ff4f 511 {"write", CmdHF14BWrite, 0, "Write data to a SRI512 | SRIX4K tag"},
7fe9b0b7 512 {NULL, NULL, 0, NULL}
513};
514
515int CmdHF14B(const char *Cmd)
516{
517 CmdsParse(CommandTable, Cmd);
518 return 0;
519}
520
521int CmdHelp(const char *Cmd)
522{
523 CmdsHelp(CommandTable);
524 return 0;
525}
Impressum, Datenschutz