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:
Philippe Teuwen
2020-08-13 10:18:12 +02:00
81 changed files with 8199 additions and 4941 deletions

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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

View File

@@ -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)),)

View File

@@ -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

View 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 ]=-");
}

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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.

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
/**

View File

@@ -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);
}
}

View File

@@ -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

View 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]);
}
}

View 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
View 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
View 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
View 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
View 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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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");

View File

@@ -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

View File

@@ -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}
};

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);

View File

@@ -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, "?");

View File

@@ -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"},

View File

@@ -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)

View File

@@ -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}
};

View File

@@ -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);

View File

@@ -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[] = {

View File

@@ -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

View File

@@ -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}
};

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

Binary file not shown.

226
fpga/fpga_felica.v Normal file
View 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

Binary file not shown.

View File

@@ -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;

Binary file not shown.

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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;
//-----------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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))