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