]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/pcf7931.c
gcc10 compiler fixes:
[proxmark3-svn] / armsrc / pcf7931.c
... / ...
CommitLineData
1#include "proxmark3.h"
2#include "apps.h"
3#include "usb_cdc.h"
4#include "lfsampling.h"
5#include "pcf7931.h"
6#include "util.h"
7#include "string.h"
8#include "fpgaloader.h"
9
10#define T0_PCF 8 //period for the pcf7931 in us
11#define ALLOC 16
12
13size_t DemodPCF7931(uint8_t **outBlocks) {
14 uint8_t bits[256] = {0x00};
15 uint8_t blocks[8][16];
16 uint8_t *dest = BigBuf_get_addr();
17
18 int GraphTraceLen = BigBuf_max_traceLen();
19 if (GraphTraceLen > 18000)
20 GraphTraceLen = 18000;
21
22 int i, j, lastval, bitidx, half_switch;
23 int clock = 64;
24 int tolerance = clock / 8;
25 int pmc, block_done;
26 int lc, warnings = 0;
27 size_t num_blocks = 0;
28 int lmin=128, lmax=128;
29 uint8_t dir;
30 //clear read buffer
31 BigBuf_Clear_keep_EM();
32
33 LFSetupFPGAForADC(95, true);
34 DoAcquisition_default(0, true);
35
36 lmin = 64;
37 lmax = 192;
38
39 i = 2;
40
41 /* Find first local max/min */
42 if(dest[1] > dest[0]) {
43 while(i < GraphTraceLen) {
44 if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
45 break;
46 i++;
47 }
48 dir = 0;
49 } else {
50 while(i < GraphTraceLen) {
51 if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
52 break;
53 i++;
54 }
55 dir = 1;
56 }
57
58 lastval = i++;
59 half_switch = 0;
60 pmc = 0;
61 block_done = 0;
62
63 for (bitidx = 0; i < GraphTraceLen; i++) {
64 if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) {
65 lc = i - lastval;
66 lastval = i;
67
68 // Switch depending on lc length:
69 // Tolerance is 1/8 of clock rate (arbitrary)
70 if (ABS(lc-clock/4) < tolerance) {
71 // 16T0
72 if((i - pmc) == lc) { /* 16T0 was previous one */
73 /* It's a PMC ! */
74 i += (128+127+16+32+33+16)-1;
75 lastval = i;
76 pmc = 0;
77 block_done = 1;
78 } else {
79 pmc = i;
80 }
81 } else if (ABS(lc-clock/2) < tolerance) {
82 // 32TO
83 if((i - pmc) == lc) { /* 16T0 was previous one */
84 /* It's a PMC ! */
85 i += (128+127+16+32+33)-1;
86 lastval = i;
87 pmc = 0;
88 block_done = 1;
89 } else if(half_switch == 1) {
90 bits[bitidx++] = 0;
91 half_switch = 0;
92 }
93 else
94 half_switch++;
95 } else if (ABS(lc-clock) < tolerance) {
96 // 64TO
97 bits[bitidx++] = 1;
98 } else {
99 // Error
100 if (++warnings > 10) {
101 Dbprintf("Error: too many detection errors, aborting.");
102 return 0;
103 }
104 }
105
106 if(block_done == 1) {
107 if(bitidx == 128) {
108 for(j = 0; j < 16; ++j) {
109 blocks[num_blocks][j] =
110 128 * bits[j*8 + 7]+
111 64 * bits[j*8 + 6] +
112 32 * bits[j*8 + 5] +
113 16 * bits[j*8 + 4] +
114 8 * bits[j*8 + 3] +
115 4 * bits[j*8 + 2] +
116 2 * bits[j*8 + 1] +
117 bits[j*8]
118 ;
119 }
120 num_blocks++;
121 }
122 bitidx = 0;
123 block_done = 0;
124 half_switch = 0;
125 }
126 if(i < GraphTraceLen)
127 dir = (dest[i-1] > dest[i]) ? 0 : 1;
128 }
129 if(bitidx==255)
130 bitidx=0;
131 warnings = 0;
132 if(num_blocks == 4) break;
133 }
134 memcpy(outBlocks, blocks, 16 * num_blocks);
135 return num_blocks;
136}
137
138bool IsBlock0PCF7931(uint8_t *block) {
139 // assuming all RFU bits are set to 0
140 // if PAC is enabled password is set to 0
141 if (block[7] == 0x01)
142 {
143 if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
144 return true;
145 }
146 else if (block[7] == 0x00)
147 {
148 if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
149 return true;
150 }
151 return false;
152}
153
154bool IsBlock1PCF7931(uint8_t *block) {
155 // assuming all RFU bits are set to 0
156
157 uint8_t rb1 = block[14] & 0x80;
158 uint8_t rfb = block[14] & 0x7f;
159 uint8_t rlb = block[15];
160
161 if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0)
162 // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled
163 if(rfb <= rlb && rfb <= 9 && rlb <= 9 && ((rfb <= 1 && rlb >= 1) || rb1))
164 return true;
165
166 return false;
167}
168
169void ReadPCF7931() {
170 int found_blocks = 0; // successfully read blocks
171 int max_blocks = 8; // readable blocks
172 uint8_t memory_blocks[8][17]; // PCF content
173
174 uint8_t single_blocks[8][17]; // PFC blocks with unknown position
175 int single_blocks_cnt = 0;
176
177 size_t n = 0; // transmitted blocks
178 uint8_t tmp_blocks[4][16]; // temporary read buffer
179
180 uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found
181 int errors = 0; // error counter
182 int tries = 0; // tries counter
183
184 memset(memory_blocks, 0, 8*17*sizeof(uint8_t));
185 memset(single_blocks, 0, 8*17*sizeof(uint8_t));
186
187 int i = 0, j = 0;
188
189 do {
190 i = 0;
191
192 memset(tmp_blocks, 0, 4*16*sizeof(uint8_t));
193 n = DemodPCF7931((uint8_t**)tmp_blocks);
194 if(!n)
195 ++errors;
196
197 // exit if no block is received
198 if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) {
199 Dbprintf("Error, no tag or bad tag");
200 return;
201 }
202
203 // exit if too many errors during reading
204 if (tries > 50 && (2*errors > tries)) {
205 Dbprintf("Error reading the tag");
206 Dbprintf("Here is the partial content");
207 goto end;
208 }
209
210 // our logic breaks if we don't get at least two blocks
211 if (n < 2) {
212 // skip if all 0s block or no blocks
213 if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
214 continue;
215
216 // add block to single blocks list
217 if (single_blocks_cnt < max_blocks) {
218 for (i = 0; i < single_blocks_cnt; ++i) {
219 if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) {
220 j = 1;
221 break;
222 }
223 }
224 if (j != 1) {
225 memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16);
226 print_result("got single block", single_blocks[single_blocks_cnt], 16);
227 single_blocks_cnt++;
228 }
229 j = 0;
230 }
231 ++tries;
232 continue;
233 }
234
235 Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors);
236 for (i = 0; i < n; ++i)
237 {
238 print_result("got consecutive blocks", tmp_blocks[i], 16);
239 }
240
241 i = 0;
242 if(!found_0_1) {
243 while (i < n - 1) {
244 if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) {
245 found_0_1 = 1;
246 memcpy(memory_blocks[0], tmp_blocks[i], 16);
247 memcpy(memory_blocks[1], tmp_blocks[i+1], 16);
248 memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1;
249 // block 1 tells how many blocks are going to be sent
250 max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1;
251 found_blocks = 2;
252
253 Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks);
254
255 // handle the following blocks
256 for (j = i + 2; j < n; ++j) {
257 memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16);
258 memory_blocks[found_blocks][ALLOC] = 1;
259 ++found_blocks;
260 }
261 break;
262 }
263 ++i;
264 }
265 } else {
266 // Trying to re-order blocks
267 // Look for identical block in memory blocks
268 while (i < n-1) {
269 // skip all zeroes blocks
270 if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
271 for (j = 1; j < max_blocks - 1; ++j) {
272 if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) {
273 memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16);
274 memory_blocks[j+1][ALLOC] = 1;
275 if (++found_blocks >= max_blocks) goto end;
276 }
277 }
278 }
279 if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
280 for (j = 0; j < max_blocks; ++j) {
281 if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) {
282 if (j == 0) {
283 memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16);
284 memory_blocks[max_blocks - 1][ALLOC] = 1;
285 } else {
286 memcpy(memory_blocks[j-1], tmp_blocks[i], 16);
287 memory_blocks[j-1][ALLOC] = 1;
288 }
289 if (++found_blocks >= max_blocks) goto end;
290 }
291 }
292 }
293 ++i;
294 }
295 }
296 ++tries;
297 if (BUTTON_PRESS()) {
298 Dbprintf("Button pressed, stopping.");
299 goto end;
300 }
301 }
302 while (found_blocks < max_blocks);
303
304 end:
305 Dbprintf("-----------------------------------------");
306 Dbprintf("Memory content:");
307 Dbprintf("-----------------------------------------");
308 for (i = 0; i < max_blocks; ++i) {
309 if (memory_blocks[i][ALLOC])
310 print_result("Block", memory_blocks[i], 16);
311 else
312 Dbprintf("<missing block %d>", i);
313 }
314 Dbprintf("-----------------------------------------");
315
316 if (found_blocks < max_blocks) {
317 Dbprintf("-----------------------------------------");
318 Dbprintf("Blocks with unknown position:");
319 Dbprintf("-----------------------------------------");
320 for (i = 0; i < single_blocks_cnt; ++i)
321 print_result("Block", single_blocks[i], 16);
322
323 Dbprintf("-----------------------------------------");
324 }
325 cmd_send(CMD_ACK,0,0,0,0,0);
326}
327
328static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
329 uint32_t tab[1024]={0}; // data times frame
330 uint32_t u = 0;
331 uint8_t parity = 0;
332 bool comp = 0;
333
334 //BUILD OF THE DATA FRAME
335 //alimentation of the tag (time for initializing)
336 AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
337 AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
338 //password indication bit
339 AddBitPCF7931(1, tab, l, p);
340 // password (on 56 bits)
341 AddBytePCF7931(pass[0], tab, l, p);
342 AddBytePCF7931(pass[1], tab, l, p);
343 AddBytePCF7931(pass[2], tab, l, p);
344 AddBytePCF7931(pass[3], tab, l, p);
345 AddBytePCF7931(pass[4], tab, l, p);
346 AddBytePCF7931(pass[5], tab, l, p);
347 AddBytePCF7931(pass[6], tab, l, p);
348 //programming mode (0 or 1)
349 AddBitPCF7931(0, tab, l, p);
350
351 //block adress on 6 bits
352 for (u = 0; u < 6; ++u) {
353 if (address & (1 << u)) { // bit 1
354 ++parity;
355 AddBitPCF7931(1, tab, l, p);
356 } else { // bit 0
357 AddBitPCF7931(0, tab, l, p);
358 }
359 }
360
361 //byte address on 4 bits
362 for (u = 0; u < 4; ++u)
363 {
364 if (byte & (1 << u)) { // bit 1
365 parity++;
366 AddBitPCF7931(1, tab, l, p);
367 }
368 else // bit 0
369 AddBitPCF7931(0, tab, l, p);
370 }
371
372 //data on 8 bits
373 for (u=0; u<8; u++)
374 {
375 if (data&(1<<u)) { // bit 1
376 parity++;
377 AddBitPCF7931(1, tab, l, p);
378 }
379 else //bit 0
380 AddBitPCF7931(0, tab, l, p);
381 }
382
383 //parity bit
384 if ((parity % 2) == 0)
385 AddBitPCF7931(0, tab, l, p); //even parity
386 else
387 AddBitPCF7931(1, tab, l, p);//odd parity
388
389 //time access memory
390 AddPatternPCF7931(5120+2680, 0, 0, tab);
391
392 //conversion of the scale time
393 for (u = 0; u < 500; ++u)
394 tab[u] = (tab[u] * 3) / 2;
395
396 //compennsation of the counter reload
397 while (!comp) {
398 comp = 1;
399 for (u = 0; tab[u] != 0; ++u)
400 if(tab[u] > 0xFFFF) {
401 tab[u] -= 0xFFFF;
402 comp = 0;
403 }
404 }
405
406 SendCmdPCF7931(tab);
407}
408
409void BruteForcePCF7931(uint64_t password, uint8_t tries, uint16_t init_delay, int32_t l, int32_t p) {
410 uint8_t i = 0;
411 uint8_t pass_array[7];
412
413 while (password < 0x00FFFFFFFFFFFFFF) {
414 if (BUTTON_PRESS()) {
415 Dbprintf("Button pressed, stopping bruteforce ...");
416 return;
417 }
418
419 num_to_bytes(password, 7, pass_array);
420
421 Dbprintf("Trying: %02x %02x %02x %02x %02x %02x %02x ...",
422 pass_array[0],
423 pass_array[1],
424 pass_array[2],
425 pass_array[3],
426 pass_array[4],
427 pass_array[5],
428 pass_array[6]);
429
430 for (i = 0; i < tries; ++i)
431 RealWritePCF7931
432 (
433 pass_array,
434 init_delay,
435 l,
436 p,
437 0,
438 7,
439 0x01
440 );
441
442 ++password;
443 }
444}
445
446/* Write on a byte of a PCF7931 tag
447 * @param address : address of the block to write
448 @param byte : address of the byte to write
449 @param data : data to write
450 */
451void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
452 Dbprintf("Initialization delay : %d us", init_delay);
453 Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
454 Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7);
455 Dbprintf("Block address : %02x", address);
456 Dbprintf("Byte address : %02x", byte);
457 Dbprintf("Data : %02x", data);
458
459 uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7};
460
461 RealWritePCF7931 (password, init_delay, l, p, address, byte, data);
462}
463
464
465
466/* Send a trame to a PCF7931 tags
467 * @param tab : array of the data frame
468 */
469
470void SendCmdPCF7931(uint32_t * tab) {
471 uint16_t u=0;
472 uint16_t tempo=0;
473
474 Dbprintf("Sending data frame ...");
475
476 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
477 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
478 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
479
480 LED_A_ON();
481
482 // steal this pin from the SSP and use it to control the modulation
483 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
484 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
485
486 //initialization of the timer
487 AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
488 AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
489 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
490 AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
491 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
492 AT91C_BASE_TCB->TCB_BCR = 1;
493
494 tempo = AT91C_BASE_TC0->TC_CV;
495 for (u = 0; tab[u] != 0; u += 3) {
496 // modulate antenna
497 HIGH(GPIO_SSC_DOUT);
498 while(tempo != tab[u])
499 tempo = AT91C_BASE_TC0->TC_CV;
500
501 // stop modulating antenna
502 LOW(GPIO_SSC_DOUT);
503 while(tempo != tab[u+1])
504 tempo = AT91C_BASE_TC0->TC_CV;
505
506 // modulate antenna
507 HIGH(GPIO_SSC_DOUT);
508 while(tempo != tab[u+2])
509 tempo = AT91C_BASE_TC0->TC_CV;
510 }
511
512 LED_A_OFF();
513 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
514 SpinDelay(200);
515
516 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
517 DbpString("Data frame sent (multiple sends may be needed)");
518 LED(0xFFFF, 1000);
519}
520
521
522/* Add a byte for building the data frame of PCF7931 tags
523 * @param b : byte to add
524 * @param tab : array of the data frame
525 * @param l : offset on low pulse width
526 * @param p : offset on low pulse positioning
527 */
528bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p) {
529 uint32_t u;
530 for (u = 0; u < 8; ++u) {
531 if (byte & (1 << u)) { //bit is 1
532 if(AddBitPCF7931(1, tab, l, p)==1)return 1;
533 } else { //bit is 0
534 if(AddBitPCF7931(0, tab, l, p)==1)return 1;
535 }
536 }
537
538 return 0;
539}
540
541/* Add a bits for building the data frame of PCF7931 tags
542 * @param b : bit to add
543 * @param tab : array of the data frame
544 * @param l : offset on low pulse width
545 * @param p : offset on low pulse positioning
546 */
547bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p) {
548 uint8_t u = 0;
549
550 for (u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array
551
552 if (b == 1) { //add a bit 1
553 if (u == 0) tab[u] = 34 * T0_PCF + p;
554 else tab[u] = 34 * T0_PCF + tab[u-1] + p;
555
556 tab[u+1] = 6 * T0_PCF+tab[u] + l;
557 tab[u+2] = 88 * T0_PCF+tab[u + 1] - l - p;
558 return 0;
559 } else { //add a bit 0
560
561 if (u == 0) tab[u] = 98 * T0_PCF + p;
562 else tab[u] = 98 * T0_PCF + tab[u-1] + p;
563
564 tab[u + 1] = 6 * T0_PCF + tab[u] + l;
565 tab[u + 2] = 24 * T0_PCF + tab[u + 1] - l - p;
566 return 0;
567 }
568
569 return 1;
570}
571
572/* Add a custom pattern in the data frame
573 * @param a : delay of the first high pulse
574 * @param b : delay of the low pulse
575 * @param c : delay of the last high pulse
576 * @param tab : array of the data frame
577 */
578bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab) {
579 uint32_t u = 0;
580 for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array
581
582 if (u == 0) tab[u] = a;
583 else tab[u] = a + tab[u - 1];
584
585 tab[u + 1] = b + tab[u];
586 tab[u + 2] = c + tab[u + 1];
587
588 return 0;
589}
Impressum, Datenschutz