]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhf15.c
FIXED: lf t55xx fsk now demods but only to binary.
[proxmark3-svn] / client / cmdhf15.c
CommitLineData
a553f267 1//-----------------------------------------------------------------------------
2// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
0546b4aa 3// Modified 2010-2012 by <adrian -at- atrox.at>
65a23af2 4// Modified 2012 by <vsza at vsza.hu>
a553f267 5//
6// This code is licensed to you under the terms of the GNU GPL, version 2 or,
7// at your option, any later version. See the LICENSE.txt file for the text of
8// the license.
9//-----------------------------------------------------------------------------
10// High frequency ISO15693 commands
11//-----------------------------------------------------------------------------
9455b51c 12// There are three basic operation modes, depending on which device (proxmark/pc)
13// the signal processing, (de)modulation, transmission protocol and logic is done.
14// Mode 1:
15// All steps are done on the proxmark, the output of the commands is returned via
16// USB-debug-print commands.
17// Mode 2:
18// The protocol is done on the PC, passing only Iso15693 data frames via USB. This
19// allows direct communication with a tag on command level
20// Mode 3:
21// The proxmark just samples the antenna and passes this "analog" data via USB to
22// the client. Signal Processing & decoding is done on the pc. This is the slowest
23// variant, but offers the possibility to analyze the waveforms directly.
a553f267 24
7fe9b0b7 25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <stdint.h>
28fdb04f 29//#include "proxusb.h"
902cb3c0 30#include "proxmark3.h"
7fe9b0b7 31#include "data.h"
32#include "graph.h"
33#include "ui.h"
34#include "cmdparser.h"
35#include "cmdhf15.h"
f38a1528 36#include "../common/iso15693tools.h"
9455b51c 37#include "cmdmain.h"
38
39#define FrameSOF Iso15693FrameSOF
40#define Logic0 Iso15693Logic0
41#define Logic1 Iso15693Logic1
42#define FrameEOF Iso15693FrameEOF
43
44#define Crc(data,datalen) Iso15693Crc(data,datalen)
45#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
46#define sprintUID(target,uid) Iso15693sprintUID(target,uid)
7bd30f12 47#define TRACE_BUFF_SIZE 12000
7fe9b0b7 48
9455b51c 49// structure and database for uid -> tagtype lookups
50typedef struct {
51 uint64_t uid;
52 int mask; // how many MSB bits used
53 char* desc;
54} productName;
55
56
57const productName uidmapping[] = {
0546b4aa 58 // UID, #significant Bits, "Vendor(+Product)"
c71e7235 59 { 0xE001000000000000LL, 16, "Motorola" },
60 { 0xE002000000000000LL, 16, "ST Microelectronics" },
61 { 0xE003000000000000LL, 16, "Hitachi" },
62 { 0xE004000000000000LL, 16, "Philips" },
63 { 0xE004010000000000LL, 24, "Philips; IC SL2 ICS20" },
64 { 0xE005000000000000LL, 16, "Infineon" },
65 { 0xE005400000000000LL, 24, "Infineon; 56x32bit" },
66 { 0xE006000000000000LL, 16, "Cylinc" },
9455b51c 67 { 0xE007000000000000LL, 16, "Texas Instrument; " },
68 { 0xE007000000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Inlay; 64x32bit" },
69 { 0xE007100000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" },
0546b4aa 70 { 0xE007800000000000LL, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" },
9455b51c 71 { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" },
72 { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" },
c71e7235 73 { 0xE008000000000000LL, 16, "Fujitsu" },
74 { 0xE009000000000000LL, 16, "Matsushita" },
75 { 0xE00A000000000000LL, 16, "NEC" },
76 { 0xE00B000000000000LL, 16, "Oki Electric" },
77 { 0xE00C000000000000LL, 16, "Toshiba" },
78 { 0xE00D000000000000LL, 16, "Mitsubishi" },
79 { 0xE00E000000000000LL, 16, "Samsung" },
80 { 0xE00F000000000000LL, 16, "Hyundai" },
81 { 0xE010000000000000LL, 16, "LG-Semiconductors" },
82 { 0xE012000000000000LL, 16, "HID Corporation" },
9455b51c 83 { 0xE016000000000000LL, 16, "EM-Marin SA (Skidata)" },
0546b4aa 84 { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034? no 'read', just 'readmulti'" },
85 { 0xE0160c0000000000LL, 24, "EM-Marin SA; EM4035?" },
9455b51c 86 { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135; 36x64bit start page 13" },
0546b4aa 87 { 0xE016940000000000LL, 24, "EM-Marin SA (Skidata); 51x64bit" },
9455b51c 88 { 0,0,"no tag-info available" } // must be the last entry
89};
90
91
e4da8ed0 92// fast method to just read the UID of a tag (collission detection not supported)
93// *buf should be large enough to fit the 64bit uid
9455b51c 94// returns 1 if suceeded
95int getUID(uint8_t *buf)
7fe9b0b7 96{
902cb3c0 97 UsbCommand resp;
9455b51c 98 uint8_t *recv;
99 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
100 uint8_t *req=c.d.asBytes;
101 int reqlen=0;
102
103 for (int retry=0;retry<3; retry++) { // don't give up the at the first try
104
105 req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
106 ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
107 req[1]=ISO15_CMD_INVENTORY;
108 req[2]=0; // mask length
109 reqlen=AddCrc(req,3);
110 c.arg[0]=reqlen;
111
112 SendCommand(&c);
113
902cb3c0 114 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
115 recv = resp.d.asBytes;
116 if (resp.arg[0]>=12 && ISO15_CRC_CHECK==Crc(recv,12)) {
9455b51c 117 memcpy(buf,&recv[2],8);
118 return 1;
119 }
120 }
121 } // retry
122 return 0;
123}
124
125
7fe9b0b7 126
9455b51c 127// get a product description based on the UID
128// uid[8] tag uid
129// returns description of the best match
130static char* getTagInfo(uint8_t *uid) {
31b6e9af 131 uint64_t myuid,mask;
9455b51c 132 int i=0, best=-1;
133 memcpy(&myuid,uid,sizeof(uint64_t));
134 while (uidmapping[i].mask>0) {
135 mask=(~0LL) <<(64-uidmapping[i].mask);
136 if ((myuid & mask) == uidmapping[i].uid) {
137 if (best==-1) {
138 best=i;
139 } else {
140 if (uidmapping[i].mask>uidmapping[best].mask) {
141 best=i;
142 }
143 }
144 }
145 i++;
146 }
7fe9b0b7 147
9455b51c 148 if (best>=0) return uidmapping[best].desc;
149
150 return uidmapping[i].desc;
7fe9b0b7 151}
152
9455b51c 153
b4a9d841 154// return a clear-text message to an errorcode
9455b51c 155static char* TagErrorStr(uint8_t error) {
b4a9d841 156 switch (error) {
157 case 0x01: return "The command is not supported";
158 case 0x02: return "The command is not recognised";
159 case 0x03: return "The option is not supported.";
160 case 0x0f: return "Unknown error.";
161 case 0x10: return "The specified block is not available (doesn’t exist).";
162 case 0x11: return "The specified block is already -locked and thus cannot be locked again";
163 case 0x12: return "The specified block is locked and its content cannot be changed.";
164 case 0x13: return "The specified block was not successfully programmed.";
165 case 0x14: return "The specified block was not successfully locked.";
166 default: return "Reserved for Future Use or Custom command error.";
167 }
9455b51c 168}
169
170
171// Mode 3
7fe9b0b7 172int CmdHF15Demod(const char *Cmd)
173{
9455b51c 174 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
175
176 int i, j;
177 int max = 0, maxPos = 0;
178
179 int skip = 4;
180
181 if (GraphTraceLen < 1000) return 0;
182
183 // First, correlate for SOF
184 for (i = 0; i < 100; i++) {
185 int corr = 0;
186 for (j = 0; j < arraylen(FrameSOF); j += skip) {
187 corr += FrameSOF[j] * GraphBuffer[i + (j / skip)];
188 }
189 if (corr > max) {
190 max = corr;
191 maxPos = i;
192 }
193 }
194 PrintAndLog("SOF at %d, correlation %d", maxPos,
195 max / (arraylen(FrameSOF) / skip));
196
197 i = maxPos + arraylen(FrameSOF) / skip;
198 int k = 0;
199 uint8_t outBuf[20];
200 memset(outBuf, 0, sizeof(outBuf));
201 uint8_t mask = 0x01;
202 for (;;) {
203 int corr0 = 0, corr1 = 0, corrEOF = 0;
204 for (j = 0; j < arraylen(Logic0); j += skip) {
205 corr0 += Logic0[j] * GraphBuffer[i + (j / skip)];
206 }
207 for (j = 0; j < arraylen(Logic1); j += skip) {
208 corr1 += Logic1[j] * GraphBuffer[i + (j / skip)];
209 }
210 for (j = 0; j < arraylen(FrameEOF); j += skip) {
211 corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)];
212 }
213 // Even things out by the length of the target waveform.
214 corr0 *= 4;
215 corr1 *= 4;
216
217 if (corrEOF > corr1 && corrEOF > corr0) {
218 PrintAndLog("EOF at %d", i);
219 break;
220 } else if (corr1 > corr0) {
221 i += arraylen(Logic1) / skip;
222 outBuf[k] |= mask;
223 } else {
224 i += arraylen(Logic0) / skip;
225 }
226 mask <<= 1;
227 if (mask == 0) {
228 k++;
229 mask = 0x01;
230 }
231 if ((i + (int)arraylen(FrameEOF)) >= GraphTraceLen) {
232 PrintAndLog("ran off end!");
233 break;
234 }
235 }
236 if (mask != 0x01) {
237 PrintAndLog("error, uneven octet! (discard extra bits!)");
238 PrintAndLog(" mask=%02x", mask);
239 }
240 PrintAndLog("%d octets", k);
241
242 for (i = 0; i < k; i++) {
243 PrintAndLog("# %2d: %02x ", i, outBuf[i]);
244 }
245 PrintAndLog("CRC=%04x", Iso15693Crc(outBuf, k - 2));
246 return 0;
7fe9b0b7 247}
248
9455b51c 249
250
251// * Acquire Samples as Reader (enables carrier, sends inquiry)
7fe9b0b7 252int CmdHF15Read(const char *Cmd)
253{
9455b51c 254 UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693};
255 SendCommand(&c);
7bd30f12 256
257 uint8_t data[TRACE_BUFF_SIZE] = {0x00};
258
259 GetFromBigBuf(data,TRACE_BUFF_SIZE,3560); //3560 -- should be offset..
260 WaitForResponseTimeout(CMD_ACK,NULL, 1500);
261
262 for (int j = 0; j < TRACE_BUFF_SIZE; j++) {
263 GraphBuffer[j] = ((int)data[j]) ;
264 }
265 GraphTraceLen = TRACE_BUFF_SIZE;
266 RepaintGraphWindow();
9455b51c 267 return 0;
268}
269
270// Record Activity without enabeling carrier
271int CmdHF15Record(const char *Cmd)
272{
273 UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693};
274 SendCommand(&c);
7bd30f12 275
276 uint8_t data[TRACE_BUFF_SIZE] = {0x00};
277
278 GetFromBigBuf(data,TRACE_BUFF_SIZE,3560); //3560 -- should be offset..
279 WaitForResponseTimeout(CMD_ACK,NULL, 1500);
280
281 for (int j = 0; j < TRACE_BUFF_SIZE; j++) {
282 GraphBuffer[j] = ((int)data[j]) ;
283 }
284 GraphTraceLen = TRACE_BUFF_SIZE;
285 RepaintGraphWindow();
9455b51c 286 return 0;
7fe9b0b7 287}
288
289int CmdHF15Reader(const char *Cmd)
290{
9455b51c 291 UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
292 SendCommand(&c);
293 return 0;
7fe9b0b7 294}
295
9455b51c 296// Simulation is still not working very good
7fe9b0b7 297int CmdHF15Sim(const char *Cmd)
298{
9455b51c 299 UsbCommand c = {CMD_SIMTAG_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
300 SendCommand(&c);
301 return 0;
7fe9b0b7 302}
303
9455b51c 304// finds the AFI (Application Family Idendifier) of a card, by trying all values
305// (There is no standard way of reading the AFI, allthough some tags support this)
306int CmdHF15Afi(const char *Cmd)
7fe9b0b7 307{
9455b51c 308 UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}};
309 SendCommand(&c);
310 return 0;
311}
312
313// Reads all memory pages
314int CmdHF15DumpMem(const char*Cmd) {
902cb3c0 315 UsbCommand resp;
9455b51c 316 uint8_t uid[8];
317 uint8_t *recv=NULL;
318 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
319 uint8_t *req=c.d.asBytes;
320 int reqlen=0;
321 int blocknum=0;
322 char output[80];
323
324 if (!getUID(uid)) {
325 PrintAndLog("No Tag found.");
326 return 0;
327 }
328
329 PrintAndLog("Reading memory from tag UID=%s",sprintUID(NULL,uid));
330 PrintAndLog("Tag Info: %s",getTagInfo(uid));
331
332 for (int retry=0; retry<5; retry++) {
333
334 req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
335 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
336 req[1]=ISO15_CMD_READ;
337 memcpy(&req[2],uid,8);
338 req[10]=blocknum;
339 reqlen=AddCrc(req,11);
340 c.arg[0]=reqlen;
341
342 SendCommand(&c);
343
902cb3c0 344 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
345 recv = resp.d.asBytes;
346 if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) {
9455b51c 347 if (!(recv[0] & ISO15_RES_ERROR)) {
348 retry=0;
349 *output=0; // reset outputstring
72e930ef 350 sprintf(output, "Block %02x ",blocknum);
902cb3c0 351 for ( int i=1; i<resp.arg[0]-2; i++) { // data in hex
7bb9d33e 352 sprintf(output+strlen(output),"%02X ",recv[i]);
9455b51c 353 }
354 strcat(output," ");
902cb3c0 355 for ( int i=1; i<resp.arg[0]-2; i++) { // data in cleaned ascii
9455b51c 356 sprintf(output+strlen(output),"%c",(recv[i]>31 && recv[i]<127)?recv[i]:'.');
357 }
358 PrintAndLog("%s",output);
359 blocknum++;
360 // PrintAndLog("bn=%i",blocknum);
361 } else {
b4a9d841 362 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
9455b51c 363 return 0;
364 }
365 } // else PrintAndLog("crc");
366 } // else PrintAndLog("r null");
9455b51c 367 } // retry
902cb3c0 368 // TODO: need fix
369// if (resp.arg[0]<3)
370// PrintAndLog("Lost Connection");
371// else if (ISO15_CRC_CHECK!=Crc(resp.d.asBytes,resp.arg[0]))
372// PrintAndLog("CRC Failed");
373// else
374// PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
9455b51c 375 return 0;
376}
377
378
379// "HF 15" interface
380
381static command_t CommandTable15[] =
382{
383 {"help", CmdHF15Help, 1, "This help"},
384 {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"},
385 {"read", CmdHF15Read, 0, "Read HF tag (ISO 15693)"},
386 {"record", CmdHF15Record, 0, "Record Samples (ISO 15693)"}, // atrox
387 {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"},
388 {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"},
389 {"cmd", CmdHF15Cmd, 0, "Send direct commands to ISO15693 tag"},
390 {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"},
391 {"dumpmemory", CmdHF15DumpMem, 0, "Read all memory pages of an ISO15693 tag"},
392 {NULL, NULL, 0, NULL}
7fe9b0b7 393};
394
395int CmdHF15(const char *Cmd)
396{
9455b51c 397 CmdsParse(CommandTable15, Cmd);
398 return 0;
7fe9b0b7 399}
400
9455b51c 401int CmdHF15Help(const char *Cmd)
7fe9b0b7 402{
9455b51c 403 CmdsHelp(CommandTable15);
404 return 0;
7fe9b0b7 405}
9455b51c 406
407
408// "HF 15 Cmd" Interface
409// Allows direct communication with the tag on command level
410
411int CmdHF15CmdInquiry(const char *Cmd)
412{
902cb3c0 413 UsbCommand resp;
9455b51c 414 uint8_t *recv;
415 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
416 uint8_t *req=c.d.asBytes;
417 int reqlen=0;
418
419 req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
420 ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
421 req[1]=ISO15_CMD_INVENTORY;
422 req[2]=0; // mask length
423 reqlen=AddCrc(req,3);
424 c.arg[0]=reqlen;
425
426 SendCommand(&c);
427
902cb3c0 428 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
429 if (resp.arg[0]>=12) {
430 recv = resp.d.asBytes;
9455b51c 431 PrintAndLog("UID=%s",sprintUID(NULL,&recv[2]));
432 PrintAndLog("Tag Info: %s",getTagInfo(&recv[2]));
433 } else {
902cb3c0 434 PrintAndLog("Response to short, just %i bytes. No tag?\n",resp.arg[0]);
9455b51c 435 }
436 } else {
437 PrintAndLog("timeout.");
438 }
439 return 0;
440}
441
442
443// Turns debugging on(1)/off(0)
444int CmdHF15CmdDebug( const char *cmd) {
445 int debug=atoi(cmd);
446 if (strlen(cmd)<1) {
7bd30f12 447 PrintAndLog("Usage: hf 15 cmd debug <0|1>");
448 PrintAndLog(" 0 no debugging");
449 PrintAndLog(" 1 turn debugging on");
9455b51c 450 return 0;
451 }
452
453 UsbCommand c = {CMD_ISO_15693_DEBUG, {debug, 0, 0}};
454 SendCommand(&c);
455 return 0;
456}
457
458
459int CmdHF15CmdRaw (const char *cmd) {
902cb3c0 460 UsbCommand resp;
9455b51c 461 uint8_t *recv;
462 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
463 int reply=1;
464 int fast=1;
465 int crc=0;
466 char buf[5]="";
467 int i=0;
468 uint8_t data[100];
469 unsigned int datalen=0, temp;
fdb67f1c 470 char *hexout;
9455b51c 471
472
473 if (strlen(cmd)<3) {
474 PrintAndLog("Usage: hf 15 cmd raw [-r] [-2] [-c] <0A 0B 0C ... hex>");
475 PrintAndLog(" -r do not read response");
476 PrintAndLog(" -2 use slower '1 out of 256' mode");
477 PrintAndLog(" -c calculate and append CRC");
478 PrintAndLog(" Tip: turn on debugging for verbose output");
479 return 0;
480 }
481
482 // strip
483 while (*cmd==' ' || *cmd=='\t') cmd++;
484
485 while (cmd[i]!='\0') {
486 if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
487 if (cmd[i]=='-') {
488 switch (cmd[i+1]) {
489 case 'r':
490 case 'R':
491 reply=0;
492 break;
493 case '2':
494 fast=0;
495 break;
496 case 'c':
497 case 'C':
498 crc=1;
499 break;
500 default:
501 PrintAndLog("Invalid option");
502 return 0;
503 }
504 i+=2;
505 continue;
506 }
507 if ((cmd[i]>='0' && cmd[i]<='9') ||
508 (cmd[i]>='a' && cmd[i]<='f') ||
509 (cmd[i]>='A' && cmd[i]<='F') ) {
510 buf[strlen(buf)+1]=0;
511 buf[strlen(buf)]=cmd[i];
512 i++;
513
514 if (strlen(buf)>=2) {
515 sscanf(buf,"%x",&temp);
516 data[datalen]=(uint8_t)(temp & 0xff);
517 datalen++;
518 *buf=0;
519 }
520 continue;
521 }
522 PrintAndLog("Invalid char on input");
523 return 0;
524 }
525 if (crc) datalen=AddCrc(data,datalen);
526
527 c.arg[0]=datalen;
528 c.arg[1]=fast;
529 c.arg[2]=reply;
530 memcpy(c.d.asBytes,data,datalen);
531
532 SendCommand(&c);
533
534 if (reply) {
902cb3c0 535 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
536 recv = resp.d.asBytes;
537 PrintAndLog("received %i octets",resp.arg[0]);
538 hexout = (char *)malloc(resp.arg[0] * 3 + 1);
fdb67f1c 539 if (hexout != NULL) {
902cb3c0 540 for (int i = 0; i < resp.arg[0]; i++) { // data in hex
7bb9d33e 541 sprintf(&hexout[i * 3], "%02X ", recv[i]);
fdb67f1c 542 }
543 PrintAndLog("%s", hexout);
544 free(hexout);
545 }
9455b51c 546 } else {
547 PrintAndLog("timeout while waiting for reply.");
548 }
549
550 } // if reply
551 return 0;
552}
553
554
0546b4aa 555/**
556 * parses common HF 15 CMD parameters and prepares some data structures
557 * Parameters:
558 * **cmd command line
559 */
9455b51c 560int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
561 int temp;
562 uint8_t *req=c->d.asBytes, uid[8];
563 uint32_t reqlen=0;
564
565 // strip
566 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
567
568 if (strstr(*cmd,"-2")==*cmd) {
c43897de 569 c->arg[1]=0; // use 1of256
9455b51c 570 (*cmd)+=2;
571 }
572
573 // strip
574 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
575
576 if (strstr(*cmd,"-o")==*cmd) {
577 req[reqlen]=ISO15_REQ_OPTION;
578 (*cmd)+=2;
579 }
580
581 // strip
582 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
583
584 switch (**cmd) {
585 case 0:
586 PrintAndLog("missing addr");
587 return 0;
588 break;
589 case 's':
590 case 'S':
591 // you must have selected the tag earlier
592 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
593 ISO15_REQ_NONINVENTORY | ISO15_REQ_SELECT;
594 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
595 reqlen+=iso15cmdlen;
596 break;
597 case 'u':
598 case 'U':
599 // unaddressed mode may not be supported by all vendors
600 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
601 ISO15_REQ_NONINVENTORY;
602 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
603 reqlen+=iso15cmdlen;
604 break;
605 case '*':
65a23af2 606 // we scan for the UID ourself
9455b51c 607 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
608 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
609 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
610 reqlen+=iso15cmdlen;
611 if (!getUID(uid)) {
612 PrintAndLog("No Tag found");
613 return 0;
614 }
615 memcpy(req+reqlen,uid,8);
616 PrintAndLog("Detected UID %s",sprintUID(NULL,uid));
617 reqlen+=8;
618 break;
619 default:
620 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
621 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
622 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
623 reqlen+=iso15cmdlen;
624
625/* sscanf(cmd,"%hX%hX%hX%hX%hX%hX%hX%hX",
626 (short unsigned int *)&uid[7],(short unsigned int *)&uid[6],
627 (short unsigned int *)&uid[5],(short unsigned int *)&uid[4],
628 (short unsigned int *)&uid[3],(short unsigned int *)&uid[2],
629 (short unsigned int *)&uid[1],(short unsigned int *)&uid[0]); */
630 for (int i=0;i<8 && (*cmd)[i*2] && (*cmd)[i*2+1];i++) { // parse UID
631 sscanf((char[]){(*cmd)[i*2],(*cmd)[i*2+1],0},"%X",&temp);
632 uid[7-i]=temp&0xff;
633 }
634
635 PrintAndLog("Using UID %s",sprintUID(NULL,uid));
636 memcpy(&req[reqlen],&uid[0],8);
637 reqlen+=8;
638 }
639 // skip to next space
640 while (**cmd!=' ' && **cmd!='\t') (*cmd)++;
641 // skip over the space
642 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
643
644 c->arg[0]=reqlen;
645 return 1;
646}
647
6d7234cd 648/**
649 * Commandline handling: HF15 CMD SYSINFO
650 * get system information from tag/VICC
651 */
652int CmdHF15CmdSysinfo(const char *Cmd) {
902cb3c0 653 UsbCommand resp;
6d7234cd 654 uint8_t *recv;
655 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
656 uint8_t *req=c.d.asBytes;
657 int reqlen=0;
658 char cmdbuf[100];
659 char *cmd=cmdbuf;
660 char output[2048]="";
661 int i;
662
663 strncpy(cmd,Cmd,99);
664
665 // usage:
666 if (strlen(cmd)<1) {
0546b4aa 667 PrintAndLog("Usage: hf 15 cmd sysinfo [options] <uid|s|u|*>");
6d7234cd 668 PrintAndLog(" options:");
669 PrintAndLog(" -2 use slower '1 out of 256' mode");
670 PrintAndLog(" uid (either): ");
671 PrintAndLog(" <8B hex> full UID eg E011223344556677");
672 PrintAndLog(" s selected tag");
673 PrintAndLog(" u unaddressed mode");
674 PrintAndLog(" * scan for tag");
675 PrintAndLog(" start#: page number to start 0-255");
676 PrintAndLog(" count#: number of pages");
677 return 0;
678 }
679
680 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_SYSINFO},1);
681 reqlen=c.arg[0];
682
683 reqlen=AddCrc(req,reqlen);
684 c.arg[0]=reqlen;
685
686 SendCommand(&c);
687
902cb3c0 688 if (WaitForResponseTimeout(CMD_ACK,&resp,1000) && resp.arg[0]>2) {
689 recv = resp.d.asBytes;
690 if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) {
6d7234cd 691 if (!(recv[0] & ISO15_RES_ERROR)) {
692 *output=0; // reset outputstring
902cb3c0 693 for ( i=1; i<resp.arg[0]-2; i++) {
7bb9d33e 694 sprintf(output+strlen(output),"%02X ",recv[i]);
6d7234cd 695 }
696 strcat(output,"\n\r");
697 strcat(output,"UID = ");
698 strcat(output,sprintUID(NULL,recv+2));
699 strcat(output,"\n\r");
700 strcat(output,getTagInfo(recv+2)); //ABC
701 strcat(output,"\n\r");
702 i=10;
703 if (recv[1] & 0x01)
7bb9d33e 704 sprintf(output+strlen(output),"DSFID supported, set to %02X\n\r",recv[i++]);
6d7234cd 705 else
706 strcat(output,"DSFID not supported\n\r");
707 if (recv[1] & 0x02)
7bb9d33e 708 sprintf(output+strlen(output),"AFI supported, set to %03X\n\r",recv[i++]);
6d7234cd 709 else
710 strcat(output,"AFI not supported\n\r");
711 if (recv[1] & 0x04) {
712 strcat(output,"Tag provides info on memory layout (vendor dependent)\n\r");
713 sprintf(output+strlen(output)," %i (or %i) bytes/page x %i pages \n\r",
714 (recv[i+1]&0x1F)+1, (recv[i+1]&0x1F), recv[i]+1);
715 i+=2;
716 } else
717 strcat(output,"Tag does not provide information on memory layout\n\r");
7bb9d33e 718 if (recv[1] & 0x08) sprintf(output+strlen(output),"IC reference given: %02X\n\r",recv[i++]);
6d7234cd 719 else strcat(output,"IC reference not given\n\r");
720
721
722 PrintAndLog("%s",output);
723 } else {
724 PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
725 }
726 } else {
727 PrintAndLog("CRC failed");
728 }
729 } else {
eba61a56 730 PrintAndLog("timeout: no answer");
6d7234cd 731 }
732
733 return 0;
734}
735
7853775e 736/**
737 * Commandline handling: HF15 CMD READMULTI
738 * Read multiple blocks at once (not all tags support this)
739 */
740int CmdHF15CmdReadmulti(const char *Cmd) {
902cb3c0 741 UsbCommand resp;
7853775e 742 uint8_t *recv;
743 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
744 uint8_t *req=c.d.asBytes;
745 int reqlen=0, pagenum,pagecount;
746 char cmdbuf[100];
747 char *cmd=cmdbuf;
748 char output[2048]="";
749
750 strncpy(cmd,Cmd,99);
751
752 // usage:
753 if (strlen(cmd)<3) {
0546b4aa 754 PrintAndLog("Usage: hf 15 cmd readmulti [options] <uid|s|u|*> <start#> <count#>");
7853775e 755 PrintAndLog(" options:");
756 PrintAndLog(" -2 use slower '1 out of 256' mode");
757 PrintAndLog(" uid (either): ");
758 PrintAndLog(" <8B hex> full UID eg E011223344556677");
759 PrintAndLog(" s selected tag");
760 PrintAndLog(" u unaddressed mode");
761 PrintAndLog(" * scan for tag");
762 PrintAndLog(" start#: page number to start 0-255");
763 PrintAndLog(" count#: number of pages");
764 return 0;
765 }
766
767 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_READMULTI},1);
768 reqlen=c.arg[0];
769
770 pagenum=strtol(cmd,NULL,0);
771
772 // skip to next space
773 while (*cmd!=' ' && *cmd!='\t') cmd++;
774 // skip over the space
775 while (*cmd==' ' || *cmd=='\t') cmd++;
776
777 pagecount=strtol(cmd,NULL,0);
778 if (pagecount>0) pagecount--; // 0 means 1 page, 1 means 2 pages, ...
779
780 req[reqlen++]=(uint8_t)pagenum;
781 req[reqlen++]=(uint8_t)pagecount;
782
783 reqlen=AddCrc(req,reqlen);
784
785 c.arg[0]=reqlen;
786
787 SendCommand(&c);
0546b4aa 788
902cb3c0 789 if (WaitForResponseTimeout(CMD_ACK,&resp,1000) && resp.arg[0]>2) {
790 recv = resp.d.asBytes;
791 if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) {
7853775e 792 if (!(recv[0] & ISO15_RES_ERROR)) {
793 *output=0; // reset outputstring
902cb3c0 794 for ( int i=1; i<resp.arg[0]-2; i++) {
7bb9d33e 795 sprintf(output+strlen(output),"%02X ",recv[i]);
7853775e 796 }
797 strcat(output," ");
902cb3c0 798 for ( int i=1; i<resp.arg[0]-2; i++) {
7853775e 799 sprintf(output+strlen(output),"%c",recv[i]>31 && recv[i]<127?recv[i]:'.');
800 }
801 PrintAndLog("%s",output);
802 } else {
803 PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
804 }
805 } else {
806 PrintAndLog("CRC failed");
807 }
808 } else {
809 PrintAndLog("no answer");
810 }
811
812 return 0;
813}
814
05151b6f 815/**
816 * Commandline handling: HF15 CMD READ
817 * Reads a single Block
818 */
9455b51c 819int CmdHF15CmdRead(const char *Cmd) {
902cb3c0 820 UsbCommand resp;
9455b51c 821 uint8_t *recv;
822 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
823 uint8_t *req=c.d.asBytes;
824 int reqlen=0, pagenum;
825 char cmdbuf[100];
826 char *cmd=cmdbuf;
827 char output[100]="";
828
829 strncpy(cmd,Cmd,99);
830
831 // usage:
832 if (strlen(cmd)<3) {
0546b4aa 833 PrintAndLog("Usage: hf 15 cmd read [options] <uid|s|u|*> <page#>");
9455b51c 834 PrintAndLog(" options:");
835 PrintAndLog(" -2 use slower '1 out of 256' mode");
836 PrintAndLog(" uid (either): ");
837 PrintAndLog(" <8B hex> full UID eg E011223344556677");
838 PrintAndLog(" s selected tag");
839 PrintAndLog(" u unaddressed mode");
840 PrintAndLog(" * scan for tag");
841 PrintAndLog(" page#: page number 0-255");
842 return 0;
843 }
844
845 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_READ},1);
846 reqlen=c.arg[0];
847
848 pagenum=strtol(cmd,NULL,0);
849 /*if (pagenum<0) {
850 PrintAndLog("invalid pagenum");
851 return 0;
852 } */
853
854 req[reqlen++]=(uint8_t)pagenum;
855
856 reqlen=AddCrc(req,reqlen);
857
858 c.arg[0]=reqlen;
859
860 SendCommand(&c);
861
902cb3c0 862 if (WaitForResponseTimeout(CMD_ACK,&resp,1000) && resp.arg[0]>2) {
863 recv = resp.d.asBytes;
864 if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) {
9455b51c 865 if (!(recv[0] & ISO15_RES_ERROR)) {
866 *output=0; // reset outputstring
867 //sprintf(output, "Block %2i ",blocknum);
902cb3c0 868 for ( int i=1; i<resp.arg[0]-2; i++) {
7bb9d33e 869 sprintf(output+strlen(output),"%02X ",recv[i]);
9455b51c 870 }
871 strcat(output," ");
902cb3c0 872 for ( int i=1; i<resp.arg[0]-2; i++) {
e8da7740 873 sprintf(output+strlen(output),"%c",recv[i]>31 && recv[i]<127?recv[i]:'.');
9455b51c 874 }
875 PrintAndLog("%s",output);
876 } else {
b4a9d841 877 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
9455b51c 878 }
879 } else {
880 PrintAndLog("CRC failed");
881 }
882 } else {
883 PrintAndLog("no answer");
884 }
885
886 return 0;
887}
888
889
05151b6f 890/**
891 * Commandline handling: HF15 CMD WRITE
892 * Writes a single Block - might run into timeout, even when successful
893 */
9455b51c 894int CmdHF15CmdWrite(const char *Cmd) {
902cb3c0 895 UsbCommand resp;
9455b51c 896 uint8_t *recv;
897 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
898 uint8_t *req=c.d.asBytes;
899 int reqlen=0, pagenum, temp;
900 char cmdbuf[100];
901 char *cmd=cmdbuf;
902 char *cmd2;
903
904 strncpy(cmd,Cmd,99);
905
906 // usage:
907 if (strlen(cmd)<3) {
0546b4aa 908 PrintAndLog("Usage: hf 15 cmd write [options] <uid|s|u|*> <page#> <hexdata>");
9455b51c 909 PrintAndLog(" options:");
910 PrintAndLog(" -2 use slower '1 out of 256' mode");
911 PrintAndLog(" -o set OPTION Flag (needed for TI)");
912 PrintAndLog(" uid (either): ");
913 PrintAndLog(" <8B hex> full UID eg E011223344556677");
914 PrintAndLog(" s selected tag");
915 PrintAndLog(" u unaddressed mode");
916 PrintAndLog(" * scan for tag");
917 PrintAndLog(" page#: page number 0-255");
918 PrintAndLog(" hexdata: data to be written eg AA BB CC DD");
919 return 0;
920 }
921
922 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_WRITE},1);
923 reqlen=c.arg[0];
924
925 // *cmd -> page num ; *cmd2 -> data
926 cmd2=cmd;
927 while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++;
928 *cmd2=0;
929 cmd2++;
930
931 pagenum=strtol(cmd,NULL,0);
932 /*if (pagenum<0) {
933 PrintAndLog("invalid pagenum");
934 return 0;
935 } */
936 req[reqlen++]=(uint8_t)pagenum;
937
938
939 while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars
940 if (*cmd2==' ') {
941 cmd2++;
942 continue;
943 }
944 sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp);
945 req[reqlen++]=temp & 0xff;
946 cmd2+=2;
947 }
948
949 reqlen=AddCrc(req,reqlen);
950
951 c.arg[0]=reqlen;
952
953 SendCommand(&c);
954
902cb3c0 955 if (WaitForResponseTimeout(CMD_ACK,&resp,2000) && resp.arg[0]>2) {
956 recv = resp.d.asBytes;
957 if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) {
9455b51c 958 if (!(recv[0] & ISO15_RES_ERROR)) {
959 PrintAndLog("OK");
960 } else {
b4a9d841 961 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
9455b51c 962 }
963 } else {
964 PrintAndLog("CRC failed");
965 }
966 } else {
65a23af2 967 PrintAndLog("timeout: no answer - data may be written anyway");
9455b51c 968 }
969
970 return 0;
971}
972
973
974
975static command_t CommandTable15Cmd[] =
976{
977 {"help", CmdHF15CmdHelp, 1, "This Help"},
978 {"inquiry", CmdHF15CmdInquiry, 0, "Search for tags in range"},
979 /*
980 {"select", CmdHF15CmdSelect, 0, "Select an tag with a specific UID for further commands"},
981 */
982 {"read", CmdHF15CmdRead, 0, "Read a block"},
983 {"write", CmdHF15CmdWrite, 0, "Write a block"},
9455b51c 984 {"readmulti",CmdHF15CmdReadmulti, 0, "Reads multiple Blocks"},
0546b4aa 985 {"sysinfo",CmdHF15CmdSysinfo, 0, "Get Card Information"},
9455b51c 986 {"raw", CmdHF15CmdRaw, 0, "Send raw hex data to tag"},
987 {"debug", CmdHF15CmdDebug, 0, "Turn debugging on/off"},
988 {NULL, NULL, 0, NULL}
989};
990
991int CmdHF15Cmd(const char *Cmd)
992{
993 CmdsParse(CommandTable15Cmd, Cmd);
994 return 0;
995}
996
997int CmdHF15CmdHelp(const char *Cmd)
998{
999 CmdsHelp(CommandTable15Cmd);
1000 return 0;
1001}
1002
Impressum, Datenschutz