Merge pull request #2616 from jmichelp/fix14b
[RRG-proxmark3.git] / armsrc / legicrf.c
blob6239f27cb036f4a24bad003386be9de4a5659de9
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // LEGIC RF simulation code
17 //-----------------------------------------------------------------------------
18 #include "legicrf.h"
20 #include "crc.h" /* legic crc-4 */
21 #include "legic_prng.h" /* legic PRNG impl */
22 #include "legic.h" /* legic_card_select_t struct */
24 #include "proxmark3_arm.h"
25 #include "cmd.h"
26 #include "BigBuf.h"
27 #include "fpgaloader.h"
28 #include "ticks.h"
29 #include "dbprint.h"
30 #include "util.h"
31 #include "string.h"
32 #include "protocols.h"
34 static uint8_t *legic_mem; /* card memory, used for read, write */
35 static legic_card_select_t card;/* metadata of currently selected card */
36 static crc_t legic_crc;
38 //-----------------------------------------------------------------------------
39 // Frame timing and pseudorandom number generator
41 // The Prng is forwarded every 100us (TAG_BIT_PERIOD), except when the reader is
42 // transmitting. In that case the prng has to be forwarded every bit transmitted:
43 // - 60us for a 0 (RWD_TIME_0)
44 // - 100us for a 1 (RWD_TIME_1)
46 // The data dependent timing makes writing comprehensible code significantly
47 // harder. The current approach forwards the prng data based if there is data on
48 // air and time based, using GET_TICKS, during computational and wait periodes.
50 // To not have the necessity to calculate/guess execution time dependent timeouts
51 // tx_frame and rx_frame use a shared timestamp to coordinate tx and rx timeslots.
52 //-----------------------------------------------------------------------------
54 static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
56 #define RWD_TIME_PAUSE 30 /* 20us */
57 #define RWD_TIME_1 150 /* READER_TIME_PAUSE 20us off + 80us on = 100us */
58 #define RWD_TIME_0 90 /* READER_TIME_PAUSE 20us off + 40us on = 60us */
59 #define RWD_FRAME_WAIT 330 /* 220us from TAG frame end to READER frame start */
60 #define TAG_FRAME_WAIT 495 /* 330us from READER frame end to TAG frame start */
61 #define TAG_BIT_PERIOD 150 /* 100us */
62 #define TAG_WRITE_TIMEOUT 60 /* 40 * 100us (write should take at most 3.6ms) */
64 #define LEGIC_CARD_MEMSIZE 1024 /* The largest Legic Prime card is 1k */
65 #define WRITE_LOWERLIMIT 4 /* UID and MCC are not writable */
67 static uint32_t input_threshold = 8; /* heuristically determined, lower values */
68 /* lead to detecting false ack during write */
70 //-----------------------------------------------------------------------------
71 // I/O interface abstraction (FPGA -> ARM)
72 //-----------------------------------------------------------------------------
73 static uint16_t rx_frame_from_fpga(void) {
74 for (;;) {
75 WDT_HIT();
77 // wait for frame be become available in rx holding register
78 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
79 return AT91C_BASE_SSC->SSC_RHR;
82 return 0;
85 //-----------------------------------------------------------------------------
86 // Demodulation (Reader)
87 //-----------------------------------------------------------------------------
89 // Returns a demodulated bit
91 // The FPGA running xcorrelation samples the subcarrier at ~13.56 MHz. The mode
92 // was initially designed to receive BSPK/2-PSK. Hance, it reports an I/Q pair
93 // every 4.7us (8 bits i and 8 bits q).
95 // The subcarrier amplitude can be calculated using Pythagoras sqrt(i^2 + q^2).
96 // To reduce CPU time the amplitude is approximated by using linear functions:
97 // am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
99 // The bit time is 99.1us (21 I/Q pairs). The receiver skips the first 5 samples
100 // and averages the next (most stable) 8 samples. The final 8 samples are dropped
101 // also.
103 // The demodulated should be aligned to the bit period by the caller. This is
104 // done in rx_bit and rx_ack.
106 // Note: The demodulator would be drifting (18.9us * 5 != 100us), rx_frame
107 // has a delay loop that aligns rx_bit calls to the TAG tx timeslots.
109 // Note: inlining this function would fail with -Os
110 static bool rx_bit(void) {
111 int32_t sum_cq = 0;
112 int32_t sum_ci = 0;
114 // skip first 5 I/Q pairs
115 for (size_t i = 0; i < 5; ++i) {
116 (void)rx_frame_from_fpga();
119 // sample next 8 I/Q pairs
120 for (uint8_t i = 0; i < 8; ++i) {
121 uint16_t iq = rx_frame_from_fpga();
122 int8_t ci = (int8_t)(iq >> 8);
123 int8_t cq = (int8_t)(iq & 0xff);
124 sum_ci += ci;
125 sum_cq += cq;
128 // calculate power
129 int32_t power = (MAX(ABS(sum_ci), ABS(sum_cq)) + (MIN(ABS(sum_ci), ABS(sum_cq)) >> 1));
131 // compare average (power / 8) to threshold
132 return ((power >> 3) > input_threshold);
135 //-----------------------------------------------------------------------------
136 // Modulation
138 // I've tried to modulate the Legic specific pause-puls using ssc and the default
139 // ssc clock of 105.4 kHz (bit periode of 9.4us) - previous commit. However,
140 // the timing was not precise enough. By increasing the ssc clock this could
141 // be circumvented, but the adventage over bitbang would be little.
142 //-----------------------------------------------------------------------------
144 static void tx_bit(bool bit) {
145 // insert pause
146 HIGH(GPIO_SSC_DOUT);
147 last_frame_end += RWD_TIME_PAUSE;
148 while (GET_TICKS < last_frame_end) { };
150 // return to carrier on, wait for bit periode to end
151 LOW(GPIO_SSC_DOUT);
152 last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
153 while (GET_TICKS < last_frame_end) { };
156 //-----------------------------------------------------------------------------
157 // Frame Handling (Reader)
159 // The LEGIC RF protocol from card to reader does not include explicit frame
160 // start/stop information or length information. The reader must know beforehand
161 // how many bits it wants to receive.
162 // Notably: a card sending a stream of 0-bits is indistinguishable from no card
163 // present.
164 //-----------------------------------------------------------------------------
166 static void tx_frame(uint32_t frame, uint8_t len) {
167 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD);
169 // wait for next tx timeslot
170 last_frame_end += RWD_FRAME_WAIT;
171 while (GET_TICKS < last_frame_end) { };
173 // backup ts for trace log
174 uint32_t last_frame_start = last_frame_end;
176 // transmit frame, MSB first
177 for (uint8_t i = 0; i < len; ++i) {
178 bool bit = (frame >> i) & 0x01;
179 tx_bit(bit ^ legic_prng_get_bit());
180 legic_prng_forward(1);
183 // add pause to mark end of the frame
184 HIGH(GPIO_SSC_DOUT);
185 last_frame_end += RWD_TIME_PAUSE;
186 while (GET_TICKS < last_frame_end) { };
187 LOW(GPIO_SSC_DOUT);
189 // log
190 uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
191 LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
194 static uint32_t rx_frame(uint8_t len) {
195 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
197 // hold sampling until card is expected to respond
198 last_frame_end += TAG_FRAME_WAIT;
199 while (GET_TICKS < last_frame_end) { };
201 // backup ts for trace log
202 uint32_t last_frame_start = last_frame_end;
204 uint32_t frame = 0;
205 for (uint8_t i = 0; i < len; ++i) {
206 frame |= (rx_bit() ^ legic_prng_get_bit()) << i;
207 legic_prng_forward(1);
209 // rx_bit runs only 95us, resync to TAG_BIT_PERIOD
210 last_frame_end += TAG_BIT_PERIOD;
211 while (GET_TICKS < last_frame_end) { };
214 // log
215 uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)};
216 LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
218 return frame;
221 static bool rx_ack(void) {
222 // change fpga into rx mode
223 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
225 // hold sampling until card is expected to respond
226 last_frame_end += TAG_FRAME_WAIT;
227 while (GET_TICKS < last_frame_end) { };
229 // backup ts for trace log
230 uint32_t last_frame_start = last_frame_end;
232 uint32_t ack = 0;
233 for (uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) {
234 // sample bit
235 ack = rx_bit();
236 legic_prng_forward(1);
238 // rx_bit runs only 95us, resync to TAG_BIT_PERIOD
239 last_frame_end += TAG_BIT_PERIOD;
240 while (GET_TICKS < last_frame_end) { };
242 // check if it was an ACK
243 if (ack) {
244 break;
248 // log
249 uint8_t cmdbytes[] = {1, BYTEx(ack, 0)};
250 LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
252 return ack;
255 //-----------------------------------------------------------------------------
256 // Legic Reader
257 //-----------------------------------------------------------------------------
259 static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
260 p_card->tagtype = cardtype;
262 switch (p_card->tagtype) {
263 case 0x0d:
264 p_card->cmdsize = 6;
265 p_card->addrsize = 5;
266 p_card->cardsize = 22;
267 break;
268 case 0x1d:
269 p_card->cmdsize = 9;
270 p_card->addrsize = 8;
271 p_card->cardsize = 256;
272 break;
273 case 0x3d:
274 p_card->cmdsize = 11;
275 p_card->addrsize = 10;
276 p_card->cardsize = 1024;
277 break;
278 default:
279 p_card->cmdsize = 0;
280 p_card->addrsize = 0;
281 p_card->cardsize = 0;
282 return PM3_ESOFT;
284 return PM3_SUCCESS;
287 static void init_reader(void) {
288 // configure FPGA
289 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
290 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
291 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
292 LED_A_ON();
294 // configure SSC with defaults
295 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
297 // re-claim GPIO_SSC_DOUT as GPIO and enable output
298 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
299 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
300 LOW(GPIO_SSC_DOUT);
302 // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
303 legic_mem = BigBuf_get_EM_addr();
304 if (legic_mem) {
305 memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE);
308 // start trace
309 clear_trace();
310 set_tracing(true);
312 // init crc calculator
313 crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
315 // start us timer
316 StartTicks();
319 // Setup reader to card connection
321 // The setup consists of a three way handshake:
322 // - Transmit initialisation vector 7 bits
323 // - Receive card type 6 bits
324 // - Transmit Acknowledge 6 bits
325 static uint32_t setup_phase(uint8_t iv) {
326 // init coordination timestamp
327 last_frame_end = GET_TICKS;
329 // Switch on carrier and let the card charge for 5ms.
330 last_frame_end += 7500;
331 while (GET_TICKS < last_frame_end) { };
333 legic_prng_init(0);
334 tx_frame(iv, 7);
336 // configure prng
337 legic_prng_init(iv);
338 legic_prng_forward(2);
340 // receive card type
341 int32_t card_type = rx_frame(6);
342 legic_prng_forward(3);
344 // send obsfuscated acknowledgment frame
345 switch (card_type) {
346 case 0x0D:
347 tx_frame(0x19, 6); // MIM22 | READCMD = 0x18 | 0x01
348 break;
349 case 0x1D:
350 case 0x3D:
351 tx_frame(0x39, 6); // MIM256 | READCMD = 0x38 | 0x01
352 break;
355 return card_type;
358 static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) {
359 crc_clear(&legic_crc);
360 crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz);
361 return crc_finish(&legic_crc);
364 static int16_t read_byte(uint16_t index, uint8_t cmd_sz) {
365 uint16_t cmd = (index << 1) | LEGIC_READ;
367 // read one byte
368 LED_B_ON();
369 legic_prng_forward(2);
370 tx_frame(cmd, cmd_sz);
371 legic_prng_forward(2);
372 uint32_t frame = rx_frame(12);
373 LED_B_OFF();
375 // split frame into data and crc
376 uint8_t byte = BYTEx(frame, 0);
377 uint8_t crc = BYTEx(frame, 1);
379 // check received against calculated crc
380 uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte);
381 if (calc_crc != crc) {
382 Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
383 return -1;
386 legic_prng_forward(1);
388 return byte;
391 // Transmit write command, wait until (3.6ms) the tag sends back an unencrypted
392 // ACK ('1' bit) and forward the prng time based.
393 static bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
394 uint32_t cmd = index << 1 | LEGIC_WRITE; // prepare command
395 uint8_t crc = calc_crc4(cmd, addr_sz + 1, byte); // calculate crc
396 cmd |= byte << (addr_sz + 1); // append value
397 cmd |= (crc & 0xF) << (addr_sz + 1 + 8); // and crc
399 // send write command
400 LED_C_ON();
401 legic_prng_forward(2);
402 tx_frame(cmd, addr_sz + 1 + 8 + 4); // cmd_sz = addr_sz + cmd + data + crc
403 legic_prng_forward(3);
404 LED_C_OFF();
406 // wait for ack
407 return rx_ack();
410 //-----------------------------------------------------------------------------
411 // Command Line Interface
413 // Only this functions are public / called from appmain.c
414 //-----------------------------------------------------------------------------
415 legic_card_select_t *getLegicCardInfo(void) {
416 return &card;
419 void LegicRfInfo(void) {
420 // configure ARM and FPGA
421 init_reader();
423 // establish shared secret and detect card type
424 uint8_t card_type = setup_phase(0x01);
425 if (init_card(card_type, &card) != PM3_SUCCESS) {
426 reply_ng(CMD_HF_LEGIC_INFO, PM3_EINIT, NULL, 0);
427 goto OUT;
430 // read UID
431 for (uint8_t i = 0; i < sizeof(card.uid); ++i) {
432 int16_t byte = read_byte(i, card.cmdsize);
433 if (byte == -1) {
434 reply_ng(CMD_HF_LEGIC_INFO, PM3_EFAILED, NULL, 0);
435 goto OUT;
437 card.uid[i] = byte & 0xFF;
440 // read MCC and check against UID
441 int16_t mcc = read_byte(4, card.cmdsize);
442 int16_t calc_mcc = CRC8Legic(card.uid, 4);
443 if (mcc != calc_mcc) {
444 reply_ng(CMD_HF_LEGIC_INFO, PM3_ESOFT, NULL, 0);
445 goto OUT;
448 // OK
449 reply_ng(CMD_HF_LEGIC_INFO, PM3_SUCCESS, (uint8_t *)&card, sizeof(legic_card_select_t));
451 OUT:
452 switch_off();
453 StopTicks();
456 int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) {
458 int res = PM3_SUCCESS;
460 // configure ARM and FPGA
461 init_reader();
463 // establish shared secret and detect card type
464 uint8_t card_type = setup_phase(iv);
465 if (init_card(card_type, &card) != PM3_SUCCESS) {
466 res = PM3_ESOFT;
467 goto OUT;
470 // do not read beyond card memory
471 if (len + offset > card.cardsize) {
472 len = card.cardsize - offset;
475 for (uint16_t i = 0; i < len; ++i) {
476 int16_t byte = read_byte(offset + i, card.cmdsize);
477 if (byte == -1) {
478 res = PM3_EOVFLOW;
479 goto OUT;
481 legic_mem[i] = byte;
483 if (i < 4) {
484 card.uid[i] = byte;
488 OUT:
489 switch_off();
490 StopTicks();
491 return res;
494 void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
495 // configure ARM and FPGA
496 init_reader();
498 // establish shared secret and detect card type
499 uint8_t card_type = setup_phase(iv);
500 if (init_card(card_type, &card) != PM3_SUCCESS) {
501 reply_ng(CMD_HF_LEGIC_READER, PM3_EINIT, NULL, 0);
502 goto OUT;
505 // do not read beyond card memory
506 if (len + offset > card.cardsize) {
507 len = card.cardsize - offset;
510 for (uint16_t i = 0; i < len; ++i) {
511 int16_t byte = read_byte(offset + i, card.cmdsize);
512 if (byte == -1) {
513 reply_ng(CMD_HF_LEGIC_READER, PM3_EFAILED, NULL, 0);
514 goto OUT;
516 legic_mem[i] = byte;
518 if (i < 4) {
519 card.uid[i] = byte;
523 // OK
524 reply_ng(CMD_HF_LEGIC_READER, PM3_SUCCESS, (uint8_t *)&len, sizeof(len));
526 OUT:
527 switch_off();
528 StopTicks();
531 void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, const uint8_t *data) {
532 // configure ARM and FPGA
533 init_reader();
535 // uid is not writeable
536 if (offset <= WRITE_LOWERLIMIT) {
537 reply_ng(CMD_HF_LEGIC_WRITER, PM3_EINVARG, NULL, 0);
538 goto OUT;
541 // establish shared secret and detect card type
542 uint8_t card_type = setup_phase(iv);
543 if (init_card(card_type, &card) != PM3_SUCCESS) {
544 reply_ng(CMD_HF_LEGIC_WRITER, PM3_EINIT, NULL, 0);
545 goto OUT;
548 // do not write beyond card memory
549 if (len + offset > card.cardsize) {
550 len = card.cardsize - offset;
553 // write in reverse order, only then is DCF (decremental field) writable
554 while (len-- > 0 && BUTTON_PRESS() == false) {
555 if (write_byte(len + offset, data[len], card.addrsize) == false) {
556 Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
557 reply_ng(CMD_HF_LEGIC_WRITER, PM3_EFAILED, NULL, 0);
558 goto OUT;
562 // OK
563 reply_ng(CMD_HF_LEGIC_WRITER, PM3_SUCCESS, (uint8_t *)&len, sizeof(len));
565 OUT:
566 switch_off();
567 StopTicks();
570 void LegicRfSetThreshold(uint32_t threshold) {
571 input_threshold = threshold;