]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso15693.c
CHG: `lf em` - some minor refactoring in 4x50 commands
[proxmark3-svn] / armsrc / iso15693.c
CommitLineData
15c4dc5a 1//-----------------------------------------------------------------------------
bd20f8f4 2// Jonathan Westhues, split Nov 2006
3// Modified by Greg Jones, Jan 2009
e6304bca 4// Modified by Adrian Dabrowski "atrox", Mar-Sept 2010,Oct 2011
bd20f8f4 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//-----------------------------------------------------------------------------
15c4dc5a 10// Routines to support ISO 15693. This includes both the reader software and
11// the `fake tag' modes, but at the moment I've implemented only the reader
12// stuff, and that barely.
bd20f8f4 13// Modified to perform modulation onboard in arm rather than on PC
15c4dc5a 14// Also added additional reader commands (SELECT, READ etc.)
15c4dc5a 15//-----------------------------------------------------------------------------
9455b51c 16// The ISO 15693 describes two transmission modes from reader to tag, and 4
17// transmission modes from tag to reader. As of Mar 2010 this code only
18// supports one of each: "1of4" mode from reader to tag, and the highspeed
19// variant with one subcarrier from card to reader.
20// As long, as the card fully support ISO 15693 this is no problem, since the
21// reader chooses both data rates, but some non-standard tags do not. Further for
22// the simulation to work, we will need to support all data rates.
23//
24// VCD (reader) -> VICC (tag)
25// 1 out of 256:
26// data rate: 1,66 kbit/s (fc/8192)
27// used for long range
28// 1 out of 4:
29// data rate: 26,48 kbit/s (fc/512)
30// used for short range, high speed
31//
32// VICC (tag) -> VCD (reader)
33// Modulation:
34// ASK / one subcarrier (423,75 khz)
35// FSK / two subcarriers (423,75 khz && 484,28 khz)
36// Data Rates / Modes:
37// low ASK: 6,62 kbit/s
38// low FSK: 6.67 kbit/s
39// high ASK: 26,48 kbit/s
40// high FSK: 26,69 kbit/s
41//-----------------------------------------------------------------------------
42// added "1 out of 256" mode (for VCD->PICC) - atrox 20100911
43
44
45// Random Remarks:
46// *) UID is always used "transmission order" (LSB), which is reverse to display order
47
48// TODO / BUGS / ISSUES:
49// *) writing to tags takes longer: we miss the answer from the tag in most cases
50// -> tweak the read-timeout times
51// *) signal decoding from the card is still a bit shaky.
52// *) signal decoding is unable to detect collissions.
53// *) add anti-collission support for inventory-commands
e6304bca 54// *) read security status of a block
9455b51c 55// *) sniffing and simulation do only support one transmission mode. need to support
56// all 8 transmission combinations
57// *) remove or refactor code under "depricated"
58// *) document all the functions
59
bd20f8f4 60
e30c654b 61#include "proxmark3.h"
f7e3ed82 62#include "util.h"
15c4dc5a 63#include "apps.h"
9ab7a6c7 64#include "string.h"
9455b51c 65#include "iso15693tools.h"
902cb3c0 66#include "cmd.h"
15c4dc5a 67
9455b51c 68///////////////////////////////////////////////////////////////////////
69// ISO 15693 Part 2 - Air Interface
70// This section basicly contains transmission and receiving of bits
71///////////////////////////////////////////////////////////////////////
72
73#define FrameSOF Iso15693FrameSOF
74#define Logic0 Iso15693Logic0
75#define Logic1 Iso15693Logic1
76#define FrameEOF Iso15693FrameEOF
15c4dc5a 77
9455b51c 78#define Crc(data,datalen) Iso15693Crc(data,datalen)
79#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
80#define sprintUID(target,uid) Iso15693sprintUID(target,uid)
15c4dc5a 81
6b23be6b 82int DEBUG = 0;
9455b51c 83
84
85// ---------------------------
86// Signal Processing
87// ---------------------------
88
89// prepare data using "1 out of 4" code for later transmission
90// resulting data rate is 26,48 kbit/s (fc/512)
91// cmd ... data
92// n ... length of data
f7e3ed82 93static void CodeIso15693AsReader(uint8_t *cmd, int n)
15c4dc5a 94{
95 int i, j;
96
97 ToSendReset();
98
99 // Give it a bit of slack at the beginning
6b23be6b 100 for(i = 0; i < 24; i++)
15c4dc5a 101 ToSendStuffBit(1);
15c4dc5a 102
9455b51c 103 // SOF for 1of4
15c4dc5a 104 ToSendStuffBit(0);
105 ToSendStuffBit(1);
106 ToSendStuffBit(1);
107 ToSendStuffBit(1);
108 ToSendStuffBit(1);
109 ToSendStuffBit(0);
110 ToSendStuffBit(1);
111 ToSendStuffBit(1);
112 for(i = 0; i < n; i++) {
113 for(j = 0; j < 8; j += 2) {
114 int these = (cmd[i] >> j) & 3;
115 switch(these) {
116 case 0:
117 ToSendStuffBit(1);
118 ToSendStuffBit(0);
119 ToSendStuffBit(1);
120 ToSendStuffBit(1);
121 ToSendStuffBit(1);
122 ToSendStuffBit(1);
123 ToSendStuffBit(1);
124 ToSendStuffBit(1);
125 break;
126 case 1:
127 ToSendStuffBit(1);
128 ToSendStuffBit(1);
129 ToSendStuffBit(1);
130 ToSendStuffBit(0);
131 ToSendStuffBit(1);
132 ToSendStuffBit(1);
133 ToSendStuffBit(1);
134 ToSendStuffBit(1);
135 break;
136 case 2:
137 ToSendStuffBit(1);
138 ToSendStuffBit(1);
139 ToSendStuffBit(1);
140 ToSendStuffBit(1);
141 ToSendStuffBit(1);
142 ToSendStuffBit(0);
143 ToSendStuffBit(1);
144 ToSendStuffBit(1);
145 break;
146 case 3:
147 ToSendStuffBit(1);
148 ToSendStuffBit(1);
149 ToSendStuffBit(1);
150 ToSendStuffBit(1);
151 ToSendStuffBit(1);
152 ToSendStuffBit(1);
153 ToSendStuffBit(1);
154 ToSendStuffBit(0);
155 break;
156 }
157 }
158 }
9455b51c 159 // EOF
15c4dc5a 160 ToSendStuffBit(1);
161 ToSendStuffBit(1);
162 ToSendStuffBit(0);
163 ToSendStuffBit(1);
164
165 // And slack at the end, too.
6b23be6b 166 for(i = 0; i < 24; i++)
15c4dc5a 167 ToSendStuffBit(1);
15c4dc5a 168}
169
9455b51c 170// encode data using "1 out of 256" sheme
171// data rate is 1,66 kbit/s (fc/8192)
172// is designed for more robust communication over longer distances
173static void CodeIso15693AsReader256(uint8_t *cmd, int n)
15c4dc5a 174{
15c4dc5a 175 int i, j;
176
9455b51c 177 ToSendReset();
178
179 // Give it a bit of slack at the beginning
6b23be6b 180 for(i = 0; i < 24; i++)
9455b51c 181 ToSendStuffBit(1);
9455b51c 182
183 // SOF for 1of256
184 ToSendStuffBit(0);
185 ToSendStuffBit(1);
186 ToSendStuffBit(1);
187 ToSendStuffBit(1);
188 ToSendStuffBit(1);
189 ToSendStuffBit(1);
190 ToSendStuffBit(1);
191 ToSendStuffBit(0);
192
15c4dc5a 193 for(i = 0; i < n; i++) {
6b23be6b 194 for (j = 0; j <= 255; j++) {
195 if (cmd[i] == j) {
9455b51c 196 ToSendStuffBit(1);
197 ToSendStuffBit(0);
15c4dc5a 198 } else {
9455b51c 199 ToSendStuffBit(1);
200 ToSendStuffBit(1);
201 }
202 }
15c4dc5a 203 }
9455b51c 204 // EOF
205 ToSendStuffBit(1);
206 ToSendStuffBit(1);
207 ToSendStuffBit(0);
208 ToSendStuffBit(1);
15c4dc5a 209
9455b51c 210 // And slack at the end, too.
6b23be6b 211 for(i = 0; i < 24; i++)
9455b51c 212 ToSendStuffBit(1);
15c4dc5a 213}
214
9455b51c 215
15c4dc5a 216// Transmit the command (to the tag) that was placed in ToSend[].
f7e3ed82 217static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 218{
219 int c;
1b4a446a 220 volatile uint32_t r;
15c4dc5a 221 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
222 if(*wait < 10) { *wait = 10; }
223
224// for(c = 0; c < *wait;) {
225// if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
226// AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
1b4a446a 227// ++c;
15c4dc5a 228// }
229// if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
1b4a446a 230// r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 231// (void)r;
232// }
233// WDT_HIT();
234// }
235
236 c = 0;
237 for(;;) {
238 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
239 AT91C_BASE_SSC->SSC_THR = cmd[c];
1b4a446a 240 if( ++c >= len) break;
15c4dc5a 241 }
242 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
1b4a446a 243 r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 244 (void)r;
245 }
246 WDT_HIT();
247 }
248 *samples = (c + *wait) << 3;
249}
250
251//-----------------------------------------------------------------------------
252// Transmit the command (to the reader) that was placed in ToSend[].
253//-----------------------------------------------------------------------------
f7e3ed82 254static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait)
15c4dc5a 255{
3fe4ff4f 256 int c = 0;
1b4a446a 257 volatile uint32_t r;
3fe4ff4f 258 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K);
15c4dc5a 259 if(*wait < 10) { *wait = 10; }
260
15c4dc5a 261 for(;;) {
262 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
263 AT91C_BASE_SSC->SSC_THR = cmd[c];
1b4a446a 264 if( ++c >= len) break;
15c4dc5a 265 }
266 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
1b4a446a 267 r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 268 (void)r;
269 }
270 WDT_HIT();
271 }
272 *samples = (c + *wait) << 3;
273}
274
9455b51c 275
276// Read from Tag
277// Parameters:
278// receivedResponse
279// maxLen
280// samples
281// elapsed
282// returns:
283// number of decoded bytes
f7e3ed82 284static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 285{
117d9ec2 286 uint8_t *dest = BigBuf_get_addr();
15c4dc5a 287
6b23be6b 288 int c = 0, getNext = FALSE;
f7e3ed82 289 int8_t prev = 0;
15c4dc5a 290
15c4dc5a 291 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
f2c2b174 292 SpinDelay(100); // greg - experiment to get rid of some of the 0 byte/failed reads
293
15c4dc5a 294 for(;;) {
f2c2b174 295 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
15c4dc5a 296 AT91C_BASE_SSC->SSC_THR = 0x43;
f2c2b174 297
15c4dc5a 298 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
f7e3ed82 299 int8_t b;
300 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 301
302 // The samples are correlations against I and Q versions of the
303 // tone that the tag AM-modulates, so every other sample is I,
304 // every other is Q. We just want power, so abs(I) + abs(Q) is
305 // close to what we want.
6b23be6b 306 // iceman 2016, amplitude sqrt(abs(i) + abs(q))
15c4dc5a 307 if(getNext) {
6b23be6b 308 dest[c++] = (uint8_t)ABS(b) + ABS(prev);
15c4dc5a 309
6b23be6b 310 if(c >= 2000)
15c4dc5a 311 break;
15c4dc5a 312 } else {
313 prev = b;
314 }
315
316 getNext = !getNext;
317 }
318 }
319
9455b51c 320 //////////////////////////////////////////
321 /////////// DEMODULATE ///////////////////
322 //////////////////////////////////////////
15c4dc5a 323
324 int i, j;
6b23be6b 325 int max = 0, maxPos=0, skip = 4;
326 int k = 0; // this will be our return value
327
9455b51c 328 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
15c4dc5a 329
330 // First, correlate for SOF
331 for(i = 0; i < 100; i++) {
332 int corr = 0;
6b23be6b 333 for(j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
334 corr += FrameSOF[j] * dest[i+(j/skip)];
15c4dc5a 335 }
336 if(corr > max) {
337 max = corr;
338 maxPos = i;
339 }
340 }
6b23be6b 341 // DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip));
15c4dc5a 342
343 // greg - If correlation is less than 1 then there's little point in continuing
6b23be6b 344 if ((max/(ARRAYLEN(FrameSOF)/skip)) >= 1)
15c4dc5a 345 {
6b23be6b 346 i = maxPos + ARRAYLEN(FrameSOF) / skip;
9455b51c 347
348 uint8_t outBuf[20];
349 memset(outBuf, 0, sizeof(outBuf));
350 uint8_t mask = 0x01;
351 for(;;) {
352 int corr0 = 0, corr1 = 0, corrEOF = 0;
6b23be6b 353 for(j = 0; j < ARRAYLEN(Logic0); j += skip) {
354 corr0 += Logic0[j] * dest[i+(j/skip)];
9455b51c 355 }
6b23be6b 356 for(j = 0; j < ARRAYLEN(Logic1); j += skip) {
357 corr1 += Logic1[j] * dest[i+(j/skip)];
9455b51c 358 }
6b23be6b 359 for(j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
360 corrEOF += FrameEOF[j] * dest[i+(j/skip)];
9455b51c 361 }
362 // Even things out by the length of the target waveform.
363 corr0 *= 4;
364 corr1 *= 4;
365
366 if(corrEOF > corr1 && corrEOF > corr0) {
367 // DbpString("EOF at %d", i);
368 break;
369 } else if(corr1 > corr0) {
6b23be6b 370 i += ARRAYLEN(Logic1)/skip;
9455b51c 371 outBuf[k] |= mask;
372 } else {
6b23be6b 373 i += ARRAYLEN(Logic0)/skip;
9455b51c 374 }
375 mask <<= 1;
376 if(mask == 0) {
377 k++;
378 mask = 0x01;
379 }
6b23be6b 380 if( ( i + (int)ARRAYLEN(FrameEOF)) >= 2000) {
9455b51c 381 DbpString("ran off end!");
382 break;
383 }
15c4dc5a 384 }
9455b51c 385 if(mask != 0x01) { // this happens, when we miss the EOF
386 // TODO: for some reason this happens quite often
387 if (DEBUG) Dbprintf("error, uneven octet! (extra bits!) mask=%02x", mask);
6b23be6b 388 if (mask < 0x08) k--; // discard the last uneven octet;
9455b51c 389 // 0x08 is an assumption - but works quite often
15c4dc5a 390 }
9455b51c 391 // uint8_t str1 [8];
392 // itoa(k,str1);
393 // strncat(str1," octets read",8);
394
395 // DbpString( str1); // DbpString("%d octets", k);
396
397 // for(i = 0; i < k; i+=3) {
398 // //DbpString("# %2d: %02x ", i, outBuf[i]);
399 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
400 // }
401
402 for(i = 0; i < k; i++) {
403 receivedResponse[i] = outBuf[i];
15c4dc5a 404 }
6b23be6b 405 } // "end if correlation > 0" (max/(ARRAYLEN(FrameSOF)/skip))
15c4dc5a 406 return k; // return the number of bytes demodulated
15c4dc5a 407}
408
9455b51c 409
15c4dc5a 410// Now the GetISO15693 message from sniffing command
f7e3ed82 411static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 412{
117d9ec2 413 uint8_t *dest = BigBuf_get_addr();
15c4dc5a 414
6b23be6b 415 int c = 0, getNext = FALSE;
f7e3ed82 416 int8_t prev = 0;
15c4dc5a 417
15c4dc5a 418 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
f2c2b174 419 SpinDelay(100); // greg - experiment to get rid of some of the 0 byte/failed reads
420
15c4dc5a 421 for(;;) {
f2c2b174 422 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
15c4dc5a 423 AT91C_BASE_SSC->SSC_THR = 0x43;
f2c2b174 424
15c4dc5a 425 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
3fe4ff4f 426 int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 427
428 // The samples are correlations against I and Q versions of the
429 // tone that the tag AM-modulates, so every other sample is I,
430 // every other is Q. We just want power, so abs(I) + abs(Q) is
431 // close to what we want.
432 if(getNext) {
6b23be6b 433 dest[c++] = (uint8_t)ABS(b) + ABS(prev);
15c4dc5a 434
6b23be6b 435 if(c >= 20000)
15c4dc5a 436 break;
15c4dc5a 437 } else {
438 prev = b;
439 }
15c4dc5a 440 getNext = !getNext;
441 }
442 }
443
9455b51c 444 //////////////////////////////////////////
445 /////////// DEMODULATE ///////////////////
446 //////////////////////////////////////////
15c4dc5a 447
6b23be6b 448 int i, j, max = 0, maxPos=0, skip = 4;
15c4dc5a 449
450 // First, correlate for SOF
451 for(i = 0; i < 19000; i++) {
452 int corr = 0;
6b23be6b 453 for(j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
15c4dc5a 454 corr += FrameSOF[j]*dest[i+(j/skip)];
455 }
456 if(corr > max) {
457 max = corr;
458 maxPos = i;
459 }
460 }
6b23be6b 461// DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip));
15c4dc5a 462
463 int k = 0; // this will be our return value
464
465 // greg - If correlation is less than 1 then there's little point in continuing
6b23be6b 466 if ((max/(ARRAYLEN(FrameSOF)/skip)) >= 1) // THIS SHOULD BE 1
15c4dc5a 467 {
9455b51c 468
6b23be6b 469 i = maxPos + ARRAYLEN(FrameSOF)/skip;
9455b51c 470
471 uint8_t outBuf[20];
472 memset(outBuf, 0, sizeof(outBuf));
473 uint8_t mask = 0x01;
474 for(;;) {
475 int corr0 = 0, corr1 = 0, corrEOF = 0;
6b23be6b 476 for(j = 0; j < ARRAYLEN(Logic0); j += skip) {
9455b51c 477 corr0 += Logic0[j]*dest[i+(j/skip)];
478 }
6b23be6b 479 for(j = 0; j < ARRAYLEN(Logic1); j += skip) {
9455b51c 480 corr1 += Logic1[j]*dest[i+(j/skip)];
481 }
6b23be6b 482 for(j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
9455b51c 483 corrEOF += FrameEOF[j]*dest[i+(j/skip)];
484 }
485 // Even things out by the length of the target waveform.
486 corr0 *= 4;
487 corr1 *= 4;
488
489 if(corrEOF > corr1 && corrEOF > corr0) {
490 // DbpString("EOF at %d", i);
491 break;
492 } else if(corr1 > corr0) {
6b23be6b 493 i += ARRAYLEN(Logic1)/skip;
9455b51c 494 outBuf[k] |= mask;
495 } else {
6b23be6b 496 i += ARRAYLEN(Logic0)/skip;
9455b51c 497 }
498 mask <<= 1;
499 if(mask == 0) {
500 k++;
501 mask = 0x01;
502 }
6b23be6b 503 if((i+(int)ARRAYLEN(FrameEOF)) >= 2000) {
9455b51c 504 DbpString("ran off end!");
505 break;
506 }
15c4dc5a 507 }
9455b51c 508 if(mask != 0x01) {
509 DbpString("sniff: error, uneven octet! (discard extra bits!)");
6b23be6b 510 // DbpString(" mask=%02x", mask);
15c4dc5a 511 }
9455b51c 512 // uint8_t str1 [8];
513 // itoa(k,str1);
514 // strncat(str1," octets read",8);
515
516 // DbpString( str1); // DbpString("%d octets", k);
517
518 // for(i = 0; i < k; i+=3) {
519 // //DbpString("# %2d: %02x ", i, outBuf[i]);
520 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
521 // }
522
523 for(i = 0; i < k; i++) {
524 receivedResponse[i] = outBuf[i];
15c4dc5a 525 }
6b23be6b 526 } // "end if correlation > 0" (max/(ARRAYLEN(FrameSOF)/skip))
15c4dc5a 527 return k; // return the number of bytes demodulated
15c4dc5a 528}
529
9455b51c 530
531static void BuildIdentifyRequest(void);
15c4dc5a 532//-----------------------------------------------------------------------------
533// Start to read an ISO 15693 tag. We send an identify request, then wait
534// for the response. The response is not demodulated, just left in the buffer
535// so that it can be downloaded to a PC and processed there.
536//-----------------------------------------------------------------------------
537void AcquireRawAdcSamplesIso15693(void)
538{
1b4a446a 539 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
15c4dc5a 540
6b23be6b 541 int c = 0, getNext = FALSE;
f7e3ed82 542 int8_t prev = 0;
1b4a446a 543 volatile uint32_t r;
15c4dc5a 544
1b4a446a 545 uint8_t *dest = BigBuf_get_addr();
15c4dc5a 546 BuildIdentifyRequest();
547
548 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
549
550 // Give the tags time to energize
551 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
552 SpinDelay(100);
553
554 // Now send the command
555 FpgaSetupSsc();
556 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
557
558 c = 0;
559 for(;;) {
560 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
561 AT91C_BASE_SSC->SSC_THR = ToSend[c];
1b4a446a 562 if( ++c == ToSendMax+3) break;
15c4dc5a 563 }
564 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
1b4a446a 565 r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 566 (void)r;
567 }
568 WDT_HIT();
569 }
570
571 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
572
573 c = 0;
15c4dc5a 574 for(;;) {
1b4a446a 575 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
15c4dc5a 576 AT91C_BASE_SSC->SSC_THR = 0x43;
1b4a446a 577
15c4dc5a 578 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
6b23be6b 579
580 int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 581
9455b51c 582 // The samples are correlations against I and Q versions of the
583 // tone that the tag AM-modulates, so every other sample is I,
584 // every other is Q. We just want power, so abs(I) + abs(Q) is
585 // close to what we want.
586 if(getNext) {
1b4a446a 587
588 dest[c++] = (uint8_t)(ABS(b) + ABS(prev));
9455b51c 589
1b4a446a 590 if(c >= 2000) break;
591
9455b51c 592 } else {
593 prev = b;
594 }
9455b51c 595 getNext = !getNext;
596 }
597 }
598}
599
600
601void RecordRawAdcSamplesIso15693(void)
602{
117d9ec2 603 uint8_t *dest = BigBuf_get_addr();
3fe4ff4f 604
6b23be6b 605 int c = 0, getNext = FALSE;
9455b51c 606 int8_t prev = 0;
607
7cc204bf 608 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
9455b51c 609 // Setup SSC
610 FpgaSetupSsc();
611
612 // Start from off (no field generated)
5ee53a0e 613 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
614 SpinDelay(200);
9455b51c 615
616 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
9455b51c 617 SpinDelay(100);
618
619 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
620
9455b51c 621 for(;;) {
622 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
623 AT91C_BASE_SSC->SSC_THR = 0x43;
624 }
625 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
626 int8_t b;
627 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
628
629 // The samples are correlations against I and Q versions of the
630 // tone that the tag AM-modulates, so every other sample is I,
631 // every other is Q. We just want power, so abs(I) + abs(Q) is
632 // close to what we want.
633 if(getNext) {
6b23be6b 634 dest[c++] = (uint8_t) ABS(b) + ABS(prev);
9455b51c 635
6b23be6b 636 if(c >= 7000)
9455b51c 637 break;
9455b51c 638 } else {
639 prev = b;
640 }
641
642 getNext = !getNext;
643 WDT_HIT();
644 }
645 }
646 Dbprintf("fin record");
647}
648
649
650// Initialize the proxmark as iso15k reader
e6304bca 651// (this might produces glitches that confuse some tags
9455b51c 652void Iso15693InitReader() {
653 LED_A_ON();
654 LED_B_ON();
655 LED_C_OFF();
656 LED_D_OFF();
657
7cc204bf 658 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
9455b51c 659 // Setup SSC
e6304bca 660 // FpgaSetupSsc();
9455b51c 661
662 // Start from off (no field generated)
663 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
e6304bca 664 SpinDelay(10);
9455b51c 665
666 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
667 FpgaSetupSsc();
668
669 // Give the tags time to energize
670 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
e6304bca 671 SpinDelay(250);
9455b51c 672
673 LED_A_ON();
674 LED_B_OFF();
675 LED_C_OFF();
676 LED_D_OFF();
677}
678
679///////////////////////////////////////////////////////////////////////
680// ISO 15693 Part 3 - Air Interface
681// This section basicly contains transmission and receiving of bits
682///////////////////////////////////////////////////////////////////////
683
684// Encode (into the ToSend buffers) an identify request, which is the first
685// thing that you must send to a tag to get a response.
686static void BuildIdentifyRequest(void)
687{
6b23be6b 688 uint8_t cmd[5] = {0,1,0,0,0};
9455b51c 689 uint16_t crc;
690 // one sub-carrier, inventory, 1 slot, fast rate
691 // AFI is at bit 5 (1<<4) when doing an INVENTORY
692 cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);
693 // inventory command code
694 cmd[1] = 0x01;
695 // no mask
696 cmd[2] = 0x00;
697 //Now the CRC
698 crc = Crc(cmd, 3);
699 cmd[3] = crc & 0xff;
700 cmd[4] = crc >> 8;
701
702 CodeIso15693AsReader(cmd, sizeof(cmd));
703}
704
705// uid is in transmission order (which is reverse of display order)
706static void BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
707{
6b23be6b 708 uint8_t cmd[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
9455b51c 709 uint16_t crc;
710 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
711 // followed by teh block data
712 // one sub-carrier, inventory, 1 slot, fast rate
713 cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit, ADDR bit, OPTION bit
714 // READ BLOCK command code
715 cmd[1] = 0x20;
716 // UID may be optionally specified here
717 // 64-bit UID
718 cmd[2] = uid[0];
719 cmd[3] = uid[1];
720 cmd[4] = uid[2];
721 cmd[5] = uid[3];
722 cmd[6] = uid[4];
723 cmd[7] = uid[5];
724 cmd[8] = uid[6];
725 cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique)
726 // Block number to read
727 cmd[10] = blockNumber;//0x00;
728 //Now the CRC
729 crc = Crc(cmd, 11); // the crc needs to be calculated over 12 bytes
730 cmd[11] = crc & 0xff;
731 cmd[12] = crc >> 8;
732
733 CodeIso15693AsReader(cmd, sizeof(cmd));
734}
735
736// Now the VICC>VCD responses when we are simulating a tag
3fe4ff4f 737 static void BuildInventoryResponse( uint8_t *uid)
9455b51c 738{
6b23be6b 739 uint8_t cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
9455b51c 740 uint16_t crc;
741 // one sub-carrier, inventory, 1 slot, fast rate
742 // AFI is at bit 5 (1<<4) when doing an INVENTORY
3fe4ff4f 743 //(1 << 2) | (1 << 5) | (1 << 1);
744 cmd[0] = 0; //
745 cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
9455b51c 746 // 64-bit UID
3fe4ff4f 747 cmd[2] = uid[7]; //0x32;
748 cmd[3] = uid[6]; //0x4b;
749 cmd[4] = uid[5]; //0x03;
750 cmd[5] = uid[4]; //0x01;
751 cmd[6] = uid[3]; //0x00;
752 cmd[7] = uid[2]; //0x10;
753 cmd[8] = uid[1]; //0x05;
754 cmd[9] = uid[0]; //0xe0;
9455b51c 755 //Now the CRC
756 crc = Crc(cmd, 10);
757 cmd[10] = crc & 0xff;
758 cmd[11] = crc >> 8;
759
760 CodeIso15693AsReader(cmd, sizeof(cmd));
761}
762
e6304bca 763// Universal Method for sending to and recv bytes from a tag
9455b51c 764// init ... should we initialize the reader?
765// speed ... 0 low speed, 1 hi speed
766// **recv will return you a pointer to the received data
767// If you do not need the answer use NULL for *recv[]
768// return: lenght of received data
769int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv) {
770
6b23be6b 771 int samples = 0, tsamples = 0;
772 int wait = 0, elapsed = 0;
773 int answerLen = 0;
9455b51c 774
6b23be6b 775 LED_A_ON(); LED_B_ON();
776
777 LED_C_OFF(); LED_D_OFF();
9455b51c 778
99cf19d9 779 if (init) Iso15693InitReader();
780
6b23be6b 781 // answer is 100bytes long?
782 uint8_t *answer = BigBuf_malloc(100);
117d9ec2 783 if (recv != NULL) memset(answer, 0, 100);
9455b51c 784
9455b51c 785 if (!speed) {
786 // low speed (1 out of 256)
787 CodeIso15693AsReader256(send, sendlen);
788 } else {
789 // high speed (1 out of 4)
790 CodeIso15693AsReader(send, sendlen);
791 }
792
793 LED_A_ON();
794 LED_B_OFF();
795
6b23be6b 796 TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait);
9455b51c 797 // Now wait for a response
798 if (recv!=NULL) {
799 LED_A_OFF();
800 LED_B_ON();
801 answerLen = GetIso15693AnswerFromTag(answer, 100, &samples, &elapsed) ;
6b23be6b 802 *recv = answer;
9455b51c 803 }
804
4a71da5a 805 LEDsoff();
9455b51c 806 return answerLen;
807}
15c4dc5a 808
15c4dc5a 809
9455b51c 810// --------------------------------------------------------------------
811// Debug Functions
812// --------------------------------------------------------------------
15c4dc5a 813
9455b51c 814// Decodes a message from a tag and displays its metadata and content
815#define DBD15STATLEN 48
816void DbdecodeIso15693Answer(int len, uint8_t *d) {
6b23be6b 817 char status[DBD15STATLEN+1] = {0};
9455b51c 818 uint16_t crc;
819
6b23be6b 820 if (len > 3) {
821 if (d[0] & ( 1 << 3 ))
822 strncat(status, "ProtExt ", DBD15STATLEN);
823 if (d[0] & 1) {
9455b51c 824 // error
6b23be6b 825 strncat(status, "Error ", DBD15STATLEN);
9455b51c 826 switch (d[1]) {
827 case 0x01:
6b23be6b 828 strncat(status, "01:notSupp", DBD15STATLEN);
15c4dc5a 829 break;
9455b51c 830 case 0x02:
6b23be6b 831 strncat(status, "02:notRecog", DBD15STATLEN);
9455b51c 832 break;
833 case 0x03:
6b23be6b 834 strncat(status, "03:optNotSupp", DBD15STATLEN);
9455b51c 835 break;
836 case 0x0f:
6b23be6b 837 strncat(status, "0f:noInfo", DBD15STATLEN);
9455b51c 838 break;
839 case 0x10:
6b23be6b 840 strncat(status, "10:dontExist", DBD15STATLEN);
9455b51c 841 break;
842 case 0x11:
6b23be6b 843 strncat(status, "11:lockAgain", DBD15STATLEN);
9455b51c 844 break;
845 case 0x12:
6b23be6b 846 strncat(status, "12:locked", DBD15STATLEN);
9455b51c 847 break;
848 case 0x13:
6b23be6b 849 strncat(status, "13:progErr", DBD15STATLEN);
9455b51c 850 break;
851 case 0x14:
6b23be6b 852 strncat(status, "14:lockErr", DBD15STATLEN);
9455b51c 853 break;
854 default:
6b23be6b 855 strncat(status, "unknownErr", DBD15STATLEN);
15c4dc5a 856 }
6b23be6b 857 strncat(status ," " ,DBD15STATLEN);
9455b51c 858 } else {
6b23be6b 859 strncat(status ,"NoErr ", DBD15STATLEN);
15c4dc5a 860 }
9455b51c 861
6b23be6b 862 crc = Crc(d,len-2);
9455b51c 863 if ( (( crc & 0xff ) == d[len-2]) && (( crc >> 8 ) == d[len-1]) )
6b23be6b 864 strncat(status, "CrcOK", DBD15STATLEN);
9455b51c 865 else
6b23be6b 866 strncat(status, "CrcFail!", DBD15STATLEN);
9455b51c 867
6b23be6b 868 Dbprintf("%s", status);
15c4dc5a 869 }
870}
871
9455b51c 872///////////////////////////////////////////////////////////////////////
873// Functions called via USB/Client
874///////////////////////////////////////////////////////////////////////
875
876void SetDebugIso15693(uint32_t debug) {
6b23be6b 877 DEBUG = debug;
878 Dbprintf("Iso15693 Debug is now %s", DEBUG ? "on" : "off");
9455b51c 879 return;
880}
881
15c4dc5a 882//-----------------------------------------------------------------------------
883// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
884// all demodulation performed in arm rather than host. - greg
885//-----------------------------------------------------------------------------
f7e3ed82 886void ReaderIso15693(uint32_t parameter)
15c4dc5a 887{
888 LED_A_ON();
889 LED_B_ON();
890 LED_C_OFF();
891 LED_D_OFF();
892
15c4dc5a 893 int answerLen1 = 0;
894 int answerLen2 = 0;
895 int answerLen3 = 0;
3fe4ff4f 896 int i = 0;
897 int samples = 0;
898 int tsamples = 0;
899 int wait = 0;
900 int elapsed = 0;
901 uint8_t TagUID[8] = {0x00};
902
99cf19d9 903 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
15c4dc5a 904
6b23be6b 905 uint8_t *answer1 = BigBuf_malloc(100);
906 uint8_t *answer2 = BigBuf_malloc(100);
907 uint8_t *answer3 = BigBuf_malloc(100);
15c4dc5a 908 // Blank arrays
6b23be6b 909 memset(answer1, 0x00, 100);
910 memset(answer2, 0x00, 100);
911 memset(answer3, 0x00, 100);
15c4dc5a 912
3fe4ff4f 913 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
15c4dc5a 914 // Setup SSC
915 FpgaSetupSsc();
916
917 // Start from off (no field generated)
5ee53a0e 918 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
919 SpinDelay(200);
15c4dc5a 920
15c4dc5a 921 // Give the tags time to energize
922 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
923 SpinDelay(200);
924
925 LED_A_ON();
926 LED_B_OFF();
927 LED_C_OFF();
928 LED_D_OFF();
929
15c4dc5a 930 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
931 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
15c4dc5a 932
933 // Now send the IDENTIFY command
934 BuildIdentifyRequest();
3fe4ff4f 935
936 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
937
15c4dc5a 938 // Now wait for a response
939 answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;
940
6b23be6b 941 if (answerLen1 >= 12) // we should do a better check than this
15c4dc5a 942 {
15c4dc5a 943 TagUID[0] = answer1[2];
944 TagUID[1] = answer1[3];
945 TagUID[2] = answer1[4];
946 TagUID[3] = answer1[5];
947 TagUID[4] = answer1[6];
948 TagUID[5] = answer1[7];
949 TagUID[6] = answer1[8]; // IC Manufacturer code
9455b51c 950 TagUID[7] = answer1[9]; // always E0
15c4dc5a 951
15c4dc5a 952 }
953
9455b51c 954 Dbprintf("%d octets read from IDENTIFY request:", answerLen1);
6b23be6b 955 DbdecodeIso15693Answer(answerLen1, answer1);
956 Dbhexdump(answerLen1, answer1, true);
9455b51c 957
958 // UID is reverse
959 if (answerLen1>=12)
3fe4ff4f 960 Dbprintf("UID = %02hX%02hX%02hX%02hX%02hX%02hX%02hX%02hX",
961 TagUID[7],TagUID[6],TagUID[5],TagUID[4],
962 TagUID[3],TagUID[2],TagUID[1],TagUID[0]);
9455b51c 963
964
965 Dbprintf("%d octets read from SELECT request:", answerLen2);
6b23be6b 966 DbdecodeIso15693Answer(answerLen2, answer2);
967 Dbhexdump(answerLen2, answer2, true);
9455b51c 968
969 Dbprintf("%d octets read from XXX request:", answerLen3);
970 DbdecodeIso15693Answer(answerLen3,answer3);
6b23be6b 971 Dbhexdump(answerLen3, answer3, true);
9455b51c 972
9455b51c 973 // read all pages
6b23be6b 974 if (answerLen1 >= 12 && DEBUG) {
975 i = 0;
976 while ( i < 32 ) { // sanity check, assume max 32 pages
9455b51c 977 BuildReadBlockRequest(TagUID,i);
6b23be6b 978 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
979 answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
9455b51c 980 if (answerLen2>0) {
6b23be6b 981 Dbprintf("READ SINGLE BLOCK %d returned %d octets:", i, answerLen2);
982 DbdecodeIso15693Answer(answerLen2, answer2);
983 Dbhexdump(answerLen2, answer2, true);
9455b51c 984 if ( *((uint32_t*) answer2) == 0x07160101 ) break; // exit on NoPageErr
985 }
6b23be6b 986 ++i;
9455b51c 987 }
988 }
15c4dc5a 989
15c4dc5a 990 LED_A_OFF();
991 LED_B_OFF();
992 LED_C_OFF();
993 LED_D_OFF();
994}
995
15c4dc5a 996// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
997// all demodulation performed in arm rather than host. - greg
3fe4ff4f 998void SimTagIso15693(uint32_t parameter, uint8_t *uid)
15c4dc5a 999{
1000 LED_A_ON();
1001 LED_B_ON();
1002 LED_C_OFF();
1003 LED_D_OFF();
1004
15c4dc5a 1005 int answerLen1 = 0;
3fe4ff4f 1006 int samples = 0;
1007 int tsamples = 0;
1008 int wait = 0;
1009 int elapsed = 0;
15c4dc5a 1010
7cc204bf 1011 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
15c4dc5a 1012
6b23be6b 1013 uint8_t *buf = BigBuf_malloc(100);
99cf19d9 1014 memset(buf, 0x00, 100);
3fe4ff4f 1015
99cf19d9 1016 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
15c4dc5a 1017 FpgaSetupSsc();
1018
3fe4ff4f 1019 // Start from off (no field generated)
5ee53a0e 1020 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
15c4dc5a 1021 SpinDelay(200);
1022
1023 LED_A_OFF();
1024 LED_B_OFF();
1025 LED_C_ON();
1026 LED_D_OFF();
1027
3fe4ff4f 1028 // Listen to reader
1029 answerLen1 = GetIso15693AnswerFromSniff(buf, 100, &samples, &elapsed) ;
15c4dc5a 1030
1031 if (answerLen1 >=1) // we should do a better check than this
1032 {
1033 // Build a suitable reponse to the reader INVENTORY cocmmand
3fe4ff4f 1034 // not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below.
1035
1036 BuildInventoryResponse(uid);
1037
15c4dc5a 1038 TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);
1039 }
1040
1041 Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,
3fe4ff4f 1042 buf[0], buf[1], buf[2], buf[3],
1043 buf[4], buf[5], buf[6], buf[7], buf[8]);
1044
1045 Dbprintf("Simulationg uid: %x %x %x %x %x %x %x %x",
1046 uid[0], uid[1], uid[2], uid[3],
1047 uid[4], uid[5], uid[6], uid[7]);
15c4dc5a 1048
1049 LED_A_OFF();
1050 LED_B_OFF();
1051 LED_C_OFF();
1052 LED_D_OFF();
1053}
9455b51c 1054
1055
1056// Since there is no standardized way of reading the AFI out of a tag, we will brute force it
1057// (some manufactures offer a way to read the AFI, though)
1058void BruteforceIso15693Afi(uint32_t speed)
1059{
1060 uint8_t data[20];
6b23be6b 1061 uint8_t *recv = data;
1062 int datalen = 0, recvlen = 0;
1063
1064 memset(data, 0, sizeof(data));
1065
9455b51c 1066 Iso15693InitReader();
1067
1068 // first without AFI
1069 // Tags should respond wihtout AFI and with AFI=0 even when AFI is active
1070
6b23be6b 1071 data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
1072 ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
1073 data[1] = ISO15_CMD_INVENTORY;
1074 data[2] = 0; // mask length
1075 datalen = AddCrc(data, 3);
1076 recvlen = SendDataTag(data, datalen, 0, speed, &recv);
9455b51c 1077 WDT_HIT();
6b23be6b 1078 if (recvlen >= 12) {
1079 Dbprintf("NoAFI UID=%s", sprintUID(NULL, &recv[2]));
9455b51c 1080 }
1081
1082 // now with AFI
1083
6b23be6b 1084 data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
1085 ISO15_REQ_INVENTORY | ISO15_REQINV_AFI | ISO15_REQINV_SLOT1;
1086 data[1] = ISO15_CMD_INVENTORY;
1087 data[2] = 0; // AFI
1088 data[3] = 0; // mask length
9455b51c 1089
6b23be6b 1090 for (int i = 0; i < 256; i++) {
1091 data[2] = i & 0xFF; // iceman 2016, is & 0xFF needed?
1092 datalen = AddCrc(data, 4);
1093 recvlen = SendDataTag(data, datalen, 0, speed, &recv);
9455b51c 1094 WDT_HIT();
6b23be6b 1095 if (recvlen >= 12) {
1096 Dbprintf("AFI=%i UID=%s", i, sprintUID(NULL, &recv[2]));
9455b51c 1097 }
1098 }
1099 Dbprintf("AFI Bruteforcing done.");
9455b51c 1100}
1101
1102// Allows to directly send commands to the tag via the client
1103void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]) {
1104
6b23be6b 1105 int recvlen = 0;
117d9ec2 1106 uint8_t *recvbuf = BigBuf_get_addr();
9455b51c 1107
1108 if (DEBUG) {
1109 Dbprintf("SEND");
d19929cb 1110 Dbhexdump(datalen,data,true);
9455b51c 1111 }
1112
6b23be6b 1113 recvlen = SendDataTag(data, datalen, 1, speed, (recv ? &recvbuf : NULL));
9455b51c 1114
1115 if (recv) {
9455b51c 1116 LED_B_ON();
6b23be6b 1117 cmd_send(CMD_ACK,recvlen>48?48:recvlen,0,0,recvbuf,48);
9455b51c 1118 LED_B_OFF();
1119
1120 if (DEBUG) {
1121 Dbprintf("RECV");
1122 DbdecodeIso15693Answer(recvlen,recvbuf);
d19929cb 1123 Dbhexdump(recvlen,recvbuf,true);
9455b51c 1124 }
1125 }
6b23be6b 1126}
Impressum, Datenschutz