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