Skip to content

Commit

Permalink
Merge branch 'master' into electra_decode
Browse files Browse the repository at this point in the history
Signed-off-by: Iceman <[email protected]>
iceman1001 authored Aug 26, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents b13227a + 42c873f commit 0e00e6b
Showing 21 changed files with 171 additions and 113 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac

## [unreleased][unreleased]
- Added ELECTRA pattern decoding in `lf search` (@CiRIP)
- Firmware size optimization, skipping unused FPGA bitstreams (@douniwan5788)
- Added pretty Hitag S config parsing (@CiRIP)
- Moved Hitag S operations into separate submenu: `lf hitag s` (@CiRIP)
- Added MFC keys for Sofia public transport cards (@user890104)
15 changes: 12 additions & 3 deletions Makefile.platform.sample
Original file line number Diff line number Diff line change
@@ -20,12 +20,21 @@ PLATFORM=PM3RDV4
#PLATFORM=PM3GENERIC
#PLATFORM_SIZE=256
#STANDALONE=
#SKIP_LF=1
#SKIP_HITAG=1
#SKIP_EM4x50=1
#SKIP_EM4x70=1
#SKIP_ZX8211=1
#SKIP_HF=1
#SKIP_ISO15693=1
#SKIP_LEGICRF=1
#SKIP_ISO14443b=1
#SKIP_ISO14443a=1
#SKIP_ICLASS=1
#SKIP_FELICA=1
#SKIP_HFPLOT=1
#SKIP_NFCBARCODE=1
#SKIP_ZX8211=1
#SKIP_LF=1
#SKIP_HFSNIFF=1
#SKIP_HFPLOT=1

# To accelerate repetitive compilations:
# Install package "ccache" -> Debian/Ubuntu: /usr/lib/ccache, Fedora/CentOS/RHEL: /usr/lib64/ccache
18 changes: 10 additions & 8 deletions armsrc/appmain.c
Original file line number Diff line number Diff line change
@@ -162,7 +162,7 @@ uint16_t SumAdc(uint8_t ch, uint8_t NbSamples) {
a += ReadAdc(ch);
return (a + (NbSamples >> 1) - 1);
}

