From f5fca2ed62fa1948cf1cc4eabaa6dc4cc27762cd Mon Sep 17 00:00:00 2001 From: "chalk.secu@gmail.com" Date: Fri, 18 Jan 2013 21:31:35 +0000 Subject: [PATCH] Added command to read PCF7931 125Khz LF tags. This is a beta version which needs to be tested. --- armsrc/appmain.c | 4 + armsrc/apps.h | 4 + armsrc/lfops.c | 258 ++++++++++++++++++++++++++++++++++++++++++ client/Makefile | 3 +- client/cmdlf.c | 2 + client/cmdlfpcf7931.c | 49 ++++++++ client/cmdlfpcf7931.h | 18 +++ include/usb_cmd.h | 1 + 8 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 client/cmdlfpcf7931.c create mode 100644 client/cmdlfpcf7931.h diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 1f005716..a284cacf 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -666,6 +666,10 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_T55XX_READ_TRACE: // Clone HID tag by ID to T55x7 T55xxReadTrace(); break; + case CMD_PCF7931_READ: // Read PCF7931 tag + ReadPCF7931(); + UsbSendPacket((uint8_t*)&ack, sizeof(ack)); + break; #endif #ifdef WITH_HITAG diff --git a/armsrc/apps.h b/armsrc/apps.h index 93b59306..fbc74dcd 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -124,6 +124,10 @@ void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode); void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode ); void T55xxReadTrace(void); +int DemodPCF7931(uint8_t **outBlocks); +int IsBlock0PCF7931(uint8_t *Block); +int IsBlock1PCF7931(uint8_t *Block); +void ReadPCF7931(); /// iso14443.h void SimulateIso14443Tag(void); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 0eb3503d..3b7216ed 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1295,3 +1295,261 @@ void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int DbpString("DONE!"); } + +#define abs(x) ( ((x)<0) ? -(x) : (x) ) +#define max(x,y) ( x GraphBuffer[0]) { + while(i < GraphTraceLen) { + if( !(GraphBuffer[i] > GraphBuffer[i-1]) && GraphBuffer[i] > lmax) + break; + i++; + } + dir = 0; + } + else { + while(i < GraphTraceLen) { + if( !(GraphBuffer[i] < GraphBuffer[i-1]) && GraphBuffer[i] < lmin) + break; + i++; + } + dir = 1; + } + + lastval = i++; + half_switch = 0; + pmc = 0; + block_done = 0; + + for (bitidx = 0; i < GraphTraceLen; i++) + { + if ( (GraphBuffer[i-1] > GraphBuffer[i] && dir == 1 && GraphBuffer[i] > lmax) || (GraphBuffer[i-1] < GraphBuffer[i] && dir == 0 && GraphBuffer[i] < lmin)) + { + lc = i - lastval; + lastval = i; + + // Switch depending on lc length: + // Tolerance is 1/8 of clock rate (arbitrary) + if (abs(lc-clock/4) < tolerance) { + // 16T0 + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33+16)-1; + lastval = i; + pmc = 0; + block_done = 1; + } + else { + pmc = i; + } + } else if (abs(lc-clock/2) < tolerance) { + // 32TO + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33)-1; + lastval = i; + pmc = 0; + block_done = 1; + } + else if(half_switch == 1) { + BitStream[bitidx++] = 0; + half_switch = 0; + } + else + half_switch++; + } else if (abs(lc-clock) < tolerance) { + // 64TO + BitStream[bitidx++] = 1; + } else { + // Error + warnings++; + if (warnings > 10) + { + Dbprintf("Error: too many detection errors, aborting."); + return 0; + } + } + + if(block_done == 1) { + if(bitidx == 128) { + for(j=0; j<16; j++) { + Blocks[num_blocks][j] = 128*BitStream[j*8+7]+ + 64*BitStream[j*8+6]+ + 32*BitStream[j*8+5]+ + 16*BitStream[j*8+4]+ + 8*BitStream[j*8+3]+ + 4*BitStream[j*8+2]+ + 2*BitStream[j*8+1]+ + BitStream[j*8]; + } + num_blocks++; + } + bitidx = 0; + block_done = 0; + half_switch = 0; + } + if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0; + else dir = 1; + } + if(bitidx==255) + bitidx=0; + warnings = 0; + if(num_blocks == 4) break; + } + memcpy(outBlocks, Blocks, 16*num_blocks); + return num_blocks; +} + +int IsBlock0PCF7931(uint8_t *Block) { + // Assume RFU means 0 :) + if((memcmp(Block, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) == 0) && memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) // PAC enabled + return 1; + if((memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block[7] == 0) // PAC disabled, can it *really* happen ? + return 1; + return 0; +} + +int IsBlock1PCF7931(uint8_t *Block) { + // Assume RFU means 0 :) + if(Block[10] == 0 && Block[11] == 0 && Block[12] == 0 && Block[13] == 0) + if((Block[14] & 0x7f) <= 9 && Block[15] <= 9) + return 1; + + return 0; +} + +#define ALLOC 16 + +void ReadPCF7931() { + uint8_t Blocks[8][17]; + uint8_t tmpBlocks[4][16]; + int i, j, ind, ind2, n; + int num_blocks = 0; + int max_blocks = 8; + int ident = 0; + int error = 0; + int tries = 0; + + memset(Blocks, 0, 8*17*sizeof(uint8_t)); + + do { + memset(tmpBlocks, 0, 4*16*sizeof(uint8_t)); + n = DemodPCF7931((uint8_t**)tmpBlocks); + if(!n) + error++; + if(error==10 && num_blocks == 0) { + Dbprintf("Error, no tag or bad tag"); + return; + } + else if (tries==20 || error==10) { + Dbprintf("Error reading the tag"); + Dbprintf("Here is the partial content"); + goto end; + } + + for(i=0; i= 0; ind--,ind2--) { + if(ind2 < 0) + ind2 = max_blocks; + if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found + // Dbprintf("Tmp %d -> Block %d", ind, ind2); + memcpy(Blocks[ind2], tmpBlocks[ind], 16); + Blocks[ind2][ALLOC] = 1; + num_blocks++; + if(num_blocks == max_blocks) goto end; + } + } + for(ind=i+1,ind2=j+1; ind < n; ind++,ind2++) { + if(ind2 > max_blocks) + ind2 = 0; + if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found + // Dbprintf("Tmp %d -> Block %d", ind, ind2); + memcpy(Blocks[ind2], tmpBlocks[ind], 16); + Blocks[ind2][ALLOC] = 1; + num_blocks++; + if(num_blocks == max_blocks) goto end; + } + } + } + } + } + } + } + tries++; + if (BUTTON_PRESS()) return; + } while (num_blocks != max_blocks); + end: + Dbprintf("-----------------------------------------"); + Dbprintf("Memory content:"); + Dbprintf("-----------------------------------------"); + for(i=0; i", i); + } + Dbprintf("-----------------------------------------"); + + return ; +} diff --git a/client/Makefile b/client/Makefile index 597f562e..028888d4 100644 --- a/client/Makefile +++ b/client/Makefile @@ -68,7 +68,8 @@ CMDSRCS = \ cmdlfti.c \ cmdparser.c \ cmdmain.c \ - cmdlft55xx.c + cmdlft55xx.c \ + cmdlfpcf7931.c CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) diff --git a/client/cmdlf.c b/client/cmdlf.c index f3a3f52a..96e31541 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -25,6 +25,7 @@ #include "cmdlfem4x.h" #include "cmdlfhitag.h" #include "cmdlft55xx.h" +#include "cmdlfpcf7931.h" static int CmdHelp(const char *Cmd); @@ -540,6 +541,7 @@ static command_t CommandTable[] = {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"}, + {"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c new file mode 100644 index 00000000..c31a9f9c --- /dev/null +++ b/client/cmdlfpcf7931.c @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2012 Chalk +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency PCF7931 commands +//----------------------------------------------------------------------------- + +#include +#include +#include "proxusb.h" +#include "ui.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "cmdlfpcf7931.h" + +static int CmdHelp(const char *Cmd); + +int CmdLFPCF7931Read(const char *Cmd) +{ + UsbCommand c = {CMD_PCF7931_READ}; + SendCommand(&c); + WaitForResponse(CMD_ACK); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFPCF7931(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfpcf7931.h b/client/cmdlfpcf7931.h new file mode 100644 index 00000000..ed60bc91 --- /dev/null +++ b/client/cmdlfpcf7931.h @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2012 Chalk +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency PCF7931 commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFPCF7931_H__ +#define CMDLFPCF7931_H__ + +int CmdLFPCF7931(const char *Cmd); + +int CmdLFPCF7931Read(const char *Cmd); + +#endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 507519ec..0e1b22af 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -74,6 +74,7 @@ typedef struct { #define CMD_T55XX_READ_BLOCK 0x0214 #define CMD_T55XX_WRITE_BLOCK 0x0215 #define CMD_T55XX_READ_TRACE 0x0216 +#define CMD_PCF7931_READ 0x0217 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ -- 2.39.2