mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-09 03:00:07 -04:00
Merge branch 'fpga'
* fpga: (139 commits) readermac fix SKIPREADLINE compilation err less cpu usage, thanks @mwalker33 iclass replay params hf iclass replay textual hf iclass replay works. A bit bad in not reading AA2. Assumes a KD mac iclass sniff now works chg: trace list color in list send arguments to standalone mode simlper select textual iceclass reader attack mode to save unique files add: mem spiffs wipe dump size bugs iclass sniff, still too slow fix the config trigger remove some extras pm3other compilation error mplicit declaration of function "Csprintf" style and trying a long timeout ...
This commit is contained in:
186
armsrc/BigBuf.c
186
armsrc/BigBuf.c
@@ -22,29 +22,56 @@ extern uint8_t _stack_start, __bss_end__;
|
||||
static uint8_t *BigBuf = &__bss_end__;
|
||||
|
||||
/* BigBuf memory layout:
|
||||
Pointer to highest available memory: BigBuf_hi
|
||||
high BigBuf_size
|
||||
reserved = BigBuf_malloc() subtracts amount from BigBuf_hi,
|
||||
Pointer to highest available memory: s_bigbuf_hi
|
||||
high s_bigbuf_size
|
||||
reserved = BigBuf_malloc() subtracts amount from s_bigbuf_hi,
|
||||
low 0x00
|
||||
*/
|
||||
|
||||
static uint32_t BigBuf_size = 0;
|
||||
static uint32_t s_bigbuf_size = 0;
|
||||
|
||||
// High memory mark
|
||||
static uint32_t BigBuf_hi = 0;
|
||||
static uint32_t s_bigbuf_hi = 0;
|
||||
|
||||
// pointer to the emulator memory.
|
||||
static uint8_t *emulator_memory = NULL;
|
||||
|
||||
//=============================================================================
|
||||
// The ToSend buffer.
|
||||
// A buffer where we can queue things up to be sent through the FPGA, for
|
||||
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
|
||||
// is the order in which they go out on the wire.
|
||||
//=============================================================================
|
||||
static tosend_t toSend = {
|
||||
.max = -1,
|
||||
.bit = 8,
|
||||
.buf = NULL
|
||||
};
|
||||
//=============================================================================
|
||||
// The dmaBuf 16bit buffer.
|
||||
// A buffer where we recive IQ samples sent from the FPGA, for demodulating
|
||||
//=============================================================================
|
||||
static dmabuf16_t dma_16 = {
|
||||
.size = DMA_BUFFER_SIZE,
|
||||
.buf = NULL
|
||||
};
|
||||
// dmaBuf 8bit buffer
|
||||
static dmabuf8_t dma_8 = {
|
||||
.size = DMA_BUFFER_SIZE,
|
||||
.buf = NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
// trace related variables
|
||||
static uint32_t traceLen = 0;
|
||||
static uint32_t trace_len = 0;
|
||||
static bool tracing = true;
|
||||
|
||||
// compute the available size for BigBuf
|
||||
void BigBuf_initialize(void) {
|
||||
BigBuf_size = (uint32_t)&_stack_start - (uint32_t)&__bss_end__;
|
||||
BigBuf_hi = BigBuf_size;
|
||||
traceLen = 0;
|
||||
s_bigbuf_size = (uint32_t)&_stack_start - (uint32_t)&__bss_end__;
|
||||
s_bigbuf_hi = s_bigbuf_size;
|
||||
trace_len = 0;
|
||||
}
|
||||
|
||||
// get the address of BigBuf
|
||||
@@ -53,7 +80,7 @@ uint8_t *BigBuf_get_addr(void) {
|
||||
}
|
||||
|
||||
uint32_t BigBuf_get_size(void) {
|
||||
return BigBuf_size;
|
||||
return s_bigbuf_size;
|
||||
}
|
||||
|
||||
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
|
||||
@@ -64,6 +91,11 @@ uint8_t *BigBuf_get_EM_addr(void) {
|
||||
|
||||
return emulator_memory;
|
||||
}
|
||||
/*
|
||||
uint32_t BigBuf_get_EM_size(void) {
|
||||
return CARD_MEMORY_SIZE;
|
||||
}
|
||||
*/
|
||||
|
||||
// clear ALL of BigBuf
|
||||
void BigBuf_Clear(void) {
|
||||
@@ -72,9 +104,9 @@ void BigBuf_Clear(void) {
|
||||
|
||||
// clear ALL of BigBuf
|
||||
void BigBuf_Clear_ext(bool verbose) {
|
||||
memset(BigBuf, 0, BigBuf_size);
|
||||
memset(BigBuf, 0, s_bigbuf_size);
|
||||
if (verbose)
|
||||
Dbprintf("Buffer cleared (%i bytes)", BigBuf_size);
|
||||
Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size);
|
||||
}
|
||||
|
||||
void BigBuf_Clear_EM(void) {
|
||||
@@ -82,57 +114,66 @@ void BigBuf_Clear_EM(void) {
|
||||
}
|
||||
|
||||
void BigBuf_Clear_keep_EM(void) {
|
||||
memset(BigBuf, 0, BigBuf_hi);
|
||||
memset(BigBuf, 0, s_bigbuf_hi);
|
||||
}
|
||||
|
||||
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
|
||||
// at the beginning of BigBuf is always for traces/samples
|
||||
uint8_t *BigBuf_malloc(uint16_t chunksize) {
|
||||
if (BigBuf_hi < chunksize)
|
||||
if (s_bigbuf_hi < chunksize)
|
||||
return NULL; // no memory left
|
||||
|
||||
chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
|
||||
BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
|
||||
return (uint8_t *)BigBuf + BigBuf_hi;
|
||||
s_bigbuf_hi -= chunksize; // aligned to 4 Byte boundary
|
||||
return (uint8_t *)BigBuf + s_bigbuf_hi;
|
||||
}
|
||||
|
||||
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
|
||||
void BigBuf_free(void) {
|
||||
BigBuf_hi = BigBuf_size;
|
||||
s_bigbuf_hi = s_bigbuf_size;
|
||||
emulator_memory = NULL;
|
||||
// shouldn't this empty BigBuf also?
|
||||
toSend.buf = NULL;
|
||||
dma_16.buf = NULL;
|
||||
dma_8.buf = NULL;
|
||||
}
|
||||
|
||||
// free allocated chunks EXCEPT the emulator memory
|
||||
void BigBuf_free_keep_EM(void) {
|
||||
if (emulator_memory != NULL)
|
||||
BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
|
||||
s_bigbuf_hi = emulator_memory - (uint8_t *)BigBuf;
|
||||
else
|
||||
BigBuf_hi = BigBuf_size;
|
||||
s_bigbuf_hi = s_bigbuf_size;
|
||||
|
||||
// shouldn't this empty BigBuf also?
|
||||
toSend.buf = NULL;
|
||||
dma_16.buf = NULL;
|
||||
dma_8.buf = NULL;
|
||||
}
|
||||
|
||||
void BigBuf_print_status(void) {
|
||||
DbpString(_CYAN_("Memory"));
|
||||
Dbprintf(" BigBuf_size.............%d", BigBuf_size);
|
||||
Dbprintf(" Available memory........%d", BigBuf_hi);
|
||||
Dbprintf(" BigBuf_size.............%d", s_bigbuf_size);
|
||||
Dbprintf(" Available memory........%d", s_bigbuf_hi);
|
||||
DbpString(_CYAN_("Tracing"));
|
||||
Dbprintf(" tracing ................%d", tracing);
|
||||
Dbprintf(" traceLen ...............%d", traceLen);
|
||||
Dbprintf(" traceLen ...............%d", trace_len);
|
||||
|
||||
Dbprintf(" dma8 memory.............%d", dma_8.buf - BigBuf_get_addr());
|
||||
Dbprintf(" dma16 memory............%d", (uint8_t*)dma_16.buf - BigBuf_get_addr());
|
||||
Dbprintf(" toSend memory...........%d", toSend.buf - BigBuf_get_addr() );
|
||||
}
|
||||
|
||||
// return the maximum trace length (i.e. the unallocated size of BigBuf)
|
||||
uint16_t BigBuf_max_traceLen(void) {
|
||||
return BigBuf_hi;
|
||||
return s_bigbuf_hi;
|
||||
}
|
||||
|
||||
void clear_trace(void) {
|
||||
traceLen = 0;
|
||||
trace_len = 0;
|
||||
}
|
||||
|
||||
void set_tracelen(uint32_t value) {
|
||||
traceLen = value;
|
||||
trace_len = value;
|
||||
}
|
||||
|
||||
void set_tracing(bool enable) {
|
||||
@@ -148,7 +189,7 @@ bool get_tracing(void) {
|
||||
* @return
|
||||
*/
|
||||
uint32_t BigBuf_get_traceLen(void) {
|
||||
return traceLen;
|
||||
return trace_len;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,16 +199,18 @@ uint32_t BigBuf_get_traceLen(void) {
|
||||
annotation of commands/responses.
|
||||
**/
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) {
|
||||
if (!tracing) return false;
|
||||
if (tracing == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *trace = BigBuf_get_addr();
|
||||
tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + traceLen);
|
||||
tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + trace_len);
|
||||
|
||||
uint32_t num_paritybytes = (iLen - 1) / 8 + 1; // number of valid paritybytes in *parity
|
||||
|
||||
// Return when trace is full
|
||||
if (TRACELOG_HDR_LEN + iLen + num_paritybytes >= BigBuf_max_traceLen() - traceLen) {
|
||||
tracing = false; // don't trace any more
|
||||
if (TRACELOG_HDR_LEN + iLen + num_paritybytes >= BigBuf_max_traceLen() - trace_len) {
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -178,39 +221,48 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
||||
duration = (UINT32_MAX - timestamp_start) + timestamp_end;
|
||||
}
|
||||
|
||||
if (duration > 0x7FFF) {
|
||||
if (duration > 0xFFFF) {
|
||||
/*
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Error in LogTrace: duration too long for 15 bits encoding: 0x%08x start:0x%08x end:0x%08x", duration, timestamp_start, timestamp_end);
|
||||
Dbprintf("Forcing duration = 0");
|
||||
Dbprintf("Error in LogTrace: duration too long for 16 bits encoding: 0x%08x start: 0x%08x end: 0x%08x", duration, timestamp_start, timestamp_end);
|
||||
}
|
||||
*/
|
||||
duration = 0;
|
||||
}
|
||||
|
||||
|
||||
hdr->timestamp = timestamp_start;
|
||||
hdr->duration = duration;
|
||||
hdr->duration = duration & 0xFFFF;
|
||||
hdr->data_len = iLen;
|
||||
hdr->isResponse = !readerToTag;
|
||||
traceLen += TRACELOG_HDR_LEN;
|
||||
trace_len += TRACELOG_HDR_LEN;
|
||||
|
||||
// data bytes
|
||||
if (btBytes != NULL && iLen != 0) {
|
||||
memcpy(trace + traceLen, btBytes, iLen);
|
||||
memcpy(hdr->frame, btBytes, iLen);
|
||||
trace_len += iLen;
|
||||
}
|
||||
traceLen += iLen;
|
||||
|
||||
// parity bytes
|
||||
if (num_paritybytes != 0) {
|
||||
if (parity != NULL) {
|
||||
memcpy(trace + traceLen, parity, num_paritybytes);
|
||||
memcpy(trace + trace_len, parity, num_paritybytes);
|
||||
} else {
|
||||
memset(trace + traceLen, 0x00, num_paritybytes);
|
||||
memset(trace + trace_len, 0x00, num_paritybytes);
|
||||
}
|
||||
trace_len += num_paritybytes;
|
||||
}
|
||||
traceLen += num_paritybytes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t
|
||||
bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, uint8_t *parity, bool reader2tag) {
|
||||
uint32_t duration = ts_end - ts_start;
|
||||
duration /= 32;
|
||||
ts_end = ts_start + duration;
|
||||
return LogTrace(bytes, len, ts_start, ts_end, parity, reader2tag);
|
||||
}
|
||||
|
||||
|
||||
// Emulator memory
|
||||
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) {
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
@@ -221,3 +273,51 @@ uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) {
|
||||
Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get the address of the ToSend buffer. Allocate part of Bigbuf for it, if not yet done
|
||||
tosend_t *get_tosend(void) {
|
||||
|
||||
if (toSend.buf == NULL)
|
||||
toSend.buf = BigBuf_malloc(TOSEND_BUFFER_SIZE);
|
||||
|
||||
return &toSend;
|
||||
}
|
||||
|
||||
void tosend_reset(void) {
|
||||
toSend.max = -1;
|
||||
toSend.bit = 8;
|
||||
}
|
||||
|
||||
void tosend_stuffbit(int b) {
|
||||
if (toSend.bit >= 8) {
|
||||
toSend.max++;
|
||||
toSend.buf[toSend.max] = 0;
|
||||
toSend.bit = 0;
|
||||
}
|
||||
|
||||
if (b)
|
||||
toSend.buf[ toSend.max] |= (1 << (7 - toSend.bit));
|
||||
|
||||
toSend.bit++;
|
||||
|
||||
if (toSend.max >= TOSEND_BUFFER_SIZE) {
|
||||
toSend.bit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dmabuf16_t *get_dma16(void) {
|
||||
if (dma_16.buf == NULL)
|
||||
dma_16.buf = (uint16_t*)BigBuf_malloc(DMA_BUFFER_SIZE * sizeof(uint16_t));
|
||||
|
||||
return &dma_16;
|
||||
}
|
||||
|
||||
dmabuf8_t *get_dma8(void) {
|
||||
if (dma_8.buf == NULL)
|
||||
dma_8.buf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||
|
||||
return &dma_8;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC
|
||||
#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these
|
||||
#define CARD_MEMORY_SIZE 4096
|
||||
#define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!?
|
||||
#define DMA_BUFFER_SIZE 256
|
||||
|
||||
// 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits
|
||||
#define TOSEND_BUFFER_SIZE (9 * MAX_FRAME_SIZE + 1 + 1 + 2)
|
||||
|
||||
uint8_t *BigBuf_get_addr(void);
|
||||
uint32_t BigBuf_get_size(void);
|
||||
@@ -39,7 +42,34 @@ void clear_trace(void);
|
||||
void set_tracing(bool enable);
|
||||
void set_tracelen(uint32_t value);
|
||||
bool get_tracing(void);
|
||||
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||
bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, uint8_t *parity, bool reader2tag);
|
||||
|
||||
|
||||
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
|
||||
|
||||
|
||||
typedef struct {
|
||||
int max;
|
||||
int bit;
|
||||
uint8_t *buf;
|
||||
} tosend_t;
|
||||
|
||||
tosend_t *get_tosend(void);
|
||||
void tosend_reset(void);
|
||||
void tosend_stuffbit(int b);
|
||||
|
||||
typedef struct {
|
||||
uint16_t size;
|
||||
uint8_t *buf;
|
||||
} dmabuf8_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t size;
|
||||
uint16_t *buf;
|
||||
} dmabuf16_t;
|
||||
|
||||
dmabuf8_t *get_dma8(void);
|
||||
dmabuf16_t *get_dma16(void);
|
||||
#endif /* __BIGBUF_H */
|
||||
|
||||
@@ -30,7 +30,7 @@ SRC_ISO14443b = iso14443b.c
|
||||
SRC_FELICA = felica.c
|
||||
SRC_CRAPTO1 = crypto1.c des.c desfire_crypto.c mifaredesfire.c aes.c platform_util.c
|
||||
SRC_CRC = crc.c crc16.c crc32.c
|
||||
SRC_ICLASS = iclass.c optimized_cipher.c
|
||||
SRC_ICLASS = iclass.c optimized_cipherutils.c optimized_ikeys.c optimized_elite.c optimized_cipher.c
|
||||
SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c
|
||||
SRC_NFCBARCODE = thinfilm.c
|
||||
|
||||
@@ -79,7 +79,7 @@ endif
|
||||
include Standalone/Makefile.inc
|
||||
|
||||
#the FPGA bitstream files. Note: order matters!
|
||||
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
|
||||
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit fpga_felica.bit
|
||||
|
||||
#the lz4 source files required for decompressing the fpga config at run time
|
||||
SRC_LZ4 = lz4.c
|
||||
|
||||
@@ -44,6 +44,9 @@ define KNOWN_STANDALONE_DEFINITIONS
|
||||
| HF_COLIN | Mifare ultra fast sniff/sim/clone |
|
||||
| (RDV4 only) | - Colin Brigato |
|
||||
+----------------------------------------------------------+
|
||||
| HF_ICECLASS | Simulate HID iCLASS legacy ags |
|
||||
| (RDV4 only) | storing in flashmem |
|
||||
+----------------------------------------------------------+
|
||||
| HF_LEGIC | Read/simulate Legic Prime tags |
|
||||
| | storing in flashmem |
|
||||
+----------------------------------------------------------+
|
||||
@@ -59,9 +62,9 @@ define KNOWN_STANDALONE_DEFINITIONS
|
||||
endef
|
||||
|
||||
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN
|
||||
STANDALONE_MODES += HF_14ASNIFF HF_BOG HF_COLIN HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG
|
||||
STANDALONE_MODES += HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG
|
||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||
STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN
|
||||
STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
||||
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
|
||||
|
||||
@@ -57,7 +57,11 @@ endif
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_legic.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_MSDSAL
|
||||
# WITH_STANDALONE_HF_MSDSAL
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_MSDSAL,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_msdsal.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_ICECLASS
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_iceclass.c
|
||||
endif
|
||||
|
||||
512
armsrc/Standalone/hf_iceclass.c
Normal file
512
armsrc/Standalone/hf_iceclass.c
Normal file
@@ -0,0 +1,512 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Christian Herrmann, 2020
|
||||
//
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// main code for hf_iceclass by Iceman
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "spiffs.h"
|
||||
#include "iclass.h"
|
||||
#include "iso15693.h"
|
||||
#include "optimized_cipher.h"
|
||||
#include "pm3_cmd.h"
|
||||
#include "protocols.h"
|
||||
|
||||
|
||||
#define ICE_STATE_NONE 0
|
||||
#define ICE_STATE_FULLSIM 1
|
||||
#define ICE_STATE_ATTACK 2
|
||||
#define ICE_STATE_READER 3
|
||||
#define ICE_STATE_CONFIGCARD 4
|
||||
|
||||
// ====================================================
|
||||
// Select which standalone function to be active.
|
||||
// 4 possiblities. Uncomment the one you wanna use.
|
||||
|
||||
#define ICE_USE ICE_STATE_FULLSIM
|
||||
//#define ICE_USE ICE_STATE_ATTACK
|
||||
//#define ICE_USE ICE_STATE_READER
|
||||
//#define ICE_USE ICE_STATE_CONFIGCARD
|
||||
|
||||
// ====================================================
|
||||
|
||||
|
||||
#define NUM_CSNS 9
|
||||
#define MAC_RESPONSES_SIZE (16 * NUM_CSNS)
|
||||
#define HF_ICLASS_FULLSIM_ORIG_BIN "iceclass-orig.bin"
|
||||
#define HF_ICLASS_FULLSIM_MOD "iceclass-modified"
|
||||
#define HF_ICLASS_FULLSIM_MOD_BIN HF_ICLASS_FULLSIM_MOD".bin"
|
||||
#define HF_ICLASS_FULLSIM_MOD_EML HF_ICLASS_FULLSIM_MOD".eml"
|
||||
#define HF_ICLASS_ATTACK_BIN "iclass_mac_attack"
|
||||
|
||||
#define HF_ICLASS_CC_A "iceclass_cc_a.bin"
|
||||
#define HF_ICLASS_CC_B "iceclass_cc_b.bin"
|
||||
char* cc_files[] = { HF_ICLASS_CC_A, HF_ICLASS_CC_B };
|
||||
|
||||
|
||||
|
||||
// times in ssp_clk_cycles @ 3,3625MHz when acting as reader
|
||||
#ifndef DELAY_ICLASS_VICC_TO_VCD_READER
|
||||
#define DELAY_ICLASS_VICC_TO_VCD_READER DELAY_ISO15693_VICC_TO_VCD_READER
|
||||
#endif
|
||||
|
||||
#ifndef ICLASS_16KS_SIZE
|
||||
#define ICLASS_16KS_SIZE 0x100 * 8
|
||||
#endif
|
||||
|
||||
// iclass card descriptors
|
||||
char * card_types[] = {
|
||||
"PicoPass 16K / 16", // 000
|
||||
"PicoPass 32K with current book 16K / 16", // 001
|
||||
"Unknown Card Type!", // 010
|
||||
"Unknown Card Type!", // 011
|
||||
"PicoPass 2K", // 100
|
||||
"Unknown Card Type!", // 101
|
||||
"PicoPass 16K / 2", // 110
|
||||
"PicoPass 32K with current book 16K / 2", // 111
|
||||
};
|
||||
|
||||
uint8_t card_app2_limit[] = {
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x1f,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
};
|
||||
|
||||
static uint8_t aa2_key[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
static uint8_t legacy_aa1_key[] = {0xAE, 0xA6, 0x84, 0xA6, 0xDA, 0xB2, 0x32, 0x78};
|
||||
|
||||
static bool have_aa2(void) {
|
||||
return memcmp(aa2_key, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8);
|
||||
}
|
||||
|
||||
static uint8_t get_pagemap(const picopass_hdr *hdr) {
|
||||
return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
|
||||
}
|
||||
|
||||
static uint8_t csns[8 * NUM_CSNS] = {
|
||||
0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0
|
||||
};
|
||||
|
||||
static void download_instructions(uint8_t t) {
|
||||
DbpString("");
|
||||
switch (t) {
|
||||
case ICE_STATE_FULLSIM: {
|
||||
DbpString("The emulator memory was saved to SPIFFS");
|
||||
DbpString("1. " _YELLOW_("mem spiffs dump o " HF_ICLASS_FULLSIM_MOD_BIN " f " HF_ICLASS_FULLSIM_MOD" e"));
|
||||
DbpString("2. " _YELLOW_("hf iclass view f " HF_ICLASS_FULLSIM_MOD_BIN));
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_ATTACK: {
|
||||
DbpString("The collected data was saved to SPIFFS. The file names below may differ");
|
||||
DbpString("1. " _YELLOW_("mem spiffs tree"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump o " HF_ICLASS_ATTACK_BIN " f " HF_ICLASS_ATTACK_BIN));
|
||||
DbpString("3. " _YELLOW_("hf iclass loclass f " HF_ICLASS_ATTACK_BIN));
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_READER: {
|
||||
DbpString("The found tags was saved to SPIFFS");
|
||||
DbpString("1. " _YELLOW_("mem spiffs tree"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump h"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save to flash if file doesn't exist.
|
||||
// Write over file if size of flash file is less than new datalen
|
||||
static void save_to_flash(uint8_t *data, uint16_t datalen) {
|
||||
|
||||
rdv40_spiffs_lazy_mount();
|
||||
|
||||
char fn[SPIFFS_OBJ_NAME_LEN];
|
||||
sprintf(fn, "iclass-%02X%02X%02X%02X%02X%02X%02X%02X.bin",
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[4], data[5], data[6], data[7]
|
||||
);
|
||||
|
||||
int res;
|
||||
if (exists_in_spiffs(fn) == false) {
|
||||
res = rdv40_spiffs_write(fn, data, datalen, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
if (res == SPIFFS_OK) {
|
||||
Dbprintf("saved to " _GREEN_("%s"), fn);
|
||||
}
|
||||
} else {
|
||||
|
||||
// if already exist, see if saved file is smaller..
|
||||
uint32_t fsize = 0;
|
||||
res = rdv40_spiffs_stat(fn, &fsize, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
if (res == SPIFFS_OK) {
|
||||
|
||||
if (fsize < datalen) {
|
||||
res = rdv40_spiffs_write(fn, data, datalen, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
if (res == SPIFFS_OK) {
|
||||
Dbprintf("wrote over " _GREEN_("%s"), fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
}
|
||||
|
||||
static int fullsim_mode(void) {
|
||||
|
||||
rdv40_spiffs_lazy_mount();
|
||||
|
||||
SpinOff(0);
|
||||
uint8_t *emul = BigBuf_get_EM_addr();
|
||||
uint32_t fsize = size_in_spiffs(HF_ICLASS_FULLSIM_ORIG_BIN);
|
||||
int res = rdv40_spiffs_read_as_filetype(HF_ICLASS_FULLSIM_ORIG_BIN, emul, fsize, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
if (res == SPIFFS_OK) {
|
||||
Dbprintf("loaded " _GREEN_(HF_ICLASS_FULLSIM_ORIG_BIN) " (%u bytes)", fsize);
|
||||
}
|
||||
|
||||
iclass_simulate(ICLASS_SIM_MODE_FULL, 0 , false, NULL, NULL, NULL);
|
||||
|
||||
LED_B_ON();
|
||||
rdv40_spiffs_lazy_mount();
|
||||
res = rdv40_spiffs_write(HF_ICLASS_FULLSIM_MOD_BIN, emul, fsize, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
LED_B_OFF();
|
||||
if (res == SPIFFS_OK) {
|
||||
Dbprintf("wrote emulator memory to " _GREEN_(HF_ICLASS_FULLSIM_MOD_BIN));
|
||||
} else {
|
||||
Dbprintf(_RED_("error") " writing "HF_ICLASS_FULLSIM_MOD_BIN" to flash ( %d )", res);
|
||||
}
|
||||
|
||||
DbpString("-=[ exiting " _CYAN_("`full simulation`") " mode ]=-");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int reader_attack_mode(void) {
|
||||
|
||||
BigBuf_free();
|
||||
uint16_t mac_response_len = 0;
|
||||
uint8_t *mac_responses = BigBuf_malloc(MAC_RESPONSES_SIZE);
|
||||
|
||||
iclass_simulate(ICLASS_SIM_MODE_READER_ATTACK, NUM_CSNS, false, csns, mac_responses, &mac_response_len);
|
||||
|
||||
if (mac_response_len > 0) {
|
||||
|
||||
bool success = (mac_response_len == MAC_RESPONSES_SIZE);
|
||||
uint8_t num_mac = (mac_response_len >> 4);
|
||||
Dbprintf("%u out of %d MAC obtained [%s]", num_mac, NUM_CSNS, (success) ? _GREEN_("ok") : _RED_("fail"));
|
||||
|
||||
size_t dumplen = NUM_CSNS * 24;
|
||||
|
||||
uint8_t *dump = BigBuf_malloc(dumplen);
|
||||
if (dump == false) {
|
||||
Dbprintf("failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
// need zeroes for the EPURSE
|
||||
memset(dump, 0, dumplen);
|
||||
|
||||
for (uint8_t i = 0 ; i < NUM_CSNS ; i++) {
|
||||
//copy CSN
|
||||
memcpy(dump + (i * 24), csns + (i * 8), 8);
|
||||
//copy epurse
|
||||
memcpy(dump + (i * 24) + 8, mac_responses + (i * 16), 8);
|
||||
// NR_MAC (eight bytes from the response) ( 8b csn + 8b epurse == 16)
|
||||
memcpy(dump + (i * 24) + 16, mac_responses + (i * 16) + 8, 8);
|
||||
}
|
||||
|
||||
LED_B_ON();
|
||||
rdv40_spiffs_lazy_mount();
|
||||
|
||||
char fn[32];
|
||||
uint16_t p_namelen = strlen(HF_ICLASS_ATTACK_BIN);
|
||||
uint16_t num = 1;
|
||||
sprintf(fn, "%.*s%s", p_namelen, HF_ICLASS_ATTACK_BIN, ".bin");
|
||||
|
||||
while (exists_in_spiffs(fn)) {
|
||||
sprintf(fn, "%.*s-%u%s", p_namelen, HF_ICLASS_ATTACK_BIN, num, ".bin");
|
||||
num++;
|
||||
}
|
||||
int res = rdv40_spiffs_write(fn, dump, dumplen, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
LED_B_OFF();
|
||||
if (res == SPIFFS_OK) {
|
||||
Dbprintf("saved to " _GREEN_("%s"), fn);
|
||||
} else {
|
||||
Dbprintf(_RED_("error") " writing %s to flash ( %d )", fn, res);
|
||||
}
|
||||
}
|
||||
BigBuf_free();
|
||||
DbpString("-=[ exiting " _CYAN_("`reader attack`") " mode ]=-");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int reader_dump_mode(void) {
|
||||
|
||||
DbpString("this mode has no tracelog");
|
||||
if (have_aa2())
|
||||
DbpString("dumping of " _YELLOW_("AA2 enabled"));
|
||||
|
||||
for (;;) {
|
||||
|
||||
BigBuf_free();
|
||||
|
||||
uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE);
|
||||
memset(card_data, 0xFF, ICLASS_16KS_SIZE);
|
||||
|
||||
if (BUTTON_PRESS()) {
|
||||
DbpString("button pressed");
|
||||
break;
|
||||
}
|
||||
|
||||
// setup authenticate AA1
|
||||
iclass_auth_req_t auth = {
|
||||
.use_raw = false,
|
||||
.use_elite = false,
|
||||
.use_credit_key = false,
|
||||
.do_auth = true,
|
||||
.send_reply = false,
|
||||
};
|
||||
memcpy(auth.key, legacy_aa1_key, sizeof(auth.key));
|
||||
|
||||
Iso15693InitReader();
|
||||
set_tracing(false);
|
||||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
bool res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
switch_off();
|
||||
continue;
|
||||
}
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
// sanity check of CSN.
|
||||
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||
switch_off();
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
// get 3 config bits
|
||||
uint8_t type = (hdr->conf.chip_config & 0x10) >> 2;
|
||||
type |= (hdr->conf.mem_config & 0x80) >> 6;
|
||||
type |= (hdr->conf.mem_config & 0x20) >> 5;
|
||||
|
||||
Dbprintf(_GREEN_("%s") ", dumping...", card_types[type]);
|
||||
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
uint8_t app1_limit, app2_limit, start_block;
|
||||
|
||||
// tags configured for NON SECURE PAGE, acts different
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
app1_limit = card_app2_limit[type];
|
||||
app2_limit = 0;
|
||||
start_block = 3;
|
||||
} else {
|
||||
|
||||
app1_limit = hdr->conf.app_limit;
|
||||
app2_limit = card_app2_limit[type];
|
||||
start_block = 5;
|
||||
|
||||
res = authenticate_iclass_tag(&auth, hdr, &start_time, &eof_time, NULL);
|
||||
if (res == false) {
|
||||
switch_off();
|
||||
Dbprintf( _RED_("failed AA1 auth") ", skipping ");
|
||||
continue;
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
}
|
||||
|
||||
uint16_t dumped = 0;
|
||||
|
||||
// main read loop
|
||||
for (uint16_t i = start_block; i <= app1_limit; i++) {
|
||||
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) {
|
||||
dumped++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pagemap != PICOPASS_NON_SECURE_PAGEMODE && have_aa2()) {
|
||||
|
||||
// authenticate AA2
|
||||
auth.use_raw = false;
|
||||
auth.use_credit_key = true;
|
||||
memcpy(auth.key, aa2_key, sizeof(auth.key));
|
||||
|
||||
res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
|
||||
if (res) {
|
||||
|
||||
// sanity check of CSN.
|
||||
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||
switch_off();
|
||||
continue;
|
||||
}
|
||||
|
||||
res = authenticate_iclass_tag(&auth, hdr, &start_time, &eof_time, NULL);
|
||||
if (res) {
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
for (uint16_t i = app1_limit + 1; i <= app2_limit; i++) {
|
||||
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) {
|
||||
dumped++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DbpString(_RED_("failed AA2 auth"));
|
||||
}
|
||||
} else {
|
||||
DbpString(_RED_("failed selecting AA2"));
|
||||
|
||||
// sanity check of CSN.
|
||||
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||
switch_off();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch_off();
|
||||
save_to_flash(card_data, (start_block + dumped) * 8 );
|
||||
Dbprintf("%u bytes saved", (start_block + dumped) * 8);
|
||||
}
|
||||
DbpString("-=[ exiting " _CYAN_("`read & dump`") " mode ]=-");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_sim_mode(void) {
|
||||
|
||||
uint8_t *emul = BigBuf_get_EM_addr();
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
SpinOff(0);
|
||||
rdv40_spiffs_lazy_mount();
|
||||
uint32_t fsize = size_in_spiffs(cc_files[i]);
|
||||
int res = rdv40_spiffs_read_as_filetype(cc_files[i], emul, fsize, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
|
||||
if (res == SPIFFS_OK) {
|
||||
Dbprintf("loaded " _GREEN_("%s") " (%u bytes) to emulator memory", cc_files[i], fsize);
|
||||
iclass_simulate(ICLASS_SIM_MODE_FULL, 0 , false, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
DbpString("-=[ exiting " _CYAN_("`glitch & config`") " mode ]=-");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" HF iCLASS mode - aka iceCLASS (iceman)");
|
||||
}
|
||||
|
||||
void RunMod(void) {
|
||||
|
||||
uint8_t mode = ICE_USE;
|
||||
uint8_t *bb = BigBuf_get_EM_addr();
|
||||
if (bb[0] > 0 && bb[0] < 5) {
|
||||
mode = bb[0];
|
||||
}
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
StandAloneMode();
|
||||
Dbprintf(_YELLOW_("HF iCLASS mode a.k.a iceCLASS started"));
|
||||
|
||||
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (mode == ICE_STATE_NONE) break;
|
||||
if (data_available()) break;
|
||||
|
||||
int res;
|
||||
switch (mode) {
|
||||
|
||||
case ICE_STATE_FULLSIM: {
|
||||
DbpString("-=[ enter " _CYAN_("`full simulation`") " mode ]=-");
|
||||
|
||||
// Look for iCLASS dump file
|
||||
rdv40_spiffs_lazy_mount();
|
||||
if (exists_in_spiffs(HF_ICLASS_FULLSIM_ORIG_BIN) == false) {
|
||||
Dbprintf(_RED_("error") " " _YELLOW_(HF_ICLASS_FULLSIM_ORIG_BIN) " file missing");
|
||||
mode = ICE_STATE_NONE;
|
||||
}
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
|
||||
if (mode == ICE_STATE_FULLSIM) {
|
||||
res = fullsim_mode();
|
||||
if (res == PM3_SUCCESS) {
|
||||
download_instructions(mode);
|
||||
}
|
||||
}
|
||||
// the button press to exit sim, is captured in main loop here
|
||||
mode = ICE_STATE_NONE;
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_ATTACK: {
|
||||
DbpString("-=[ enter " _CYAN_("`reader attack`") " mode ]=-");
|
||||
res = reader_attack_mode();
|
||||
if (res == PM3_SUCCESS)
|
||||
download_instructions(mode);
|
||||
|
||||
mode = ICE_STATE_NONE;
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_READER: {
|
||||
DbpString("-=[ enter " _CYAN_("`read & dump`") " mode, continuous scanning ]=-");
|
||||
res = reader_dump_mode();
|
||||
if (res == PM3_SUCCESS)
|
||||
download_instructions(mode);
|
||||
|
||||
mode = ICE_STATE_NONE;
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_CONFIGCARD: {
|
||||
DbpString("-=[ enter " _CYAN_("`glitch & config`") " mode ]=-");
|
||||
|
||||
// Look for config cards
|
||||
rdv40_spiffs_lazy_mount();
|
||||
for (uint8_t i =0; i < 2; i++) {
|
||||
if (exists_in_spiffs(cc_files[i]) == false) {
|
||||
Dbprintf(_RED_("error") ", " _YELLOW_("%s") " file missing", cc_files[i]);
|
||||
mode = ICE_STATE_NONE;
|
||||
}
|
||||
}
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
|
||||
if (mode == ICE_STATE_CONFIGCARD)
|
||||
config_sim_mode();
|
||||
|
||||
mode = ICE_STATE_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_off();
|
||||
Dbprintf("-=[ exit ]=-");
|
||||
}
|
||||
@@ -34,7 +34,7 @@
|
||||
#endif
|
||||
|
||||
#define MAX_IND 16 // 4 LEDs - 2^4 combinations
|
||||
#define CLOCK 64 //for 125kHz
|
||||
#define LF_CLOCK 64 // for 125kHz
|
||||
|
||||
// low & high - array for storage IDs. Its length must be equal.
|
||||
// Predefined IDs must be stored in low[].
|
||||
@@ -57,34 +57,35 @@ static uint64_t rev_quads(uint64_t bits) {
|
||||
}
|
||||
|
||||
static void fillbuff(uint8_t bit) {
|
||||
memset(bba + buflen, bit, CLOCK / 2);
|
||||
buflen += (CLOCK / 2);
|
||||
memset(bba + buflen, bit ^ 1, CLOCK / 2);
|
||||
buflen += (CLOCK / 2);
|
||||
memset(bba + buflen, bit, LF_CLOCK / 2);
|
||||
buflen += (LF_CLOCK / 2);
|
||||
memset(bba + buflen, bit ^ 1, LF_CLOCK / 2);
|
||||
buflen += (LF_CLOCK / 2);
|
||||
}
|
||||
|
||||
static void construct_EM410x_emul(uint64_t id) {
|
||||
|
||||
|
||||
int i, j;
|
||||
int binary[4] = {0};
|
||||
int parity[4] = {0};
|
||||
buflen = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 9; i++)
|
||||
for (i = 0; i < 9; i++)
|
||||
fillbuff(1);
|
||||
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
for (uint8_t j = 3; j > 0; j--, id /= 2)
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 3; j >= 0; j--, id /= 2)
|
||||
binary[j] = id % 2;
|
||||
|
||||
for (uint8_t j = 0; j < 4; j++)
|
||||
for (j = 0; j < 4; j++)
|
||||
fillbuff(binary[j]);
|
||||
|
||||
fillbuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||
for (uint8_t j = 0; j < 4; j++)
|
||||
for (j = 0; j < 4; j++)
|
||||
parity[j] ^= binary[j];
|
||||
}
|
||||
|
||||
for (uint8_t j = 0; j < 4; j++)
|
||||
for (j = 0; j < 4; j++)
|
||||
fillbuff(parity[j]);
|
||||
|
||||
fillbuff(0);
|
||||
@@ -207,7 +208,7 @@ void RunMod(void) {
|
||||
state = 0;
|
||||
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
|
||||
// Click - write ID to tag
|
||||
copy_em410x_to_t55xx(0, CLOCK, (uint32_t)(low[selected] >> 32), (uint32_t)(low[selected] & 0xffffffff));
|
||||
copy_em410x_to_t55xx(0, LF_CLOCK, (uint32_t)(low[selected] >> 32), (uint32_t)(low[selected] & 0xffffffff));
|
||||
led_slot(selected);
|
||||
state = 0; // Switch to select mode
|
||||
}
|
||||
|
||||
156
armsrc/appmain.c
156
armsrc/appmain.c
@@ -20,6 +20,7 @@
|
||||
#include "fpga.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "string.h"
|
||||
#include "printf.h"
|
||||
#include "legicrf.h"
|
||||
#include "BigBuf.h"
|
||||
#include "iso14443a.h"
|
||||
@@ -62,20 +63,7 @@
|
||||
#include "spiffs.h"
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// A buffer where we can queue things up to be sent through the FPGA, for
|
||||
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
|
||||
// is the order in which they go out on the wire.
|
||||
//=============================================================================
|
||||
|
||||
#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits
|
||||
uint8_t ToSend[TOSEND_BUFFER_SIZE];
|
||||
int ToSendMax = -1;
|
||||
|
||||
extern uint32_t _stack_start, _stack_end;
|
||||
|
||||
|
||||
static int ToSendBit;
|
||||
struct common_area common_area __attribute__((section(".commonarea")));
|
||||
static int button_status = BUTTON_NO_CLICK;
|
||||
static bool allow_send_wtx = false;
|
||||
@@ -86,29 +74,6 @@ inline void send_wtx(uint16_t wtx) {
|
||||
}
|
||||
}
|
||||
|
||||
void ToSendReset(void) {
|
||||
ToSendMax = -1;
|
||||
ToSendBit = 8;
|
||||
}
|
||||
|
||||
void ToSendStuffBit(int b) {
|
||||
if (ToSendBit >= 8) {
|
||||
ToSendMax++;
|
||||
ToSend[ToSendMax] = 0;
|
||||
ToSendBit = 0;
|
||||
}
|
||||
|
||||
if (b)
|
||||
ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
|
||||
|
||||
ToSendBit++;
|
||||
|
||||
if (ToSendMax >= sizeof(ToSend)) {
|
||||
ToSendBit = 0;
|
||||
DbpString("ToSendStuffBit overflowed!");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read an ADC channel and block till it completes, then return the result
|
||||
// in ADC units (0 to 1023). Also a routine to sum up a number of samples and
|
||||
@@ -213,7 +178,7 @@ static void MeasureAntennaTuning(void) {
|
||||
LED_A_ON();
|
||||
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER);
|
||||
SpinDelay(50);
|
||||
|
||||
#if defined RDV4
|
||||
@@ -328,6 +293,28 @@ static void TimingIntervalAcquisition(void) {
|
||||
StartTickCount();
|
||||
}
|
||||
|
||||
static void print_debug_level(void) {
|
||||
char dbglvlstr[20] = {0};
|
||||
switch(DBGLEVEL) {
|
||||
case DBG_NONE:
|
||||
sprintf(dbglvlstr, "NONE");
|
||||
break;
|
||||
case DBG_ERROR:
|
||||
sprintf(dbglvlstr, "ERROR");
|
||||
break;
|
||||
case DBG_INFO:
|
||||
sprintf(dbglvlstr, "INFO");
|
||||
break;
|
||||
case DBG_DEBUG:
|
||||
sprintf(dbglvlstr, "DEBUG");
|
||||
break;
|
||||
case DBG_EXTENDED:
|
||||
sprintf(dbglvlstr, "EXTENDED");
|
||||
break;
|
||||
}
|
||||
Dbprintf(" DBGLEVEL................%d ( " _YELLOW_("%s")" )", DBGLEVEL, dbglvlstr);
|
||||
}
|
||||
|
||||
// measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
|
||||
// Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the PacketCommandNG structure included.
|
||||
static void printConnSpeed(void) {
|
||||
@@ -374,10 +361,10 @@ static void SendStatus(void) {
|
||||
DbpString(_CYAN_("Various"));
|
||||
|
||||
print_stack_usage();
|
||||
|
||||
Dbprintf(" DBGLEVEL................%d", DBGLEVEL);
|
||||
Dbprintf(" ToSendMax...............%d", ToSendMax);
|
||||
Dbprintf(" ToSendBit...............%d", ToSendBit);
|
||||
print_debug_level();
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
Dbprintf(" ToSendMax...............%d", ts->max );
|
||||
Dbprintf(" ToSend BUFFERSIZE.......%d", TOSEND_BUFFER_SIZE);
|
||||
while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
|
||||
uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks
|
||||
@@ -515,6 +502,7 @@ static void SendCapabilities(void) {
|
||||
|
||||
// Show some leds in a pattern to identify StandAlone mod is running
|
||||
void StandAloneMode(void) {
|
||||
DbpString("");
|
||||
DbpString("Stand-alone mode, no computer necessary");
|
||||
SpinDown(50);
|
||||
SpinDelay(50);
|
||||
@@ -735,7 +723,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
// emulator
|
||||
case CMD_SET_DBGMODE: {
|
||||
DBGLEVEL = packet->data.asBytes[0];
|
||||
Dbprintf("Debug level: %d", DBGLEVEL);
|
||||
print_debug_level();
|
||||
reply_ng(CMD_SET_DBGMODE, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
@@ -793,7 +781,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
case CMD_LF_HID_WATCH: {
|
||||
uint32_t high, low;
|
||||
int res = lf_hid_watch(0, &high, &low);
|
||||
reply_ng(CMD_LF_HID_WATCH, res, NULL, 0);
|
||||
reply_ng(CMD_LF_HID_WATCH, res, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HID_SIMULATE: {
|
||||
@@ -974,6 +962,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type
|
||||
SniffHitag2();
|
||||
// SniffHitag2(packet->oldarg[0]);
|
||||
reply_ng(CMD_LF_HITAG_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content
|
||||
@@ -1034,8 +1023,18 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
AcquireRawAdcSamplesIso15693();
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_RAWADC: {
|
||||
RecordRawAdcSamplesIso15693();
|
||||
case CMD_HF_ISO15693_SNIFF: {
|
||||
/*
|
||||
struct p {
|
||||
uint8_t jam_search_len;
|
||||
uint8_t jam_search_string[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
|
||||
SniffIso15693(payload->jam_search_len, payload->jam_search_string);
|
||||
*/
|
||||
SniffIso15693(0, NULL);
|
||||
reply_ng(CMD_HF_ISO15693_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_COMMAND: {
|
||||
@@ -1051,7 +1050,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_SIMULATE: {
|
||||
SimTagIso15693(packet->oldarg[0], packet->data.asBytes);
|
||||
struct p {
|
||||
uint8_t uid[10];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SimTagIso15693(payload->uid);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1094,6 +1097,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
}
|
||||
case CMD_HF_ISO14443B_SNIFF: {
|
||||
SniffIso14443b();
|
||||
reply_ng(CMD_HF_ISO14443B_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443B_SIMULATE: {
|
||||
@@ -1118,6 +1122,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
}
|
||||
case CMD_HF_FELICA_SNIFF: {
|
||||
felica_sniff(packet->oldarg[0], packet->oldarg[1]);
|
||||
reply_ng(CMD_HF_FELICA_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_FELICALITE_DUMP: {
|
||||
@@ -1129,6 +1134,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
#ifdef WITH_ISO14443a
|
||||
case CMD_HF_ISO14443A_SNIFF: {
|
||||
SniffIso14443a(packet->data.asBytes[0]);
|
||||
reply_ng(CMD_HF_ISO14443A_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_READER: {
|
||||
@@ -1379,7 +1385,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
#ifdef WITH_ICLASS
|
||||
// Makes use of ISO14443a FPGA Firmware
|
||||
case CMD_HF_ICLASS_SNIFF: {
|
||||
SniffIClass();
|
||||
struct p {
|
||||
uint8_t jam_search_len;
|
||||
uint8_t jam_search_string[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SniffIClass(payload->jam_search_len, payload->jam_search_string);
|
||||
reply_ng(CMD_HF_ICLASS_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_SIMULATE: {
|
||||
@@ -1391,7 +1403,12 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_REPLAY: {
|
||||
ReaderIClass_Replay(packet->oldarg[0], packet->data.asBytes);
|
||||
struct p {
|
||||
uint8_t reader[4];
|
||||
uint8_t mac[4];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
ReaderIClass_Replay(payload->reader, payload->mac);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_EML_MEMSET: {
|
||||
@@ -1401,36 +1418,14 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_WRITEBL: {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t data[12];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
iClass_WriteBlock(payload->blockno, payload->data);
|
||||
break;
|
||||
}
|
||||
// iceman2019, unused?
|
||||
case CMD_HF_ICLASS_READCHECK: { // auth step 1
|
||||
iClass_ReadCheck(packet->oldarg[0], packet->oldarg[1]);
|
||||
iClass_WriteBlock(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_READBL: {
|
||||
/*
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
*/
|
||||
iClass_ReadBlk(packet->data.asBytes[0]);
|
||||
iClass_ReadBlock(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_AUTH: { //check
|
||||
/*
|
||||
struct p {
|
||||
uint8_t mac[4];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
*/
|
||||
iClass_Authentication(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
@@ -1439,7 +1434,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_DUMP: {
|
||||
iClass_Dump(packet->oldarg[0], packet->oldarg[1]);
|
||||
iClass_Dump(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_CLONE: {
|
||||
@@ -1452,6 +1447,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
iClass_Clone(payload->startblock, payload->endblock, payload->data);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_RESTORE: {
|
||||
iClass_Restore(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HFSNIFF
|
||||
@@ -1619,7 +1618,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
case 1: // MEASURE_ANTENNA_TUNING_HF_START
|
||||
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER);
|
||||
reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
case 2:
|
||||
@@ -1906,6 +1905,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_SPIFFS_WIPE: {
|
||||
LED_B_ON();
|
||||
rdv40_spiffs_safe_wipe();
|
||||
reply_ng(CMD_SPIFFS_WIPE, PM3_SUCCESS, NULL, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
case CMD_FLASHMEM_SET_SPIBAUDRATE: {
|
||||
if (packet->length != sizeof(uint32_t))
|
||||
break;
|
||||
@@ -2063,6 +2069,8 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_STANDALONE: {
|
||||
uint8_t *bb = BigBuf_get_EM_addr();
|
||||
bb[0] = packet->data.asBytes[0];
|
||||
RunMod();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,6 @@ int gLow = 0;
|
||||
static void init_tag(void) {
|
||||
|
||||
// initialize global tag structure
|
||||
|
||||
for (int i = 0; i < 34; i++)
|
||||
for (int j = 0; j < 7; j++)
|
||||
tag.sectors[i][j] = 0x00;
|
||||
@@ -109,9 +108,7 @@ static void init_tag(void) {
|
||||
static uint8_t bits2byte(uint8_t *bits, int length) {
|
||||
|
||||
// converts <length> separate bits into a single "byte"
|
||||
|
||||
uint8_t byte = 0;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
||||
byte |= bits[i];
|
||||
@@ -124,11 +121,10 @@ static uint8_t bits2byte(uint8_t *bits, int length) {
|
||||
}
|
||||
|
||||
static void msb2lsb_word(uint8_t *word) {
|
||||
|
||||
|
||||
// reorders given <word> according to EM4x50 datasheet (msb -> lsb)
|
||||
|
||||
|
||||
uint8_t buff[4];
|
||||
|
||||
buff[0] = reflect8(word[3]);
|
||||
buff[1] = reflect8(word[2]);
|
||||
buff[2] = reflect8(word[1]);
|
||||
@@ -141,13 +137,12 @@ static void msb2lsb_word(uint8_t *word) {
|
||||
}
|
||||
|
||||
static void save_word(int pos, uint8_t bits[EM4X50_TAG_WORD]) {
|
||||
|
||||
|
||||
// split "raw" word into data, row and column parity bits and stop bit and
|
||||
// save them in global tag structure
|
||||
|
||||
uint8_t row_parity[4];
|
||||
uint8_t col_parity[8];
|
||||
|
||||
|
||||
// data and row parities
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tag.sectors[pos][i] = bits2byte(&bits[9*i],8);
|
||||
@@ -161,7 +156,7 @@ static void save_word(int pos, uint8_t bits[EM4X50_TAG_WORD]) {
|
||||
col_parity[i] = bits[36+i];
|
||||
|
||||
tag.sectors[pos][5] = bits2byte(col_parity,8);
|
||||
|
||||
|
||||
// stop bit
|
||||
tag.sectors[pos][6] = bits[44];
|
||||
}
|
||||
@@ -169,7 +164,7 @@ static void save_word(int pos, uint8_t bits[EM4X50_TAG_WORD]) {
|
||||
static void wait_timer(int timer, uint32_t period) {
|
||||
|
||||
// do nothing for <period> using timer <timer>
|
||||
|
||||
|
||||
if (timer == FPGA_TIMER_0) {
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
@@ -184,23 +179,22 @@ static void wait_timer(int timer, uint32_t period) {
|
||||
}
|
||||
|
||||
static void em4x50_setup_read(void) {
|
||||
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||
|
||||
// 50ms for the resonant antenna to settle.
|
||||
SpinDelay(50);
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
||||
// start a 1.5ticks is 1us
|
||||
StartTicks();
|
||||
|
||||
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125);
|
||||
|
||||
// Connect the A/D to the peak-detected low-frequency path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
|
||||
// Steal this pin from the SSP (SPI communication channel with fpga) and
|
||||
// use it to control the modulation
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
@@ -208,7 +202,7 @@ static void em4x50_setup_read(void) {
|
||||
|
||||
// Disable modulation at default, which means enable the field
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
||||
|
||||
// Enable Peripheral Clock for
|
||||
// TIMER_CLOCK0, used to measure exact timing before answering
|
||||
// TIMER_CLOCK1, used to capture edges of the tag frames
|
||||
@@ -221,17 +215,17 @@ static void em4x50_setup_read(void) {
|
||||
|
||||
// TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
|
||||
|
||||
|
||||
// TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
|
||||
|
||||
|
||||
// Enable and reset counters
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
|
||||
// synchronized startup procedure
|
||||
while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC1 returned to zero
|
||||
|
||||
|
||||
// Watchdog hit
|
||||
WDT_HIT();
|
||||
}
|
||||
@@ -239,21 +233,21 @@ static void em4x50_setup_read(void) {
|
||||
// functions for "reader" use case
|
||||
|
||||
static bool get_signalproperties(void) {
|
||||
|
||||
|
||||
// calculate signal properties (mean amplitudes) from measured data:
|
||||
// 32 amplitudes (maximum values) -> mean amplitude value -> gHigh -> gLow
|
||||
|
||||
|
||||
bool signal_found = false;
|
||||
int no_periods = 32, pct = 75, noise = 140;
|
||||
uint8_t sample = 0, sample_ref = 127;
|
||||
uint8_t sample_ref = 127;
|
||||
uint8_t sample_max_mean = 0;
|
||||
uint8_t sample_max[no_periods];
|
||||
uint32_t sample_max_sum = 0;
|
||||
memcpy(sample_max, 0x00, sizeof(sample_max));
|
||||
|
||||
|
||||
// wait until signal/noise > 1 (max. 32 periods)
|
||||
for (int i = 0; i < T0 * no_periods; i++) {
|
||||
|
||||
|
||||
// about 2 samples per bit period
|
||||
wait_timer(0, T0 * EM4X50_T_TAG_HALF_PERIOD);
|
||||
|
||||
@@ -261,9 +255,9 @@ static bool get_signalproperties(void) {
|
||||
signal_found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!signal_found)
|
||||
return false;
|
||||
|
||||
@@ -273,39 +267,36 @@ static bool get_signalproperties(void) {
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
while (AT91C_BASE_TC0->TC_CV < T0 * 3 * EM4X50_T_TAG_FULL_PERIOD) {
|
||||
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
|
||||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
if (sample > sample_max[i])
|
||||
sample_max[i] = sample;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
sample_max_sum += sample_max[i];
|
||||
}
|
||||
|
||||
|
||||
sample_max_mean = sample_max_sum / no_periods;
|
||||
|
||||
|
||||
// set global envelope variables
|
||||
gHigh = sample_ref + pct * (sample_max_mean - sample_ref) / 100;
|
||||
gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int get_next_bit(void) {
|
||||
|
||||
|
||||
// returns bit value (or EM4X50_BIT_OTHER -> no bit pattern) by evaluating
|
||||
// a single sample within a bit period (given there is no LIW, ACK or NAK)
|
||||
// This function is not used for decoding, it is only used for identifying
|
||||
// a listen window (return value = EM4X50_BIT_OTHER) in functions
|
||||
// "find_double_listen_window" and "check_ack"
|
||||
|
||||
uint8_t sample;
|
||||
|
||||
// get sample at 3/4 of bit period
|
||||
wait_timer(0, T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD);
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
// wait until end of bit period
|
||||
wait_timer(0, T0 * EM4X50_T_TAG_QUARTER_PERIOD);
|
||||
@@ -315,7 +306,7 @@ static int get_next_bit(void) {
|
||||
return EM4X50_BIT_0;
|
||||
else if (sample < gLow)
|
||||
return EM4X50_BIT_1;
|
||||
|
||||
|
||||
return EM4X50_BIT_OTHER;
|
||||
}
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) {
|
||||
}
|
||||
|
||||
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
|
||||
uint8_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
|
||||
uint16_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
|
||||
if (power)
|
||||
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
||||
if (highspeed)
|
||||
@@ -445,7 +445,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Start iso18092_setup");
|
||||
|
||||
LEDsoff();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_FELICA);
|
||||
|
||||
// allocate command receive buffer
|
||||
BigBuf_free();
|
||||
@@ -464,7 +464,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO18092);
|
||||
|
||||
// LSB transfer. Remember to set it back to MSB with
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
|
||||
@@ -134,7 +134,7 @@ void SetupSpi(int mode) {
|
||||
// Set up the synchronous serial port with the set of options that fits
|
||||
// the FPGA mode. Both RX and TX are always enabled.
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaSetupSsc(void) {
|
||||
void FpgaSetupSsc(uint16_t fpga_mode) {
|
||||
// First configure the GPIOs, and get ourselves a clock.
|
||||
AT91C_BASE_PIOA->PIO_ASR =
|
||||
GPIO_SSC_FRAME |
|
||||
@@ -152,12 +152,16 @@ void FpgaSetupSsc(void) {
|
||||
// data and frame signal is sampled on falling edge of RK
|
||||
AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);
|
||||
|
||||
// 8 bits per transfer, no loopback, MSB first, 1 transfer per sync
|
||||
// 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync
|
||||
// pulse, no output sync
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
if ((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER && FpgaGetCurrent() == FPGA_BITSTREAM_HF) {
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
} else {
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
}
|
||||
|
||||
// TX clock comes from TK pin, no clock output, outputs change on falling
|
||||
// edge of TK, frame sync is sampled on rising edge of TK, start TX on rising edge of TF
|
||||
// TX clock comes from TK pin, no clock output, outputs change on rising edge of TK,
|
||||
// TF (frame sync) is sampled on falling edge of TK, start TX on rising edge of TF
|
||||
AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
|
||||
|
||||
// tx framing is the same as the rx framing
|
||||
@@ -171,7 +175,7 @@ void FpgaSetupSsc(void) {
|
||||
// a single buffer as a circular buffer (so that we just chain back to
|
||||
// ourselves, not to another buffer).
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FpgaSetupSscDma(uint8_t *buf, int len) {
|
||||
bool FpgaSetupSscDma(uint8_t *buf, uint16_t len) {
|
||||
if (buf == NULL) return false;
|
||||
|
||||
FpgaDisableSscDma();
|
||||
@@ -347,8 +351,10 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, lz4_streamp co
|
||||
* length.
|
||||
*/
|
||||
static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, lz4_streamp compressed_fpga_stream, uint8_t *output_buffer) {
|
||||
int result = 0;
|
||||
|
||||
#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
|
||||
|
||||
int result = 0;
|
||||
uint16_t numbytes = 0;
|
||||
while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
|
||||
char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
|
||||
@@ -439,7 +445,7 @@ void FpgaDownloadAndGo(int bitstream_version) {
|
||||
// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
|
||||
// where C is the 4 bit command and D is the 12 bit data
|
||||
//
|
||||
// @params cmd and v gets or over eachother. Take careful note of overlapping bits.
|
||||
// @params cmd and v gets OR:ED over each other. Take careful note of overlapping bits.
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaSendCommand(uint16_t cmd, uint16_t v) {
|
||||
SetupSpi(SPI_FPGA_MODE);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
// definitions for multiple FPGA config files support
|
||||
#define FPGA_BITSTREAM_LF 1
|
||||
#define FPGA_BITSTREAM_HF 2
|
||||
#define FPGA_BITSTREAM_HF_FELICA 3
|
||||
|
||||
/*
|
||||
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand)
|
||||
@@ -52,23 +53,26 @@ thres| x x x x x x x x
|
||||
#define FPGA_CMD_TRACE_ENABLE (2<<12) // C
|
||||
|
||||
// Definitions for the FPGA configuration word.
|
||||
#define FPGA_MAJOR_MODE_MASK 0x01C0
|
||||
#define FPGA_MINOR_MODE_MASK 0x003F
|
||||
|
||||
// LF
|
||||
#define FPGA_MAJOR_MODE_LF_READER (0<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_ADC (3<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_READER (0<<6)
|
||||
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<6)
|
||||
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<6)
|
||||
#define FPGA_MAJOR_MODE_LF_ADC (3<<6)
|
||||
|
||||
// HF
|
||||
#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO18092 (5<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_GET_TRACE (6<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_READER (0<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO14443A (2<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SNIFF (3<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO18092 (4<<6) // D
|
||||
#define FPGA_MAJOR_MODE_HF_GET_TRACE (5<<6) // D
|
||||
|
||||
// BOTH HF / LF
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<5) // D
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<6) // D
|
||||
|
||||
|
||||
// Options for LF_READER
|
||||
#define FPGA_LF_ADC_READER_FIELD 0x1
|
||||
@@ -78,13 +82,20 @@ thres| x x x x x x x x
|
||||
#define FPGA_LF_EDGE_DETECT_READER_FIELD 0x1
|
||||
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 0x2
|
||||
|
||||
// Options for the HF reader, tx to tag
|
||||
#define FPGA_HF_READER_TX_SHALLOW_MOD 0x1
|
||||
// Options for the HF reader
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_IQ (0<<0)
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE (1<<0)
|
||||
#define FPGA_HF_READER_MODE_RECEIVE_PHASE (2<<0)
|
||||
#define FPGA_HF_READER_MODE_SEND_FULL_MOD (3<<0)
|
||||
#define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD (4<<0)
|
||||
#define FPGA_HF_READER_MODE_SNIFF_IQ (5<<0)
|
||||
#define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE (6<<0)
|
||||
#define FPGA_HF_READER_MODE_SNIFF_PHASE (7<<0)
|
||||
#define FPGA_HF_READER_MODE_SEND_JAM (8<<0)
|
||||
|
||||
// Options for the HF reader, correlating against rx from tag
|
||||
#define FPGA_HF_READER_RX_XCORR_848_KHZ 0x1
|
||||
#define FPGA_HF_READER_RX_XCORR_SNOOP 0x2
|
||||
#define FPGA_HF_READER_RX_XCORR_QUARTER 0x4
|
||||
#define FPGA_HF_READER_SUBCARRIER_848_KHZ (0<<4)
|
||||
#define FPGA_HF_READER_SUBCARRIER_424_KHZ (1<<4)
|
||||
#define FPGA_HF_READER_SUBCARRIER_212_KHZ (2<<4)
|
||||
|
||||
// Options for the HF simulated tag, how to modulate
|
||||
#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000
|
||||
@@ -112,9 +123,9 @@ void FpgaEnableTracing(void);
|
||||
void FpgaDisableTracing(void);
|
||||
void FpgaDownloadAndGo(int bitstream_version);
|
||||
// void FpgaGatherVersion(int bitstream_version, char *dst, int len);
|
||||
void FpgaSetupSsc(void);
|
||||
void FpgaSetupSsc(uint16_t fpga_mode);
|
||||
void SetupSpi(int mode);
|
||||
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
||||
bool FpgaSetupSscDma(uint8_t *buf, uint16_t len);
|
||||
void Fpga_print_status(void);
|
||||
int FpgaGetCurrent(void);
|
||||
void SetAdcMuxFor(uint32_t whichGpio);
|
||||
|
||||
@@ -41,12 +41,12 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SNIFF);
|
||||
|
||||
// Setting Frame Mode For better performance on high speed data transfer.
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNIFF);
|
||||
SpinDelay(100);
|
||||
|
||||
*len = (BigBuf_max_traceLen() & 0xFFFE);
|
||||
@@ -114,17 +114,18 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
||||
}
|
||||
|
||||
void HfPlotDownload(void) {
|
||||
uint8_t *buf = ToSend;
|
||||
uint8_t *this_buf = buf;
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
uint8_t *this_buf = ts->buf;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_GET_TRACE);
|
||||
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address
|
||||
AT91C_BASE_PDC_SSC->PDC_RCR = PM3_CMD_DATA_SIZE; // transfer this many samples
|
||||
buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register
|
||||
ts->buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM
|
||||
@@ -132,7 +133,7 @@ void HfPlotDownload(void) {
|
||||
LED_B_ON();
|
||||
for (size_t i = 0; i < FPGA_TRACE_SIZE; i += PM3_CMD_DATA_SIZE) {
|
||||
// prepare next DMA transfer:
|
||||
uint8_t *next_buf = buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE));
|
||||
uint8_t *next_buf = ts->buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE));
|
||||
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = PM3_CMD_DATA_SIZE;
|
||||
|
||||
30
armsrc/i2c.c
30
armsrc/i2c.c
@@ -225,7 +225,7 @@ static bool I2C_WaitForSim(void) {
|
||||
// 8051 speaks with smart card.
|
||||
// 1000*50*3.07 = 153.5ms
|
||||
// 1byte transfer == 1ms with max frame being 256bytes
|
||||
if (!WaitSCL_H_delay(20 * 1000 * 50))
|
||||
if (!WaitSCL_H_delay(30 * 1000 * 50))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -631,7 +631,7 @@ int I2C_get_version(uint8_t *maj, uint8_t *min) {
|
||||
}
|
||||
|
||||
// Will read response from smart card module, retries 3 times to get the data.
|
||||
static bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
||||
bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
||||
|
||||
uint8_t i = 3;
|
||||
int16_t len = 0;
|
||||
@@ -658,7 +658,7 @@ static bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetATR(smart_card_atr_t *card_ptr) {
|
||||
bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
||||
|
||||
if (!card_ptr)
|
||||
return false;
|
||||
@@ -666,19 +666,18 @@ bool GetATR(smart_card_atr_t *card_ptr) {
|
||||
card_ptr->atr_len = 0;
|
||||
memset(card_ptr->atr, 0, sizeof(card_ptr->atr));
|
||||
|
||||
|
||||
// Send ATR
|
||||
// start [C0 01] stop start C1 len aa bb cc stop]
|
||||
I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN);
|
||||
|
||||
//wait for sim card to answer.
|
||||
// 1byte = 1ms , max frame 256bytes. SHould wait 256ms atleast just in case.
|
||||
if (!I2C_WaitForSim())
|
||||
// 1byte = 1ms , max frame 256bytes. Should wait 256ms atleast just in case.
|
||||
if (I2C_WaitForSim() == false)
|
||||
return false;
|
||||
|
||||
// read bytes from module
|
||||
uint8_t len = sizeof(card_ptr->atr);
|
||||
if (!sc_rx_bytes(card_ptr->atr, &len))
|
||||
if (sc_rx_bytes(card_ptr->atr, &len) == false)
|
||||
return false;
|
||||
|
||||
uint8_t pos_td = 1;
|
||||
@@ -706,17 +705,19 @@ bool GetATR(smart_card_atr_t *card_ptr) {
|
||||
}
|
||||
|
||||
card_ptr->atr_len = len;
|
||||
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
|
||||
if (verbose) {
|
||||
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SmartCardAtr(void) {
|
||||
smart_card_atr_t card;
|
||||
LED_D_ON();
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
I2C_Reset_EnterMainProgram();
|
||||
bool isOK = GetATR(&card);
|
||||
bool isOK = GetATR(&card, true);
|
||||
reply_mix(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
@@ -730,10 +731,13 @@ void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) {
|
||||
uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME);
|
||||
smartcard_command_t flags = arg0;
|
||||
|
||||
if ((flags & SC_CONNECT))
|
||||
if ((flags & SC_CLEARLOG) == SC_CLEARLOG)
|
||||
clear_trace();
|
||||
|
||||
set_tracing(true);
|
||||
if ((flags & SC_LOG) == SC_LOG)
|
||||
set_tracing(true);
|
||||
else
|
||||
set_tracing(false);
|
||||
|
||||
if ((flags & SC_CONNECT)) {
|
||||
|
||||
@@ -741,7 +745,7 @@ void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) {
|
||||
|
||||
if ((flags & SC_SELECT)) {
|
||||
smart_card_atr_t card;
|
||||
bool gotATR = GetATR(&card);
|
||||
bool gotATR = GetATR(&card, true);
|
||||
//reply_old(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||
if (!gotATR)
|
||||
goto OUT;
|
||||
|
||||
@@ -33,8 +33,9 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
|
||||
int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
|
||||
bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
|
||||
|
||||
bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen);
|
||||
//
|
||||
bool GetATR(smart_card_atr_t *card_ptr);
|
||||
bool GetATR(smart_card_atr_t *card_ptr, bool verbose);
|
||||
|
||||
// generice functions
|
||||
void SmartCardAtr(void);
|
||||
|
||||
3582
armsrc/iclass.c
3582
armsrc/iclass.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
// Iceman, August 2020
|
||||
//
|
||||
// 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
|
||||
@@ -12,18 +13,30 @@
|
||||
#define __ICLASS_H
|
||||
|
||||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
void RAMFUNC SniffIClass(void);
|
||||
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||
void ReaderIClass(uint8_t arg0);
|
||||
void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac);
|
||||
void iClass_Authentication(uint8_t *mac);
|
||||
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
||||
void iClass_WriteBlock(uint8_t blockno, uint8_t *data);
|
||||
void iClass_ReadBlk(uint8_t blockno);
|
||||
bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len);
|
||||
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);
|
||||
void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac);
|
||||
|
||||
void iClass_WriteBlock(uint8_t *msg);
|
||||
void iClass_Dump(uint8_t *msg);
|
||||
|
||||
void iClass_Restore(uint8_t *msg);
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||
|
||||
int do_iclass_simulation_nonsec(void);
|
||||
int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf);
|
||||
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_t *datain, uint8_t *dataout, uint16_t *dataoutlen);
|
||||
|
||||
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
||||
void iClass_Authentication(uint8_t *bytes);
|
||||
bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
|
||||
|
||||
void iClass_ReadBlock(uint8_t *msg);
|
||||
bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time);
|
||||
|
||||
bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time);
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
|
||||
#endif
|
||||
|
||||
@@ -585,10 +585,6 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||
uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
|
||||
// The DMA buffer, used to stream samples from the FPGA
|
||||
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||
uint8_t *data = dmaBuf;
|
||||
|
||||
uint8_t previous_data = 0;
|
||||
int maxDataLen = 0, dataLen;
|
||||
bool TagIsActive = false;
|
||||
@@ -600,10 +596,14 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
DbpString("Starting to sniff");
|
||||
Dbprintf("Starting to sniff. Press PM3 Button to stop.");
|
||||
|
||||
// The DMA buffer, used to stream samples from the FPGA
|
||||
dmabuf8_t *dma = get_dma8();
|
||||
uint8_t *data = dma->buf;
|
||||
|
||||
// Setup and start DMA.
|
||||
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, DMA_BUFFER_SIZE)) {
|
||||
if (!FpgaSetupSscDma((uint8_t *) dma->buf, DMA_BUFFER_SIZE)) {
|
||||
if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
|
||||
return;
|
||||
}
|
||||
@@ -621,7 +621,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||
WDT_HIT();
|
||||
LED_A_ON();
|
||||
|
||||
int register readBufDataP = data - dmaBuf;
|
||||
int register readBufDataP = data - dma->buf;
|
||||
int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
|
||||
if (readBufDataP <= dmaBufDataP)
|
||||
dataLen = dmaBufDataP - readBufDataP;
|
||||
@@ -640,13 +640,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||
|
||||
// primary buffer was stopped( <-- we lost data!
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dma->buf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
|
||||
Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
|
||||
}
|
||||
// secondary buffer sets as primary, secondary buffer was stopped
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
@@ -710,16 +710,15 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||
previous_data = *data;
|
||||
rx_samples++;
|
||||
data++;
|
||||
if (data == dmaBuf + DMA_BUFFER_SIZE) {
|
||||
data = dmaBuf;
|
||||
if (data == dma->buf + DMA_BUFFER_SIZE) {
|
||||
data = dma->buf;
|
||||
}
|
||||
} // end main loop
|
||||
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len);
|
||||
Dbprintf("traceLen=" _YELLOW_("%d")", Uart.output[0]="_YELLOW_("%08x"), BigBuf_get_traceLen(), (uint32_t)Uart.output[0]);
|
||||
Dbprintf("trace len = " _YELLOW_("%d"), BigBuf_get_traceLen());
|
||||
}
|
||||
switch_off();
|
||||
}
|
||||
@@ -729,62 +728,61 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par, bool collision) {
|
||||
|
||||
//uint8_t localCol = 0;
|
||||
ToSendReset();
|
||||
tosend_reset();
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
// Correction bit, might be removed when not needed
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(1); // <-----
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(1); // <-----
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
|
||||
// Send startbit
|
||||
ToSend[++ToSendMax] = SEC_D;
|
||||
LastProxToAirDuration = 8 * ToSendMax - 4;
|
||||
ts->buf[++ts->max] = SEC_D;
|
||||
LastProxToAirDuration = 8 * ts->max - 4;
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
uint8_t b = cmd[i];
|
||||
|
||||
// Data bits
|
||||
for (uint16_t j = 0; j < 8; j++) {
|
||||
//if (collision && (localCol >= colpos)){
|
||||
if (collision) {
|
||||
ToSend[++ToSendMax] = SEC_COLL;
|
||||
//localCol++;
|
||||
ts->buf[++ts->max] = SEC_COLL;
|
||||
} else {
|
||||
if (b & 1) {
|
||||
ToSend[++ToSendMax] = SEC_D;
|
||||
ts->buf[++ts->max] = SEC_D;
|
||||
} else {
|
||||
ToSend[++ToSendMax] = SEC_E;
|
||||
ts->buf[++ts->max] = SEC_E;
|
||||
}
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (collision) {
|
||||
ToSend[++ToSendMax] = SEC_COLL;
|
||||
LastProxToAirDuration = 8 * ToSendMax;
|
||||
ts->buf[++ts->max] = SEC_COLL;
|
||||
LastProxToAirDuration = 8 * ts->max;
|
||||
} else {
|
||||
// Get the parity bit
|
||||
if (par[i >> 3] & (0x80 >> (i & 0x0007))) {
|
||||
ToSend[++ToSendMax] = SEC_D;
|
||||
LastProxToAirDuration = 8 * ToSendMax - 4;
|
||||
ts->buf[++ts->max] = SEC_D;
|
||||
LastProxToAirDuration = 8 * ts->max - 4;
|
||||
} else {
|
||||
ToSend[++ToSendMax] = SEC_E;
|
||||
LastProxToAirDuration = 8 * ToSendMax;
|
||||
ts->buf[++ts->max] = SEC_E;
|
||||
LastProxToAirDuration = 8 * ts->max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send stopbit
|
||||
ToSend[++ToSendMax] = SEC_F;
|
||||
ts->buf[++ts->max] = SEC_F;
|
||||
|
||||
// Convert from last byte pos to length
|
||||
ToSendMax++;
|
||||
ts->max++;
|
||||
}
|
||||
|
||||
static void CodeIso14443aAsTagEx(const uint8_t *cmd, uint16_t len, bool collision) {
|
||||
@@ -799,37 +797,39 @@ static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) {
|
||||
static void Code4bitAnswerAsTag(uint8_t cmd) {
|
||||
uint8_t b = cmd;
|
||||
|
||||
ToSendReset();
|
||||
tosend_reset();
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
// Correction bit, might be removed when not needed
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(1); // 1
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(1); // 1
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
tosend_stuffbit(0);
|
||||
|
||||
// Send startbit
|
||||
ToSend[++ToSendMax] = SEC_D;
|
||||
ts->buf[++ts->max] = SEC_D;
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
if (b & 1) {
|
||||
ToSend[++ToSendMax] = SEC_D;
|
||||
LastProxToAirDuration = 8 * ToSendMax - 4;
|
||||
ts->buf[++ts->max] = SEC_D;
|
||||
LastProxToAirDuration = 8 * ts->max - 4;
|
||||
} else {
|
||||
ToSend[++ToSendMax] = SEC_E;
|
||||
LastProxToAirDuration = 8 * ToSendMax;
|
||||
ts->buf[++ts->max] = SEC_E;
|
||||
LastProxToAirDuration = 8 * ts->max;
|
||||
}
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
// Send stopbit
|
||||
ToSend[++ToSendMax] = SEC_F;
|
||||
ts->buf[++ts->max] = SEC_F;
|
||||
|
||||
// Convert from last byte pos to length
|
||||
ToSendMax++;
|
||||
ts->max++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -887,32 +887,36 @@ bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffe
|
||||
// Prepare the tag modulation bits from the message
|
||||
CodeIso14443aAsTag(response_info->response, response_info->response_n);
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
// Make sure we do not exceed the free buffer space
|
||||
if (ToSendMax > max_buffer_size) {
|
||||
if (ts->max > max_buffer_size) {
|
||||
Dbprintf("ToSend buffer, Out-of-bound, when modulating bits for tag answer:");
|
||||
Dbhexdump(response_info->response_n, response_info->response, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the byte array, used for this modulation to the buffer position
|
||||
memcpy(response_info->modulation, ToSend, ToSendMax);
|
||||
memcpy(response_info->modulation, ts->buf, ts->max);
|
||||
|
||||
// Store the number of bytes that were used for encoding/modulation and the time needed to transfer them
|
||||
response_info->modulation_n = ToSendMax;
|
||||
response_info->modulation_n = ts->max;
|
||||
response_info->ProxToAirDuration = LastProxToAirDuration;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size) {
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
// Retrieve and store the current buffer index
|
||||
response_info->modulation = *buffer;
|
||||
|
||||
// Forward the prepare tag modulation function to the inner function
|
||||
if (prepare_tag_modulation(response_info, *max_buffer_size)) {
|
||||
// Update the free buffer offset and the remaining buffer size
|
||||
*buffer += ToSendMax;
|
||||
*max_buffer_size -= ToSendMax;
|
||||
*buffer += ts->max;
|
||||
*max_buffer_size -= ts->max;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -1499,10 +1503,13 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
||||
uint8_t pwd[4];
|
||||
emlGetMemBt(pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
|
||||
if (memcmp(receivedCmd + 1, pwd, 4) == 0) {
|
||||
uint8_t cmd[4];
|
||||
emlGetMemBt(cmd, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
EmSendCmd(cmd, sizeof(cmd));
|
||||
uint8_t pack[4];
|
||||
emlGetMemBt(pack, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
|
||||
if (memcmp(pack, "\x00\x00\x00\x00", 4) == 0) {
|
||||
memcpy(pack, "\x80\x80\x00\x00", 4);
|
||||
}
|
||||
AddCrc14A(pack, sizeof(pack) - 2);
|
||||
EmSendCmd(pack, sizeof(pack));
|
||||
} else {
|
||||
EmSend4bit(CARD_NACK_NA);
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Auth attempt: %08x", bytes_to_num(receivedCmd + 1, 4));
|
||||
@@ -1635,12 +1642,14 @@ static void PrepareDelayedTransfer(uint16_t delay) {
|
||||
for (uint16_t i = 0; i < delay; i++)
|
||||
bitmask |= (0x01 << i);
|
||||
|
||||
ToSend[ToSendMax++] = 0x00;
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
for (uint16_t i = 0; i < ToSendMax; i++) {
|
||||
uint8_t bits_to_shift = ToSend[i] & bitmask;
|
||||
ToSend[i] = ToSend[i] >> delay;
|
||||
ToSend[i] = ToSend[i] | (bits_shifted << (8 - delay));
|
||||
ts->buf[ts->max++] = 0x00;
|
||||
|
||||
for (uint16_t i = 0; i < ts->max; i++) {
|
||||
uint8_t bits_to_shift = ts->buf[i] & bitmask;
|
||||
ts->buf[i] = ts->buf[i] >> delay;
|
||||
ts->buf[i] = ts->buf[i] | (bits_shifted << (8 - delay));
|
||||
bits_shifted = bits_to_shift;
|
||||
}
|
||||
}
|
||||
@@ -1698,11 +1707,12 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing
|
||||
static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *par) {
|
||||
int last = 0;
|
||||
|
||||
ToSendReset();
|
||||
tosend_reset();
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
// Start of Communication (Seq. Z)
|
||||
ToSend[++ToSendMax] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
|
||||
ts->buf[++ts->max] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ts->max + 1) - 6;
|
||||
|
||||
size_t bytecount = nbytes(bits);
|
||||
// Generate send structure for the data bits
|
||||
@@ -1714,17 +1724,17 @@ static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, cons
|
||||
for (j = 0; j < bitsleft; j++) {
|
||||
if (b & 1) {
|
||||
// Sequence X
|
||||
ToSend[++ToSendMax] = SEC_X;
|
||||
LastProxToAirDuration = 8 * (ToSendMax + 1) - 2;
|
||||
ts->buf[++ts->max] = SEC_X;
|
||||
LastProxToAirDuration = 8 * (ts->max + 1) - 2;
|
||||
last = 1;
|
||||
} else {
|
||||
if (last == 0) {
|
||||
// Sequence Z
|
||||
ToSend[++ToSendMax] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
|
||||
ts->buf[++ts->max] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ts->max + 1) - 6;
|
||||
} else {
|
||||
// Sequence Y
|
||||
ToSend[++ToSendMax] = SEC_Y;
|
||||
ts->buf[++ts->max] = SEC_Y;
|
||||
last = 0;
|
||||
}
|
||||
}
|
||||
@@ -1736,17 +1746,17 @@ static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, cons
|
||||
// Get the parity bit
|
||||
if (par[i >> 3] & (0x80 >> (i & 0x0007))) {
|
||||
// Sequence X
|
||||
ToSend[++ToSendMax] = SEC_X;
|
||||
LastProxToAirDuration = 8 * (ToSendMax + 1) - 2;
|
||||
ts->buf[++ts->max] = SEC_X;
|
||||
LastProxToAirDuration = 8 * (ts->max + 1) - 2;
|
||||
last = 1;
|
||||
} else {
|
||||
if (last == 0) {
|
||||
// Sequence Z
|
||||
ToSend[++ToSendMax] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
|
||||
ts->buf[++ts->max] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ts->max + 1) - 6;
|
||||
} else {
|
||||
// Sequence Y
|
||||
ToSend[++ToSendMax] = SEC_Y;
|
||||
ts->buf[++ts->max] = SEC_Y;
|
||||
last = 0;
|
||||
}
|
||||
}
|
||||
@@ -1756,16 +1766,16 @@ static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, cons
|
||||
// End of Communication: Logic 0 followed by Sequence Y
|
||||
if (last == 0) {
|
||||
// Sequence Z
|
||||
ToSend[++ToSendMax] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ToSendMax + 1) - 6;
|
||||
ts->buf[++ts->max] = SEC_Z;
|
||||
LastProxToAirDuration = 8 * (ts->max + 1) - 6;
|
||||
} else {
|
||||
// Sequence Y
|
||||
ToSend[++ToSendMax] = SEC_Y;
|
||||
ts->buf[++ts->max] = SEC_Y;
|
||||
}
|
||||
ToSend[++ToSendMax] = SEC_Y;
|
||||
ts->buf[++ts->max] = SEC_Y;
|
||||
|
||||
// Convert to length of command:
|
||||
ToSendMax++;
|
||||
ts->max++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1967,7 +1977,8 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
|
||||
|
||||
int EmSend4bit(uint8_t resp) {
|
||||
Code4bitAnswerAsTag(resp);
|
||||
int res = EmSendCmd14443aRaw(ToSend, ToSendMax);
|
||||
tosend_t *ts = get_tosend();
|
||||
int res = EmSendCmd14443aRaw(ts->buf, ts->max);
|
||||
// do the tracing for the previous reader request and this tag answer:
|
||||
uint8_t par[1] = {0x00};
|
||||
GetParity(&resp, 1, par);
|
||||
@@ -1988,7 +1999,9 @@ int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par) {
|
||||
}
|
||||
int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision) {
|
||||
CodeIso14443aAsTagPar(resp, respLen, par, collision);
|
||||
int res = EmSendCmd14443aRaw(ToSend, ToSendMax);
|
||||
tosend_t *ts = get_tosend();
|
||||
int res = EmSendCmd14443aRaw(ts->buf, ts->max);
|
||||
|
||||
// do the tracing for the previous reader request and this tag answer:
|
||||
EmLogTrace(Uart.output,
|
||||
Uart.len,
|
||||
@@ -2149,7 +2162,8 @@ void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t
|
||||
|
||||
CodeIso14443aBitsAsReaderPar(frame, bits, par);
|
||||
// Send command to tag
|
||||
TransmitFor14443a(ToSend, ToSendMax, timing);
|
||||
tosend_t *ts = get_tosend();
|
||||
TransmitFor14443a(ts->buf, ts->max, timing);
|
||||
if (g_trigger) LED_A_ON();
|
||||
|
||||
LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart << 4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration) << 4) + DELAY_ARM2AIR_AS_READER, par, true);
|
||||
@@ -2527,7 +2541,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
@@ -2551,7 +2565,6 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||
hf_field_active = true;
|
||||
}
|
||||
|
||||
|
||||
void hf_field_off(void) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@
|
||||
|
||||
void iso14443b_setup(void);
|
||||
uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
|
||||
uint8_t iso14443b_select_card(iso14b_card_select_t *card);
|
||||
int iso14443b_select_card(iso14b_card_select_t *card);
|
||||
uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
|
||||
|
||||
void SimulateIso14443bTag(uint32_t pupi);
|
||||
|
||||
2115
armsrc/iso15693.c
2115
armsrc/iso15693.c
File diff suppressed because it is too large
Load Diff
@@ -12,15 +12,41 @@
|
||||
#define __ISO15693_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "pm3_cmd.h" // struct
|
||||
|
||||
|
||||
void RecordRawAdcSamplesIso15693(void);
|
||||
// Delays in SSP_CLK ticks.
|
||||
// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag
|
||||
#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response
|
||||
|
||||
//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when acting as reader. All values should be multiples of 16
|
||||
#define DELAY_ISO15693_VCD_TO_VICC_READER 1056 // 1056/3,39MHz = 311.5us from end of command EOF to start of tag response
|
||||
#define DELAY_ISO15693_VICC_TO_VCD_READER 1024 // 1024/3.39MHz = 302.1us between end of tag response and next reader command
|
||||
|
||||
void Iso15693InitReader(void);
|
||||
void Iso15693InitTag(void);
|
||||
void CodeIso15693AsReader(uint8_t *cmd, int n);
|
||||
void CodeIso15693AsTag(uint8_t *cmd, size_t len);
|
||||
|
||||
void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time, uint32_t slot_time, bool slow);
|
||||
int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time);
|
||||
void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time);
|
||||
int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeout, uint32_t *eof_time);
|
||||
|
||||
//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 SimTagIso15693(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 Iso15693InitReader(void);
|
||||
|
||||
void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||
|
||||
int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t *recv,
|
||||
uint16_t max_recv_len, uint32_t start_time, uint16_t timeout, uint32_t *eof_time);
|
||||
|
||||
int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, uint16_t timeout, uint32_t *eof_time);
|
||||
|
||||
void SetTag15693Uid(uint8_t *uid);
|
||||
#endif
|
||||
|
||||
@@ -152,7 +152,7 @@ static void tx_bit(bool bit) {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void tx_frame(uint32_t frame, uint8_t len) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD);
|
||||
|
||||
// wait for next tx timeslot
|
||||
last_frame_end += RWD_FRAME_WAIT;
|
||||
@@ -180,9 +180,7 @@ static void tx_frame(uint32_t frame, uint8_t len) {
|
||||
}
|
||||
|
||||
static uint32_t rx_frame(uint8_t len) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
|
||||
| FPGA_HF_READER_RX_XCORR_848_KHZ
|
||||
| FPGA_HF_READER_RX_XCORR_QUARTER);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
|
||||
|
||||
// hold sampling until card is expected to respond
|
||||
last_frame_end += TAG_FRAME_WAIT;
|
||||
@@ -210,9 +208,7 @@ static uint32_t rx_frame(uint8_t len) {
|
||||
|
||||
static bool rx_ack(void) {
|
||||
// change fpga into rx mode
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
|
||||
| FPGA_HF_READER_RX_XCORR_848_KHZ
|
||||
| FPGA_HF_READER_RX_XCORR_QUARTER);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
|
||||
|
||||
// hold sampling until card is expected to respond
|
||||
last_frame_end += TAG_FRAME_WAIT;
|
||||
@@ -279,14 +275,12 @@ static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
|
||||
static void init_reader(bool clear_mem) {
|
||||
// configure FPGA
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
|
||||
| FPGA_HF_READER_RX_XCORR_848_KHZ
|
||||
| FPGA_HF_READER_RX_XCORR_QUARTER);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
LED_A_ON();
|
||||
|
||||
// configure SSC with defaults
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
|
||||
|
||||
// re-claim GPIO_SSC_DOUT as GPIO and enable output
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
|
||||
@@ -303,12 +303,11 @@ static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
|
||||
static void init_tag(void) {
|
||||
// configure FPGA
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR
|
||||
| FPGA_HF_SIMULATOR_MODULATE_212K);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_212K);
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// configure SSC with defaults
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
|
||||
// first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
||||
@@ -181,7 +181,7 @@ void lf_init(bool reader, bool simulate) {
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
||||
|
||||
// When in reader mode, give the field a bit of time to settle.
|
||||
// 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered.
|
||||
|
||||
@@ -678,7 +678,7 @@ void AcquireTiType(void) {
|
||||
AT91C_BASE_SSC->SSC_TCMR = 0;
|
||||
// Transmit Frame Mode Register
|
||||
AT91C_BASE_SSC->SSC_TFMR = 0;
|
||||
// iceman, FpgaSetupSsc() ?? the code above? can it be replaced?
|
||||
// iceman, FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER) ?? the code above? can it be replaced?
|
||||
LED_D_ON();
|
||||
|
||||
// modulate antenna
|
||||
@@ -721,7 +721,7 @@ void AcquireTiType(void) {
|
||||
}
|
||||
|
||||
// reset SSC
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
||||
}
|
||||
|
||||
// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc
|
||||
@@ -2597,24 +2597,35 @@ void Cotag(uint32_t arg0) {
|
||||
LFSetupFPGAForADC(LF_FREQ2DIV(132), true);
|
||||
|
||||
//clear buffer now so it does not interfere with timing later
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
//send COTAG start pulse
|
||||
/*
|
||||
ON(740) OFF(2035)
|
||||
ON(3330) OFF(2035)
|
||||
ON(740) OFF(2035)
|
||||
ON(1000)
|
||||
*/
|
||||
|
||||
ON(800) OFF(2200)
|
||||
ON(3600) OFF(2200)
|
||||
ON(800) OFF(2200)
|
||||
ON(3400)
|
||||
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_FREQ2DIV(125));
|
||||
|
||||
switch (rawsignal) {
|
||||
case 0:
|
||||
doCotagAcquisition(40000);
|
||||
doCotagAcquisition();
|
||||
break;
|
||||
case 1:
|
||||
doCotagAcquisitionManchester();
|
||||
break;
|
||||
case 2:
|
||||
case 2: {
|
||||
DoAcquisition_config(false, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Turn the field off
|
||||
|
||||
@@ -51,11 +51,11 @@ void printConfig(void) {
|
||||
}
|
||||
|
||||
void printSamples(void) {
|
||||
DbpString(_CYAN_("LF Sampling memory"));
|
||||
Dbprintf(" decimation counter.....%d ", samples.dec_counter);
|
||||
Dbprintf(" sum.....%u ", samples.sum);
|
||||
Dbprintf(" counter.....%u ", samples.counter);
|
||||
Dbprintf(" total saved.....%u ", samples.total_saved);
|
||||
DbpString(_CYAN_("LF Sampling memory usage"));
|
||||
// Dbprintf(" decimation counter...%d", samples.dec_counter);
|
||||
// Dbprintf(" sum..................%u", samples.sum);
|
||||
Dbprintf(" counter.............." _YELLOW_("%u"), samples.counter);
|
||||
Dbprintf(" total saved.........." _YELLOW_("%u"), samples.total_saved);
|
||||
print_stack_usage();
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ void LFSetupFPGAForADC(int divisor, bool reader_field) {
|
||||
SpinDelay(50);
|
||||
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
||||
|
||||
// start a 1.5ticks is 1us
|
||||
StartTicks();
|
||||
@@ -480,19 +480,19 @@ void doT55x7Acquisition(size_t sample_size) {
|
||||
|
||||
#define COTAG_T1 384
|
||||
#define COTAG_T2 (COTAG_T1>>1)
|
||||
#define COTAG_ONE_THRESHOLD 128+10
|
||||
#define COTAG_ZERO_THRESHOLD 128-10
|
||||
#define COTAG_ONE_THRESHOLD 128+5
|
||||
#define COTAG_ZERO_THRESHOLD 128-5
|
||||
#ifndef COTAG_BITS
|
||||
#define COTAG_BITS 264
|
||||
#endif
|
||||
void doCotagAcquisition(size_t sample_size) {
|
||||
void doCotagAcquisition() {
|
||||
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
uint16_t bufsize = MIN(sample_size, BigBuf_max_traceLen());
|
||||
uint16_t bufsize = BigBuf_max_traceLen();
|
||||
|
||||
dest[0] = 0;
|
||||
uint8_t firsthigh = 0, firstlow = 0;
|
||||
uint16_t i = 0, noise_counter = 0, checker = 0;
|
||||
uint16_t i = 0, noise_counter = 0;
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("doCotagAcquisition - after init");
|
||||
@@ -504,21 +504,8 @@ void doCotagAcquisition(size_t sample_size) {
|
||||
if (BUTTON_PRESS())
|
||||
break;
|
||||
|
||||
if (checker == 4000) {
|
||||
if (data_available())
|
||||
break;
|
||||
else
|
||||
checker = 0;
|
||||
} else {
|
||||
++checker;
|
||||
}
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
LED_D_ON();
|
||||
}
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
@@ -551,9 +538,13 @@ void doCotagAcquisition(size_t sample_size) {
|
||||
}
|
||||
}
|
||||
|
||||
Dbprintf("doCotagAcquisition - %u high %u == 1 low %u == 1", i, firsthigh, firstlow);
|
||||
|
||||
// Ensure that DC offset removal and noise check is performed for any device-side processing
|
||||
removeSignalOffset(dest, bufsize);
|
||||
printSamples();
|
||||
computeSignalProperties(dest, bufsize);
|
||||
printSamples();
|
||||
}
|
||||
|
||||
uint32_t doCotagAcquisitionManchester(void) {
|
||||
@@ -565,7 +556,7 @@ uint32_t doCotagAcquisitionManchester(void) {
|
||||
uint8_t firsthigh = 0, firstlow = 0;
|
||||
uint8_t curr = 0, prev = 0;
|
||||
uint16_t sample_counter = 0, period = 0;
|
||||
uint16_t noise_counter = 0, checker = 0;
|
||||
uint16_t noise_counter = 0;
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("doCotagAcquisitionManchester - after init");
|
||||
@@ -576,15 +567,6 @@ uint32_t doCotagAcquisitionManchester(void) {
|
||||
|
||||
if (BUTTON_PRESS())
|
||||
break;
|
||||
|
||||
if (checker == 4000) {
|
||||
if ( data_available())
|
||||
break;
|
||||
else
|
||||
checker = 0;
|
||||
} else {
|
||||
++checker;
|
||||
}
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ typedef struct {
|
||||
* acquisition of Cotag LF signal. Similar to other LF, since the Cotag has such long datarate RF/384
|
||||
* and is Manchester?, we directly gather the manchester data into bigbuff
|
||||
**/
|
||||
void doCotagAcquisition(size_t sample_size);
|
||||
void doCotagAcquisition(void);
|
||||
uint32_t doCotagAcquisitionManchester(void);
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,7 +77,15 @@
|
||||
-- piwi 2019
|
||||
**/
|
||||
|
||||
/**
|
||||
add the possibility to do iCLASS on device only
|
||||
-- iceman 2020
|
||||
**/
|
||||
|
||||
#include "optimized_cipher.h"
|
||||
#include "optimized_elite.h"
|
||||
#include "optimized_ikeys.h"
|
||||
#include "optimized_cipherutils.h"
|
||||
|
||||
static const uint8_t opt_select_LUT[256] = {
|
||||
00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04,
|
||||
@@ -241,11 +249,34 @@ static void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) {
|
||||
opt_output(k, &_init, out);
|
||||
}
|
||||
|
||||
static void opt_MAC_N(uint8_t *k, uint8_t *input, uint8_t in_size, uint8_t *out) {
|
||||
State _init = {
|
||||
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
|
||||
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
|
||||
0x4c, // b
|
||||
0xE012 // t
|
||||
};
|
||||
|
||||
opt_suc(k, &_init, input, in_size, false);
|
||||
opt_output(k, &_init, out);
|
||||
}
|
||||
|
||||
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) {
|
||||
uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
opt_MAC(div_key_p, cc_nr_p, dest);
|
||||
memcpy(mac, dest, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
void opt_doReaderMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) {
|
||||
opt_suc(div_key_p, &_init, nr, 4, false);
|
||||
opt_output(div_key_p, &_init, mac);
|
||||
}
|
||||
|
||||
|
||||
void doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]) {
|
||||
uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
opt_MAC_N(div_key_p, in_p, in_size, dest);
|
||||
memcpy(mac, dest, 4);
|
||||
}
|
||||
|
||||
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
|
||||
@@ -257,7 +288,6 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
|
||||
};
|
||||
opt_suc(div_key_p, &_init, cc_p, 12, true);
|
||||
opt_output(div_key_p, &_init, mac);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,5 +321,24 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
|
||||
void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) {
|
||||
opt_suc(div_key_p, &_init, nr, 4, true);
|
||||
opt_output(div_key_p, &_init, mac);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite) {
|
||||
if (elite) {
|
||||
uint8_t keytable[128] = {0};
|
||||
uint8_t key_index[8] = {0};
|
||||
uint8_t key_sel[8] = { 0 };
|
||||
uint8_t key_sel_p[8] = { 0 };
|
||||
hash2(key, keytable);
|
||||
hash1(csn, key_index);
|
||||
for (uint8_t i = 0; i < 8 ; i++)
|
||||
key_sel[i] = keytable[key_index[i]];
|
||||
|
||||
//Permute from iclass format to standard format
|
||||
permutekey_rev(key_sel, key_sel_p);
|
||||
diversifyKey(csn, key_sel_p, div_key);
|
||||
} else {
|
||||
diversifyKey(csn, key, div_key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ typedef struct {
|
||||
/** The reader MAC is MAC(key, CC * NR )
|
||||
**/
|
||||
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
|
||||
|
||||
void opt_doReaderMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p);
|
||||
|
||||
/**
|
||||
* The tag MAC is MAC(key, CC * NR * 32x0))
|
||||
*/
|
||||
@@ -46,4 +49,6 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p);
|
||||
*/
|
||||
void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p);
|
||||
|
||||
void doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]);
|
||||
void iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite);
|
||||
#endif // OPTIMIZED_CIPHER_H
|
||||
|
||||
140
armsrc/optimized_cipherutils.c
Normal file
140
armsrc/optimized_cipherutils.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*****************************************************************************
|
||||
* WARNING
|
||||
*
|
||||
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
|
||||
*
|
||||
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
|
||||
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
|
||||
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
|
||||
*
|
||||
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This file is part of loclass. It is a reconstructon of the cipher engine
|
||||
* used in iClass, and RFID techology.
|
||||
*
|
||||
* The implementation is based on the work performed by
|
||||
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
|
||||
* Milosch Meriac in the paper "Dismantling IClass".
|
||||
*
|
||||
* Copyright (C) 2014 Martin Holst Swende
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation, or, at your option, any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "optimized_cipherutils.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Return and remove the first bit (x0) in the stream : <x0 x1 x2 x3 ... xn >
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
bool headBit(BitstreamIn *stream) {
|
||||
int bytepos = stream->position >> 3; // divide by 8
|
||||
int bitpos = (stream->position++) & 7; // mask out 00000111
|
||||
return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1;
|
||||
}
|
||||
/**
|
||||
* @brief Return and remove the last bit (xn) in the stream: <x0 x1 x2 ... xn>
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
bool tailBit(BitstreamIn *stream) {
|
||||
int bitpos = stream->numbits - 1 - (stream->position++);
|
||||
|
||||
int bytepos = bitpos >> 3;
|
||||
bitpos &= 7;
|
||||
return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1;
|
||||
}
|
||||
/**
|
||||
* @brief Pushes bit onto the stream
|
||||
* @param stream
|
||||
* @param bit
|
||||
*/
|
||||
void pushBit(BitstreamOut *stream, bool bit) {
|
||||
int bytepos = stream->position >> 3; // divide by 8
|
||||
int bitpos = stream->position & 7;
|
||||
*(stream->buffer + bytepos) |= (bit) << (7 - bitpos);
|
||||
stream->position++;
|
||||
stream->numbits++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pushes the lower six bits onto the stream
|
||||
* as b0 b1 b2 b3 b4 b5 b6
|
||||
* @param stream
|
||||
* @param bits
|
||||
*/
|
||||
void push6bits(BitstreamOut *stream, uint8_t bits) {
|
||||
pushBit(stream, bits & 0x20);
|
||||
pushBit(stream, bits & 0x10);
|
||||
pushBit(stream, bits & 0x08);
|
||||
pushBit(stream, bits & 0x04);
|
||||
pushBit(stream, bits & 0x02);
|
||||
pushBit(stream, bits & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bitsLeft
|
||||
* @param stream
|
||||
* @return number of bits left in stream
|
||||
*/
|
||||
int bitsLeft(BitstreamIn *stream) {
|
||||
return stream->numbits - stream->position;
|
||||
}
|
||||
/**
|
||||
* @brief numBits
|
||||
* @param stream
|
||||
* @return Number of bits stored in stream
|
||||
*/
|
||||
void x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest) {
|
||||
while (len--) {
|
||||
dest[len] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t x_bytes_to_num(uint8_t *src, size_t len) {
|
||||
uint64_t num = 0;
|
||||
while (len--) {
|
||||
num = (num << 8) | (*src);
|
||||
src++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
uint8_t reversebytes(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
void reverse_arraybytes(uint8_t *arr, size_t len) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < len ; i++) {
|
||||
arr[i] = reversebytes(arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < len ; i++) {
|
||||
dest[i] = reversebytes(arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
66
armsrc/optimized_cipherutils.h
Normal file
66
armsrc/optimized_cipherutils.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*****************************************************************************
|
||||
* WARNING
|
||||
*
|
||||
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
|
||||
*
|
||||
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
|
||||
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
|
||||
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
|
||||
*
|
||||
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This file is part of loclass. It is a reconstructon of the cipher engine
|
||||
* used in iClass, and RFID techology.
|
||||
*
|
||||
* The implementation is based on the work performed by
|
||||
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
|
||||
* Milosch Meriac in the paper "Dismantling IClass".
|
||||
*
|
||||
* Copyright (C) 2014 Martin Holst Swende
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation, or, at your option, any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef CIPHERUTILS_H
|
||||
#define CIPHERUTILS_H
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint8_t numbits;
|
||||
uint8_t position;
|
||||
} BitstreamIn;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint8_t numbits;
|
||||
uint8_t position;
|
||||
} BitstreamOut;
|
||||
|
||||
bool headBit(BitstreamIn *stream);
|
||||
bool tailBit(BitstreamIn *stream);
|
||||
void pushBit(BitstreamOut *stream, bool bit);
|
||||
int bitsLeft(BitstreamIn *stream);
|
||||
|
||||
void push6bits(BitstreamOut *stream, uint8_t bits);
|
||||
void x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest);
|
||||
uint64_t x_bytes_to_num(uint8_t *src, size_t len);
|
||||
uint8_t reversebytes(uint8_t b);
|
||||
void reverse_arraybytes(uint8_t *arr, size_t len);
|
||||
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len);
|
||||
#endif // CIPHERUTILS_H
|
||||
238
armsrc/optimized_elite.c
Normal file
238
armsrc/optimized_elite.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/*****************************************************************************
|
||||
* WARNING
|
||||
*
|
||||
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
|
||||
*
|
||||
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
|
||||
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
|
||||
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
|
||||
*
|
||||
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This file is part of loclass. It is a reconstructon of the cipher engine
|
||||
* used in iClass, and RFID techology.
|
||||
*
|
||||
* The implementation is based on the work performed by
|
||||
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
|
||||
* Milosch Meriac in the paper "Dismantling IClass".
|
||||
*
|
||||
* Copyright (C) 2014 Martin Holst Swende
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation, or, at your option, any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "optimized_elite.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "mbedtls/des.h"
|
||||
#include "optimized_ikeys.h"
|
||||
|
||||
/**
|
||||
* @brief Permutes a key from standard NIST format to Iclass specific format
|
||||
* from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220
|
||||
*
|
||||
* If you permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below.
|
||||
*
|
||||
* 1 0 1 1 1 1 1 1 bf
|
||||
* 0 0 0 0 0 0 0 1 01
|
||||
* 0 0 1 0 1 1 0 1 2d
|
||||
* 0 0 1 0 1 0 1 0 2a
|
||||
* 1 1 1 1 1 0 0 1 f9
|
||||
* 0 1 0 0 0 1 0 0 44
|
||||
* 1 0 0 0 1 1 0 1 8d
|
||||
* 0 1 1 0 1 1 0 0 6c
|
||||
*
|
||||
* 8 0 b 8 b a 9 e
|
||||
* a d 9 8 b 7 0 a
|
||||
*
|
||||
* @param key
|
||||
* @param dest
|
||||
*/
|
||||
void permutekey(uint8_t key[8], uint8_t dest[8]) {
|
||||
int i;
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) |
|
||||
(((key[6] & (0x80 >> i)) >> (7 - i)) << 6) |
|
||||
(((key[5] & (0x80 >> i)) >> (7 - i)) << 5) |
|
||||
(((key[4] & (0x80 >> i)) >> (7 - i)) << 4) |
|
||||
(((key[3] & (0x80 >> i)) >> (7 - i)) << 3) |
|
||||
(((key[2] & (0x80 >> i)) >> (7 - i)) << 2) |
|
||||
(((key[1] & (0x80 >> i)) >> (7 - i)) << 1) |
|
||||
(((key[0] & (0x80 >> i)) >> (7 - i)) << 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Permutes a key from iclass specific format to NIST format
|
||||
* @brief permutekey_rev
|
||||
* @param key
|
||||
* @param dest
|
||||
*/
|
||||
void permutekey_rev(uint8_t key[8], uint8_t dest[8]) {
|
||||
int i;
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) |
|
||||
(((key[1] & (0x80 >> i)) >> (7 - i)) << 6) |
|
||||
(((key[2] & (0x80 >> i)) >> (7 - i)) << 5) |
|
||||
(((key[3] & (0x80 >> i)) >> (7 - i)) << 4) |
|
||||
(((key[4] & (0x80 >> i)) >> (7 - i)) << 3) |
|
||||
(((key[5] & (0x80 >> i)) >> (7 - i)) << 2) |
|
||||
(((key[6] & (0x80 >> i)) >> (7 - i)) << 1) |
|
||||
(((key[7] & (0x80 >> i)) >> (7 - i)) << 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for hash1
|
||||
* @brief rr
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
static inline uint8_t rr(uint8_t val) {
|
||||
return val >> 1 | ((val & 1) << 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for hash1
|
||||
* @brief rl
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
static inline uint8_t rl(uint8_t val) {
|
||||
return val << 1 | ((val & 0x80) >> 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for hash1
|
||||
* @brief swap
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
static inline uint8_t swap(uint8_t val) {
|
||||
return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash1 takes CSN as input, and determines what bytes in the keytable will be used
|
||||
* when constructing the K_sel.
|
||||
* @param csn the CSN used
|
||||
* @param k output
|
||||
*/
|
||||
void hash1(uint8_t csn[], uint8_t k[]) {
|
||||
k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7];
|
||||
k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7];
|
||||
k[2] = rr(swap(csn[2] + k[1]));
|
||||
k[3] = rl(swap(csn[3] + k[0]));
|
||||
k[4] = ~rr(csn[4] + k[2]) + 1;
|
||||
k[5] = ~rl(csn[5] + k[3]) + 1;
|
||||
k[6] = rr(csn[6] + (k[4] ^ 0x3c));
|
||||
k[7] = rl(csn[7] + (k[5] ^ 0xc3));
|
||||
|
||||
k[7] &= 0x7F;
|
||||
k[6] &= 0x7F;
|
||||
k[5] &= 0x7F;
|
||||
k[4] &= 0x7F;
|
||||
k[3] &= 0x7F;
|
||||
k[2] &= 0x7F;
|
||||
k[1] &= 0x7F;
|
||||
k[0] &= 0x7F;
|
||||
}
|
||||
/**
|
||||
Definition 14. Define the rotate key function rk : (F 82 ) 8 × N → (F 82 ) 8 as
|
||||
rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
|
||||
rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
|
||||
**/
|
||||
static void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) {
|
||||
memcpy(outp_key, key, 8);
|
||||
uint8_t j;
|
||||
while (n-- > 0) {
|
||||
for (j = 0; j < 8 ; j++)
|
||||
outp_key[j] = rl(outp_key[j]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static mbedtls_des_context ctx_enc;
|
||||
static mbedtls_des_context ctx_dec;
|
||||
|
||||
static void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
|
||||
uint8_t key_std_format[8] = {0};
|
||||
permutekey_rev(iclass_key, key_std_format);
|
||||
mbedtls_des_setkey_dec(&ctx_dec, key_std_format);
|
||||
mbedtls_des_crypt_ecb(&ctx_dec, input, output);
|
||||
}
|
||||
|
||||
static void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
|
||||
uint8_t key_std_format[8] = {0};
|
||||
permutekey_rev(iclass_key, key_std_format);
|
||||
mbedtls_des_setkey_enc(&ctx_enc, key_std_format);
|
||||
mbedtls_des_crypt_ecb(&ctx_enc, input, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select.
|
||||
* @param key unpermuted custom key
|
||||
* @param hash1 hash1
|
||||
* @param key_sel output key_sel=h[hash1[i]]
|
||||
*/
|
||||
void hash2(uint8_t *key64, uint8_t *outp_keytable) {
|
||||
/**
|
||||
*Expected:
|
||||
* High Security Key Table
|
||||
|
||||
00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
|
||||
10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
|
||||
20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
|
||||
30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
|
||||
40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
|
||||
50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
|
||||
60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
|
||||
70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
|
||||
|
||||
**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
|
||||
uint8_t key64_negated[8] = {0};
|
||||
uint8_t z[8][8] = {{0}, {0}};
|
||||
uint8_t temp_output[8] = {0};
|
||||
|
||||
//calculate complement of key
|
||||
int i;
|
||||
for (i = 0; i < 8; i++)
|
||||
key64_negated[i] = ~key64[i];
|
||||
|
||||
// Once again, key is on iclass-format
|
||||
desencrypt_iclass(key64, key64_negated, z[0]);
|
||||
|
||||
uint8_t y[8][8] = {{0}, {0}};
|
||||
|
||||
// y[0]=DES_dec(z[0],~key)
|
||||
// Once again, key is on iclass-format
|
||||
desdecrypt_iclass(z[0], key64_negated, y[0]);
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
rk(key64, i, temp_output);
|
||||
desdecrypt_iclass(temp_output, z[i - 1], z[i]);
|
||||
desencrypt_iclass(temp_output, y[i - 1], y[i]);
|
||||
}
|
||||
|
||||
if (outp_keytable != NULL) {
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
memcpy(outp_keytable + i * 16, y[i], 8);
|
||||
memcpy(outp_keytable + 8 + i * 16, z[i], 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
armsrc/optimized_elite.h
Normal file
62
armsrc/optimized_elite.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*****************************************************************************
|
||||
* WARNING
|
||||
*
|
||||
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
|
||||
*
|
||||
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
|
||||
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
|
||||
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
|
||||
*
|
||||
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This file is part of loclass. It is a reconstructon of the cipher engine
|
||||
* used in iClass, and RFID techology.
|
||||
*
|
||||
* The implementation is based on the work performed by
|
||||
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
|
||||
* Milosch Meriac in the paper "Dismantling IClass".
|
||||
*
|
||||
* Copyright (C) 2014 Martin Holst Swende
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation, or, at your option, any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef ELITE_CRACK_H
|
||||
#define ELITE_CRACK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void permutekey(uint8_t key[8], uint8_t dest[8]);
|
||||
/**
|
||||
* Permutes a key from iclass specific format to NIST format
|
||||
* @brief permutekey_rev
|
||||
* @param key
|
||||
* @param dest
|
||||
*/
|
||||
void permutekey_rev(uint8_t key[8], uint8_t dest[8]);
|
||||
/**
|
||||
* Hash1 takes CSN as input, and determines what bytes in the keytable will be used
|
||||
* when constructing the K_sel.
|
||||
* @param csn the CSN used
|
||||
* @param k output
|
||||
*/
|
||||
void hash1(uint8_t *csn, uint8_t *k);
|
||||
void hash2(uint8_t *key64, uint8_t *outp_keytable);
|
||||
|
||||
#endif
|
||||
324
armsrc/optimized_ikeys.c
Normal file
324
armsrc/optimized_ikeys.c
Normal file
@@ -0,0 +1,324 @@
|
||||
/*****************************************************************************
|
||||
* WARNING
|
||||
*
|
||||
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
|
||||
*
|
||||
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
|
||||
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
|
||||
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
|
||||
*
|
||||
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This file is part of loclass. It is a reconstructon of the cipher engine
|
||||
* used in iClass, and RFID techology.
|
||||
*
|
||||
* The implementation is based on the work performed by
|
||||
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
|
||||
* Milosch Meriac in the paper "Dismantling IClass".
|
||||
*
|
||||
* Copyright (C) 2014 Martin Holst Swende
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation, or, at your option, any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
From "Dismantling iclass":
|
||||
This section describes in detail the built-in key diversification algorithm of iClass.
|
||||
Besides the obvious purpose of deriving a card key from a master key, this
|
||||
algorithm intends to circumvent weaknesses in the cipher by preventing the
|
||||
usage of certain ‘weak’ keys. In order to compute a diversified key, the iClass
|
||||
reader first encrypts the card identity id with the master key K, using single
|
||||
DES. The resulting ciphertext is then input to a function called hash0 which
|
||||
outputs the diversified key k.
|
||||
|
||||
k = hash0(DES enc (id, K))
|
||||
|
||||
Here the DES encryption of id with master key K outputs a cryptogram c
|
||||
of 64 bits. These 64 bits are divided as c = x, y, z [0] , . . . , z [7] ∈ F 82 × F 82 × (F 62 ) 8
|
||||
which is used as input to the hash0 function. This function introduces some
|
||||
obfuscation by performing a number of permutations, complement and modulo
|
||||
operations, see Figure 2.5. Besides that, it checks for and removes patterns like
|
||||
similar key bytes, which could produce a strong bias in the cipher. Finally, the
|
||||
output of hash0 is the diversified card key k = k [0] , . . . , k [7] ∈ (F 82 ) 8 .
|
||||
|
||||
**/
|
||||
#include "optimized_ikeys.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include "mbedtls/des.h"
|
||||
#include "optimized_cipherutils.h"
|
||||
|
||||
uint8_t pi[35] = {
|
||||
0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D,
|
||||
0x2E, 0x33, 0x35, 0x39, 0x36, 0x3A, 0x3C, 0x47,
|
||||
0x4B, 0x4D, 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A,
|
||||
0x5C, 0x63, 0x65, 0x66, 0x69, 0x6A, 0x6C, 0x71,
|
||||
0x72, 0x74, 0x78
|
||||
};
|
||||
|
||||
static mbedtls_des_context ctx_enc;
|
||||
|
||||
/**
|
||||
* @brief The key diversification algorithm uses 6-bit bytes.
|
||||
* This implementation uses 64 bit uint to pack seven of them into one
|
||||
* variable. When they are there, they are placed as follows:
|
||||
* XXXX XXXX N0 .... N7, occupying the last 48 bits.
|
||||
*
|
||||
* This function picks out one from such a collection
|
||||
* @param all
|
||||
* @param n bitnumber
|
||||
* @return
|
||||
*/
|
||||
static uint8_t getSixBitByte(uint64_t c, int n) {
|
||||
return (c >> (42 - 6 * n)) & 0x3F;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Puts back a six-bit 'byte' into a uint64_t.
|
||||
* @param c buffer
|
||||
* @param z the value to place there
|
||||
* @param n bitnumber.
|
||||
*/
|
||||
static void pushbackSixBitByte(uint64_t *c, uint8_t z, int n) {
|
||||
//0x XXXX YYYY ZZZZ ZZZZ ZZZZ
|
||||
// ^z0 ^z7
|
||||
//z0: 1111 1100 0000 0000
|
||||
|
||||
uint64_t masked = z & 0x3F;
|
||||
uint64_t eraser = 0x3F;
|
||||
masked <<= 42 - 6 * n;
|
||||
eraser <<= 42 - 6 * n;
|
||||
|
||||
//masked <<= 6*n;
|
||||
//eraser <<= 6*n;
|
||||
|
||||
eraser = ~eraser;
|
||||
(*c) &= eraser;
|
||||
(*c) |= masked;
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Swaps the z-values.
|
||||
* If the input value has format XYZ0Z1...Z7, the output will have the format
|
||||
* XYZ7Z6...Z0 instead
|
||||
* @param c
|
||||
* @return
|
||||
*/
|
||||
static uint64_t swapZvalues(uint64_t c) {
|
||||
uint64_t newz = 0;
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 0), 7);
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 1), 6);
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 2), 5);
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 3), 4);
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 4), 3);
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 5), 2);
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 6), 1);
|
||||
pushbackSixBitByte(&newz, getSixBitByte(c, 7), 0);
|
||||
newz |= (c & 0xFFFF000000000000);
|
||||
return newz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 4 six-bit bytes chunked into a uint64_t,as 00..00a0a1a2a3
|
||||
*/
|
||||
static uint64_t ck(int i, int j, uint64_t z) {
|
||||
if (i == 1 && j == -1) {
|
||||
// ck(1, −1, z [0] . . . z [3] ) = z [0] . . . z [3]
|
||||
return z;
|
||||
} else if (j == -1) {
|
||||
// ck(i, −1, z [0] . . . z [3] ) = ck(i − 1, i − 2, z [0] . . . z [3] )
|
||||
return ck(i - 1, i - 2, z);
|
||||
}
|
||||
|
||||
if (getSixBitByte(z, i) == getSixBitByte(z, j)) {
|
||||
//ck(i, j − 1, z [0] . . . z [i] ← j . . . z [3] )
|
||||
uint64_t newz = 0;
|
||||
int c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
uint8_t val = getSixBitByte(z, c);
|
||||
if (c == i)
|
||||
pushbackSixBitByte(&newz, j, c);
|
||||
else
|
||||
pushbackSixBitByte(&newz, val, c);
|
||||
}
|
||||
return ck(i, j - 1, newz);
|
||||
} else {
|
||||
return ck(i, j - 1, z);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
Definition 8.
|
||||
Let the function check : (F 62 ) 8 → (F 62 ) 8 be defined as
|
||||
check(z [0] . . . z [7] ) = ck(3, 2, z [0] . . . z [3] ) · ck(3, 2, z [4] . . . z [7] )
|
||||
|
||||
where ck : N × N × (F 62 ) 4 → (F 62 ) 4 is defined as
|
||||
|
||||
ck(1, −1, z [0] . . . z [3] ) = z [0] . . . z [3]
|
||||
ck(i, −1, z [0] . . . z [3] ) = ck(i − 1, i − 2, z [0] . . . z [3] )
|
||||
ck(i, j, z [0] . . . z [3] ) =
|
||||
ck(i, j − 1, z [0] . . . z [i] ← j . . . z [3] ), if z [i] = z [j] ;
|
||||
ck(i, j − 1, z [0] . . . z [3] ), otherwise
|
||||
|
||||
otherwise.
|
||||
**/
|
||||
|
||||
static uint64_t check(uint64_t z) {
|
||||
//These 64 bits are divided as c = x, y, z [0] , . . . , z [7]
|
||||
|
||||
// ck(3, 2, z [0] . . . z [3] )
|
||||
uint64_t ck1 = ck(3, 2, z);
|
||||
|
||||
// ck(3, 2, z [4] . . . z [7] )
|
||||
uint64_t ck2 = ck(3, 2, z << 24);
|
||||
|
||||
//The ck function will place the values
|
||||
// in the middle of z.
|
||||
ck1 &= 0x00000000FFFFFF000000;
|
||||
ck2 &= 0x00000000FFFFFF000000;
|
||||
|
||||
return ck1 | ck2 >> 24;
|
||||
}
|
||||
|
||||
static void permute(BitstreamIn *p_in, uint64_t z, int l, int r, BitstreamOut *out) {
|
||||
if (bitsLeft(p_in) == 0)
|
||||
return;
|
||||
|
||||
bool pn = tailBit(p_in);
|
||||
if (pn) { // pn = 1
|
||||
uint8_t zl = getSixBitByte(z, l);
|
||||
|
||||
push6bits(out, zl + 1);
|
||||
permute(p_in, z, l + 1, r, out);
|
||||
} else { // otherwise
|
||||
uint8_t zr = getSixBitByte(z, r);
|
||||
|
||||
push6bits(out, zr);
|
||||
permute(p_in, z, l, r + 1, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*Definition 11. Let the function hash0 : F 82 × F 82 × (F 62 ) 8 → (F 82 ) 8 be defined as
|
||||
* hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where
|
||||
* z'[i] = (z[i] mod (63-i)) + i i = 0...3
|
||||
* z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3
|
||||
* ẑ = check(z');
|
||||
* @param c
|
||||
* @param k this is where the diversified key is put (should be 8 bytes)
|
||||
* @return
|
||||
*/
|
||||
void hash0(uint64_t c, uint8_t k[8]) {
|
||||
c = swapZvalues(c);
|
||||
|
||||
//These 64 bits are divided as c = x, y, z [0] , . . . , z [7]
|
||||
// x = 8 bits
|
||||
// y = 8 bits
|
||||
// z0-z7 6 bits each : 48 bits
|
||||
uint8_t x = (c & 0xFF00000000000000) >> 56;
|
||||
uint8_t y = (c & 0x00FF000000000000) >> 48;
|
||||
uint64_t zP = 0;
|
||||
|
||||
for (int n = 0; n < 4 ; n++) {
|
||||
uint8_t zn = getSixBitByte(c, n);
|
||||
uint8_t zn4 = getSixBitByte(c, n + 4);
|
||||
uint8_t _zn = (zn % (63 - n)) + n;
|
||||
uint8_t _zn4 = (zn4 % (64 - n)) + n;
|
||||
pushbackSixBitByte(&zP, _zn, n);
|
||||
pushbackSixBitByte(&zP, _zn4, n + 4);
|
||||
}
|
||||
|
||||
uint64_t zCaret = check(zP);
|
||||
uint8_t p = pi[x % 35];
|
||||
|
||||
if (x & 1) //Check if x7 is 1
|
||||
p = ~p;
|
||||
|
||||
BitstreamIn p_in = { &p, 8, 0 };
|
||||
uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
BitstreamOut out = {outbuffer, 0, 0};
|
||||
permute(&p_in, zCaret, 0, 4, &out); //returns 48 bits? or 6 8-bytes
|
||||
|
||||
//Out is now a buffer containing six-bit bytes, should be 48 bits
|
||||
// if all went well
|
||||
//Shift z-values down onto the lower segment
|
||||
|
||||
uint64_t zTilde = x_bytes_to_num(outbuffer, sizeof(outbuffer));
|
||||
|
||||
zTilde >>= 16;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// the key on index i is first a bit from y
|
||||
// then six bits from z,
|
||||
// then a bit from p
|
||||
|
||||
// Init with zeroes
|
||||
k[i] = 0;
|
||||
// First, place yi leftmost in k
|
||||
//k[i] |= (y << i) & 0x80 ;
|
||||
|
||||
// First, place y(7-i) leftmost in k
|
||||
k[i] |= (y << (7 - i)) & 0x80 ;
|
||||
|
||||
uint8_t zTilde_i = getSixBitByte(zTilde, i);
|
||||
// zTildeI is now on the form 00XXXXXX
|
||||
// with one leftshift, it'll be
|
||||
// 0XXXXXX0
|
||||
// So after leftshift, we can OR it into k
|
||||
// However, when doing complement, we need to
|
||||
// again MASK 0XXXXXX0 (0x7E)
|
||||
zTilde_i <<= 1;
|
||||
|
||||
//Finally, add bit from p or p-mod
|
||||
//Shift bit i into rightmost location (mask only after complement)
|
||||
uint8_t p_i = p >> i & 0x1;
|
||||
|
||||
if (k[i]) { // yi = 1
|
||||
k[i] |= ~zTilde_i & 0x7E;
|
||||
k[i] |= p_i & 1;
|
||||
k[i] += 1;
|
||||
|
||||
} else { // otherwise
|
||||
k[i] |= zTilde_i & 0x7E;
|
||||
k[i] |= (~p_i) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Performs Elite-class key diversification
|
||||
* @param csn
|
||||
* @param key
|
||||
* @param div_key
|
||||
*/
|
||||
void diversifyKey(uint8_t *csn, uint8_t *key, uint8_t *div_key) {
|
||||
// Prepare the DES key
|
||||
mbedtls_des_setkey_enc(&ctx_enc, key);
|
||||
|
||||
uint8_t crypted_csn[8] = {0};
|
||||
|
||||
// Calculate DES(CSN, KEY)
|
||||
mbedtls_des_crypt_ecb(&ctx_enc, csn, crypted_csn);
|
||||
|
||||
//Calculate HASH0(DES))
|
||||
uint64_t c_csn = x_bytes_to_num(crypted_csn, sizeof(crypted_csn));
|
||||
|
||||
hash0(c_csn, div_key);
|
||||
}
|
||||
|
||||
69
armsrc/optimized_ikeys.h
Normal file
69
armsrc/optimized_ikeys.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*****************************************************************************
|
||||
* WARNING
|
||||
*
|
||||
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
|
||||
*
|
||||
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
|
||||
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
|
||||
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
|
||||
*
|
||||
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This file is part of loclass. It is a reconstructon of the cipher engine
|
||||
* used in iClass, and RFID techology.
|
||||
*
|
||||
* The implementation is based on the work performed by
|
||||
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
|
||||
* Milosch Meriac in the paper "Dismantling IClass".
|
||||
*
|
||||
* Copyright (C) 2014 Martin Holst Swende
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation, or, at your option, any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef IKEYS_H
|
||||
#define IKEYS_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*Definition 11. Let the function hash0 : F 82 × F 82 × (F 62 ) 8 → (F 82 ) 8 be defined as
|
||||
* hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where
|
||||
* z'[i] = (z[i] mod (63-i)) + i i = 0...3
|
||||
* z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3
|
||||
* ẑ = check(z');
|
||||
* @param c
|
||||
* @param k this is where the diversified key is put (should be 8 bytes)
|
||||
* @return
|
||||
*/
|
||||
void hash0(uint64_t c, uint8_t k[8]);
|
||||
/**
|
||||
* @brief Performs Elite-class key diversification
|
||||
* @param csn
|
||||
* @param key
|
||||
* @param div_key
|
||||
*/
|
||||
|
||||
void diversifyKey(uint8_t csn[8], uint8_t key[8], uint8_t div_key[8]);
|
||||
/**
|
||||
* @brief Permutes a key from standard NIST format to Iclass specific format
|
||||
* @param key
|
||||
* @param dest
|
||||
*/
|
||||
|
||||
#endif // IKEYS_H
|
||||
@@ -472,16 +472,20 @@ int rdv40_spiffs_is_symlink(const char *s) {
|
||||
// ATTENTION : you must NOT provide the whole filename (so please do not include the .lnk extension)
|
||||
// TODO : integrate in read_function
|
||||
int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION( //
|
||||
char linkdest[SPIFFS_OBJ_NAME_LEN]; //
|
||||
char linkfilename[SPIFFS_OBJ_NAME_LEN]; //
|
||||
RDV40_SPIFFS_SAFE_FUNCTION(
|
||||
char linkdest[SPIFFS_OBJ_NAME_LEN];
|
||||
char linkfilename[SPIFFS_OBJ_NAME_LEN];
|
||||
sprintf(linkfilename, "%s.lnk", filename);
|
||||
if (DBGLEVEL > 1) Dbprintf("Linkk real filename is destination is : %s", linkfilename);
|
||||
|
||||
if (DBGLEVEL > 1) Dbprintf("Linkk real filename is : " _YELLOW_("%s"), linkfilename);
|
||||
|
||||
read_from_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
|
||||
if (DBGLEVEL > 1) Dbprintf("Symlink destination is : %s", linkdest);
|
||||
read_from_spiffs((char *)linkdest, (uint8_t *)dst, size); //
|
||||
)
|
||||
}
|
||||
|
||||
if (DBGLEVEL > 1) Dbprintf("Symlink destination is : " _YELLOW_("%s"), linkdest);
|
||||
|
||||
read_from_spiffs((char *)linkdest, (uint8_t *)dst, size);
|
||||
)
|
||||
}
|
||||
|
||||
// BEWARE ! This function is DESTRUCTIVE as it will UPDATE an existing symlink
|
||||
// Since it creates a .lnk extension file it may be minor to mistake the order of arguments
|
||||
@@ -496,10 +500,10 @@ int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RD
|
||||
// rdv40_spiffs_read_as_symlink((uint8_t *)"world",(uint8_t *) buffer, orig_file_size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
// TODO : FORBID creating a symlink with a basename (before.lnk) which already exists as a file !
|
||||
int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION( //
|
||||
char linkfilename[SPIFFS_OBJ_NAME_LEN]; //
|
||||
RDV40_SPIFFS_SAFE_FUNCTION(
|
||||
char linkfilename[SPIFFS_OBJ_NAME_LEN];
|
||||
sprintf(linkfilename, "%s.lnk", filename);
|
||||
write_to_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN); //
|
||||
write_to_spiffs((char *)linkfilename, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -510,20 +514,20 @@ int rdv40_spiffs_make_symlink(char *linkdest, char *filename, RDV40SpiFFSSafetyL
|
||||
// preexistance, avoiding a link being created if filename exists, or avoiding a file being created if
|
||||
// symlink exists with same name
|
||||
int rdv40_spiffs_read_as_filetype(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) {
|
||||
RDV40_SPIFFS_SAFE_FUNCTION( //
|
||||
RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename); //
|
||||
switch (filetype) {
|
||||
case RDV40_SPIFFS_FILETYPE_REAL:
|
||||
rdv40_spiffs_read((char *)filename, (uint8_t *)dst, size, level);
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_SYMLINK:
|
||||
rdv40_spiffs_read_as_symlink((char *)filename, (uint8_t *)dst, size, level);
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_BOTH:
|
||||
case RDV40_SPIFFS_FILETYPE_UNKNOWN:
|
||||
default:
|
||||
RDV40_SPIFFS_SAFE_FUNCTION(
|
||||
RDV40SpiFFSFileType filetype = filetype_in_spiffs((char *)filename);
|
||||
switch (filetype) {
|
||||
case RDV40_SPIFFS_FILETYPE_REAL:
|
||||
rdv40_spiffs_read((char *)filename, (uint8_t *)dst, size, level);
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_SYMLINK:
|
||||
rdv40_spiffs_read_as_symlink((char *)filename, (uint8_t *)dst, size, level);
|
||||
break;
|
||||
case RDV40_SPIFFS_FILETYPE_BOTH:
|
||||
case RDV40_SPIFFS_FILETYPE_UNKNOWN:
|
||||
default:
|
||||
;
|
||||
} //
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -552,7 +556,7 @@ void rdv40_spiffs_safe_print_fsinfo(void) {
|
||||
Dbprintf(" Max Path Length............" _YELLOW_("%d")" chars", fsinfo.maxPathLength);
|
||||
DbpString("");
|
||||
Dbprintf(" filesystem size used available use% mounted");
|
||||
Dbprintf(" spiffs %6d B %6d B %6d B"_YELLOW_("%2d%")" /"
|
||||
Dbprintf(" spiffs %6d B %6d B %6d B " _YELLOW_("%2d%")" /"
|
||||
, fsinfo.totalBytes
|
||||
, fsinfo.usedBytes
|
||||
, fsinfo.freeBytes
|
||||
@@ -601,6 +605,37 @@ void rdv40_spiffs_safe_print_tree(uint8_t banner) {
|
||||
rdv40_spiffs_lazy_mount_rollback(changed);
|
||||
}
|
||||
|
||||
void rdv40_spiffs_safe_wipe(void) {
|
||||
|
||||
int changed = rdv40_spiffs_lazy_mount();
|
||||
|
||||
spiffs_DIR d;
|
||||
struct spiffs_dirent e;
|
||||
struct spiffs_dirent *pe = &e;
|
||||
SPIFFS_opendir(&fs, "/", &d);
|
||||
|
||||
while ((pe = SPIFFS_readdir(&d, pe))) {
|
||||
|
||||
if (rdv40_spiffs_is_symlink((const char *)pe->name)) {
|
||||
|
||||
char linkdest[SPIFFS_OBJ_NAME_LEN];
|
||||
read_from_spiffs((char *)pe->name, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
|
||||
|
||||
remove_from_spiffs(linkdest);
|
||||
Dbprintf(".lnk removed %s", pe->name);
|
||||
|
||||
remove_from_spiffs((char *)pe->name);
|
||||
Dbprintf("removed %s", linkdest);
|
||||
|
||||
} else {
|
||||
remove_from_spiffs((char *)pe->name);
|
||||
Dbprintf("removed %s", pe->name);
|
||||
}
|
||||
}
|
||||
|
||||
SPIFFS_closedir(&d);
|
||||
rdv40_spiffs_lazy_mount_rollback(changed);
|
||||
}
|
||||
|
||||
// Selftest function
|
||||
void test_spiffs(void) {
|
||||
|
||||
@@ -58,6 +58,8 @@ int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel leve
|
||||
uint32_t size_in_spiffs(const char *filename);
|
||||
int exists_in_spiffs(const char *filename);
|
||||
|
||||
void rdv40_spiffs_safe_wipe(void);
|
||||
|
||||
#define SPIFFS_OK 0
|
||||
#define SPIFFS_ERR_NOT_MOUNTED -10000
|
||||
#define SPIFFS_ERR_FULL -10001
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
void ReadThinFilm(void) {
|
||||
|
||||
clear_trace();
|
||||
|
||||
set_tracing(true);
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
@@ -60,15 +59,19 @@ static uint16_t ReadReaderField(void) {
|
||||
}
|
||||
|
||||
static void CodeThinfilmAsTag(const uint8_t *cmd, uint16_t len) {
|
||||
ToSendReset();
|
||||
|
||||
tosend_reset();
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
uint8_t b = cmd[i];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
ToSend[++ToSendMax] = (b & 0x80) ? SEC_D : SEC_E;
|
||||
ts->buf[++ts->max] = (b & 0x80) ? SEC_D : SEC_E;
|
||||
b <<= 1;
|
||||
}
|
||||
}
|
||||
ToSendMax++;
|
||||
ts->max++;
|
||||
}
|
||||
|
||||
static int EmSendCmdThinfilmRaw(uint8_t *resp, uint16_t respLen) {
|
||||
@@ -122,7 +125,7 @@ void SimulateThinFilm(uint8_t *data, size_t len) {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
|
||||
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
@@ -132,6 +135,8 @@ void SimulateThinFilm(uint8_t *data, size_t len) {
|
||||
|
||||
uint16_t hf_baseline = ReadReaderField();
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
// Start the timer
|
||||
StartCountSspClk();
|
||||
|
||||
@@ -147,7 +152,8 @@ void SimulateThinFilm(uint8_t *data, size_t len) {
|
||||
if (hf_av < hf_baseline)
|
||||
hf_baseline = hf_av;
|
||||
if (hf_av > hf_baseline + 10) {
|
||||
EmSendCmdThinfilmRaw(ToSend, ToSendMax);
|
||||
|
||||
EmSendCmdThinfilmRaw(ts->buf, ts->max);
|
||||
if (!reader_detected) {
|
||||
LED_B_ON();
|
||||
//Dbprintf("Reader detected, start beaming data");
|
||||
|
||||
@@ -117,47 +117,61 @@ uint32_t RAMFUNC GetCountUS(void) {
|
||||
void StartCountSspClk(void) {
|
||||
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); // Enable Clock to all timers
|
||||
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1 // XC0 Clock = TIOA1
|
||||
| AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none
|
||||
| AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0
|
||||
| AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none
|
||||
| AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0
|
||||
|
||||
// configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs:
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // disable TC1
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz
|
||||
| AT91C_TC_CPCSTOP // Stop clock on RC compare
|
||||
| AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event
|
||||
| AT91C_TC_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16)
|
||||
| AT91C_TC_ENETRG // Enable external trigger event
|
||||
| AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare
|
||||
| AT91C_TC_WAVE // Waveform Mode
|
||||
| AT91C_TC_AEEVT_SET // Set TIOA1 on external event
|
||||
| AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare
|
||||
AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04
|
||||
| AT91C_TC_CPCSTOP // Stop clock on RC compare
|
||||
| AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event
|
||||
| AT91C_TC_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16)
|
||||
| AT91C_TC_ENETRG // Enable external trigger event
|
||||
| AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare
|
||||
| AT91C_TC_WAVE // Waveform Mode
|
||||
| AT91C_TC_AEEVT_SET // Set TIOA1 on external event
|
||||
| AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare
|
||||
AT91C_BASE_TC1->TC_RC = 0x01; // RC Compare value = 0x01, pulse width to TC0
|
||||
|
||||
// use TC0 to count TIOA1 pulses
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // disable TC0
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0 // TC0 clock = XC0 clock = TIOA1
|
||||
| AT91C_TC_WAVE // Waveform Mode
|
||||
| AT91C_TC_WAVESEL_UP // just count
|
||||
| AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare
|
||||
| AT91C_TC_ACPC_SET; // Set TIOA0 on RC Compare
|
||||
| AT91C_TC_WAVE // Waveform Mode
|
||||
| AT91C_TC_WAVESEL_UP // just count
|
||||
| AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare
|
||||
| AT91C_TC_ACPC_SET; // Set TIOA0 on RC Compare
|
||||
AT91C_BASE_TC0->TC_RA = 1; // RA Compare value = 1; pulse width to TC2
|
||||
AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow
|
||||
|
||||
// use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk)
|
||||
AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2
|
||||
AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0
|
||||
| AT91C_TC_WAVE // Waveform Mode
|
||||
| AT91C_TC_WAVESEL_UP; // just count
|
||||
| AT91C_TC_WAVE // Waveform Mode
|
||||
| AT91C_TC_WAVESEL_UP; // just count
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC0
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC1
|
||||
AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC2
|
||||
|
||||
//
|
||||
// synchronize the counter with the ssp_frame signal.
|
||||
// Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present
|
||||
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame)
|
||||
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low
|
||||
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high
|
||||
// Note: FPGA must be in a FPGA mode with SSC transfer, otherwise SSC_FRAME and SSC_CLK signals would not be present
|
||||
//
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame)
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high; 1st ssp_clk after start of frame
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK); // wait for ssp_clk to go low;
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high; 2nd ssp_clk after start of frame
|
||||
if ((AT91C_BASE_SSC->SSC_RFMR & SSC_FRAME_MODE_BITS_IN_WORD(32)) == SSC_FRAME_MODE_BITS_IN_WORD(16)) { // 16bit frame
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK); // wait for ssp_clk to go low;
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high; 3rd ssp_clk after start of frame
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK); // wait for ssp_clk to go low;
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high; 4th ssp_clk after start of frame
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK); // wait for ssp_clk to go low;
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high; 5th ssp_clk after start of frame
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK); // wait for ssp_clk to go low;
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high; 6th ssp_clk after start of frame
|
||||
}
|
||||
|
||||
// note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame
|
||||
// it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge
|
||||
|
||||
@@ -19,53 +19,69 @@
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_flashmemspiffs_remove(void) {
|
||||
PrintAndLogEx(NORMAL, "Remove a file from spiffs filesystem");
|
||||
PrintAndLogEx(NORMAL, " Usage: mem spiffs remove <filename>");
|
||||
PrintAndLogEx(NORMAL, "Remove a file from spiffs filesystem\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs remove <filename>");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs remove lasttag.bin"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_rename(void) {
|
||||
PrintAndLogEx(NORMAL, "Rename/move a file in spiffs filesystem");
|
||||
PrintAndLogEx(NORMAL, " Usage: mem spiffs rename <source> <destination>");
|
||||
PrintAndLogEx(NORMAL, "Rename/move a file in spiffs filesystem\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs rename <source> <destination>");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs rename lasttag.bin oldtag.bin"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_copy(void) {
|
||||
PrintAndLogEx(NORMAL, "Copy a file to another (destructively) in spiffs filesystem");
|
||||
PrintAndLogEx(NORMAL, " Usage: mem spiffs copy <source> <destination>");
|
||||
PrintAndLogEx(NORMAL, "Copy a file to another (destructively) in spiffs filesystem\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs copy <source> <destination>");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs copy lasttag.bin lasttag_cpy.bin"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_dump(void) {
|
||||
PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console");
|
||||
PrintAndLogEx(NORMAL, "Size is handled by first sending a STAT command against file existence");
|
||||
PrintAndLogEx(NORMAL, " Usage: mem spiffs dump o <filename> [f <file name> [e]] [p]");
|
||||
PrintAndLogEx(NORMAL, " o <filename> : filename in SPIFFS");
|
||||
PrintAndLogEx(NORMAL, " f <filename> : file name to save to");
|
||||
PrintAndLogEx(NORMAL, " p : print dump in console");
|
||||
PrintAndLogEx(NORMAL, " e : also save in EML format (good for tags save and dictonnary files)");
|
||||
PrintAndLogEx(NORMAL, "Size is handled by first sending a STAT command against file existence\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs dump o <filename> [f <file name> [e]] [p]");
|
||||
PrintAndLogEx(NORMAL, " o <filename> - filename in SPIFFS");
|
||||
PrintAndLogEx(NORMAL, " f <filename> - file name to save to <w/o .bin>");
|
||||
PrintAndLogEx(NORMAL, " p - print dump in console");
|
||||
PrintAndLogEx(NORMAL, " e - also save in EML format (good for tags save and dictonnary files)");
|
||||
PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem spiffs dump o hf_colin/lasttag f lasttag e");
|
||||
PrintAndLogEx(NORMAL, " mem spiffs dump o hf_colin/lasttag p");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin f lasttag e"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin p"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmemspiffs_load(void) {
|
||||
PrintAndLogEx(NORMAL, "Uploads binary-wise file into device filesystem");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs load o <filename> f <filename>");
|
||||
PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first");
|
||||
PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)");
|
||||
PrintAndLogEx(NORMAL, " o <filename> : destination filename");
|
||||
PrintAndLogEx(NORMAL, " f <filename> : local filename");
|
||||
PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs load o <filename> f <filename>");
|
||||
PrintAndLogEx(NORMAL, " o <filename> - destination filename");
|
||||
PrintAndLogEx(NORMAL, " f <filename> - local filename");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem spiffs load f myfile o myapp.conf");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs load f myfile o myapp.conf"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int usage_flashmemspiffs_wipe(void) {
|
||||
PrintAndLogEx(NORMAL, "wipes all files on the device filesystem " _RED_("* Warning *"));
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spiffs wipe [h]");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs wipe"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int CmdFlashMemSpiFFSMount(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
clearCommandBuffer();
|
||||
@@ -277,12 +293,12 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) {
|
||||
}
|
||||
|
||||
if ((filename[0] == '\0') && (!print)) {
|
||||
PrintAndLogEx(FAILED, "No print asked and Local dump Filename missing or invalid");
|
||||
PrintAndLogEx(FAILED, "No print asked and local dump filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (destfilename[0] == '\0') {
|
||||
PrintAndLogEx(FAILED, "SPIFFS Filename missing or invalid");
|
||||
PrintAndLogEx(FAILED, "SPIFFS filename missing or invalid");
|
||||
errors = true;
|
||||
}
|
||||
|
||||
@@ -320,9 +336,16 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) {
|
||||
}
|
||||
|
||||
if (filename[0] != '\0') {
|
||||
saveFile(filename, "", dump, len);
|
||||
saveFile(filename, ".bin", dump, len);
|
||||
if (eml) {
|
||||
saveFileEML(filename, dump, len, 16);
|
||||
uint8_t eml_len = 16;
|
||||
|
||||
if (strstr(filename, "class") != NULL)
|
||||
eml_len = 8;
|
||||
else if (strstr(filename, "mfu") != NULL)
|
||||
eml_len = 4;
|
||||
|
||||
saveFileEML(filename, dump, len, eml_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,6 +420,23 @@ out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSWipe(const char *Cmd) {
|
||||
|
||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (ctmp == 'h') {
|
||||
return usage_flashmemspiffs_wipe();
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Wiping all files from SPIFFS FileSystem");
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0);
|
||||
WaitForResponse(CMD_SPIFFS_WIPE, &resp);
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
PrintAndLogEx(HINT, "Try use '" _YELLOW_("mem spiffs tree") "' to verify.");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
|
||||
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
@@ -457,20 +497,18 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
|
||||
static command_t CommandTable[] = {
|
||||
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{
|
||||
"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash,
|
||||
"Copy a file to another (destructively) in SPIFFS FileSystem in FlashMEM (spiffs)"
|
||||
},
|
||||
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented Filesystem"},
|
||||
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print filesystem info and usage statistics (spiffs)"},
|
||||
{"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS Filesystem (spiffs)"},
|
||||
{"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS Filesystem if not already mounted (spiffs)"},
|
||||
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations (require wiping pages 0 and 1)"},
|
||||
{"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash Memory FileSystem Tree (spiffs)"},
|
||||
{"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented Filesystem"},
|
||||
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print filesystem info and usage statistics (spiffs)"},
|
||||
{"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS Filesystem (spiffs)"},
|
||||
{"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS Filesystem if not already mounted (spiffs)"},
|
||||
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS FileSystem in FlashMEM (spiffs)"},
|
||||
{"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations (require wiping pages 0 and 1)"},
|
||||
{"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash Memory FileSystem Tree (spiffs)"},
|
||||
{"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS Filesystem if not already mounted (spiffs)"},
|
||||
{"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS FileSystem." _RED_("* dangerous *") },
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -129,6 +129,15 @@ int CmdHFSearch(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for iCLASS / PicoPass tag...");
|
||||
if (IfPm3Iclass()) {
|
||||
if (read_iclass_csn(false, false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iCLASS tag / PicoPass tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for LEGIC tag...");
|
||||
if (IfPm3Legicrf()) {
|
||||
@@ -156,7 +165,6 @@ int CmdHFSearch(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
/*
|
||||
// 14b and iclass is the longest test (put last)
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for CryptoRF tag...");
|
||||
if (IfPm3Iso14443b()) {
|
||||
@@ -167,7 +175,7 @@ int CmdHFSearch(const char *Cmd) {
|
||||
}
|
||||
*/
|
||||
|
||||
// 14b and iclass is the longest test (put last)
|
||||
// 14b is the longest test (put last)
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag...");
|
||||
if (IfPm3Iso14443b()) {
|
||||
@@ -177,14 +185,6 @@ int CmdHFSearch(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
PROMPT_CLEARLINE;
|
||||
PrintAndLogEx(INPLACE, " Searching for iClass / PicoPass tag...");
|
||||
if (IfPm3Iclass()) {
|
||||
if (readIclass(false, false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") " found\n");
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
PROMPT_CLEARLINE;
|
||||
if (res != PM3_SUCCESS) {
|
||||
|
||||
@@ -134,7 +134,7 @@ static bool waitCmd14b(bool verbose) {
|
||||
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
|
||||
if ((resp.oldarg[0] & 0xFF) > 0) return false;
|
||||
|
||||
@@ -314,7 +314,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0];
|
||||
if (status == 0) {
|
||||
@@ -330,7 +330,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0];
|
||||
if (status == 0) {
|
||||
@@ -515,7 +515,7 @@ static bool HF14B_Std_Info(bool verbose) {
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
switch_off_field_14b();
|
||||
return false;
|
||||
@@ -556,7 +556,7 @@ static bool HF14B_ST_Info(bool verbose) {
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
return false;
|
||||
}
|
||||
@@ -611,7 +611,7 @@ static bool HF14B_ST_Reader(bool verbose) {
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
return false;
|
||||
}
|
||||
@@ -651,7 +651,7 @@ static bool HF14B_Std_Reader(bool verbose) {
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
return false;
|
||||
}
|
||||
@@ -695,7 +695,7 @@ static bool HF14B_Other_Reader(void) {
|
||||
// clearCommandBuffer();
|
||||
// SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, 0, data, datalen);
|
||||
// PacketResponseNG resp;
|
||||
// WaitForResponse(CMD_ACK,&resp);
|
||||
// WaitForResponse(CMD_HF_ISO14443B_COMMAND,&resp);
|
||||
|
||||
// if (datalen > 2 ) {
|
||||
// PrintAndLogEx(NORMAL, "\n14443-3b tag found:");
|
||||
@@ -709,7 +709,7 @@ static bool HF14B_Other_Reader(void) {
|
||||
// clearCommandBuffer();
|
||||
// SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1);
|
||||
// PacketResponseNG resp;
|
||||
// WaitForResponse(CMD_ACK, &resp);
|
||||
// WaitForResponse(CMD_HF_ISO14443B_COMMAND, &resp);
|
||||
|
||||
// if (datalen > 0) {
|
||||
// PrintAndLogEx(NORMAL, "\n14443-3b tag found:");
|
||||
@@ -723,7 +723,7 @@ static bool HF14B_Other_Reader(void) {
|
||||
// clearCommandBuffer();
|
||||
// SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1);
|
||||
// PacketResponseNG resp;
|
||||
// WaitForResponse(CMD_ACK, &resp);
|
||||
// WaitForResponse(CMD_HF_ISO14443B_COMMAND, &resp);
|
||||
|
||||
// if (datalen > 0) {
|
||||
// PrintAndLogEx(NORMAL, "\n14443-3b tag found:");
|
||||
@@ -899,7 +899,7 @@ static int CmdHF14BDump(const char *Cmd) {
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0);
|
||||
|
||||
//select
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
||||
if (resp.oldarg[0]) {
|
||||
PrintAndLogEx(INFO, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]);
|
||||
goto out;
|
||||
@@ -915,7 +915,7 @@ static int CmdHF14BDump(const char *Cmd) {
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xFF;
|
||||
if (status > 0) {
|
||||
|
||||
@@ -973,12 +973,12 @@ static int CmdHF15Info(const char *Cmd) {
|
||||
|
||||
// Record Activity without enabling carrier
|
||||
//helptext
|
||||
static int CmdHF15Record(const char *Cmd) {
|
||||
static int CmdHF15Sniff(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_15_record();
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO15693_RAWADC, NULL, 0);
|
||||
SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1841,9 +1841,8 @@ static command_t CommandTable[] = {
|
||||
{"demod", CmdHF15Demod, AlwaysAvailable, "Demodulate ISO15693 from tag"},
|
||||
{"dump", CmdHF15Dump, IfPm3Iso15693, "Read all memory pages of an ISO15693 tag, save to file"},
|
||||
{"info", CmdHF15Info, IfPm3Iso15693, "Tag information"},
|
||||
// {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"},
|
||||
{"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"},
|
||||
{"raw", CmdHF15Raw, IfPm3Iso15693, "Send raw hex data to tag"},
|
||||
{"record", CmdHF15Record, IfPm3Iso15693, "Record Samples (ISO15693)"},
|
||||
{"read", CmdHF15Read, IfPm3Iso15693, "Read a block"},
|
||||
{"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO15693 reader"},
|
||||
{"readmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple Blocks"},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,8 @@ typedef struct iclass_prekey {
|
||||
|
||||
int CmdHFiClass(const char *Cmd);
|
||||
|
||||
int readIclass(bool loop, bool verbose);
|
||||
int info_iclass(void);
|
||||
int read_iclass_csn(bool loop, bool verbose);
|
||||
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);
|
||||
|
||||
|
||||
@@ -507,8 +507,10 @@ void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd[1] >= 0x2D && cmd[1] <= 0x9F) snprintf(exp, size, "Optional RFU");
|
||||
else if (cmd[1] >= 0xA0 && cmd[1] <= 0xDF) snprintf(exp, size, "Cust IC MFG dependent");
|
||||
if (cmd[1] > ISO15693_STAYQUIET && cmd[1] < ISO15693_READBLOCK) snprintf(exp, size, "Mandatory RFU");
|
||||
else if (cmd[1] > ISO15693_READ_MULTI_SECSTATUS && cmd[1] <= 0x9F) snprintf(exp, size, "Optional RFU");
|
||||
// else if (cmd[1] >= 0xA0 && cmd[1] <= 0xDF) snprintf(exp, size, "Cust IC MFG dependent");
|
||||
else if (cmd[1] > ISO15693_READ_SIGNATURE && cmd[1] <= 0xDF) snprintf(exp, size, "Cust IC MFG dependent");
|
||||
else if (cmd[1] >= 0xE0) snprintf(exp, size, "Proprietary IC MFG dependent");
|
||||
else
|
||||
snprintf(exp, size, "?");
|
||||
|
||||
@@ -4856,8 +4856,8 @@ static command_t CommandTable[] = {
|
||||
{"rdbl", CmdHF14AMfRdBl, IfPm3Iso14443a, "Read MIFARE classic block"},
|
||||
{"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE classic sector"},
|
||||
{"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE classic binary file to BLANK tag"},
|
||||
{"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE classic block"},
|
||||
{"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"},
|
||||
{"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE classic block"},
|
||||
// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
|
||||
{"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"},
|
||||
|
||||
@@ -382,7 +382,7 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
|
||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor);
|
||||
else if (major == 0x12 && minor == 0x00)
|
||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
|
||||
else if (major == 0x13 && minor == 0x00)
|
||||
else if (major == 0x33 && minor == 0x00)
|
||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
|
||||
else if (major == 0x30 && minor == 0x00)
|
||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
|
||||
@@ -644,8 +644,8 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
||||
return DESFIRE_EV1;
|
||||
if (major == 0x12 && minor == 0x00)
|
||||
return DESFIRE_EV2;
|
||||
// if (major == 0x13 && minor == 0x00)
|
||||
// return DESFIRE_EV3;
|
||||
if (major == 0x33 && minor == 0x00)
|
||||
return DESFIRE_EV3;
|
||||
if (major == 0x30 && minor == 0x00)
|
||||
return DESFIRE_LIGHT;
|
||||
if (major == 0x11 && minor == 0x00)
|
||||
|
||||
@@ -36,7 +36,7 @@ static int usage_dbg(void) {
|
||||
PrintAndLogEx(NORMAL, " 4 - print even debug messages in timing critical functions");
|
||||
PrintAndLogEx(NORMAL, " Note: this option therefore may cause malfunction itself");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " hw dbg 3");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hw dbg 3"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ static int usage_hw_detectreader(void) {
|
||||
PrintAndLogEx(NORMAL, " <type> L = 125/134 kHz, H = 13.56 MHz");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " hw detectreader L");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hw detectreader L"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ static int usage_hw_setmux(void) {
|
||||
PrintAndLogEx(NORMAL, " <type> Low peak, Low raw, Hi peak, Hi raw");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " hw setmux lopkd");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hw setmux lopkd"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -78,8 +78,8 @@ static int usage_hw_connect(void) {
|
||||
PrintAndLogEx(NORMAL, " b <baudrate> Baudrate");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " hw connect p "SERIAL_PORT_EXAMPLE_H);
|
||||
PrintAndLogEx(NORMAL, " hw connect p "SERIAL_PORT_EXAMPLE_H" b 115200");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hw connect p "SERIAL_PORT_EXAMPLE_H));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hw connect p "SERIAL_PORT_EXAMPLE_H" b 115200"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -486,9 +486,10 @@ static int CmdSetMux(const char *Cmd) {
|
||||
}
|
||||
|
||||
static int CmdStandalone(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
// (void)Cmd; // Cmd is not used so far
|
||||
uint8_t arg = param_get8ex(Cmd, 0, 0, 10);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_STANDALONE, NULL, 0);
|
||||
SendCommandNG(CMD_STANDALONE, (uint8_t *)&arg, sizeof(arg));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -606,23 +607,23 @@ static int CmdConnect(const char *Cmd) {
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"connect", CmdConnect, AlwaysAvailable, "connect Proxmark3 to serial port"},
|
||||
{"dbg", CmdDbg, IfPm3Present, "Set Proxmark3 debug level"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"connect", CmdConnect, AlwaysAvailable, "connect Proxmark3 to serial port"},
|
||||
{"dbg", CmdDbg, IfPm3Present, "Set Proxmark3 debug level"},
|
||||
{"detectreader", CmdDetectReader, IfPm3Present, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
|
||||
{"fpgaoff", CmdFPGAOff, IfPm3Present, "Set FPGA off"},
|
||||
{"lcd", CmdLCD, IfPm3Lcd, "<HEX command> <count> -- Send command/data to LCD"},
|
||||
{"lcdreset", CmdLCDReset, IfPm3Lcd, "Hardware reset LCD"},
|
||||
{"ping", CmdPing, IfPm3Present, "Test if the Proxmark3 is responsive"},
|
||||
{"readmem", CmdReadmem, IfPm3Present, "[address] -- Read memory at decimal address from flash"},
|
||||
{"reset", CmdReset, IfPm3Present, "Reset the Proxmark3"},
|
||||
{"setlfdivisor", CmdSetDivisor, IfPm3Present, "<19 - 255> -- Drive LF antenna at 12MHz/(divisor+1)"},
|
||||
{"setmux", CmdSetMux, IfPm3Present, "Set the ADC mux to a specific value"},
|
||||
{"standalone", CmdStandalone, IfPm3Present, "Jump to the standalone mode"},
|
||||
{"status", CmdStatus, IfPm3Present, "Show runtime status information about the connected Proxmark3"},
|
||||
{"tia", CmdTia, IfPm3Present, "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider"},
|
||||
{"tune", CmdTune, IfPm3Present, "Measure antenna tuning"},
|
||||
{"version", CmdVersion, IfPm3Present, "Show version information about the connected Proxmark3"},
|
||||
{"fpgaoff", CmdFPGAOff, IfPm3Present, "Set FPGA off"},
|
||||
{"lcd", CmdLCD, IfPm3Lcd, "<HEX command> <count> -- Send command/data to LCD"},
|
||||
{"lcdreset", CmdLCDReset, IfPm3Lcd, "Hardware reset LCD"},
|
||||
{"ping", CmdPing, IfPm3Present, "Test if the Proxmark3 is responsive"},
|
||||
{"readmem", CmdReadmem, IfPm3Present, "[address] -- Read memory at decimal address from flash"},
|
||||
{"reset", CmdReset, IfPm3Present, "Reset the Proxmark3"},
|
||||
{"setlfdivisor", CmdSetDivisor, IfPm3Present, "<19 - 255> -- Drive LF antenna at 12MHz/(divisor+1)"},
|
||||
{"setmux", CmdSetMux, IfPm3Present, "Set the ADC mux to a specific value"},
|
||||
{"standalone", CmdStandalone, IfPm3Present, "Jump to the standalone mode"},
|
||||
{"status", CmdStatus, IfPm3Present, "Show runtime status information about the connected Proxmark3"},
|
||||
{"tia", CmdTia, IfPm3Present, "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider"},
|
||||
{"tune", CmdTune, IfPm3Present, "Measure antenna tuning"},
|
||||
{"version", CmdVersion, IfPm3Present, "Show version information about the connected Proxmark3"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -608,10 +608,11 @@ int CmdEM4x50Dump(const char *Cmd) {
|
||||
em4x50_data_t etd;
|
||||
etd.pwd_given = false;
|
||||
etd.addr_given = false;
|
||||
|
||||
etd.newpwd_given = false;
|
||||
|
||||
char filename[FILE_PATH_SIZE] = {0x00};
|
||||
char *fptr = filename;
|
||||
|
||||
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
@@ -655,9 +656,9 @@ int CmdEM4x50Dump(const char *Cmd) {
|
||||
bool success = (resp.status & STATUS_SUCCESS) >> 1;
|
||||
if (success == false) {
|
||||
PrintAndLogEx(FAILED, "reading tag " _RED_("failed"));
|
||||
return PM3_ESOFT;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
||||
// structured format
|
||||
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||
prepare_result(resp.data.asBytes, 0, EM4X50_NO_WORDS - 1, words);
|
||||
|
||||
@@ -641,7 +641,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) {
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors) {
|
||||
if (errors || strlen(Cmd) == 0) {
|
||||
free(data);
|
||||
return usage_hitag_checkchallenges();
|
||||
}
|
||||
@@ -734,43 +734,61 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
||||
|
||||
|
||||
// Annotate HITAG protocol
|
||||
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_reader) {
|
||||
}
|
||||
|
||||
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response) {
|
||||
|
||||
// iceman: live decrypt of trace?
|
||||
if (is_response) {
|
||||
|
||||
uint8_t cmdbits = (cmd[0] & 0xC0) >> 6;
|
||||
|
||||
if (cmdsize == 1) {
|
||||
if (cmdbits == HITAG2_START_AUTH) {
|
||||
snprintf(exp, size, "START AUTH");
|
||||
return;
|
||||
uint8_t cmdbits = (cmd[0] & 0xC0) >> 6;
|
||||
|
||||
if (cmdsize == 1) {
|
||||
if (cmdbits == HITAG2_START_AUTH) {
|
||||
snprintf(exp, size, "START AUTH");
|
||||
return;
|
||||
}
|
||||
if (cmdbits == HITAG2_HALT) {
|
||||
snprintf(exp, size, "HALT");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cmdbits == HITAG2_HALT) {
|
||||
snprintf(exp, size, "HALT");
|
||||
return;
|
||||
|
||||
if (cmdsize == 3) {
|
||||
if (cmdbits == HITAG2_START_AUTH) {
|
||||
// C 1 C 0
|
||||
// 1100 0 00 1 1100 000
|
||||
uint8_t page = (cmd[0] & 0x38) >> 3;
|
||||
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
|
||||
snprintf(exp, size, "READ page(%x) %x", page, inv_page);
|
||||
return;
|
||||
}
|
||||
if (cmdbits == HITAG2_WRITE_PAGE) {
|
||||
uint8_t page = (cmd[0] & 0x38) >> 3;
|
||||
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
|
||||
snprintf(exp, size, "WRITE page(%x) %x", page, inv_page);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdsize == 9) {
|
||||
snprintf(exp, size, "Nr Ar Is response");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (cmdsize == 9) {
|
||||
snprintf(exp, size, "Nr Ar");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (cmdsize == 2) {
|
||||
if (cmdbits == HITAG2_START_AUTH) {
|
||||
// C 1 C 0
|
||||
// 1100 0 00 1 1100 000
|
||||
uint8_t page = (cmd[0] & 0x38) >> 3;
|
||||
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
|
||||
snprintf(exp, size, "READ page(%x) %x", page, inv_page);
|
||||
return;
|
||||
}
|
||||
if (cmdbits == HITAG2_WRITE_PAGE) {
|
||||
uint8_t page = (cmd[0] & 0x38) >> 3;
|
||||
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
|
||||
snprintf(exp, size, "WRITE page(%x) %x", page, inv_page);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_reader) {
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
int CmdLFHitag(const char *Cmd);
|
||||
|
||||
int readHitagUid(void);
|
||||
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_reader);
|
||||
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_reader);
|
||||
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_reader);
|
||||
#endif
|
||||
|
||||
@@ -3711,28 +3711,30 @@ static int CmdT55xxProtect(const char *Cmd) {
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "<start password> <end password> Simple bruteforce attack to find password"},
|
||||
{"config", CmdT55xxSetConfig, AlwaysAvailable, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
||||
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"},
|
||||
{"clonehelp", CmdT55xxCloneHelp, IfPm3Lf, "Shows the available clone commands"},
|
||||
{"config", CmdT55xxSetConfig, AlwaysAvailable, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
||||
{"dangerraw", CmdT55xxDangerousRaw, IfPm3Lf, "Sends raw bitstream. Dangerous, do not use!! b <bitstream> t <timing>"},
|
||||
{"detect", CmdT55xxDetect, AlwaysAvailable, "[1] Try detecting the tag modulation from reading the configuration block."},
|
||||
{"deviceconfig", CmdT55xxSetDeviceConfig, IfPm3Lf, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"},
|
||||
{"dump", CmdT55xxDump, IfPm3Lf, "[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]"},
|
||||
{"restore", CmdT55xxRestore, IfPm3Lf, "f <filename> [p <password>] Restore T55xx card Page 0 / Page 1 blocks"},
|
||||
{"info", CmdT55xxInfo, AlwaysAvailable, "[1] Show T55x7 configuration data (page 0/ blk 0)"},
|
||||
{"p1detect", CmdT55xxDetectPage1, IfPm3Lf, "[1] Try detecting if this is a t55xx tag by reading page 1"},
|
||||
{"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"},
|
||||
{"read", CmdT55xxReadBlock, IfPm3Lf, "b <block> p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"},
|
||||
{"resetread", CmdResetRead, IfPm3Lf, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"},
|
||||
// {"restore", CmdT55xxRestore, IfPm3Lf, "[password] Restore T55xx card Page 0 / Page 1 blocks"},
|
||||
{"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"},
|
||||
{"special", special, IfPm3Lf, "Show block changes with 64 different offsets"},
|
||||
{"restore", CmdT55xxRestore, IfPm3Lf, "f <filename> [p <password>] Restore T55xx card Page 0 / Page 1 blocks"},
|
||||
{"trace", CmdT55xxReadTrace, AlwaysAvailable, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"},
|
||||
{"wakeup", CmdT55xxWakeUp, IfPm3Lf, "Send AOR wakeup command"},
|
||||
{"wipe", CmdT55xxWipe, IfPm3Lf, "[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
|
||||
{"write", CmdT55xxWriteBlock, IfPm3Lf, "b <block> d <data> p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"},
|
||||
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("recovery") " ---------------------"},
|
||||
{"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "<start password> <end password> Simple bruteforce attack to find password"},
|
||||
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"},
|
||||
{"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"},
|
||||
{"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"},
|
||||
{"special", special, IfPm3Lf, "Show block changes with 64 different offsets"},
|
||||
{"wipe", CmdT55xxWipe, IfPm3Lf, "[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -465,9 +465,10 @@ static int CmdSmartRaw(const char *Cmd) {
|
||||
//Validations
|
||||
if (errors || cmdp == 0) return usage_sm_raw();
|
||||
|
||||
uint8_t flags = 0;
|
||||
uint8_t flags = SC_LOG;
|
||||
if (active || active_select) {
|
||||
flags |= SC_CONNECT;
|
||||
|
||||
flags |= (SC_CONNECT | SC_CLEARLOG);
|
||||
if (active_select)
|
||||
flags |= SC_SELECT;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ static int usage_trace_list(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: trace list <protocol> [f][c| <0|1>");
|
||||
PrintAndLogEx(NORMAL, " f - show frame delay times as well");
|
||||
PrintAndLogEx(NORMAL, " c - mark CRC bytes");
|
||||
PrintAndLogEx(NORMAL, " r - show relative times (gap and duration)");
|
||||
PrintAndLogEx(NORMAL, " u - display times in microseconds instead of clock cycles");
|
||||
PrintAndLogEx(NORMAL, " x - show hexdump to convert to pcap(ng) or to import into Wireshark using encapsulation type \"ISO 14443\"");
|
||||
PrintAndLogEx(NORMAL, " syntax to use: `text2pcap -t \"%%S.\" -l 264 -n <input-text-file> <output-pcapng-file>`");
|
||||
PrintAndLogEx(NORMAL, " <0|1> - use data from Tracebuffer, if not set, try to collect a trace from Proxmark3 device.");
|
||||
@@ -179,13 +181,16 @@ static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trac
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes) {
|
||||
static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes, uint32_t *prev_eot, bool use_us) {
|
||||
// sanity check
|
||||
if (is_last_record(tracepos, traceLen)) return traceLen;
|
||||
if (is_last_record(tracepos, traceLen)) {
|
||||
PrintAndLogEx(DEBUG, "last record triggered. t-pos: %u t-len %u", tracepos, traceLen);
|
||||
return traceLen;
|
||||
}
|
||||
|
||||
uint32_t end_of_transmission_timestamp = 0;
|
||||
uint32_t duration;
|
||||
uint16_t data_len;
|
||||
uint32_t EndOfTransmissionTimestamp;
|
||||
uint8_t topaz_reader_command[9];
|
||||
char explanation[40] = {0};
|
||||
uint8_t mfData[32] = {0};
|
||||
@@ -197,9 +202,16 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
data_len = hdr->data_len;
|
||||
|
||||
if (tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr) > traceLen) {
|
||||
PrintAndLogEx(DEBUG, "trace pos offset %d larger than reported tracelen %d", tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr), traceLen);
|
||||
return traceLen;
|
||||
}
|
||||
|
||||
|
||||
// adjust for different time scales
|
||||
if (protocol == ICLASS || protocol == ISO_15693) {
|
||||
duration *= 32;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *frame = hdr->frame;
|
||||
uint8_t *parityBytes = hdr->frame + data_len;
|
||||
|
||||
@@ -262,8 +274,13 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
char line[18][120] = {{0}};
|
||||
|
||||
if (data_len == 0) {
|
||||
sprintf(line[0], "<empty trace - possible error>");
|
||||
return tracepos;
|
||||
if (protocol == ICLASS && duration == 2048) {
|
||||
sprintf(line[0], "<SOF>");
|
||||
} else if (protocol == ISO_15693 && duration == 512) {
|
||||
sprintf(line[0], "<EOF>");
|
||||
} else {
|
||||
sprintf(line[0], "<empty trace - possible error>");
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < data_len && j / 18 < 18; j++) {
|
||||
@@ -314,7 +331,20 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
// Draw the CRC column
|
||||
const char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " "));
|
||||
|
||||
EndOfTransmissionTimestamp = hdr->timestamp + duration;
|
||||
|
||||
uint32_t previous_end_of_transmission_timestamp = 0;
|
||||
if (prev_eot) {
|
||||
if (*prev_eot) {
|
||||
previous_end_of_transmission_timestamp = *prev_eot;
|
||||
} else {
|
||||
previous_end_of_transmission_timestamp = hdr->timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
end_of_transmission_timestamp = hdr->timestamp + duration;
|
||||
|
||||
if (prev_eot)
|
||||
*prev_eot = end_of_transmission_timestamp;
|
||||
|
||||
// Always annotate LEGIC read/tag
|
||||
if (protocol == LEGIC)
|
||||
@@ -325,8 +355,18 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
|
||||
if (protocol == FELICA)
|
||||
annotateFelica(explanation, sizeof(explanation), frame, data_len);
|
||||
|
||||
if (protocol == PROTO_HITAG1) {
|
||||
annotateHitag1(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||
}
|
||||
if (protocol == PROTO_HITAG2) {
|
||||
annotateHitag2(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||
}
|
||||
if (protocol == PROTO_HITAGS) {
|
||||
annotateHitagS(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||
}
|
||||
|
||||
if (!hdr->isResponse) {
|
||||
if (hdr->isResponse == false) {
|
||||
switch (protocol) {
|
||||
case ICLASS:
|
||||
annotateIclass(explanation, sizeof(explanation), frame, data_len);
|
||||
@@ -355,15 +395,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
case LTO:
|
||||
annotateLTO(explanation, sizeof(explanation), frame, data_len);
|
||||
break;
|
||||
case PROTO_HITAG1:
|
||||
annotateHitag1(explanation, sizeof(explanation), frame, data_len);
|
||||
break;
|
||||
case PROTO_HITAG2:
|
||||
annotateHitag2(explanation, sizeof(explanation), frame, data_len);
|
||||
break;
|
||||
case PROTO_HITAGS:
|
||||
annotateHitagS(explanation, sizeof(explanation), frame, data_len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -372,44 +403,70 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
int num_lines = MIN((data_len - 1) / 18 + 1, 18);
|
||||
for (int j = 0; j < num_lines ; j++) {
|
||||
if (j == 0) {
|
||||
PrintAndLogEx(NORMAL, " %10u | %10u | %s |%-72s | %s| %s",
|
||||
(hdr->timestamp - first_hdr->timestamp),
|
||||
(EndOfTransmissionTimestamp - first_hdr->timestamp),
|
||||
(hdr->isResponse ? "Tag" : "Rdr"),
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : "");
|
||||
|
||||
uint32_t time1 = hdr->timestamp - first_hdr->timestamp;
|
||||
uint32_t time2 = end_of_transmission_timestamp - first_hdr->timestamp;
|
||||
if (prev_eot) {
|
||||
time1 = hdr->timestamp - previous_end_of_transmission_timestamp;
|
||||
time2 = duration;
|
||||
}
|
||||
|
||||
if (use_us) {
|
||||
PrintAndLogEx(NORMAL, " %10.1f | %10.1f | %s |%-72s | %s| %s",
|
||||
(float)time1/13.56,
|
||||
(float)time2/13.56,
|
||||
(hdr->isResponse ? "Tag" : _YELLOW_("Rdr")),
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " %10u | %10u | %s |%-72s | %s| %s",
|
||||
(hdr->timestamp - first_hdr->timestamp),
|
||||
(end_of_transmission_timestamp - first_hdr->timestamp),
|
||||
(hdr->isResponse ? "Tag" : _YELLOW_("Rdr")),
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " | | |%-72s | %s| %s",
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : "");
|
||||
line[j],
|
||||
(j == num_lines - 1) ? crc : " ",
|
||||
(j == num_lines - 1) ? explanation : ""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (DecodeMifareData(frame, data_len, parityBytes, hdr->isResponse, mfData, &mfDataLen)) {
|
||||
memset(explanation, 0x00, sizeof(explanation));
|
||||
if (!hdr->isResponse) {
|
||||
annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen);
|
||||
if (protocol == PROTO_MIFARE) {
|
||||
if (DecodeMifareData(frame, data_len, parityBytes, hdr->isResponse, mfData, &mfDataLen)) {
|
||||
memset(explanation, 0x00, sizeof(explanation));
|
||||
if (hdr->isResponse == false) {
|
||||
annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen);
|
||||
}
|
||||
uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen);
|
||||
PrintAndLogEx(NORMAL, " | | * |%-72s | %-4s| %s",
|
||||
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
||||
(crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")),
|
||||
explanation);
|
||||
}
|
||||
uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen);
|
||||
PrintAndLogEx(NORMAL, " | | * |%-72s | %-4s| %s",
|
||||
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
||||
(crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")),
|
||||
explanation);
|
||||
}
|
||||
|
||||
if (is_last_record(tracepos, traceLen)) return traceLen;
|
||||
if (is_last_record(tracepos, traceLen)) {
|
||||
return traceLen;
|
||||
}
|
||||
|
||||
if (showWaitCycles && !hdr->isResponse && next_record_is_response(tracepos, trace)) {
|
||||
if (showWaitCycles && hdr->isResponse == false && next_record_is_response(tracepos, trace)) {
|
||||
|
||||
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
|
||||
|
||||
PrintAndLogEx(NORMAL, " %10u | %10u | %s |fdt (Frame Delay Time): %d",
|
||||
(EndOfTransmissionTimestamp - first_hdr->timestamp),
|
||||
PrintAndLogEx(NORMAL, " %10u | %10u | %s |fdt (Frame Delay Time): " _YELLOW_("%d"),
|
||||
(end_of_transmission_timestamp - first_hdr->timestamp),
|
||||
(next_hdr->timestamp - first_hdr->timestamp),
|
||||
" ",
|
||||
(next_hdr->timestamp - EndOfTransmissionTimestamp));
|
||||
(next_hdr->timestamp - end_of_transmission_timestamp));
|
||||
}
|
||||
|
||||
return tracepos;
|
||||
@@ -417,7 +474,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
|
||||
static int download_trace(void) {
|
||||
|
||||
if (!IfPm3Present()) {
|
||||
if (IfPm3Present() == false) {
|
||||
PrintAndLogEx(FAILED, "You requested a trace upload in offline mode, consider using parameter '1' for working from Tracebuffer");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
@@ -434,7 +491,7 @@ static int download_trace(void) {
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "downloading tracelog from device");
|
||||
PrintAndLogEx(INFO, "downloading tracelog data from device");
|
||||
|
||||
// Query for the size of the trace, downloading PM3_CMD_DATA_SIZE
|
||||
PacketResponseNG response;
|
||||
@@ -478,10 +535,10 @@ static int SanityOfflineCheck( bool useTraceBuffer ){
|
||||
|
||||
static int CmdTraceLoad(const char *Cmd) {
|
||||
|
||||
char filename[FILE_PATH_SIZE];
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || (strlen(Cmd) == 1 && cmdp == 'h')) return usage_trace_load();
|
||||
|
||||
char filename[FILE_PATH_SIZE];
|
||||
param_getstr(Cmd, 0, filename, sizeof(filename));
|
||||
|
||||
if (g_trace)
|
||||
@@ -501,6 +558,9 @@ static int CmdTraceLoad(const char *Cmd) {
|
||||
|
||||
static int CmdTraceSave(const char *Cmd) {
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || (strlen(Cmd) == 1 && cmdp == 'h')) return usage_trace_save();
|
||||
|
||||
if (g_traceLen == 0) {
|
||||
download_trace();
|
||||
}
|
||||
@@ -511,9 +571,6 @@ static int CmdTraceSave(const char *Cmd) {
|
||||
}
|
||||
|
||||
char filename[FILE_PATH_SIZE];
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || (strlen(Cmd) == 1 && cmdp == 'h')) return usage_trace_save();
|
||||
|
||||
param_getstr(Cmd, 0, filename, sizeof(filename));
|
||||
saveFile(filename, ".trace", g_trace, g_traceLen);
|
||||
return PM3_SUCCESS;
|
||||
@@ -523,18 +580,12 @@ int CmdTraceList(const char *Cmd) {
|
||||
|
||||
clearCommandBuffer();
|
||||
|
||||
bool showWaitCycles = false;
|
||||
bool markCRCBytes = false;
|
||||
bool showHex = false;
|
||||
bool isOnline = true;
|
||||
bool showWaitCycles = false, markCRCBytes = false;
|
||||
bool showHex = false, isOnline = true;
|
||||
bool use_us = false, use_relative = false;
|
||||
bool errors = false;
|
||||
uint8_t protocol = 0;
|
||||
char type[10] = {0};
|
||||
|
||||
//int tlen = param_getstr(Cmd,0,type);
|
||||
//char param1 = param_getchar(Cmd, 1);
|
||||
//char param2 = param_getchar(Cmd, 2);
|
||||
|
||||
char cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
@@ -564,6 +615,14 @@ int CmdTraceList(const char *Cmd) {
|
||||
isOnline = false;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'r':
|
||||
use_relative = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'u':
|
||||
use_us = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
@@ -623,34 +682,79 @@ int CmdTraceList(const char *Cmd) {
|
||||
tracepos = printHexLine(tracepos, g_traceLen, g_trace, protocol);
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(INFO, _YELLOW_("Start") " = Start of Start Bit, " _YELLOW_("End") " = End of last modulation. " _YELLOW_("Src") " = Source of Transfer");
|
||||
if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO)
|
||||
PrintAndLogEx(INFO, "ISO14443A - All times are in carrier periods (1/13.56MHz)");
|
||||
if (protocol == THINFILM)
|
||||
PrintAndLogEx(INFO, "Thinfilm - All times are in carrier periods (1/13.56MHz)");
|
||||
if (protocol == ICLASS)
|
||||
PrintAndLogEx(INFO, "iClass - Timings are not as accurate");
|
||||
|
||||
if (use_relative) {
|
||||
PrintAndLogEx(INFO, _YELLOW_("gap") " = time between transfers. " _YELLOW_("duration") " = duration of data transfer. " _YELLOW_("src") " = source of transfer");
|
||||
} else {
|
||||
PrintAndLogEx(INFO, _YELLOW_("start") " = start of start frame " _YELLOW_("end") " = end of frame. " _YELLOW_("src") " = source of transfer");
|
||||
}
|
||||
|
||||
if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO) {
|
||||
if (use_us)
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO14443A") " - all times are in microseconds");
|
||||
else
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO14443A") " - all times are in carrier periods (1/13.56MHz)");
|
||||
}
|
||||
|
||||
if (protocol == THINFILM) {
|
||||
if (use_us)
|
||||
PrintAndLogEx(INFO, _YELLOW_("Thinfilm") " - all times are in microseconds");
|
||||
else
|
||||
PrintAndLogEx(INFO, _YELLOW_("Thinfilm") " - all times are in carrier periods (1/13.56MHz)");
|
||||
}
|
||||
|
||||
if (protocol == ICLASS || protocol == ISO_15693) {
|
||||
if (use_us)
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO15693 / iCLASS") " - all times are in microseconds");
|
||||
else
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO15693 / iCLASS") " - all times are in carrier periods (1/13.56MHz)");
|
||||
}
|
||||
|
||||
if (protocol == LEGIC)
|
||||
PrintAndLogEx(INFO, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n"
|
||||
PrintAndLogEx(INFO, _YELLOW_("LEGIC") " - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n"
|
||||
" Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)");
|
||||
if (protocol == ISO_14443B)
|
||||
PrintAndLogEx(INFO, "ISO14443B"); // Timings ?
|
||||
if (protocol == ISO_15693)
|
||||
PrintAndLogEx(INFO, "ISO15693 - Timings are not as accurate");
|
||||
|
||||
if (protocol == ISO_14443B) {
|
||||
if (use_us)
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO14443B") " - all times are in microseconds");
|
||||
else
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO14443B") " - all times are in carrier periods (1/13.56MHz)");
|
||||
}
|
||||
|
||||
if (protocol == ISO_7816_4)
|
||||
PrintAndLogEx(INFO, "ISO7816-4 / Smartcard - Timings N/A yet");
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO7816-4 / Smartcard") " - Timings N/A");
|
||||
|
||||
if (protocol == PROTO_HITAG1 || protocol == PROTO_HITAG2 || protocol == PROTO_HITAGS)
|
||||
PrintAndLogEx(INFO, "Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)");
|
||||
if (protocol == FELICA)
|
||||
PrintAndLogEx(INFO, "ISO18092 / FeliCa - Timings are not as accurate");
|
||||
PrintAndLogEx(INFO, _YELLOW_("Hitag1 / Hitag2 / HitagS") " - Timings in ETU (8us)");
|
||||
|
||||
if (protocol == FELICA) {
|
||||
if (use_us)
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO18092 / FeliCa") " - all times are in microseconds");
|
||||
else
|
||||
PrintAndLogEx(INFO, _YELLOW_("ISO18092 / FeliCa") " - all times are in carrier periods (1/13.56MHz)");
|
||||
}
|
||||
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");
|
||||
if (use_relative) {
|
||||
PrintAndLogEx(NORMAL, " Gap | Duration | Src | Data (! denotes parity error, ' denotes short bytes) | CRC | Annotation");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "------------+------------+-----+-------------------------------------------------------------------------+-----+--------------------");
|
||||
|
||||
ClearAuthData();
|
||||
// clean authentication data used with the mifare classic decrypt fct
|
||||
if (protocol == ISO_14443A || protocol == PROTO_MIFARE)
|
||||
ClearAuthData();
|
||||
|
||||
uint32_t previous_EOT = 0;
|
||||
uint32_t *prev_EOT = NULL;
|
||||
if (use_relative) {
|
||||
prev_EOT = &previous_EOT;
|
||||
}
|
||||
|
||||
while (tracepos < g_traceLen) {
|
||||
tracepos = printTraceLine(tracepos, g_traceLen, g_trace, protocol, showWaitCycles, markCRCBytes);
|
||||
tracepos = printTraceLine(tracepos, g_traceLen, g_trace, protocol, showWaitCycles, markCRCBytes, prev_EOT, use_us);
|
||||
|
||||
if (kbd_enter_pressed())
|
||||
break;
|
||||
|
||||
@@ -303,7 +303,7 @@ static void PacketResponseReceived(PacketResponseNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_DEBUG_PRINT_INTEGERS: {
|
||||
if (! packet->ng)
|
||||
if (packet->ng == false)
|
||||
PrintAndLogEx(NORMAL, "[" _MAGENTA_("pm3") "] ["_BLUE_("#")"] " "%" PRIx64 ", %" PRIx64 ", %" PRIx64 "", packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -671,21 +671,21 @@ static void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t form
|
||||
PrintAndLogEx(SUCCESS, " Parity: %s",card->ParityValid ? "Valid" : "Invalid");
|
||||
*/
|
||||
|
||||
char s[80] = {0};
|
||||
char s[110] = {0};
|
||||
if (format.Fields.hasFacilityCode)
|
||||
snprintf(s, sizeof(s), "FC: %u", card->FacilityCode);
|
||||
snprintf(s, sizeof(s), "FC: " _GREEN_("%u"), card->FacilityCode);
|
||||
|
||||
if (format.Fields.hasCardNumber)
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " CN: %" PRIu64, card->CardNumber);
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " CN: " _GREEN_("%"PRIu64), card->CardNumber);
|
||||
|
||||
if (format.Fields.hasIssueLevel)
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " Issue %u", card->IssueLevel);
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " Issue " _GREEN_("%u"), card->IssueLevel);
|
||||
|
||||
if (format.Fields.hasOEMCode)
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " OEM: %u", card->OEM);
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " OEM: " _GREEN_("%u"), card->OEM);
|
||||
|
||||
if (format.Fields.hasParity)
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " parity: %s", card->ParityValid ? "valid" : "invalid");
|
||||
snprintf(s + strlen(s), sizeof(s) - strlen(s), " parity: %s", card->ParityValid ? _GREEN_("valid") : _RED_("invalid"));
|
||||
|
||||
PrintAndLogEx(SUCCESS, "[%s] - %s; %s", format.Name, format.Descrp, s);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
#define CARD_INS_ENCRYPT 0x02
|
||||
#define CARD_INS_DECODE 0x06
|
||||
#define CARD_INS_NUMBLOCKS 0x07
|
||||
#define CARD_INS_PINSIZE 0x08
|
||||
static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// look for CryptoHelper
|
||||
bool IsCryptoHelperPresent(void) {
|
||||
bool IsCryptoHelperPresent(bool verbose) {
|
||||
|
||||
if (IfPm3Smartcard()) {
|
||||
int resp_len = 0;
|
||||
@@ -31,14 +32,13 @@ bool IsCryptoHelperPresent(void) {
|
||||
ExchangeAPDUSC(true, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
|
||||
|
||||
if (strstr("CryptoHelper", (char *)resp) == 0) {
|
||||
PrintAndLogEx(INFO, "Found smart card helper");
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Found smart card helper");
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) {
|
||||
@@ -92,3 +92,17 @@ uint8_t GetNumberBlocksForUserId(uint8_t *src) {
|
||||
ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
|
||||
return resp[8];
|
||||
}
|
||||
|
||||
// Call with block6
|
||||
uint8_t GetPinSize(uint8_t *src) {
|
||||
int resp_len = 0;
|
||||
uint8_t resp[254] = {0};
|
||||
uint8_t c[] = {0x96, CARD_INS_PINSIZE, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
memcpy(c + 5, src, 8);
|
||||
ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
|
||||
|
||||
if ( resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
|
||||
return resp[8];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
#include <ctype.h>
|
||||
#include "common.h"
|
||||
|
||||
bool IsCryptoHelperPresent(void);
|
||||
bool IsCryptoHelperPresent(bool verbose);
|
||||
bool Encrypt(uint8_t *src, uint8_t *dest);
|
||||
bool Decrypt(uint8_t *src, uint8_t *dest);
|
||||
void DecodeBlock6(uint8_t *src);
|
||||
uint8_t GetNumberBlocksForUserId(uint8_t *src);
|
||||
uint8_t GetPinSize(uint8_t *src);
|
||||
#endif
|
||||
|
||||
@@ -5,17 +5,22 @@ RMDIR = rm -rf
|
||||
# rmdir only if dir is empty, tolerate failure
|
||||
RMDIR_SOFT = -rmdir
|
||||
#
|
||||
all: fpga_lf.bit fpga_hf.bit
|
||||
all: fpga_lf.bit fpga_hf.bit fpga_felica.bit
|
||||
clean:
|
||||
$(Q)$(RM) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp
|
||||
$(Q)$(RM) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp xst_felica.srp
|
||||
$(Q)$(RM) *.map *.ngc *.xrpt *.pcf *.rbt *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst
|
||||
$(Q)$(RMDIR) *_auto_* 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 hi_sniffer.v hi_flite.v hi_get_trace.v
|
||||
#fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_reader.v hi_iso14443a.v hi_sniffer.v hi_flite.v hi_get_trace.v
|
||||
fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_reader.v hi_iso14443a.v hi_sniffer.v hi_get_trace.v
|
||||
$(Q)$(RM) $@
|
||||
$(info [-] XST $@)
|
||||
$(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr
|
||||
|
||||
fpga_felica.ngc: fpga_felica.v fpga.ucf xst_felica.scr util.v hi_simulate.v hi_reader.v hi_sniffer.v hi_flite.v hi_get_trace.v
|
||||
$(Q)$(RM) $@
|
||||
$(info [-] XST $@)
|
||||
$(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_felica.scr
|
||||
|
||||
fpga_lf.ngc: fpga_lf.v fpga.ucf xst_lf.scr util.v clk_divider.v lo_edge_detect.v lo_read.v lo_passthru.v lp20khz_1MSa_iir_filter.v min_max_tracker.v lf_edge_detect.v
|
||||
$(Q)$(RM) $@
|
||||
|
||||
BIN
fpga/fpga_felica.bit
Normal file
BIN
fpga/fpga_felica.bit
Normal file
Binary file not shown.
226
fpga/fpga_felica.v
Normal file
226
fpga/fpga_felica.v
Normal file
@@ -0,0 +1,226 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// The FPGA is responsible for interfacing between the A/D, the coil drivers,
|
||||
// and the ARM. In the low-frequency modes it passes the data straight
|
||||
// through, so that the ARM gets raw A/D samples over the SSP. In the high-
|
||||
// frequency modes, the FPGA might perform some demodulation first, to
|
||||
// reduce the amount of data that we must send to the ARM.
|
||||
//
|
||||
// I am not really an FPGA/ASIC designer, so I am sure that a lot of this
|
||||
// could be improved.
|
||||
//
|
||||
// Jonathan Westhues, March 2006
|
||||
// Added ISO14443-A support by Gerhard de Koning Gans, April 2008
|
||||
// iZsh <izsh at fail0verflow.com>, June 2014
|
||||
// Piwi, Feb 2019
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h
|
||||
// Note: the definitions here are without shifts
|
||||
|
||||
// Commands:
|
||||
`define FPGA_CMD_SET_CONFREG 1
|
||||
`define FPGA_CMD_TRACE_ENABLE 2
|
||||
|
||||
// Major modes:
|
||||
`define FPGA_MAJOR_MODE_HF_READER 0
|
||||
`define FPGA_MAJOR_MODE_HF_SIMULATOR 1
|
||||
`define FPGA_MAJOR_MODE_HF_ISO14443A 2
|
||||
`define FPGA_MAJOR_MODE_HF_SNIFF 3
|
||||
`define FPGA_MAJOR_MODE_HF_ISO18092 4
|
||||
`define FPGA_MAJOR_MODE_HF_GET_TRACE 5
|
||||
`define FPGA_MAJOR_MODE_OFF 7
|
||||
|
||||
// Options for the generic HF reader
|
||||
`define FPGA_HF_READER_MODE_RECEIVE_IQ 0
|
||||
`define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE 1
|
||||
`define FPGA_HF_READER_MODE_RECEIVE_PHASE 2
|
||||
`define FPGA_HF_READER_MODE_SEND_FULL_MOD 3
|
||||
`define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD 4
|
||||
`define FPGA_HF_READER_MODE_SNIFF_IQ 5
|
||||
`define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE 6
|
||||
`define FPGA_HF_READER_MODE_SNIFF_PHASE 7
|
||||
`define FPGA_HF_READER_MODE_SEND_JAM 8
|
||||
|
||||
`define FPGA_HF_READER_SUBCARRIER_848_KHZ 0
|
||||
`define FPGA_HF_READER_SUBCARRIER_424_KHZ 1
|
||||
`define FPGA_HF_READER_SUBCARRIER_212_KHZ 2
|
||||
|
||||
// Options for the HF simulated tag, how to modulate
|
||||
`define FPGA_HF_SIMULATOR_NO_MODULATION 0
|
||||
`define FPGA_HF_SIMULATOR_MODULATE_BPSK 1
|
||||
`define FPGA_HF_SIMULATOR_MODULATE_212K 2
|
||||
`define FPGA_HF_SIMULATOR_MODULATE_424K 4
|
||||
`define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 5
|
||||
|
||||
// Options for ISO14443A
|
||||
`define FPGA_HF_ISO14443A_SNIFFER 0
|
||||
`define FPGA_HF_ISO14443A_TAGSIM_LISTEN 1
|
||||
`define FPGA_HF_ISO14443A_TAGSIM_MOD 2
|
||||
`define FPGA_HF_ISO14443A_READER_LISTEN 3
|
||||
`define FPGA_HF_ISO14443A_READER_MOD 4
|
||||
|
||||
//options for ISO18092 / Felica
|
||||
`define FPGA_HF_ISO18092_FLAG_NOMOD 1 // 0001 disable modulation module
|
||||
`define FPGA_HF_ISO18092_FLAG_424K 2 // 0010 should enable 414k mode (untested). No autodetect
|
||||
`define FPGA_HF_ISO18092_FLAG_READER 4 // 0100 enables antenna power, to act as a reader instead of tag
|
||||
|
||||
`include "hi_reader.v"
|
||||
`include "hi_simulate.v"
|
||||
//`include "hi_iso14443a.v"
|
||||
`include "hi_sniffer.v"
|
||||
`include "util.v"
|
||||
`include "hi_flite.v"
|
||||
`include "hi_get_trace.v"
|
||||
|
||||
module fpga_felica(
|
||||
input spck, output miso, input mosi, input ncs,
|
||||
input pck0, input ck_1356meg, input ck_1356megb,
|
||||
output pwr_lo, output pwr_hi,
|
||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
||||
input [7:0] adc_d, output adc_clk, output adc_noe,
|
||||
output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk,
|
||||
input cross_hi, input cross_lo,
|
||||
output dbg
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The SPI receiver. This sets up the configuration word, which the rest of
|
||||
// the logic looks at to determine how to connect the A/D and the coil
|
||||
// drivers (i.e., which section gets it). Also assign some symbolic names
|
||||
// to the configuration bits, for use below.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Attempt to write up how its hooked up. Iceman 2020.
|
||||
|
||||
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand()
|
||||
Send 16 bit command / data pair to FPGA
|
||||
The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
|
||||
where
|
||||
C is 4bit command
|
||||
D is 12bit data
|
||||
|
||||
shift_reg receive this 16bit frame
|
||||
|
||||
|
||||
-----+--------- frame layout --------------------
|
||||
bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
-----+-------------------------------------------
|
||||
cmd | x x x x
|
||||
major| x x x
|
||||
opt | x x x
|
||||
divi | x x x x x x x x
|
||||
thres| x x x x x x x x
|
||||
-----+-------------------------------------------
|
||||
*/
|
||||
|
||||
reg [15:0] shift_reg;
|
||||
reg [8:0] conf_word;
|
||||
reg trace_enable;
|
||||
|
||||
// We switch modes between transmitting to the 13.56 MHz tag and receiving
|
||||
// from it, which means that we must make sure that we can do so without
|
||||
// glitching, or else we will glitch the transmitted carrier.
|
||||
always @(posedge ncs)
|
||||
begin
|
||||
case(shift_reg[15:12])
|
||||
`FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[8:0];
|
||||
`FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0];
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge spck)
|
||||
begin
|
||||
if(~ncs)
|
||||
begin
|
||||
shift_reg[15:1] <= shift_reg[14:0];
|
||||
shift_reg[0] <= mosi;
|
||||
end
|
||||
end
|
||||
|
||||
// select module (outputs) based on major mode
|
||||
wire [2:0] major_mode = conf_word[8:6];
|
||||
|
||||
// configuring the HF reader
|
||||
wire [1:0] subcarrier_frequency = conf_word[5:4];
|
||||
wire [3:0] minor_mode = conf_word[3:0];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// And then we instantiate the modules corresponding to each of the FPGA's
|
||||
// major modes, and use muxes to connect the outputs of the active mode to
|
||||
// the output pins.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 000 - HF reader
|
||||
hi_reader hr(
|
||||
ck_1356megb,
|
||||
hr_pwr_lo, hr_pwr_hi, hr_pwr_oe1, hr_pwr_oe2, hr_pwr_oe3, hr_pwr_oe4,
|
||||
adc_d, hr_adc_clk,
|
||||
hr_ssp_frame, hr_ssp_din, ssp_dout, hr_ssp_clk,
|
||||
hr_dbg,
|
||||
subcarrier_frequency, minor_mode
|
||||
);
|
||||
|
||||
// 001 - HF simulated tag
|
||||
hi_simulate hs(
|
||||
ck_1356meg,
|
||||
hs_pwr_lo, hs_pwr_hi, hs_pwr_oe1, hs_pwr_oe2, hs_pwr_oe3, hs_pwr_oe4,
|
||||
adc_d, hs_adc_clk,
|
||||
hs_ssp_frame, hs_ssp_din, ssp_dout, hs_ssp_clk,
|
||||
hs_dbg,
|
||||
minor_mode
|
||||
);
|
||||
|
||||
// 011 - HF sniff
|
||||
hi_sniffer he(
|
||||
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, he_ssp_clk
|
||||
);
|
||||
|
||||
// 100 - HF ISO18092 FeliCa
|
||||
hi_flite hfl(
|
||||
ck_1356megb,
|
||||
hfl_pwr_lo, hfl_pwr_hi, hfl_pwr_oe1, hfl_pwr_oe2, hfl_pwr_oe3, hfl_pwr_oe4,
|
||||
adc_d, hfl_adc_clk,
|
||||
hfl_ssp_frame, hfl_ssp_din, ssp_dout, hfl_ssp_clk,
|
||||
hfl_dbg,
|
||||
minor_mode
|
||||
);
|
||||
|
||||
// 101 - HF get trace
|
||||
hi_get_trace gt(
|
||||
ck_1356megb,
|
||||
adc_d, trace_enable, major_mode,
|
||||
gt_ssp_frame, gt_ssp_din, gt_ssp_clk
|
||||
);
|
||||
|
||||
// Major modes:
|
||||
// 000 -- HF reader; subcarrier frequency and modulation depth selectable
|
||||
// 001 -- HF simulated tag
|
||||
// 010 -- HF ISO14443-A - removed for space...
|
||||
// 011 -- HF sniff
|
||||
// 100 -- HF ISO18092 FeliCa
|
||||
// 101 -- HF get trace
|
||||
// 110 -- unused
|
||||
// 111 -- FPGA_MAJOR_MODE_OFF
|
||||
|
||||
// 000 001 010 011 100 101 110 111
|
||||
mux8 mux_ssp_clk (major_mode, ssp_clk, hr_ssp_clk, hs_ssp_clk, 1'b0, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_din (major_mode, ssp_din, hr_ssp_din, hs_ssp_din, 1'b0, he_ssp_din, hfl_ssp_din, gt_ssp_din, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_frame (major_mode, ssp_frame, hr_ssp_frame, hs_ssp_frame, 1'b0, he_ssp_frame, hfl_ssp_frame, gt_ssp_frame, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, hr_pwr_oe1, hs_pwr_oe1, 1'b0, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, hr_pwr_oe2, hs_pwr_oe2, 1'b0, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, hr_pwr_oe3, hs_pwr_oe3, 1'b0, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, hr_pwr_oe4, hs_pwr_oe4, 1'b0, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_lo (major_mode, pwr_lo, hr_pwr_lo, hs_pwr_lo, 1'b0, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_hi (major_mode, pwr_hi, hr_pwr_hi, hs_pwr_hi, 1'b0, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_adc_clk (major_mode, adc_clk, hr_adc_clk, hs_adc_clk, 1'b0, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_dbg (major_mode, dbg, hr_dbg, hs_dbg, 1'b0, he_dbg, hfl_dbg, 1'b0, 1'b0, 1'b0);
|
||||
|
||||
// In all modes, let the ADC's outputs be enabled.
|
||||
assign adc_noe = 1'b0;
|
||||
|
||||
endmodule
|
||||
BIN
fpga/fpga_hf.bit
BIN
fpga/fpga_hf.bit
Binary file not shown.
172
fpga/fpga_hf.v
172
fpga/fpga_hf.v
@@ -23,23 +23,28 @@
|
||||
`define FPGA_CMD_TRACE_ENABLE 2
|
||||
|
||||
// Major modes:
|
||||
`define FPGA_MAJOR_MODE_HF_READER_TX 0
|
||||
`define FPGA_MAJOR_MODE_HF_READER_RX_XCORR 1
|
||||
`define FPGA_MAJOR_MODE_HF_SIMULATOR 2
|
||||
`define FPGA_MAJOR_MODE_HF_ISO14443A 3
|
||||
`define FPGA_MAJOR_MODE_HF_SNOOP 4
|
||||
`define FPGA_MAJOR_MODE_HF_ISO18092 5
|
||||
`define FPGA_MAJOR_MODE_HF_GET_TRACE 6
|
||||
`define FPGA_MAJOR_MODE_HF_READER 0
|
||||
`define FPGA_MAJOR_MODE_HF_SIMULATOR 1
|
||||
`define FPGA_MAJOR_MODE_HF_ISO14443A 2
|
||||
`define FPGA_MAJOR_MODE_HF_SNIFF 3
|
||||
`define FPGA_MAJOR_MODE_HF_ISO18092 4
|
||||
`define FPGA_MAJOR_MODE_HF_GET_TRACE 5
|
||||
`define FPGA_MAJOR_MODE_OFF 7
|
||||
|
||||
// Options for the generic HF reader
|
||||
// Options for the HF reader, tx to tag
|
||||
`define FPGA_HF_READER_TX_SHALLOW_MOD 1
|
||||
`define FPGA_HF_READER_MODE_RECEIVE_IQ 0
|
||||
`define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE 1
|
||||
`define FPGA_HF_READER_MODE_RECEIVE_PHASE 2
|
||||
`define FPGA_HF_READER_MODE_SEND_FULL_MOD 3
|
||||
`define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD 4
|
||||
`define FPGA_HF_READER_MODE_SNIFF_IQ 5
|
||||
`define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE 6
|
||||
`define FPGA_HF_READER_MODE_SNIFF_PHASE 7
|
||||
`define FPGA_HF_READER_MODE_SEND_JAM 8
|
||||
|
||||
// Options for the HF reader, correlating against rx from tag
|
||||
`define FPGA_HF_READER_RX_XCORR_848_KHZ 1
|
||||
`define FPGA_HF_READER_RX_XCORR_SNOOP 2
|
||||
`define FPGA_HF_READER_RX_XCORR_QUARTER 4
|
||||
`define FPGA_HF_READER_SUBCARRIER_848_KHZ 0
|
||||
`define FPGA_HF_READER_SUBCARRIER_424_KHZ 1
|
||||
`define FPGA_HF_READER_SUBCARRIER_212_KHZ 2
|
||||
|
||||
// Options for the HF simulated tag, how to modulate
|
||||
`define FPGA_HF_SIMULATOR_NO_MODULATION 0
|
||||
@@ -60,13 +65,12 @@
|
||||
`define FPGA_HF_ISO18092_FLAG_424K 2 // 0010 should enable 414k mode (untested). No autodetect
|
||||
`define FPGA_HF_ISO18092_FLAG_READER 4 // 0100 enables antenna power, to act as a reader instead of tag
|
||||
|
||||
`include "hi_read_tx.v"
|
||||
`include "hi_read_rx_xcorr.v"
|
||||
`include "hi_reader.v"
|
||||
`include "hi_simulate.v"
|
||||
`include "hi_iso14443a.v"
|
||||
`include "hi_sniffer.v"
|
||||
`include "util.v"
|
||||
`include "hi_flite.v"
|
||||
// `include "hi_flite.v"
|
||||
`include "hi_get_trace.v"
|
||||
|
||||
module fpga_hf(
|
||||
@@ -105,14 +109,14 @@ bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
-----+-------------------------------------------
|
||||
cmd | x x x x
|
||||
major| x x x
|
||||
opt | x x
|
||||
opt | x x x
|
||||
divi | x x x x x x x x
|
||||
thres| x x x x x x x x
|
||||
-----+-------------------------------------------
|
||||
*/
|
||||
|
||||
reg [15:0] shift_reg;
|
||||
reg [7:0] conf_word;
|
||||
reg [8:0] conf_word;
|
||||
reg trace_enable;
|
||||
|
||||
// We switch modes between transmitting to the 13.56 MHz tag and receiving
|
||||
@@ -121,7 +125,7 @@ reg trace_enable;
|
||||
always @(posedge ncs)
|
||||
begin
|
||||
case(shift_reg[15:12])
|
||||
`FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[7:0];
|
||||
`FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[8:0];
|
||||
`FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0];
|
||||
endcase
|
||||
end
|
||||
@@ -135,25 +139,12 @@ begin
|
||||
end
|
||||
end
|
||||
|
||||
wire [2:0] major_mode = conf_word[7:5];
|
||||
// select module (outputs) based on major mode
|
||||
wire [2:0] major_mode = conf_word[8:6];
|
||||
|
||||
// For the high-frequency transmit configuration: modulation depth, either
|
||||
// 100% (just quite driving antenna, steady LOW), or shallower (tri-state
|
||||
// some fraction of the buffers)
|
||||
wire hi_read_tx_shallow_modulation = conf_word[0];
|
||||
|
||||
// For the high-frequency receive correlator: frequency against which to
|
||||
// correlate.
|
||||
wire hi_read_rx_xcorr_848 = conf_word[0];
|
||||
|
||||
// and whether to drive the coil (reader) or just short it (snooper)
|
||||
wire hi_read_rx_xcorr_snoop = conf_word[1];
|
||||
|
||||
// divide subcarrier frequency by 4
|
||||
wire hi_read_rx_xcorr_quarter = conf_word[2];
|
||||
|
||||
// For the high-frequency simulated tag: what kind of modulation to use.
|
||||
wire [2:0] hi_simulate_mod_type = conf_word[2:0];
|
||||
// configuring the HF reader
|
||||
wire [1:0] subcarrier_frequency = conf_word[5:4];
|
||||
wire [3:0] minor_mode = conf_word[3:0];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// And then we instantiate the modules corresponding to each of the FPGA's
|
||||
@@ -161,95 +152,86 @@ wire [2:0] hi_simulate_mod_type = conf_word[2:0];
|
||||
// the output pins.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
hi_read_tx ht(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ht_pwr_lo, ht_pwr_hi, ht_pwr_oe1, ht_pwr_oe2, ht_pwr_oe3, ht_pwr_oe4,
|
||||
adc_d, ht_adc_clk,
|
||||
ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
ht_dbg,
|
||||
hi_read_tx_shallow_modulation
|
||||
);
|
||||
|
||||
hi_read_rx_xcorr hrxc(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
hrxc_pwr_lo, hrxc_pwr_hi, hrxc_pwr_oe1, hrxc_pwr_oe2, hrxc_pwr_oe3, hrxc_pwr_oe4,
|
||||
adc_d, hrxc_adc_clk,
|
||||
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
|
||||
// 000 - HF reader
|
||||
hi_reader hr(
|
||||
ck_1356megb,
|
||||
hr_pwr_lo, hr_pwr_hi, hr_pwr_oe1, hr_pwr_oe2, hr_pwr_oe3, hr_pwr_oe4,
|
||||
adc_d, hr_adc_clk,
|
||||
hr_ssp_frame, hr_ssp_din, ssp_dout, hr_ssp_clk,
|
||||
hr_dbg,
|
||||
subcarrier_frequency, minor_mode
|
||||
);
|
||||
|
||||
// 001 - HF simulated tag
|
||||
hi_simulate hs(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ck_1356meg,
|
||||
hs_pwr_lo, hs_pwr_hi, hs_pwr_oe1, hs_pwr_oe2, hs_pwr_oe3, hs_pwr_oe4,
|
||||
adc_d, hs_adc_clk,
|
||||
hs_ssp_frame, hs_ssp_din, ssp_dout, hs_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
hs_dbg,
|
||||
hi_simulate_mod_type
|
||||
minor_mode
|
||||
);
|
||||
|
||||
// 010 - HF ISO14443-A
|
||||
hi_iso14443a hisn(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ck_1356meg,
|
||||
hisn_pwr_lo, hisn_pwr_hi, hisn_pwr_oe1, hisn_pwr_oe2, hisn_pwr_oe3, hisn_pwr_oe4,
|
||||
adc_d, hisn_adc_clk,
|
||||
hisn_ssp_frame, hisn_ssp_din, ssp_dout, hisn_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
hisn_dbg,
|
||||
hi_simulate_mod_type
|
||||
minor_mode
|
||||
);
|
||||
|
||||
// 011 - HF sniff
|
||||
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
|
||||
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, he_ssp_clk
|
||||
);
|
||||
|
||||
// 100 - HF ISO18092 FeliCa
|
||||
/*
|
||||
hi_flite hfl(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
hfl_pwr_lo, hfl_pwr_hi, hfl_pwr_oe1, hfl_pwr_oe2, hfl_pwr_oe3, hfl_pwr_oe4,
|
||||
adc_d, hfl_adc_clk,
|
||||
hfl_ssp_frame, hfl_ssp_din, ssp_dout, hfl_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
hfl_dbg,
|
||||
hi_simulate_mod_type
|
||||
ck_1356megb,
|
||||
hfl_pwr_lo, hfl_pwr_hi, hfl_pwr_oe1, hfl_pwr_oe2, hfl_pwr_oe3, hfl_pwr_oe4,
|
||||
adc_d, hfl_adc_clk,
|
||||
hfl_ssp_frame, hfl_ssp_din, ssp_dout, hfl_ssp_clk,
|
||||
hfl_dbg,
|
||||
minor_mode
|
||||
);
|
||||
*/
|
||||
|
||||
// 101 - HF get trace
|
||||
hi_get_trace gt(
|
||||
ck_1356megb,
|
||||
adc_d, trace_enable, major_mode,
|
||||
gt_ssp_frame, gt_ssp_din, gt_ssp_clk
|
||||
);
|
||||
|
||||
|
||||
// Major modes:
|
||||
// 000 -- HF reader; subcarrier frequency and modulation depth selectable
|
||||
// 001 -- HF simulated tag
|
||||
// 010 -- HF ISO14443-A
|
||||
// 011 -- HF sniff
|
||||
// 100 -- HF ISO18092 FeliCa
|
||||
// 101 -- HF get trace
|
||||
// 110 -- unused
|
||||
// 111 -- FPGA_MAJOR_MODE_OFF
|
||||
|
||||
// 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
|
||||
// 101 -- Felica modem, reusing HF reader
|
||||
// 110 -- HF get trace
|
||||
// 111 -- everything off
|
||||
// 000 001 010 011 100 101 110 111
|
||||
|
||||
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, 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, hfl_ssp_din, gt_ssp_din, 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, hfl_ssp_frame, gt_ssp_frame, 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, hfl_pwr_oe1, 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, hfl_pwr_oe2, 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, hfl_pwr_oe3, 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, hfl_pwr_oe4, 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, hfl_pwr_lo, 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, hfl_pwr_hi, 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, hfl_adc_clk, 1'b0, 1'b0);
|
||||
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_clk (major_mode, ssp_clk, hr_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_din (major_mode, ssp_din, hr_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, gt_ssp_din, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_frame (major_mode, ssp_frame, hr_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, gt_ssp_frame, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, hr_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, hr_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, hr_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, hr_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_lo (major_mode, pwr_lo, hr_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_hi (major_mode, pwr_hi, hr_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_adc_clk (major_mode, adc_clk, hr_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0, 1'b0);
|
||||
mux8 mux_dbg (major_mode, dbg, hr_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0, 1'b0);
|
||||
|
||||
// In all modes, let the ADC's outputs be enabled.
|
||||
assign adc_noe = 1'b0;
|
||||
|
||||
BIN
fpga/fpga_lf.bit
BIN
fpga/fpga_lf.bit
Binary file not shown.
@@ -122,7 +122,7 @@ reg [7:0] divisor;
|
||||
reg [7:0] lf_ed_threshold;
|
||||
reg [11:0] conf_word;
|
||||
|
||||
wire [2:0] major_mode = conf_word[7:5];
|
||||
wire [2:0] major_mode = conf_word[8:6];
|
||||
wire lf_field = conf_word[0];
|
||||
wire lf_ed_toggle_mode = conf_word[1];
|
||||
|
||||
@@ -135,7 +135,7 @@ begin
|
||||
begin
|
||||
// 12 bit data
|
||||
conf_word <= shift_reg[11:0];
|
||||
if (shift_reg[7:5] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT)
|
||||
if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT)
|
||||
begin
|
||||
lf_ed_threshold <= 127; // default threshold
|
||||
end
|
||||
|
||||
@@ -14,25 +14,23 @@
|
||||
*/
|
||||
|
||||
module hi_flite(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ck_1356meg,
|
||||
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,
|
||||
mod_type
|
||||
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
input ck_1356meg;
|
||||
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 [2:0] mod_type;
|
||||
assign dbg=0;
|
||||
input [3:0] mod_type;
|
||||
|
||||
assign dbg = 0;
|
||||
|
||||
wire power = mod_type[2];
|
||||
wire speed = mod_type[1];
|
||||
@@ -40,7 +38,7 @@ wire disabl = mod_type[0];
|
||||
|
||||
// Most off, oe4 for modulation;
|
||||
// Trying reader emulation (would presumably just require switching power on, but I am not sure)
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_lo = 1'b0;
|
||||
|
||||
// 512x64/fc -wait before ts0, 32768 ticks
|
||||
// tslot: 256*64/fc
|
||||
@@ -347,11 +345,11 @@ reg pwr_oe4;
|
||||
|
||||
wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl);
|
||||
|
||||
always @(ck_1356megb or ssp_dout or power or disabl or mod)
|
||||
always @(ck_1356meg or ssp_dout or power or disabl or mod)
|
||||
begin
|
||||
if (power)
|
||||
begin
|
||||
pwr_hi <= ck_1356megb;
|
||||
pwr_hi <= ck_1356meg;
|
||||
pwr_oe1 <= 1'b0;//mod;
|
||||
pwr_oe2 <= 1'b0;//mod;
|
||||
pwr_oe3 <= 1'b0;//mod;
|
||||
|
||||
@@ -3,31 +3,22 @@
|
||||
// Gerhard de Koning Gans, April 2008
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// constants for the different modes:
|
||||
`define SNIFFER 3'b000
|
||||
`define TAGSIM_LISTEN 3'b001
|
||||
`define TAGSIM_MOD 3'b010
|
||||
`define READER_LISTEN 3'b011
|
||||
`define READER_MOD 3'b100
|
||||
|
||||
module hi_iso14443a(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ck_1356meg,
|
||||
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,
|
||||
mod_type
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
input ck_1356meg;
|
||||
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 [2:0] mod_type;
|
||||
input [3:0] mod_type;
|
||||
|
||||
|
||||
wire adc_clk = ck_1356meg;
|
||||
@@ -151,7 +142,7 @@ begin
|
||||
end
|
||||
|
||||
// adjust internal timer counter if necessary:
|
||||
if (negedge_cnt[3:0] == 4'd13 && (mod_type == `SNIFFER || mod_type == `TAGSIM_LISTEN) && deep_modulation)
|
||||
if (negedge_cnt[3:0] == 4'd13 && (mod_type == `FPGA_HF_ISO14443A_SNIFFER || mod_type == `FPGA_HF_ISO14443A_TAGSIM_LISTEN) && deep_modulation)
|
||||
begin
|
||||
if (reader_falling_edge_time == 4'd1) // reader signal changes right after sampling. Better sample earlier next time.
|
||||
begin
|
||||
@@ -185,7 +176,7 @@ reg [3:0] mod_detect_reset_time;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (mod_type == `READER_LISTEN)
|
||||
if (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN)
|
||||
// (our) reader signal changes at negedge_cnt[3:0]=9, tag response expected to start n*16+4 ticks later, further delayed by
|
||||
// 3 ticks ADC conversion. The maximum filter output (edge detected) will be detected after subcarrier zero crossing (+7 ticks).
|
||||
// To allow some timing variances, we want to have the maximum filter outputs well within the detection window, i.e.
|
||||
@@ -195,7 +186,7 @@ begin
|
||||
mod_detect_reset_time <= 4'd4;
|
||||
end
|
||||
else
|
||||
if (mod_type == `SNIFFER)
|
||||
if (mod_type == `FPGA_HF_ISO14443A_SNIFFER)
|
||||
begin
|
||||
// detect a rising edge of reader's signal and sync modulation detector to the tag's answer:
|
||||
if (~pre_after_hysteresis && after_hysteresis && deep_modulation)
|
||||
@@ -320,7 +311,7 @@ reg [3:0] sub_carrier_cnt;
|
||||
// response window of 1128 - 774 = 354 ticks.
|
||||
|
||||
// reset on a pause in listen mode. I.e. the counter starts when the pause is over:
|
||||
assign fdt_reset = ~after_hysteresis && mod_type == `TAGSIM_LISTEN;
|
||||
assign fdt_reset = ~after_hysteresis && mod_type == `FPGA_HF_ISO14443A_TAGSIM_LISTEN;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
@@ -363,7 +354,7 @@ reg mod_sig_coil;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (mod_type == `TAGSIM_MOD) // need to take care of proper fdt timing
|
||||
if (mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD) // need to take care of proper fdt timing
|
||||
begin
|
||||
if(fdt_counter == `FDT_COUNT)
|
||||
begin
|
||||
@@ -438,7 +429,7 @@ always @(negedge adc_clk)
|
||||
begin
|
||||
if (negedge_cnt[5:0] == 6'd63) // fill the buffer
|
||||
begin
|
||||
if (mod_type == `SNIFFER)
|
||||
if (mod_type == `FPGA_HF_ISO14443A_SNIFFER)
|
||||
begin
|
||||
if(deep_modulation) // a reader is sending (or there's no field at all)
|
||||
begin
|
||||
@@ -455,7 +446,7 @@ begin
|
||||
end
|
||||
end
|
||||
|
||||
if(negedge_cnt[2:0] == 3'b000 && mod_type == `SNIFFER) // shift at double speed
|
||||
if(negedge_cnt[2:0] == 3'b000 && mod_type == `FPGA_HF_ISO14443A_SNIFFER) // shift at double speed
|
||||
begin
|
||||
// Don't shift if we just loaded new data, obviously.
|
||||
if(negedge_cnt[5:0] != 6'd0)
|
||||
@@ -464,7 +455,7 @@ begin
|
||||
end
|
||||
end
|
||||
|
||||
if(negedge_cnt[3:0] == 4'b0000 && mod_type != `SNIFFER)
|
||||
if(negedge_cnt[3:0] == 4'b0000 && mod_type != `FPGA_HF_ISO14443A_SNIFFER)
|
||||
begin
|
||||
// Don't shift if we just loaded new data, obviously.
|
||||
if(negedge_cnt[6:0] != 7'd0)
|
||||
@@ -484,8 +475,8 @@ reg ssp_frame;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if(mod_type == `SNIFFER)
|
||||
// SNIFFER mode (ssp_clk = adc_clk / 8, ssp_frame clock = adc_clk / 64)):
|
||||
if(mod_type == `FPGA_HF_ISO14443A_SNIFFER)
|
||||
// FPGA_HF_ISO14443A_SNIFFER mode (ssp_clk = adc_clk / 8, ssp_frame clock = adc_clk / 64)):
|
||||
begin
|
||||
if(negedge_cnt[2:0] == 3'd0)
|
||||
ssp_clk <= 1'b1;
|
||||
@@ -505,7 +496,7 @@ begin
|
||||
if(negedge_cnt[3:0] == 4'd8)
|
||||
ssp_clk <= 1'b0;
|
||||
|
||||
if(negedge_cnt[6:0] == 7'd7) // ssp_frame rising edge indicates start of frame
|
||||
if(negedge_cnt[6:0] == 7'd7) // ssp_frame rising edge indicates start of frame, sampled on falling edge of ssp_clk
|
||||
ssp_frame <= 1'b1;
|
||||
if(negedge_cnt[6:0] == 7'd23)
|
||||
ssp_frame <= 1'b0;
|
||||
@@ -525,23 +516,23 @@ begin
|
||||
if(negedge_cnt[3:0] == 4'd0)
|
||||
begin
|
||||
// What do we communicate to the ARM
|
||||
if(mod_type == `TAGSIM_LISTEN)
|
||||
if(mod_type == `FPGA_HF_ISO14443A_TAGSIM_LISTEN)
|
||||
sendbit = after_hysteresis;
|
||||
else if(mod_type == `TAGSIM_MOD)
|
||||
else if(mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD)
|
||||
/* if(fdt_counter > 11'd772) sendbit = mod_sig_coil; // huh?
|
||||
else */
|
||||
sendbit = fdt_indicator;
|
||||
else if (mod_type == `READER_LISTEN)
|
||||
else if (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN)
|
||||
sendbit = curbit;
|
||||
else
|
||||
sendbit = 1'b0;
|
||||
end
|
||||
|
||||
|
||||
if(mod_type == `SNIFFER)
|
||||
if(mod_type == `FPGA_HF_ISO14443A_SNIFFER)
|
||||
// send sampled reader and tag data:
|
||||
bit_to_arm = to_arm[7];
|
||||
else if (mod_type == `TAGSIM_MOD && fdt_elapsed && temp_buffer_reset)
|
||||
else if (mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD && fdt_elapsed && temp_buffer_reset)
|
||||
// send timing information:
|
||||
bit_to_arm = to_arm[7];
|
||||
else
|
||||
@@ -554,22 +545,22 @@ end
|
||||
|
||||
assign ssp_din = bit_to_arm;
|
||||
|
||||
// Subcarrier (adc_clk/16, for TAGSIM_MOD only).
|
||||
// Subcarrier (adc_clk/16, for FPGA_HF_ISO14443A_TAGSIM_MOD only).
|
||||
wire sub_carrier;
|
||||
assign sub_carrier = ~sub_carrier_cnt[3];
|
||||
|
||||
// in READER_MOD: drop carrier for mod_sig_coil==1 (pause); in READER_LISTEN: carrier always on; in other modes: carrier always off
|
||||
assign pwr_hi = (ck_1356megb & (((mod_type == `READER_MOD) & ~mod_sig_coil) || (mod_type == `READER_LISTEN)));
|
||||
// in FPGA_HF_ISO14443A_READER_MOD: drop carrier for mod_sig_coil==1 (pause); in FPGA_HF_ISO14443A_READER_LISTEN: carrier always on; in other modes: carrier always off
|
||||
assign pwr_hi = (ck_1356meg & (((mod_type == `FPGA_HF_ISO14443A_READER_MOD) & ~mod_sig_coil) || (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN)));
|
||||
|
||||
|
||||
// Enable HF antenna drivers:
|
||||
assign pwr_oe1 = 1'b0;
|
||||
assign pwr_oe3 = 1'b0;
|
||||
|
||||
// TAGSIM_MOD: short circuit antenna with different resistances (modulated by sub_carrier modulated by mod_sig_coil)
|
||||
// FPGA_HF_ISO14443A_TAGSIM_MOD: short circuit antenna with different resistances (modulated by sub_carrier modulated by mod_sig_coil)
|
||||
// for pwr_oe4 = 1 (tristate): antenna load = 10k || 33 = 32,9 Ohms
|
||||
// for pwr_oe4 = 0 (active): antenna load = 10k || 33 || 33 = 16,5 Ohms
|
||||
assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `TAGSIM_MOD);
|
||||
assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD);
|
||||
|
||||
// This is all LF, so doesn't matter.
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Jonathan Westhues, April 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_read_rx_xcorr(
|
||||
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
|
||||
);
|
||||
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;
|
||||
|
||||
// Carrier is steady on through this, unless we're snooping.
|
||||
assign pwr_hi = ck_1356megb & (~snoop);
|
||||
assign pwr_oe1 = 1'b0;
|
||||
assign pwr_oe3 = 1'b0;
|
||||
assign pwr_oe4 = 1'b0;
|
||||
|
||||
reg [2:0] fc_div;
|
||||
always @(negedge ck_1356megb)
|
||||
fc_div <= fc_div + 1;
|
||||
|
||||
(* clock_signal = "yes" *) reg adc_clk; // sample frequency, always 16 * fc
|
||||
always @(ck_1356megb, xcorr_is_848, xcorr_quarter_freq, fc_div)
|
||||
if (xcorr_is_848 & ~xcorr_quarter_freq) // fc = 847.5 kHz, standard ISO14443B
|
||||
adc_clk <= ck_1356megb;
|
||||
else if (~xcorr_is_848 & ~xcorr_quarter_freq) // fc = 423.75 kHz
|
||||
adc_clk <= fc_div[0];
|
||||
else if (xcorr_is_848 & xcorr_quarter_freq) // fc = 211.875 kHz
|
||||
adc_clk <= fc_div[1];
|
||||
else // fc = 105.9375 kHz
|
||||
adc_clk <= fc_div[2];
|
||||
|
||||
// When we're a reader, we just need to do the BPSK demod; but when we're an
|
||||
// eavesdropper, we also need to pick out the commands sent by the reader,
|
||||
// using AM. Do this the same way that we do it for the simulated tag.
|
||||
reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev;
|
||||
reg [11:0] has_been_low_for;
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if(& adc_d[7:0]) after_hysteresis <= 1'b1;
|
||||
else if(~(| adc_d[7:0])) after_hysteresis <= 1'b0;
|
||||
|
||||
if(after_hysteresis)
|
||||
begin
|
||||
has_been_low_for <= 7'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(has_been_low_for == 12'd4095)
|
||||
begin
|
||||
has_been_low_for <= 12'd0;
|
||||
after_hysteresis <= 1'b1;
|
||||
end
|
||||
else
|
||||
has_been_low_for <= has_been_low_for + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Let us report a correlation every 4 subcarrier cycles, or 4*16=64 samples,
|
||||
// so we need a 6-bit counter.
|
||||
reg [5:0] corr_i_cnt;
|
||||
|
||||
// And a couple of registers in which to accumulate the correlations. Since
|
||||
// load modulation saturates the ADC we have to use a large enough register
|
||||
// 32 * 255 = 8160, which can be held in 13 bits. Add 1 bit for sign.
|
||||
//
|
||||
// The initial code assumed a phase shift of up to 25% and the accumulators were
|
||||
// 11 bits (32 * 255 * 0,25 = 2040), we will pack all bits exceeding 11 bits into
|
||||
// MSB. This prevents under/-overflows but preserves sensitivity on the lower end.
|
||||
reg signed [13:0] corr_i_accum;
|
||||
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;
|
||||
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
corr_i_cnt <= corr_i_cnt + 1;
|
||||
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.
|
||||
if(corr_i_cnt == 6'd0)
|
||||
begin
|
||||
// send 10 bits of tag signal, 4 MSBs are stuffed into 2 MSB
|
||||
if(~corr_i_accum[13])
|
||||
corr_i_out <= {corr_i_accum[13],
|
||||
corr_i_accum[12] | corr_i_accum[11] | corr_i_accum[10],
|
||||
corr_i_accum[12] | corr_i_accum[11] | corr_i_accum[9],
|
||||
corr_i_accum[8:4]};
|
||||
else
|
||||
corr_i_out <= {corr_i_accum[13],
|
||||
corr_i_accum[12] & corr_i_accum[11] & corr_i_accum[10],
|
||||
corr_i_accum[12] & corr_i_accum[11] & corr_i_accum[9],
|
||||
corr_i_accum[8:4]};
|
||||
|
||||
if(~corr_q_accum[13])
|
||||
corr_q_out <= {corr_q_accum[13],
|
||||
corr_q_accum[12] | corr_q_accum[11] | corr_q_accum[10],
|
||||
corr_q_accum[12] | corr_q_accum[11] | corr_q_accum[9],
|
||||
corr_q_accum[8:4]};
|
||||
else
|
||||
corr_q_out <= {corr_q_accum[13],
|
||||
corr_q_accum[12] & corr_q_accum[11] & corr_q_accum[10],
|
||||
corr_q_accum[12] & corr_q_accum[11] & corr_q_accum[9],
|
||||
corr_q_accum[8:4]};
|
||||
|
||||
if(snoop)
|
||||
begin
|
||||
// replace LSB with 1 bit reader signal
|
||||
corr_i_out[0] <= after_hysteresis_prev_prev;
|
||||
corr_q_out[0] <= after_hysteresis_prev;
|
||||
after_hysteresis_prev_prev <= after_hysteresis;
|
||||
end
|
||||
|
||||
corr_i_accum <= adc_d;
|
||||
corr_q_accum <= adc_d;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(corr_i_cnt[3])
|
||||
corr_i_accum <= corr_i_accum - adc_d;
|
||||
else
|
||||
corr_i_accum <= corr_i_accum + adc_d;
|
||||
|
||||
if(corr_i_cnt[3] == corr_i_cnt[2]) // phase shifted by pi/2
|
||||
corr_q_accum <= corr_q_accum + adc_d;
|
||||
else
|
||||
corr_q_accum <= corr_q_accum - adc_d;
|
||||
|
||||
end
|
||||
|
||||
// The logic in hi_simulate.v reports 4 samples per bit. We report two
|
||||
// (I, Q) pairs per bit, so we should do 2 samples per pair.
|
||||
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.
|
||||
|
||||
if(corr_i_cnt[1:0] == 2'b10)
|
||||
ssp_clk <= 1'b0;
|
||||
|
||||
if(corr_i_cnt[1:0] == 2'b00)
|
||||
begin
|
||||
ssp_clk <= 1'b1;
|
||||
// Don't shift if we just loaded new data, obviously.
|
||||
if(corr_i_cnt != 6'd0)
|
||||
begin
|
||||
corr_i_out[7:0] <= {corr_i_out[6:0], corr_q_out[7]};
|
||||
corr_q_out[7:1] <= corr_q_out[6:0];
|
||||
end
|
||||
end
|
||||
|
||||
// set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35
|
||||
// (send two frames with 8 Bits each)
|
||||
if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000)
|
||||
ssp_frame = 1'b1;
|
||||
else
|
||||
ssp_frame = 1'b0;
|
||||
|
||||
end
|
||||
|
||||
assign ssp_din = corr_i_out[7];
|
||||
|
||||
assign dbg = corr_i_cnt[3];
|
||||
|
||||
// Unused.
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
endmodule
|
||||
@@ -1,78 +0,0 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// The way that we connect things when transmitting a command to an ISO
|
||||
// 15693 tag, using 100% modulation only for now.
|
||||
//
|
||||
// Jonathan Westhues, April 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_read_tx(
|
||||
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,
|
||||
shallow_modulation
|
||||
);
|
||||
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 shallow_modulation;
|
||||
|
||||
// low frequency outputs, not relevant
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
// The high-frequency stuff. For now, for testing, just bring out the carrier,
|
||||
// and allow the ARM to modulate it over the SSP.
|
||||
reg pwr_hi;
|
||||
reg pwr_oe1;
|
||||
reg pwr_oe3;
|
||||
reg pwr_oe4;
|
||||
|
||||
always @(ck_1356megb or ssp_dout or shallow_modulation)
|
||||
begin
|
||||
if(shallow_modulation)
|
||||
begin
|
||||
pwr_hi <= ck_1356megb;
|
||||
pwr_oe1 <= 1'b0;
|
||||
pwr_oe3 <= 1'b0;
|
||||
pwr_oe4 <= ~ssp_dout;
|
||||
end
|
||||
else
|
||||
begin
|
||||
pwr_hi <= ck_1356megb & ssp_dout;
|
||||
pwr_oe1 <= 1'b0;
|
||||
pwr_oe3 <= 1'b0;
|
||||
pwr_oe4 <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Then just divide the 13.56 MHz clock down to produce appropriate clocks
|
||||
// for the synchronous serial port.
|
||||
|
||||
reg [6:0] hi_div_by_128;
|
||||
|
||||
always @(posedge ck_1356meg)
|
||||
hi_div_by_128 <= hi_div_by_128 + 1;
|
||||
|
||||
assign ssp_clk = hi_div_by_128[6];
|
||||
|
||||
reg [2:0] hi_byte_div;
|
||||
|
||||
always @(negedge ssp_clk)
|
||||
hi_byte_div <= hi_byte_div + 1;
|
||||
|
||||
assign ssp_frame = (hi_byte_div == 3'b000);
|
||||
|
||||
assign ssp_din = 1'b0;
|
||||
|
||||
assign dbg = ssp_frame;
|
||||
|
||||
endmodule
|
||||
335
fpga/hi_reader.v
Normal file
335
fpga/hi_reader.v
Normal file
@@ -0,0 +1,335 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Jonathan Westhues, April 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_reader(
|
||||
ck_1356meg,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
dbg,
|
||||
subcarrier_frequency, minor_mode
|
||||
);
|
||||
input ck_1356meg;
|
||||
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;
|
||||
output dbg;
|
||||
input [1:0] subcarrier_frequency;
|
||||
input [3:0] minor_mode;
|
||||
|
||||
assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz
|
||||
|
||||
// When we're a reader, we just need to do the BPSK demod; but when we're an
|
||||
// eavesdropper, we also need to pick out the commands sent by the reader,
|
||||
// using AM. Do this the same way that we do it for the simulated tag.
|
||||
reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev;
|
||||
reg [11:0] has_been_low_for;
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (& adc_d[7:0]) after_hysteresis <= 1'b1;
|
||||
else if (~(| adc_d[7:0])) after_hysteresis <= 1'b0;
|
||||
|
||||
if (after_hysteresis)
|
||||
begin
|
||||
has_been_low_for <= 12'd0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (has_been_low_for == 12'd4095)
|
||||
begin
|
||||
has_been_low_for <= 12'd0;
|
||||
after_hysteresis <= 1'b1;
|
||||
end
|
||||
else
|
||||
has_been_low_for <= has_been_low_for + 1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Let us report a correlation every 64 samples. I.e.
|
||||
// one Q/I pair after 4 subcarrier cycles for the 848kHz subcarrier,
|
||||
// one Q/I pair after 2 subcarrier cycles for the 424kHz subcarriers,
|
||||
// one Q/I pair for each subcarrier cyle for the 212kHz subcarrier.
|
||||
// We need a 6-bit counter for the timing.
|
||||
reg [5:0] corr_i_cnt;
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
corr_i_cnt <= corr_i_cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
// A couple of registers in which to accumulate the correlations. From the 64 samples
|
||||
// we would add at most 32 times the difference between unmodulated and modulated signal. It should
|
||||
// be safe to assume that a tag will not be able to modulate the carrier signal by more than 25%.
|
||||
// 32 * 255 * 0,25 = 2040, which can be held in 11 bits. Add 1 bit for sign.
|
||||
// Temporary we might need more bits. For the 212kHz subcarrier we could possible add 32 times the
|
||||
// maximum signal value before a first subtraction would occur. 32 * 255 = 8160 can be held in 13 bits.
|
||||
// Add one bit for sign -> need 14 bit registers but final result will fit into 12 bits.
|
||||
reg signed [13:0] corr_i_accum;
|
||||
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;
|
||||
|
||||
|
||||
// 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;
|
||||
reg [12:0] min_ci_cq_2; // min_ci_cq / 2
|
||||
|
||||
always @(*)
|
||||
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_2 <= abs_cq / 2;
|
||||
end
|
||||
else
|
||||
begin
|
||||
max_ci_cq <= abs_cq;
|
||||
min_ci_cq_2 <= abs_ci / 2;
|
||||
end
|
||||
|
||||
corr_amplitude <= max_ci_cq + min_ci_cq_2;
|
||||
|
||||
end
|
||||
|
||||
|
||||
// The subcarrier reference signals
|
||||
reg subcarrier_I;
|
||||
reg subcarrier_Q;
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_848_KHZ)
|
||||
begin
|
||||
subcarrier_I = ~corr_i_cnt[3];
|
||||
subcarrier_Q = ~(corr_i_cnt[3] ^ corr_i_cnt[2]);
|
||||
end
|
||||
else if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_212_KHZ)
|
||||
begin
|
||||
subcarrier_I = ~corr_i_cnt[5];
|
||||
subcarrier_Q = ~(corr_i_cnt[5] ^ corr_i_cnt[4]);
|
||||
end
|
||||
else
|
||||
begin // 424 kHz
|
||||
subcarrier_I = ~corr_i_cnt[4];
|
||||
subcarrier_Q = ~(corr_i_cnt[4] ^ corr_i_cnt[3]);
|
||||
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) results or the
|
||||
// resulting amplitude to send out later over the SSP.
|
||||
if (corr_i_cnt == 6'd0)
|
||||
begin
|
||||
if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_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 if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ)
|
||||
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
|
||||
if (corr_i_accum[13] == 1'b0)
|
||||
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
|
||||
if (corr_q_accum[13] == 1'b0)
|
||||
corr_q_out <= {7'b0111111, after_hysteresis_prev};
|
||||
else
|
||||
corr_q_out <= {7'b1000000, after_hysteresis_prev};
|
||||
end
|
||||
else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE)
|
||||
begin
|
||||
// send amplitude
|
||||
corr_i_out <= {2'b00, corr_amplitude[13:8]};
|
||||
corr_q_out <= corr_amplitude[7:0];
|
||||
end
|
||||
else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_IQ)
|
||||
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
|
||||
if (corr_i_accum[13] == 1'b0)
|
||||
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
|
||||
if (corr_q_accum[13] == 1'b0)
|
||||
corr_q_out <= 8'b01111111;
|
||||
else
|
||||
corr_q_out <= 8'b10000000;
|
||||
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});
|
||||
corr_q_accum <= $signed({1'b0, adc_d});
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (subcarrier_I)
|
||||
corr_i_accum <= corr_i_accum + $signed({1'b0, adc_d});
|
||||
else
|
||||
corr_i_accum <= corr_i_accum - $signed({1'b0, adc_d});
|
||||
|
||||
if (subcarrier_Q)
|
||||
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. 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'b00)
|
||||
begin
|
||||
// Don't shift if we just loaded new data, obviously.
|
||||
if (corr_i_cnt != 6'd0)
|
||||
begin
|
||||
corr_i_out[7:0] <= {corr_i_out[6:0], corr_q_out[7]};
|
||||
corr_q_out[7:1] <= corr_q_out[6:0];
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
// ssp clock and frame signal for communication to and from ARM
|
||||
// _____ _____ _____ _
|
||||
// ssp_clk | |_____| |_____| |_____|
|
||||
// _____
|
||||
// ssp_frame ___| |____________________________
|
||||
// ___________ ___________ ___________ _
|
||||
// ssp_d_in X___________X___________X___________X_
|
||||
//
|
||||
// corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ...
|
||||
//
|
||||
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (corr_i_cnt[1:0] == 2'b00)
|
||||
ssp_clk <= 1'b1;
|
||||
|
||||
if (corr_i_cnt[1:0] == 2'b10)
|
||||
ssp_clk <= 1'b0;
|
||||
|
||||
// set ssp_frame signal for corr_i_cnt = 1..3
|
||||
// (send one frame with 16 Bits)
|
||||
if (corr_i_cnt == 6'd1)
|
||||
ssp_frame <= 1'b1;
|
||||
|
||||
if (corr_i_cnt == 6'd3)
|
||||
ssp_frame <= 1'b0;
|
||||
end
|
||||
|
||||
|
||||
assign ssp_din = corr_i_out[7];
|
||||
|
||||
|
||||
// a jamming signal
|
||||
reg jam_signal;
|
||||
reg [3:0] jam_counter;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (corr_i_cnt == 6'd0)
|
||||
begin
|
||||
jam_counter <= jam_counter + 1;
|
||||
jam_signal <= jam_counter[1] ^ jam_counter[3];
|
||||
end
|
||||
end
|
||||
|
||||
// Antenna drivers
|
||||
reg pwr_hi, pwr_oe4;
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
|
||||
begin
|
||||
pwr_hi = ck_1356meg;
|
||||
pwr_oe4 = ssp_dout;
|
||||
end
|
||||
else if (minor_mode == `FPGA_HF_READER_MODE_SEND_FULL_MOD)
|
||||
begin
|
||||
pwr_hi = ck_1356meg & ~ssp_dout;
|
||||
pwr_oe4 = 1'b0;
|
||||
end
|
||||
else if (minor_mode == `FPGA_HF_READER_MODE_SEND_JAM)
|
||||
begin
|
||||
pwr_hi = ck_1356meg & jam_signal;
|
||||
pwr_oe4 = 1'b0;
|
||||
end
|
||||
else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ
|
||||
|| minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE
|
||||
|| minor_mode == `FPGA_HF_READER_MODE_SNIFF_PHASE)
|
||||
begin // all off
|
||||
pwr_hi = 1'b0;
|
||||
pwr_oe4 = 1'b0;
|
||||
end
|
||||
else // receiving from tag
|
||||
begin
|
||||
pwr_hi = ck_1356meg;
|
||||
pwr_oe4 = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// always on
|
||||
assign pwr_oe1 = 1'b0;
|
||||
assign pwr_oe3 = 1'b0;
|
||||
|
||||
// Unused.
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
// Debug Output
|
||||
assign dbg = corr_i_cnt[3];
|
||||
|
||||
endmodule
|
||||
@@ -17,82 +17,105 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_simulate(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ck_1356meg,
|
||||
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,
|
||||
mod_type
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
input ck_1356meg;
|
||||
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 [2:0] mod_type;
|
||||
input [3:0] mod_type;
|
||||
|
||||
// Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can
|
||||
// always be low.
|
||||
assign pwr_hi = 1'b0;
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_hi = 1'b0; // HF antenna connected to GND
|
||||
assign pwr_lo = 1'b0; // LF antenna connected to GND
|
||||
|
||||
// This one is all LF, so doesn't matter
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
assign adc_clk = ck_1356meg;
|
||||
assign dbg = ssp_frame;
|
||||
|
||||
// The comparator with hysteresis on the output from the peak detector.
|
||||
reg after_hysteresis;
|
||||
assign adc_clk = ck_1356meg;
|
||||
reg [11:0] has_been_low_for;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if(& adc_d[7:5]) after_hysteresis = 1'b1;
|
||||
else if(~(| adc_d[7:5])) after_hysteresis = 1'b0;
|
||||
if (& adc_d[7:5]) after_hysteresis <= 1'b1; // if (adc_d >= 224)
|
||||
else if (~(| adc_d[7:5])) after_hysteresis <= 1'b0; // if (adc_d <= 31)
|
||||
|
||||
if (adc_d >= 224)
|
||||
begin
|
||||
has_been_low_for <= 12'd0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (has_been_low_for == 12'd4095)
|
||||
begin
|
||||
has_been_low_for <= 12'd0;
|
||||
after_hysteresis <= 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
has_been_low_for <= has_been_low_for + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Divide 13.56 MHz to produce various frequencies for SSP_CLK
|
||||
// and modulation. 11 bits allow for factors of up to /128.
|
||||
reg [10:0] ssp_clk_divider;
|
||||
// and modulation.
|
||||
reg [8:0] ssp_clk_divider;
|
||||
|
||||
always @(posedge adc_clk)
|
||||
always @(negedge adc_clk)
|
||||
ssp_clk_divider <= (ssp_clk_divider + 1);
|
||||
|
||||
reg ssp_clk;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if(mod_type == 3'b101)
|
||||
// Get bit every at 53kHz (every 8th carrier bit of 424kHz)
|
||||
ssp_clk <= ssp_clk_divider[7];
|
||||
else if(mod_type == 3'b010)
|
||||
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
|
||||
// Get bit every at 53KHz (every 8th carrier bit of 424kHz)
|
||||
ssp_clk <= ~ssp_clk_divider[7];
|
||||
else if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
||||
// Get next bit at 212kHz
|
||||
ssp_clk <= ssp_clk_divider[5];
|
||||
ssp_clk <= ~ssp_clk_divider[5];
|
||||
else
|
||||
// Get next bit at 424kHz
|
||||
ssp_clk <= ssp_clk_divider[4];
|
||||
ssp_clk <= ~ssp_clk_divider[4];
|
||||
end
|
||||
|
||||
|
||||
// Divide SSP_CLK by 8 to produce the byte framing signal; the phase of
|
||||
// this is arbitrary, because it's just a bitstream.
|
||||
// One nasty issue, though: I can't make it work with both rx and tx at
|
||||
// once. The phase wrt ssp_clk must be changed. TODO to find out why
|
||||
// that is and make a better fix.
|
||||
reg [2:0] ssp_frame_divider_to_arm;
|
||||
always @(posedge ssp_clk)
|
||||
ssp_frame_divider_to_arm <= (ssp_frame_divider_to_arm + 1);
|
||||
reg [2:0] ssp_frame_divider_from_arm;
|
||||
always @(negedge ssp_clk)
|
||||
ssp_frame_divider_from_arm <= (ssp_frame_divider_from_arm + 1);
|
||||
|
||||
|
||||
// Produce the byte framing signal; the phase of this signal
|
||||
// is arbitrary, because it's just a bit stream in this module.
|
||||
reg ssp_frame;
|
||||
always @(ssp_frame_divider_to_arm or ssp_frame_divider_from_arm or mod_type)
|
||||
if(mod_type == 3'b000) // not modulating, so listening, to ARM
|
||||
ssp_frame = (ssp_frame_divider_to_arm == 3'b000);
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
||||
begin
|
||||
if (ssp_clk_divider[8:5] == 4'd1)
|
||||
ssp_frame <= 1'b1;
|
||||
if (ssp_clk_divider[8:5] == 4'd5)
|
||||
ssp_frame <= 1'b0;
|
||||
end
|
||||
else
|
||||
ssp_frame = (ssp_frame_divider_from_arm == 3'b000);
|
||||
begin
|
||||
if (ssp_clk_divider[7:4] == 4'd1)
|
||||
ssp_frame <= 1'b1;
|
||||
if (ssp_clk_divider[7:4] == 4'd5)
|
||||
ssp_frame <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Synchronize up the after-hysteresis signal, to produce DIN.
|
||||
reg ssp_din;
|
||||
@@ -101,29 +124,25 @@ always @(posedge ssp_clk)
|
||||
|
||||
// Modulating carrier frequency is fc/64 (212kHz) to fc/16 (848kHz). Reuse ssp_clk divider for that.
|
||||
reg modulating_carrier;
|
||||
always @(mod_type or ssp_clk or ssp_dout)
|
||||
if(mod_type == 3'b000)
|
||||
always @(*)
|
||||
if(mod_type == `FPGA_HF_SIMULATOR_NO_MODULATION)
|
||||
modulating_carrier <= 1'b0; // no modulation
|
||||
else if(mod_type == 3'b001)
|
||||
else if(mod_type == `FPGA_HF_SIMULATOR_MODULATE_BPSK)
|
||||
modulating_carrier <= ssp_dout ^ ssp_clk_divider[3]; // XOR means BPSK
|
||||
else if(mod_type == 3'b010)
|
||||
else if(mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
||||
modulating_carrier <= ssp_dout & ssp_clk_divider[5]; // switch 212kHz subcarrier on/off
|
||||
else if(mod_type == 3'b100 || mod_type == 3'b101)
|
||||
else if(mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K || mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
|
||||
modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off
|
||||
else
|
||||
modulating_carrier <= 1'b0; // yet unused
|
||||
|
||||
// This one is all LF, so doesn't matter
|
||||
assign pwr_oe2 = modulating_carrier;
|
||||
|
||||
// Toggle only one of these, since we are already producing much deeper
|
||||
|
||||
// Load modulation. Toggle only one of these, since we are already producing much deeper
|
||||
// modulation than a real tag would.
|
||||
assign pwr_oe1 = modulating_carrier;
|
||||
assign pwr_oe4 = modulating_carrier;
|
||||
|
||||
assign pwr_oe1 = 1'b0; // 33 Ohms Load
|
||||
assign pwr_oe4 = modulating_carrier; // 33 Ohms Load
|
||||
// This one is always on, so that we can watch the carrier.
|
||||
assign pwr_oe3 = 1'b0;
|
||||
|
||||
assign dbg = ssp_din;
|
||||
assign pwr_oe3 = 1'b0; // 10k Load
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
module hi_sniffer(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ck_1356meg,
|
||||
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.
|
||||
ssp_frame, ssp_din, ssp_clk
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
input ck_1356meg;
|
||||
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;
|
||||
|
||||
1
fpga/xst_felica.scr
Normal file
1
fpga/xst_felica.scr
Normal file
@@ -0,0 +1 @@
|
||||
run -ifn fpga_felica.v -ifmt Verilog -ofn fpga_felica.ngc -ofmt NGC -p xc2s30-5-vq100 -top fpga_felica -opt_mode area -opt_level 2 -resource_sharing yes -fsm_style bram -fsm_encoding compact
|
||||
@@ -1 +0,0 @@
|
||||
run -ifn fpga_nfc.v -ifmt Verilog -ofn fpga_nfc.ngc -ofmt NGC -p xc2s30-5-vq100 -top fpga_nfc -opt_mode area -opt_level 2 -resource_sharing yes -fsm_style bram -fsm_encoding compact
|
||||
@@ -162,6 +162,8 @@ typedef enum SMARTCARD_COMMAND {
|
||||
SC_RAW = (1 << 2),
|
||||
SC_SELECT = (1 << 3),
|
||||
SC_RAW_T0 = (1 << 4),
|
||||
SC_CLEARLOG = (1 << 5),
|
||||
SC_LOG = (1 << 6),
|
||||
} smartcard_command_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -122,6 +122,7 @@ typedef struct {
|
||||
bool verbose;
|
||||
} PACKED sample_config;
|
||||
|
||||
// Tracelog Header struct
|
||||
typedef struct {
|
||||
uint32_t timestamp;
|
||||
uint16_t duration;
|
||||
@@ -288,6 +289,78 @@ typedef struct {
|
||||
const char *value;
|
||||
} PACKED ecdsa_publickey_t;
|
||||
|
||||
|
||||
// iCLASS auth request data structure
|
||||
// used with read block, dump, write block
|
||||
typedef struct {
|
||||
uint8_t key[8];
|
||||
bool use_raw;
|
||||
bool use_elite;
|
||||
bool use_credit_key;
|
||||
bool send_reply;
|
||||
bool do_auth;
|
||||
uint8_t blockno;
|
||||
} PACKED iclass_auth_req_t;
|
||||
|
||||
// iCLASS read block response data structure
|
||||
typedef struct {
|
||||
bool isOK;
|
||||
uint8_t div_key[8];
|
||||
uint8_t mac[4];
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_readblock_resp_t;
|
||||
|
||||
// iCLASS dump data structure
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t start_block;
|
||||
uint8_t end_block;
|
||||
} PACKED iclass_dump_req_t;
|
||||
|
||||
// iCLASS write block request data structure
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_writeblock_req_t;
|
||||
|
||||
// iCLASS dump data structure
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t start_block;
|
||||
uint8_t end_block;
|
||||
uint8_t data[];
|
||||
} PACKED iclass_restore_req_t;
|
||||
|
||||
|
||||
// iclass / picopass chip config structures and shared routines
|
||||
typedef struct {
|
||||
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_t;
|
||||
|
||||
// iCLASS secure mode memory mapping
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
picopass_conf_block_t conf;
|
||||
uint8_t epurse[8];
|
||||
uint8_t key_d[8];
|
||||
uint8_t key_c[8];
|
||||
uint8_t app_issuer_area[8];
|
||||
} picopass_hdr;
|
||||
|
||||
// iCLASS non-secure mode memory mapping
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
picopass_conf_block_t conf;
|
||||
uint8_t app_issuer_area[8];
|
||||
} picopass_ns_hdr;
|
||||
|
||||
|
||||
// For the bootloader
|
||||
#define CMD_DEVICE_INFO 0x0000
|
||||
//#define CMD_SETUP_WRITE 0x0001
|
||||
@@ -336,11 +409,12 @@ typedef struct {
|
||||
#define CMD_SPIFFS_MOUNT 0x0130
|
||||
#define CMD_SPIFFS_UNMOUNT 0x0131
|
||||
#define CMD_SPIFFS_WRITE 0x0132
|
||||
|
||||
// We take +0x1000 when having a variant of similar function (todo : make it an argument!)
|
||||
#define CMD_SPIFFS_APPEND 0x1132
|
||||
|
||||
#define CMD_SPIFFS_READ 0x0133
|
||||
//We use no open/close instruvtion, as they are handled internally.
|
||||
//We use no open/close instruction, as they are handled internally.
|
||||
#define CMD_SPIFFS_REMOVE 0x0134
|
||||
#define CMD_SPIFFS_RM CMD_SPIFFS_REMOVE
|
||||
#define CMD_SPIFFS_RENAME 0x0135
|
||||
@@ -351,6 +425,9 @@ typedef struct {
|
||||
#define CMD_SPIFFS_FSTAT 0x0138
|
||||
#define CMD_SPIFFS_INFO 0x0139
|
||||
#define CMD_SPIFFS_FORMAT CMD_FLASHMEM_WIPE
|
||||
|
||||
#define CMD_SPIFFS_WIPE 0x013A
|
||||
|
||||
// This take a +0x2000 as they are high level helper and special functions
|
||||
// As the others, they may have safety level argument if it makkes sense
|
||||
#define CMD_SPIFFS_PRINT_TREE 0x2130
|
||||
@@ -432,7 +509,7 @@ typedef struct {
|
||||
#define CMD_HF_ISO14443B_COMMAND 0x0305
|
||||
#define CMD_HF_ISO15693_READER 0x0310
|
||||
#define CMD_HF_ISO15693_SIMULATE 0x0311
|
||||
#define CMD_HF_ISO15693_RAWADC 0x0312
|
||||
#define CMD_HF_ISO15693_SNIFF 0x0312
|
||||
#define CMD_HF_ISO15693_COMMAND 0x0313
|
||||
#define CMD_HF_ISO15693_FINDAFI 0x0315
|
||||
#define CMD_LF_SNIFF_RAW_ADC 0x0317
|
||||
@@ -467,6 +544,7 @@ typedef struct {
|
||||
#define CMD_HF_LEGIC_INFO 0x03BC
|
||||
#define CMD_HF_LEGIC_ESET 0x03BD
|
||||
|
||||
// iCLASS / Picopass
|
||||
#define CMD_HF_ICLASS_READCHECK 0x038F
|
||||
#define CMD_HF_ICLASS_CLONE 0x0390
|
||||
#define CMD_HF_ICLASS_DUMP 0x0391
|
||||
@@ -479,6 +557,7 @@ typedef struct {
|
||||
#define CMD_HF_ICLASS_EML_MEMSET 0x0398
|
||||
#define CMD_HF_ICLASS_AUTH 0x0399
|
||||
#define CMD_HF_ICLASS_CHKKEYS 0x039A
|
||||
#define CMD_HF_ICLASS_RESTORE 0x039B
|
||||
|
||||
// For ISO1092 / FeliCa
|
||||
#define CMD_HF_FELICA_SIMULATE 0x03A0
|
||||
@@ -580,14 +659,31 @@ typedef struct {
|
||||
#define FLAG_FORCED_ATQA 0x800
|
||||
#define FLAG_FORCED_SAK 0x1000
|
||||
|
||||
//Iclass reader flags
|
||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
||||
#define FLAG_ICLASS_READER_CC 0x02
|
||||
#define FLAG_ICLASS_READER_CSN 0x04
|
||||
#define FLAG_ICLASS_READER_CONF 0x08
|
||||
// iCLASS reader flags
|
||||
#define FLAG_ICLASS_READER_INIT 0x01
|
||||
#define FLAG_ICLASS_READER_CLEARTRACE 0x02
|
||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x04
|
||||
#define FLAG_ICLASS_READER_CREDITKEY 0x08
|
||||
#define FLAG_ICLASS_READER_AIA 0x10
|
||||
#define FLAG_ICLASS_READER_ONE_TRY 0x20
|
||||
#define FLAG_ICLASS_READER_CEDITKEY 0x40
|
||||
|
||||
// iCLASS reader status flags
|
||||
#define FLAG_ICLASS_CSN 0x01
|
||||
#define FLAG_ICLASS_CC 0x02
|
||||
#define FLAG_ICLASS_CONF 0x04
|
||||
#define FLAG_ICLASS_AIA 0x08
|
||||
|
||||
// iCLASS simulation modes
|
||||
#define ICLASS_SIM_MODE_CSN 0
|
||||
#define ICLASS_SIM_MODE_CSN_DEFAULT 1
|
||||
#define ICLASS_SIM_MODE_READER_ATTACK 2
|
||||
#define ICLASS_SIM_MODE_FULL 3
|
||||
#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4
|
||||
#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only
|
||||
#define ICLASS_SIM_MODE_CONFIG_CARD 6
|
||||
|
||||
#define MODE_SIM_CSN 0
|
||||
#define MODE_EXIT_AFTER_MAC 1
|
||||
#define MODE_FULLSIM 2
|
||||
|
||||
// Dbprintf flags
|
||||
#define FLAG_RAWPRINT 0x00
|
||||
|
||||
@@ -135,7 +135,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||
#define ICLASS_CMD_ACT 0xE
|
||||
|
||||
#define ICLASS_CREDIT(x) (((x) & 0x10) == 0x10)
|
||||
#define ICLASS_DEBIT(x) !(ICLASS_CREDIT(x))
|
||||
#define ICLASS_DEBIT(x) (((x) & 0x80) == 0x80)
|
||||
|
||||
|
||||
#define ISO14443A_CMD_REQA 0x26
|
||||
@@ -297,7 +297,6 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||
#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes)
|
||||
#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes)
|
||||
|
||||
|
||||
// Definitions of which protocol annotations there are available
|
||||
#define ISO_14443A 0
|
||||
#define ICLASS 1
|
||||
@@ -315,7 +314,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||
#define PROTO_HITAG2 13
|
||||
#define PROTO_HITAGS 14
|
||||
|
||||
//-- Picopass fuses
|
||||
// Picopass fuses
|
||||
#define FUSE_FPERS 0x80
|
||||
#define FUSE_CODING1 0x40
|
||||
#define FUSE_CODING0 0x20
|
||||
@@ -325,6 +324,11 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||
#define FUSE_FPROD0 0x02
|
||||
#define FUSE_RA 0x01
|
||||
|
||||
// Picopass Pagemode fuses
|
||||
#define PICOPASS_NON_SECURE_PAGEMODE 0x01
|
||||
#define PICOPASS_SECURE_PAGEMODE 0x11
|
||||
|
||||
|
||||
// ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||
#define ISO7816_READ_BINARY 0xB0
|
||||
#define ISO7816_WRITE_BINARY 0xD0
|
||||
|
||||
@@ -50,10 +50,13 @@ static int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile) {
|
||||
if (total_size >= num_infiles * FPGA_CONFIG_SIZE) {
|
||||
fprintf(stderr,
|
||||
"Input files too big (total > %li bytes). These are probably not PM3 FPGA config files.\n"
|
||||
, num_infiles * FPGA_CONFIG_SIZE);
|
||||
, num_infiles * FPGA_CONFIG_SIZE
|
||||
);
|
||||
|
||||
for (uint16_t j = 0; j < num_infiles; j++) {
|
||||
fclose(infile[j]);
|
||||
}
|
||||
|
||||
free(fpga_config);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
@@ -188,8 +191,10 @@ static int zlib_decompress(FILE *infile, FILE *outfile) {
|
||||
* length.
|
||||
*/
|
||||
static int bitparse_find_section(FILE *infile, char section_name, unsigned int *section_length) {
|
||||
int result = 0;
|
||||
|
||||
#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
|
||||
|
||||
int result = 0;
|
||||
uint16_t numbytes = 0;
|
||||
while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
|
||||
char current_name = (char)fgetc(infile);
|
||||
@@ -252,6 +257,8 @@ static int FpgaGatherVersion(FILE *infile, char *infile_name, char *dst, int len
|
||||
strncat(dst, "LF", len - strlen(dst) - 1);
|
||||
else if (!memcmp("fpga_hf", basename(infile_name), 7))
|
||||
strncat(dst, "HF", len - strlen(dst) - 1);
|
||||
else if (!memcmp("fpga_felica", basename(infile_name), 7))
|
||||
strncat(dst, "HF FeliCa", len - strlen(dst) - 1);
|
||||
|
||||
strncat(dst, " image built", len - strlen(dst) - 1);
|
||||
if (bitparse_find_section(infile, 'b', &fpga_info_len)) {
|
||||
|
||||
80
tools/pm3_key_file_diff.py
Executable file
80
tools/pm3_key_file_diff.py
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Copyright 2018 Gerhard Klostermeier
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# Usage: ./key-file-diff.py <file A> <file B>
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# Info:
|
||||
# - Read two key files and show the keys that are in file B but not in A.
|
||||
# - Keys must be 12 hex characters long and at the beginning of a line.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def main(args):
|
||||
"""
|
||||
Read two key files and show the keys that are in file B but not in A.
|
||||
:param args: Path to two key files A and B (positional shell parameters).
|
||||
:return: 0 if everything went fine.
|
||||
"""
|
||||
key_file_a = args[1]
|
||||
key_file_b = args[2]
|
||||
|
||||
with open(key_file_a, 'r') as f:
|
||||
keys_a = parse_keys(f)
|
||||
with open(key_file_b, 'r') as f:
|
||||
keys_b = parse_keys(f)
|
||||
|
||||
# Show all keys that are in B but not in A.
|
||||
keys_diff = keys_b.difference(keys_a)
|
||||
for key in keys_diff:
|
||||
print(key)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def parse_keys(file):
|
||||
"""
|
||||
Parse keys from a file and return them as a set.
|
||||
Keys must be 12 hex characters long and at the beginning of a line.
|
||||
:param file: Path to a file containing keys.
|
||||
:return: A set of keys read from the file.
|
||||
"""
|
||||
keys = set()
|
||||
key_regex = re.compile('^[0-9a-fA-F]{12}')
|
||||
for line in file:
|
||||
key = key_regex.match(line)
|
||||
try:
|
||||
key = key.group(0).upper()
|
||||
keys.add(key)
|
||||
except AttributeError:
|
||||
pass
|
||||
return keys
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(main(sys.argv))
|
||||
Reference in New Issue
Block a user