#ifdef WITH_LF
static void MeasureAntennaTuning(void) {

uint32_t peak = 0;
@@ -236,7 +236,7 @@ static void MeasureAntennaTuning(void) {
reply_ng(CMD_MEASURE_ANTENNA_TUNING, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
LEDsoff();
}

#endif
// Measure HF in milliVolt
static uint16_t MeasureAntennaTuningHfData(void) {

@@ -306,7 +306,7 @@ static void SendVersion(void) {
strncat(VersionString, "\n [ "_YELLOW_("FPGA")" ] \n ", sizeof(VersionString) - strlen(VersionString) - 1);

for (int i = 0; i < g_fpga_bitstream_num; i++) {
strncat(VersionString, g_fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1);
strncat(VersionString, g_fpga_version_information[i].versionString, sizeof(VersionString) - strlen(VersionString) - 1);
if (i < g_fpga_bitstream_num - 1) {
strncat(VersionString, "\n ", sizeof(VersionString) - strlen(VersionString) - 1);
}
@@ -1610,7 +1610,9 @@ static void PacketReceived(PacketCommandNG *packet) {
struct p *payload = (struct p *) packet->data.asBytes;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaSendCommand(FPGA_CMD_SET_EDGE_DETECT_THRESHOLD, (payload->threshold & 0x3f) | ((payload->threshold_high & 0x3f) << 6));
#ifdef WITH_LEGICRF
LegicRfSetThreshold((uint32_t)payload->legic_threshold);
#endif
break;
}
case CMD_HF_ISO14443A_SNIFF: {
@@ -2301,10 +2303,12 @@ static void PacketReceived(PacketCommandNG *packet) {
BigBuf_free();
break;
}
#ifdef WITH_LF
case CMD_MEASURE_ANTENNA_TUNING: {
MeasureAntennaTuning();
break;
}
#endif
case CMD_MEASURE_ANTENNA_TUNING_HF: {
if (packet->length != 1)
reply_ng(CMD_MEASURE_ANTENNA_TUNING_HF, PM3_EINVARG, NULL, 0);
@@ -2394,12 +2398,8 @@ static void PacketReceived(PacketCommandNG *packet) {
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
}
// Trigger a finish downloading signal with an ACK frame
// iceman, when did sending samplingconfig array got attached here?!?
// arg0 = status of download transfer
// arg1 = RFU
// arg2 = tracelen?
// asbytes = samplingconfig array
reply_mix(CMD_ACK, 1, 0, BigBuf_get_traceLen(), getSamplingConfig(), sizeof(sample_config));
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
LED_B_OFF();
break;
}
@@ -2818,11 +2818,13 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
#endif
#ifdef WITH_LF
case CMD_LF_SET_DIVISOR: {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, packet->data.asBytes[0]);
break;
}
#endif
case CMD_SET_ADC_MUX: {
switch (packet->data.asBytes[0]) {
case 0:
2 changes: 1 addition & 1 deletion armsrc/em4x70.c
Original file line number Diff line number Diff line change
@@ -377,7 +377,7 @@ static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *
uint8_t rev_rnd[7];
uint8_t temp_rnd[7];

reverse_arraycopy((uint8_t *)rnd, rev_rnd, sizeof(rev_rnd));
reverse_arraybytes_copy((uint8_t *)rnd, rev_rnd, sizeof(rev_rnd));
memcpy(temp_rnd, rnd, sizeof(temp_rnd));

for (int k = start_key; k <= 0xFFFF; ++k) {
79 changes: 48 additions & 31 deletions armsrc/fpgaloader.c
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ typedef struct {
typedef lz4_stream_t *lz4_streamp_t;

// remember which version of the bitstream we have already downloaded to the FPGA
static int downloaded_bitstream = 0;
static int downloaded_bitstream = FPGA_BITSTREAM_UNKNOWN;

// this is where the bitstreams are located in memory:
extern uint32_t _binary_obj_fpga_all_bit_z_start[], _binary_obj_fpga_all_bit_z_end[];
@@ -221,14 +221,31 @@ static int get_from_fpga_combined_stream(lz4_streamp_t compressed_fpga_stream, u
return *fpga_image_ptr++;
}

static int bitstream_target_to_index(FPGA_config bitstream_target) {
static int8_t bitstream_index_map[FPGA_BITSTREAM_MAX] = {-1};

// Initialize
if (bitstream_index_map[0] == -1){
bitstream_index_map[0] = 0;

for (size_t i = 0; i < g_fpga_bitstream_num; i++) {
FPGA_VERSION_INFORMATION info = g_fpga_version_information[i];
bitstream_index_map[info.target_config] = i;
}
}

return bitstream_index_map[bitstream_target];
}

//----------------------------------------------------------------------------
// Undo the interleaving of several FPGA config files. FPGA config files
// are combined into one big file:
// 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc.
//----------------------------------------------------------------------------
static int get_from_fpga_stream(int bitstream_version, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {
while ((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % g_fpga_bitstream_num != (bitstream_version - 1)) {
// skip undesired data belonging to other bitstream_versions
static int get_from_fpga_stream(int bitstream_target, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {
int bitstream_index = bitstream_target_to_index(bitstream_target);
while ((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % g_fpga_bitstream_num != bitstream_index) {
// skip undesired data belonging to other bitstream_targets
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
}

@@ -238,7 +255,7 @@ static int get_from_fpga_stream(int bitstream_version, lz4_streamp_t compressed_
//----------------------------------------------------------------------------
// Initialize decompression of the respective (HF or LF) FPGA stream
//----------------------------------------------------------------------------
static bool reset_fpga_stream(int bitstream_version, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {
static bool reset_fpga_stream(int bitstream_target, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {
uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE];

uncompressed_bytes_cnt = 0;
@@ -254,7 +271,7 @@ static bool reset_fpga_stream(int bitstream_version, lz4_streamp_t compressed_fp
fpga_image_ptr = output_buffer + FPGA_RING_BUFFER_BYTES;

for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++)
header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
header[i] = get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer);

// Check for a valid .bit file (starts with bitparse_fixed_header)
if (memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0)
@@ -276,7 +293,7 @@ static void DownloadFPGA_byte(uint8_t w) {
}

// Download the fpga image starting at current stream position with length FpgaImageLen bytes
static void DownloadFPGA(int bitstream_version, int FpgaImageLen, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {
static void DownloadFPGA(int bitstream_target, int FpgaImageLen, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {
int i = 0;
#if !defined XC3
AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON;
@@ -354,7 +371,7 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, lz4_streamp_t
#endif

for (i = 0; i < FpgaImageLen; i++) {
int b = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
int b = get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer);
if (b < 0) {
Dbprintf("Error %d during FpgaDownload", b);
break;
@@ -383,14 +400,14 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, lz4_streamp_t
* (big endian), <length> bytes content. Except for section 'e' which has 4 bytes
* length.
*/
static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {
static int bitparse_find_section(int bitstream_target, char section_name, uint32_t *section_length, lz4_streamp_t compressed_fpga_stream, uint8_t *output_buffer) {

#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);
char current_name = get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer);
numbytes++;
uint32_t current_length = 0;
if (current_name < 'a' || current_name > 'e') {
@@ -401,19 +418,19 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
switch (current_name) {
case 'e':
/* Four byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
current_length += get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer) << 24;
current_length += get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer) << 16;
current_length += get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer) << 0;
numbytes += 4;
if (current_length > 300 * 1024) {
/* section e should never exceed about 300KB, if the length is too big limit it but still send the bitstream just in case */
current_length = 300 * 1024;
}
break;
default: /* Two byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
current_length += get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer) << 0;
numbytes += 2;
if (current_length > 64) {
/* if text field is too long, keep it but truncate it */
@@ -429,7 +446,7 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
}

for (uint32_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) {
get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
get_from_fpga_stream(bitstream_target, compressed_fpga_stream, output_buffer);
numbytes++;
}
}
@@ -438,16 +455,16 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3

//----------------------------------------------------------------------------
// Change FPGA image status, if image loaded.
// bitstream_version is your new fpga image version
// bitstream_target is your new fpga image version
// return true if can change.
// return false if image is unloaded.
//----------------------------------------------------------------------------
#if defined XC3
static bool FpgaConfCurrentMode(int bitstream_version) {
static bool FpgaConfCurrentMode(int bitstream_target) {
// fpga "XC3S100E" image merge
// If fpga image is no init
// We need load hf_lf_allinone.bit
if (downloaded_bitstream != 0) {
if (downloaded_bitstream != FPGA_BITSTREAM_UNKNOWN) {
// test start
// PIO controls the following pins
AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_SWITCH;
@@ -457,13 +474,13 @@ static bool FpgaConfCurrentMode(int bitstream_version) {
// try to turn off antenna
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);

if (bitstream_version == FPGA_BITSTREAM_LF) {
if (bitstream_target == FPGA_BITSTREAM_LF) {
LOW(GPIO_FPGA_SWITCH);
} else {
HIGH(GPIO_FPGA_SWITCH);
}
// update downloaded_bitstream
downloaded_bitstream = bitstream_version;
downloaded_bitstream = bitstream_target;
// turn off antenna
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return true;
@@ -476,18 +493,18 @@ static bool FpgaConfCurrentMode(int bitstream_version) {
// Check which FPGA image is currently loaded (if any). If necessary
// decompress and load the correct (HF or LF) image to the FPGA
//----------------------------------------------------------------------------
void FpgaDownloadAndGo(int bitstream_version) {
void FpgaDownloadAndGo(int bitstream_target) {

// check whether or not the bitstream is already loaded
if (downloaded_bitstream == bitstream_version) {
if (downloaded_bitstream == bitstream_target) {
FpgaEnableTracing();
return;
}

#if defined XC3
// If we can change image version
// direct return.
if (FpgaConfCurrentMode(bitstream_version)) {
if (FpgaConfCurrentMode(bitstream_target)) {
return;
}
#endif
@@ -506,19 +523,19 @@ void FpgaDownloadAndGo(int bitstream_version) {
compressed_fpga_stream.lz4StreamDecode = &lz4StreamDecode_body;
uint8_t *output_buffer = BigBuf_malloc(FPGA_RING_BUFFER_BYTES);

if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer))
if (!reset_fpga_stream(bitstream_target, &compressed_fpga_stream, output_buffer))
return;

uint32_t bitstream_length;
if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) {
DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer);
downloaded_bitstream = bitstream_version;
if (bitparse_find_section(bitstream_target, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) {
DownloadFPGA(bitstream_target, bitstream_length, &compressed_fpga_stream, output_buffer);
downloaded_bitstream = bitstream_target;
}

#if defined XC3
// first download fpga image to hf
// we need to change fpga status to hf
FpgaConfCurrentMode(bitstream_version);
FpgaConfCurrentMode(bitstream_target);
#endif

// turn off antenna
@@ -603,7 +620,7 @@ void SetAdcMuxFor(uint32_t whichGpio) {

void Fpga_print_status(void) {
DbpString(_CYAN_("Current FPGA image"));
Dbprintf(" mode....................%s", g_fpga_version_information[downloaded_bitstream - 1]);
Dbprintf(" mode.................... %s", g_fpga_version_information[bitstream_target_to_index(downloaded_bitstream)]);
}

int FpgaGetCurrent(void) {
5 changes: 3 additions & 2 deletions armsrc/fpgaloader.h
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
#define __FPGALOADER_H

#include "common.h"
#include "fpga.h"

#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
@@ -164,8 +165,8 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v);
void FpgaWriteConfWord(uint16_t v);
void FpgaEnableTracing(void);
void FpgaDisableTracing(void);
void FpgaDownloadAndGo(int bitstream_version);
// void FpgaGatherVersion(int bitstream_version, char *dst, int len);
void FpgaDownloadAndGo(int bitstream_target);
// void FpgaGatherVersion(int bitstream_target, char *dst, int len);
void FpgaSetupSsc(uint16_t fpga_mode);
void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, uint16_t len);
21 changes: 0 additions & 21 deletions armsrc/optimized_cipherutils.c
Original file line number Diff line number Diff line change
@@ -114,24 +114,3 @@ uint64_t x_bytes_to_num(uint8_t *src, size_t len) {
return num;
}

uint8_t reversebyte(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) {
size_t i;
for (i = 0; i < len ; i++) {
arr[i] = reversebyte(arr[i]);
}
}

void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) {
size_t i;
for (i = 0; i < len ; i++) {
dest[i] = reversebyte(arr[i]);
}
}

3 changes: 0 additions & 3 deletions armsrc/optimized_cipherutils.h
Original file line number Diff line number Diff line change
@@ -57,7 +57,4 @@ int bitsLeft(BitstreamIn_t *stream);
void push6bits(BitstreamOut_t *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 reversebyte(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
Loading

0 comments on commit 0e00e6b

Please sign in to comment.