]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/iso15693.c
CHG: 'hf iclass dump' - output fixes
[proxmark3-svn] / armsrc / iso15693.c
... / ...
CommitLineData
1//-----------------------------------------------------------------------------
2// Jonathan Westhues, split Nov 2006
3// Modified by Greg Jones, Jan 2009
4// Modified by Adrian Dabrowski "atrox", Mar-Sept 2010,Oct 2011
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// 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.
13// Modified to perform modulation onboard in arm rather than on PC
14// Also added additional reader commands (SELECT, READ etc.)
15//-----------------------------------------------------------------------------
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
54// *) read security status of a block
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
60
61#include "proxmark3.h"
62#include "util.h"
63#include "apps.h"
64#include "string.h"
65#include "iso15693tools.h"
66#include "cmd.h"
67
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
77
78#define Crc(data,datalen) Iso15693Crc(data,datalen)
79#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
80#define sprintUID(target,uid) Iso15693sprintUID(target,uid)
81
82int DEBUG = 0;
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
93static void CodeIso15693AsReader(uint8_t *cmd, int n)
94{
95 int i, j;
96
97 ToSendReset();
98
99 // Give it a bit of slack at the beginning
100 for(i = 0; i < 24; i++)
101 ToSendStuffBit(1);
102
103 // SOF for 1of4
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 }
159 // EOF
160 ToSendStuffBit(1);
161 ToSendStuffBit(1);
162 ToSendStuffBit(0);
163 ToSendStuffBit(1);
164
165 // And slack at the end, too.
166 for(i = 0; i < 24; i++)
167 ToSendStuffBit(1);
168}
169
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)
174{
175 int i, j;
176
177 ToSendReset();
178
179 // Give it a bit of slack at the beginning
180 for(i = 0; i < 24; i++)
181 ToSendStuffBit(1);
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
193 for(i = 0; i < n; i++) {
194 for (j = 0; j <= 255; j++) {
195 if (cmd[i] == j) {
196 ToSendStuffBit(1);
197 ToSendStuffBit(0);
198 } else {
199 ToSendStuffBit(1);
200 ToSendStuffBit(1);
201 }
202 }
203 }
204 // EOF
205 ToSendStuffBit(1);
206 ToSendStuffBit(1);
207 ToSendStuffBit(0);
208 ToSendStuffBit(1);
209
210 // And slack at the end, too.
211 for(i = 0; i < 24; i++)
212 ToSendStuffBit(1);
213}
214
215
216// Transmit the command (to the tag) that was placed in ToSend[].
217static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait)
218{
219 int c;
220 volatile uint32_t r;
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!
227// ++c;
228// }
229// if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
230// r = AT91C_BASE_SSC->SSC_RHR;
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];
240 if( ++c >= len) break;
241 }
242 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
243 r = AT91C_BASE_SSC->SSC_RHR;
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//-----------------------------------------------------------------------------
254static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait)
255{
256 int c = 0;
257 volatile uint32_t r;
258 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K);
259 if(*wait < 10) { *wait = 10; }
260
261 for(;;) {
262 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
263 AT91C_BASE_SSC->SSC_THR = cmd[c];
264 if( ++c >= len) break;
265 }
266 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
267 r = AT91C_BASE_SSC->SSC_RHR;
268 (void)r;
269 }
270 WDT_HIT();
271 }
272 *samples = (c + *wait) << 3;
273}
274
275
276// Read from Tag
277// Parameters:
278// receivedResponse
279// maxLen
280// samples
281// elapsed
282// returns:
283// number of decoded bytes
284static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
285{
286 uint8_t *dest = BigBuf_get_addr();
287
288 int c = 0, getNext = FALSE;
289 int8_t prev = 0;
290
291 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
292 SpinDelay(100); // greg - experiment to get rid of some of the 0 byte/failed reads
293
294 for(;;) {
295 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
296 AT91C_BASE_SSC->SSC_THR = 0x43;
297
298 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
299 int8_t b;
300 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
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.
306 // iceman 2016, amplitude sqrt(abs(i) + abs(q))
307 if(getNext) {
308 dest[c++] = (uint8_t)ABS(b) + ABS(prev);
309
310 if(c >= 2000)
311 break;
312 } else {
313 prev = b;
314 }
315
316 getNext = !getNext;
317 }
318 }
319
320 //////////////////////////////////////////
321 /////////// DEMODULATE ///////////////////
322 //////////////////////////////////////////
323
324 int i, j;
325 int max = 0, maxPos=0, skip = 4;
326 int k = 0; // this will be our return value
327
328 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
329
330 // First, correlate for SOF
331 for(i = 0; i < 100; i++) {
332 int corr = 0;
333 for(j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
334 corr += FrameSOF[j] * dest[i+(j/skip)];
335 }
336 if(corr > max) {
337 max = corr;
338 maxPos = i;
339 }
340 }
341 // DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip));
342
343 // greg - If correlation is less than 1 then there's little point in continuing
344 if ((max/(ARRAYLEN(FrameSOF)/skip)) >= 1)
345 {
346 i = maxPos + ARRAYLEN(FrameSOF) / skip;
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;
353 for(j = 0; j < ARRAYLEN(Logic0); j += skip) {
354 corr0 += Logic0[j] * dest[i+(j/skip)];
355 }
356 for(j = 0; j < ARRAYLEN(Logic1); j += skip) {
357 corr1 += Logic1[j] * dest[i+(j/skip)];
358 }
359 for(j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
360 corrEOF += FrameEOF[j] * dest[i+(j/skip)];
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) {
370 i += ARRAYLEN(Logic1)/skip;
371 outBuf[k] |= mask;
372 } else {
373 i += ARRAYLEN(Logic0)/skip;
374 }
375 mask <<= 1;
376 if(mask == 0) {
377 k++;
378 mask = 0x01;
379 }
380 if( ( i + (int)ARRAYLEN(FrameEOF)) >= 2000) {
381 DbpString("ran off end!");
382 break;
383 }
384 }
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);
388 if (mask < 0x08) k--; // discard the last uneven octet;
389 // 0x08 is an assumption - but works quite often
390 }
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];
404 }
405 } // "end if correlation > 0" (max/(ARRAYLEN(FrameSOF)/skip))
406 return k; // return the number of bytes demodulated
407}
408
409
410// Now the GetISO15693 message from sniffing command
411static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
412{
413 uint8_t *dest = BigBuf_get_addr();
414
415 int c = 0, getNext = FALSE;
416 int8_t prev = 0;
417
418 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
419 SpinDelay(100); // greg - experiment to get rid of some of the 0 byte/failed reads
420
421 for(;;) {
422 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
423 AT91C_BASE_SSC->SSC_THR = 0x43;
424
425 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
426 int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
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) {
433 dest[c++] = (uint8_t)ABS(b) + ABS(prev);
434
435 if(c >= 20000)
436 break;
437 } else {
438 prev = b;
439 }
440 getNext = !getNext;
441 }
442 }
443
444 //////////////////////////////////////////
445 /////////// DEMODULATE ///////////////////
446 //////////////////////////////////////////
447
448 int i, j, max = 0, maxPos=0, skip = 4;
449
450 // First, correlate for SOF
451 for(i = 0; i < 19000; i++) {
452 int corr = 0;
453 for(j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
454 corr += FrameSOF[j]*dest[i+(j/skip)];
455 }
456 if(corr > max) {
457 max = corr;
458 maxPos = i;
459 }
460 }
461// DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip));
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
466 if ((max/(ARRAYLEN(FrameSOF)/skip)) >= 1) // THIS SHOULD BE 1
467 {
468
469 i = maxPos + ARRAYLEN(FrameSOF)/skip;
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;
476 for(j = 0; j < ARRAYLEN(Logic0); j += skip) {
477 corr0 += Logic0[j]*dest[i+(j/skip)];
478 }
479 for(j = 0; j < ARRAYLEN(Logic1); j += skip) {
480 corr1 += Logic1[j]*dest[i+(j/skip)];
481 }
482 for(j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
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) {
493 i += ARRAYLEN(Logic1)/skip;
494 outBuf[k] |= mask;
495 } else {
496 i += ARRAYLEN(Logic0)/skip;
497 }
498 mask <<= 1;
499 if(mask == 0) {
500 k++;
501 mask = 0x01;
502 }
503 if((i+(int)ARRAYLEN(FrameEOF)) >= 2000) {
504 DbpString("ran off end!");
505 break;
506 }
507 }
508 if(mask != 0x01) {
509 DbpString("sniff: error, uneven octet! (discard extra bits!)");
510 // DbpString(" mask=%02x", mask);
511 }
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];
525 }
526 } // "end if correlation > 0" (max/(ARRAYLEN(FrameSOF)/skip))
527 return k; // return the number of bytes demodulated
528}
529
530
531static void BuildIdentifyRequest(void);
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{
539 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
540
541 int c = 0, getNext = FALSE;
542 int8_t prev = 0;
543 volatile uint32_t r;
544
545 uint8_t *dest = BigBuf_get_addr();
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];
562 if( ++c == ToSendMax+3) break;
563 }
564 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
565 r = AT91C_BASE_SSC->SSC_RHR;
566 (void)r;
567 }
568 WDT_HIT();
569 }
570
571 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
572
573 c = 0;
574 for(;;) {
575 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
576 AT91C_BASE_SSC->SSC_THR = 0x43;
577
578 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
579
580 int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
581
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) {
587
588 dest[c++] = (uint8_t)(ABS(b) + ABS(prev));
589
590 if(c >= 2000) break;
591
592 } else {
593 prev = b;
594 }
595 getNext = !getNext;
596 }
597 }
598}
599
600
601void RecordRawAdcSamplesIso15693(void)
602{
603 uint8_t *dest = BigBuf_get_addr();
604
605 int c = 0, getNext = FALSE;
606 int8_t prev = 0;
607
608 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
609 // Setup SSC
610 FpgaSetupSsc();
611
612 // Start from off (no field generated)
613 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
614 SpinDelay(200);
615
616 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
617 SpinDelay(100);
618
619 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
620
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) {
634 dest[c++] = (uint8_t) ABS(b) + ABS(prev);
635
636 if(c >= 7000)
637 break;
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
651// (this might produces glitches that confuse some tags
652void Iso15693InitReader() {
653 LED_A_ON();
654 LED_B_ON();
655 LED_C_OFF();
656 LED_D_OFF();
657
658 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
659 // Setup SSC
660 // FpgaSetupSsc();
661
662 // Start from off (no field generated)
663 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
664 SpinDelay(10);
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);
671 SpinDelay(250);
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{
688 uint8_t cmd[5] = {0,1,0,0,0};
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{
708 uint8_t cmd[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
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
737 static void BuildInventoryResponse( uint8_t *uid)
738{
739 uint8_t cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
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
743 //(1 << 2) | (1 << 5) | (1 << 1);
744 cmd[0] = 0; //
745 cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
746 // 64-bit UID
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;
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
763// Universal Method for sending to and recv bytes from a tag
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
771 int samples = 0, tsamples = 0;
772 int wait = 0, elapsed = 0;
773 int answerLen = 0;
774
775 LED_A_ON(); LED_B_ON();
776
777 LED_C_OFF(); LED_D_OFF();
778
779 if (init) Iso15693InitReader();
780
781 // answer is 100bytes long?
782 uint8_t *answer = BigBuf_malloc(100);
783 if (recv != NULL) memset(answer, 0, 100);
784
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
796 TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait);
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) ;
802 *recv = answer;
803 }
804
805 LEDsoff();
806 return answerLen;
807}
808
809
810// --------------------------------------------------------------------
811// Debug Functions
812// --------------------------------------------------------------------
813
814// Decodes a message from a tag and displays its metadata and content
815#define DBD15STATLEN 48
816void DbdecodeIso15693Answer(int len, uint8_t *d) {
817 char status[DBD15STATLEN+1] = {0};
818 uint16_t crc;
819
820 if (len > 3) {
821 if (d[0] & ( 1 << 3 ))
822 strncat(status, "ProtExt ", DBD15STATLEN);
823 if (d[0] & 1) {
824 // error
825 strncat(status, "Error ", DBD15STATLEN);
826 switch (d[1]) {
827 case 0x01:
828 strncat(status, "01:notSupp", DBD15STATLEN);
829 break;
830 case 0x02:
831 strncat(status, "02:notRecog", DBD15STATLEN);
832 break;
833 case 0x03:
834 strncat(status, "03:optNotSupp", DBD15STATLEN);
835 break;
836 case 0x0f:
837 strncat(status, "0f:noInfo", DBD15STATLEN);
838 break;
839 case 0x10:
840 strncat(status, "10:dontExist", DBD15STATLEN);
841 break;
842 case 0x11:
843 strncat(status, "11:lockAgain", DBD15STATLEN);
844 break;
845 case 0x12:
846 strncat(status, "12:locked", DBD15STATLEN);
847 break;
848 case 0x13:
849 strncat(status, "13:progErr", DBD15STATLEN);
850 break;
851 case 0x14:
852 strncat(status, "14:lockErr", DBD15STATLEN);
853 break;
854 default:
855 strncat(status, "unknownErr", DBD15STATLEN);
856 }
857 strncat(status ," " ,DBD15STATLEN);
858 } else {
859 strncat(status ,"NoErr ", DBD15STATLEN);
860 }
861
862 crc = Crc(d,len-2);
863 if ( (( crc & 0xff ) == d[len-2]) && (( crc >> 8 ) == d[len-1]) )
864 strncat(status, "CrcOK", DBD15STATLEN);
865 else
866 strncat(status, "CrcFail!", DBD15STATLEN);
867
868 Dbprintf("%s", status);
869 }
870}
871
872///////////////////////////////////////////////////////////////////////
873// Functions called via USB/Client
874///////////////////////////////////////////////////////////////////////
875
876void SetDebugIso15693(uint32_t debug) {
877 DEBUG = debug;
878 Dbprintf("Iso15693 Debug is now %s", DEBUG ? "on" : "off");
879 return;
880}
881
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//-----------------------------------------------------------------------------
886void ReaderIso15693(uint32_t parameter)
887{
888 LED_A_ON();
889 LED_B_ON();
890 LED_C_OFF();
891 LED_D_OFF();
892
893 int answerLen1 = 0;
894 int answerLen2 = 0;
895 int answerLen3 = 0;
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
903 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
904
905 uint8_t *answer1 = BigBuf_malloc(100);
906 uint8_t *answer2 = BigBuf_malloc(100);
907 uint8_t *answer3 = BigBuf_malloc(100);
908 // Blank arrays
909 memset(answer1, 0x00, 100);
910 memset(answer2, 0x00, 100);
911 memset(answer3, 0x00, 100);
912
913 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
914 // Setup SSC
915 FpgaSetupSsc();
916
917 // Start from off (no field generated)
918 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
919 SpinDelay(200);
920
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
930 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
931 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
932
933 // Now send the IDENTIFY command
934 BuildIdentifyRequest();
935
936 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
937
938 // Now wait for a response
939 answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;
940
941 if (answerLen1 >= 12) // we should do a better check than this
942 {
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
950 TagUID[7] = answer1[9]; // always E0
951
952 }
953
954 Dbprintf("%d octets read from IDENTIFY request:", answerLen1);
955 DbdecodeIso15693Answer(answerLen1, answer1);
956 Dbhexdump(answerLen1, answer1, true);
957
958 // UID is reverse
959 if (answerLen1>=12)
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]);
963
964
965 Dbprintf("%d octets read from SELECT request:", answerLen2);
966 DbdecodeIso15693Answer(answerLen2, answer2);
967 Dbhexdump(answerLen2, answer2, true);
968
969 Dbprintf("%d octets read from XXX request:", answerLen3);
970 DbdecodeIso15693Answer(answerLen3,answer3);
971 Dbhexdump(answerLen3, answer3, true);
972
973 // read all pages
974 if (answerLen1 >= 12 && DEBUG) {
975 i = 0;
976 while ( i < 32 ) { // sanity check, assume max 32 pages
977 BuildReadBlockRequest(TagUID,i);
978 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
979 answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
980 if (answerLen2>0) {
981 Dbprintf("READ SINGLE BLOCK %d returned %d octets:", i, answerLen2);
982 DbdecodeIso15693Answer(answerLen2, answer2);
983 Dbhexdump(answerLen2, answer2, true);
984 if ( *((uint32_t*) answer2) == 0x07160101 ) break; // exit on NoPageErr
985 }
986 ++i;
987 }
988 }
989
990 LED_A_OFF();
991 LED_B_OFF();
992 LED_C_OFF();
993 LED_D_OFF();
994}
995
996// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
997// all demodulation performed in arm rather than host. - greg
998void SimTagIso15693(uint32_t parameter, uint8_t *uid)
999{
1000 LED_A_ON();
1001 LED_B_ON();
1002 LED_C_OFF();
1003 LED_D_OFF();
1004
1005 int answerLen1 = 0;
1006 int samples = 0;
1007 int tsamples = 0;
1008 int wait = 0;
1009 int elapsed = 0;
1010
1011 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
1012
1013 uint8_t *buf = BigBuf_malloc(100);
1014 memset(buf, 0x00, 100);
1015
1016 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1017 FpgaSetupSsc();
1018
1019 // Start from off (no field generated)
1020 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1021 SpinDelay(200);
1022
1023 LED_A_OFF();
1024 LED_B_OFF();
1025 LED_C_ON();
1026 LED_D_OFF();
1027
1028 // Listen to reader
1029 answerLen1 = GetIso15693AnswerFromSniff(buf, 100, &samples, &elapsed) ;
1030
1031 if (answerLen1 >=1) // we should do a better check than this
1032 {
1033 // Build a suitable reponse to the reader INVENTORY cocmmand
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
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,
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]);
1048
1049 LED_A_OFF();
1050 LED_B_OFF();
1051 LED_C_OFF();
1052 LED_D_OFF();
1053}
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];
1061 uint8_t *recv = data;
1062 int datalen = 0, recvlen = 0;
1063
1064 memset(data, 0, sizeof(data));
1065
1066 Iso15693InitReader();
1067
1068 // first without AFI
1069 // Tags should respond wihtout AFI and with AFI=0 even when AFI is active
1070
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);
1077 WDT_HIT();
1078 if (recvlen >= 12) {
1079 Dbprintf("NoAFI UID=%s", sprintUID(NULL, &recv[2]));
1080 }
1081
1082 // now with AFI
1083
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
1089
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);
1094 WDT_HIT();
1095 if (recvlen >= 12) {
1096 Dbprintf("AFI=%i UID=%s", i, sprintUID(NULL, &recv[2]));
1097 }
1098 }
1099 Dbprintf("AFI Bruteforcing done.");
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
1105 int recvlen = 0;
1106 uint8_t *recvbuf = BigBuf_get_addr();
1107
1108 if (DEBUG) {
1109 Dbprintf("SEND");
1110 Dbhexdump(datalen,data,true);
1111 }
1112
1113 recvlen = SendDataTag(data, datalen, 1, speed, (recv ? &recvbuf : NULL));
1114
1115 if (recv) {
1116 LED_B_ON();
1117 cmd_send(CMD_ACK,recvlen>48?48:recvlen,0,0,recvbuf,48);
1118 LED_B_OFF();
1119
1120 if (DEBUG) {
1121 Dbprintf("RECV");
1122 DbdecodeIso15693Answer(recvlen,recvbuf);
1123 Dbhexdump(recvlen,recvbuf,true);
1124 }
1125 }
1126}
Impressum, Datenschutz