1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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 //-----------------------------------------------------------------------------
18 #include "proxmark3_arm.h"
21 #include "fpgaloader.h"
25 #include "lfsampling.h"
28 #define T0_PCF 8 //period for the pcf7931 in us
31 size_t DemodPCF7931(uint8_t **outBlocks
, bool ledcontrol
) {
34 uint8_t bits
[256] = {0x00};
35 uint8_t blocks
[8][16];
37 uint8_t *dest
= BigBuf_get_addr();
39 int g_GraphTraceLen
= BigBuf_max_traceLen();
40 if (g_GraphTraceLen
> 18000) {
41 g_GraphTraceLen
= 18000;
44 int i
= 2, j
, lastval
, bitidx
, half_switch
;
46 int tolerance
= clock
/ 8;
49 size_t num_blocks
= 0;
50 int lmin
= 64, lmax
= 192;
53 BigBuf_Clear_keep_EM();
54 LFSetupFPGAForADC(LF_DIVISOR_125
, true);
55 DoAcquisition_default(0, true, ledcontrol
);
57 /* Find first local max/min */
58 if (dest
[1] > dest
[0]) {
59 while (i
< g_GraphTraceLen
) {
60 if (!(dest
[i
] > dest
[i
- 1]) && dest
[i
] > lmax
) {
67 while (i
< g_GraphTraceLen
) {
68 if (!(dest
[i
] < dest
[i
- 1]) && dest
[i
] < lmin
) {
81 for (bitidx
= 0; i
< g_GraphTraceLen
; i
++) {
83 if ((dest
[i
- 1] > dest
[i
] && dir
== 1 && dest
[i
] > lmax
) || (dest
[i
- 1] < dest
[i
] && dir
== 0 && dest
[i
] < lmin
)) {
87 // Switch depending on lc length:
88 // Tolerance is 1/8 of clock rate (arbitrary)
89 if (ABS(lc
- clock
/ 4) < tolerance
) {
91 if ((i
- pmc
) == lc
) { // 16T0 was previous one
93 i
+= (128 + 127 + 16 + 32 + 33 + 16) - 1;
100 } else if (ABS(lc
- clock
/ 2) < tolerance
) {
102 if ((i
- pmc
) == lc
) { // 16T0 was previous one
104 i
+= (128 + 127 + 16 + 32 + 33) - 1;
108 } else if (half_switch
== 1) {
113 } else if (ABS(lc
- clock
) < tolerance
) {
118 if (++warnings
> 10) {
120 if (g_dbglevel
>= DBG_EXTENDED
) {
121 Dbprintf("Error: too many detection errors, aborting");
128 if (block_done
== 1) {
130 for (j
= 0; j
< 16; ++j
) {
131 blocks
[num_blocks
][j
] =
132 128 * bits
[j
* 8 + 7] +
133 64 * bits
[j
* 8 + 6] +
134 32 * bits
[j
* 8 + 5] +
135 16 * bits
[j
* 8 + 4] +
136 8 * bits
[j
* 8 + 3] +
137 4 * bits
[j
* 8 + 2] +
138 2 * bits
[j
* 8 + 1] +
149 if (i
< g_GraphTraceLen
) {
150 dir
= (dest
[i
- 1] > dest
[i
]) ? 0 : 1;
158 if (num_blocks
== 4) {
162 memcpy(outBlocks
, blocks
, 16 * num_blocks
);
166 bool IsBlock0PCF7931(uint8_t *block
) {
167 // assuming all RFU bits are set to 0
168 // if PAC is enabled password is set to 0
169 if (block
[7] == 0x01) {
170 if (!memcmp(block
, "\x00\x00\x00\x00\x00\x00\x00", 7) &&
171 !memcmp(block
+ 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) {
175 } else if (block
[7] == 0x00) {
176 if (!memcmp(block
+ 9, "\x00\x00\x00\x00\x00\x00\x00", 7)) {
183 bool IsBlock1PCF7931(const uint8_t *block
) {
184 // assuming all RFU bits are set to 0
186 uint8_t rb1
= block
[14] & 0x80;
187 uint8_t rfb
= block
[14] & 0x7f;
188 uint8_t rlb
= block
[15];
194 // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled
198 && ((rfb
<= 1 && rlb
>= 1) || rb1
)) {
206 void ReadPCF7931(bool ledcontrol
) {
207 int found_blocks
= 0; // successfully read blocks
208 int max_blocks
= 8; // readable blocks
209 uint8_t memory_blocks
[8][17]; // PCF content
210 uint8_t single_blocks
[8][17]; // PFC blocks with unknown position
211 int single_blocks_cnt
= 0;
213 size_t n
; // transmitted blocks
214 uint8_t tmp_blocks
[4][16]; // temporary read buffer
216 uint8_t found_0_1
= 0; // flag: blocks 0 and 1 were found
217 int errors
= 0; // error counter
218 int tries
= 0; // tries counter
220 memset(memory_blocks
, 0, 8 * 17 * sizeof(uint8_t));
221 memset(single_blocks
, 0, 8 * 17 * sizeof(uint8_t));
228 memset(tmp_blocks
, 0, 4 * 16 * sizeof(uint8_t));
229 n
= DemodPCF7931((uint8_t **)tmp_blocks
, ledcontrol
);
233 // exit if no block is received
234 if (errors
>= 10 && found_blocks
== 0 && single_blocks_cnt
== 0) {
236 if (g_dbglevel
>= DBG_INFO
)
237 Dbprintf("[!!] Error, no tag or bad tag");
241 // exit if too many errors during reading
242 if (tries
> 50 && (2 * errors
> tries
)) {
244 if (g_dbglevel
>= DBG_INFO
) {
245 Dbprintf("[!!] Error reading the tag, only partial content");
251 // our logic breaks if we don't get at least two blocks
253 // skip if all 0s block or no blocks
254 if (n
== 0 || !memcmp(tmp_blocks
[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
257 // add block to single blocks list
258 if (single_blocks_cnt
< max_blocks
) {
259 for (i
= 0; i
< single_blocks_cnt
; ++i
) {
260 if (!memcmp(single_blocks
[i
], tmp_blocks
[0], 16)) {
266 memcpy(single_blocks
[single_blocks_cnt
], tmp_blocks
[0], 16);
267 print_result("got single block", single_blocks
[single_blocks_cnt
], 16);
276 if (g_dbglevel
>= DBG_EXTENDED
)
277 Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n
, found_blocks
, (max_blocks
== 0 ? found_blocks
: max_blocks
), tries
, errors
);
279 for (i
= 0; i
< n
; ++i
) {
280 print_result("got consecutive blocks", tmp_blocks
[i
], 16);
286 if (IsBlock0PCF7931(tmp_blocks
[i
]) && IsBlock1PCF7931(tmp_blocks
[i
+ 1])) {
288 memcpy(memory_blocks
[0], tmp_blocks
[i
], 16);
289 memcpy(memory_blocks
[1], tmp_blocks
[i
+ 1], 16);
290 memory_blocks
[0][ALLOC
] = memory_blocks
[1][ALLOC
] = 1;
291 // block 1 tells how many blocks are going to be sent
292 max_blocks
= MAX((memory_blocks
[1][14] & 0x7f), memory_blocks
[1][15]) + 1;
295 Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks
);
297 // handle the following blocks
298 for (j
= i
+ 2; j
< n
; ++j
) {
299 memcpy(memory_blocks
[found_blocks
], tmp_blocks
[j
], 16);
300 memory_blocks
[found_blocks
][ALLOC
] = 1;
308 // Trying to re-order blocks
309 // Look for identical block in memory blocks
311 // skip all zeroes blocks
312 if (memcmp(tmp_blocks
[i
], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
313 for (j
= 1; j
< max_blocks
- 1; ++j
) {
314 if (!memcmp(tmp_blocks
[i
], memory_blocks
[j
], 16) && !memory_blocks
[j
+ 1][ALLOC
]) {
315 memcpy(memory_blocks
[j
+ 1], tmp_blocks
[i
+ 1], 16);
316 memory_blocks
[j
+ 1][ALLOC
] = 1;
317 if (++found_blocks
>= max_blocks
) goto end
;
321 if (memcmp(tmp_blocks
[i
+ 1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
322 for (j
= 0; j
< max_blocks
; ++j
) {
323 if (!memcmp(tmp_blocks
[i
+ 1], memory_blocks
[j
], 16) && !memory_blocks
[(j
== 0 ? max_blocks
: j
) - 1][ALLOC
]) {
325 memcpy(memory_blocks
[max_blocks
- 1], tmp_blocks
[i
], 16);
326 memory_blocks
[max_blocks
- 1][ALLOC
] = 1;
328 memcpy(memory_blocks
[j
- 1], tmp_blocks
[i
], 16);
329 memory_blocks
[j
- 1][ALLOC
] = 1;
331 if (++found_blocks
>= max_blocks
) goto end
;
339 if (BUTTON_PRESS()) {
340 if (g_dbglevel
>= DBG_EXTENDED
)
341 Dbprintf("Button pressed, stopping.");
345 } while (found_blocks
< max_blocks
);
348 Dbprintf("-----------------------------------------");
349 Dbprintf("Memory content:");
350 Dbprintf("-----------------------------------------");
351 for (i
= 0; i
< max_blocks
; ++i
) {
352 if (memory_blocks
[i
][ALLOC
])
353 print_result("Block", memory_blocks
[i
], 16);
355 Dbprintf("<missing block %d>", i
);
357 Dbprintf("-----------------------------------------");
359 if (found_blocks
< max_blocks
) {
360 Dbprintf("-----------------------------------------");
361 Dbprintf("Blocks with unknown position:");
362 Dbprintf("-----------------------------------------");
363 for (i
= 0; i
< single_blocks_cnt
; ++i
)
364 print_result("Block", single_blocks
[i
], 16);
366 Dbprintf("-----------------------------------------");
368 reply_mix(CMD_ACK
, 0, 0, 0, 0, 0);
371 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
, bool ledcontrol
) {
372 uint32_t tab
[1024] = {0}; // data times frame
377 //BUILD OF THE DATA FRAME
378 //alimentation of the tag (time for initializing)
379 AddPatternPCF7931(init_delay
, 0, 8192 / 2 * T0_PCF
, tab
);
380 AddPatternPCF7931(8192 / 2 * T0_PCF
+ 319 * T0_PCF
+ 70, 3 * T0_PCF
, 29 * T0_PCF
, tab
);
381 //password indication bit
382 AddBitPCF7931(1, tab
, l
, p
);
383 //password (on 56 bits)
384 AddBytePCF7931(pass
[0], tab
, l
, p
);
385 AddBytePCF7931(pass
[1], tab
, l
, p
);
386 AddBytePCF7931(pass
[2], tab
, l
, p
);
387 AddBytePCF7931(pass
[3], tab
, l
, p
);
388 AddBytePCF7931(pass
[4], tab
, l
, p
);
389 AddBytePCF7931(pass
[5], tab
, l
, p
);
390 AddBytePCF7931(pass
[6], tab
, l
, p
);
391 //programming mode (0 or 1)
392 AddBitPCF7931(0, tab
, l
, p
);
394 //block address on 6 bits
395 for (u
= 0; u
< 6; ++u
) {
396 if (address
& (1 << u
)) { // bit 1
398 AddBitPCF7931(1, tab
, l
, p
);
400 AddBitPCF7931(0, tab
, l
, p
);
404 //byte address on 4 bits
405 for (u
= 0; u
< 4; ++u
) {
406 if (byte
& (1 << u
)) { // bit 1
408 AddBitPCF7931(1, tab
, l
, p
);
410 AddBitPCF7931(0, tab
, l
, p
);
414 for (u
= 0; u
< 8; u
++) {
415 if (data
& (1 << u
)) { // bit 1
417 AddBitPCF7931(1, tab
, l
, p
);
419 AddBitPCF7931(0, tab
, l
, p
);
423 if ((parity
% 2) == 0)
424 AddBitPCF7931(0, tab
, l
, p
); //even parity
426 AddBitPCF7931(1, tab
, l
, p
);//odd parity
429 AddPatternPCF7931(5120 + 2680, 0, 0, tab
);
431 //conversion of the scale time
432 for (u
= 0; u
< 500; ++u
)
433 tab
[u
] = (tab
[u
] * 3) / 2;
435 //compensation of the counter reload
438 for (u
= 0; tab
[u
] != 0; ++u
)
439 if (tab
[u
] > 0xFFFF) {
445 SendCmdPCF7931(tab
, ledcontrol
);
448 /* Write on a byte of a PCF7931 tag
449 * @param address : address of the block to write
450 @param byte : address of the byte to write
451 @param data : data to write
453 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
, bool ledcontrol
) {
455 if (g_dbglevel
>= DBG_INFO
) {
456 Dbprintf("Initialization delay : %d us", init_delay
);
457 Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l
, p
);
460 Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1
, pass2
, pass3
, pass4
, pass5
, pass6
, pass7
);
461 Dbprintf("Block address : %02x", address
);
462 Dbprintf("Byte address : %02x", byte
);
463 Dbprintf("Data : %02x", data
);
465 uint8_t password
[7] = {pass1
, pass2
, pass3
, pass4
, pass5
, pass6
, pass7
};
467 RealWritePCF7931(password
, init_delay
, l
, p
, address
, byte
, data
, ledcontrol
);
471 /* Send a trame to a PCF7931 tags
472 * @param tab : array of the data frame
475 void SendCmdPCF7931(const uint32_t *tab
, bool ledcontrol
) {
476 uint16_t u
= 0, tempo
= 0;
478 if (g_dbglevel
>= DBG_INFO
) {
479 Dbprintf("Sending data frame...");
482 FpgaDownloadAndGo(FPGA_BITSTREAM_LF
);
483 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, LF_DIVISOR_125
); //125kHz
484 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU
);
486 if (ledcontrol
) LED_A_ON();
488 // steal this pin from the SSP and use it to control the modulation
489 AT91C_BASE_PIOA
->PIO_PER
= GPIO_SSC_DOUT
;
490 AT91C_BASE_PIOA
->PIO_OER
= GPIO_SSC_DOUT
;
492 //initialization of the timer
493 AT91C_BASE_PMC
->PMC_PCER
|= (0x1 << AT91C_ID_TC0
);
494 AT91C_BASE_TCB
->TCB_BMR
= AT91C_TCB_TC0XC0S_NONE
| AT91C_TCB_TC1XC1S_TIOA0
| AT91C_TCB_TC2XC2S_NONE
;
495 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKDIS
; // timer disable
496 AT91C_BASE_TC0
->TC_CMR
= AT91C_TC_CLKS_TIMER_DIV3_CLOCK
; // clock at 48/32 MHz
497 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKEN
;
499 // Assert a sync signal. This sets all timers to 0 on next active clock edge
500 AT91C_BASE_TCB
->TCB_BCR
= 1;
502 tempo
= AT91C_BASE_TC0
->TC_CV
;
503 for (u
= 0; tab
[u
] != 0; u
+= 3) {
506 while (tempo
!= tab
[u
]) {
507 tempo
= AT91C_BASE_TC0
->TC_CV
;
510 // stop modulating antenna
512 while (tempo
!= tab
[u
+ 1]) {
513 tempo
= AT91C_BASE_TC0
->TC_CV
;
518 while (tempo
!= tab
[u
+ 2]) {
519 tempo
= AT91C_BASE_TC0
->TC_CV
;
523 if (ledcontrol
) LED_A_OFF();
524 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
527 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKDIS
; // timer disable
531 /* Add a byte for building the data frame of PCF7931 tags
532 * @param b : byte 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
537 bool AddBytePCF7931(uint8_t byte
, uint32_t *tab
, int32_t l
, int32_t p
) {
539 for (u
= 0; u
< 8; ++u
) {
540 if (byte
& (1 << u
)) { //bit is 1
541 if (AddBitPCF7931(1, tab
, l
, p
) == 1) return true;
543 if (AddBitPCF7931(0, tab
, l
, p
) == 1) return true;
550 /* Add a bits for building the data frame of PCF7931 tags
551 * @param b : bit to add
552 * @param tab : array of the data frame
553 * @param l : offset on low pulse width
554 * @param p : offset on low pulse positioning
556 bool AddBitPCF7931(bool b
, uint32_t *tab
, int32_t l
, int32_t p
) {
559 //we put the cursor at the last value of the array
560 for (u
= 0; tab
[u
] != 0; u
+= 3) { };
562 if (b
== 1) { //add a bit 1
564 tab
[u
] = 34 * T0_PCF
+ p
;
566 tab
[u
] = 34 * T0_PCF
+ tab
[u
- 1] + p
;
568 tab
[u
+ 1] = 6 * T0_PCF
+ tab
[u
] + l
;
569 tab
[u
+ 2] = 88 * T0_PCF
+ tab
[u
+ 1] - l
- p
;
571 } else { //add a bit 0
574 tab
[u
] = 98 * T0_PCF
+ p
;
576 tab
[u
] = 98 * T0_PCF
+ tab
[u
- 1] + p
;
578 tab
[u
+ 1] = 6 * T0_PCF
+ tab
[u
] + l
;
579 tab
[u
+ 2] = 24 * T0_PCF
+ tab
[u
+ 1] - l
- p
;
585 /* Add a custom pattern in the data frame
586 * @param a : delay of the first high pulse
587 * @param b : delay of the low pulse
588 * @param c : delay of the last high pulse
589 * @param tab : array of the data frame
591 bool AddPatternPCF7931(uint32_t a
, uint32_t b
, uint32_t c
, uint32_t *tab
) {
593 for (u
= 0; tab
[u
] != 0; u
+= 3) {} //we put the cursor at the last value of the array
595 tab
[u
] = (u
== 0) ? a
: a
+ tab
[u
- 1];
596 tab
[u
+ 1] = b
+ tab
[u
];
597 tab
[u
+ 2] = c
+ tab
[u
+ 1];