mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-21 22:03:19 -07:00
fixing hf 15: implement hf 15 snoop
* rename hf 15 record to hf 15 snoop * speedup sampling / decoding: * new FPGA mode FPGA_HF_READER_RX_XCORR_AMPLITUDE implements amplitude(ci, cq) on FPGA * inlining the decoders in iso15693.c * inlining memcpy/memset in LogTrace() * giving up the moving correlator for SOF in Handle15693SamplesFromTag * decode more of EOF in Handle15693SamplesFromTag() * some refactoring
This commit is contained in:
parent
6b882a3918
commit
3de4a49416
16 changed files with 714 additions and 575 deletions
|
@ -36,8 +36,8 @@ static uint16_t BigBuf_hi = BIGBUF_SIZE;
|
|||
static uint8_t *emulator_memory = NULL;
|
||||
|
||||
// trace related variables
|
||||
static uint16_t traceLen = 0;
|
||||
int tracing = 1; //Last global one.. todo static?
|
||||
static uint32_t traceLen = 0;
|
||||
static bool tracing = true;
|
||||
|
||||
// get the address of BigBuf
|
||||
uint8_t *BigBuf_get_addr(void)
|
||||
|
@ -66,7 +66,7 @@ void BigBuf_Clear(void)
|
|||
// clear ALL of BigBuf
|
||||
void BigBuf_Clear_ext(bool verbose)
|
||||
{
|
||||
memset(BigBuf,0,BIGBUF_SIZE);
|
||||
memset(BigBuf, 0, BIGBUF_SIZE);
|
||||
if (verbose)
|
||||
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ void BigBuf_Clear_EM(void){
|
|||
|
||||
void BigBuf_Clear_keep_EM(void)
|
||||
{
|
||||
memset(BigBuf,0,BigBuf_hi);
|
||||
memset(BigBuf, 0, BigBuf_hi);
|
||||
}
|
||||
|
||||
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
|
||||
|
@ -162,8 +162,8 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
|||
|
||||
uint8_t *trace = BigBuf_get_addr();
|
||||
|
||||
uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
|
||||
uint16_t duration = timestamp_end - timestamp_start;
|
||||
uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
|
||||
uint32_t duration = timestamp_end - timestamp_start;
|
||||
|
||||
// Return when trace is full
|
||||
uint16_t max_traceLen = BigBuf_max_traceLen();
|
||||
|
@ -200,19 +200,23 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
|||
|
||||
// data bytes
|
||||
if (btBytes != NULL && iLen != 0) {
|
||||
memcpy(trace + traceLen, btBytes, iLen);
|
||||
for (int i = 0; i < iLen; i++) {
|
||||
trace[traceLen++] = *btBytes++;
|
||||
}
|
||||
}
|
||||
traceLen += iLen;
|
||||
|
||||
// parity bytes
|
||||
if (num_paritybytes != 0) {
|
||||
if (parity != NULL) {
|
||||
memcpy(trace + traceLen, parity, num_paritybytes);
|
||||
for (int i = 0; i < num_paritybytes; i++) {
|
||||
trace[traceLen++] = *parity++;
|
||||
}
|
||||
} else {
|
||||
memset(trace + traceLen, 0x00, num_paritybytes);
|
||||
for (int i = 0; i < num_paritybytes; i++) {
|
||||
trace[traceLen++] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
traceLen += num_paritybytes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -254,8 +258,9 @@ int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwP
|
|||
trace[traceLen++] = ((dwParity >> 24) & 0xff);
|
||||
trace[traceLen++] = iBits;
|
||||
|
||||
memcpy(trace + traceLen, btBytes, iLen);
|
||||
traceLen += iLen;
|
||||
for (int i = 0; i < iLen; i++) {
|
||||
trace[traceLen++] = *btBytes++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "legicrfsim.h"
|
||||
#include "hitag2.h"
|
||||
#include "hitagS.h"
|
||||
#include "iso15693.h"
|
||||
#include "lfsampling.h"
|
||||
#include "BigBuf.h"
|
||||
#include "mifareutil.h"
|
||||
|
@ -1105,8 +1106,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
|
||||
AcquireRawAdcSamplesIso15693();
|
||||
break;
|
||||
case CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693:
|
||||
RecordRawAdcSamplesIso15693();
|
||||
|
||||
case CMD_SNOOP_ISO_15693:
|
||||
SnoopIso15693();
|
||||
break;
|
||||
|
||||
case CMD_ISO_15693_COMMAND:
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
extern const uint8_t OddByteParity[256];
|
||||
extern int rsamples; // = 0;
|
||||
extern int tracing; // = TRUE;
|
||||
extern uint8_t trigger;
|
||||
|
||||
// This may be used (sparingly) to declare a function to be copied to
|
||||
|
@ -101,7 +100,6 @@ void RAMFUNC SnoopIso14443b(void);
|
|||
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
|
||||
|
||||
// Also used in iclass.c
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
|
||||
|
||||
void RAMFUNC SniffMifare(uint8_t param);
|
||||
|
@ -150,15 +148,6 @@ void OnSuccess();
|
|||
void OnError(uint8_t reason);
|
||||
|
||||
|
||||
/// iso15693.h
|
||||
void RecordRawAdcSamplesIso15693(void);
|
||||
void AcquireRawAdcSamplesIso15693(void);
|
||||
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
|
||||
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
|
||||
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
|
||||
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]); // send arbitrary commands from CLI - atrox
|
||||
void SetDebugIso15693(uint32_t flag);
|
||||
|
||||
/// iclass.h
|
||||
void RAMFUNC SnoopIClass(void);
|
||||
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
|
|
|
@ -61,6 +61,7 @@ void SetAdcMuxFor(uint32_t whichGpio);
|
|||
#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0)
|
||||
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
|
||||
#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2)
|
||||
#define FPGA_HF_READER_RX_XCORR_AMPLITUDE (1<<3)
|
||||
// Options for the HF simulated tag, how to modulate
|
||||
#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0)
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0)
|
||||
|
|
|
@ -751,12 +751,9 @@ void RAMFUNC SnoopIClass(void)
|
|||
|
||||
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,true)) break;
|
||||
//if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break;
|
||||
if(tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(Uart.output, Uart.byteCnt, parity);
|
||||
LogTrace(Uart.output,Uart.byteCnt, time_start, time_stop, parity, true);
|
||||
}
|
||||
|
||||
|
||||
/* And ready to receive another command. */
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
|
@ -779,11 +776,9 @@ void RAMFUNC SnoopIClass(void)
|
|||
rsamples = samples - Demod.samples;
|
||||
LED_B_ON();
|
||||
|
||||
if(tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(Demod.output, Demod.len, parity);
|
||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, false);
|
||||
}
|
||||
|
||||
// And ready to receive another response.
|
||||
memset(&Demod, 0, sizeof(Demod));
|
||||
|
@ -1322,7 +1317,6 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
|
|||
t2r_time = GetCountSspClk();
|
||||
}
|
||||
|
||||
if (tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(receivedCmd, len, parity);
|
||||
LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, true);
|
||||
|
@ -1331,12 +1325,10 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
|
|||
GetParity(trace_data, trace_data_size, parity);
|
||||
LogTrace(trace_data, trace_data_size, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, false);
|
||||
}
|
||||
if(!tracing) {
|
||||
if(!get_tracing()) {
|
||||
DbpString("Trace full");
|
||||
//break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Dbprintf("%x", cmdsRecvd);
|
||||
|
@ -1509,11 +1501,9 @@ void ReaderTransmitIClass(uint8_t* frame, int len)
|
|||
LED_A_ON();
|
||||
|
||||
// Store reader command in buffer
|
||||
if (tracing) {
|
||||
uint8_t par[MAX_PARITY_SIZE];
|
||||
GetParity(frame, len, par);
|
||||
LogTrace(frame, len, rsamples, rsamples, par, true);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1569,11 +1559,9 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer)
|
|||
int samples = 0;
|
||||
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return false;
|
||||
rsamples += samples;
|
||||
if (tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(receivedAnswer, Demod.len, parity);
|
||||
LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,false);
|
||||
}
|
||||
if(samples == 0) return false;
|
||||
return Demod.len;
|
||||
}
|
||||
|
@ -1715,7 +1703,7 @@ void ReaderIClass(uint8_t arg0) {
|
|||
// if only looking for one card try 2 times if we missed it the first time
|
||||
if (try_once && tryCnt > 2) break;
|
||||
tryCnt++;
|
||||
if(!tracing) {
|
||||
if(!get_tracing()) {
|
||||
DbpString("Trace full");
|
||||
break;
|
||||
}
|
||||
|
@ -1828,7 +1816,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
|||
|
||||
WDT_HIT();
|
||||
|
||||
if(!tracing) {
|
||||
if(!get_tracing()) {
|
||||
DbpString("Trace full");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1220,7 +1220,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
|||
EmSendPrecompiledCmd(p_response);
|
||||
}
|
||||
|
||||
if (!tracing) {
|
||||
if (!get_tracing()) {
|
||||
Dbprintf("Trace Full. Simulation stopped.");
|
||||
break;
|
||||
}
|
||||
|
@ -1619,9 +1619,7 @@ void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t
|
|||
LED_A_ON();
|
||||
|
||||
// Log reader command in trace buffer
|
||||
if (tracing) {
|
||||
LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, par, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1652,9 +1650,7 @@ void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
|
|||
static int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity)
|
||||
{
|
||||
if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return false;
|
||||
if (tracing) {
|
||||
LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false);
|
||||
}
|
||||
return Demod.len;
|
||||
}
|
||||
|
||||
|
@ -1662,9 +1658,7 @@ static int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t
|
|||
int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
|
||||
{
|
||||
if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) return false;
|
||||
if (tracing) {
|
||||
LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false);
|
||||
}
|
||||
return Demod.len;
|
||||
}
|
||||
|
||||
|
|
|
@ -386,10 +386,7 @@ void SimulateIso14443bTag(void)
|
|||
break;
|
||||
}
|
||||
|
||||
if (tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
LogTrace(receivedCmd, len, 0, 0, parity, true);
|
||||
}
|
||||
LogTrace(receivedCmd, len, 0, 0, NULL, true);
|
||||
|
||||
// Good, look at the command now.
|
||||
if ( (len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len) == 0)
|
||||
|
@ -463,10 +460,7 @@ void SimulateIso14443bTag(void)
|
|||
}
|
||||
|
||||
// trace the response:
|
||||
if (tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
LogTrace(resp, respLen, 0, 0, parity, false);
|
||||
}
|
||||
LogTrace(resp, respLen, 0, 0, NULL, false);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -763,9 +757,8 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
|
|||
|
||||
if (!quiet) Dbprintf("max behindby = %d, samples = %d, gotFrame = %d, Demod.len = %d, Demod.sumI = %d, Demod.sumQ = %d", maxBehindBy, samples, gotFrame, Demod.len, Demod.sumI, Demod.sumQ);
|
||||
//Tracing
|
||||
if (tracing && Demod.len > 0) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
LogTrace(Demod.output, Demod.len, 0, 0, parity, false);
|
||||
if (Demod.len > 0) {
|
||||
LogTrace(Demod.output, Demod.len, 0, 0, NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,10 +851,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
|
|||
{
|
||||
CodeIso14443bAsReader(cmd, len);
|
||||
TransmitFor14443b();
|
||||
if (tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
LogTrace(cmd,len, 0, 0, parity, true);
|
||||
}
|
||||
LogTrace(cmd,len, 0, 0, NULL, true);
|
||||
}
|
||||
|
||||
/* Sends an APDU to the tag
|
||||
|
@ -1153,7 +1143,6 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
upTo = dmaBuf;
|
||||
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
|
||||
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
|
||||
bool TagIsActive = false;
|
||||
bool ReaderIsActive = false;
|
||||
|
@ -1198,9 +1187,7 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
||||
if(Handle14443bUartBit(ci & 0x01)) {
|
||||
triggered = true;
|
||||
if(tracing) {
|
||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
||||
}
|
||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, NULL, true);
|
||||
/* And ready to receive another command. */
|
||||
UartReset();
|
||||
/* And also reset the demod code, which might have been */
|
||||
|
@ -1209,9 +1196,7 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
}
|
||||
if(Handle14443bUartBit(cq & 0x01)) {
|
||||
triggered = true;
|
||||
if(tracing) {
|
||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
||||
}
|
||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, NULL, true);
|
||||
/* And ready to receive another command. */
|
||||
UartReset();
|
||||
/* And also reset the demod code, which might have been */
|
||||
|
@ -1223,13 +1208,8 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
|
||||
if(!ReaderIsActive && triggered) { // no need to try decoding tag data if the reader is sending or not yet triggered
|
||||
if(Handle14443bSamplesDemod(ci/2, cq/2)) {
|
||||
|
||||
//Use samples as a time measurement
|
||||
if(tracing)
|
||||
{
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
LogTrace(Demod.output, Demod.len, samples, samples, parity, false);
|
||||
}
|
||||
LogTrace(Demod.output, Demod.len, samples, samples, NULL, false);
|
||||
// And ready to receive another response.
|
||||
DemodReset();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
24
armsrc/iso15693.h
Normal file
24
armsrc/iso15693.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Piwi - October 2018
|
||||
//
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Routines to support ISO 15693.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __ISO15693_H
|
||||
#define __ISO15693_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void SnoopIso15693(void);
|
||||
void AcquireRawAdcSamplesIso15693(void);
|
||||
void ReaderIso15693(uint32_t parameter);
|
||||
void SimTagIso15693(uint32_t parameter, uint8_t *uid);
|
||||
void BruteforceIso15693Afi(uint32_t speed);
|
||||
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]);
|
||||
void SetDebugIso15693(uint32_t flag);
|
||||
|
||||
#endif
|
|
@ -264,7 +264,7 @@ 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) && (oddparity8(frame[j]) != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
|
||||
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
|
||||
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x!", frame[j]);
|
||||
} else {
|
||||
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
|
||||
}
|
||||
|
@ -281,14 +281,11 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
|||
}
|
||||
}
|
||||
|
||||
if(data_len == 0)
|
||||
{
|
||||
if(data_len == 0){
|
||||
sprintf(line[0],"<empty trace - possible error>");
|
||||
if (data_len == 0) {
|
||||
sprintf(line[0]," <empty trace - possible error>");
|
||||
}
|
||||
}
|
||||
//--- Draw the CRC column
|
||||
|
||||
//--- Draw the CRC column
|
||||
char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " "));
|
||||
|
||||
EndOfTransmissionTimestamp = timestamp + duration;
|
||||
|
|
|
@ -38,15 +38,54 @@
|
|||
#include "protocols.h"
|
||||
#include "cmdmain.h"
|
||||
|
||||
#define FrameSOF Iso15693FrameSOF
|
||||
#define Logic0 Iso15693Logic0
|
||||
#define Logic1 Iso15693Logic1
|
||||
#define FrameEOF Iso15693FrameEOF
|
||||
|
||||
#define Crc(data,datalen) Iso15693Crc(data,datalen)
|
||||
#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
|
||||
#define sprintUID(target,uid) Iso15693sprintUID(target,uid)
|
||||
|
||||
// SOF defined as
|
||||
// 1) Unmodulated time of 56.64us
|
||||
// 2) 24 pulses of 423.75khz
|
||||
// 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
|
||||
|
||||
static const int Iso15693FrameSOF[] = {
|
||||
-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, 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, 1, 1,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
static const int Iso15693Logic0[] = {
|
||||
1, 1, 1, 1,
|
||||
1, 1, 1, 1,
|
||||
-1, -1, -1, -1,
|
||||
-1, -1, -1, -1
|
||||
};
|
||||
static const int Iso15693Logic1[] = {
|
||||
-1, -1, -1, -1,
|
||||
-1, -1, -1, -1,
|
||||
1, 1, 1, 1,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
|
||||
// EOF defined as
|
||||
// 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
|
||||
// 2) 24 pulses of 423.75khz
|
||||
// 3) Unmodulated time of 56.64us
|
||||
|
||||
static const int Iso15693FrameEOF[] = {
|
||||
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, 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, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
// structure and database for uid -> tagtype lookups
|
||||
typedef struct {
|
||||
uint64_t uid;
|
||||
|
@ -293,8 +332,8 @@ int CmdHF15Demod(const char *Cmd)
|
|||
// First, correlate for SOF
|
||||
for (i = 0; i < 200; i++) {
|
||||
int corr = 0;
|
||||
for (j = 0; j < arraylen(FrameSOF); j += skip) {
|
||||
corr += FrameSOF[j] * GraphBuffer[i + (j / skip)];
|
||||
for (j = 0; j < arraylen(Iso15693FrameSOF); j += skip) {
|
||||
corr += Iso15693FrameSOF[j] * GraphBuffer[i + (j / skip)];
|
||||
}
|
||||
if (corr > max) {
|
||||
max = corr;
|
||||
|
@ -302,28 +341,28 @@ int CmdHF15Demod(const char *Cmd)
|
|||
}
|
||||
}
|
||||
PrintAndLog("SOF at %d, correlation %d", maxPos,
|
||||
max / (arraylen(FrameSOF) / skip));
|
||||
max / (arraylen(Iso15693FrameSOF) / skip));
|
||||
|
||||
i = maxPos + arraylen(FrameSOF) / skip;
|
||||
i = maxPos + arraylen(Iso15693FrameSOF) / skip;
|
||||
int k = 0;
|
||||
uint8_t outBuf[20];
|
||||
memset(outBuf, 0, sizeof(outBuf));
|
||||
uint8_t mask = 0x01;
|
||||
for (;;) {
|
||||
int corr0 = 0, corr00 = 0, corr01 = 0, corr1 = 0, corrEOF = 0;
|
||||
for(j = 0; j < arraylen(Logic0); j += skip) {
|
||||
corr0 += Logic0[j]*GraphBuffer[i+(j/skip)];
|
||||
for(j = 0; j < arraylen(Iso15693Logic0); j += skip) {
|
||||
corr0 += Iso15693Logic0[j]*GraphBuffer[i+(j/skip)];
|
||||
}
|
||||
corr01 = corr00 = corr0;
|
||||
for(j = 0; j < arraylen(Logic0); j += skip) {
|
||||
corr00 += Logic0[j]*GraphBuffer[i+arraylen(Logic0)/skip+(j/skip)];
|
||||
corr01 += Logic1[j]*GraphBuffer[i+arraylen(Logic0)/skip+(j/skip)];
|
||||
for(j = 0; j < arraylen(Iso15693Logic0); j += skip) {
|
||||
corr00 += Iso15693Logic0[j]*GraphBuffer[i+arraylen(Iso15693Logic0)/skip+(j/skip)];
|
||||
corr01 += Iso15693Logic1[j]*GraphBuffer[i+arraylen(Iso15693Logic0)/skip+(j/skip)];
|
||||
}
|
||||
for(j = 0; j < arraylen(Logic1); j += skip) {
|
||||
corr1 += Logic1[j]*GraphBuffer[i+(j/skip)];
|
||||
for(j = 0; j < arraylen(Iso15693Logic1); j += skip) {
|
||||
corr1 += Iso15693Logic1[j]*GraphBuffer[i+(j/skip)];
|
||||
}
|
||||
for(j = 0; j < arraylen(FrameEOF); j += skip) {
|
||||
corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)];
|
||||
for(j = 0; j < arraylen(Iso15693FrameEOF); j += skip) {
|
||||
corrEOF += Iso15693FrameEOF[j]*GraphBuffer[i+(j/skip)];
|
||||
}
|
||||
// Even things out by the length of the target waveform.
|
||||
corr00 *= 2;
|
||||
|
@ -335,17 +374,17 @@ int CmdHF15Demod(const char *Cmd)
|
|||
PrintAndLog("EOF at %d", i);
|
||||
break;
|
||||
} else if (corr1 > corr0) {
|
||||
i += arraylen(Logic1) / skip;
|
||||
i += arraylen(Iso15693Logic1) / skip;
|
||||
outBuf[k] |= mask;
|
||||
} else {
|
||||
i += arraylen(Logic0) / skip;
|
||||
i += arraylen(Iso15693Logic0) / skip;
|
||||
}
|
||||
mask <<= 1;
|
||||
if (mask == 0) {
|
||||
k++;
|
||||
mask = 0x01;
|
||||
}
|
||||
if ((i + (int)arraylen(FrameEOF)) >= GraphTraceLen) {
|
||||
if ((i + (int)arraylen(Iso15693FrameEOF)) >= GraphTraceLen) {
|
||||
PrintAndLog("ran off end!");
|
||||
break;
|
||||
}
|
||||
|
@ -374,10 +413,9 @@ int CmdHF15Read(const char *Cmd)
|
|||
}
|
||||
|
||||
// Record Activity without enabling carrier
|
||||
// TODO: currently it DOES enable the carrier
|
||||
int CmdHF15Record(const char *Cmd)
|
||||
int CmdHF15Snoop(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693};
|
||||
UsbCommand c = {CMD_SNOOP_ISO_15693};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -514,7 +552,7 @@ static command_t CommandTable15[] =
|
|||
{"help", CmdHF15Help, 1, "This help"},
|
||||
{"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"},
|
||||
{"read", CmdHF15Read, 0, "Read HF tag (ISO 15693)"},
|
||||
{"record", CmdHF15Record, 0, "Record Samples (ISO 15693)"}, // atrox
|
||||
{"snoop", CmdHF15Snoop, 0, "Eavesdrop ISO 15693 communications"},
|
||||
{"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"},
|
||||
{"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"},
|
||||
{"cmd", CmdHF15Cmd, 0, "Send direct commands to ISO15693 tag"},
|
||||
|
|
|
@ -14,57 +14,4 @@ int Iso15693AddCrc(uint8_t *req, int n);
|
|||
char* Iso15693sprintUID(char *target,uint8_t *uid);
|
||||
unsigned short iclass_crc16(char *data_p, unsigned short length);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Map a sequence of octets (~layer 2 command) into the set of bits to feed
|
||||
// to the FPGA, to transmit that command to the tag.
|
||||
// Mode: highspeed && one subcarrier (ASK)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// The sampling rate is 106.353 ksps/s, for T = 18.8 us
|
||||
|
||||
// SOF defined as
|
||||
// 1) Unmodulated time of 56.64us
|
||||
// 2) 24 pulses of 423.75khz
|
||||
// 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
|
||||
|
||||
static const int Iso15693FrameSOF[] = {
|
||||
-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, 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, 1, 1,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
static const int Iso15693Logic0[] = {
|
||||
1, 1, 1, 1,
|
||||
1, 1, 1, 1,
|
||||
-1, -1, -1, -1,
|
||||
-1, -1, -1, -1
|
||||
};
|
||||
static const int Iso15693Logic1[] = {
|
||||
-1, -1, -1, -1,
|
||||
-1, -1, -1, -1,
|
||||
1, 1, 1, 1,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
|
||||
// EOF defined as
|
||||
// 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
|
||||
// 2) 24 pulses of 423.75khz
|
||||
// 3) Unmodulated time of 56.64us
|
||||
|
||||
static const int Iso15693FrameEOF[] = {
|
||||
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, 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, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
BIN
fpga/fpga_hf.bit
BIN
fpga/fpga_hf.bit
Binary file not shown.
|
@ -75,6 +75,8 @@ wire hi_read_rx_xcorr_848 = conf_word[0];
|
|||
wire hi_read_rx_xcorr_snoop = conf_word[1];
|
||||
// divide subcarrier frequency by 4
|
||||
wire hi_read_rx_xcorr_quarter = conf_word[2];
|
||||
// send amplitude only instead of ci/cq pair
|
||||
wire hi_read_rx_xcorr_amplitude = conf_word[3];
|
||||
|
||||
// For the high-frequency simulated tag: what kind of modulation to use.
|
||||
wire [2:0] hi_simulate_mod_type = conf_word[2:0];
|
||||
|
@ -102,7 +104,7 @@ hi_read_rx_xcorr hrxc(
|
|||
hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
hrxc_dbg,
|
||||
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
|
||||
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter, hi_read_rx_xcorr_amplitude
|
||||
);
|
||||
|
||||
hi_simulate hs(
|
||||
|
|
|
@ -10,7 +10,7 @@ module hi_read_rx_xcorr(
|
|||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
xcorr_is_848, snoop, xcorr_quarter_freq
|
||||
xcorr_is_848, snoop, xcorr_quarter_freq, hi_read_rx_xcorr_amplitude
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
|
@ -20,7 +20,7 @@ module hi_read_rx_xcorr(
|
|||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input xcorr_is_848, snoop, xcorr_quarter_freq;
|
||||
input xcorr_is_848, snoop, xcorr_quarter_freq, hi_read_rx_xcorr_amplitude;
|
||||
|
||||
// Carrier is steady on through this, unless we're snooping.
|
||||
assign pwr_hi = ck_1356megb & (~snoop);
|
||||
|
@ -83,11 +83,46 @@ reg signed [13:0] corr_q_accum;
|
|||
// we will report maximum 8 significant bits
|
||||
reg signed [7:0] corr_i_out;
|
||||
reg signed [7:0] corr_q_out;
|
||||
|
||||
// clock and frame signal for communication to ARM
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
|
||||
|
||||
|
||||
// the amplitude of the subcarrier is sqrt(ci^2 + cq^2).
|
||||
// approximate by amplitude = max(|ci|,|cq|) + 1/2*min(|ci|,|cq|)
|
||||
reg [13:0] corr_amplitude, abs_ci, abs_cq, max_ci_cq, min_ci_cq;
|
||||
|
||||
|
||||
always @(corr_i_accum or corr_q_accum)
|
||||
begin
|
||||
if (corr_i_accum[13] == 1'b0)
|
||||
abs_ci <= corr_i_accum;
|
||||
else
|
||||
abs_ci <= -corr_i_accum;
|
||||
|
||||
if (corr_q_accum[13] == 1'b0)
|
||||
abs_cq <= corr_q_accum;
|
||||
else
|
||||
abs_cq <= -corr_q_accum;
|
||||
|
||||
if (abs_ci > abs_cq)
|
||||
begin
|
||||
max_ci_cq <= abs_ci;
|
||||
min_ci_cq <= abs_cq;
|
||||
end
|
||||
else
|
||||
begin
|
||||
max_ci_cq <= abs_cq;
|
||||
min_ci_cq <= abs_ci;
|
||||
end
|
||||
|
||||
corr_amplitude <= max_ci_cq + min_ci_cq/2;
|
||||
|
||||
end
|
||||
|
||||
|
||||
// The subcarrier reference signals
|
||||
reg subcarrier_I;
|
||||
reg subcarrier_Q;
|
||||
|
@ -111,17 +146,26 @@ begin
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
// ADC data appears on the rising edge, so sample it on the falling edge
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
// These are the correlators: we correlate against in-phase and quadrature
|
||||
// versions of our reference signal, and keep the (signed) result to
|
||||
// send out later over the SSP.
|
||||
// versions of our reference signal, and keep the (signed) results or the
|
||||
// resulting amplitude to send out later over the SSP.
|
||||
if(corr_i_cnt == 6'd0)
|
||||
begin
|
||||
if(snoop)
|
||||
begin
|
||||
// Send 7 most significant bits of tag signal (signed), plus 1 bit reader signal
|
||||
if (hi_read_rx_xcorr_amplitude)
|
||||
begin
|
||||
// send amplitude plus 2 bits reader signal
|
||||
corr_i_out <= corr_amplitude[13:6];
|
||||
corr_q_out <= {corr_amplitude[5:0], after_hysteresis_prev_prev, after_hysteresis_prev};
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal
|
||||
if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111)
|
||||
corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev};
|
||||
else // truncate to maximum value
|
||||
|
@ -129,6 +173,7 @@ begin
|
|||
corr_i_out <= {7'b0111111, after_hysteresis_prev_prev};
|
||||
else
|
||||
corr_i_out <= {7'b1000000, after_hysteresis_prev_prev};
|
||||
// Send 7 most significant bits of quadrature phase tag signal (signed), plus 1 bit reader signal
|
||||
if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111)
|
||||
corr_q_out <= {corr_q_accum[11:5], after_hysteresis_prev};
|
||||
else // truncate to maximum value
|
||||
|
@ -136,11 +181,19 @@ begin
|
|||
corr_q_out <= {7'b0111111, after_hysteresis_prev};
|
||||
else
|
||||
corr_q_out <= {7'b1000000, after_hysteresis_prev};
|
||||
after_hysteresis_prev_prev <= after_hysteresis;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Send 8 bits of tag signal
|
||||
if (hi_read_rx_xcorr_amplitude)
|
||||
begin
|
||||
// send amplitude
|
||||
corr_i_out <= {2'b00, corr_amplitude[13:8]};
|
||||
corr_q_out <= corr_amplitude[7:0];
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Send 8 bits of in phase tag signal
|
||||
if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111)
|
||||
corr_i_out <= corr_i_accum[11:4];
|
||||
else // truncate to maximum value
|
||||
|
@ -148,6 +201,7 @@ begin
|
|||
corr_i_out <= 8'b01111111;
|
||||
else
|
||||
corr_i_out <= 8'b10000000;
|
||||
// Send 8 bits of quadrature phase tag signal
|
||||
if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111)
|
||||
corr_q_out <= corr_q_accum[11:4];
|
||||
else // truncate to maximum value
|
||||
|
@ -156,6 +210,10 @@ begin
|
|||
else
|
||||
corr_q_out <= 8'b10000000;
|
||||
end
|
||||
end
|
||||
|
||||
// for each Q/I pair report two reader signal samples when sniffing. Store the 1st.
|
||||
after_hysteresis_prev_prev <= after_hysteresis;
|
||||
// Initialize next correlation.
|
||||
// Both I and Q reference signals are high when corr_i_nct == 0. Therefore need to accumulate.
|
||||
corr_i_accum <= $signed({1'b0,adc_d});
|
||||
|
@ -172,16 +230,16 @@ begin
|
|||
corr_q_accum <= corr_q_accum + $signed({1'b0,adc_d});
|
||||
else
|
||||
corr_q_accum <= corr_q_accum - $signed({1'b0,adc_d});
|
||||
|
||||
end
|
||||
|
||||
// for each Q/I pair report two reader signal samples when sniffing
|
||||
// for each Q/I pair report two reader signal samples when sniffing. Store the 2nd.
|
||||
if(corr_i_cnt == 6'd32)
|
||||
after_hysteresis_prev <= after_hysteresis;
|
||||
|
||||
// Then the result from last time is serialized and send out to the ARM.
|
||||
// We get one report each cycle, and each report is 16 bits, so the
|
||||
// ssp_clk should be the adc_clk divided by 64/16 = 4.
|
||||
// ssp_clk frequency = 13,56MHz / 4 = 3.39MHz
|
||||
|
||||
if(corr_i_cnt[1:0] == 2'b10)
|
||||
ssp_clk <= 1'b0;
|
||||
|
|
|
@ -122,7 +122,7 @@ typedef struct{
|
|||
#define CMD_ISO_14443B_COMMAND 0x0305
|
||||
#define CMD_READER_ISO_15693 0x0310
|
||||
#define CMD_SIMTAG_ISO_15693 0x0311
|
||||
#define CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 0x0312
|
||||
#define CMD_SNOOP_ISO_15693 0x0312
|
||||
#define CMD_ISO_15693_COMMAND 0x0313
|
||||
#define CMD_ISO_15693_COMMAND_DONE 0x0314
|
||||
#define CMD_ISO_15693_FIND_AFI 0x0315
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue