]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhf15.c
Small fixes,
[proxmark3-svn] / client / cmdhf15.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 // Modified 2010-2012 by <adrian -at- atrox.at>
4 // Modified 2012 by <vsza at vsza.hu>
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 //-----------------------------------------------------------------------------
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.
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdint.h>
29 //#include "proxusb.h"
30 #include "proxmark3.h"
31 #include "data.h"
32 #include "graph.h"
33 #include "ui.h"
34 #include "cmdparser.h"
35 #include "cmdhf15.h"
36 #include "../common/iso15693tools.h"
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)
47 #define TRACE_BUFF_SIZE 12000
48
49 // structure and database for uid -> tagtype lookups
50 typedef struct {
51 uint64_t uid;
52 int mask; // how many MSB bits used
53 char* desc;
54 } productName;
55
56
57 const productName uidmapping[] = {
58 // UID, #significant Bits, "Vendor(+Product)"
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" },
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" },
70 { 0xE007800000000000LL, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" },
71 { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" },
72 { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" },
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" },
83 { 0xE016000000000000LL, 16, "EM-Marin SA (Skidata)" },
84 { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034? no 'read', just 'readmulti'" },
85 { 0xE0160c0000000000LL, 24, "EM-Marin SA; EM4035?" },
86 { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135; 36x64bit start page 13" },
87 { 0xE016940000000000LL, 24, "EM-Marin SA (Skidata); 51x64bit" },
88 { 0,0,"no tag-info available" } // must be the last entry
89 };
90
91
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
94 // returns 1 if suceeded
95 int getUID(uint8_t *buf)
96 {
97 UsbCommand resp;
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
114 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
115 recv = resp.d.asBytes;
116 if (resp.arg[0]>=12 && ISO15_CRC_CHECK==Crc(recv,12)) {
117 memcpy(buf,&recv[2],8);
118 return 1;
119 }
120 }
121 } // retry
122 return 0;
123 }
124
125
126
127 // get a product description based on the UID
128 // uid[8] tag uid
129 // returns description of the best match
130 static char* getTagInfo(uint8_t *uid) {
131 uint64_t myuid,mask;
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 }
147
148 if (best>=0) return uidmapping[best].desc;
149
150 return uidmapping[i].desc;
151 }
152
153
154 // return a clear-text message to an errorcode
155 static char* TagErrorStr(uint8_t error) {
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 }
168 }
169
170
171 // Mode 3
172 int CmdHF15Demod(const char *Cmd)
173 {
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;
247 }
248
249
250
251 // * Acquire Samples as Reader (enables carrier, sends inquiry)
252 int CmdHF15Read(const char *Cmd)
253 {
254 UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693};
255 SendCommand(&c);
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();
267 return 0;
268 }
269
270 // Record Activity without enabeling carrier
271 int CmdHF15Record(const char *Cmd)
272 {
273 UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693};
274 SendCommand(&c);
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();
286 return 0;
287 }
288
289 int CmdHF15Reader(const char *Cmd)
290 {
291 UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
292 SendCommand(&c);
293 return 0;
294 }
295
296 // Simulation is still not working very good
297 int CmdHF15Sim(const char *Cmd)
298 {
299 UsbCommand c = {CMD_SIMTAG_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
300 SendCommand(&c);
301 return 0;
302 }
303
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)
306 int CmdHF15Afi(const char *Cmd)
307 {
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
314 int CmdHF15DumpMem(const char*Cmd) {
315 UsbCommand resp;
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
344 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
345 recv = resp.d.asBytes;
346 if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) {
347 if (!(recv[0] & ISO15_RES_ERROR)) {
348 retry=0;
349 *output=0; // reset outputstring
350 sprintf(output, "Block %2i ",blocknum);
351 for ( int i=1; i<resp.arg[0]-2; i++) { // data in hex
352 sprintf(output+strlen(output),"%02X ",recv[i]);
353 }
354 strcat(output," ");
355 for ( int i=1; i<resp.arg[0]-2; i++) { // data in cleaned ascii
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 {
362 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
363 return 0;
364 }
365 } // else PrintAndLog("crc");
366 } // else PrintAndLog("r null");
367 } // retry
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]));
375 return 0;
376 }
377
378
379 // "HF 15" interface
380
381 static 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}
393 };
394
395 int CmdHF15(const char *Cmd)
396 {
397 CmdsParse(CommandTable15, Cmd);
398 return 0;
399 }
400
401 int CmdHF15Help(const char *Cmd)
402 {
403 CmdsHelp(CommandTable15);
404 return 0;
405 }
406
407
408 // "HF 15 Cmd" Interface
409 // Allows direct communication with the tag on command level
410
411 int CmdHF15CmdInquiry(const char *Cmd)
412 {
413 UsbCommand resp;
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
428 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
429 if (resp.arg[0]>=12) {
430 recv = resp.d.asBytes;
431 PrintAndLog("UID=%s",sprintUID(NULL,&recv[2]));
432 PrintAndLog("Tag Info: %s",getTagInfo(&recv[2]));
433 } else {
434 PrintAndLog("Response to short, just %i bytes. No tag?\n",resp.arg[0]);
435 }
436 } else {
437 PrintAndLog("timeout.");
438 }
439 return 0;
440 }
441
442
443 // Turns debugging on(1)/off(0)
444 int CmdHF15CmdDebug( const char *cmd) {
445 int debug=atoi(cmd);
446 if (strlen(cmd)<1) {
447 PrintAndLog("Usage: hf 15 cmd debug <0|1>");
448 PrintAndLog(" 0 no debugging");
449 PrintAndLog(" 1 turn debugging on");
450 return 0;
451 }
452
453 UsbCommand c = {CMD_ISO_15693_DEBUG, {debug, 0, 0}};
454 SendCommand(&c);
455 return 0;
456 }
457
458
459 int CmdHF15CmdRaw (const char *cmd) {
460 UsbCommand resp;
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;
470 char *hexout;
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) {
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);
539 if (hexout != NULL) {
540 for (int i = 0; i < resp.arg[0]; i++) { // data in hex
541 sprintf(&hexout[i * 3], "%02X ", recv[i]);
542 }
543 PrintAndLog("%s", hexout);
544 free(hexout);
545 }
546 } else {
547 PrintAndLog("timeout while waiting for reply.");
548 }
549
550 } // if reply
551 return 0;
552 }
553
554
555 /**
556 * parses common HF 15 CMD parameters and prepares some data structures
557 * Parameters:
558 * **cmd command line
559 */
560 int 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) {
569 c->arg[1]=0; // use 1of256
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 '*':
606 // we scan for the UID ourself
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
648 /**
649 * Commandline handling: HF15 CMD SYSINFO
650 * get system information from tag/VICC
651 */
652 int CmdHF15CmdSysinfo(const char *Cmd) {
653 UsbCommand resp;
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) {
667 PrintAndLog("Usage: hf 15 cmd sysinfo [options] <uid|s|u|*>");
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
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])) {
691 if (!(recv[0] & ISO15_RES_ERROR)) {
692 *output=0; // reset outputstring
693 for ( i=1; i<resp.arg[0]-2; i++) {
694 sprintf(output+strlen(output),"%02X ",recv[i]);
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)
704 sprintf(output+strlen(output),"DSFID supported, set to %02X\n\r",recv[i++]);
705 else
706 strcat(output,"DSFID not supported\n\r");
707 if (recv[1] & 0x02)
708 sprintf(output+strlen(output),"AFI supported, set to %03X\n\r",recv[i++]);
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");
718 if (recv[1] & 0x08) sprintf(output+strlen(output),"IC reference given: %02X\n\r",recv[i++]);
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 {
730 PrintAndLog("timeout: no answer");
731 }
732
733 return 0;
734 }
735
736 /**
737 * Commandline handling: HF15 CMD READMULTI
738 * Read multiple blocks at once (not all tags support this)
739 */
740 int CmdHF15CmdReadmulti(const char *Cmd) {
741 UsbCommand resp;
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) {
754 PrintAndLog("Usage: hf 15 cmd readmulti [options] <uid|s|u|*> <start#> <count#>");
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);
788
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])) {
792 if (!(recv[0] & ISO15_RES_ERROR)) {
793 *output=0; // reset outputstring
794 for ( int i=1; i<resp.arg[0]-2; i++) {
795 sprintf(output+strlen(output),"%02X ",recv[i]);
796 }
797 strcat(output," ");
798 for ( int i=1; i<resp.arg[0]-2; i++) {
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
815 /**
816 * Commandline handling: HF15 CMD READ
817 * Reads a single Block
818 */
819 int CmdHF15CmdRead(const char *Cmd) {
820 UsbCommand resp;
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) {
833 PrintAndLog("Usage: hf 15 cmd read [options] <uid|s|u|*> <page#>");
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
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])) {
865 if (!(recv[0] & ISO15_RES_ERROR)) {
866 *output=0; // reset outputstring
867 //sprintf(output, "Block %2i ",blocknum);
868 for ( int i=1; i<resp.arg[0]-2; i++) {
869 sprintf(output+strlen(output),"%02X ",recv[i]);
870 }
871 strcat(output," ");
872 for ( int i=1; i<resp.arg[0]-2; i++) {
873 sprintf(output+strlen(output),"%c",recv[i]>31 && recv[i]<127?recv[i]:'.');
874 }
875 PrintAndLog("%s",output);
876 } else {
877 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
878 }
879 } else {
880 PrintAndLog("CRC failed");
881 }
882 } else {
883 PrintAndLog("no answer");
884 }
885
886 return 0;
887 }
888
889
890 /**
891 * Commandline handling: HF15 CMD WRITE
892 * Writes a single Block - might run into timeout, even when successful
893 */
894 int CmdHF15CmdWrite(const char *Cmd) {
895 UsbCommand resp;
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) {
908 PrintAndLog("Usage: hf 15 cmd write [options] <uid|s|u|*> <page#> <hexdata>");
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
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])) {
958 if (!(recv[0] & ISO15_RES_ERROR)) {
959 PrintAndLog("OK");
960 } else {
961 PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
962 }
963 } else {
964 PrintAndLog("CRC failed");
965 }
966 } else {
967 PrintAndLog("timeout: no answer - data may be written anyway");
968 }
969
970 return 0;
971 }
972
973
974
975 static 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"},
984 {"readmulti",CmdHF15CmdReadmulti, 0, "Reads multiple Blocks"},
985 {"sysinfo",CmdHF15CmdSysinfo, 0, "Get Card Information"},
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
991 int CmdHF15Cmd(const char *Cmd)
992 {
993 CmdsParse(CommandTable15Cmd, Cmd);
994 return 0;
995 }
996
997 int CmdHF15CmdHelp(const char *Cmd)
998 {
999 CmdsHelp(CommandTable15Cmd);
1000 return 0;
1001 }
1002
Impressum, Datenschutz