]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhf15.c
added 'hf 15 cmd sysinfo' using Adrian's second patch from issue 20
[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;
448
449
450 if (strlen(cmd)<3) {
451 PrintAndLog("Usage: hf 15 cmd raw [-r] [-2] [-c] <0A 0B 0C ... hex>");
452 PrintAndLog(" -r do not read response");
453 PrintAndLog(" -2 use slower '1 out of 256' mode");
454 PrintAndLog(" -c calculate and append CRC");
455 PrintAndLog(" Tip: turn on debugging for verbose output");
456 return 0;
457 }
458
459 // strip
460 while (*cmd==' ' || *cmd=='\t') cmd++;
461
462 while (cmd[i]!='\0') {
463 if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
464 if (cmd[i]=='-') {
465 switch (cmd[i+1]) {
466 case 'r':
467 case 'R':
468 reply=0;
469 break;
470 case '2':
471 fast=0;
472 break;
473 case 'c':
474 case 'C':
475 crc=1;
476 break;
477 default:
478 PrintAndLog("Invalid option");
479 return 0;
480 }
481 i+=2;
482 continue;
483 }
484 if ((cmd[i]>='0' && cmd[i]<='9') ||
485 (cmd[i]>='a' && cmd[i]<='f') ||
486 (cmd[i]>='A' && cmd[i]<='F') ) {
487 buf[strlen(buf)+1]=0;
488 buf[strlen(buf)]=cmd[i];
489 i++;
490
491 if (strlen(buf)>=2) {
492 sscanf(buf,"%x",&temp);
493 data[datalen]=(uint8_t)(temp & 0xff);
494 datalen++;
495 *buf=0;
496 }
497 continue;
498 }
499 PrintAndLog("Invalid char on input");
500 return 0;
501 }
502 if (crc) datalen=AddCrc(data,datalen);
503
504 c.arg[0]=datalen;
505 c.arg[1]=fast;
506 c.arg[2]=reply;
507 memcpy(c.d.asBytes,data,datalen);
508
509 SendCommand(&c);
510
511 if (reply) {
512 r=WaitForResponseTimeout(CMD_ACK,1000);
513
514 if (r!=NULL) {
515 recv = r->d.asBytes;
516 PrintAndLog("received %i octets",r->arg[0]);
517 // TODO: output
518 } else {
519 PrintAndLog("timeout while waiting for reply.");
520 }
521
522 } // if reply
523 return 0;
524}
525
526
527int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
528 int temp;
529 uint8_t *req=c->d.asBytes, uid[8];
530 uint32_t reqlen=0;
531
532 // strip
533 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
534
535 if (strstr(*cmd,"-2")==*cmd) {
c43897de 536 c->arg[1]=0; // use 1of256
9455b51c 537 (*cmd)+=2;
538 }
539
540 // strip
541 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
542
543 if (strstr(*cmd,"-o")==*cmd) {
544 req[reqlen]=ISO15_REQ_OPTION;
545 (*cmd)+=2;
546 }
547
548 // strip
549 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
550
551 switch (**cmd) {
552 case 0:
553 PrintAndLog("missing addr");
554 return 0;
555 break;
556 case 's':
557 case 'S':
558 // you must have selected the tag earlier
559 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
560 ISO15_REQ_NONINVENTORY | ISO15_REQ_SELECT;
561 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
562 reqlen+=iso15cmdlen;
563 break;
564 case 'u':
565 case 'U':
566 // unaddressed mode may not be supported by all vendors
567 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
568 ISO15_REQ_NONINVENTORY;
569 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
570 reqlen+=iso15cmdlen;
571 break;
572 case '*':
573 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
574 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
575 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
576 reqlen+=iso15cmdlen;
577 if (!getUID(uid)) {
578 PrintAndLog("No Tag found");
579 return 0;
580 }
581 memcpy(req+reqlen,uid,8);
582 PrintAndLog("Detected UID %s",sprintUID(NULL,uid));
583 reqlen+=8;
584 break;
585 default:
586 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
587 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
588 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
589 reqlen+=iso15cmdlen;
590
591/* sscanf(cmd,"%hX%hX%hX%hX%hX%hX%hX%hX",
592 (short unsigned int *)&uid[7],(short unsigned int *)&uid[6],
593 (short unsigned int *)&uid[5],(short unsigned int *)&uid[4],
594 (short unsigned int *)&uid[3],(short unsigned int *)&uid[2],
595 (short unsigned int *)&uid[1],(short unsigned int *)&uid[0]); */
596 for (int i=0;i<8 && (*cmd)[i*2] && (*cmd)[i*2+1];i++) { // parse UID
597 sscanf((char[]){(*cmd)[i*2],(*cmd)[i*2+1],0},"%X",&temp);
598 uid[7-i]=temp&0xff;
599 }
600
601 PrintAndLog("Using UID %s",sprintUID(NULL,uid));
602 memcpy(&req[reqlen],&uid[0],8);
603 reqlen+=8;
604 }
605 // skip to next space
606 while (**cmd!=' ' && **cmd!='\t') (*cmd)++;
607 // skip over the space
608 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
609
610 c->arg[0]=reqlen;
611 return 1;
612}
613
614
615
6d7234cd 616/**
617 * Commandline handling: HF15 CMD SYSINFO
618 * get system information from tag/VICC
619 */
620int CmdHF15CmdSysinfo(const char *Cmd) {
621 UsbCommand *r;
622 uint8_t *recv;
623 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
624 uint8_t *req=c.d.asBytes;
625 int reqlen=0;
626 char cmdbuf[100];
627 char *cmd=cmdbuf;
628 char output[2048]="";
629 int i;
630
631 strncpy(cmd,Cmd,99);
632
633 // usage:
634 if (strlen(cmd)<1) {
635 PrintAndLog("Usage: hf 15 cmd sysinfo [options] <uid|s|*>");
636 PrintAndLog(" options:");
637 PrintAndLog(" -2 use slower '1 out of 256' mode");
638 PrintAndLog(" uid (either): ");
639 PrintAndLog(" <8B hex> full UID eg E011223344556677");
640 PrintAndLog(" s selected tag");
641 PrintAndLog(" u unaddressed mode");
642 PrintAndLog(" * scan for tag");
643 PrintAndLog(" start#: page number to start 0-255");
644 PrintAndLog(" count#: number of pages");
645 return 0;
646 }
647
648 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_SYSINFO},1);
649 reqlen=c.arg[0];
650
651 reqlen=AddCrc(req,reqlen);
652 c.arg[0]=reqlen;
653
654 SendCommand(&c);
655
656 r=WaitForResponseTimeout(CMD_ACK,1000);
657
658 if (r!=NULL && r->arg[0]>2) {
659 recv = r->d.asBytes;
660 if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
661 if (!(recv[0] & ISO15_RES_ERROR)) {
662 *output=0; // reset outputstring
663 for ( i=1; i<r->arg[0]-2; i++) {
664 sprintf(output+strlen(output),"%02hX ",recv[i]);
665 }
666 strcat(output,"\n\r");
667 strcat(output,"UID = ");
668 strcat(output,sprintUID(NULL,recv+2));
669 strcat(output,"\n\r");
670 strcat(output,getTagInfo(recv+2)); //ABC
671 strcat(output,"\n\r");
672 i=10;
673 if (recv[1] & 0x01)
674 sprintf(output+strlen(output),"DSFID supported, set to %02hX\n\r",recv[i++]);
675 else
676 strcat(output,"DSFID not supported\n\r");
677 if (recv[1] & 0x02)
678 sprintf(output+strlen(output),"AFI supported, set to %03hX\n\r",recv[i++]);
679 else
680 strcat(output,"AFI not supported\n\r");
681 if (recv[1] & 0x04) {
682 strcat(output,"Tag provides info on memory layout (vendor dependent)\n\r");
683 sprintf(output+strlen(output)," %i (or %i) bytes/page x %i pages \n\r",
684 (recv[i+1]&0x1F)+1, (recv[i+1]&0x1F), recv[i]+1);
685 i+=2;
686 } else
687 strcat(output,"Tag does not provide information on memory layout\n\r");
688 if (recv[1] & 0x08) sprintf(output+strlen(output),"IC reference given: %02hX\n\r",recv[i++]);
689 else strcat(output,"IC reference not given\n\r");
690
691
692 PrintAndLog("%s",output);
693 } else {
694 PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
695 }
696 } else {
697 PrintAndLog("CRC failed");
698 }
699 } else {
700 PrintAndLog("no answer");
701 }
702
703 return 0;
704}
705
706
707
9455b51c 708int CmdHF15CmdRead(const char *Cmd) {
709 UsbCommand *r;
710 uint8_t *recv;
711 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
712 uint8_t *req=c.d.asBytes;
713 int reqlen=0, pagenum;
714 char cmdbuf[100];
715 char *cmd=cmdbuf;
716 char output[100]="";
717
718 strncpy(cmd,Cmd,99);
719
720 // usage:
721 if (strlen(cmd)<3) {
722 PrintAndLog("Usage: hf 15 cmd read [options] <uid|s|*> <page#>");
723 PrintAndLog(" options:");
724 PrintAndLog(" -2 use slower '1 out of 256' mode");
725 PrintAndLog(" uid (either): ");
726 PrintAndLog(" <8B hex> full UID eg E011223344556677");
727 PrintAndLog(" s selected tag");
728 PrintAndLog(" u unaddressed mode");
729 PrintAndLog(" * scan for tag");
730 PrintAndLog(" page#: page number 0-255");
731 return 0;
732 }
733
734 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_READ},1);
735 reqlen=c.arg[0];
736
737 pagenum=strtol(cmd,NULL,0);
738 /*if (pagenum<0) {
739 PrintAndLog("invalid pagenum");
740 return 0;
741 } */
742
743 req[reqlen++]=(uint8_t)pagenum;
744
745 reqlen=AddCrc(req,reqlen);
746
747 c.arg[0]=reqlen;
748
749 SendCommand(&c);
750
751 r=WaitForResponseTimeout(CMD_ACK,1000);
752
753 if (r!=NULL && r->arg[0]>2) {
754 recv = r->d.asBytes;
755 if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
756 if (!(recv[0] & ISO15_RES_ERROR)) {
757 *output=0; // reset outputstring
758 //sprintf(output, "Block %2i ",blocknum);
759 for ( int i=1; i<r->arg[0]-2; i++) {
760 sprintf(output+strlen(output),"%02hX ",recv[i]);
761 }
762 strcat(output," ");
382223b9 763 for ( int i=1; i<r->arg[0]-2; i++) {
e8da7740 764 sprintf(output+strlen(output),"%c",recv[i]>31 && recv[i]<127?recv[i]:'.');
9455b51c 765 }
766 PrintAndLog("%s",output);
767 } else {
b4a9d841 768 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
9455b51c 769 }
770 } else {
771 PrintAndLog("CRC failed");
772 }
773 } else {
774 PrintAndLog("no answer");
775 }
776
777 return 0;
778}
779
780
781int CmdHF15CmdWrite(const char *Cmd) {
782 UsbCommand *r;
783 uint8_t *recv;
784 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
785 uint8_t *req=c.d.asBytes;
786 int reqlen=0, pagenum, temp;
787 char cmdbuf[100];
788 char *cmd=cmdbuf;
789 char *cmd2;
790
791 strncpy(cmd,Cmd,99);
792
793 // usage:
794 if (strlen(cmd)<3) {
795 PrintAndLog("Usage: hf 15 cmd write [options] <uid|s|*> <page#> <hexdata>");
796 PrintAndLog(" options:");
797 PrintAndLog(" -2 use slower '1 out of 256' mode");
798 PrintAndLog(" -o set OPTION Flag (needed for TI)");
799 PrintAndLog(" uid (either): ");
800 PrintAndLog(" <8B hex> full UID eg E011223344556677");
801 PrintAndLog(" s selected tag");
802 PrintAndLog(" u unaddressed mode");
803 PrintAndLog(" * scan for tag");
804 PrintAndLog(" page#: page number 0-255");
805 PrintAndLog(" hexdata: data to be written eg AA BB CC DD");
806 return 0;
807 }
808
809 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_WRITE},1);
810 reqlen=c.arg[0];
811
812 // *cmd -> page num ; *cmd2 -> data
813 cmd2=cmd;
814 while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++;
815 *cmd2=0;
816 cmd2++;
817
818 pagenum=strtol(cmd,NULL,0);
819 /*if (pagenum<0) {
820 PrintAndLog("invalid pagenum");
821 return 0;
822 } */
823 req[reqlen++]=(uint8_t)pagenum;
824
825
826 while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars
827 if (*cmd2==' ') {
828 cmd2++;
829 continue;
830 }
831 sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp);
832 req[reqlen++]=temp & 0xff;
833 cmd2+=2;
834 }
835
836 reqlen=AddCrc(req,reqlen);
837
838 c.arg[0]=reqlen;
839
840 SendCommand(&c);
841
842 r=WaitForResponseTimeout(CMD_ACK,2000);
843
844 if (r!=NULL && r->arg[0]>2) {
845 recv = r->d.asBytes;
846 if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
847 if (!(recv[0] & ISO15_RES_ERROR)) {
848 PrintAndLog("OK");
849 } else {
b4a9d841 850 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
9455b51c 851 }
852 } else {
853 PrintAndLog("CRC failed");
854 }
855 } else {
856 PrintAndLog("no answer");
857 }
858
859 return 0;
860}
861
862
863
864static command_t CommandTable15Cmd[] =
865{
866 {"help", CmdHF15CmdHelp, 1, "This Help"},
867 {"inquiry", CmdHF15CmdInquiry, 0, "Search for tags in range"},
868 /*
869 {"select", CmdHF15CmdSelect, 0, "Select an tag with a specific UID for further commands"},
870 */
871 {"read", CmdHF15CmdRead, 0, "Read a block"},
872 {"write", CmdHF15CmdWrite, 0, "Write a block"},
873/*
874 {"readmulti",CmdHF15CmdReadmulti, 0, "Reads multiple Blocks"},
875*/
6d7234cd 876 {"sysinfo", CmdHF15CmdSysinfo, 0, "Get Card Information"},
9455b51c 877 {"raw", CmdHF15CmdRaw, 0, "Send raw hex data to tag"},
878 {"debug", CmdHF15CmdDebug, 0, "Turn debugging on/off"},
879 {NULL, NULL, 0, NULL}
880};
881
882int CmdHF15Cmd(const char *Cmd)
883{
884 CmdsParse(CommandTable15Cmd, Cmd);
885 return 0;
886}
887
888int CmdHF15CmdHelp(const char *Cmd)
889{
890 CmdsHelp(CommandTable15Cmd);
891 return 0;
892}
893
Impressum, Datenschutz