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