]>
Commit | Line | Data |
---|---|---|
1b902aa0 A |
1 | //----------------------------------------------------------------------------- |
2 | // (c) 2009 Henryk Plötz <henryk@ploetzli.ch> | |
3 | // 2016 Iceman | |
4 | // 2018 AntiCat | |
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 | // LEGIC RF simulation code | |
11 | //----------------------------------------------------------------------------- | |
12 | ||
fc52fbd4 | 13 | #include "legicrfsim.h" |
14 | ||
1b902aa0 A |
15 | #include "proxmark3.h" |
16 | #include "apps.h" | |
17 | #include "util.h" | |
18 | #include "string.h" | |
1b902aa0 A |
19 | #include "legic_prng.h" |
20 | #include "legic.h" | |
21 | #include "crc.h" | |
53edb044 | 22 | #include "usb_cdc.h" // for usb_poll_validate_length |
fc52fbd4 | 23 | #include "fpgaloader.h" |
1b902aa0 A |
24 | |
25 | static uint8_t* legic_mem; /* card memory, used for sim */ | |
26 | static legic_card_select_t card;/* metadata of currently selected card */ | |
27 | static crc_t legic_crc; | |
28 | ||
29 | //----------------------------------------------------------------------------- | |
30 | // Frame timing and pseudorandom number generator | |
31 | // | |
32 | // The Prng is forwarded every 99.1us (TAG_BIT_PERIOD), except when the reader is | |
33 | // transmitting. In that case the prng has to be forwarded every bit transmitted: | |
34 | // - 31.3us for a 0 (RWD_TIME_0) | |
35 | // - 99.1us for a 1 (RWD_TIME_1) | |
36 | // | |
37 | // The data dependent timing makes writing comprehensible code significantly | |
38 | // harder. The current aproach forwards the prng data based if there is data on | |
39 | // air and time based, using GetCountSspClk(), during computational and wait | |
40 | // periodes. SSP Clock is clocked by the FPGA at 212 kHz (subcarrier frequency). | |
41 | // | |
42 | // To not have the necessity to calculate/guess exection time dependend timeouts | |
43 | // tx_frame and rx_frame use a shared timestamp to coordinate tx and rx timeslots. | |
44 | //----------------------------------------------------------------------------- | |
45 | ||
46 | static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */ | |
47 | ||
48 | #define TAG_FRAME_WAIT 70 /* 330us from READER frame end to TAG frame start */ | |
49 | #define TAG_ACK_WAIT 758 /* 3.57ms from READER frame end to TAG write ACK */ | |
50 | #define TAG_BIT_PERIOD 21 /* 99.1us */ | |
51 | ||
52 | #define RWD_TIME_PAUSE 4 /* 18.9us */ | |
53 | #define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */ | |
54 | #define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */ | |
437035a7 | 55 | #define RWD_CMD_TIMEOUT 120 /* 120 * 99.1us (arbitrary value) */ |
1b902aa0 A |
56 | #define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */ |
57 | #define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */ | |
58 | ||
59 | #define RWD_PULSE 1 /* Pulse is signaled with GPIO_SSC_DIN high */ | |
60 | #define RWD_PAUSE 0 /* Pause is signaled with GPIO_SSC_DIN low */ | |
61 | ||
62 | //----------------------------------------------------------------------------- | |
63 | // Demodulation | |
64 | //----------------------------------------------------------------------------- | |
65 | ||
66 | // Returns true if a pulse/pause is received within timeout | |
67 | static inline bool wait_for(bool value, const uint32_t timeout) { | |
68 | while((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) { | |
69 | if(GetCountSspClk() > timeout) { | |
70 | return false; | |
71 | } | |
72 | } | |
73 | return true; | |
74 | } | |
75 | ||
76 | // Returns a demedulated bit or -1 on code violation | |
77 | // | |
78 | // rx_bit decodes bits using a thresholds. rx_bit has to be called by as soon as | |
79 | // a frame starts (first pause is received). rx_bit checks for a pause up to | |
80 | // 18.9us followed by a pulse of 80.2us or 42.4us: | |
81 | // - A bit length <18.9us is a code violation | |
82 | // - A bit length >80.2us is a 1 | |
83 | // - A bit length <80.2us is a 0 | |
84 | // - A bit length >148.6us is a code violation | |
85 | static inline int8_t rx_bit() { | |
86 | // backup ts for threshold calculation | |
87 | uint32_t bit_start = last_frame_end; | |
88 | ||
89 | // wait for pause to end | |
90 | if(!wait_for(RWD_PULSE, bit_start + RWD_TIME_1*3/2)) { | |
91 | return -1; | |
92 | } | |
93 | ||
94 | // wait for next pause | |
95 | if(!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1*3/2)) { | |
96 | return -1; | |
97 | } | |
98 | ||
99 | // update bit and frame end | |
100 | last_frame_end = GetCountSspClk(); | |
101 | ||
102 | // check for code violation (bit to short) | |
103 | if(last_frame_end - bit_start < RWD_TIME_PAUSE) { | |
104 | return -1; | |
105 | } | |
106 | ||
107 | // apply threshold (average of RWD_TIME_0 and ) | |
108 | return (last_frame_end - bit_start > (RWD_TIME_0 + RWD_TIME_1) / 2); | |
109 | } | |
110 | ||
111 | //----------------------------------------------------------------------------- | |
112 | // Modulation | |
113 | // | |
114 | // LEGIC RF uses a very basic load modulation from card to reader: | |
115 | // - Subcarrier on for a 1 | |
116 | // - Subcarrier off for for a 0 | |
117 | // | |
118 | // The 212kHz subcarrier is generated by the FPGA as well as a mathcing ssp clk. | |
119 | // Each bit is transfered in a 99.1us slot and the first timeslot starts 330us | |
120 | // after the final 20us pause generated by the reader. | |
121 | //----------------------------------------------------------------------------- | |
122 | ||
123 | // Transmits a bit | |
124 | // | |
125 | // Note: The Subcarrier is not disabled during bits to prevent glitches. This is | |
126 | // not mandatory but results in a cleaner signal. tx_frame will disable | |
127 | // the subcarrier when the frame is done. | |
128 | static inline void tx_bit(bool bit) { | |
129 | LED_C_ON(); | |
130 | ||
131 | if(bit) { | |
132 | // modulate subcarrier | |
133 | HIGH(GPIO_SSC_DOUT); | |
134 | } else { | |
135 | // do not modulate subcarrier | |
136 | LOW(GPIO_SSC_DOUT); | |
137 | } | |
138 | ||
139 | // wait for tx timeslot to end | |
140 | last_frame_end += TAG_BIT_PERIOD; | |
141 | while(GetCountSspClk() < last_frame_end) { }; | |
142 | LED_C_OFF(); | |
143 | } | |
144 | ||
145 | //----------------------------------------------------------------------------- | |
146 | // Frame Handling | |
147 | // | |
148 | // The LEGIC RF protocol from reader to card does not include explicit frame | |
149 | // start/stop information or length information. The tag detects end of frame | |
150 | // trough an extended pulse (>99.1us) without a pause. | |
151 | // In reverse direction (card to reader) the number of bites is well known | |
152 | // and depends only the command received (IV, ACK, READ or WRITE). | |
153 | //----------------------------------------------------------------------------- | |
154 | ||
155 | static void tx_frame(uint32_t frame, uint8_t len) { | |
156 | // wait for next tx timeslot | |
157 | last_frame_end += TAG_FRAME_WAIT; | |
158 | legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1); | |
159 | while(GetCountSspClk() < last_frame_end) { }; | |
160 | ||
161 | // transmit frame, MSB first | |
162 | for(uint8_t i = 0; i < len; ++i) { | |
163 | bool bit = (frame >> i) & 0x01; | |
164 | tx_bit(bit ^ legic_prng_get_bit()); | |
165 | legic_prng_forward(1); | |
166 | }; | |
167 | ||
168 | // disable subcarrier | |
169 | LOW(GPIO_SSC_DOUT); | |
170 | } | |
171 | ||
172 | static void tx_ack() { | |
173 | // wait for ack timeslot | |
174 | last_frame_end += TAG_ACK_WAIT; | |
175 | legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1); | |
176 | while(GetCountSspClk() < last_frame_end) { }; | |
177 | ||
178 | // transmit ack (ack is not encrypted) | |
179 | tx_bit(true); | |
180 | legic_prng_forward(1); | |
181 | ||
182 | // disable subcarrier | |
183 | LOW(GPIO_SSC_DOUT); | |
184 | } | |
185 | ||
186 | // Returns a demedulated frame or -1 on code violation | |
187 | // | |
188 | // Since TX to RX delay is arbitrary rx_frame has to: | |
189 | // - detect start of frame (first pause) | |
190 | // - forward prng based on ts/TAG_BIT_PERIOD | |
191 | // - receive the frame | |
192 | // - detect end of frame (last pause) | |
193 | static int32_t rx_frame(uint8_t *len) { | |
194 | int32_t frame = 0; | |
195 | ||
196 | // add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay) | |
197 | // those will be substracted at the end of the rx phase | |
198 | last_frame_end -= 2; | |
199 | ||
200 | // wait for first pause (start of frame) | |
201 | for(uint8_t i = 0; true; ++i) { | |
202 | // increment prng every TAG_BIT_PERIOD | |
203 | last_frame_end += TAG_BIT_PERIOD; | |
204 | legic_prng_forward(1); | |
205 | ||
206 | // if start of frame was received exit delay loop | |
207 | if(wait_for(RWD_PAUSE, last_frame_end)) { | |
208 | last_frame_end = GetCountSspClk(); | |
209 | break; | |
210 | } | |
211 | ||
212 | // check for code violation | |
213 | if(i > RWD_CMD_TIMEOUT) { | |
214 | return -1; | |
215 | } | |
216 | } | |
217 | ||
218 | // receive frame | |
219 | for(*len = 0; true; ++(*len)) { | |
220 | // receive next bit | |
221 | LED_D_ON(); | |
222 | int8_t bit = rx_bit(); | |
223 | LED_D_OFF(); | |
224 | ||
225 | // check for code violation and to short / long frame | |
226 | if((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) { | |
227 | return -1; | |
228 | } | |
229 | ||
230 | // check for code violation caused by end of frame | |
231 | if(bit < 0) { | |
232 | break; | |
233 | } | |
234 | ||
235 | // append bit | |
236 | frame |= (bit ^ legic_prng_get_bit()) << (*len); | |
237 | legic_prng_forward(1); | |
238 | } | |
239 | ||
240 | // rx_bit sets coordination timestamp to start of pause, append pause duration | |
241 | // and substract 2 SSP clock cycles (1 for rx and 1 for tx pipeline delay) to | |
242 | // obtain exact end of frame. | |
243 | last_frame_end += RWD_TIME_PAUSE - 2; | |
244 | ||
245 | return frame; | |
246 | } | |
247 | ||
248 | //----------------------------------------------------------------------------- | |
249 | // Legic Simulator | |
250 | //----------------------------------------------------------------------------- | |
251 | ||
252 | static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) { | |
253 | p_card->tagtype = cardtype; | |
254 | ||
255 | switch(p_card->tagtype) { | |
256 | case 0: | |
257 | p_card->cmdsize = 6; | |
258 | p_card->addrsize = 5; | |
259 | p_card->cardsize = 22; | |
260 | break; | |
261 | case 1: | |
262 | p_card->cmdsize = 9; | |
263 | p_card->addrsize = 8; | |
264 | p_card->cardsize = 256; | |
265 | break; | |
266 | case 2: | |
267 | p_card->cmdsize = 11; | |
268 | p_card->addrsize = 10; | |
269 | p_card->cardsize = 1024; | |
270 | break; | |
271 | default: | |
272 | p_card->cmdsize = 0; | |
273 | p_card->addrsize = 0; | |
274 | p_card->cardsize = 0; | |
275 | return 2; | |
276 | } | |
277 | return 0; | |
278 | } | |
279 | ||
280 | static void init_tag() { | |
281 | // configure FPGA | |
282 | FpgaDownloadAndGo(FPGA_BITSTREAM_HF); | |
283 | FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | |
284 | | FPGA_HF_SIMULATOR_MODULATE_212K); | |
285 | SetAdcMuxFor(GPIO_MUXSEL_HIPKD); | |
286 | ||
287 | // configure SSC with defaults | |
6a5d4e17 | 288 | FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR); |
1b902aa0 A |
289 | |
290 | // first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT | |
291 | LOW(GPIO_SSC_DOUT); | |
292 | AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; | |
293 | AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; | |
294 | ||
295 | // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. | |
296 | legic_mem = BigBuf_get_addr(); | |
297 | ||
298 | // init crc calculator | |
299 | crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0); | |
300 | ||
301 | // start 212kHz timer (running from SSP Clock) | |
302 | StartCountSspClk(); | |
303 | } | |
304 | ||
305 | // Setup reader to card connection | |
306 | // | |
307 | // The setup consists of a three way handshake: | |
308 | // - Receive initialisation vector 7 bits | |
309 | // - Transmit card type 6 bits | |
310 | // - Receive Acknowledge 6 bits | |
311 | static int32_t setup_phase(legic_card_select_t *p_card) { | |
312 | uint8_t len = 0; | |
313 | ||
314 | // init coordination timestamp | |
315 | last_frame_end = GetCountSspClk(); | |
316 | ||
317 | // reset prng | |
318 | legic_prng_init(0); | |
319 | ||
320 | // wait for iv | |
321 | int32_t iv = rx_frame(&len); | |
322 | if((len != 7) || (iv < 0)) { | |
323 | return -1; | |
324 | } | |
325 | ||
326 | // configure prng | |
327 | legic_prng_init(iv); | |
328 | ||
329 | // reply with card type | |
330 | switch(p_card->tagtype) { | |
331 | case 0: | |
332 | tx_frame(0x0D, 6); | |
333 | break; | |
334 | case 1: | |
335 | tx_frame(0x1D, 6); | |
336 | break; | |
337 | case 2: | |
338 | tx_frame(0x3D, 6); | |
339 | break; | |
340 | } | |
341 | ||
342 | // wait for ack | |
343 | int32_t ack = rx_frame(&len); | |
344 | if((len != 6) || (ack < 0)) { | |
345 | return -1; | |
346 | } | |
347 | ||
348 | // validate data | |
349 | switch(p_card->tagtype) { | |
350 | case 0: | |
351 | if(ack != 0x19) return -1; | |
352 | break; | |
353 | case 1: | |
354 | if(ack != 0x39) return -1; | |
355 | break; | |
356 | case 2: | |
357 | if(ack != 0x39) return -1; | |
358 | break; | |
359 | } | |
360 | ||
361 | // During rx the prng is clocked using the variable reader period. | |
362 | // Since rx_frame detects end of frame by detecting a code violation, | |
363 | // the prng is off by one bit period after each rx phase. Hence, tx | |
364 | // code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1). | |
365 | // This is not possible for back to back rx, so this quirk reduces | |
366 | // the gap by one period. | |
367 | last_frame_end += TAG_BIT_PERIOD; | |
368 | ||
369 | return 0; | |
370 | } | |
371 | ||
372 | static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) { | |
373 | crc_clear(&legic_crc); | |
374 | crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz); | |
375 | return crc_finish(&legic_crc); | |
376 | } | |
377 | ||
378 | static int32_t connected_phase(legic_card_select_t *p_card) { | |
379 | uint8_t len = 0; | |
380 | ||
381 | // wait for command | |
382 | int32_t cmd = rx_frame(&len); | |
383 | if(cmd < 0) { | |
384 | return -1; | |
385 | } | |
386 | ||
387 | // check if command is LEGIC_READ | |
388 | if(len == p_card->cmdsize) { | |
389 | // prepare data | |
390 | uint8_t byte = legic_mem[cmd >> 1]; | |
391 | uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte); | |
392 | ||
393 | // transmit data | |
394 | tx_frame((crc << 8) | byte, 12); | |
395 | ||
396 | return 0; | |
397 | } | |
398 | ||
399 | // check if command is LEGIC_WRITE | |
400 | if(len == p_card->cmdsize + 8 + 4) { | |
401 | // decode data | |
402 | uint16_t mask = (1 << p_card->addrsize) - 1; | |
403 | uint16_t addr = (cmd >> 1) & mask; | |
404 | uint8_t byte = (cmd >> p_card->cmdsize) & 0xff; | |
405 | uint8_t crc = (cmd >> (p_card->cmdsize + 8)) & 0xf; | |
406 | ||
407 | // check received against calculated crc | |
408 | uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte); | |
409 | if(calc_crc != crc) { | |
410 | Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc); | |
411 | return -1; | |
412 | } | |
413 | ||
414 | // store data | |
415 | legic_mem[addr] = byte; | |
416 | ||
417 | // transmit ack | |
418 | tx_ack(); | |
419 | ||
420 | return 0; | |
421 | } | |
422 | ||
423 | return -1; | |
424 | } | |
425 | ||
426 | //----------------------------------------------------------------------------- | |
427 | // Command Line Interface | |
428 | // | |
429 | // Only this function is public / called from appmain.c | |
430 | //----------------------------------------------------------------------------- | |
431 | ||
432 | void LegicRfSimulate(uint8_t cardtype) { | |
433 | // configure ARM and FPGA | |
434 | init_tag(); | |
435 | ||
436 | // verify command line input | |
437 | if(init_card(cardtype, &card) != 0) { | |
438 | DbpString("Unknown tagtype."); | |
439 | goto OUT; | |
440 | } | |
441 | ||
442 | LED_A_ON(); | |
443 | DbpString("Starting Legic emulator, press button to end"); | |
53edb044 | 444 | while(!BUTTON_PRESS() && !usb_poll_validate_length()) { |
1b902aa0 A |
445 | WDT_HIT(); |
446 | ||
447 | // wait for carrier, restart after timeout | |
448 | if(!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) { | |
449 | continue; | |
450 | } | |
451 | ||
452 | // wait for connection, restart on error | |
453 | if(setup_phase(&card)) { | |
454 | continue; | |
455 | } | |
456 | ||
457 | // conection is established, process commands until one fails | |
458 | while(!connected_phase(&card)) { | |
459 | WDT_HIT(); | |
460 | } | |
461 | } | |
462 | ||
463 | OUT: | |
464 | DbpString("Stopped"); | |
465 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); | |
466 | LED_A_OFF(); | |
467 | LED_C_OFF(); | |
468 | LED_D_OFF(); | |
469 | StopTicks(); | |
470 | } |