]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhf15.c
4fce726da790c2753e0e0623b8f225904e2f48c6
[proxmark3-svn] / client / cmdhf15.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 // Modified 2010 by <adrian -at- atrox.at>
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 //-----------------------------------------------------------------------------
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.
23
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"
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)
45
46 static int CmdHelp(const char *Cmd);
47
48 // structure and database for uid -> tagtype lookups
49 typedef struct {
50 uint64_t uid;
51 int mask; // how many MSB bits used
52 char* desc;
53 } productName;
54
55
56 const productName uidmapping[] = {
57 { 0xE007000000000000LL, 16, "Texas Instrument; " },
58 { 0xE007000000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Inlay; 64x32bit" },
59 { 0xE007100000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" },
60 { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" },
61 { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" },
62 { 0xE005000000000000LL, 16, "Infineon" },
63 { 0xE005400000000000LL, 24, "Infineon; 56x32bit" },
64 { 0xE004000000000000LL, 16, "Philips" },
65 { 0xE002000000000000LL, 16, "STMicroelectronics" },
66 { 0xE016000000000000LL, 16, "EM-Marin SA (Skidata)" },
67 { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); no memory" },
68 { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135; 36x64bit start page 13" },
69 { 0,0,"no tag-info available" } // must be the last entry
70 };
71
72
73 // fast method to just read the UID of an tag (collission detection not supported)
74 // *buf shouls be large enough to fit the 64bit uid
75 // returns 1 if suceeded
76 int getUID(uint8_t *buf)
77 {
78 UsbCommand *r;
79 uint8_t *recv;
80 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
81 uint8_t *req=c.d.asBytes;
82 int reqlen=0;
83
84 for (int retry=0;retry<3; retry++) { // don't give up the at the first try
85
86 req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
87 ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
88 req[1]=ISO15_CMD_INVENTORY;
89 req[2]=0; // mask length
90 reqlen=AddCrc(req,3);
91 c.arg[0]=reqlen;
92
93 SendCommand(&c);
94
95 r=WaitForResponseTimeout(CMD_ACK,1000);
96
97 if (r!=NULL) {
98 recv = r->d.asBytes;
99 if (r->arg[0]>=12 && ISO15_CRC_CHECK==Crc(recv,12)) {
100 memcpy(buf,&recv[2],8);
101 return 1;
102 }
103 }
104 } // retry
105 return 0;
106 }
107
108
109
110 // get a product description based on the UID
111 // uid[8] tag uid
112 // returns description of the best match
113 static char* getTagInfo(uint8_t *uid) {
114 uint64_t myuid,mask;
115 int i=0, best=-1;
116 memcpy(&myuid,uid,sizeof(uint64_t));
117 while (uidmapping[i].mask>0) {
118 mask=(~0LL) <<(64-uidmapping[i].mask);
119 if ((myuid & mask) == uidmapping[i].uid) {
120 if (best==-1) {
121 best=i;
122 } else {
123 if (uidmapping[i].mask>uidmapping[best].mask) {
124 best=i;
125 }
126 }
127 }
128 i++;
129 }
130
131 if (best>=0) return uidmapping[best].desc;
132
133 return uidmapping[i].desc;
134 }
135
136
137 // will return a clear-text message to an errorcode
138 static char* TagErrorStr(uint8_t error) {
139 // TODO
140 return NULL;
141 }
142
143
144 // Mode 3
145 int CmdHF15Demod(const char *Cmd)
146 {
147 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
148
149 int i, j;
150 int max = 0, maxPos = 0;
151
152 int skip = 4;
153
154 if (GraphTraceLen < 1000) return 0;
155
156 // First, correlate for SOF
157 for (i = 0; i < 100; i++) {
158 int corr = 0;
159 for (j = 0; j < arraylen(FrameSOF); j += skip) {
160 corr += FrameSOF[j] * GraphBuffer[i + (j / skip)];
161 }
162 if (corr > max) {
163 max = corr;
164 maxPos = i;
165 }
166 }
167 PrintAndLog("SOF at %d, correlation %d", maxPos,
168 max / (arraylen(FrameSOF) / skip));
169
170 i = maxPos + arraylen(FrameSOF) / skip;
171 int k = 0;
172 uint8_t outBuf[20];
173 memset(outBuf, 0, sizeof(outBuf));
174 uint8_t mask = 0x01;
175 for (;;) {
176 int corr0 = 0, corr1 = 0, corrEOF = 0;
177 for (j = 0; j < arraylen(Logic0); j += skip) {
178 corr0 += Logic0[j] * GraphBuffer[i + (j / skip)];
179 }
180 for (j = 0; j < arraylen(Logic1); j += skip) {
181 corr1 += Logic1[j] * GraphBuffer[i + (j / skip)];
182 }
183 for (j = 0; j < arraylen(FrameEOF); j += skip) {
184 corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)];
185 }
186 // Even things out by the length of the target waveform.
187 corr0 *= 4;
188 corr1 *= 4;
189
190 if (corrEOF > corr1 && corrEOF > corr0) {
191 PrintAndLog("EOF at %d", i);
192 break;
193 } else if (corr1 > corr0) {
194 i += arraylen(Logic1) / skip;
195 outBuf[k] |= mask;
196 } else {
197 i += arraylen(Logic0) / skip;
198 }
199 mask <<= 1;
200 if (mask == 0) {
201 k++;
202 mask = 0x01;
203 }
204 if ((i + (int)arraylen(FrameEOF)) >= GraphTraceLen) {
205 PrintAndLog("ran off end!");
206 break;
207 }
208 }
209 if (mask != 0x01) {
210 PrintAndLog("error, uneven octet! (discard extra bits!)");
211 PrintAndLog(" mask=%02x", mask);
212 }
213 PrintAndLog("%d octets", k);
214
215 for (i = 0; i < k; i++) {
216 PrintAndLog("# %2d: %02x ", i, outBuf[i]);
217 }
218 PrintAndLog("CRC=%04x", Iso15693Crc(outBuf, k - 2));
219 return 0;
220 }
221
222
223
224 // * Acquire Samples as Reader (enables carrier, sends inquiry)
225 int CmdHF15Read(const char *Cmd)
226 {
227 UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693};
228 SendCommand(&c);
229 return 0;
230 }
231
232 // Record Activity without enabeling carrier
233 int CmdHF15Record(const char *Cmd)
234 {
235 UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693};
236 SendCommand(&c);
237 return 0;
238 }
239
240 int CmdHF15Reader(const char *Cmd)
241 {
242 UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
243 SendCommand(&c);
244 return 0;
245 }
246
247 // Simulation is still not working very good
248 int CmdHF15Sim(const char *Cmd)
249 {
250 UsbCommand c = {CMD_SIMTAG_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
251 SendCommand(&c);
252 return 0;
253 }
254
255 // finds the AFI (Application Family Idendifier) of a card, by trying all values
256 // (There is no standard way of reading the AFI, allthough some tags support this)
257 int CmdHF15Afi(const char *Cmd)
258 {
259 UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}};
260 SendCommand(&c);
261 return 0;
262 }
263
264 // Reads all memory pages
265 int CmdHF15DumpMem(const char*Cmd) {
266 UsbCommand *r;
267 uint8_t uid[8];
268 uint8_t *recv=NULL;
269 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
270 uint8_t *req=c.d.asBytes;
271 int reqlen=0;
272 int blocknum=0;
273 char output[80];
274
275 if (!getUID(uid)) {
276 PrintAndLog("No Tag found.");
277 return 0;
278 }
279
280 PrintAndLog("Reading memory from tag UID=%s",sprintUID(NULL,uid));
281 PrintAndLog("Tag Info: %s",getTagInfo(uid));
282
283 for (int retry=0; retry<5; retry++) {
284
285 req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
286 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
287 req[1]=ISO15_CMD_READ;
288 memcpy(&req[2],uid,8);
289 req[10]=blocknum;
290 reqlen=AddCrc(req,11);
291 c.arg[0]=reqlen;
292
293 SendCommand(&c);
294
295 r=WaitForResponseTimeout(CMD_ACK,1000);
296
297 if (r!=NULL) {
298 recv = r->d.asBytes;
299 if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
300 if (!(recv[0] & ISO15_RES_ERROR)) {
301 retry=0;
302 *output=0; // reset outputstring
303 sprintf(output, "Block %2i ",blocknum);
304 for ( int i=1; i<r->arg[0]-2; i++) { // data in hex
305 sprintf(output+strlen(output),"%02hX ",recv[i]);
306 }
307 strcat(output," ");
308 for ( int i=1; i<r->arg[0]-2; i++) { // data in cleaned ascii
309 sprintf(output+strlen(output),"%c",(recv[i]>31 && recv[i]<127)?recv[i]:'.');
310 }
311 PrintAndLog("%s",output);
312 blocknum++;
313 // PrintAndLog("bn=%i",blocknum);
314 } else {
315 PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
316 return 0;
317 }
318 } // else PrintAndLog("crc");
319 } // else PrintAndLog("r null");
320
321 } // retry
322 if (r && r->arg[0]<3)
323 PrintAndLog("Lost Connection");
324 else if (r && ISO15_CRC_CHECK!=Crc(r->d.asBytes,r->arg[0]))
325 PrintAndLog("CRC Failed");
326 else
327 PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
328 return 0;
329 }
330
331
332 // "HF 15" interface
333
334 static command_t CommandTable15[] =
335 {
336 {"help", CmdHF15Help, 1, "This help"},
337 {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"},
338 {"read", CmdHF15Read, 0, "Read HF tag (ISO 15693)"},
339 {"record", CmdHF15Record, 0, "Record Samples (ISO 15693)"}, // atrox
340 {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"},
341 {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"},
342 {"cmd", CmdHF15Cmd, 0, "Send direct commands to ISO15693 tag"},
343 {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"},
344 {"dumpmemory", CmdHF15DumpMem, 0, "Read all memory pages of an ISO15693 tag"},
345 {NULL, NULL, 0, NULL}
346 };
347
348 int CmdHF15(const char *Cmd)
349 {
350 CmdsParse(CommandTable15, Cmd);
351 return 0;
352 }
353
354 int CmdHF15Help(const char *Cmd)
355 {
356 CmdsHelp(CommandTable15);
357 return 0;
358 }
359
360
361 // "HF 15 Cmd" Interface
362 // Allows direct communication with the tag on command level
363
364 int CmdHF15CmdInquiry(const char *Cmd)
365 {
366 UsbCommand *r;
367 uint8_t *recv;
368 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
369 uint8_t *req=c.d.asBytes;
370 int reqlen=0;
371
372 req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
373 ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
374 req[1]=ISO15_CMD_INVENTORY;
375 req[2]=0; // mask length
376 reqlen=AddCrc(req,3);
377 c.arg[0]=reqlen;
378
379 SendCommand(&c);
380
381 r=WaitForResponseTimeout(CMD_ACK,1000);
382
383 if (r!=NULL) {
384 if (r->arg[0]>=12) {
385 recv = r->d.asBytes;
386 PrintAndLog("UID=%s",sprintUID(NULL,&recv[2]));
387 PrintAndLog("Tag Info: %s",getTagInfo(&recv[2]));
388 } else {
389 PrintAndLog("Response to short, just %i bytes. No tag?\n",r->arg[0]);
390 }
391 } else {
392 PrintAndLog("timeout.");
393 }
394 return 0;
395 }
396
397
398 // Turns debugging on(1)/off(0)
399 int CmdHF15CmdDebug( const char *cmd) {
400 int debug=atoi(cmd);
401 if (strlen(cmd)<1) {
402 PrintAndLog("Usage: hf 15 cmd debug <0/1>");
403 PrintAndLog(" 0..no debugging output 1..turn debugging on");
404 return 0;
405 }
406
407 UsbCommand c = {CMD_ISO_15693_DEBUG, {debug, 0, 0}};
408 SendCommand(&c);
409 return 0;
410 }
411
412
413 int CmdHF15CmdRaw (const char *cmd) {
414 UsbCommand *r;
415 uint8_t *recv;
416 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
417 int reply=1;
418 int fast=1;
419 int crc=0;
420 char buf[5]="";
421 int i=0;
422 uint8_t data[100];
423 unsigned int datalen=0, temp;
424
425
426 if (strlen(cmd)<3) {
427 PrintAndLog("Usage: hf 15 cmd raw [-r] [-2] [-c] <0A 0B 0C ... hex>");
428 PrintAndLog(" -r do not read response");
429 PrintAndLog(" -2 use slower '1 out of 256' mode");
430 PrintAndLog(" -c calculate and append CRC");
431 PrintAndLog(" Tip: turn on debugging for verbose output");
432 return 0;
433 }
434
435 // strip
436 while (*cmd==' ' || *cmd=='\t') cmd++;
437
438 while (cmd[i]!='\0') {
439 if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
440 if (cmd[i]=='-') {
441 switch (cmd[i+1]) {
442 case 'r':
443 case 'R':
444 reply=0;
445 break;
446 case '2':
447 fast=0;
448 break;
449 case 'c':
450 case 'C':
451 crc=1;
452 break;
453 default:
454 PrintAndLog("Invalid option");
455 return 0;
456 }
457 i+=2;
458 continue;
459 }
460 if ((cmd[i]>='0' && cmd[i]<='9') ||
461 (cmd[i]>='a' && cmd[i]<='f') ||
462 (cmd[i]>='A' && cmd[i]<='F') ) {
463 buf[strlen(buf)+1]=0;
464 buf[strlen(buf)]=cmd[i];
465 i++;
466
467 if (strlen(buf)>=2) {
468 sscanf(buf,"%x",&temp);
469 data[datalen]=(uint8_t)(temp & 0xff);
470 datalen++;
471 *buf=0;
472 }
473 continue;
474 }
475 PrintAndLog("Invalid char on input");
476 return 0;
477 }
478 if (crc) datalen=AddCrc(data,datalen);
479
480 c.arg[0]=datalen;
481 c.arg[1]=fast;
482 c.arg[2]=reply;
483 memcpy(c.d.asBytes,data,datalen);
484
485 SendCommand(&c);
486
487 if (reply) {
488 r=WaitForResponseTimeout(CMD_ACK,1000);
489
490 if (r!=NULL) {
491 recv = r->d.asBytes;
492 PrintAndLog("received %i octets",r->arg[0]);
493 // TODO: output
494 } else {
495 PrintAndLog("timeout while waiting for reply.");
496 }
497
498 } // if reply
499 return 0;
500 }
501
502
503 int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
504 int temp;
505 uint8_t *req=c->d.asBytes, uid[8];
506 uint32_t reqlen=0;
507
508 // strip
509 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
510
511 if (strstr(*cmd,"-2")==*cmd) {
512 c->arg[1]=0; // quse 1of256
513 (*cmd)+=2;
514 }
515
516 // strip
517 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
518
519 if (strstr(*cmd,"-o")==*cmd) {
520 req[reqlen]=ISO15_REQ_OPTION;
521 (*cmd)+=2;
522 }
523
524 // strip
525 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
526
527 switch (**cmd) {
528 case 0:
529 PrintAndLog("missing addr");
530 return 0;
531 break;
532 case 's':
533 case 'S':
534 // you must have selected the tag earlier
535 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
536 ISO15_REQ_NONINVENTORY | ISO15_REQ_SELECT;
537 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
538 reqlen+=iso15cmdlen;
539 break;
540 case 'u':
541 case 'U':
542 // unaddressed mode may not be supported by all vendors
543 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
544 ISO15_REQ_NONINVENTORY;
545 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
546 reqlen+=iso15cmdlen;
547 break;
548 case '*':
549 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
550 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
551 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
552 reqlen+=iso15cmdlen;
553 if (!getUID(uid)) {
554 PrintAndLog("No Tag found");
555 return 0;
556 }
557 memcpy(req+reqlen,uid,8);
558 PrintAndLog("Detected UID %s",sprintUID(NULL,uid));
559 reqlen+=8;
560 break;
561 default:
562 req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
563 ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
564 memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen);
565 reqlen+=iso15cmdlen;
566
567 /* sscanf(cmd,"%hX%hX%hX%hX%hX%hX%hX%hX",
568 (short unsigned int *)&uid[7],(short unsigned int *)&uid[6],
569 (short unsigned int *)&uid[5],(short unsigned int *)&uid[4],
570 (short unsigned int *)&uid[3],(short unsigned int *)&uid[2],
571 (short unsigned int *)&uid[1],(short unsigned int *)&uid[0]); */
572 for (int i=0;i<8 && (*cmd)[i*2] && (*cmd)[i*2+1];i++) { // parse UID
573 sscanf((char[]){(*cmd)[i*2],(*cmd)[i*2+1],0},"%X",&temp);
574 uid[7-i]=temp&0xff;
575 }
576
577 PrintAndLog("Using UID %s",sprintUID(NULL,uid));
578 memcpy(&req[reqlen],&uid[0],8);
579 reqlen+=8;
580 }
581 // skip to next space
582 while (**cmd!=' ' && **cmd!='\t') (*cmd)++;
583 // skip over the space
584 while (**cmd==' ' || **cmd=='\t') (*cmd)++;
585
586 c->arg[0]=reqlen;
587 return 1;
588 }
589
590
591
592 int CmdHF15CmdRead(const char *Cmd) {
593 UsbCommand *r;
594 uint8_t *recv;
595 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
596 uint8_t *req=c.d.asBytes;
597 int reqlen=0, pagenum;
598 char cmdbuf[100];
599 char *cmd=cmdbuf;
600 char output[100]="";
601
602 strncpy(cmd,Cmd,99);
603
604 // usage:
605 if (strlen(cmd)<3) {
606 PrintAndLog("Usage: hf 15 cmd read [options] <uid|s|*> <page#>");
607 PrintAndLog(" options:");
608 PrintAndLog(" -2 use slower '1 out of 256' mode");
609 PrintAndLog(" uid (either): ");
610 PrintAndLog(" <8B hex> full UID eg E011223344556677");
611 PrintAndLog(" s selected tag");
612 PrintAndLog(" u unaddressed mode");
613 PrintAndLog(" * scan for tag");
614 PrintAndLog(" page#: page number 0-255");
615 return 0;
616 }
617
618 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_READ},1);
619 reqlen=c.arg[0];
620
621 pagenum=strtol(cmd,NULL,0);
622 /*if (pagenum<0) {
623 PrintAndLog("invalid pagenum");
624 return 0;
625 } */
626
627 req[reqlen++]=(uint8_t)pagenum;
628
629 reqlen=AddCrc(req,reqlen);
630
631 c.arg[0]=reqlen;
632
633 SendCommand(&c);
634
635 r=WaitForResponseTimeout(CMD_ACK,1000);
636
637 if (r!=NULL && r->arg[0]>2) {
638 recv = r->d.asBytes;
639 if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
640 if (!(recv[0] & ISO15_RES_ERROR)) {
641 *output=0; // reset outputstring
642 //sprintf(output, "Block %2i ",blocknum);
643 for ( int i=1; i<r->arg[0]-2; i++) {
644 sprintf(output+strlen(output),"%02hX ",recv[i]);
645 }
646 strcat(output," ");
647 for ( int i=2; i<r->arg[0]-2; i++) {
648 sprintf(output+strlen(output),"%c",recv[i]>31 || recv[i]<127?recv[i]:'.');
649 }
650 PrintAndLog("%s",output);
651 } else {
652 PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
653 }
654 } else {
655 PrintAndLog("CRC failed");
656 }
657 } else {
658 PrintAndLog("no answer");
659 }
660
661 return 0;
662 }
663
664
665 int CmdHF15CmdWrite(const char *Cmd) {
666 UsbCommand *r;
667 uint8_t *recv;
668 UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
669 uint8_t *req=c.d.asBytes;
670 int reqlen=0, pagenum, temp;
671 char cmdbuf[100];
672 char *cmd=cmdbuf;
673 char *cmd2;
674
675 strncpy(cmd,Cmd,99);
676
677 // usage:
678 if (strlen(cmd)<3) {
679 PrintAndLog("Usage: hf 15 cmd write [options] <uid|s|*> <page#> <hexdata>");
680 PrintAndLog(" options:");
681 PrintAndLog(" -2 use slower '1 out of 256' mode");
682 PrintAndLog(" -o set OPTION Flag (needed for TI)");
683 PrintAndLog(" uid (either): ");
684 PrintAndLog(" <8B hex> full UID eg E011223344556677");
685 PrintAndLog(" s selected tag");
686 PrintAndLog(" u unaddressed mode");
687 PrintAndLog(" * scan for tag");
688 PrintAndLog(" page#: page number 0-255");
689 PrintAndLog(" hexdata: data to be written eg AA BB CC DD");
690 return 0;
691 }
692
693 prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_WRITE},1);
694 reqlen=c.arg[0];
695
696 // *cmd -> page num ; *cmd2 -> data
697 cmd2=cmd;
698 while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++;
699 *cmd2=0;
700 cmd2++;
701
702 pagenum=strtol(cmd,NULL,0);
703 /*if (pagenum<0) {
704 PrintAndLog("invalid pagenum");
705 return 0;
706 } */
707 req[reqlen++]=(uint8_t)pagenum;
708
709
710 while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars
711 if (*cmd2==' ') {
712 cmd2++;
713 continue;
714 }
715 sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp);
716 req[reqlen++]=temp & 0xff;
717 cmd2+=2;
718 }
719
720 reqlen=AddCrc(req,reqlen);
721
722 c.arg[0]=reqlen;
723
724 SendCommand(&c);
725
726 r=WaitForResponseTimeout(CMD_ACK,2000);
727
728 if (r!=NULL && r->arg[0]>2) {
729 recv = r->d.asBytes;
730 if (ISO15_CRC_CHECK==Crc(recv,r->arg[0])) {
731 if (!(recv[0] & ISO15_RES_ERROR)) {
732 PrintAndLog("OK");
733 } else {
734 PrintAndLog("Tag returned Error %i: %s",recv[0],TagErrorStr(recv[0]));
735 }
736 } else {
737 PrintAndLog("CRC failed");
738 }
739 } else {
740 PrintAndLog("no answer");
741 }
742
743 return 0;
744 }
745
746
747
748 static command_t CommandTable15Cmd[] =
749 {
750 {"help", CmdHF15CmdHelp, 1, "This Help"},
751 {"inquiry", CmdHF15CmdInquiry, 0, "Search for tags in range"},
752 /*
753 {"select", CmdHF15CmdSelect, 0, "Select an tag with a specific UID for further commands"},
754 */
755 {"read", CmdHF15CmdRead, 0, "Read a block"},
756 {"write", CmdHF15CmdWrite, 0, "Write a block"},
757 /*
758 {"readmulti",CmdHF15CmdReadmulti, 0, "Reads multiple Blocks"},
759 */
760 {"raw", CmdHF15CmdRaw, 0, "Send raw hex data to tag"},
761 {"debug", CmdHF15CmdDebug, 0, "Turn debugging on/off"},
762 {NULL, NULL, 0, NULL}
763 };
764
765 int CmdHF15Cmd(const char *Cmd)
766 {
767 CmdsParse(CommandTable15Cmd, Cmd);
768 return 0;
769 }
770
771 int CmdHF15CmdHelp(const char *Cmd)
772 {
773 CmdsHelp(CommandTable15Cmd);
774 return 0;
775 }
776
Impressum, Datenschutz