ADD: 'lf t55xx deviceconfig' - command that allows for setting t55xx timings via the client. If run on a RDV40, it also saves the config to flashmemory. This gives you option to have custom timings for your custom antenna in order for your RDV40 to work optimal against a t55xx tag and with your custom antenna. (@iceman)

This commit is contained in:
Chris 2018-09-11 18:35:07 +02:00
parent 5959cdf62c
commit ba2543b627
10 changed files with 185 additions and 26 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added 'lf t55xx deviceconfig' - enables custom t55xx timing settings. (RDV40) (@iceman)
- Chg adaptations for FPC communications (work in progress) (@iceman)
- Fix 'stand-alone Colin' - remake to benefit from flashmem for persistence. (@cjbrigato)
- Fix 'LEGIC SIM' - remake of legic sim (@drandreas)

View file

@ -392,7 +392,8 @@ void SendStatus(void) {
I2C_print_status();
#endif
#ifdef WITH_LF
printConfig(); //LF Sampling config
printConfig(); // LF Sampling config
printT55xxConfig(); // LF T55XX Config
#endif
printUSBSpeed();
Dbprintf("Various");
@ -625,6 +626,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
switch(c->cmd) {
#ifdef WITH_LF
case CMD_SET_LF_T55XX_CONFIG:
setT55xxConfig((t55xx_config *) c->d.asBytes);
break;
case CMD_SET_LF_SAMPLING_CONFIG:
setSamplingConfig((sample_config *) c->d.asBytes);
break;
@ -701,9 +705,10 @@ void UsbPacketReceived(uint8_t *packet, int len) {
c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6]
);
break;
case CMD_T55XX_READ_BLOCK:
case CMD_T55XX_READ_BLOCK: {
T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]);
break;
}
case CMD_T55XX_WRITE_BLOCK:
T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
break;
@ -1475,6 +1480,10 @@ void __attribute__((noreturn)) AppMain(void) {
usart_init();
#endif
#ifdef WITH_FLASH
loadT55xxConfig();
#endif
// This is made as late as possible to ensure enumeration without timeout
// against device such as http://www.hobbytronics.co.uk/usb-host-board-v2
usb_disable();

View file

@ -108,6 +108,10 @@ void TurnReadLFOn(uint32_t delay);
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd);
void Cotag(uint32_t arg0);
void setT55xxConfig(t55xx_config *c);
t55xx_config * getT55xxConfig(void);
void printT55xxConfig(void);
void loadT55xxConfig(void);
/// iso14443b.h
void SimulateIso14443bTag(uint32_t pupi);

View file

@ -1,7 +1,5 @@
#include "flashmem.h"
/* here: use NCPS2 @ PA10: */
#define SPI_CSR_NUM 2
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)

View file

