mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-23 14:35:28 -07:00
Merge branch 'master' into hard_nested
Conflicts: client/Makefile client/cmdhfmf.c
This commit is contained in:
commit
91d171cfd2
59 changed files with 4473 additions and 2129 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
|||
# .gitignore
|
||||
# don't push these files to the repository
|
||||
|
||||
.history
|
||||
*.log
|
||||
*.eml
|
||||
*.o
|
||||
|
|
23
CHANGELOG.md
23
CHANGELOG.md
|
@ -5,13 +5,36 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
## [unreleased][unreleased]
|
||||
|
||||
### Added
|
||||
- Added viking demod to `lf search` (marshmellow)
|
||||
- `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow)
|
||||
- `lf t55xx resetread` added reset then read command - should allow determining start
|
||||
of stream transmissions (marshmellow)
|
||||
- `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow)
|
||||
- `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow)
|
||||
- `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
|
||||
- `hf iclass writeblk` to select, authenticate, and write 1 block to an iclass card (or picopass) (marshmellow + others)
|
||||
- `hf iclass clone` to take a saved dump file and clone selected blocks to a new tag (marshmellow + others)
|
||||
- `hf iclass calcnewkey` - to calculate the div_key change to change a key - (experimental) (marshmellow + others)
|
||||
- `hf iclass encryptblk` - to encrypt a data block hex to prep for writing that block (marshmellow)
|
||||
- ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young)
|
||||
- AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young)
|
||||
- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman)
|
||||
- Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman)
|
||||
- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman)
|
||||
- Added 'hf snoop'. This command take digitalized signal from FPGA and put in BigBuffer. (pwpiwi + enio)
|
||||
- Added Topaz (NFC type 1) protocol support ('hf topaz reader', 'hf list topaz', 'hf 14a raw -T', 'hf topaz snoop'). (piwi)
|
||||
- Added option c to 'hf list' (mark CRC bytes) (piwi)
|
||||
|
||||
### Changed
|
||||
- Adjusted lf em410x em410xsim to accept a clock argument
|
||||
- Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow)
|
||||
- Adjusted lf t55xx write input variables (marshmellow)
|
||||
- Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman)
|
||||
- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate.
|
||||
- Adjusted timings for t55xx commands. more reliable now. (marshmellow & iceman)
|
||||
- `lf cmdread` adjusted input methods and added help text (marshmellow & iceman)
|
||||
- changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow)
|
||||
- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to muliple pages for the larger tags yet)
|
||||
- Revised workflow for StandAloneMode14a (Craig Young)
|
||||
- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
|
||||
- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)
|
||||
|
|
2
Makefile
2
Makefile
|
@ -22,7 +22,7 @@ help:
|
|||
@echo + all - Make bootrom, armsrc and the OS-specific host directory
|
||||
@echo + client - Make only the OS-specific host directory
|
||||
@echo + flash-bootrom - Make bootrom and flash it
|
||||
@echo + flash-os - Make armsrc and flash os (includes fpga)
|
||||
@echo + flash-os - Make armsrc and flash os \(includes fpga\)
|
||||
@echo + flash-all - Make bootrom and armsrc and flash bootrom and os image
|
||||
@echo + clean - Clean in bootrom, armsrc and the OS-specific host directory
|
||||
|
||||
|
|
|
@ -50,9 +50,15 @@ uint8_t *BigBuf_get_EM_addr(void)
|
|||
|
||||
// clear ALL of BigBuf
|
||||
void BigBuf_Clear(void)
|
||||
{
|
||||
BigBuf_Clear_ext(true);
|
||||
}
|
||||
// clear ALL of BigBuf
|
||||
void BigBuf_Clear_ext(bool verbose)
|
||||
{
|
||||
memset(BigBuf,0,BIGBUF_SIZE);
|
||||
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
|
||||
if (verbose)
|
||||
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -178,8 +184,12 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
|||
traceLen += iLen;
|
||||
|
||||
// parity bytes
|
||||
if (parity != NULL && iLen != 0) {
|
||||
memcpy(trace + traceLen, parity, num_paritybytes);
|
||||
if (iLen != 0) {
|
||||
if (parity != NULL) {
|
||||
memcpy(trace + traceLen, parity, num_paritybytes);
|
||||
} else {
|
||||
memset(trace + traceLen, 0x00, num_paritybytes);
|
||||
}
|
||||
}
|
||||
traceLen += num_paritybytes;
|
||||
|
||||
|
@ -228,6 +238,8 @@ int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwP
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Emulator memory
|
||||
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
|
||||
uint8_t* mem = BigBuf_get_EM_addr();
|
||||
|
|
|
@ -25,6 +25,7 @@ extern uint8_t *BigBuf_get_addr(void);
|
|||
extern uint8_t *BigBuf_get_EM_addr(void);
|
||||
extern uint16_t BigBuf_max_traceLen(void);
|
||||
extern void BigBuf_Clear(void);
|
||||
extern void BigBuf_Clear_ext(bool verbose);
|
||||
extern uint8_t *BigBuf_malloc(uint16_t);
|
||||
extern void BigBuf_free(void);
|
||||
extern void BigBuf_free_keep_EM(void);
|
||||
|
|
|
@ -10,12 +10,12 @@ APP_INCLUDES = apps.h
|
|||
|
||||
#remove one of the following defines and comment out the relevant line
|
||||
#in the next section to remove that particular feature from compilation
|
||||
APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE \
|
||||
APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -DWITH_HFSNOOP \
|
||||
-fno-strict-aliasing -ffunction-sections -fdata-sections
|
||||
#-DWITH_LCD
|
||||
|
||||
#SRC_LCD = fonts.c LCD.c
|
||||
SRC_LF = lfops.c hitag2.c lfsampling.c
|
||||
SRC_LF = lfops.c hitag2.c lfsampling.c pcf7931.c lfdemod.c protocols.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
|
||||
SRC_ISO14443b = iso14443b.c
|
||||
|
@ -52,7 +52,6 @@ THUMBSRC = start.c \
|
|||
# These are to be compiled in ARM mode
|
||||
ARMSRC = fpgaloader.c \
|
||||
legicrf.c \
|
||||
lfdemod.c \
|
||||
$(SRC_ISO14443a) \
|
||||
$(SRC_ISO14443b) \
|
||||
$(SRC_CRAPTO1) \
|
||||
|
@ -60,7 +59,8 @@ ARMSRC = fpgaloader.c \
|
|||
legic_prng.c \
|
||||
iclass.c \
|
||||
BigBuf.c \
|
||||
optimized_cipher.c
|
||||
optimized_cipher.c \
|
||||
hfsnoop.c
|
||||
|
||||
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||
include ../common/Makefile.common
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "lfsampling.h"
|
||||
#include "BigBuf.h"
|
||||
#include "mifareutil.h"
|
||||
#include "pcf7931.h"
|
||||
#ifdef WITH_LCD
|
||||
#include "LCD.h"
|
||||
#endif
|
||||
|
@ -945,7 +946,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
CmdIOdemodFSK(c->arg[0], 0, 0, 1);
|
||||
break;
|
||||
case CMD_IO_CLONE_TAG:
|
||||
CopyIOtoT55x7(c->arg[0], c->arg[1], c->d.asBytes[0]);
|
||||
CopyIOtoT55x7(c->arg[0], c->arg[1]);
|
||||
break;
|
||||
case CMD_EM410X_DEMOD:
|
||||
CmdEM410xdemod(c->arg[0], 0, 0, 1);
|
||||
|
@ -974,21 +975,22 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
CopyIndala224toT55x7(c->d.asDwords[0], c->d.asDwords[1], c->d.asDwords[2], c->d.asDwords[3], c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6]);
|
||||
break;
|
||||
case CMD_T55XX_READ_BLOCK:
|
||||
T55xxReadBlock(c->arg[1], c->arg[2],c->d.asBytes[0]);
|
||||
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]);
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
break;
|
||||
case CMD_T55XX_READ_TRACE:
|
||||
T55xxReadTrace();
|
||||
case CMD_T55XX_WAKEUP:
|
||||
T55xxWakeUp(c->arg[0]);
|
||||
break;
|
||||
case CMD_T55XX_RESET_READ:
|
||||
T55xxResetRead();
|
||||
break;
|
||||
case CMD_PCF7931_READ:
|
||||
ReadPCF7931();
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
break;
|
||||
case CMD_PCF7931_WRITE:
|
||||
WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]);
|
||||
WritePCF7931(c->d.asBytes[0],c->d.asBytes[1],c->d.asBytes[2],c->d.asBytes[3],c->d.asBytes[4],c->d.asBytes[5],c->d.asBytes[6], c->d.asBytes[9], c->d.asBytes[7]-128,c->d.asBytes[8]-128, c->arg[0], c->arg[1], c->arg[2]);
|
||||
break;
|
||||
case CMD_EM4X_READ_WORD:
|
||||
EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]);
|
||||
|
@ -998,7 +1000,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
break;
|
||||
case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
|
||||
CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
|
||||
break;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HITAG
|
||||
|
@ -1181,11 +1183,34 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
ReaderIClass(c->arg[0]);
|
||||
break;
|
||||
case CMD_READER_ICLASS_REPLAY:
|
||||
ReaderIClass_Replay(c->arg[0], c->d.asBytes);
|
||||
ReaderIClass_Replay(c->arg[0], c->d.asBytes);
|
||||
break;
|
||||
case CMD_ICLASS_EML_MEMSET:
|
||||
case CMD_ICLASS_EML_MEMSET:
|
||||
emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
|
||||
break;
|
||||
case CMD_ICLASS_WRITEBLOCK:
|
||||
iClass_WriteBlock(c->arg[0], c->d.asBytes);
|
||||
break;
|
||||
case CMD_ICLASS_READCHECK: // auth step 1
|
||||
iClass_ReadCheck(c->arg[0], c->arg[1]);
|
||||
break;
|
||||
case CMD_ICLASS_READBLOCK:
|
||||
iClass_ReadBlk(c->arg[0]);
|
||||
break;
|
||||
case CMD_ICLASS_AUTHENTICATION: //check
|
||||
iClass_Authentication(c->d.asBytes);
|
||||
break;
|
||||
case CMD_ICLASS_DUMP:
|
||||
iClass_Dump(c->arg[0], c->arg[1]);
|
||||
break;
|
||||
case CMD_ICLASS_CLONE:
|
||||
iClass_Clone(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WITH_HFSNOOP
|
||||
case CMD_HF_SNIFFER:
|
||||
HfSnoop(c->arg[0], c->arg[1]);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CMD_BUFF_CLEAR:
|
||||
|
@ -1323,7 +1348,7 @@ void __attribute__((noreturn)) AppMain(void)
|
|||
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;
|
||||
// PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
|
||||
AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |
|
||||
AT91C_PMC_PRES_CLK_4;
|
||||
AT91C_PMC_PRES_CLK_4; // 4 for 24Mhz pck0, 2 for 48 MHZ pck0
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;
|
||||
|
||||
// Reset SPI
|
||||
|
|
|
@ -58,7 +58,7 @@ extern uint8_t bits_per_sample ;
|
|||
extern bool averaging;
|
||||
|
||||
void AcquireRawAdcSamples125k(int divisor);
|
||||
void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command);
|
||||
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command);
|
||||
void ReadTItag(void);
|
||||
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
|
||||
|
||||
|
@ -73,24 +73,18 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
|
|||
void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol); // Realtime demodulation mode for AWID26
|
||||
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol);
|
||||
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
|
||||
void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an ioProx card to T5557/T5567
|
||||
void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567
|
||||
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
|
||||
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
|
||||
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
|
||||
void CopyIndala64toT55x7(int hi, int lo); // Clone Indala 64-bit tag by UID to T55x7
|
||||
void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int uid6, int uid7); // Clone Indala 224-bit tag by UID to T55x7
|
||||
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
|
||||
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
|
||||
void T55xxResetRead(void);
|
||||
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();
|
||||
void SendCmdPCF7931(uint32_t * tab);
|
||||
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
|
||||
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
|
||||
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
|
||||
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);
|
||||
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd);
|
||||
void T55xxWakeUp(uint32_t Pwd);
|
||||
void TurnReadLFOn();
|
||||
//void T55xxReadTrace(void);
|
||||
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
||||
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
||||
|
||||
|
@ -157,9 +151,6 @@ void OnSuccess();
|
|||
void OnError(uint8_t reason);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// iso15693.h
|
||||
void RecordRawAdcSamplesIso15693(void);
|
||||
void AcquireRawAdcSamplesIso15693(void);
|
||||
|
@ -175,6 +166,13 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
|||
void ReaderIClass(uint8_t arg0);
|
||||
void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
|
||||
void IClass_iso14443A_GetPublic(uint8_t arg0);
|
||||
void iClass_Authentication(uint8_t *MAC);
|
||||
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data);
|
||||
void iClass_ReadBlk(uint8_t blockNo);
|
||||
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata);
|
||||
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
|
||||
|
||||
// hitag2.h
|
||||
void SnoopHitag(uint32_t type);
|
||||
|
@ -186,5 +184,6 @@ bool cmd_receive(UsbCommand* cmd);
|
|||
bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
|
||||
|
||||
/// util.h
|
||||
void HfSnoop(int , int);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,6 +43,7 @@ void SetAdcMuxFor(uint32_t whichGpio);
|
|||
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5)
|
||||
// BOTH
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<5)
|
||||
// Options for LF_ADC
|
||||
|
|
79
armsrc/hfsnoop.c
Normal file
79
armsrc/hfsnoop.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "BigBuf.h"
|
||||
#include "util.h"
|
||||
|
||||
static void RAMFUNC optimizedSnoop(void);
|
||||
|
||||
static void RAMFUNC optimizedSnoop(void)
|
||||
{
|
||||
int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
|
||||
|
||||
uint16_t *dest = (uint16_t *)BigBuf_get_addr();
|
||||
uint16_t *destend = dest + n;
|
||||
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); // Setting Frame mode, 16 bits per word
|
||||
// Reading data loop
|
||||
while(dest <= destend)
|
||||
{
|
||||
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)
|
||||
{
|
||||
*dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||
dest = dest + 1;
|
||||
}
|
||||
}
|
||||
//Resetting Frame mode (First set in fpgaloader.c)
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
}
|
||||
|
||||
void HfSnoop(int samplesToSkip, int triggersToSkip)
|
||||
{
|
||||
Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.", samplesToSkip, triggersToSkip);
|
||||
bool trigger_cnt;
|
||||
LED_D_ON();
|
||||
// Select correct configs
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||
SpinDelay(100);
|
||||
|
||||
BigBuf_free();
|
||||
BigBuf_Clear();
|
||||
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); // Setting Frame Mode For better performance on high speed data transfer.
|
||||
|
||||
trigger_cnt = 0;
|
||||
uint16_t r = 0;
|
||||
while(!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
r = (uint16_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
r = MAX(r & 0xff, r >> 8);
|
||||
if (r >= 240)
|
||||
{
|
||||
if (++trigger_cnt > triggersToSkip) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!BUTTON_PRESS()) {
|
||||
int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0
|
||||
while(waitcount != 0) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
waitcount--;
|
||||
}
|
||||
}
|
||||
optimizedSnoop();
|
||||
Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r);
|
||||
}
|
||||
|
||||
DbpString("HF Snoop end");
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
}
|
||||
|
286
armsrc/iclass.c
286
armsrc/iclass.c
|
@ -1601,16 +1601,16 @@ void setupIclassReader()
|
|||
|
||||
}
|
||||
|
||||
size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
|
||||
bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
|
||||
{
|
||||
while(retries-- > 0)
|
||||
{
|
||||
ReaderTransmitIClass(command, cmdsize);
|
||||
if(expected_size == ReaderReceiveIClass(resp)){
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 1;//Error
|
||||
return false;//Error
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1620,14 +1620,17 @@ size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t*
|
|||
* 1 = Got CSN
|
||||
* 2 = Got CSN and CC
|
||||
*/
|
||||
uint8_t handshakeIclassTag(uint8_t *card_data)
|
||||
uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key)
|
||||
{
|
||||
static uint8_t act_all[] = { 0x0a };
|
||||
static uint8_t identify[] = { 0x0c };
|
||||
//static uint8_t identify[] = { 0x0c };
|
||||
static uint8_t identify[] = { 0x0c, 0x00, 0x73, 0x33 };
|
||||
static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
|
||||
static uint8_t readcheck_cc[]= { 0x88, 0x02,};
|
||||
static uint8_t readcheck_cc[]= { 0x88, 0x02 };
|
||||
if (use_credit_key)
|
||||
readcheck_cc[0] = 0x18;
|
||||
else
|
||||
readcheck_cc[0] = 0x88;
|
||||
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
|
||||
|
@ -1668,6 +1671,9 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
|
|||
|
||||
return read_status;
|
||||
}
|
||||
uint8_t handshakeIclassTag(uint8_t *card_data){
|
||||
return handshakeIclassTag_ext(card_data, false);
|
||||
}
|
||||
|
||||
|
||||
// Reader iClass Anticollission
|
||||
|
@ -1687,6 +1693,9 @@ void ReaderIClass(uint8_t arg0) {
|
|||
uint8_t result_status = 0;
|
||||
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
|
||||
bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
|
||||
bool use_credit_key = false;
|
||||
if (arg0 & FLAG_ICLASS_READER_CEDITKEY)
|
||||
use_credit_key = true;
|
||||
set_tracing(TRUE);
|
||||
setupIclassReader();
|
||||
|
||||
|
@ -1701,7 +1710,7 @@ void ReaderIClass(uint8_t arg0) {
|
|||
}
|
||||
WDT_HIT();
|
||||
|
||||
read_status = handshakeIclassTag(card_data);
|
||||
read_status = handshakeIclassTag_ext(card_data, use_credit_key);
|
||||
|
||||
if(read_status == 0) continue;
|
||||
if(read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
|
||||
|
@ -1715,11 +1724,10 @@ void ReaderIClass(uint8_t arg0) {
|
|||
if(arg0 & FLAG_ICLASS_READER_CONF)
|
||||
{
|
||||
if(sendCmdGetResponseWithRetries(readConf, sizeof(readConf),card_data+8, 10, 10))
|
||||
{
|
||||
Dbprintf("Failed to dump config block");
|
||||
}else
|
||||
{
|
||||
result_status |= FLAG_ICLASS_READER_CONF;
|
||||
} else {
|
||||
Dbprintf("Failed to dump config block");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1727,10 +1735,9 @@ void ReaderIClass(uint8_t arg0) {
|
|||
if(arg0 & FLAG_ICLASS_READER_AA){
|
||||
if(sendCmdGetResponseWithRetries(readAA, sizeof(readAA),card_data+(8*4), 10, 10))
|
||||
{
|
||||
// Dbprintf("Failed to dump AA block");
|
||||
}else
|
||||
{
|
||||
result_status |= FLAG_ICLASS_READER_AA;
|
||||
} else {
|
||||
//Dbprintf("Failed to dump AA block");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1762,8 +1769,8 @@ void ReaderIClass(uint8_t arg0) {
|
|||
}
|
||||
LED_B_OFF();
|
||||
}
|
||||
cmd_send(CMD_ACK,0,0,0,card_data, 0);
|
||||
LED_A_OFF();
|
||||
cmd_send(CMD_ACK,0,0,0,card_data, 0);
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||
|
@ -1814,7 +1821,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
|||
//for now replay captured auth (as cc not updated)
|
||||
memcpy(check+5,MAC,4);
|
||||
|
||||
if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
|
||||
if(!sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
|
||||
{
|
||||
Dbprintf("Error: Authentication Fail!");
|
||||
continue;
|
||||
|
@ -1826,7 +1833,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
|||
read[2] = crc >> 8;
|
||||
read[3] = crc & 0xff;
|
||||
|
||||
if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
|
||||
if(!sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
|
||||
{
|
||||
Dbprintf("Dump config (block 1) failed");
|
||||
continue;
|
||||
|
@ -1853,7 +1860,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
|||
read[2] = crc >> 8;
|
||||
read[3] = crc & 0xff;
|
||||
|
||||
if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
|
||||
if(sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
|
||||
{
|
||||
Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
block, resp[0], resp[1], resp[2],
|
||||
|
@ -1904,130 +1911,129 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
|||
LED_A_OFF();
|
||||
}
|
||||
|
||||
//2. Create Read method (cut-down from above) based off responses from 1.
|
||||
// Since we have the MAC could continue to use replay function.
|
||||
//3. Create Write method
|
||||
/*
|
||||
void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) {
|
||||
uint8_t act_all[] = { 0x0a };
|
||||
uint8_t identify[] = { 0x0c };
|
||||
uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t readcheck_cc[]= { 0x88, 0x02 };
|
||||
uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
|
||||
uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
uint16_t crc = 0;
|
||||
|
||||
uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
|
||||
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) {
|
||||
uint8_t readcheck[] = { keyType, blockNo };
|
||||
uint8_t resp[] = {0,0,0,0,0,0,0,0};
|
||||
size_t isOK = 0;
|
||||
isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6);
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
|
||||
// Reset trace buffer
|
||||
memset(trace, 0x44, RECV_CMD_OFFSET);
|
||||
traceLen = 0;
|
||||
void iClass_Authentication(uint8_t *MAC) {
|
||||
uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
memcpy(check+5,MAC,4);
|
||||
bool isOK;
|
||||
isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6);
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) {
|
||||
uint8_t readcmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; //0x88, 0x00 // can i use 0C?
|
||||
char bl = blockNo;
|
||||
uint16_t rdCrc = iclass_crc16(&bl, 1);
|
||||
readcmd[2] = rdCrc >> 8;
|
||||
readcmd[3] = rdCrc & 0xff;
|
||||
uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK = false;
|
||||
|
||||
// Setup SSC
|
||||
FpgaSetupSsc();
|
||||
// Start from off (no field generated)
|
||||
// Signal field is off with the appropriate LED
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
//readcmd[1] = blockNo;
|
||||
isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, 10, 10);
|
||||
memcpy(readdata, resp, sizeof(resp));
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
return isOK;
|
||||
}
|
||||
|
||||
// Now give it time to spin up.
|
||||
// Signal field is on with the appropriate LED
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
SpinDelay(200);
|
||||
void iClass_ReadBlk(uint8_t blockno) {
|
||||
uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK = false;
|
||||
isOK = iClass_ReadBlock(blockno, readblockdata);
|
||||
cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
void iClass_Dump(uint8_t blockno, uint8_t numblks) {
|
||||
uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK = false;
|
||||
uint8_t blkCnt = 0;
|
||||
|
||||
for(int i=0;i<1;i++) {
|
||||
|
||||
if(traceLen > TRACE_SIZE) {
|
||||
DbpString("Trace full");
|
||||
break;
|
||||
}
|
||||
|
||||
if (BUTTON_PRESS()) break;
|
||||
|
||||
// Send act_all
|
||||
ReaderTransmitIClass(act_all, 1);
|
||||
// Card present?
|
||||
if(ReaderReceiveIClass(resp)) {
|
||||
ReaderTransmitIClass(identify, 1);
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
// Select card
|
||||
memcpy(&select[1],resp,8);
|
||||
ReaderTransmitIClass(select, sizeof(select));
|
||||
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
resp[0], resp[1], resp[2],
|
||||
resp[3], resp[4], resp[5],
|
||||
resp[6], resp[7]);
|
||||
}
|
||||
// Card selected
|
||||
Dbprintf("Readcheck on Sector 2");
|
||||
ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
|
||||
if(ReaderReceiveIClass(resp) == 8) {
|
||||
Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
resp[0], resp[1], resp[2],
|
||||
resp[3], resp[4], resp[5],
|
||||
resp[6], resp[7]);
|
||||
}else return;
|
||||
Dbprintf("Authenticate");
|
||||
//for now replay captured auth (as cc not updated)
|
||||
memcpy(check+5,MAC,4);
|
||||
Dbprintf(" AA: %02x %02x %02x %02x",
|
||||
check[5], check[6], check[7],check[8]);
|
||||
ReaderTransmitIClass(check, sizeof(check));
|
||||
if(ReaderReceiveIClass(resp) == 4) {
|
||||
Dbprintf(" AR: %02x %02x %02x %02x",
|
||||
resp[0], resp[1], resp[2],resp[3]);
|
||||
}else {
|
||||
Dbprintf("Error: Authentication Fail!");
|
||||
return;
|
||||
}
|
||||
Dbprintf("Write Block");
|
||||
|
||||
//read configuration for max block number
|
||||
read_success=false;
|
||||
read[1]=1;
|
||||
uint8_t *blockno=&read[1];
|
||||
crc = iclass_crc16((char *)blockno,1);
|
||||
read[2] = crc >> 8;
|
||||
read[3] = crc & 0xff;
|
||||
while(!read_success){
|
||||
ReaderTransmitIClass(read, sizeof(read));
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
read_success=true;
|
||||
mem=resp[5];
|
||||
memory.k16= (mem & 0x80);
|
||||
memory.book= (mem & 0x20);
|
||||
memory.k2= (mem & 0x8);
|
||||
memory.lockauth= (mem & 0x2);
|
||||
memory.keyaccess= (mem & 0x1);
|
||||
|
||||
}
|
||||
}
|
||||
if (memory.k16){
|
||||
cardsize=255;
|
||||
}else cardsize=32;
|
||||
//check card_size
|
||||
|
||||
memcpy(write+1,blockNo,1);
|
||||
memcpy(write+2,data,8);
|
||||
memcpy(write+10,mac,4);
|
||||
while(!send_success){
|
||||
ReaderTransmitIClass(write, sizeof(write));
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
write_success=true;
|
||||
}
|
||||
}//
|
||||
}
|
||||
WDT_HIT();
|
||||
BigBuf_free();
|
||||
uint8_t *dataout = BigBuf_malloc(255*8);
|
||||
if (dataout == NULL){
|
||||
Dbprintf("out of memory");
|
||||
OnError(1);
|
||||
return;
|
||||
}
|
||||
|
||||
LED_A_OFF();
|
||||
}*/
|
||||
memset(dataout,0xFF,255*8);
|
||||
|
||||
for (;blkCnt < numblks; blkCnt++) {
|
||||
isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata);
|
||||
if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0xBB || readblockdata[2] == 0xBB)) { //try again
|
||||
isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata);
|
||||
if (!isOK) {
|
||||
Dbprintf("Block %02X failed to read", blkCnt+blockno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(dataout+(blkCnt*8),readblockdata,8);
|
||||
}
|
||||
//return pointer to dump memory in arg3
|
||||
cmd_send(CMD_ACK,isOK,blkCnt,BigBuf_max_traceLen(),0,0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
|
||||
uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
//uint8_t readblockdata[10];
|
||||
//write[1] = blockNo;
|
||||
memcpy(write+2, data, 12); // data + mac
|
||||
uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK;
|
||||
isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10);
|
||||
if (isOK) {
|
||||
//Dbprintf("WriteResp: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",resp[0],resp[1],resp[2],resp[3],resp[4],resp[5],resp[6],resp[7],resp[8],resp[9]);
|
||||
if (memcmp(write+2,resp,8)) {
|
||||
//error try again
|
||||
isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10);
|
||||
}
|
||||
}
|
||||
return isOK;
|
||||
}
|
||||
|
||||
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) {
|
||||
bool isOK = iClass_WriteBlock_ext(blockNo, data);
|
||||
if (isOK){
|
||||
Dbprintf("Write block [%02x] successful",blockNo);
|
||||
} else {
|
||||
Dbprintf("Write block [%02x] failed",blockNo);
|
||||
}
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
|
||||
int i;
|
||||
int written = 0;
|
||||
int total_block = (endblock - startblock) + 1;
|
||||
for (i = 0; i < total_block;i++){
|
||||
// block number
|
||||
if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){
|
||||
Dbprintf("Write block [%02x] successful",i + startblock);
|
||||
written++;
|
||||
} else {
|
||||
if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){
|
||||
Dbprintf("Write block [%02x] successful",i + startblock);
|
||||
written++;
|
||||
} else {
|
||||
Dbprintf("Write block [%02x] failed",i + startblock);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (written == total_block)
|
||||
Dbprintf("Clone complete");
|
||||
else
|
||||
Dbprintf("Clone incomplete");
|
||||
|
||||
cmd_send(CMD_ACK,1,0,0,0,0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
|
|
@ -213,6 +213,12 @@ void AppendCrc14443a(uint8_t* data, int len)
|
|||
ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
|
||||
}
|
||||
|
||||
void AppendCrc14443b(uint8_t* data, int len)
|
||||
{
|
||||
ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// ISO 14443 Type A - Miller decoder
|
||||
//=============================================================================
|
||||
|
@ -232,13 +238,17 @@ void AppendCrc14443a(uint8_t* data, int len)
|
|||
static tUart Uart;
|
||||
|
||||
// Lookup-Table to decide if 4 raw bits are a modulation.
|
||||
// We accept two or three consecutive "0" in any position with the rest "1"
|
||||
// We accept the following:
|
||||
// 0001 - a 3 tick wide pause
|
||||
// 0011 - a 2 tick wide pause, or a three tick wide pause shifted left
|
||||
// 0111 - a 2 tick wide pause shifted left
|
||||
// 1001 - a 2 tick wide pause shifted right
|
||||
const bool Mod_Miller_LUT[] = {
|
||||
TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE,
|
||||
TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE
|
||||
FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
|
||||
FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
|
||||
};
|
||||
#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x00F0) >> 4])
|
||||
#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x000F)])
|
||||
#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
|
||||
#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
|
||||
|
||||
void UartReset()
|
||||
{
|
||||
|
@ -248,8 +258,6 @@ void UartReset()
|
|||
Uart.parityLen = 0; // number of decoded parity bytes
|
||||
Uart.shiftReg = 0; // shiftreg to hold decoded data bits
|
||||
Uart.parityBits = 0; // holds 8 parity bits
|
||||
Uart.twoBits = 0x0000; // buffer for 2 Bits
|
||||
Uart.highCnt = 0;
|
||||
Uart.startTime = 0;
|
||||
Uart.endTime = 0;
|
||||
}
|
||||
|
@ -258,6 +266,7 @@ void UartInit(uint8_t *data, uint8_t *parity)
|
|||
{
|
||||
Uart.output = data;
|
||||
Uart.parity = parity;
|
||||
Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits
|
||||
UartReset();
|
||||
}
|
||||
|
||||
|
@ -265,40 +274,37 @@ void UartInit(uint8_t *data, uint8_t *parity)
|
|||
static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
||||
{
|
||||
|
||||
Uart.twoBits = (Uart.twoBits << 8) | bit;
|
||||
Uart.fourBits = (Uart.fourBits << 8) | bit;
|
||||
|
||||
if (Uart.state == STATE_UNSYNCD) { // not yet synced
|
||||
|
||||
if (Uart.highCnt < 2) { // wait for a stable unmodulated signal
|
||||
if (Uart.twoBits == 0xffff) {
|
||||
Uart.highCnt++;
|
||||
} else {
|
||||
Uart.highCnt = 0;
|
||||
}
|
||||
} else {
|
||||
Uart.syncBit = 0xFFFF; // not set
|
||||
// we look for a ...1111111100x11111xxxxxx pattern (the start bit)
|
||||
if ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8; // mask is 11x11111 xxxxxxxx,
|
||||
// check for 00x11111 xxxxxxxx
|
||||
else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7; // both masks shifted right one bit, left padded with '1'
|
||||
else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6; // ...
|
||||
else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5;
|
||||
else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4;
|
||||
else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3;
|
||||
else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2;
|
||||
else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1;
|
||||
if (Uart.syncBit != 0xFFFF) { // found a sync bit
|
||||
Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
|
||||
Uart.startTime -= Uart.syncBit;
|
||||
Uart.endTime = Uart.startTime;
|
||||
Uart.state = STATE_START_OF_COMMUNICATION;
|
||||
}
|
||||
Uart.syncBit = 9999; // not set
|
||||
// The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
|
||||
// Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
|
||||
// we therefore look for a ...xx11111111111100x11111xxxxxx... pattern
|
||||
// (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
|
||||
#define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000
|
||||
#define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00000111 11111111 10001111 10000000
|
||||
if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7;
|
||||
else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6;
|
||||
else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5;
|
||||
else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4;
|
||||
else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3;
|
||||
else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2;
|
||||
else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1;
|
||||
else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0;
|
||||
|
||||
if (Uart.syncBit != 9999) { // found a sync bit
|
||||
Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
|
||||
Uart.startTime -= Uart.syncBit;
|
||||
Uart.endTime = Uart.startTime;
|
||||
Uart.state = STATE_START_OF_COMMUNICATION;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) {
|
||||
if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation in both halves - error
|
||||
if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {
|
||||
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error
|
||||
UartReset();
|
||||
} else { // Modulation in first half = Sequence Z = logic "0"
|
||||
if (Uart.state == STATE_MILLER_X) { // error - must not follow after X
|
||||
|
@ -322,7 +328,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
|
||||
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
|
||||
Uart.bitCount++;
|
||||
Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg
|
||||
Uart.state = STATE_MILLER_X;
|
||||
|
@ -358,12 +364,10 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
return TRUE; // we are finished with decoding the raw data sequence
|
||||
} else {
|
||||
UartReset(); // Nothing received - start over
|
||||
Uart.highCnt = 1;
|
||||
}
|
||||
}
|
||||
if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||
UartReset();
|
||||
Uart.highCnt = 1;
|
||||
} else { // a logic "0"
|
||||
Uart.bitCount++;
|
||||
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
|
||||
|
@ -680,6 +684,9 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
|
||||
// And ready to receive another response.
|
||||
DemodReset();
|
||||
// And reset the Miller decoder including itS (now outdated) input buffer
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
LED_C_OFF();
|
||||
}
|
||||
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
|
||||
|
@ -1336,7 +1343,7 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8
|
|||
}
|
||||
|
||||
// Only transmit parity bit if we transmitted a complete byte
|
||||
if (j == 8) {
|
||||
if (j == 8 && parity != NULL) {
|
||||
// Get the parity bit
|
||||
if (parity[i>>3] & (0x80 >> (i&0x0007))) {
|
||||
// Sequence X
|
||||
|
@ -1630,6 +1637,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing)
|
||||
{
|
||||
CodeIso14443aBitsAsReaderPar(frame, bits, par);
|
||||
|
@ -1645,11 +1653,13 @@ void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing)
|
||||
{
|
||||
ReaderTransmitBitsPar(frame, len*8, par, timing);
|
||||
}
|
||||
|
||||
|
||||
void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
|
||||
{
|
||||
// Generate parity and redirect
|
||||
|
@ -1658,6 +1668,7 @@ void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
|
|||
ReaderTransmitBitsPar(frame, len, par, timing);
|
||||
}
|
||||
|
||||
|
||||
void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
|
||||
{
|
||||
// Generate parity and redirect
|
||||
|
@ -1722,6 +1733,11 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
|||
}
|
||||
}
|
||||
|
||||
// check for proprietary anticollision:
|
||||
if ((resp[0] & 0x1F) == 0) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
|
||||
// which case we need to make a cascade 2 request and select - this is a long UID
|
||||
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
||||
|
@ -1938,15 +1954,38 @@ void ReaderIso14443a(UsbCommand *c)
|
|||
|
||||
if(param & ISO14A_RAW) {
|
||||
if(param & ISO14A_APPEND_CRC) {
|
||||
AppendCrc14443a(cmd,len);
|
||||
if(param & ISO14A_TOPAZMODE) {
|
||||
AppendCrc14443b(cmd,len);
|
||||
} else {
|
||||
AppendCrc14443a(cmd,len);
|
||||
}
|
||||
len += 2;
|
||||
if (lenbits) lenbits += 16;
|
||||
}
|
||||
if(lenbits>0) {
|
||||
GetParity(cmd, lenbits/8, par);
|
||||
ReaderTransmitBitsPar(cmd, lenbits, par, NULL);
|
||||
} else {
|
||||
ReaderTransmit(cmd,len, NULL);
|
||||
if(lenbits>0) { // want to send a specific number of bits (e.g. short commands)
|
||||
if(param & ISO14A_TOPAZMODE) {
|
||||
int bits_to_send = lenbits;
|
||||
uint16_t i = 0;
|
||||
ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity
|
||||
bits_to_send -= 7;
|
||||
while (bits_to_send > 0) {
|
||||
ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL); // following bytes are 8 bit and no parity
|
||||
bits_to_send -= 8;
|
||||
}
|
||||
} else {
|
||||
GetParity(cmd, lenbits/8, par);
|
||||
ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity
|
||||
}
|
||||
} else { // want to send complete bytes only
|
||||
if(param & ISO14A_TOPAZMODE) {
|
||||
uint16_t i = 0;
|
||||
ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy
|
||||
while (i < len) {
|
||||
ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL); // following bytes: 8 bits, no paritiy
|
||||
}
|
||||
} else {
|
||||
ReaderTransmit(cmd,len, NULL); // 8 bits, odd parity
|
||||
}
|
||||
}
|
||||
arg0 = ReaderReceive(buf, par);
|
||||
cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
|
||||
|
@ -2905,7 +2944,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
|||
if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break;
|
||||
|
||||
/* And ready to receive another command. */
|
||||
UartReset();
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
/* And also reset the demod code */
|
||||
DemodReset();
|
||||
|
@ -2922,6 +2961,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
|||
|
||||
// And ready to receive another response.
|
||||
DemodReset();
|
||||
// And reset the Miller decoder including its (now outdated) input buffer
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
}
|
||||
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
|
||||
}
|
||||
|
|
|
@ -56,15 +56,14 @@ typedef struct {
|
|||
// DROP_FIRST_HALF,
|
||||
} state;
|
||||
uint16_t shiftReg;
|
||||
uint16_t bitCount;
|
||||
int16_t bitCount;
|
||||
uint16_t len;
|
||||
uint16_t byteCntMax;
|
||||
uint16_t posCnt;
|
||||
uint16_t syncBit;
|
||||
uint8_t parityBits;
|
||||
uint8_t parityLen;
|
||||
uint16_t highCnt;
|
||||
uint16_t twoBits;
|
||||
uint32_t fourBits;
|
||||
uint32_t startTime, endTime;
|
||||
uint8_t *output;
|
||||
uint8_t *parity;
|
||||
|
|
1116
armsrc/lfops.c
1116
armsrc/lfops.c
File diff suppressed because it is too large
Load diff
|
@ -103,7 +103,6 @@ void LFSetupFPGAForADC(int divisor, bool lf_field)
|
|||
FpgaSetupSsc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Does the sample acquisition. If threshold is specified, the actual sampling
|
||||
* is not commenced until the threshold has been reached.
|
||||
|
@ -154,9 +153,6 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
|
|||
if ((trigger_threshold > 0) && (sample < (trigger_threshold+128)) && (sample > (128-trigger_threshold))) //
|
||||
continue;
|
||||
|
||||
//if (trigger_threshold > 0 && sample < trigger_threshold) //
|
||||
//continue;
|
||||
|
||||
trigger_threshold = 0;
|
||||
sample_total_numbers++;
|
||||
|
||||
|
@ -252,3 +248,59 @@ uint32_t SnoopLF()
|
|||
{
|
||||
return ReadLF(false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds
|
||||
* the data is collected in BigBuf.
|
||||
**/
|
||||
void doT55x7Acquisition(size_t sample_size) {
|
||||
|
||||
#define T55xx_READ_UPPER_THRESHOLD 128+40 // 40 grph
|
||||
#define T55xx_READ_TOL 5
|
||||
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
uint16_t bufsize = BigBuf_max_traceLen();
|
||||
|
||||
if ( bufsize > sample_size )
|
||||
bufsize = sample_size;
|
||||
|
||||
uint16_t i = 0;
|
||||
bool startFound = false;
|
||||
bool highFound = false;
|
||||
uint8_t curSample = 0;
|
||||
uint8_t firstSample = 0;
|
||||
uint16_t skipCnt = 0;
|
||||
while(!BUTTON_PRESS() && skipCnt<1000) {
|
||||
WDT_HIT();
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||
LED_D_ON();
|
||||
}
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
LED_D_OFF();
|
||||
|
||||
// skip until the first high sample above threshold
|
||||
if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) {
|
||||
if (curSample > firstSample)
|
||||
firstSample = curSample;
|
||||
highFound = true;
|
||||
} else if (!highFound) {
|
||||
skipCnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip until first high samples begin to change
|
||||
if (startFound || curSample < firstSample-T55xx_READ_TOL){
|
||||
// if just found start - recover last sample
|
||||
if (!startFound) {
|
||||
dest[i++] = firstSample;
|
||||
startFound = true;
|
||||
}
|
||||
// collect samples
|
||||
dest[i++] = curSample;
|
||||
if (i >= bufsize-1) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#ifndef LFSAMPLING_H
|
||||
#define LFSAMPLING_H
|
||||
|
||||
/**
|
||||
* acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds
|
||||
* the data is collected in BigBuf.
|
||||
**/
|
||||
void doT55x7Acquisition(size_t sample_size);
|
||||
|
||||
/**
|
||||
* Initializes the FPGA for reader-mode (field on), and acquires the samples.
|
||||
* @return number of bits sampled
|
||||
|
@ -41,7 +47,6 @@ uint32_t DoAcquisition_config( bool silent);
|
|||
**/
|
||||
void LFSetupFPGAForADC(int divisor, bool lf_field);
|
||||
|
||||
|
||||
/**
|
||||
* Called from the USB-handler to set the sampling configuration
|
||||
* The sampling config is used for std reading and snooping.
|
||||
|
|
526
armsrc/pcf7931.c
Normal file
526
armsrc/pcf7931.c
Normal file
|
@ -0,0 +1,526 @@
|
|||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "lfsampling.h"
|
||||
#include "pcf7931.h"
|
||||
#include "string.h"
|
||||
|
||||
#define T0_PCF 8 //period for the pcf7931 in us
|
||||
#define ALLOC 16
|
||||
|
||||
#define abs(x) ( ((x)<0) ? -(x) : (x) )
|
||||
#define max(x,y) ( x<y ? y:x)
|
||||
|
||||
int DemodPCF7931(uint8_t **outBlocks) {
|
||||
|
||||
uint8_t bits[256] = {0x00};
|
||||
uint8_t blocks[8][16];
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
int GraphTraceLen = BigBuf_max_traceLen();
|
||||
if ( GraphTraceLen > 18000 )
|
||||
GraphTraceLen = 18000;
|
||||
|
||||
|
||||
int i, j, lastval, bitidx, half_switch;
|
||||
int clock = 64;
|
||||
int tolerance = clock / 8;
|
||||
int pmc, block_done;
|
||||
int lc, warnings = 0;
|
||||
int num_blocks = 0;
|
||||
int lmin=128, lmax=128;
|
||||
uint8_t dir;
|
||||
|
||||
LFSetupFPGAForADC(95, true);
|
||||
DoAcquisition_default(0, true);
|
||||
|
||||
lmin = 64;
|
||||
lmax = 192;
|
||||
|
||||
i = 2;
|
||||
|
||||
/* Find first local max/min */
|
||||
if(dest[1] > dest[0]) {
|
||||
while(i < GraphTraceLen) {
|
||||
if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
dir = 0;
|
||||
}
|
||||
else {
|
||||
while(i < GraphTraceLen) {
|
||||
if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
dir = 1;
|
||||
}
|
||||
|
||||
lastval = i++;
|
||||
half_switch = 0;
|
||||
pmc = 0;
|
||||
block_done = 0;
|
||||
|
||||
for (bitidx = 0; i < GraphTraceLen; i++)
|
||||
{
|
||||
if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[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) {
|
||||
bits[bitidx++] = 0;
|
||||
half_switch = 0;
|
||||
}
|
||||
else
|
||||
half_switch++;
|
||||
} else if (abs(lc-clock) < tolerance) {
|
||||
// 64TO
|
||||
bits[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*bits[j*8+7]+
|
||||
64*bits[j*8+6]+
|
||||
32*bits[j*8+5]+
|
||||
16*bits[j*8+4]+
|
||||
8*bits[j*8+3]+
|
||||
4*bits[j*8+2]+
|
||||
2*bits[j*8+1]+
|
||||
bits[j*8];
|
||||
|
||||
}
|
||||
num_blocks++;
|
||||
}
|
||||
bitidx = 0;
|
||||
block_done = 0;
|
||||
half_switch = 0;
|
||||
}
|
||||
if(i < GraphTraceLen)
|
||||
dir =(dest[i-1] > dest[i]) ? 0 : 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;
|
||||
}
|
||||
|
||||
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<n; i++)
|
||||
Dbprintf("(dbg) %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
tmpBlocks[i][0], tmpBlocks[i][1], tmpBlocks[i][2], tmpBlocks[i][3], tmpBlocks[i][4], tmpBlocks[i][5], tmpBlocks[i][6], tmpBlocks[i][7],
|
||||
tmpBlocks[i][8], tmpBlocks[i][9], tmpBlocks[i][10], tmpBlocks[i][11], tmpBlocks[i][12], tmpBlocks[i][13], tmpBlocks[i][14], tmpBlocks[i][15]);
|
||||
if(!ident) {
|
||||
for(i=0; i<n; i++) {
|
||||
if(IsBlock0PCF7931(tmpBlocks[i])) {
|
||||
// Found block 0 ?
|
||||
if(i < n-1 && IsBlock1PCF7931(tmpBlocks[i+1])) {
|
||||
// Found block 1!
|
||||
// \o/
|
||||
ident = 1;
|
||||
memcpy(Blocks[0], tmpBlocks[i], 16);
|
||||
Blocks[0][ALLOC] = 1;
|
||||
memcpy(Blocks[1], tmpBlocks[i+1], 16);
|
||||
Blocks[1][ALLOC] = 1;
|
||||
max_blocks = max((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
|
||||
// Debug print
|
||||
Dbprintf("(dbg) Max blocks: %d", max_blocks);
|
||||
num_blocks = 2;
|
||||
// Handle following blocks
|
||||
for(j=i+2, ind2=2; j!=i; j++, ind2++, num_blocks++) {
|
||||
if(j==n) j=0;
|
||||
if(j==i) break;
|
||||
memcpy(Blocks[ind2], tmpBlocks[j], 16);
|
||||
Blocks[ind2][ALLOC] = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(i=0; i<n; i++) { // Look for identical block in known blocks
|
||||
if(memcmp(tmpBlocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { // Block is not full of 00
|
||||
for(j=0; j<max_blocks; j++) {
|
||||
if(Blocks[j][ALLOC] == 1 && !memcmp(tmpBlocks[i], Blocks[j], 16)) {
|
||||
// Found an identical block
|
||||
for(ind=i-1,ind2=j-1; ind >= 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<max_blocks; i++) {
|
||||
if(Blocks[i][ALLOC]==1)
|
||||
Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
Blocks[i][0], Blocks[i][1], Blocks[i][2], Blocks[i][3], Blocks[i][4], Blocks[i][5], Blocks[i][6], Blocks[i][7],
|
||||
Blocks[i][8], Blocks[i][9], Blocks[i][10], Blocks[i][11], Blocks[i][12], Blocks[i][13], Blocks[i][14], Blocks[i][15]);
|
||||
else
|
||||
Dbprintf("<missing block %d>", i);
|
||||
}
|
||||
Dbprintf("-----------------------------------------");
|
||||
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
}
|
||||
|
||||
|
||||
/* Write on a byte of a PCF7931 tag
|
||||
* @param address : address of the block to write
|
||||
@param byte : address of the byte to write
|
||||
@param data : data to write
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
||||
uint32_t tab[1024]={0}; // data times frame
|
||||
uint32_t u = 0;
|
||||
uint8_t parity = 0;
|
||||
bool comp = 0;
|
||||
|
||||
//BUILD OF THE DATA FRAME
|
||||
|
||||
//alimentation of the tag (time for initializing)
|
||||
AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
|
||||
|
||||
//PMC
|
||||
Dbprintf("Initialization delay : %d us", init_delay);
|
||||
AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
|
||||
|
||||
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
|
||||
|
||||
//password indication bit
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
|
||||
|
||||
//password (on 56 bits)
|
||||
Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7);
|
||||
AddBytePCF7931(pass1, tab, l, p);
|
||||
AddBytePCF7931(pass2, tab, l, p);
|
||||
AddBytePCF7931(pass3, tab, l, p);
|
||||
AddBytePCF7931(pass4, tab, l, p);
|
||||
AddBytePCF7931(pass5, tab, l, p);
|
||||
AddBytePCF7931(pass6, tab, l, p);
|
||||
AddBytePCF7931(pass7, tab, l, p);
|
||||
|
||||
//programming mode (0 or 1)
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
|
||||
//block adress on 6 bits
|
||||
Dbprintf("Block address : %02x", address);
|
||||
for (u=0; u<6; u++)
|
||||
{
|
||||
if (address&(1<<u)) { // bit 1
|
||||
parity++;
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
} else{ // bit 0
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
}
|
||||
}
|
||||
|
||||
//byte address on 4 bits
|
||||
Dbprintf("Byte address : %02x", byte);
|
||||
for (u=0; u<4; u++)
|
||||
{
|
||||
if (byte&(1<<u)) { // bit 1
|
||||
parity++;
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
} else{ // bit 0
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
}
|
||||
}
|
||||
|
||||
//data on 8 bits
|
||||
Dbprintf("Data : %02x", data);
|
||||
for (u=0; u<8; u++)
|
||||
{
|
||||
if (data&(1<<u)) { // bit 1
|
||||
parity++;
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
} else{ //bit 0
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//parity bit
|
||||
if((parity%2)==0){
|
||||
AddBitPCF7931(0, tab, l, p); //even parity
|
||||
}else{
|
||||
AddBitPCF7931(1, tab, l, p);//odd parity
|
||||
}
|
||||
|
||||
//time access memory
|
||||
AddPatternPCF7931(5120+2680, 0, 0, tab);
|
||||
|
||||
//conversion of the scale time
|
||||
for(u=0;u<500;u++){
|
||||
tab[u]=(tab[u] * 3)/2;
|
||||
}
|
||||
|
||||
|
||||
//compennsation of the counter reload
|
||||
while (!comp){
|
||||
comp = 1;
|
||||
for(u=0;tab[u]!=0;u++){
|
||||
if(tab[u] > 0xFFFF){
|
||||
tab[u] -= 0xFFFF;
|
||||
comp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendCmdPCF7931(tab);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Send a trame to a PCF7931 tags
|
||||
* @param tab : array of the data frame
|
||||
*/
|
||||
|
||||
void SendCmdPCF7931(uint32_t * tab){
|
||||
uint16_t u=0;
|
||||
uint16_t tempo=0;
|
||||
|
||||
Dbprintf("SENDING DATA FRAME...");
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
// steal this pin from the SSP and use it to control the modulation
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
|
||||
//initialization of the timer
|
||||
AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
|
||||
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
|
||||
AT91C_BASE_TCB->TCB_BCR = 1;
|
||||
|
||||
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
for(u=0;tab[u]!= 0;u+=3){
|
||||
|
||||
|
||||
// modulate antenna
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
while(tempo != tab[u]){
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
}
|
||||
|
||||
// stop modulating antenna
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
while(tempo != tab[u+1]){
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
}
|
||||
|
||||
|
||||
// modulate antenna
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
while(tempo != tab[u+2]){
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
LED_A_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
DbpString("FINISH !");
|
||||
DbpString("(Could be usefull to send the same trame many times)");
|
||||
LED(0xFFFF, 1000);
|
||||
}
|
||||
|
||||
|
||||
/* Add a byte for building the data frame of PCF7931 tags
|
||||
* @param b : byte to add
|
||||
* @param tab : array of the data frame
|
||||
* @param l : offset on low pulse width
|
||||
* @param p : offset on low pulse positioning
|
||||
*/
|
||||
|
||||
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
|
||||
|
||||
uint32_t u;
|
||||
for (u=0; u<8; u++)
|
||||
{
|
||||
if (byte&(1<<u)) { //bit à 1
|
||||
if(AddBitPCF7931(1, tab, l, p)==1)return 1;
|
||||
} else { //bit à 0
|
||||
if(AddBitPCF7931(0, tab, l, p)==1)return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add a bits for building the data frame of PCF7931 tags
|
||||
* @param b : bit to add
|
||||
* @param tab : array of the data frame
|
||||
* @param l : offset on low pulse width
|
||||
* @param p : offset on low pulse positioning
|
||||
*/
|
||||
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
|
||||
uint8_t u = 0;
|
||||
|
||||
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
|
||||
|
||||
|
||||
if(b==1){ //add a bit 1
|
||||
if(u==0) tab[u] = 34*T0_PCF+p;
|
||||
else tab[u] = 34*T0_PCF+tab[u-1]+p;
|
||||
|
||||
tab[u+1] = 6*T0_PCF+tab[u]+l;
|
||||
tab[u+2] = 88*T0_PCF+tab[u+1]-l-p;
|
||||
return 0;
|
||||
}else{ //add a bit 0
|
||||
|
||||
if(u==0) tab[u] = 98*T0_PCF+p;
|
||||
else tab[u] = 98*T0_PCF+tab[u-1]+p;
|
||||
|
||||
tab[u+1] = 6*T0_PCF+tab[u]+l;
|
||||
tab[u+2] = 24*T0_PCF+tab[u+1]-l-p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add a custom pattern in the data frame
|
||||
* @param a : delay of the first high pulse
|
||||
* @param b : delay of the low pulse
|
||||
* @param c : delay of the last high pulse
|
||||
* @param tab : array of the data frame
|
||||
*/
|
||||
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){
|
||||
uint32_t u = 0;
|
||||
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
|
||||
|
||||
if(u==0) tab[u] = a;
|
||||
else tab[u] = a + tab[u-1];
|
||||
|
||||
tab[u+1] = b+tab[u];
|
||||
tab[u+2] = c+tab[u+1];
|
||||
|
||||
return 0;
|
||||
}
|
14
armsrc/pcf7931.h
Normal file
14
armsrc/pcf7931.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef __PCF7931_H
|
||||
#define __PCF7931_H
|
||||
|
||||
int DemodPCF7931(uint8_t **outBlocks);
|
||||
int IsBlock0PCF7931(uint8_t *Block);
|
||||
int IsBlock1PCF7931(uint8_t *Block);
|
||||
void ReadPCF7931();
|
||||
void SendCmdPCF7931(uint32_t * tab);
|
||||
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
|
||||
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
|
||||
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
|
||||
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);
|
||||
|
||||
#endif
|
|
@ -86,6 +86,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
cmdhfmf.c \
|
||||
cmdhfmfu.c \
|
||||
cmdhfmfhard.c \
|
||||
cmdhftopaz.c \
|
||||
cmdhw.c \
|
||||
cmdlf.c \
|
||||
cmdlfio.c \
|
||||
|
|
|
@ -637,6 +637,32 @@ int CmdG_Prox_II_Demod(const char *Cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//see ASKDemod for what args are accepted
|
||||
int CmdVikingDemod(const char *Cmd)
|
||||
{
|
||||
if (!ASKDemod(Cmd, false, false, 1)) {
|
||||
if (g_debugMode) PrintAndLog("ASKDemod failed");
|
||||
return 0;
|
||||
}
|
||||
size_t size = DemodBufferLen;
|
||||
//call lfdemod.c demod for gProxII
|
||||
int ans = VikingDemod_AM(DemodBuffer, &size);
|
||||
if (ans < 0) {
|
||||
if (g_debugMode) PrintAndLog("Error Viking_Demod %d", ans);
|
||||
return 0;
|
||||
}
|
||||
//got a good demod
|
||||
uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
|
||||
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
|
||||
uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32);
|
||||
uint8_t checksum = bytebits_to_byte(DemodBuffer+ans+32+24, 8);
|
||||
PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, checksum);
|
||||
PrintAndLog("Raw: %08X%08X", raw1,raw2);
|
||||
setDemodBuf(DemodBuffer+ans, 64, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//by marshmellow - see ASKDemod
|
||||
int Cmdaskrawdemod(const char *Cmd)
|
||||
{
|
||||
|
@ -1130,8 +1156,6 @@ int CmdFSKdemodParadox(const char *Cmd)
|
|||
//print ioprox ID and some format details
|
||||
int CmdFSKdemodIO(const char *Cmd)
|
||||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
//set defaults
|
||||
int idx=0;
|
||||
//something in graphbuffer?
|
||||
if (GraphTraceLen < 65) {
|
||||
|
@ -1220,11 +1244,6 @@ int CmdFSKdemodIO(const char *Cmd)
|
|||
//print full AWID Prox ID and some bit format details if found
|
||||
int CmdFSKdemodAWID(const char *Cmd)
|
||||
{
|
||||
|
||||
//int verbose=1;
|
||||
//sscanf(Cmd, "%i", &verbose);
|
||||
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
size_t size = getFromGraphBuf(BitStream);
|
||||
if (size==0) return 0;
|
||||
|
@ -1423,7 +1442,6 @@ int CmdFSKdemodPyramid(const char *Cmd)
|
|||
uint32_t fc = 0;
|
||||
uint32_t cardnum = 0;
|
||||
uint32_t code1 = 0;
|
||||
//uint32_t code2 = 0;
|
||||
if (fmtLen==26){
|
||||
fc = bytebits_to_byte(BitStream+73, 8);
|
||||
cardnum = bytebits_to_byte(BitStream+81, 16);
|
||||
|
@ -1597,61 +1615,33 @@ int CmdIndalaDecode(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
uint8_t invert=0;
|
||||
ans = indala26decode(DemodBuffer, &DemodBufferLen, &invert);
|
||||
if (ans < 1) {
|
||||
size_t size = DemodBufferLen;
|
||||
size_t startIdx = indala26decode(DemodBuffer, &size, &invert);
|
||||
if (startIdx < 1) {
|
||||
if (g_debugMode==1)
|
||||
PrintAndLog("Error2: %d",ans);
|
||||
return -1;
|
||||
}
|
||||
char showbits[251]={0x00};
|
||||
setDemodBuf(DemodBuffer, size, startIdx);
|
||||
if (invert)
|
||||
if (g_debugMode==1)
|
||||
PrintAndLog("Had to invert bits");
|
||||
|
||||
PrintAndLog("BitLen: %d",DemodBufferLen);
|
||||
//convert UID to HEX
|
||||
uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
|
||||
int idx;
|
||||
uid1=0;
|
||||
uid2=0;
|
||||
PrintAndLog("BitLen: %d",DemodBufferLen);
|
||||
if (DemodBufferLen==64){
|
||||
for( idx=0; idx<64; idx++) {
|
||||
uid1=(uid1<<1)|(uid2>>31);
|
||||
if (DemodBuffer[idx] == 0) {
|
||||
uid2=(uid2<<1)|0;
|
||||
showbits[idx]='0';
|
||||
} else {
|
||||
uid2=(uid2<<1)|1;
|
||||
showbits[idx]='1';
|
||||
}
|
||||
}
|
||||
showbits[idx]='\0';
|
||||
PrintAndLog("Indala UID=%s (%x%08x)", showbits, uid1, uid2);
|
||||
}
|
||||
else {
|
||||
uid3=0;
|
||||
uid4=0;
|
||||
uid5=0;
|
||||
uid6=0;
|
||||
uid7=0;
|
||||
for( idx=0; idx<DemodBufferLen; idx++) {
|
||||
uid1=(uid1<<1)|(uid2>>31);
|
||||
uid2=(uid2<<1)|(uid3>>31);
|
||||
uid3=(uid3<<1)|(uid4>>31);
|
||||
uid4=(uid4<<1)|(uid5>>31);
|
||||
uid5=(uid5<<1)|(uid6>>31);
|
||||
uid6=(uid6<<1)|(uid7>>31);
|
||||
if (DemodBuffer[idx] == 0) {
|
||||
uid7=(uid7<<1)|0;
|
||||
showbits[idx]='0';
|
||||
}
|
||||
else {
|
||||
uid7=(uid7<<1)|1;
|
||||
showbits[idx]='1';
|
||||
}
|
||||
}
|
||||
showbits[idx]='\0';
|
||||
PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
|
||||
uid1=bytebits_to_byte(DemodBuffer,32);
|
||||
uid2=bytebits_to_byte(DemodBuffer+32,32);
|
||||
if (DemodBufferLen==64) {
|
||||
PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin(DemodBuffer,DemodBufferLen), uid1, uid2);
|
||||
} else {
|
||||
uid3=bytebits_to_byte(DemodBuffer+64,32);
|
||||
uid4=bytebits_to_byte(DemodBuffer+96,32);
|
||||
uid5=bytebits_to_byte(DemodBuffer+128,32);
|
||||
uid6=bytebits_to_byte(DemodBuffer+160,32);
|
||||
uid7=bytebits_to_byte(DemodBuffer+192,32);
|
||||
PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)",
|
||||
sprint_bin(DemodBuffer,DemodBufferLen), uid1, uid2, uid3, uid4, uid5, uid6, uid7);
|
||||
}
|
||||
if (g_debugMode){
|
||||
PrintAndLog("DEBUG: printing demodbuffer:");
|
||||
|
@ -2353,6 +2343,7 @@ static command_t CommandTable[] =
|
|||
{"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ask demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"},
|
||||
{"askem410xdemod", CmdAskEM410xDemod, 1, "[clock] [invert<0|1>] [maxErr] -- Demodulate an EM410x tag from GraphBuffer (args optional)"},
|
||||
{"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"},
|
||||
{"askvikingdemod", CmdVikingDemod, 1, "Demodulate a Viking tag from GraphBuffer"},
|
||||
{"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"},
|
||||
{"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
|
||||
{"bin2hex", Cmdbin2hex, 1, "bin2hex <digits> -- Converts binary to hexadecimal"},
|
||||
|
|
|
@ -17,6 +17,7 @@ int CmdData(const char *Cmd);
|
|||
void printDemodBuff(void);
|
||||
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
|
||||
int CmdAskEM410xDemod(const char *Cmd);
|
||||
int CmdVikingDemod(const char *Cmd);
|
||||
int CmdG_Prox_II_Demod(const char *Cmd);
|
||||
int Cmdaskrawdemod(const char *Cmd);
|
||||
int Cmdaskmandemod(const char *Cmd);
|
||||
|
|
308
client/cmdhf.c
308
client/cmdhf.c
|
@ -23,6 +23,7 @@
|
|||
#include "cmdhficlass.h"
|
||||
#include "cmdhfmf.h"
|
||||
#include "cmdhfmfu.h"
|
||||
#include "cmdhftopaz.h"
|
||||
#include "protocols.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
@ -187,6 +188,26 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
||||
{
|
||||
switch(cmd[0]) {
|
||||
case TOPAZ_REQA :snprintf(exp, size, "REQA");break;
|
||||
case TOPAZ_WUPA :snprintf(exp, size, "WUPA");break;
|
||||
case TOPAZ_RID :snprintf(exp, size, "RID");break;
|
||||
case TOPAZ_RALL :snprintf(exp, size, "RALL");break;
|
||||
case TOPAZ_READ :snprintf(exp, size, "READ");break;
|
||||
case TOPAZ_WRITE_E :snprintf(exp, size, "WRITE-E");break;
|
||||
case TOPAZ_WRITE_NE :snprintf(exp, size, "WRITE-NE");break;
|
||||
case TOPAZ_RSEG :snprintf(exp, size, "RSEG");break;
|
||||
case TOPAZ_READ8 :snprintf(exp, size, "READ8");break;
|
||||
case TOPAZ_WRITE_E8 :snprintf(exp, size, "WRITE-E8");break;
|
||||
case TOPAZ_WRITE_NE8 :snprintf(exp, size, "WRITE-NE8");break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
06 00 = INITIATE
|
||||
0E xx = SELECT ID (xx = Chip-ID)
|
||||
|
@ -218,7 +239,34 @@ void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief iso14443B_CRC_Ok Checks CRC in command or response
|
||||
* @brief iso14443A_CRC_check Checks CRC in command or response
|
||||
* @param isResponse
|
||||
* @param data
|
||||
* @param len
|
||||
* @return 0 : CRC-command, CRC not ok
|
||||
* 1 : CRC-command, CRC ok
|
||||
* 2 : Not crc-command
|
||||
*/
|
||||
|
||||
uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
|
||||
{
|
||||
uint8_t b1,b2;
|
||||
|
||||
if(len <= 2) return 2;
|
||||
|
||||
if(isResponse & (len < 6)) return 2;
|
||||
|
||||
ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2);
|
||||
if (b1 != data[len-2] || b2 != data[len-1]) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief iso14443B_CRC_check Checks CRC in command or response
|
||||
* @param isResponse
|
||||
* @param data
|
||||
* @param len
|
||||
|
@ -235,9 +283,10 @@ uint8_t iso14443B_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
|
|||
|
||||
ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2);
|
||||
if(b1 != data[len-2] || b2 != data[len-1]) {
|
||||
return 0;
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -301,11 +350,66 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
|
||||
|
||||
bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen)
|
||||
{
|
||||
return(tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen);
|
||||
}
|
||||
|
||||
|
||||
bool next_record_is_response(uint16_t tracepos, uint8_t *trace)
|
||||
{
|
||||
uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t)));
|
||||
|
||||
return(next_records_datalen & 0x8000);
|
||||
}
|
||||
|
||||
|
||||
bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len)
|
||||
{
|
||||
|
||||
#define MAX_TOPAZ_READER_CMD_LEN 16
|
||||
|
||||
uint32_t last_timestamp = timestamp + *duration;
|
||||
|
||||
if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false;
|
||||
|
||||
memcpy(topaz_reader_command, frame, *data_len);
|
||||
|
||||
while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) {
|
||||
uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos));
|
||||
*tracepos += sizeof(uint32_t);
|
||||
uint16_t next_duration = *((uint16_t *)(trace + *tracepos));
|
||||
*tracepos += sizeof(uint16_t);
|
||||
uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF;
|
||||
*tracepos += sizeof(uint16_t);
|
||||
uint8_t *next_frame = (trace + *tracepos);
|
||||
*tracepos += next_data_len;
|
||||
if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) {
|
||||
memcpy(topaz_reader_command + *data_len, next_frame, next_data_len);
|
||||
*data_len += next_data_len;
|
||||
last_timestamp = next_timestamp + next_duration;
|
||||
} else {
|
||||
// rewind and exit
|
||||
*tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t);
|
||||
break;
|
||||
}
|
||||
uint16_t next_parity_len = (next_data_len-1)/8 + 1;
|
||||
*tracepos += next_parity_len;
|
||||
}
|
||||
|
||||
*duration = last_timestamp - timestamp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes)
|
||||
{
|
||||
bool isResponse;
|
||||
uint16_t duration, data_len, parity_len;
|
||||
|
||||
uint16_t data_len, parity_len;
|
||||
uint32_t duration;
|
||||
uint8_t topaz_reader_command[9];
|
||||
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
|
||||
char explanation[30] = {0};
|
||||
|
||||
|
@ -336,29 +440,31 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
|||
uint8_t *parityBytes = trace + tracepos;
|
||||
tracepos += parity_len;
|
||||
|
||||
if (protocol == TOPAZ && !isResponse) {
|
||||
// topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
|
||||
// merge them:
|
||||
if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) {
|
||||
frame = topaz_reader_command;
|
||||
}
|
||||
}
|
||||
|
||||
//Check the CRC status
|
||||
uint8_t crcStatus = 2;
|
||||
|
||||
if (data_len > 2) {
|
||||
uint8_t b1, b2;
|
||||
if(protocol == ICLASS)
|
||||
{
|
||||
crcStatus = iclass_CRC_check(isResponse, frame, data_len);
|
||||
|
||||
}else if (protocol == ISO_14443B)
|
||||
{
|
||||
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
|
||||
}
|
||||
else if (protocol == ISO_14443A){//Iso 14443a
|
||||
|
||||
ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
|
||||
|
||||
if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
|
||||
if(!(isResponse & (data_len < 6)))
|
||||
{
|
||||
crcStatus = 0;
|
||||
}
|
||||
}
|
||||
switch (protocol) {
|
||||
case ICLASS:
|
||||
crcStatus = iclass_CRC_check(isResponse, frame, data_len);
|
||||
break;
|
||||
case ISO_14443B:
|
||||
case TOPAZ:
|
||||
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
|
||||
break;
|
||||
case ISO_14443A:
|
||||
crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
//0 CRC-command, CRC not ok
|
||||
|
@ -380,19 +486,22 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
|||
uint8_t parityBits = parityBytes[j>>3];
|
||||
if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
|
||||
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
|
||||
|
||||
} else {
|
||||
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]);
|
||||
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
|
||||
}
|
||||
|
||||
}
|
||||
if(crcStatus == 1)
|
||||
{//CRC-command
|
||||
char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1;
|
||||
(*pos1) = '[';
|
||||
char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2;
|
||||
(*pos2) = ']';
|
||||
|
||||
if (markCRCBytes) {
|
||||
if(crcStatus == 0 || crcStatus == 1)
|
||||
{//CRC-command
|
||||
char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4);
|
||||
(*pos1) = '[';
|
||||
char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4);
|
||||
sprintf(pos2, "%c", ']');
|
||||
}
|
||||
}
|
||||
|
||||
if(data_len == 0)
|
||||
{
|
||||
if(data_len == 0){
|
||||
|
@ -407,18 +516,19 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
|||
|
||||
if(!isResponse)
|
||||
{
|
||||
if(protocol == ICLASS)
|
||||
annotateIclass(explanation,sizeof(explanation),frame,data_len);
|
||||
else if (protocol == ISO_14443A)
|
||||
annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
|
||||
else if(protocol == ISO_14443B)
|
||||
annotateIso14443b(explanation,sizeof(explanation),frame,data_len);
|
||||
switch(protocol) {
|
||||
case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break;
|
||||
case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break;
|
||||
case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break;
|
||||
case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
int num_lines = MIN((data_len - 1)/16 + 1, 16);
|
||||
for (int j = 0; j < num_lines ; j++) {
|
||||
if (j == 0) {
|
||||
PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
|
||||
PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s",
|
||||
(timestamp - first_timestamp),
|
||||
(EndOfTransmissionTimestamp - first_timestamp),
|
||||
(isResponse ? "Tag" : "Rdr"),
|
||||
|
@ -426,26 +536,22 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
|||
(j == num_lines-1) ? crc : " ",
|
||||
(j == num_lines-1) ? explanation : "");
|
||||
} else {
|
||||
PrintAndLog(" | | | %-64s| %s| %s",
|
||||
PrintAndLog(" | | |%-64s | %s| %s",
|
||||
line[j],
|
||||
(j == num_lines-1)?crc:" ",
|
||||
(j == num_lines-1) ? crc : " ",
|
||||
(j == num_lines-1) ? explanation : "");
|
||||
}
|
||||
}
|
||||
|
||||
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||
if (is_last_record(tracepos, trace, traceLen)) return traceLen;
|
||||
|
||||
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
|
||||
|
||||
if (showWaitCycles && !isResponse && next_isResponse) {
|
||||
if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
|
||||
uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
|
||||
if (next_timestamp != 0x44444444) {
|
||||
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
|
||||
(EndOfTransmissionTimestamp - first_timestamp),
|
||||
(next_timestamp - first_timestamp),
|
||||
" ",
|
||||
(next_timestamp - EndOfTransmissionTimestamp));
|
||||
}
|
||||
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
|
||||
(EndOfTransmissionTimestamp - first_timestamp),
|
||||
(next_timestamp - first_timestamp),
|
||||
" ",
|
||||
(next_timestamp - EndOfTransmissionTimestamp));
|
||||
}
|
||||
|
||||
return tracepos;
|
||||
|
@ -455,49 +561,52 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
|||
int CmdHFList(const char *Cmd)
|
||||
{
|
||||
bool showWaitCycles = false;
|
||||
bool markCRCBytes = false;
|
||||
char type[40] = {0};
|
||||
int tlen = param_getstr(Cmd,0,type);
|
||||
char param = param_getchar(Cmd, 1);
|
||||
char param1 = param_getchar(Cmd, 1);
|
||||
char param2 = param_getchar(Cmd, 2);
|
||||
bool errors = false;
|
||||
uint8_t protocol = 0;
|
||||
//Validate params
|
||||
if(tlen == 0)
|
||||
{
|
||||
|
||||
if(tlen == 0) {
|
||||
errors = true;
|
||||
}
|
||||
if(param == 'h' || (param !=0 && param != 'f'))
|
||||
{
|
||||
|
||||
if(param1 == 'h'
|
||||
|| (param1 != 0 && param1 != 'f' && param1 != 'c')
|
||||
|| (param2 != 0 && param2 != 'f' && param2 != 'c')) {
|
||||
errors = true;
|
||||
}
|
||||
if(!errors)
|
||||
{
|
||||
if(strcmp(type, "iclass") == 0)
|
||||
{
|
||||
|
||||
if(!errors) {
|
||||
if(strcmp(type, "iclass") == 0) {
|
||||
protocol = ICLASS;
|
||||
}else if(strcmp(type, "14a") == 0)
|
||||
{
|
||||
} else if(strcmp(type, "14a") == 0) {
|
||||
protocol = ISO_14443A;
|
||||
}
|
||||
else if(strcmp(type, "14b") == 0)
|
||||
{
|
||||
} else if(strcmp(type, "14b") == 0) {
|
||||
protocol = ISO_14443B;
|
||||
}else if(strcmp(type,"raw")== 0)
|
||||
{
|
||||
} else if(strcmp(type,"topaz")== 0) {
|
||||
protocol = TOPAZ;
|
||||
} else if(strcmp(type,"raw")== 0) {
|
||||
protocol = -1;//No crc, no annotations
|
||||
}else{
|
||||
} else {
|
||||
errors = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
PrintAndLog("List protocol data in trace buffer.");
|
||||
PrintAndLog("Usage: hf list <protocol> [f]");
|
||||
PrintAndLog("Usage: hf list <protocol> [f][c]");
|
||||
PrintAndLog(" f - show frame delay times as well");
|
||||
PrintAndLog(" c - mark CRC bytes");
|
||||
PrintAndLog("Supported <protocol> values:");
|
||||
PrintAndLog(" raw - just show raw data without annotations");
|
||||
PrintAndLog(" 14a - interpret data as iso14443a communications");
|
||||
PrintAndLog(" 14b - interpret data as iso14443b communications");
|
||||
PrintAndLog(" iclass - interpret data as iclass communications");
|
||||
PrintAndLog(" topaz - interpret data as topaz communications");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("example: hf list 14a f");
|
||||
PrintAndLog("example: hf list iclass");
|
||||
|
@ -505,10 +614,13 @@ int CmdHFList(const char *Cmd)
|
|||
}
|
||||
|
||||
|
||||
if (param == 'f') {
|
||||
if (param1 == 'f' || param2 == 'f') {
|
||||
showWaitCycles = true;
|
||||
}
|
||||
|
||||
if (param1 == 'c' || param2 == 'c') {
|
||||
markCRCBytes = true;
|
||||
}
|
||||
|
||||
uint8_t *trace;
|
||||
uint16_t tracepos = 0;
|
||||
|
@ -537,12 +649,12 @@ int CmdHFList(const char *Cmd)
|
|||
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
|
||||
PrintAndLog("iClass - Timings are not as accurate");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
||||
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
||||
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
||||
PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
||||
|
||||
while(tracepos < traceLen)
|
||||
{
|
||||
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
|
||||
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
|
||||
}
|
||||
|
||||
free(trace);
|
||||
|
@ -557,16 +669,16 @@ int CmdHFSearch(const char *Cmd){
|
|||
PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
ans = HF14BInfo(false);
|
||||
if (ans) {
|
||||
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
ans = HFiClassReader("", false, false);
|
||||
if (ans) {
|
||||
PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
ans = HF14BInfo(false);
|
||||
if (ans) {
|
||||
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
ans = HF15Reader("", false);
|
||||
if (ans) {
|
||||
PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n");
|
||||
|
@ -576,21 +688,31 @@ int CmdHFSearch(const char *Cmd){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CmdHFSnoop(const char *Cmd)
|
||||
{
|
||||
char * pEnd;
|
||||
UsbCommand c = {CMD_HF_SNIFFER, {strtol(Cmd, &pEnd,0),strtol(pEnd, &pEnd,0),0}};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
|
||||
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
|
||||
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
|
||||
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
|
||||
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
|
||||
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
|
||||
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
|
||||
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
|
||||
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
|
||||
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
|
||||
{"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
|
||||
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
|
||||
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
|
||||
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
|
||||
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
|
||||
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
|
||||
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
|
||||
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
|
||||
{"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
|
||||
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
|
||||
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
|
||||
{"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"},
|
||||
{"snoop", CmdHFSnoop, 0, "<samples to skip (10000)> <triggers to skip (1)> Generic HF Snoop"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdHF(const char *Cmd)
|
||||
|
|
|
@ -141,7 +141,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
|
||||
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
|
||||
|
||||
if(select_status == 0) {
|
||||
if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
|
||||
|
@ -352,16 +352,16 @@ int CmdHF14AReader(const char *Cmd)
|
|||
PrintAndLog(" x0 -> <1 kByte");
|
||||
break;
|
||||
case 0x01:
|
||||
PrintAndLog(" x0 -> 1 kByte");
|
||||
PrintAndLog(" x1 -> 1 kByte");
|
||||
break;
|
||||
case 0x02:
|
||||
PrintAndLog(" x0 -> 2 kByte");
|
||||
PrintAndLog(" x2 -> 2 kByte");
|
||||
break;
|
||||
case 0x03:
|
||||
PrintAndLog(" x0 -> 4 kByte");
|
||||
PrintAndLog(" x3 -> 4 kByte");
|
||||
break;
|
||||
case 0x04:
|
||||
PrintAndLog(" x0 -> 8 kByte");
|
||||
PrintAndLog(" x4 -> 8 kByte");
|
||||
break;
|
||||
}
|
||||
switch (card.ats[pos + 3] & 0xf0) {
|
||||
|
@ -565,20 +565,22 @@ int CmdHF14ASnoop(const char *Cmd) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14ACmdRaw(const char *cmd) {
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
|
||||
uint8_t reply=1;
|
||||
uint8_t crc=0;
|
||||
uint8_t power=0;
|
||||
uint8_t active=0;
|
||||
uint8_t active_select=0;
|
||||
uint16_t numbits=0;
|
||||
uint32_t timeout=0;
|
||||
uint8_t bTimeout=0;
|
||||
bool reply=1;
|
||||
bool crc = FALSE;
|
||||
bool power = FALSE;
|
||||
bool active = FALSE;
|
||||
bool active_select = FALSE;
|
||||
uint16_t numbits = 0;
|
||||
bool bTimeout = FALSE;
|
||||
uint32_t timeout = 0;
|
||||
bool topazmode = FALSE;
|
||||
char buf[5]="";
|
||||
int i=0;
|
||||
int i = 0;
|
||||
uint8_t data[USB_CMD_DATA_SIZE];
|
||||
uint16_t datalen=0;
|
||||
uint16_t datalen = 0;
|
||||
uint32_t temp;
|
||||
|
||||
if (strlen(cmd)<2) {
|
||||
|
@ -590,9 +592,11 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
|||
PrintAndLog(" -s active signal field ON with select");
|
||||
PrintAndLog(" -b number of bits to send. Useful for send partial byte");
|
||||
PrintAndLog(" -t timeout in ms");
|
||||
PrintAndLog(" -T use Topaz protocol to send command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// strip
|
||||
while (*cmd==' ' || *cmd=='\t') cmd++;
|
||||
|
||||
|
@ -601,19 +605,19 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
|||
if (cmd[i]=='-') {
|
||||
switch (cmd[i+1]) {
|
||||
case 'r':
|
||||
reply=0;
|
||||
reply = FALSE;
|
||||
break;
|
||||
case 'c':
|
||||
crc=1;
|
||||
crc = TRUE;
|
||||
break;
|
||||
case 'p':
|
||||
power=1;
|
||||
power = TRUE;
|
||||
break;
|
||||
case 'a':
|
||||
active=1;
|
||||
active = TRUE;
|
||||
break;
|
||||
case 's':
|
||||
active_select=1;
|
||||
active_select = TRUE;
|
||||
break;
|
||||
case 'b':
|
||||
sscanf(cmd+i+2,"%d",&temp);
|
||||
|
@ -623,13 +627,16 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
|||
i-=2;
|
||||
break;
|
||||
case 't':
|
||||
bTimeout=1;
|
||||
bTimeout = TRUE;
|
||||
sscanf(cmd+i+2,"%d",&temp);
|
||||
timeout = temp;
|
||||
i+=3;
|
||||
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
|
||||
i-=2;
|
||||
break;
|
||||
case 'T':
|
||||
topazmode = TRUE;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Invalid option");
|
||||
return 0;
|
||||
|
@ -659,10 +666,15 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
|||
PrintAndLog("Invalid char on input");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(crc && datalen>0 && datalen<sizeof(data)-2)
|
||||
{
|
||||
uint8_t first, second;
|
||||
ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
|
||||
if (topazmode) {
|
||||
ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
|
||||
} else {
|
||||
ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
|
||||
}
|
||||
data[datalen++] = first;
|
||||
data[datalen++] = second;
|
||||
}
|
||||
|
@ -675,7 +687,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
|||
}
|
||||
|
||||
if(bTimeout){
|
||||
#define MAX_TIMEOUT 40542464 // (2^32-1) * (8*16) / 13560000Hz * 1000ms/s =
|
||||
#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
|
||||
c.arg[0] |= ISO14A_SET_TIMEOUT;
|
||||
if(timeout > MAX_TIMEOUT) {
|
||||
timeout = MAX_TIMEOUT;
|
||||
|
@ -683,11 +695,16 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
|||
}
|
||||
c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
||||
}
|
||||
|
||||
if(power)
|
||||
c.arg[0] |= ISO14A_NO_DISCONNECT;
|
||||
if(datalen>0)
|
||||
|
||||
if(datalen > 0)
|
||||
c.arg[0] |= ISO14A_RAW;
|
||||
|
||||
if(topazmode)
|
||||
c.arg[0] |= ISO14A_TOPAZMODE;
|
||||
|
||||
// Max buffer is USB_CMD_DATA_SIZE
|
||||
c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
|
||||
memcpy(c.d.asBytes,data,datalen);
|
||||
|
@ -703,6 +720,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void waitCmd(uint8_t iSelect)
|
||||
{
|
||||
uint8_t *recv;
|
||||
|
@ -712,7 +730,7 @@ static void waitCmd(uint8_t iSelect)
|
|||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
recv = resp.d.asBytes;
|
||||
uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0];
|
||||
PrintAndLog("received %i octets",iLen);
|
||||
PrintAndLog("received %i octets", iLen);
|
||||
if(!iLen)
|
||||
return;
|
||||
hexout = (char *)malloc(iLen * 3 + 1);
|
||||
|
|
1534
client/cmdhficlass.c
1534
client/cmdhficlass.c
File diff suppressed because it is too large
Load diff
|
@ -14,11 +14,26 @@
|
|||
|
||||
int CmdHFiClass(const char *Cmd);
|
||||
|
||||
int CmdHFiClassSnoop(const char *Cmd);
|
||||
int CmdHFiClassSim(const char *Cmd);
|
||||
int CmdHFiClassCalcNewKey(const char *Cmd);
|
||||
int CmdHFiClassCloneTag(const char *Cmd);
|
||||
int CmdHFiClassDecrypt(const char *Cmd);
|
||||
int CmdHFiClassEncryptBlk(const char *Cmd);
|
||||
int CmdHFiClassELoad(const char *Cmd);
|
||||
int CmdHFiClassList(const char *Cmd);
|
||||
int HFiClassReader(const char *Cmd, bool loop, bool verbose);
|
||||
int CmdHFiClassReader(const char *Cmd);
|
||||
int CmdHFiClassReader_Dump(const char *Cmd);
|
||||
int CmdHFiClassReader_Replay(const char *Cmd);
|
||||
|
||||
int CmdHFiClassReadKeyFile(const char *filename);
|
||||
int CmdHFiClassReadTagFile(const char *Cmd);
|
||||
int CmdHFiClass_ReadBlock(const char *Cmd);
|
||||
int CmdHFiClass_TestMac(const char *Cmd);
|
||||
int CmdHFiClassManageKeys(const char *Cmd);
|
||||
int CmdHFiClass_loclass(const char *Cmd);
|
||||
int CmdHFiClassSnoop(const char *Cmd);
|
||||
int CmdHFiClassSim(const char *Cmd);
|
||||
int CmdHFiClassWriteKeyFile(const char *Cmd);
|
||||
int CmdHFiClass_WriteBlock(const char *Cmd);
|
||||
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize);
|
||||
void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite);
|
||||
#endif
|
||||
|
|
|
@ -2050,6 +2050,13 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
return 0;
|
||||
}
|
||||
|
||||
//needs nt, ar, at, Data to decrypt
|
||||
int CmdDecryptTraceCmds(const char *Cmd){
|
||||
uint8_t data[50];
|
||||
int len = 0;
|
||||
param_gethex_ex(Cmd,3,data,&len);
|
||||
return tryDecryptWord(param_get32ex(Cmd,0,0,16),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),data,len/2);
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
|
@ -2079,6 +2086,7 @@ static command_t CommandTable[] =
|
|||
{"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},
|
||||
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},
|
||||
{"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},
|
||||
{"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
571
client/cmdhftopaz.c
Normal file
571
client/cmdhftopaz.c
Normal file
|
@ -0,0 +1,571 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2015 Piwi
|
||||
//
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// High frequency Topaz (NFC Type 1) commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "cmdmain.h"
|
||||
#include "cmdparser.h"
|
||||
#include "cmdhftopaz.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "ui.h"
|
||||
#include "mifare.h"
|
||||
#include "proxmark3.h"
|
||||
#include "iso14443crc.h"
|
||||
#include "protocols.h"
|
||||
|
||||
#define TOPAZ_STATIC_MEMORY (0x0f * 8) // 15 blocks with 8 Bytes each
|
||||
|
||||
// a struct to describe a memory area which contains lock bits and the corresponding lockable memory area
|
||||
typedef struct dynamic_lock_area {
|
||||
struct dynamic_lock_area *next;
|
||||
uint16_t byte_offset; // the address of the lock bits
|
||||
uint16_t size_in_bits;
|
||||
uint16_t first_locked_byte; // the address of the lockable area
|
||||
uint16_t bytes_locked_per_bit;
|
||||
} dynamic_lock_area_t;
|
||||
|
||||
|
||||
static struct {
|
||||
uint8_t HR01[2];
|
||||
uint8_t uid[7];
|
||||
uint16_t size;
|
||||
uint8_t data_blocks[TOPAZ_STATIC_MEMORY/8][8]; // this memory is always there
|
||||
uint8_t *dynamic_memory; // this memory can be there
|
||||
dynamic_lock_area_t *dynamic_lock_areas; // lock area descriptors
|
||||
} topaz_tag;
|
||||
|
||||
|
||||
static void topaz_switch_on_field(void)
|
||||
{
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, 0, 0}};
|
||||
SendCommand(&c);
|
||||
}
|
||||
|
||||
|
||||
static void topaz_switch_off_field(void)
|
||||
{
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
|
||||
SendCommand(&c);
|
||||
}
|
||||
|
||||
|
||||
// send a raw topaz command, returns the length of the response (0 in case of error)
|
||||
static int topaz_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response)
|
||||
{
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, len, 0}};
|
||||
memcpy(c.d.asBytes, cmd, len);
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
WaitForResponse(CMD_ACK, &resp);
|
||||
|
||||
if (resp.arg[0] > 0) {
|
||||
memcpy(response, resp.d.asBytes, resp.arg[0]);
|
||||
}
|
||||
|
||||
return resp.arg[0];
|
||||
}
|
||||
|
||||
|
||||
// calculate CRC bytes and send topaz command, returns the length of the response (0 in case of error)
|
||||
static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response)
|
||||
{
|
||||
if (len > 1) {
|
||||
uint8_t first, second;
|
||||
ComputeCrc14443(CRC_14443_B, cmd, len-2, &first, &second);
|
||||
cmd[len-2] = first;
|
||||
cmd[len-1] = second;
|
||||
}
|
||||
|
||||
return topaz_send_cmd_raw(cmd, len, response);
|
||||
}
|
||||
|
||||
|
||||
// select a topaz tag. Send WUPA and RID.
|
||||
static int topaz_select(uint8_t *atqa, uint8_t *rid_response)
|
||||
{
|
||||
// ToDo: implement anticollision
|
||||
|
||||
uint8_t wupa_cmd[] = {TOPAZ_WUPA};
|
||||
uint8_t rid_cmd[] = {TOPAZ_RID, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
topaz_switch_on_field();
|
||||
|
||||
if (!topaz_send_cmd(wupa_cmd, sizeof(wupa_cmd), atqa)) {
|
||||
topaz_switch_off_field();
|
||||
return -1; // WUPA failed
|
||||
}
|
||||
|
||||
if (!topaz_send_cmd(rid_cmd, sizeof(rid_cmd), rid_response)) {
|
||||
topaz_switch_off_field();
|
||||
return -2; // RID failed
|
||||
}
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
|
||||
// read all of the static memory of a selected Topaz tag.
|
||||
static int topaz_rall(uint8_t *uid, uint8_t *response)
|
||||
{
|
||||
uint8_t rall_cmd[] = {TOPAZ_RALL, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
memcpy(&rall_cmd[3], uid, 4);
|
||||
if (!topaz_send_cmd(rall_cmd, sizeof(rall_cmd), response)) {
|
||||
topaz_switch_off_field();
|
||||
return -1; // RALL failed
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read a block (8 Bytes) of a selected Topaz tag.
|
||||
static int topaz_read_block(uint8_t *uid, uint8_t blockno, uint8_t *block_data)
|
||||
{
|
||||
uint8_t read8_cmd[] = {TOPAZ_READ8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t read8_response[11];
|
||||
|
||||
read8_cmd[1] = blockno;
|
||||
memcpy(&read8_cmd[10], uid, 4);
|
||||
if (!topaz_send_cmd(read8_cmd, sizeof(read8_cmd), read8_response)) {
|
||||
topaz_switch_off_field();
|
||||
return -1; // READ8 failed
|
||||
}
|
||||
|
||||
memcpy(block_data, &read8_response[1], 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read a segment (16 blocks = 128 Bytes) of a selected Topaz tag. Works only for tags with dynamic memory.
|
||||
static int topaz_read_segment(uint8_t *uid, uint8_t segno, uint8_t *segment_data)
|
||||
{
|
||||
uint8_t rseg_cmd[] = {TOPAZ_RSEG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t rseg_response[131];
|
||||
|
||||
rseg_cmd[1] = segno << 4;
|
||||
memcpy(&rseg_cmd[10], uid, 4);
|
||||
if (!topaz_send_cmd(rseg_cmd, sizeof(rseg_cmd), rseg_response)) {
|
||||
topaz_switch_off_field();
|
||||
return -1; // RSEG failed
|
||||
}
|
||||
|
||||
memcpy(segment_data, &rseg_response[1], 128);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// search for the lock area descriptor for the lockable area including byteno
|
||||
static dynamic_lock_area_t *get_dynamic_lock_area(uint16_t byteno)
|
||||
{
|
||||
dynamic_lock_area_t *lock_area;
|
||||
|
||||
lock_area = topaz_tag.dynamic_lock_areas;
|
||||
|
||||
while (lock_area != NULL) {
|
||||
if (byteno < lock_area->first_locked_byte) {
|
||||
lock_area = lock_area->next;
|
||||
} else {
|
||||
return lock_area;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// check if a memory byte is locked.
|
||||
static bool topaz_byte_is_locked(uint16_t byteno)
|
||||
{
|
||||
uint8_t *lockbits;
|
||||
uint16_t locked_bytes_per_bit;
|
||||
dynamic_lock_area_t *lock_area;
|
||||
|
||||
if (byteno < TOPAZ_STATIC_MEMORY) {
|
||||
lockbits = &topaz_tag.data_blocks[0x0e][0];
|
||||
locked_bytes_per_bit = 8;
|
||||
} else {
|
||||
lock_area = get_dynamic_lock_area(byteno);
|
||||
if (lock_area == NULL) {
|
||||
return false;
|
||||
} else {
|
||||
lockbits = &topaz_tag.dynamic_memory[lock_area->byte_offset - TOPAZ_STATIC_MEMORY];
|
||||
locked_bytes_per_bit = lock_area->bytes_locked_per_bit;
|
||||
byteno = byteno - lock_area->first_locked_byte;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t blockno = byteno / locked_bytes_per_bit;
|
||||
if(lockbits[blockno/8] & (0x01 << (blockno % 8))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read and print the Capability Container
|
||||
static int topaz_print_CC(uint8_t *data)
|
||||
{
|
||||
if(data[0] != 0xe1) {
|
||||
topaz_tag.size = TOPAZ_STATIC_MEMORY;
|
||||
return -1; // no NDEF message
|
||||
}
|
||||
|
||||
PrintAndLog("Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
|
||||
PrintAndLog(" %02x: NDEF Magic Number", data[0]);
|
||||
PrintAndLog(" %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f);
|
||||
uint16_t memsize = (data[2] + 1) * 8;
|
||||
topaz_tag.size = memsize;
|
||||
topaz_tag.dynamic_memory = malloc(memsize - TOPAZ_STATIC_MEMORY);
|
||||
PrintAndLog(" %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize);
|
||||
PrintAndLog(" %02x: %s / %s", data[3],
|
||||
(data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security",
|
||||
(data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// return type, length and value of a TLV, starting at memory position *TLV_ptr
|
||||
static void get_TLV(uint8_t **TLV_ptr, uint8_t *TLV_type, uint16_t *TLV_length, uint8_t **TLV_value)
|
||||
{
|
||||
*TLV_length = 0;
|
||||
*TLV_value = NULL;
|
||||
|
||||
*TLV_type = **TLV_ptr;
|
||||
*TLV_ptr += 1;
|
||||
switch (*TLV_type) {
|
||||
case 0x00: // NULL TLV.
|
||||
case 0xFE: // Terminator TLV.
|
||||
break;
|
||||
case 0x01: // Lock Control TLV
|
||||
case 0x02: // Reserved Memory TLV
|
||||
case 0x03: // NDEF message TLV
|
||||
case 0xFD: // proprietary TLV
|
||||
*TLV_length = **TLV_ptr;
|
||||
*TLV_ptr += 1;
|
||||
if (*TLV_length == 0xff) {
|
||||
*TLV_length = **TLV_ptr << 8;
|
||||
*TLV_ptr += 1;
|
||||
*TLV_length |= **TLV_ptr;
|
||||
*TLV_ptr += 1;
|
||||
}
|
||||
*TLV_value = *TLV_ptr;
|
||||
*TLV_ptr += *TLV_length;
|
||||
break;
|
||||
default: // RFU
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// lock area TLVs contain no information on the start of the respective lockable area. Lockable areas
|
||||
// do not include the lock bits and reserved memory. We therefore need to adjust the start of the
|
||||
// respective lockable areas accordingly
|
||||
static void adjust_lock_areas(uint16_t block_start, uint16_t block_size)
|
||||
{
|
||||
dynamic_lock_area_t *lock_area = topaz_tag.dynamic_lock_areas;
|
||||
while (lock_area != NULL) {
|
||||
if (lock_area->first_locked_byte <= block_start) {
|
||||
lock_area->first_locked_byte += block_size;
|
||||
}
|
||||
lock_area = lock_area->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read and print the lock area and reserved memory TLVs
|
||||
static void topaz_print_control_TLVs(uint8_t *memory)
|
||||
{
|
||||
uint8_t *TLV_ptr = memory;
|
||||
uint8_t TLV_type = 0;
|
||||
uint16_t TLV_length;
|
||||
uint8_t *TLV_value;
|
||||
bool lock_TLV_present = false;
|
||||
bool reserved_memory_control_TLV_present = false;
|
||||
uint16_t next_lockable_byte = 0x0f * 8; // first byte after static memory area
|
||||
|
||||
while(*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) {
|
||||
// all Lock Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV)
|
||||
get_TLV(&TLV_ptr, &TLV_type, &TLV_length, &TLV_value);
|
||||
if (TLV_type == 0x01) { // a Lock Control TLV
|
||||
uint8_t pages_addr = TLV_value[0] >> 4;
|
||||
uint8_t byte_offset = TLV_value[0] & 0x0f;
|
||||
uint16_t size_in_bits = TLV_value[1] ? TLV_value[1] : 256;
|
||||
uint16_t size_in_bytes = (size_in_bits + 7)/8;
|
||||
uint16_t bytes_per_page = 1 << (TLV_value[2] & 0x0f);
|
||||
uint16_t bytes_locked_per_bit = 1 << (TLV_value[2] >> 4);
|
||||
uint16_t area_start = pages_addr * bytes_per_page + byte_offset;
|
||||
PrintAndLog("Lock Area of %d bits at byte offset 0x%04x. Each Lock Bit locks %d bytes.",
|
||||
size_in_bits,
|
||||
area_start,
|
||||
bytes_locked_per_bit);
|
||||
lock_TLV_present = true;
|
||||
dynamic_lock_area_t *old = topaz_tag.dynamic_lock_areas;
|
||||
dynamic_lock_area_t *new = topaz_tag.dynamic_lock_areas;
|
||||
if (old == NULL) {
|
||||
new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t));
|
||||
} else {
|
||||
while(old->next != NULL) {
|
||||
old = old->next;
|
||||
}
|
||||
new = old->next = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t));
|
||||
}
|
||||
new->next = NULL;
|
||||
if (area_start <= next_lockable_byte) {
|
||||
// lock areas are not lockable
|
||||
next_lockable_byte += size_in_bytes;
|
||||
}
|
||||
new->first_locked_byte = next_lockable_byte;
|
||||
new->byte_offset = area_start;
|
||||
new->size_in_bits = size_in_bits;
|
||||
new->bytes_locked_per_bit = bytes_locked_per_bit;
|
||||
next_lockable_byte += size_in_bits * bytes_locked_per_bit;
|
||||
}
|
||||
if (TLV_type == 0x02) { // a Reserved Memory Control TLV
|
||||
uint8_t pages_addr = TLV_value[0] >> 4;
|
||||
uint8_t byte_offset = TLV_value[0] & 0x0f;
|
||||
uint8_t size_in_bytes = TLV_value[1] ? TLV_value[1] : 256;
|
||||
uint8_t bytes_per_page = 1 << (TLV_value[2] & 0x0f);
|
||||
uint16_t area_start = pages_addr * bytes_per_page + byte_offset;
|
||||
PrintAndLog("Reserved Memory of %d bytes at byte offset 0x%02x.",
|
||||
size_in_bytes,
|
||||
area_start);
|
||||
reserved_memory_control_TLV_present = true;
|
||||
adjust_lock_areas(area_start, size_in_bytes); // reserved memory areas are not lockable
|
||||
if (area_start <= next_lockable_byte) {
|
||||
next_lockable_byte += size_in_bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!lock_TLV_present) {
|
||||
PrintAndLog("(No Lock Control TLV present)");
|
||||
}
|
||||
|
||||
if (!reserved_memory_control_TLV_present) {
|
||||
PrintAndLog("(No Reserved Memory Control TLV present)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read all of the dynamic memory
|
||||
static int topaz_read_dynamic_data(void)
|
||||
{
|
||||
// first read the remaining block of segment 0
|
||||
if(topaz_read_block(topaz_tag.uid, 0x0f, &topaz_tag.dynamic_memory[0]) == -1) {
|
||||
PrintAndLog("Error while reading dynamic memory block %02x. Aborting...", 0x0f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// read the remaining segments
|
||||
uint8_t max_segment = topaz_tag.size / 128 - 1;
|
||||
for(uint8_t segment = 1; segment <= max_segment; segment++) {
|
||||
if(topaz_read_segment(topaz_tag.uid, segment, &topaz_tag.dynamic_memory[(segment-1)*128+8]) == -1) {
|
||||
PrintAndLog("Error while reading dynamic memory block %02x. Aborting...", 0x0f);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read and print the dynamic memory
|
||||
static void topaz_print_dynamic_data(void)
|
||||
{
|
||||
if (topaz_tag.size > TOPAZ_STATIC_MEMORY) {
|
||||
PrintAndLog("Dynamic Data blocks:");
|
||||
if (topaz_read_dynamic_data() == 0) {
|
||||
PrintAndLog("block# | offset | Data | Locked(y/n)");
|
||||
char line[80];
|
||||
for (uint16_t blockno = 0x0f; blockno < topaz_tag.size/8; blockno++) {
|
||||
uint8_t *block_data = &topaz_tag.dynamic_memory[(blockno-0x0f)*8];
|
||||
char lockbits[9];
|
||||
for (uint16_t j = 0; j < 8; j++) {
|
||||
sprintf(&line[3*j], "%02x ", block_data[j]);
|
||||
lockbits[j] = topaz_byte_is_locked(blockno*8+j) ? 'y' : 'n';
|
||||
}
|
||||
lockbits[8] = '\0';
|
||||
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", blockno, blockno*8, line, lockbits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void topaz_print_lifecycle_state(uint8_t *data)
|
||||
{
|
||||
// to be done
|
||||
}
|
||||
|
||||
|
||||
static void topaz_print_NDEF(uint8_t *data)
|
||||
{
|
||||
// to be done.
|
||||
}
|
||||
|
||||
|
||||
// read a Topaz tag and print some usefull information
|
||||
int CmdHFTopazReader(const char *Cmd)
|
||||
{
|
||||
int status;
|
||||
uint8_t atqa[2];
|
||||
uint8_t rid_response[8];
|
||||
uint8_t *uid_echo = &rid_response[2];
|
||||
uint8_t rall_response[124];
|
||||
|
||||
status = topaz_select(atqa, rid_response);
|
||||
|
||||
if (status == -1) {
|
||||
PrintAndLog("Error: couldn't receive ATQA");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PrintAndLog("ATQA : %02x %02x", atqa[1], atqa[0]);
|
||||
if (atqa[1] != 0x0c && atqa[0] != 0x00) {
|
||||
PrintAndLog("Tag doesn't support the Topaz protocol.");
|
||||
topaz_switch_off_field();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status == -2) {
|
||||
PrintAndLog("Error: tag didn't answer to RID");
|
||||
topaz_switch_off_field();
|
||||
return -1;
|
||||
}
|
||||
|
||||
topaz_tag.HR01[0] = rid_response[0];
|
||||
topaz_tag.HR01[1] = rid_response[1];
|
||||
|
||||
// ToDo: CRC check
|
||||
PrintAndLog("HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0],
|
||||
(rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
|
||||
(rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
|
||||
(rid_response[0] & 0x0F) == 0x10 ? "static" : "dynamic");
|
||||
PrintAndLog("HR1 : %02x", rid_response[1]);
|
||||
|
||||
status = topaz_rall(uid_echo, rall_response);
|
||||
|
||||
if(status == -1) {
|
||||
PrintAndLog("Error: tag didn't answer to RALL");
|
||||
topaz_switch_off_field();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(topaz_tag.uid, rall_response+2, 7);
|
||||
PrintAndLog("UID : %02x %02x %02x %02x %02x %02x %02x",
|
||||
topaz_tag.uid[6],
|
||||
topaz_tag.uid[5],
|
||||
topaz_tag.uid[4],
|
||||
topaz_tag.uid[3],
|
||||
topaz_tag.uid[2],
|
||||
topaz_tag.uid[1],
|
||||
topaz_tag.uid[0]);
|
||||
PrintAndLog(" UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s",
|
||||
topaz_tag.uid[6],
|
||||
getTagInfo(topaz_tag.uid[6]));
|
||||
|
||||
memcpy(topaz_tag.data_blocks, rall_response+2, 0x0f*8);
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Static Data blocks 00 to 0c:");
|
||||
PrintAndLog("block# | offset | Data | Locked(y/n)");
|
||||
char line[80];
|
||||
for (uint16_t i = 0; i <= 0x0c; i++) {
|
||||
char lockbits[9];
|
||||
for (uint16_t j = 0; j < 8; j++) {
|
||||
sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[i][j] /*rall_response[2 + 8*i + j]*/);
|
||||
lockbits[j] = topaz_byte_is_locked(i*8+j) ? 'y' : 'n';
|
||||
}
|
||||
lockbits[8] = '\0';
|
||||
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", i, i*8, line, lockbits);
|
||||
}
|
||||
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Static Reserved block 0d:");
|
||||
for (uint16_t j = 0; j < 8; j++) {
|
||||
sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0d][j]);
|
||||
}
|
||||
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", 0x0d, 0x0d*8, line, "n/a");
|
||||
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Static Lockbits and OTP Bytes:");
|
||||
for (uint16_t j = 0; j < 8; j++) {
|
||||
sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0e][j]);
|
||||
}
|
||||
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", 0x0e, 0x0e*8, line, "n/a");
|
||||
|
||||
PrintAndLog("");
|
||||
|
||||
status = topaz_print_CC(&topaz_tag.data_blocks[1][0]);
|
||||
|
||||
if (status == -1) {
|
||||
PrintAndLog("No NDEF message data present");
|
||||
topaz_switch_off_field();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintAndLog("");
|
||||
topaz_print_control_TLVs(&topaz_tag.data_blocks[1][4]);
|
||||
|
||||
PrintAndLog("");
|
||||
topaz_print_dynamic_data();
|
||||
|
||||
topaz_print_lifecycle_state(&topaz_tag.data_blocks[1][0]);
|
||||
|
||||
topaz_print_NDEF(&topaz_tag.data_blocks[1][0]);
|
||||
|
||||
topaz_switch_off_field();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHFTopazCmdRaw(const char *Cmd)
|
||||
{
|
||||
PrintAndLog("not yet implemented. Use hf 14 raw with option -T.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"reader", CmdHFTopazReader, 0, "Act like a Topaz reader"},
|
||||
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop a Topaz reader-tag communication"},
|
||||
{"raw", CmdHFTopazCmdRaw, 0, "Send raw hex data to tag"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
int CmdHFTopaz(const char *Cmd) {
|
||||
// flush
|
||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||
|
||||
// parse
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int CmdHelp(const char *Cmd)
|
||||
{
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
16
client/cmdhftopaz.h
Normal file
16
client/cmdhftopaz.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2015 Piwi
|
||||
//
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// High frequency Topaz (NFC Type 1) commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef CMDHFTOPAZ_H__
|
||||
#define CMDHFTOPAZ_H__
|
||||
|
||||
int CmdHFTopaz(const char *Cmd);
|
||||
|
||||
#endif
|
108
client/cmdlf.c
108
client/cmdlf.c
|
@ -33,17 +33,82 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
||||
|
||||
int usage_lf_cmdread()
|
||||
{
|
||||
PrintAndLog("Usage: lf cmdread d <delay period> z <zero period> o <one period> c <cmdbytes> [H] ");
|
||||
PrintAndLog("Options: ");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog(" L Low frequency (125 KHz)");
|
||||
PrintAndLog(" H High frequency (134 KHz)");
|
||||
PrintAndLog(" d <delay> delay OFF period");
|
||||
PrintAndLog(" z <zero> time period ZERO");
|
||||
PrintAndLog(" o <one> time period ONE");
|
||||
PrintAndLog(" c <cmd> Command bytes");
|
||||
PrintAndLog(" ************* All periods in microseconds");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf cmdread d 80 z 100 o 200 c 11000");
|
||||
PrintAndLog(" lf cmdread d 80 z 100 o 100 c 11000 H");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send a command before reading */
|
||||
int CmdLFCommandRead(const char *Cmd)
|
||||
{
|
||||
static char dummy[3];
|
||||
|
||||
dummy[0]= ' ';
|
||||
|
||||
static char dummy[3] = {0x20,0x00,0x00};
|
||||
UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
||||
sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
|
||||
// in case they specified 'h'
|
||||
bool errors = FALSE;
|
||||
//uint8_t divisor = 95; //125khz
|
||||
uint8_t cmdp = 0;
|
||||
int strLength = 0;
|
||||
while(param_getchar(Cmd, cmdp) != 0x00)
|
||||
{
|
||||
switch(param_getchar(Cmd, cmdp))
|
||||
{
|
||||
case 'h':
|
||||
return usage_lf_cmdread();
|
||||
case 'H':
|
||||
//divisor = 88;
|
||||
dummy[1]='h';
|
||||
cmdp++;
|
||||
break;
|
||||
case 'L':
|
||||
cmdp++;
|
||||
break;
|
||||
case 'c':
|
||||
strLength = param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes);
|
||||
cmdp+=2;
|
||||
break;
|
||||
case 'd':
|
||||
c.arg[0] = param_get32ex(Cmd, cmdp+1, 0, 10);
|
||||
cmdp+=2;
|
||||
break;
|
||||
case 'z':
|
||||
c.arg[1] = param_get32ex(Cmd, cmdp+1, 0, 10);
|
||||
cmdp+=2;
|
||||
break;
|
||||
case 'o':
|
||||
c.arg[2] = param_get32ex(Cmd, cmdp+1, 0, 10);
|
||||
cmdp+=2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = 1;
|
||||
break;
|
||||
}
|
||||
if(errors) break;
|
||||
}
|
||||
// No args
|
||||
if(cmdp == 0) errors = 1;
|
||||
|
||||
//Validations
|
||||
if(errors) return usage_lf_cmdread();
|
||||
|
||||
// in case they specified 'H'
|
||||
strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -493,7 +558,12 @@ int CmdLFRead(const char *Cmd)
|
|||
//And ship it to device
|
||||
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}};
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
//WaitForResponse(CMD_ACK,NULL);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
|
||||
PrintAndLog("command execution time out");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1085,6 +1155,12 @@ int CmdLFfind(const char *Cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
ans=CmdVikingDemod("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid Viking ID Found!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ans=CmdPSKNexWatch("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid NexWatch ID Found!");
|
||||
|
@ -1126,28 +1202,28 @@ int CmdLFfind(const char *Cmd)
|
|||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
|
||||
{"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"},
|
||||
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
|
||||
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
||||
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
|
||||
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
||||
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
|
||||
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
|
||||
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
|
||||
{"cmdread", CmdLFCommandRead, 0, "<d period> <z period> <o period> <c command> ['H'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'H' for 134)"},
|
||||
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
|
||||
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
|
||||
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
||||
{"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"},
|
||||
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
||||
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
||||
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
|
||||
{"read", CmdLFRead, 0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
|
||||
{"search", CmdLFfind, 1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
|
||||
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
|
||||
{"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
|
||||
{"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [biphase/manchester/raw <'b'|'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
|
||||
{"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
|
||||
{"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
|
||||
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
|
||||
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
|
||||
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
|
||||
{"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}
|
||||
};
|
||||
|
||||
|
|
|
@ -73,22 +73,23 @@ int CmdEM410xSim(const char *Cmd)
|
|||
uint8_t uid[5] = {0x00};
|
||||
|
||||
if (cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: lf em4x 410xsim <UID>");
|
||||
PrintAndLog("Usage: lf em4x em410xsim <UID> <clock>");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" sample: lf em4x 410xsim 0F0368568B");
|
||||
PrintAndLog(" sample: lf em4x em410xsim 0F0368568B");
|
||||
return 0;
|
||||
}
|
||||
/* clock is 64 in EM410x tags */
|
||||
uint8_t clock = 64;
|
||||
|
||||
if (param_gethex(Cmd, 0, uid, 10)) {
|
||||
PrintAndLog("UID must include 10 HEX symbols");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]);
|
||||
param_getdec(Cmd,1, &clock);
|
||||
|
||||
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock);
|
||||
PrintAndLog("Press pm3-button to about simulation");
|
||||
|
||||
/* clock is 64 in EM410x tags */
|
||||
int clock = 64;
|
||||
|
||||
/* clear our graph */
|
||||
ClearGraph(0);
|
||||
|
@ -197,21 +198,13 @@ int CmdEM410xWrite(const char *Cmd)
|
|||
}
|
||||
|
||||
// Check Clock
|
||||
if (card == 1)
|
||||
{
|
||||
// Default: 64
|
||||
if (clock == 0)
|
||||
clock = 64;
|
||||
// Default: 64
|
||||
if (clock == 0)
|
||||
clock = 64;
|
||||
|
||||
// Allowed clock rates: 16, 32 and 64
|
||||
if ((clock != 16) && (clock != 32) && (clock != 64)) {
|
||||
PrintAndLog("Error! Clock rate %d not valid. Supported clock rates are 16, 32 and 64.\n", clock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (clock != 0)
|
||||
{
|
||||
PrintAndLog("Error! Clock rate is only supported on T55x7 tags.\n");
|
||||
// Allowed clock rates: 16, 32, 40 and 64
|
||||
if ((clock != 16) && (clock != 32) && (clock != 64) && (clock != 40)) {
|
||||
PrintAndLog("Error! Clock rate %d not valid. Supported clock rates are 16, 32, 40 and 64.\n", clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -221,11 +214,11 @@ int CmdEM410xWrite(const char *Cmd)
|
|||
// provide for backwards-compatibility for older firmware, and to avoid
|
||||
// having to add another argument to CMD_EM410X_WRITE_TAG, we just store
|
||||
// the clock rate in bits 8-15 of the card value
|
||||
card = (card & 0xFF) | (((uint64_t)clock << 8) & 0xFF00);
|
||||
}
|
||||
else if (card == 0)
|
||||
card = (card & 0xFF) | ((clock << 8) & 0xFF00);
|
||||
} else if (card == 0) {
|
||||
PrintAndLog("Writing %s tag with UID 0x%010" PRIx64, "T5555", id, clock);
|
||||
else {
|
||||
card = (card & 0xFF) | ((clock << 8) & 0xFF00);
|
||||
} else {
|
||||
PrintAndLog("Error! Bad card type selected.\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -608,7 +601,7 @@ static command_t CommandTable[] =
|
|||
{"help", CmdHelp, 1, "This help"},
|
||||
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
|
||||
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
|
||||
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||
{"em410xsim", CmdEM410xSim, 0, "<UID> [clock rate] -- Simulate EM410x tag"},
|
||||
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||
{"em410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Low frequency PCF7931 commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "proxmark3.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "graph.h"
|
||||
#include "cmdparser.h"
|
||||
#include "cmddata.h"
|
||||
|
@ -22,115 +22,158 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
struct pcf7931_config configPcf = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},17500,{0,0}};
|
||||
#define PCF7931_DEFAULT_INITDELAY 17500
|
||||
#define PCF7931_DEFAULT_OFFSET_WIDTH 0
|
||||
#define PCF7931_DEFAULT_OFFSET_POSITION 0
|
||||
|
||||
int CmdLFPCF7931Read(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_PCF7931_READ};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
return 0;
|
||||
// Default values - Configuration
|
||||
struct pcf7931_config configPcf = {
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
|
||||
PCF7931_DEFAULT_INITDELAY,
|
||||
PCF7931_DEFAULT_OFFSET_WIDTH,
|
||||
PCF7931_DEFAULT_OFFSET_POSITION
|
||||
};
|
||||
|
||||
// Resets the configuration settings to default values.
|
||||
int pcf7931_resetConfig(){
|
||||
memset(configPcf.Pwd, 0xFF, sizeof(configPcf.Pwd) );
|
||||
configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY;
|
||||
configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH;
|
||||
configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFPCF7931Config(const char *Cmd)
|
||||
{
|
||||
int res = 0;
|
||||
res = sscanf(Cmd, "%02x %02x %02x %02x %02x %02x %02x %d %d %d", &configPcf.password[0], &configPcf.password[1], &configPcf.password[2], &configPcf.password[3], &configPcf.password[4], &configPcf.password[5], &configPcf.password[6], &configPcf.init_delay, &configPcf.offset[0], &configPcf.offset[1]);
|
||||
|
||||
if (res >= 7 || res < 1){
|
||||
if(res == 7) configPcf.init_delay = 17500; //default value
|
||||
|
||||
if(res<=8){
|
||||
configPcf.offset[0] = 0; //default value
|
||||
configPcf.offset[1] = 0; //default value
|
||||
}
|
||||
|
||||
if(res < 1){
|
||||
PrintAndLog("Usage: <password byte 1 (in hex, lsb first)> <password byte 2 (in hex, lsb first)> [...] <password byte 7 (in hex, lsb first)> <tag initialization delay (in us)> <optional : offset on the low pulses width (in us)> <optional : offset on the low pulses position (in us)>");
|
||||
PrintAndLog("The time offsets could be usefull to correct slew rate generated by the antenna.");
|
||||
}
|
||||
|
||||
PrintAndLog("Current configuration :");
|
||||
PrintAndLog("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", configPcf.password[0], configPcf.password[1], configPcf.password[2], configPcf.password[3], configPcf.password[4], configPcf.password[5], configPcf.password[6]);
|
||||
PrintAndLog("Tag initialization delay : %d us", configPcf.init_delay);
|
||||
PrintAndLog("Offsets : %d us on the low pulses width, %d us on the low pulses positions", configPcf.offset[0], configPcf.offset[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//default values
|
||||
configPcf.password[0] = 0xFF;
|
||||
configPcf.password[1] = 0xFF;
|
||||
configPcf.password[2] = 0xFF;
|
||||
configPcf.password[3] = 0xFF;
|
||||
configPcf.password[4] = 0xFF;
|
||||
configPcf.password[5] = 0xFF;
|
||||
configPcf.password[6] = 0xFF;
|
||||
|
||||
configPcf.init_delay = 17500;
|
||||
configPcf.offset[0] = 0;
|
||||
configPcf.offset[1] = 0;
|
||||
|
||||
PrintAndLog("Incorrect format");
|
||||
PrintAndLog("Examples of right usage : lf pcf7931 config 11 22 33 44 55 66 77 20000");
|
||||
PrintAndLog(" lf pcf7931 config FF FF FF FF FF FF FF 17500 -10 30");
|
||||
return 0;
|
||||
int pcf7931_printConfig(){
|
||||
PrintAndLog("Password (LSB first on bytes) : %s", sprint_hex( configPcf.Pwd, sizeof(configPcf.Pwd)));
|
||||
PrintAndLog("Tag initialization delay : %d us", configPcf.InitDelay);
|
||||
PrintAndLog("Offset low pulses width : %d us", configPcf.OffsetWidth);
|
||||
PrintAndLog("Offset low pulses position : %d us", configPcf.OffsetPosition);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CmdLFPCF7931Write(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_PCF7931_WRITE};
|
||||
|
||||
int res = 0;
|
||||
res = sscanf(Cmd, "%x %x %x", &c.arg[0], &c.arg[1], &c.arg[2]);
|
||||
|
||||
if(res < 1) {
|
||||
PrintAndLog("Please specify the block address in hex");
|
||||
return 0;
|
||||
}
|
||||
if (res == 1){
|
||||
PrintAndLog("Please specify the byte address in hex");
|
||||
return 0;
|
||||
}
|
||||
if(res == 2) {
|
||||
PrintAndLog("Please specify the data in hex (1 byte)");
|
||||
return 0;
|
||||
}
|
||||
if(res == 3) {
|
||||
uint8_t n=0;
|
||||
for(n=0;n<7;n++) c.d.asDwords[n] = configPcf.password[n];
|
||||
c.d.asDwords[7] = (configPcf.offset[0]+128);
|
||||
c.d.asDwords[8] = (configPcf.offset[1]+128);
|
||||
c.d.asDwords[9] = configPcf.init_delay;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintAndLog("INCORRECT FORMAT");
|
||||
return 0;
|
||||
int usage_pcf7931_read(){
|
||||
PrintAndLog("Usage: lf pcf7931 read [h] ");
|
||||
PrintAndLog("This command tries to read a PCF7931 tag.");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf pcf7931 read");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usage_pcf7931_write(){
|
||||
PrintAndLog("Usage: lf pcf7931 write [h] <block address> <byte address> <data>");
|
||||
PrintAndLog("This command tries to write a PCF7931 tag.");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog(" blockaddress Block to save [0-7]");
|
||||
PrintAndLog(" byteaddress Index of byte inside block to write [0-15]");
|
||||
PrintAndLog(" data one byte of data (hex)");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf pcf7931 write 2 1 FF");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usage_pcf7931_config(){
|
||||
PrintAndLog("Usage: lf pcf7931 config [h] [r] <pwd> <delay> <offset width> <offset position>");
|
||||
PrintAndLog("This command tries to set the configuration used with PCF7931 commands");
|
||||
PrintAndLog("The time offsets could be useful to correct slew rate generated by the antenna");
|
||||
PrintAndLog("Caling without some parameter will print the current configuration.");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog(" r Reset configuration to default values");
|
||||
PrintAndLog(" pwd Password, hex, 7bytes, LSB-order");
|
||||
PrintAndLog(" delay Tag initialization delay (in us) decimal");
|
||||
PrintAndLog(" offset Low pulses width (in us) decimal");
|
||||
PrintAndLog(" offset Low pulses position (in us) decimal");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf pcf7931 config");
|
||||
PrintAndLog(" lf pcf7931 config r");
|
||||
PrintAndLog(" lf pcf7931 config 11223344556677 20000");
|
||||
PrintAndLog(" lf pcf7931 config 11223344556677 17500 -10 30");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFPCF7931Read(const char *Cmd){
|
||||
|
||||
uint8_t ctmp = param_getchar(Cmd, 0);
|
||||
if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_read();
|
||||
|
||||
UsbCommand resp;
|
||||
UsbCommand c = {CMD_PCF7931_READ, {0, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
|
||||
PrintAndLog("command execution time out");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFPCF7931Config(const char *Cmd){
|
||||
|
||||
uint8_t ctmp = param_getchar(Cmd, 0);
|
||||
if ( ctmp == 0) return pcf7931_printConfig();
|
||||
if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_config();
|
||||
if ( ctmp == 'R' || ctmp == 'r' ) return pcf7931_resetConfig();
|
||||
|
||||
if ( param_gethex(Cmd, 0, configPcf.Pwd, 14) ) return usage_pcf7931_config();
|
||||
|
||||
configPcf.InitDelay = (param_get32ex(Cmd,1,0,10) & 0xFFFF);
|
||||
configPcf.OffsetWidth = (int)(param_get32ex(Cmd,2,0,10) & 0xFFFF);
|
||||
configPcf.OffsetPosition = (int)(param_get32ex(Cmd,3,0,10) & 0xFFFF);
|
||||
|
||||
pcf7931_printConfig();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFPCF7931Write(const char *Cmd){
|
||||
|
||||
uint8_t ctmp = param_getchar(Cmd, 0);
|
||||
if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_pcf7931_write();
|
||||
|
||||
uint8_t block = 0, bytepos = 0, data = 0;
|
||||
|
||||
if ( param_getdec(Cmd, 0, &block) ) return usage_pcf7931_write();
|
||||
if ( param_getdec(Cmd, 1, &bytepos) ) return usage_pcf7931_write();
|
||||
|
||||
if ( (block > 7) || (bytepos > 15) ) return usage_pcf7931_write();
|
||||
|
||||
data = param_get8ex(Cmd, 2, 0, 16);
|
||||
|
||||
PrintAndLog("Writing block: %d", block);
|
||||
PrintAndLog(" pos: %d", bytepos);
|
||||
PrintAndLog(" data: 0x%02X", data);
|
||||
|
||||
UsbCommand c = {CMD_PCF7931_WRITE, { block, bytepos, data} };
|
||||
memcpy(c.d.asDwords, configPcf.Pwd, sizeof(configPcf.Pwd) );
|
||||
c.d.asDwords[7] = (configPcf.OffsetWidth + 128);
|
||||
c.d.asDwords[8] = (configPcf.OffsetPosition + 128);
|
||||
c.d.asDwords[9] = configPcf.InitDelay;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
//no ack?
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"},
|
||||
{"write", CmdLFPCF7931Write, 1, "Write data on a PCF7931 transponder. Usage : lf pcf7931 write <bloc address> <byte address> <data>"},
|
||||
{"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"read", CmdLFPCF7931Read, 0, "Read content of a PCF7931 transponder"},
|
||||
{"write", CmdLFPCF7931Write, 0, "Write data on a PCF7931 transponder."},
|
||||
{"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdLFPCF7931(const char *Cmd)
|
||||
{
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHelp(const char *Cmd)
|
||||
{
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,17 +13,23 @@
|
|||
#define CMDLFPCF7931_H__
|
||||
|
||||
struct pcf7931_config{
|
||||
uint8_t password[7];
|
||||
uint16_t init_delay;
|
||||
int16_t offset[2];
|
||||
uint8_t Pwd[7];
|
||||
uint16_t InitDelay;
|
||||
int16_t OffsetWidth;
|
||||
int16_t OffsetPosition;
|
||||
};
|
||||
|
||||
int pcf7931_resetConfig();
|
||||
int pcf7931_printConfig();
|
||||
|
||||
int usage_pcf7931_read();
|
||||
int usage_pcf7931_write();
|
||||
int usage_pcf7931_config();
|
||||
|
||||
int CmdLFPCF7931(const char *Cmd);
|
||||
|
||||
int CmdLFPCF7931Read(const char *Cmd);
|
||||
|
||||
int CmdLFPCF7931Write(const char *Cmd);
|
||||
|
||||
int CmdLFPCF7931Config(const char *Cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,16 +28,24 @@
|
|||
|
||||
#define CONFIGURATION_BLOCK 0x00
|
||||
#define TRACE_BLOCK 0x01
|
||||
#define REGULAR_READ_MODE_BLOCK 0xFF
|
||||
|
||||
// Default configuration
|
||||
t55xx_conf_block_t config = { .modulation = DEMOD_ASK, .inverted = FALSE, .offset = 0x00, .block0 = 0x00};
|
||||
|
||||
t55xx_conf_block_t Get_t55xx_Config(){
|
||||
return config;
|
||||
}
|
||||
void Set_t55xx_Config(t55xx_conf_block_t conf){
|
||||
config = conf;
|
||||
}
|
||||
|
||||
int usage_t55xx_config(){
|
||||
PrintAndLog("Usage: lf t55xx config [d <demodulation>] [i 1] [o <offset>]");
|
||||
PrintAndLog("Options: ");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog(" b <8|16|32|40|50|64|100|128> Set bitrate");
|
||||
PrintAndLog(" d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NZ|BI|BIa> Set demodulation FSK / ASK / PSK / NZ / Biphase / Biphase A");
|
||||
PrintAndLog(" d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa> Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A");
|
||||
PrintAndLog(" i [1] Invert data signal, defaults to normal");
|
||||
PrintAndLog(" o [offset] Set offset, where data should start decode in bitstream");
|
||||
PrintAndLog("");
|
||||
|
@ -49,31 +57,41 @@ int usage_t55xx_config(){
|
|||
return 0;
|
||||
}
|
||||
int usage_t55xx_read(){
|
||||
PrintAndLog("Usage: lf t55xx read <block> <password>");
|
||||
PrintAndLog(" <block>, block number to read. Between 0-7");
|
||||
PrintAndLog(" <password>, OPTIONAL password (8 hex characters)");
|
||||
PrintAndLog("Usage: lf t55xx read [b <block>] [p <password>] <override_safety> <page1>");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" b <block> - block number to read. Between 0-7");
|
||||
PrintAndLog(" p <password> - OPTIONAL password (8 hex characters)");
|
||||
PrintAndLog(" o - OPTIONAL override safety check");
|
||||
PrintAndLog(" 1 - OPTIONAL read Page 1 instead of Page 0");
|
||||
PrintAndLog(" ****WARNING****");
|
||||
PrintAndLog(" Use of read with password on a tag not configured for a pwd");
|
||||
PrintAndLog(" can damage the tag");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx read 0 - read data from block 0");
|
||||
PrintAndLog(" lf t55xx read 0 feedbeef - read data from block 0 password feedbeef");
|
||||
PrintAndLog(" lf t55xx read b 0 - read data from block 0");
|
||||
PrintAndLog(" lf t55xx read b 0 p feedbeef - read data from block 0 password feedbeef");
|
||||
PrintAndLog(" lf t55xx read b 0 p feedbeef o - read data from block 0 password feedbeef safety check");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
int usage_t55xx_write(){
|
||||
PrintAndLog("Usage: lf t55xx wr <block> <data> [password]");
|
||||
PrintAndLog(" <block>, block number to write. Between 0-7");
|
||||
PrintAndLog(" <data>, 4 bytes of data to write (8 hex characters)");
|
||||
PrintAndLog(" [password], OPTIONAL password 4bytes (8 hex characters)");
|
||||
PrintAndLog("Usage: lf t55xx wr [b <block>] [d <data>] [p <password>] [1]");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" b <block> - block number to write. Between 0-7");
|
||||
PrintAndLog(" d <data> - 4 bytes of data to write (8 hex characters)");
|
||||
PrintAndLog(" p <password> - OPTIONAL password 4bytes (8 hex characters)");
|
||||
PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx wr 3 11223344 - write 11223344 to block 3");
|
||||
PrintAndLog(" lf t55xx wr 3 11223344 feedbeef - write 11223344 to block 3 password feedbeef");
|
||||
PrintAndLog(" lf t55xx wr b 3 d 11223344 - write 11223344 to block 3");
|
||||
PrintAndLog(" lf t55xx wr b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
int usage_t55xx_trace() {
|
||||
PrintAndLog("Usage: lf t55xx trace [1]");
|
||||
PrintAndLog(" [graph buffer data], if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx trace");
|
||||
|
@ -83,7 +101,8 @@ int usage_t55xx_trace() {
|
|||
}
|
||||
int usage_t55xx_info() {
|
||||
PrintAndLog("Usage: lf t55xx info [1]");
|
||||
PrintAndLog(" [graph buffer data], if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx info");
|
||||
|
@ -92,17 +111,21 @@ int usage_t55xx_info() {
|
|||
return 0;
|
||||
}
|
||||
int usage_t55xx_dump(){
|
||||
PrintAndLog("Usage: lf t55xx dump <password>");
|
||||
PrintAndLog(" <password>, OPTIONAL password 4bytes (8 hex symbols)");
|
||||
PrintAndLog("Usage: lf t55xx dump <password> [o]");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" <password> - OPTIONAL password 4bytes (8 hex symbols)");
|
||||
PrintAndLog(" o - OPTIONAL override, force pwd read despite danger to card");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx dump");
|
||||
PrintAndLog(" lf t55xx dump feedbeef");
|
||||
PrintAndLog(" lf t55xx dump feedbeef o");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
int usage_t55xx_detect(){
|
||||
PrintAndLog("Usage: lf t55xx detect");
|
||||
PrintAndLog("Usage: lf t55xx detect [1]");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx detect");
|
||||
|
@ -110,18 +133,29 @@ int usage_t55xx_detect(){
|
|||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
int usage_t55xx_wakup(){
|
||||
PrintAndLog("Usage: lf t55xx wakeup [h] p <password>");
|
||||
PrintAndLog("This commands send the Answer-On-Request command and leaves the readerfield ON afterwards.");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h - this help");
|
||||
PrintAndLog(" p <password> - password 4bytes (8 hex symbols)");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx wakeup p 11223344 - send wakeup password");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
int CmdT55xxSetConfig(const char *Cmd) {
|
||||
|
||||
uint8_t offset = 0;
|
||||
bool errors = FALSE;
|
||||
uint8_t cmdp = 0;
|
||||
char modulation[5] = {0x00};
|
||||
char tmp = 0x00;
|
||||
uint8_t bitRate = 0;
|
||||
uint8_t rates[9] = {8,16,32,40,50,64,100,128,0};
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = FALSE;
|
||||
while(param_getchar(Cmd, cmdp) != 0x00 && !errors)
|
||||
{
|
||||
tmp = param_getchar(Cmd, cmdp);
|
||||
|
@ -201,64 +235,91 @@ int CmdT55xxSetConfig(const char *Cmd) {
|
|||
}
|
||||
|
||||
// No args
|
||||
if (cmdp == 0) {
|
||||
printConfiguration( config );
|
||||
return 0;
|
||||
}
|
||||
//Validations
|
||||
if (errors)
|
||||
return usage_t55xx_config();
|
||||
if (cmdp == 0) return printConfiguration( config );
|
||||
|
||||
config.block0 = 0;
|
||||
printConfiguration ( config );
|
||||
return 0;
|
||||
//Validations
|
||||
if (errors) return usage_t55xx_config();
|
||||
|
||||
config.block0 = 0;
|
||||
return printConfiguration ( config );
|
||||
}
|
||||
|
||||
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password){
|
||||
//Password mode
|
||||
if ( usepwd ) {
|
||||
// try reading the config block and verify that PWD bit is set before doing this!
|
||||
if ( !override ) {
|
||||
if ( !AquireData(0, CONFIGURATION_BLOCK, false, 0 ) ) return 0;
|
||||
if ( !tryDetectModulation() ) {
|
||||
PrintAndLog("Safety Check: Could not detect if PWD bit is set in config block. Exits.");
|
||||
return 0;
|
||||
} else {
|
||||
PrintAndLog("Safety Check: PWD bit is NOT set in config block. Reading without password...");
|
||||
usepwd = false;
|
||||
page1 = false;
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Safety Check Overriden - proceeding despite risk");
|
||||
}
|
||||
}
|
||||
|
||||
if (!AquireData(page1, block, usepwd, password) ) return 0;
|
||||
if (!DecodeT55xxBlock()) return 0;
|
||||
|
||||
char blk[10]={0};
|
||||
sprintf(blk,"%d", block);
|
||||
printT55xxBlock(blk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdT55xxReadBlock(const char *Cmd) {
|
||||
int block = -1;
|
||||
int password = 0xFFFFFFFF; //default to blank Block 7
|
||||
uint8_t block = REGULAR_READ_MODE_BLOCK;
|
||||
uint32_t password = 0; //default to blank Block 7
|
||||
bool usepwd = false;
|
||||
bool override = false;
|
||||
bool page1 = false;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch(param_getchar(Cmd, cmdp)) {
|
||||
case 'h':
|
||||
case 'H':
|
||||
return usage_t55xx_read();
|
||||
case 'b':
|
||||
case 'B':
|
||||
errors |= param_getdec(Cmd, cmdp+1, &block);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'o':
|
||||
case 'O':
|
||||
override = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
password = param_get32ex(Cmd, cmdp+1, 0, 16);
|
||||
usepwd = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case '1':
|
||||
page1 = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (errors) return usage_t55xx_read();
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (cmdp == 'h' || cmdp == 'H')
|
||||
return usage_t55xx_read();
|
||||
|
||||
int res = sscanf(Cmd, "%d %x", &block, &password);
|
||||
|
||||
if ( res < 1 || res > 2 )
|
||||
return usage_t55xx_read();
|
||||
|
||||
|
||||
if ((block < 0) | (block > 7)) {
|
||||
if (block > 7 && block != REGULAR_READ_MODE_BLOCK ) {
|
||||
PrintAndLog("Block must be between 0 and 7");
|
||||
return 1;
|
||||
}
|
||||
|
||||
UsbCommand c = {CMD_T55XX_READ_BLOCK, {0, block, 0}};
|
||||
c.d.asBytes[0] = 0x0;
|
||||
|
||||
//Password mode
|
||||
if ( res == 2 ) {
|
||||
c.arg[2] = password;
|
||||
c.d.asBytes[0] = 0x1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
|
||||
PrintAndLog("command execution time out");
|
||||
return 2;
|
||||
}
|
||||
|
||||
uint8_t got[12000];
|
||||
GetFromBigBuf(got,sizeof(got),0);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
setGraphBuf(got, 12000);
|
||||
DemodBufferLen=0;
|
||||
if (!DecodeT55xxBlock()) return 3;
|
||||
char blk[10]={0};
|
||||
sprintf(blk,"%d", block);
|
||||
printT55xxBlock(blk);
|
||||
return 0;
|
||||
PrintAndLog("Reading Page %d:", page1);
|
||||
PrintAndLog("blk | hex data | binary");
|
||||
return T55xxReadBlock(block, page1, usepwd, override, password);
|
||||
}
|
||||
|
||||
bool DecodeT55xxBlock(){
|
||||
|
@ -269,9 +330,6 @@ bool DecodeT55xxBlock(){
|
|||
uint8_t bitRate[8] = {8,16,32,40,50,64,100,128};
|
||||
DemodBufferLen = 0x00;
|
||||
|
||||
//trim 1/2 a clock from beginning
|
||||
snprintf(cmdStr, sizeof(buf),"%d", bitRate[config.bitrate]/2 );
|
||||
CmdLtrim(cmdStr);
|
||||
switch( config.modulation ){
|
||||
case DEMOD_FSK:
|
||||
snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted );
|
||||
|
@ -323,17 +381,17 @@ int CmdT55xxDetect(const char *Cmd){
|
|||
return usage_t55xx_detect();
|
||||
|
||||
if (strlen(Cmd)==0)
|
||||
AquireData( CONFIGURATION_BLOCK );
|
||||
if ( !AquireData(0, CONFIGURATION_BLOCK, false, 0) )
|
||||
return 0;
|
||||
|
||||
if ( !tryDetectModulation() )
|
||||
PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'");
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// detect configuration?
|
||||
bool tryDetectModulation(){
|
||||
char cmdStr[8] = {0};
|
||||
uint8_t hits = 0;
|
||||
t55xx_conf_block_t tests[15];
|
||||
int bitRate=0;
|
||||
|
@ -341,8 +399,6 @@ bool tryDetectModulation(){
|
|||
save_restoreGB(1);
|
||||
if (GetFskClock("", FALSE, FALSE)){
|
||||
fskClocks(&fc1, &fc2, &clk, FALSE);
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)){
|
||||
tests[hits].modulation = DEMOD_FSK;
|
||||
if (fc1==8 && fc2 == 5)
|
||||
|
@ -369,8 +425,6 @@ bool tryDetectModulation(){
|
|||
} else {
|
||||
clk = GetAskClock("", FALSE, FALSE);
|
||||
if (clk>0) {
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( ASKDemod("0 0 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_ASK;
|
||||
tests[hits].bitrate = bitRate;
|
||||
|
@ -404,8 +458,6 @@ bool tryDetectModulation(){
|
|||
save_restoreGB(0);
|
||||
clk = GetNrzClock("", FALSE, FALSE);
|
||||
if (clk>0) {
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_NRZ;
|
||||
tests[hits].bitrate = bitRate;
|
||||
|
@ -427,9 +479,6 @@ bool tryDetectModulation(){
|
|||
save_restoreGB(0);
|
||||
clk = GetPskClock("", FALSE, FALSE);
|
||||
if (clk>0) {
|
||||
PrintAndLog("clk %d",clk);
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_PSK1;
|
||||
tests[hits].bitrate = bitRate;
|
||||
|
@ -491,7 +540,7 @@ bool tryDetectModulation(){
|
|||
bool testModulation(uint8_t mode, uint8_t modread){
|
||||
switch( mode ){
|
||||
case DEMOD_FSK:
|
||||
if (modread > 3 && modread < 8) return TRUE;
|
||||
if (modread >= DEMOD_FSK1 && modread <= DEMOD_FSK2a) return TRUE;
|
||||
break;
|
||||
case DEMOD_ASK:
|
||||
if (modread == DEMOD_ASK) return TRUE;
|
||||
|
@ -615,14 +664,14 @@ void printT55xxBlock(const char *blockNum){
|
|||
bits[i - config.offset]=DemodBuffer[i];
|
||||
|
||||
blockData = PackBits(0, 32, bits);
|
||||
PrintAndLog("[%s] 0x%08X %s", blockNum, blockData, sprint_bin(bits,32));
|
||||
PrintAndLog(" %s | %08X | %s", blockNum, blockData, sprint_bin(bits,32));
|
||||
}
|
||||
|
||||
int special(const char *Cmd) {
|
||||
uint32_t blockData = 0;
|
||||
uint8_t bits[32] = {0x00};
|
||||
|
||||
PrintAndLog("[OFFSET] [DATA] [BINARY]");
|
||||
PrintAndLog("OFFSET | DATA | BINARY");
|
||||
PrintAndLog("----------------------------------------------------");
|
||||
int i,j = 0;
|
||||
for (; j < 64; ++j){
|
||||
|
@ -632,86 +681,142 @@ int special(const char *Cmd) {
|
|||
|
||||
blockData = PackBits(0, 32, bits);
|
||||
|
||||
PrintAndLog("[%02d] 0x%08X %s",j , blockData, sprint_bin(bits,32));
|
||||
PrintAndLog(" %02d | 0x%08X | %s",j , blockData, sprint_bin(bits,32));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printConfiguration( t55xx_conf_block_t b){
|
||||
int printConfiguration( t55xx_conf_block_t b){
|
||||
PrintAndLog("Modulation : %s", GetSelectedModulationStr(b.modulation) );
|
||||
PrintAndLog("Bit Rate : %s", GetBitRateStr(b.bitrate) );
|
||||
PrintAndLog("Inverted : %s", (b.inverted) ? "Yes" : "No" );
|
||||
PrintAndLog("Offset : %d", b.offset);
|
||||
PrintAndLog("Block0 : 0x%08X", b.block0);
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdT55xxWriteBlock(const char *Cmd)
|
||||
{
|
||||
int block = 8; //default to invalid block
|
||||
int data = 0xFFFFFFFF; //default to blank Block
|
||||
int password = 0xFFFFFFFF; //default to blank Block 7
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (cmdp == 'h' || cmdp == 'H') {
|
||||
usage_t55xx_write();
|
||||
return 0;
|
||||
int CmdT55xxWakeUp(const char *Cmd) {
|
||||
uint32_t password = 0;
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = true;
|
||||
while(param_getchar(Cmd, cmdp) != 0x00) {
|
||||
switch(param_getchar(Cmd, cmdp)) {
|
||||
case 'h':
|
||||
case 'H':
|
||||
return usage_t55xx_wakup();
|
||||
case 'p':
|
||||
case 'P':
|
||||
password = param_get32ex(Cmd, cmdp+1, 0xFFFFFFFF, 16);
|
||||
cmdp += 2;
|
||||
errors = false;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int res = sscanf(Cmd, "%d %x %x",&block, &data, &password);
|
||||
|
||||
if ( res < 2 || res > 3) {
|
||||
usage_t55xx_write();
|
||||
return 1;
|
||||
if (errors) return usage_t55xx_wakup();
|
||||
|
||||
UsbCommand c = {CMD_T55XX_WAKEUP, {password, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
PrintAndLog("Wake up command sent. Try read now");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdT55xxWriteBlock(const char *Cmd) {
|
||||
uint8_t block = 0xFF; //default to invalid block
|
||||
uint32_t data = 0xFFFFFFFF; //default to blank Block
|
||||
uint32_t password = 0xFFFFFFFF; //default to blank Block 7
|
||||
bool usepwd = false;
|
||||
bool page1 = false;
|
||||
bool gotdata = false;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch(param_getchar(Cmd, cmdp)) {
|
||||
case 'h':
|
||||
case 'H':
|
||||
return usage_t55xx_write();
|
||||
case 'b':
|
||||
case 'B':
|
||||
errors |= param_getdec(Cmd, cmdp+1, &block);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
data = param_get32ex(Cmd, cmdp+1, 0, 16);
|
||||
gotdata = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
password = param_get32ex(Cmd, cmdp+1, 0, 16);
|
||||
usepwd = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case '1':
|
||||
page1 = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (errors || !gotdata) return usage_t55xx_write();
|
||||
|
||||
if (block > 7) {
|
||||
PrintAndLog("Block number must be between 0 and 7");
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}};
|
||||
UsbCommand resp;
|
||||
c.d.asBytes[0] = 0x0;
|
||||
c.d.asBytes[0] = (page1) ? 0x2 : 0;
|
||||
|
||||
PrintAndLog("Writing to block: %d data : 0x%08X", block, data);
|
||||
PrintAndLog("Writing to page: %d block: %d data : 0x%08X", page1, block, data);
|
||||
|
||||
//Password mode
|
||||
if (res == 3) {
|
||||
if (usepwd) {
|
||||
c.arg[2] = password;
|
||||
c.d.asBytes[0] = 0x1;
|
||||
c.d.asBytes[0] |= 0x1;
|
||||
PrintAndLog("pwd : 0x%08X", password);
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
|
||||
PrintAndLog("Error occurred, device did not ACK write operation. (May be due to old firmware)");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdT55xxReadTrace(const char *Cmd)
|
||||
{
|
||||
int CmdT55xxReadTrace(const char *Cmd) {
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
bool pwdmode = false;
|
||||
uint32_t password = 0;
|
||||
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H')
|
||||
return usage_t55xx_trace();
|
||||
|
||||
if (strlen(Cmd)==0)
|
||||
AquireData( TRACE_BLOCK );
|
||||
if ( !AquireData( TRACE_BLOCK, REGULAR_READ_MODE_BLOCK, pwdmode, password ) )
|
||||
return 0;
|
||||
|
||||
if (!DecodeT55xxBlock()) return 1;
|
||||
if (!DecodeT55xxBlock()) return 0;
|
||||
|
||||
if ( !DemodBufferLen) return 0;
|
||||
|
||||
if ( !DemodBufferLen) return 1;
|
||||
|
||||
RepaintGraphWindow();
|
||||
uint8_t repeat = 0;
|
||||
if (config.offset > 5)
|
||||
repeat = 32;
|
||||
uint8_t si = config.offset+repeat;
|
||||
uint32_t bl0 = PackBits(si, 32, DemodBuffer);
|
||||
uint32_t bl1 = PackBits(si+32, 32, DemodBuffer);
|
||||
uint32_t bl1 = PackBits(si, 32, DemodBuffer);
|
||||
uint32_t bl2 = PackBits(si+32, 32, DemodBuffer);
|
||||
|
||||
uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8;
|
||||
uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8;
|
||||
|
@ -732,7 +837,7 @@ int CmdT55xxReadTrace(const char *Cmd)
|
|||
|
||||
if ( acl != 0xE0 ) {
|
||||
PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintAndLog("");
|
||||
|
@ -749,8 +854,8 @@ int CmdT55xxReadTrace(const char *Cmd)
|
|||
PrintAndLog(" Die Number : %d", dw);
|
||||
PrintAndLog("-------------------------------------------------------------");
|
||||
PrintAndLog(" Raw Data - Page 1");
|
||||
PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(DemodBuffer+config.offset+repeat,32) );
|
||||
PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat+32,32) );
|
||||
PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) );
|
||||
PrintAndLog(" Block 2 : 0x%08X %s", bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) );
|
||||
PrintAndLog("-------------------------------------------------------------");
|
||||
|
||||
/*
|
||||
|
@ -779,13 +884,16 @@ int CmdT55xxInfo(const char *Cmd){
|
|||
Normal mode
|
||||
Extended mode
|
||||
*/
|
||||
bool pwdmode = false;
|
||||
uint32_t password = 0;
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H')
|
||||
return usage_t55xx_info();
|
||||
|
||||
if (strlen(Cmd)==0)
|
||||
AquireData( CONFIGURATION_BLOCK );
|
||||
if ( !AquireData( 0, CONFIGURATION_BLOCK, pwdmode, password ) )
|
||||
return 1;
|
||||
|
||||
if (!DecodeT55xxBlock()) return 1;
|
||||
|
||||
|
@ -836,67 +944,59 @@ int CmdT55xxInfo(const char *Cmd){
|
|||
|
||||
int CmdT55xxDump(const char *Cmd){
|
||||
|
||||
char s[20] = {0x00};
|
||||
uint8_t pwd[4] = {0x00};
|
||||
|
||||
uint32_t password = 0;
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if ( cmdp == 'h' || cmdp == 'H') {
|
||||
usage_t55xx_dump();
|
||||
return 0;
|
||||
}
|
||||
bool override = false;
|
||||
if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_dump();
|
||||
|
||||
bool hasPwd = ( strlen(Cmd) > 0);
|
||||
if ( hasPwd ){
|
||||
if (param_gethex(Cmd, 0, pwd, 8)) {
|
||||
PrintAndLog("password must include 8 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
bool usepwd = ( strlen(Cmd) > 0);
|
||||
if ( usepwd ){
|
||||
password = param_get32ex(Cmd, 0, 0, 16);
|
||||
if (param_getchar(Cmd, 1) =='o' )
|
||||
override = true;
|
||||
}
|
||||
|
||||
for ( int i = 0; i <8; ++i){
|
||||
memset(s,0,sizeof(s));
|
||||
PrintAndLog("Reading Page 0:");
|
||||
PrintAndLog("blk | hex data | binary");
|
||||
for ( uint8_t i = 0; i <8; ++i){
|
||||
T55xxReadBlock(i, 0, usepwd, override, password);
|
||||
/*memset(s,0,sizeof(s));
|
||||
if ( hasPwd ) {
|
||||
sprintf(s,"%d %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]);
|
||||
if ( override ) {
|
||||
sprintf(s,"b %d p %02x%02x%02x%02x o", i, pwd[0],pwd[1],pwd[2],pwd[3]);
|
||||
} else {
|
||||
sprintf(s,"b %d p %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]);
|
||||
}
|
||||
} else {
|
||||
sprintf(s,"%d", i);
|
||||
sprintf(s,"b %d", i);
|
||||
}
|
||||
CmdT55xxReadBlock(s);
|
||||
CmdT55xxReadBlock(s);*/
|
||||
}
|
||||
return 0;
|
||||
PrintAndLog("Reading Page 1:");
|
||||
PrintAndLog("blk | hex data | binary");
|
||||
for ( uint8_t i = 0; i<4; i++){
|
||||
T55xxReadBlock(i, 1, usepwd, override, password);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AquireData( uint8_t block ){
|
||||
int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){
|
||||
|
||||
UsbCommand c;
|
||||
|
||||
if ( block == CONFIGURATION_BLOCK )
|
||||
c.cmd = CMD_T55XX_READ_BLOCK;
|
||||
else if (block == TRACE_BLOCK )
|
||||
c.cmd = CMD_T55XX_READ_TRACE;
|
||||
|
||||
c.arg[0] = 0x00;
|
||||
c.arg[1] = 0x00;
|
||||
c.arg[2] = 0x00;
|
||||
c.d.asBytes[0] = 0x0;
|
||||
|
||||
//Password mode
|
||||
// if ( res == 2 ) {
|
||||
// c.arg[2] = password;
|
||||
// c.d.asBytes[0] = 0x1;
|
||||
// }
|
||||
uint8_t arg0 = (page<<1) | pwdmode;
|
||||
UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}};
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
|
||||
PrintAndLog("command execution time out");
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t got[12000];
|
||||
GetFromBigBuf(got,sizeof(got),0);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
setGraphBuf(got, 12000);
|
||||
return 0;
|
||||
setGraphBuf(got, sizeof(got));
|
||||
return 1;
|
||||
}
|
||||
|
||||
char * GetBitRateStr(uint32_t id){
|
||||
|
@ -1072,17 +1172,36 @@ uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits){
|
|||
return tmp;
|
||||
}
|
||||
|
||||
int CmdResetRead(const char *Cmd) {
|
||||
UsbCommand c = {CMD_T55XX_RESET_READ, {0,0,0}};
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
|
||||
PrintAndLog("command execution time out");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t got[BIGBUF_SIZE-1];
|
||||
GetFromBigBuf(got,sizeof(got),0);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
setGraphBuf(got, sizeof(got));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
||||
{"detect", CmdT55xxDetect, 0, "[1] Try detecting the tag modulation from reading the configuration block."},
|
||||
{"read", CmdT55xxReadBlock, 0, "<block> [password] -- Read T55xx block data (page 0) [optional password]"},
|
||||
{"write", CmdT55xxWriteBlock,0, "<block> <data> [password] -- Write T55xx block data (page 0) [optional password]"},
|
||||
{"trace", CmdT55xxReadTrace, 0, "[1] Show T55xx traceability data (page 1/ blk 0-1)"},
|
||||
{"info", CmdT55xxInfo, 0, "[1] Show T55xx configuration data (page 0/ blk 0)"},
|
||||
{"dump", CmdT55xxDump, 0, "[password] Dump T55xx card block 0-7. [optional password]"},
|
||||
{"special", special, 0, "Show block changes with 64 different offsets"},
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
||||
{"detect", CmdT55xxDetect, 0, "[1] Try detecting the tag modulation from reading the configuration block."},
|
||||
{"read", CmdT55xxReadBlock, 0, "b <block> p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"},
|
||||
{"resetread",CmdResetRead, 0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"},
|
||||
{"write", CmdT55xxWriteBlock,0, "b <block> d <data> p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"},
|
||||
{"trace", CmdT55xxReadTrace, 0, "[1] Show T55xx traceability data (page 1/ blk 0-1)"},
|
||||
{"info", CmdT55xxInfo, 0, "[1] Show T55xx configuration data (page 0/ blk 0)"},
|
||||
{"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"},
|
||||
{"special", special, 0, "Show block changes with 64 different offsets"},
|
||||
{"wakeup", CmdT55xxWakeUp, 0, "Send AOR wakeup command"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ typedef struct {
|
|||
RF_128 = 0x07,
|
||||
} bitrate;
|
||||
} t55xx_conf_block_t;
|
||||
t55xx_conf_block_t Get_t55xx_Config();
|
||||
void Set_t55xx_Config(t55xx_conf_block_t conf);
|
||||
|
||||
|
||||
int CmdLFT55XX(const char *Cmd);
|
||||
int CmdT55xxSetConfig(const char *Cmd);
|
||||
|
@ -47,6 +50,7 @@ int CmdT55xxWriteBlock(const char *Cmd);
|
|||
int CmdT55xxReadTrace(const char *Cmd);
|
||||
int CmdT55xxInfo(const char *Cmd);
|
||||
int CmdT55xxDetect(const char *Cmd);
|
||||
int CmdResetRead(const char *Cmd);
|
||||
|
||||
char * GetBitRateStr(uint32_t id);
|
||||
char * GetSaferStr(uint32_t id);
|
||||
|
@ -55,12 +59,12 @@ char * GetModelStrFromCID(uint32_t cid);
|
|||
char * GetSelectedModulationStr( uint8_t id);
|
||||
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream);
|
||||
void printT55xxBlock(const char *demodStr);
|
||||
void printConfiguration( t55xx_conf_block_t b);
|
||||
int printConfiguration( t55xx_conf_block_t b);
|
||||
|
||||
bool DecodeT55xxBlock();
|
||||
bool tryDetectModulation();
|
||||
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate);
|
||||
int special(const char *Cmd);
|
||||
int AquireData( uint8_t block );
|
||||
int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,15 +42,15 @@ static int cmd_tail;//Starts as 0
|
|||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
|
||||
{"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
|
||||
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
|
||||
{"hw", CmdHW, 1, "{ Hardware commands... }"},
|
||||
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
|
||||
{"script", CmdScript, 1,"{ Scripting commands }"},
|
||||
{"quit", CmdQuit, 1, "Exit program"},
|
||||
{"exit", CmdQuit, 1, "Exit program"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
|
||||
{"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
|
||||
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
|
||||
{"hw", CmdHW, 1, "{ Hardware commands... }"},
|
||||
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
|
||||
{"script", CmdScript, 1, "{ Scripting commands }"},
|
||||
{"quit", CmdQuit, 1, "Exit program"},
|
||||
{"exit", CmdQuit, 1, "Exit program"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
command_t* getTopLevelCommandTable()
|
||||
|
@ -65,8 +65,7 @@ int CmdHelp(const char *Cmd)
|
|||
|
||||
int CmdQuit(const char *Cmd)
|
||||
{
|
||||
exit(0);
|
||||
return 0;
|
||||
return 99;
|
||||
}
|
||||
/**
|
||||
* @brief This method should be called when sending a new command to the pm3. In case any old
|
||||
|
@ -164,8 +163,8 @@ bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
|
|||
// Entry point into our code: called whenever the user types a command and
|
||||
// then presses Enter, which the full command line that they typed.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CommandReceived(char *Cmd) {
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
int CommandReceived(char *Cmd) {
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "usb_cmd.h"
|
||||
#include "cmdparser.h"
|
||||
void UsbCommandReceived(UsbCommand *UC);
|
||||
void CommandReceived(char *Cmd);
|
||||
int CommandReceived(char *Cmd);
|
||||
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
|
||||
bool WaitForResponse(uint32_t cmd, UsbCommand* response);
|
||||
void clearCommandBuffer();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "cmdparser.h"
|
||||
#include "proxmark3.h"
|
||||
|
||||
|
||||
void CmdsHelp(const command_t Commands[])
|
||||
{
|
||||
if (Commands[0].Name == NULL)
|
||||
|
@ -28,48 +29,51 @@ void CmdsHelp(const command_t Commands[])
|
|||
}
|
||||
}
|
||||
|
||||
void CmdsParse(const command_t Commands[], const char *Cmd)
|
||||
|
||||
int CmdsParse(const command_t Commands[], const char *Cmd)
|
||||
{
|
||||
if(strcmp( Cmd, "XX_internal_command_dump_XX") == 0)
|
||||
{// Help dump children
|
||||
dumpCommandsRecursive(Commands, 0);
|
||||
return;
|
||||
}
|
||||
if(strcmp( Cmd, "XX_internal_command_dump_markdown_XX") == 0)
|
||||
{// Markdown help dump children
|
||||
dumpCommandsRecursive(Commands, 1);
|
||||
return;
|
||||
}
|
||||
char cmd_name[32];
|
||||
int len = 0;
|
||||
memset(cmd_name, 0, 32);
|
||||
sscanf(Cmd, "%31s%n", cmd_name, &len);
|
||||
int i = 0;
|
||||
while (Commands[i].Name && strcmp(Commands[i].Name, cmd_name))
|
||||
++i;
|
||||
if(strcmp( Cmd, "XX_internal_command_dump_XX") == 0)
|
||||
{// Help dump children
|
||||
dumpCommandsRecursive(Commands, 0);
|
||||
return 0;
|
||||
}
|
||||
if(strcmp( Cmd, "XX_internal_command_dump_markdown_XX") == 0)
|
||||
{// Markdown help dump children
|
||||
dumpCommandsRecursive(Commands, 1);
|
||||
return 0;
|
||||
}
|
||||
char cmd_name[32];
|
||||
int len = 0;
|
||||
memset(cmd_name, 0, 32);
|
||||
sscanf(Cmd, "%31s%n", cmd_name, &len);
|
||||
int i = 0;
|
||||
while (Commands[i].Name && strcmp(Commands[i].Name, cmd_name))
|
||||
++i;
|
||||
|
||||
/* try to find exactly one prefix-match */
|
||||
if(!Commands[i].Name) {
|
||||
int last_match = 0;
|
||||
int matches = 0;
|
||||
/* try to find exactly one prefix-match */
|
||||
if(!Commands[i].Name) {
|
||||
int last_match = 0;
|
||||
int matches = 0;
|
||||
|
||||
for(i=0;Commands[i].Name;i++) {
|
||||
if( !strncmp(Commands[i].Name, cmd_name, strlen(cmd_name)) ) {
|
||||
last_match = i;
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
if(matches == 1) i=last_match;
|
||||
}
|
||||
for(i=0;Commands[i].Name;i++) {
|
||||
if( !strncmp(Commands[i].Name, cmd_name, strlen(cmd_name)) ) {
|
||||
last_match = i;
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
if(matches == 1) i=last_match;
|
||||
}
|
||||
|
||||
if (Commands[i].Name) {
|
||||
while (Cmd[len] == ' ')
|
||||
++len;
|
||||
Commands[i].Parse(Cmd + len);
|
||||
} else {
|
||||
// show help for selected hierarchy or if command not recognised
|
||||
CmdsHelp(Commands);
|
||||
}
|
||||
if (Commands[i].Name) {
|
||||
while (Cmd[len] == ' ')
|
||||
++len;
|
||||
return Commands[i].Parse(Cmd + len);
|
||||
} else {
|
||||
// show help for selected hierarchy or if command not recognised
|
||||
CmdsHelp(Commands);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char pparent[512] = {0};
|
||||
|
|
|
@ -24,7 +24,7 @@ typedef struct command_s
|
|||
// Print help for each command in the command array
|
||||
void CmdsHelp(const command_t Commands[]);
|
||||
// Parse a command line
|
||||
void CmdsParse(const command_t Commands[], const char *Cmd);
|
||||
int CmdsParse(const command_t Commands[], const char *Cmd);
|
||||
void dumpCommandsRecursive(const command_t cmds[], int markdown);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,7 +73,7 @@ typedef struct {
|
|||
#define CMD_INDALA_CLONE_TAG_L 0x0213
|
||||
#define CMD_T55XX_READ_BLOCK 0x0214
|
||||
#define CMD_T55XX_WRITE_BLOCK 0x0215
|
||||
#define CMD_T55XX_READ_TRACE 0x0216
|
||||
#define CMD_T55XX_RESET_READ 0x0216
|
||||
#define CMD_PCF7931_READ 0x0217
|
||||
#define CMD_EM4X_READ_WORD 0x0218
|
||||
#define CMD_EM4X_WRITE_WORD 0x0219
|
||||
|
@ -85,6 +85,7 @@ typedef struct {
|
|||
#define CMD_ASK_SIM_TAG 0x021F
|
||||
#define CMD_PSK_SIM_TAG 0x0220
|
||||
#define CMD_AWID_DEMOD_FSK 0x0221
|
||||
#define CMD_T55XX_WAKEUP 0x0224
|
||||
|
||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
|
@ -115,9 +116,17 @@ typedef struct {
|
|||
#define CMD_WRITER_LEGIC_RF 0x0389
|
||||
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
|
||||
|
||||
#define CMD_ICLASS_READCHECK 0x038F
|
||||
#define CMD_ICLASS_CLONE 0x0390
|
||||
#define CMD_ICLASS_DUMP 0x0391
|
||||
#define CMD_SNOOP_ICLASS 0x0392
|
||||
#define CMD_SIMULATE_TAG_ICLASS 0x0393
|
||||
#define CMD_READER_ICLASS 0x0394
|
||||
#define CMD_READER_ICLASS_REPLAY 0x0395
|
||||
#define CMD_ICLASS_READBLOCK 0x0396
|
||||
#define CMD_ICLASS_WRITEBLOCK 0x0397
|
||||
#define CMD_ICLASS_EML_MEMSET 0x0398
|
||||
#define CMD_ICLASS_AUTHENTICATION 0x0399
|
||||
|
||||
// For measurements of the antenna tuning
|
||||
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||
|
|
|
@ -224,23 +224,44 @@ void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out)
|
|||
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
|
||||
{
|
||||
uint8_t cc_nr[13] = { 0 };
|
||||
uint8_t div_key[8];
|
||||
uint8_t div_key[8];
|
||||
//cc_nr=(uint8_t*)malloc(length+1);
|
||||
|
||||
memcpy(cc_nr,cc_nr_p,12);
|
||||
memcpy(div_key,div_key_p,8);
|
||||
memcpy(cc_nr, cc_nr_p, 12);
|
||||
memcpy(div_key, div_key_p, 8);
|
||||
|
||||
reverse_arraybytes(cc_nr,12);
|
||||
BitstreamIn bitstream = {cc_nr,12 * 8,0};
|
||||
uint8_t dest []= {0,0,0,0,0,0,0,0};
|
||||
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
|
||||
MAC(div_key,bitstream, out);
|
||||
//The output MAC must also be reversed
|
||||
reverse_arraybytes(dest, sizeof(dest));
|
||||
memcpy(mac, dest, 4);
|
||||
BitstreamIn bitstream = {cc_nr, 12 * 8, 0};
|
||||
uint8_t dest []= {0,0,0,0,0,0,0,0};
|
||||
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
|
||||
MAC(div_key,bitstream, out);
|
||||
//The output MAC must also be reversed
|
||||
reverse_arraybytes(dest, sizeof(dest));
|
||||
memcpy(mac, dest, 4);
|
||||
//free(cc_nr);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4])
|
||||
{
|
||||
uint8_t *address_data;
|
||||
uint8_t div_key[8];
|
||||
address_data = (uint8_t*) malloc(address_data_size);
|
||||
|
||||
memcpy(address_data, address_data_p, address_data_size);
|
||||
memcpy(div_key, div_key_p, 8);
|
||||
|
||||
reverse_arraybytes(address_data, address_data_size);
|
||||
BitstreamIn bitstream = {address_data, address_data_size * 8, 0};
|
||||
uint8_t dest []= {0,0,0,0,0,0,0,0};
|
||||
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
|
||||
MAC(div_key, bitstream, out);
|
||||
//The output MAC must also be reversed
|
||||
reverse_arraybytes(dest, sizeof(dest));
|
||||
memcpy(mac, dest, 4);
|
||||
free(address_data);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef ON_DEVICE
|
||||
int testMAC()
|
||||
{
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <stdint.h>
|
||||
|
||||
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
|
||||
void doMAC_N(uint8_t *address_data_p,uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]);
|
||||
|
||||
#ifndef ON_DEVICE
|
||||
int testMAC();
|
||||
#endif
|
||||
|
|
|
@ -44,7 +44,7 @@ local _commands = {
|
|||
CMD_INDALA_CLONE_TAG_L = 0x0213,
|
||||
CMD_T55XX_READ_BLOCK = 0x0214,
|
||||
CMD_T55XX_WRITE_BLOCK = 0x0215,
|
||||
CMD_T55XX_READ_TRACE = 0x0216,
|
||||
CMD_T55XX_RESET_READ = 0x0216,
|
||||
CMD_PCF7931_READ = 0x0217,
|
||||
CMD_EM4X_READ_WORD = 0x0218,
|
||||
CMD_EM4X_WRITE_WORD = 0x0219,
|
||||
|
@ -56,7 +56,7 @@ local _commands = {
|
|||
CMD_ASK_SIM_TAG = 0x021F,
|
||||
CMD_PSK_SIM_TAG = 0x0220,
|
||||
CMD_AWID_DEMOD_FSK = 0x0221,
|
||||
|
||||
CMD_T55XX_WAKEUP = 0x0224,
|
||||
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
--// For the 13.56 MHz tags
|
||||
|
@ -88,11 +88,17 @@ local _commands = {
|
|||
CMD_EPA_PACE_COLLECT_NONCE = 0x038A,
|
||||
--//CMD_EPA_ = 0x038B,
|
||||
|
||||
CMD_ICLASS_READCHECK = 0x038F,
|
||||
CMD_ICLASS_CLONE = 0x0390,
|
||||
CMD_ICLASS_DUMP = 0x0391,
|
||||
CMD_SNOOP_ICLASS = 0x0392,
|
||||
CMD_SIMULATE_TAG_ICLASS = 0x0393,
|
||||
CMD_READER_ICLASS = 0x0394,
|
||||
CMD_READER_ICLASS_REPLAY = 0x0395,
|
||||
CMD_ICLASS_ISO14443A_WRITE = 0x0397,
|
||||
CMD_READER_ICLASS_REPLAY = 0x0395,
|
||||
CMD_ICLASS_READBLOCK = 0x0396,
|
||||
CMD_ICLASS_WRITEBLOCK = 0x0397,
|
||||
CMD_ICLASS_EML_MEMSET = 0x0398,
|
||||
CMD_ICLASS_AUTHENTICATION = 0x0399,
|
||||
|
||||
--// For measurements of the antenna tuning
|
||||
CMD_MEASURE_ANTENNA_TUNING = 0x0400,
|
||||
|
|
|
@ -620,3 +620,23 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){
|
||||
/*
|
||||
uint32_t nt; // tag challenge
|
||||
uint32_t ar_enc; // encrypted reader response
|
||||
uint32_t at_enc; // encrypted tag response
|
||||
*/
|
||||
if (traceCrypto1) {
|
||||
crypto1_destroy(traceCrypto1);
|
||||
}
|
||||
ks2 = ar_enc ^ prng_successor(nt, 64);
|
||||
ks3 = at_enc ^ prng_successor(nt, 96);
|
||||
traceCrypto1 = lfsr_recovery64(ks2, ks3);
|
||||
|
||||
mf_crypto1_decrypt(traceCrypto1, data, len, 0);
|
||||
|
||||
PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) );
|
||||
crypto1_destroy(traceCrypto1);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -67,3 +67,4 @@ int isBlockEmpty(int blockN);
|
|||
int isBlockTrailer(int blockN);
|
||||
int loadTraceCard(uint8_t *tuid);
|
||||
int saveTraceCard(void);
|
||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
||||
|
|
|
@ -155,12 +155,11 @@ static void *main_loop(void *targ) {
|
|||
cmd[strlen(cmd) - 1] = 0x00;
|
||||
|
||||
if (cmd[0] != 0x00) {
|
||||
if (strncmp(cmd, "quit", 4) == 0) {
|
||||
exit(0);
|
||||
int ret = CommandReceived(cmd);
|
||||
add_history(cmd);
|
||||
if (ret == 99) { // exit or quit
|
||||
break;
|
||||
}
|
||||
CommandReceived(cmd);
|
||||
add_history(cmd);
|
||||
}
|
||||
free(cmd);
|
||||
} else {
|
||||
|
@ -223,7 +222,7 @@ int main(int argc, char* argv[]) {
|
|||
.usb_present = 0,
|
||||
.script_cmds_file = NULL
|
||||
};
|
||||
pthread_t main_loop_t;
|
||||
pthread_t main_loop_threat;
|
||||
|
||||
|
||||
sp = uart_open(argv[1]);
|
||||
|
@ -258,18 +257,20 @@ int main(int argc, char* argv[]) {
|
|||
// create a mutex to avoid interlacing print commands from our different threads
|
||||
pthread_mutex_init(&print_lock, NULL);
|
||||
|
||||
pthread_create(&main_loop_t, NULL, &main_loop, &marg);
|
||||
pthread_create(&main_loop_threat, NULL, &main_loop, &marg);
|
||||
InitGraphics(argc, argv);
|
||||
|
||||
MainGraphics();
|
||||
|
||||
pthread_join(main_loop_t, NULL);
|
||||
pthread_join(main_loop_threat, NULL);
|
||||
|
||||
// Clean up the port
|
||||
uart_close(sp);
|
||||
|
||||
if (offline == 0) {
|
||||
uart_close(sp);
|
||||
}
|
||||
|
||||
// clean up mutex
|
||||
pthread_mutex_destroy(&print_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "util.h"
|
||||
#include "nonce2key/nonce2key.h"
|
||||
#include "../common/iso15693tools.h"
|
||||
#include "iso14443crc.h"
|
||||
#include "../common/crc16.h"
|
||||
#include "../common/crc64.h"
|
||||
#include "../common/sha1.h"
|
||||
|
@ -228,6 +229,27 @@ static int l_iso15693_crc(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_iso14443b_crc(lua_State *L)
|
||||
{
|
||||
/* void ComputeCrc14443(int CrcType,
|
||||
const unsigned char *Data, int Length,
|
||||
unsigned char *TransmitFirst,
|
||||
unsigned char *TransmitSecond)
|
||||
*/
|
||||
unsigned char buf[USB_CMD_DATA_SIZE];
|
||||
size_t len = 0;
|
||||
const char *data = luaL_checklstring(L, 1, &len);
|
||||
if (USB_CMD_DATA_SIZE < len)
|
||||
len = USB_CMD_DATA_SIZE-2;
|
||||
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
sscanf(&data[i], "%02x", (unsigned int *)&buf[i / 2]);
|
||||
}
|
||||
ComputeCrc14443(CRC_14443_B, buf, len, &buf[len], &buf[len+1]);
|
||||
|
||||
lua_pushlstring(L, (const char *)&buf, len+2);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
Simple AES 128 cbc hook up to OpenSSL.
|
||||
params: key, input
|
||||
|
@ -426,6 +448,7 @@ int set_pm3_libraries(lua_State *L)
|
|||
{"clearCommandBuffer", l_clearCommandBuffer},
|
||||
{"console", l_CmdConsole},
|
||||
{"iso15693_crc", l_iso15693_crc},
|
||||
{"iso14443b_crc", l_iso14443b_crc},
|
||||
{"aes128_decrypt", l_aes128decrypt_cbc},
|
||||
{"aes128_decrypt_ecb", l_aes128decrypt_ecb},
|
||||
{"aes128_encrypt", l_aes128encrypt_cbc},
|
||||
|
|
|
@ -333,7 +333,28 @@ int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
|
|||
|
||||
return 0;
|
||||
}
|
||||
int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt)
|
||||
{
|
||||
int bg, en, temp, i;
|
||||
|
||||
//if (hexcnt % 2)
|
||||
// return 1;
|
||||
|
||||
if (param_getptr(line, &bg, &en, paramnum)) return 1;
|
||||
|
||||
*hexcnt = en - bg + 1;
|
||||
if (*hexcnt % 2) //error if not complete hex bytes
|
||||
return 1;
|
||||
|
||||
for(i = 0; i < *hexcnt; i += 2) {
|
||||
if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) ) return 1;
|
||||
|
||||
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
|
||||
data[i / 2] = temp & 0xff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int param_getstr(const char *line, int paramnum, char * str)
|
||||
{
|
||||
int bg, en;
|
||||
|
|
|
@ -55,6 +55,7 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
|
|||
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
|
||||
uint8_t param_isdec(const char *line, int paramnum);
|
||||
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
|
||||
int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt);
|
||||
int param_getstr(const char *line, int paramnum, char * str);
|
||||
|
||||
int hextobinarray( char *target, char *source);
|
||||
|
|
|
@ -67,7 +67,7 @@ VPATH = . ../common ../fpga ../zlib
|
|||
|
||||
INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES)
|
||||
|
||||
CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os
|
||||
CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 -Os $(APP_CFLAGS)
|
||||
LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
|
||||
|
||||
LIBS = -lgcc
|
||||
|
|
119
common/lfdemod.c
119
common/lfdemod.c
|
@ -282,6 +282,16 @@ int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert)
|
|||
return bestErr;
|
||||
}
|
||||
|
||||
uint32_t manchesterEncode2Bytes(uint16_t datain) {
|
||||
uint32_t output = 0;
|
||||
uint8_t curBit = 0;
|
||||
for (uint8_t i=0; i<16; i++) {
|
||||
curBit = (datain >> (15-i) & 1);
|
||||
output |= (1<<(((15-i)*2)+curBit));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//encode binary data into binary manchester
|
||||
int ManchesterEncode(uint8_t *BitStream, size_t size)
|
||||
|
@ -369,7 +379,9 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
|
|||
if (fclow==0) fclow=8;
|
||||
//set the threshold close to 0 (graph) or 128 std to avoid static
|
||||
uint8_t threshold_value = 123;
|
||||
|
||||
size_t preLastSample = 0;
|
||||
size_t LastSample = 0;
|
||||
size_t currSample = 0;
|
||||
// sync to first lo-hi transition, and threshold
|
||||
|
||||
// Need to threshold first sample
|
||||
|
@ -389,13 +401,22 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
|
|||
|
||||
// Check for 0->1 transition
|
||||
if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition
|
||||
if ((idx-last_transition)<(fclow-2)){ //0-5 = garbage noise
|
||||
preLastSample = LastSample;
|
||||
LastSample = currSample;
|
||||
currSample = idx-last_transition;
|
||||
if (currSample < (fclow-2)){ //0-5 = garbage noise
|
||||
//do nothing with extra garbage
|
||||
} else if ((idx-last_transition) < (fchigh-1)) { //6-8 = 8 waves
|
||||
} else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves
|
||||
if (LastSample > (fchigh-2) && preLastSample < (fchigh-1)){
|
||||
dest[numBits-1]=1; //correct last 9 wave surrounded by 8 waves
|
||||
}
|
||||
dest[numBits++]=1;
|
||||
} else if ((idx-last_transition) > (fchigh+1) && !numBits) { //12 + and first bit = garbage
|
||||
|
||||
} else if (currSample > (fchigh+1) && !numBits) { //12 + and first bit = garbage
|
||||
//do nothing with beginning garbage
|
||||
} else { //9+ = 10 waves
|
||||
} else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's
|
||||
dest[numBits++]=1;
|
||||
} else { //9+ = 10 sample waves
|
||||
dest[numBits++]=0;
|
||||
}
|
||||
last_transition = idx;
|
||||
|
@ -576,6 +597,25 @@ int IOdemodFSK(uint8_t *dest, size_t size)
|
|||
return (int) startIdx;
|
||||
}
|
||||
return -5;
|
||||
}
|
||||
|
||||
// by marshmellow
|
||||
// find viking preamble 0xF200 in already demoded data
|
||||
int VikingDemod_AM(uint8_t *dest, size_t *size) {
|
||||
//make sure buffer has data
|
||||
if (*size < 64*2) return -2;
|
||||
|
||||
size_t startIdx = 0;
|
||||
uint8_t preamble[] = {1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
|
||||
if (errChk == 0) return -4; //preamble not found
|
||||
uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ bytebits_to_byte(dest+startIdx+8,8) ^ bytebits_to_byte(dest+startIdx+16,8)
|
||||
^ bytebits_to_byte(dest+startIdx+24,8) ^ bytebits_to_byte(dest+startIdx+32,8) ^ bytebits_to_byte(dest+startIdx+40,8)
|
||||
^ bytebits_to_byte(dest+startIdx+48,8) ^ bytebits_to_byte(dest+startIdx+56,8);
|
||||
if ( checkCalc != 0xA8 ) return -5;
|
||||
if (*size != 64) return -6;
|
||||
//return start position
|
||||
return (int) startIdx;
|
||||
}
|
||||
|
||||
// by marshmellow
|
||||
|
@ -1033,63 +1073,20 @@ void psk2TOpsk1(uint8_t *BitStream, size_t size)
|
|||
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert)
|
||||
{
|
||||
//26 bit 40134 format (don't know other formats)
|
||||
int i;
|
||||
int long_wait=29;//29 leading zeros in format
|
||||
int start;
|
||||
int first = 0;
|
||||
int first2 = 0;
|
||||
int bitCnt = 0;
|
||||
int ii;
|
||||
// Finding the start of a UID
|
||||
for (start = 0; start <= *size - 250; start++) {
|
||||
first = bitStream[start];
|
||||
for (i = start; i < start + long_wait; i++) {
|
||||
if (bitStream[i] != first) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (start + long_wait)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start == *size - 250 + 1) {
|
||||
// did not find start sequence
|
||||
return -1;
|
||||
}
|
||||
// Inverting signal if needed
|
||||
if (first == 1) {
|
||||
for (i = start; i < *size; i++) {
|
||||
bitStream[i] = !bitStream[i];
|
||||
}
|
||||
*invert = 1;
|
||||
}else *invert=0;
|
||||
uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
|
||||
uint8_t preamble_i[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0};
|
||||
size_t startidx = 0;
|
||||
if (!preambleSearch(bitStream, preamble, sizeof(preamble), size, &startidx)){
|
||||
// if didn't find preamble try again inverting
|
||||
if (!preambleSearch(bitStream, preamble_i, sizeof(preamble_i), size, &startidx)) return -1;
|
||||
*invert ^= 1;
|
||||
}
|
||||
if (*size != 64 && *size != 224) return -2;
|
||||
if (*invert==1)
|
||||
for (size_t i = startidx; i < *size; i++)
|
||||
bitStream[i] ^= 1;
|
||||
|
||||
int iii;
|
||||
//found start once now test length by finding next one
|
||||
for (ii=start+29; ii <= *size - 250; ii++) {
|
||||
first2 = bitStream[ii];
|
||||
for (iii = ii; iii < ii + long_wait; iii++) {
|
||||
if (bitStream[iii] != first2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iii == (ii + long_wait)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ii== *size - 250 + 1){
|
||||
// did not find second start sequence
|
||||
return -2;
|
||||
}
|
||||
bitCnt=ii-start;
|
||||
|
||||
// Dumping UID
|
||||
i = start;
|
||||
for (ii = 0; ii < bitCnt; ii++) {
|
||||
bitStream[ii] = bitStream[i++];
|
||||
}
|
||||
*size=bitCnt;
|
||||
return 1;
|
||||
return (int) startidx;
|
||||
}
|
||||
|
||||
// by marshmellow - demodulate NRZ wave (both similar enough)
|
||||
|
|
|
@ -27,9 +27,9 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t f
|
|||
int DetectNRZClock(uint8_t dest[], size_t size, int clock);
|
||||
int DetectPSKClock(uint8_t dest[], size_t size, int clock);
|
||||
int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
|
||||
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
|
||||
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
|
||||
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
|
||||
uint32_t manchesterEncode2Bytes(uint16_t datain);
|
||||
int ManchesterEncode(uint8_t *BitStream, size_t size);
|
||||
int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert);
|
||||
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr);
|
||||
|
@ -41,13 +41,15 @@ void psk1TOpsk2(uint8_t *BitStream, size_t size);
|
|||
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
|
||||
|
||||
//tag specific
|
||||
int FDXBdemodBI(uint8_t *dest, size_t *size);
|
||||
int AWIDdemodFSK(uint8_t *dest, size_t *size);
|
||||
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
|
||||
int FDXBdemodBI(uint8_t *dest, size_t *size);
|
||||
int gProxII_Demod(uint8_t BitStream[], size_t *size);
|
||||
int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
|
||||
int IOdemodFSK(uint8_t *dest, size_t size);
|
||||
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
int PyramiddemodFSK(uint8_t *dest, size_t *size);
|
||||
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
|
||||
int PyramiddemodFSK(uint8_t *dest, size_t *size);
|
||||
int VikingDemod_AM(uint8_t *dest, size_t *size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,23 +3,45 @@
|
|||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include "protocols.h"
|
||||
|
||||
// ATA55xx shared presets & routines
|
||||
uint32_t GetT55xxClockBit(uint32_t clock) {
|
||||
switch (clock) {
|
||||
case 128:
|
||||
return T55x7_BITRATE_RF_128;
|
||||
case 100:
|
||||
return T55x7_BITRATE_RF_100;
|
||||
case 64:
|
||||
return T55x7_BITRATE_RF_64;
|
||||
case 50:
|
||||
return T55x7_BITRATE_RF_50;
|
||||
case 40:
|
||||
return T55x7_BITRATE_RF_40;
|
||||
case 32:
|
||||
return T55x7_BITRATE_RF_32;
|
||||
case 16:
|
||||
return T55x7_BITRATE_RF_16;
|
||||
case 8:
|
||||
return T55x7_BITRATE_RF_8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ON_DEVICE
|
||||
#include "ui.h"
|
||||
#define prnt PrintAndLog
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// iclass / picopass chip config structures and shared routines
|
||||
typedef struct {
|
||||
uint8_t app_limit;
|
||||
uint8_t otp[2];
|
||||
uint8_t block_writelock;
|
||||
uint8_t chip_config;
|
||||
uint8_t mem_config;
|
||||
uint8_t eas;
|
||||
uint8_t fuses;
|
||||
}picopass_conf_block;
|
||||
|
||||
uint8_t app_limit; //[8]
|
||||
uint8_t otp[2]; //[9-10]
|
||||
uint8_t block_writelock;//[11]
|
||||
uint8_t chip_config; //[12]
|
||||
uint8_t mem_config; //[13]
|
||||
uint8_t eas; //[14]
|
||||
uint8_t fuses; //[15]
|
||||
} picopass_conf_block;
|
||||
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
|
@ -28,32 +50,17 @@ typedef struct {
|
|||
uint8_t key_d[8];
|
||||
uint8_t key_c[8];
|
||||
uint8_t app_issuer_area[8];
|
||||
} picopass_hdr;
|
||||
|
||||
}picopass_hdr;
|
||||
|
||||
|
||||
//#define prnt printf
|
||||
/*void prnt(char *fmt,...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vprintf(fmt, argptr);
|
||||
printf(" "); // cleaning prompt
|
||||
va_end(argptr);
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
uint8_t isset(uint8_t val, uint8_t mask)
|
||||
{
|
||||
uint8_t isset(uint8_t val, uint8_t mask) {
|
||||
return (val & mask);
|
||||
}
|
||||
|
||||
uint8_t notset(uint8_t val, uint8_t mask){
|
||||
uint8_t notset(uint8_t val, uint8_t mask) {
|
||||
return !(val & mask);
|
||||
}
|
||||
|
||||
void fuse_config(const picopass_hdr *hdr)
|
||||
{
|
||||
void fuse_config(const picopass_hdr *hdr) {
|
||||
uint8_t fuses = hdr->conf.fuses;
|
||||
|
||||
if (isset(fuses,FUSE_FPERS))prnt(" Mode: Personalization [Programmable]");
|
||||
|
@ -74,42 +81,68 @@ void fuse_config(const picopass_hdr *hdr)
|
|||
if( isset( fuses, FUSE_RA)) prnt(" RA: Read access enabled");
|
||||
else prnt(" RA: Read access not enabled");
|
||||
}
|
||||
void mem_config(const picopass_hdr *hdr)
|
||||
{
|
||||
uint8_t mem = hdr->conf.mem_config;
|
||||
if( isset (mem, 0x80)) prnt(" Mem: 16KBits (255 * 8 bytes)");
|
||||
else prnt(" Mem: 2 KBits ( 32 * 8 bytes)");
|
||||
|
||||
void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) {
|
||||
// mem-bit 5, mem-bit 7, chip-bit 4: defines chip type
|
||||
if(isset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
|
||||
*kb = 2;
|
||||
*app_areas = 2;
|
||||
*max_blk = 31;
|
||||
} else if(isset(chip_cfg, 0x10) && isset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
|
||||
*kb = 16;
|
||||
*app_areas = 2;
|
||||
*max_blk = 255; //16kb
|
||||
} else if(notset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
|
||||
*kb = 16;
|
||||
*app_areas = 16;
|
||||
*max_blk = 255; //16kb
|
||||
} else if(isset(chip_cfg, 0x10) && isset(mem_cfg, 0x80) && isset(mem_cfg, 0x20)) {
|
||||
*kb = 32;
|
||||
*app_areas = 3;
|
||||
*max_blk = 255; //16kb
|
||||
} else if(notset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && isset(mem_cfg, 0x20)) {
|
||||
*kb = 32;
|
||||
*app_areas = 17;
|
||||
*max_blk = 255; //16kb
|
||||
} else {
|
||||
*kb = 32;
|
||||
*app_areas = 2;
|
||||
*max_blk = 255;
|
||||
}
|
||||
}
|
||||
void applimit_config(const picopass_hdr *hdr)
|
||||
{
|
||||
|
||||
void mem_app_config(const picopass_hdr *hdr) {
|
||||
uint8_t mem = hdr->conf.mem_config;
|
||||
uint8_t chip = hdr->conf.chip_config;
|
||||
uint8_t applimit = hdr->conf.app_limit;
|
||||
prnt(" AA1: blocks 6-%d", applimit);
|
||||
prnt(" AA2: blocks %d-", (applimit+1));
|
||||
if (applimit < 6) applimit = 26;
|
||||
uint8_t kb = 2;
|
||||
uint8_t app_areas = 2;
|
||||
uint8_t max_blk = 31;
|
||||
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
|
||||
prnt(" Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem);
|
||||
prnt(" AA1: blocks 06-%02X", applimit);
|
||||
prnt(" AA2: blocks %02X-%02X", applimit+1, max_blk);
|
||||
}
|
||||
void print_picopass_info(const picopass_hdr *hdr)
|
||||
{
|
||||
void print_picopass_info(const picopass_hdr *hdr) {
|
||||
fuse_config(hdr);
|
||||
mem_config(hdr);
|
||||
applimit_config(hdr);
|
||||
mem_app_config(hdr);
|
||||
}
|
||||
void printIclassDumpInfo(uint8_t* iclass_dump)
|
||||
{
|
||||
// picopass_hdr hdr;
|
||||
// memcpy(&hdr, iclass_dump, sizeof(picopass_hdr));
|
||||
void printIclassDumpInfo(uint8_t* iclass_dump) {
|
||||
print_picopass_info((picopass_hdr *) iclass_dump);
|
||||
}
|
||||
|
||||
/*
|
||||
void test()
|
||||
{
|
||||
void test() {
|
||||
picopass_hdr hdr = {0x27,0xaf,0x48,0x01,0xf9,0xff,0x12,0xe0,0x12,0xff,0xff,0xff,0x7f,0x1f,0xff,0x3c};
|
||||
prnt("Picopass configuration:");
|
||||
print_picopass_info(&hdr);
|
||||
}
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char *argv[]) {
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
//ON_DEVICE
|
||||
|
|
|
@ -99,7 +99,7 @@ NXP/Philips CUSTOM COMMANDS
|
|||
#define ICLASS_CMD_CHECK 0x05
|
||||
#define ICLASS_CMD_DETECT 0x0F
|
||||
#define ICLASS_CMD_HALT 0x00
|
||||
#define ICLASS_CMD_UPDATE 0x87
|
||||
#define ICLASS_CMD_UPDATE 0x87
|
||||
#define ICLASS_CMD_ACT 0x8E
|
||||
#define ICLASS_CMD_READ4 0x06
|
||||
|
||||
|
@ -180,9 +180,25 @@ NXP/Philips CUSTOM COMMANDS
|
|||
#define ISO15693_READ_MULTI_SECSTATUS 0x2C
|
||||
|
||||
|
||||
#define ISO_14443A 0
|
||||
#define ICLASS 1
|
||||
#define ISO_14443B 2
|
||||
// Topaz command set:
|
||||
#define TOPAZ_REQA 0x26 // Request
|
||||
#define TOPAZ_WUPA 0x52 // WakeUp
|
||||
#define TOPAZ_RID 0x78 // Read ID
|
||||
#define TOPAZ_RALL 0x00 // Read All (all bytes)
|
||||
#define TOPAZ_READ 0x01 // Read (a single byte)
|
||||
#define TOPAZ_WRITE_E 0x53 // Write-with-erase (a single byte)
|
||||
#define TOPAZ_WRITE_NE 0x1a // Write-no-erase (a single byte)
|
||||
// additional commands for Dynamic Memory Model
|
||||
#define TOPAZ_RSEG 0x10 // Read segment
|
||||
#define TOPAZ_READ8 0x02 // Read (eight bytes)
|
||||
#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes)
|
||||
#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes)
|
||||
|
||||
|
||||
#define ISO_14443A 0
|
||||
#define ICLASS 1
|
||||
#define ISO_14443B 2
|
||||
#define TOPAZ 3
|
||||
|
||||
//-- Picopass fuses
|
||||
#define FUSE_FPERS 0x80
|
||||
|
@ -194,7 +210,60 @@ NXP/Philips CUSTOM COMMANDS
|
|||
#define FUSE_FPROD0 0x02
|
||||
#define FUSE_RA 0x01
|
||||
|
||||
|
||||
void printIclassDumpInfo(uint8_t* iclass_dump);
|
||||
void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb);
|
||||
|
||||
#endif // PROTOCOLS_H
|
||||
/* T55x7 configuration register definitions */
|
||||
#define T55x7_POR_DELAY 0x00000001
|
||||
#define T55x7_ST_TERMINATOR 0x00000008
|
||||
#define T55x7_PWD 0x00000010
|
||||
#define T55x7_MAXBLOCK_SHIFT 5
|
||||
#define T55x7_AOR 0x00000200
|
||||
#define T55x7_PSKCF_RF_2 0
|
||||
#define T55x7_PSKCF_RF_4 0x00000400
|
||||
#define T55x7_PSKCF_RF_8 0x00000800
|
||||
#define T55x7_MODULATION_DIRECT 0
|
||||
#define T55x7_MODULATION_PSK1 0x00001000
|
||||
#define T55x7_MODULATION_PSK2 0x00002000
|
||||
#define T55x7_MODULATION_PSK3 0x00003000
|
||||
#define T55x7_MODULATION_FSK1 0x00004000
|
||||
#define T55x7_MODULATION_FSK2 0x00005000
|
||||
#define T55x7_MODULATION_FSK1a 0x00006000
|
||||
#define T55x7_MODULATION_FSK2a 0x00007000
|
||||
#define T55x7_MODULATION_MANCHESTER 0x00008000
|
||||
#define T55x7_MODULATION_BIPHASE 0x00010000
|
||||
#define T55x7_MODULATION_DIPHASE 0x00018000
|
||||
#define T55x7_BITRATE_RF_8 0
|
||||
#define T55x7_BITRATE_RF_16 0x00040000
|
||||
#define T55x7_BITRATE_RF_32 0x00080000
|
||||
#define T55x7_BITRATE_RF_40 0x000C0000
|
||||
#define T55x7_BITRATE_RF_50 0x00100000
|
||||
#define T55x7_BITRATE_RF_64 0x00140000
|
||||
#define T55x7_BITRATE_RF_100 0x00180000
|
||||
#define T55x7_BITRATE_RF_128 0x001C0000
|
||||
|
||||
/* T5555 (Q5) configuration register definitions */
|
||||
#define T5555_ST_TERMINATOR 0x00000001
|
||||
#define T5555_MAXBLOCK_SHIFT 0x00000001
|
||||
#define T5555_MODULATION_MANCHESTER 0
|
||||
#define T5555_MODULATION_PSK1 0x00000010
|
||||
#define T5555_MODULATION_PSK2 0x00000020
|
||||
#define T5555_MODULATION_PSK3 0x00000030
|
||||
#define T5555_MODULATION_FSK1 0x00000040
|
||||
#define T5555_MODULATION_FSK2 0x00000050
|
||||
#define T5555_MODULATION_BIPHASE 0x00000060
|
||||
#define T5555_MODULATION_DIRECT 0x00000070
|
||||
#define T5555_INVERT_OUTPUT 0x00000080
|
||||
#define T5555_PSK_RF_2 0
|
||||
#define T5555_PSK_RF_4 0x00000100
|
||||
#define T5555_PSK_RF_8 0x00000200
|
||||
#define T5555_USE_PWD 0x00000400
|
||||
#define T5555_USE_AOR 0x00000800
|
||||
#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2
|
||||
#define T5555_FAST_WRITE 0x00004000
|
||||
#define T5555_PAGE_SELECT 0x00008000
|
||||
|
||||
uint32_t GetT55xxClockBit(uint32_t clock);
|
||||
|
||||
#endif
|
||||
// PROTOCOLS_H
|
||||
|
|
|
@ -5,7 +5,7 @@ clean:
|
|||
$(DELETE) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp
|
||||
$(DELETE) *.map *.ngc *.xrpt *.pcf *.rbt *_auto_* *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst xst
|
||||
|
||||
fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v
|
||||
fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v
|
||||
$(DELETE) $@
|
||||
$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr
|
||||
|
||||
|
|
BIN
fpga/fpga_hf.bit
BIN
fpga/fpga_hf.bit
Binary file not shown.
|
@ -17,6 +17,7 @@
|
|||
`include "hi_read_rx_xcorr.v"
|
||||
`include "hi_simulate.v"
|
||||
`include "hi_iso14443a.v"
|
||||
`include "hi_sniffer.v"
|
||||
`include "util.v"
|
||||
|
||||
module fpga_hf(
|
||||
|
@ -122,25 +123,36 @@ hi_iso14443a hisn(
|
|||
hi_simulate_mod_type
|
||||
);
|
||||
|
||||
hi_sniffer he(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
he_pwr_lo, he_pwr_hi, he_pwr_oe1, he_pwr_oe2, he_pwr_oe3, he_pwr_oe4,
|
||||
adc_d, he_adc_clk,
|
||||
he_ssp_frame, he_ssp_din, ssp_dout, he_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
he_dbg,
|
||||
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
|
||||
);
|
||||
|
||||
// Major modes:
|
||||
|
||||
// 000 -- HF reader, transmitting to tag; modulation depth selectable
|
||||
// 001 -- HF reader, receiving from tag, correlating as it goes; frequency selectable
|
||||
// 010 -- HF simulated tag
|
||||
// 011 -- HF ISO14443-A
|
||||
// 100 -- HF Snoop
|
||||
// 111 -- everything off
|
||||
|
||||
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, 1'b0, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, 1'b0, 1'b0, 1'b0);
|
||||
|
||||
// In all modes, let the ADC's outputs be enabled.
|
||||
assign adc_noe = 1'b0;
|
||||
|
|
57
fpga/hi_sniffer.v
Normal file
57
fpga/hi_sniffer.v
Normal file
|
@ -0,0 +1,57 @@
|
|||
module hi_sniffer(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
xcorr_is_848, snoop, xcorr_quarter_freq // not used.
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input xcorr_is_848, snoop, xcorr_quarter_freq; // not used.
|
||||
|
||||
// We are only snooping, all off.
|
||||
assign pwr_hi = 1'b0;
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_oe1 = 1'b0;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
assign pwr_oe3 = 1'b0;
|
||||
assign pwr_oe4 = 1'b0;
|
||||
|
||||
reg ssp_frame;
|
||||
reg [7:0] adc_d_out = 8'd0;
|
||||
reg [2:0] ssp_cnt = 3'd0;
|
||||
|
||||
assign adc_clk = ck_1356meg;
|
||||
assign ssp_clk = ~ck_1356meg;
|
||||
|
||||
always @(posedge ssp_clk)
|
||||
begin
|
||||
if(ssp_cnt[2:0] == 3'd7)
|
||||
ssp_cnt[2:0] <= 3'd0;
|
||||
else
|
||||
ssp_cnt <= ssp_cnt + 1;
|
||||
|
||||
if(ssp_cnt[2:0] == 3'b000) // set frame length
|
||||
begin
|
||||
adc_d_out[7:0] <= adc_d;
|
||||
ssp_frame <= 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]};
|
||||
ssp_frame <= 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
assign ssp_din = adc_d_out[0];
|
||||
|
||||
endmodule
|
|
@ -26,14 +26,15 @@ typedef struct {
|
|||
} __attribute__((__packed__)) iso14a_card_select_t;
|
||||
|
||||
typedef enum ISO14A_COMMAND {
|
||||
ISO14A_CONNECT = 1,
|
||||
ISO14A_NO_DISCONNECT = 2,
|
||||
ISO14A_APDU = 4,
|
||||
ISO14A_RAW = 8,
|
||||
ISO14A_REQUEST_TRIGGER = 0x10,
|
||||
ISO14A_APPEND_CRC = 0x20,
|
||||
ISO14A_SET_TIMEOUT = 0x40,
|
||||
ISO14A_NO_SELECT = 0x80
|
||||
ISO14A_CONNECT = (1 << 0),
|
||||
ISO14A_NO_DISCONNECT = (1 << 1),
|
||||
ISO14A_APDU = (1 << 2),
|
||||
ISO14A_RAW = (1 << 3),
|
||||
ISO14A_REQUEST_TRIGGER = (1 << 4),
|
||||
ISO14A_APPEND_CRC = (1 << 5),
|
||||
ISO14A_SET_TIMEOUT = (1 << 6),
|
||||
ISO14A_NO_SELECT = (1 << 7),
|
||||
ISO14A_TOPAZMODE = (1 << 8)
|
||||
} iso14a_command_t;
|
||||
|
||||
#endif // _MIFARE_H_
|
||||
|
|
|
@ -85,7 +85,7 @@ typedef struct{
|
|||
#define CMD_INDALA_CLONE_TAG_L 0x0213
|
||||
#define CMD_T55XX_READ_BLOCK 0x0214
|
||||
#define CMD_T55XX_WRITE_BLOCK 0x0215
|
||||
#define CMD_T55XX_READ_TRACE 0x0216
|
||||
#define CMD_T55XX_RESET_READ 0x0216
|
||||
#define CMD_PCF7931_READ 0x0217
|
||||
#define CMD_PCF7931_WRITE 0x0222
|
||||
#define CMD_EM4X_READ_WORD 0x0218
|
||||
|
@ -99,6 +99,7 @@ typedef struct{
|
|||
#define CMD_ASK_SIM_TAG 0x021F
|
||||
#define CMD_PSK_SIM_TAG 0x0220
|
||||
#define CMD_AWID_DEMOD_FSK 0x0221
|
||||
#define CMD_T55XX_WAKEUP 0x0224
|
||||
|
||||
|
||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
@ -133,12 +134,17 @@ typedef struct{
|
|||
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
|
||||
#define CMD_EPA_PACE_REPLAY 0x038B
|
||||
|
||||
#define CMD_ICLASS_READCHECK 0x038F
|
||||
#define CMD_ICLASS_CLONE 0x0390
|
||||
#define CMD_ICLASS_DUMP 0x0391
|
||||
#define CMD_SNOOP_ICLASS 0x0392
|
||||
#define CMD_SIMULATE_TAG_ICLASS 0x0393
|
||||
#define CMD_READER_ICLASS 0x0394
|
||||
#define CMD_READER_ICLASS_REPLAY 0x0395
|
||||
#define CMD_ICLASS_ISO14443A_WRITE 0x0397
|
||||
#define CMD_ICLASS_READBLOCK 0x0396
|
||||
#define CMD_ICLASS_WRITEBLOCK 0x0397
|
||||
#define CMD_ICLASS_EML_MEMSET 0x0398
|
||||
#define CMD_ICLASS_AUTHENTICATION 0x0399
|
||||
|
||||
// For measurements of the antenna tuning
|
||||
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||
|
@ -193,6 +199,8 @@ typedef struct{
|
|||
#define CMD_MIFARE_DESFIRE_INFO 0x072d
|
||||
#define CMD_MIFARE_DESFIRE 0x072e
|
||||
|
||||
#define CMD_HF_SNIFFER 0x0800
|
||||
|
||||
#define CMD_UNKNOWN 0xFFFF
|
||||
|
||||
|
||||
|
@ -210,6 +218,7 @@ typedef struct{
|
|||
#define FLAG_ICLASS_READER_CONF 0x08
|
||||
#define FLAG_ICLASS_READER_AA 0x10
|
||||
#define FLAG_ICLASS_READER_ONE_TRY 0x20
|
||||
#define FLAG_ICLASS_READER_CEDITKEY 0x40
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue