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