@ -18,6 +18,8 @@
#include "lfsampling.h"
#include "protocols.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "common.h"
#include "flashmem.h" // persistence on mem
#ifndef SHORT_COIL
# define SHORT_COIL() LOW(GPIO_SSC_DOUT)
@ -26,11 +28,11 @@
# define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
#endif
#define START_GAP 28*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc)
#define WRITE_GAP 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc)
#define WRITE_0 15*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc)
#define WRITE_1 47*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550
#define READ_GAP 15*8
//#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc)
//#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc)
//#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc)
//#define WRITE_1 47*8 // 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550
//#define READ_GAP 15*8
// VALUES TAKEN FROM EM4x function: SendForward
// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle)
@ -49,7 +51,68 @@
// new timer:
// = 1us = 1.5ticks
// 1fc = 8us = 12ticks
/*
Default LF T55xx config is set to:
startgap = 31*8
writegap = 17*8
write_0 = 15*8
write_1 = 47*8
read_gap = 15*8
*/
t55xx_config t_config = { 31*8, 17*8, 15*8, 47*8, 15*8 } ;
void printT55xxConfig(void) {
Dbprintf("LF T55XX config");
Dbprintf(" [q] startgap............%d*8 (%d)", t_config.start_gap/8, t_config.start_gap);
Dbprintf(" [b] writegap............%d*8 (%d)", t_config.write_gap/8, t_config.write_gap);
Dbprintf(" [d] write_0.............%d*8 (%d)", t_config.write_0/8, t_config.write_0);
Dbprintf(" [a] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1);
Dbprintf(" [t] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap);
}
void setT55xxConfig(t55xx_config *c) {
if (c->start_gap != 0) t_config.start_gap = c->start_gap*8;
if (c->write_gap != 0) t_config.write_gap = c->write_gap*8;
if (c->write_0 != 0) t_config.write_0 = c->write_0*8;
if (c->write_1 != 0) t_config.write_1 = c->write_1*8;
if (c->read_gap != 0) t_config.read_gap = c->read_gap*8;
printT55xxConfig();
#if WITH_FLASH
if (!FlashInit())
return;
Flash_CheckBusy(BUSY_TIMEOUT);
uint16_t isok = Flash_WriteDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, sizeof(t55xx_config));
FlashStop();
if ( isok == T55XX_CONFIG_LEN) {
if (MF_DBGLEVEL > 1) DbpString("T55XX Config save success");
}
#endif
}
t55xx_config* getT55xxConfig(void) {
return &t_config;
}
void loadT55xxConfig(void) {
#if WITH_FLASH
if (!FlashInit())
return;
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, T55XX_CONFIG_LEN);
FlashStop();
if ( isok == T55XX_CONFIG_LEN) {
if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success");
}
#endif
}
/**
* Function to do a modulation and then get samples.
@ -1266,11 +1329,11 @@ void TurnReadLF_off(uint32_t delay) {
// Write one bit to card
void T55xxWriteBit(int bit) {
if (!bit)
TurnReadLFOn(WRITE_0);
TurnReadLFOn(t_config.write_0);
else
TurnReadLFOn(WRITE_1);
TurnReadLFOn(t_config.write_1);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF);
WaitUS(WRITE_GAP);
WaitUS(t_config.write_gap);
}
// Send T5577 reset command then read stream (see if we can identify the start of the stream)
@ -1284,17 +1347,17 @@ void T55xxResetRead(void) {
// Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up...
WaitMS(6);
WaitMS(4);
// Trigger T55x7 in mode.
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF);
WaitUS(START_GAP);
WaitUS(t_config.start_gap);
// reset tag - op code 00
T55xxWriteBit(0);
T55xxWriteBit(0);
TurnReadLFOn(READ_GAP);
TurnReadLFOn(t_config.read_gap);
// Acquisition
DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0);
@ -1319,10 +1382,10 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg)
LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up...
WaitMS(6);
WaitMS(4);
// Trigger T55x7 in mode.
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF);
WaitUS(START_GAP);
WaitUS(t_config.start_gap);
if (testMode) Dbprintf("TestMODE");
// Std Opcode 10
@ -1404,10 +1467,10 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
// Set up FPGA, 125kHz to power up the tag
LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up...
WaitMS(6);
WaitMS(4);
// Trigger T55x7 Direct Access Mode with start gap
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF);
WaitUS(START_GAP);
WaitUS(t_config.start_gap);
// Opcode 1[page]
T55xxWriteBit(1);
@ -1450,11 +1513,11 @@ void T55xxWakeUp(uint32_t Pwd){
// Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up...
WaitMS(6);
WaitMS(4);
// Trigger T55x7 Direct Access Mode
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF);
WaitUS(START_GAP);
WaitUS(t_config.start_gap);
// Opcode 10
T55xxWriteBit(1);

View file

@ -187,6 +187,22 @@ int usage_t55xx_recoverpw(){
PrintAndLogEx(NORMAL, " lf t55xx wipe Q5 - wipes a t5555 Q5 tag, config block 0x6001F004");
return 0;
}
int usage_lf_deviceconfig(){
PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a <gap> b <gap> c <gap> d <gap> e <gap>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - This help");
PrintAndLogEx(NORMAL, " a <8..28> - Set start gap");
PrintAndLogEx(NORMAL, " b <8..28> - Set write gap");
PrintAndLogEx(NORMAL, " c <8..28> - Set write ZERO gap");
PrintAndLogEx(NORMAL, " d <8..28> - Set write ONE gap");
PrintAndLogEx(NORMAL, " e <8..28> - Set read gap");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 - start gap 31*8");
PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 b 20 - start gap 31*8, write gap 20*8");
PrintAndLogEx(NORMAL, "");
return 0;
}
static int CmdHelp(const char *Cmd);
void printT5xxHeader(uint8_t page){
@ -461,8 +477,7 @@ static int SanityOfflineCheck( bool useGraphBuffer ){
int CmdT55xxDetect(const char *Cmd){
bool errors = false;
bool useGB = false;
bool usepwd = false;
bool useGB = false, usepwd = false;
uint32_t password = 0;
uint8_t cmdp = 0;
@ -1291,7 +1306,7 @@ int CmdT55xxDump(const char *Cmd){
return 1;
}
bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){
bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) {
// arg0 bitmodes:
// bit0 = pwdmode
// bit1 = page to read from
@ -1882,11 +1897,60 @@ int CmdT55xxDetectPage1(const char *Cmd){
return success;
}
int CmdT55xxSetDeviceConfig(const char *Cmd){
uint8_t startgap = 0, writegap = 0;
uint8_t write0 = 0, write1 = 0, readgap = 0;
bool errors = false;
uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_deviceconfig();
case 'a':
errors |= param_getdec(Cmd, cmdp+1, &startgap);
cmdp += 2;
break;
case 'b':
errors |= param_getdec(Cmd, cmdp+1, &writegap);
cmdp += 2;
break;
case 'c':
errors |= param_getdec(Cmd, cmdp+1, &write0);
cmdp += 2;
break;
case 'd':
errors |= param_getdec(Cmd, cmdp+1, &write1);
cmdp += 2;
break;
case 'e':
errors |= param_getdec(Cmd, cmdp+1, &readgap);
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = 1;
break;
}
}
//Validations
if (errors || cmdp == 0) return usage_lf_deviceconfig();
t55xx_config config = { startgap, writegap, write0, write1, readgap };
UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {0,0,0} };
memcpy(c.d.asBytes, &config, sizeof(t55xx_config));
clearCommandBuffer();
SendCommand(&c);
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"bruteforce", CmdT55xxBruteForce,0, "<start password> <end password> [i <*.dic>] Simple bruteforce attack to find password"},
{"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
{"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."},
{"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"},
{"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"},
{"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"},
{"info", CmdT55xxInfo, 1, "[1] Show T55x7 configuration data (page 0/ blk 0)"},

View file

@ -160,6 +160,7 @@ extern bool tryDetectP1(bool getData);
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5);
int special(const char *Cmd);
bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password );
bool AquireDataEx( uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint32_t timing ) ;
bool detectPassword(int password);

View file

@ -105,6 +105,7 @@ typedef struct {
#define CMD_VIKING_CLONE_TAG 0x0222
#define CMD_T55XX_WAKEUP 0x0224
#define CMD_COTAG 0x0225
#define CMD_SET_LF_T55XX_CONFIG 0x0226
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */

View file

@ -55,7 +55,7 @@ extern uint32_t FLASHMEM_SPIBAUDRATE;
#endif
#ifndef FLASH_MEM_MAX_SIZE
# define FLASH_MEM_MAX_SIZE 0x3FFFF
# define FLASH_MEM_MAX_SIZE 0x3FFFF // (262143)
#endif
#ifndef FLASH_MEM_ID_LEN
@ -70,6 +70,15 @@ extern uint32_t FLASHMEM_SPIBAUDRATE;
# define FLASH_MEM_SIGNATURE_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN)
#endif
#if WITH_FLASH
#ifndef T55XX_CONFIG_LEN
# define T55XX_CONFIG_LEN sizeof( t55xx_config )
#endif
#ifndef T55XX_CONFIG_OFFSET
#define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN - T55XX_CONFIG_LEN)
#endif
#endif
// RDV40, validation structure to help identifying that client/firmware is talking with RDV40
typedef struct {

View file

@ -43,6 +43,14 @@ typedef struct{
int trigger_threshold;
} sample_config;
typedef struct{
uint16_t start_gap;
uint16_t write_gap;
uint16_t write_0;
uint16_t write_1;
uint16_t read_gap;
} t55xx_config;
// For the bootloader
#define CMD_DEVICE_INFO 0x0000
#define CMD_SETUP_WRITE 0x0001
@ -130,6 +138,7 @@ typedef struct{
#define CMD_VIKING_CLONE_TAG 0x0222
#define CMD_T55XX_WAKEUP 0x0224
#define CMD_COTAG 0x0225
#define CMD_SET_LF_T55XX_CONFIG 0x0226
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */