Merge pull request #3366 from cindersocket/feat-iclass-emulator-workflows

Preserve iCLASS emulator memory across HF_15 reloads
This commit is contained in:
Iceman authored and GitHub committed 2026-06-08 06:30:01 +02:00
commit c9220526bf
5 files changed
+42 -14

No files matched your search

+1
View File
@@ -4,6 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
- Added `hf mfdes getversion` command (@kormax)
- Fixed iCLASS emulator writes clearing previously loaded emulator memory after an FPGA reload (@cindersocket)
- Added DES transport mode support for iCLASS credential encode/decode helpers. (@cindersocket)
- Changed `doc/magic_cards_notes.md` - updated the ID82xx / Hitag µ clone section with current Proxmark3 support, chip variations, default passwords and detection notes (@mishamyte)
- Added two Mifare Classic keys into extensive dictionary which are hardcoded into Mifare Plus SE (@team-orangeBlue)
+2 -6
View File
@@ -2366,12 +2366,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_ICLASS_EML_MEMSET: {
//-----------------------------------------------------------------------------
// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15) here although FPGA is not
// involved in dealing with emulator memory. But if it is called later, it might
// destroy the Emulator Memory.
//-----------------------------------------------------------------------------
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15);
FpgaDownloadAndGo_keep_EM(FPGA_BITSTREAM_HF_15);
struct p {
uint16_t offset;
uint16_t len;
@@ -2732,6 +2727,7 @@ static void PacketReceived(PacketCommandNG *packet) {
}
case CMD_FPGA_MAJOR_MODE_OFF: { // ## FPGA Control
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
FpgaResetBitstream();
g_hf_field_active = false;
g_hf_field_timeout_active = false;
SpinDelay(200);
+23 -6
View File
@@ -495,8 +495,7 @@ static bool FpgaConfCurrentMode(int bitstream_target) {
// 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_target) {
static void FpgaDownloadAndGoEx(int bitstream_target, bool keep_em) {
// check whether or not the bitstream is already loaded
if (downloaded_bitstream == bitstream_target) {
FpgaEnableTracing();
@@ -517,8 +516,13 @@ void FpgaDownloadAndGo(int bitstream_target) {
bool verbose = (g_dbglevel > 3);
// make sure that we have enough memory to decompress
BigBuf_free();
BigBuf_Clear_ext(verbose);
if (keep_em) {
BigBuf_free_keep_EM();
BigBuf_Clear_keep_EM();
} else {
BigBuf_free();
BigBuf_Clear_ext(verbose);
}
lz4_stream_t compressed_fpga_stream;
LZ4_streamDecode_t lz4StreamDecode_body = {{ 0 }};
@@ -545,8 +549,21 @@ void FpgaDownloadAndGo(int bitstream_target) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// free eventually allocated BigBuf memory
BigBuf_free();
BigBuf_Clear_ext(false);
if (keep_em) {
BigBuf_free_keep_EM();
BigBuf_Clear_keep_EM();
} else {
BigBuf_free();
BigBuf_Clear_ext(false);
}
}
void FpgaDownloadAndGo(int bitstream_target) {
FpgaDownloadAndGoEx(bitstream_target, false);
}
void FpgaDownloadAndGo_keep_EM(int bitstream_target) {
FpgaDownloadAndGoEx(bitstream_target, true);
}
//-----------------------------------------------------------------------------
+1
View File
@@ -166,6 +166,7 @@ void FpgaWriteConfWord(uint16_t v);
void FpgaEnableTracing(void);
void FpgaDisableTracing(void);
void FpgaDownloadAndGo(int bitstream_target);
void FpgaDownloadAndGo_keep_EM(int bitstream_target);
// void FpgaGatherVersion(int bitstream_target, char *dst, int len);
void FpgaSetupSsc(uint16_t fpga_mode);
void SetupSpi(int mode);
+15 -2
View File
@@ -12,6 +12,7 @@ TESTDESFIREVALUE=false
TESTHIDWIEGAND=false
TESTMFHIDENCODE=false
TESTICLASSREADER=false
TESTICLASSEMU=false
NEED_MF_HID_ENCODE_WIPE=false
TESTMANUAL=false
@@ -21,13 +22,14 @@ while (( "$#" )); do
case "$1" in
-h|--help)
echo """
Usage: $0 [--pm3bin /path/to/pm3] [--pm3port /dev/tty...] [desfire_value|hid_wiegand|mf_hid_encode|iclass_reader]
Usage: $0 [--pm3bin /path/to/pm3] [--pm3port /dev/tty...] [desfire_value|hid_wiegand|mf_hid_encode|iclass_emu|iclass_reader]
--pm3bin ...: Specify path to pm3 binary to test
--pm3port ...: Specify serial port for client/proxmark3
--manual ...: Pause after successful online LF HID clone/read checks for external reader verification
desfire_value: Test DESFire value operations with card
hid_wiegand: Test LF HID T55xx clone and PM3 readback flows
mf_hid_encode: Test MIFARE Classic HID encoding flows
iclass_emu: Test iCLASS emulator memory load/write/read flows
iclass_reader: Load iCLASS HID credentials into emulator memory for external reader verification
You must specify a test target - no default 'all' for online tests
"""
@@ -75,6 +77,11 @@ Usage: $0 [--pm3bin /path/to/pm3] [--pm3port /dev/tty...] [desfire_value|hid_wie
TESTICLASSREADER=true
shift
;;
iclass_emu)
TESTALL=false
TESTICLASSEMU=true
shift
;;
-*|--*=) # unsupported flags
echo "Error: Unsupported flag $1" >&2
exit 1
@@ -358,7 +365,7 @@ if command -v git >/dev/null && git rev-parse --is-inside-work-tree >/dev/null 2
fi
# Check that user specified a test
if [ "$TESTDESFIREVALUE" = false ] && [ "$TESTHIDWIEGAND" = false ] && [ "$TESTMFHIDENCODE" = false ] && [ "$TESTICLASSREADER" = false ]; then
if [ "$TESTDESFIREVALUE" = false ] && [ "$TESTHIDWIEGAND" = false ] && [ "$TESTMFHIDENCODE" = false ] && [ "$TESTICLASSEMU" = false ] && [ "$TESTICLASSREADER" = false ]; then
echo "Error: You must specify a test target. Use -h for help."
exit 1
fi
@@ -417,6 +424,12 @@ while true; do
if ! CheckMfHidEncodeCleanup "hf mf encodehid cleanup verify"; then break; fi
fi
if $TESTICLASSEMU; then
echo -e "\n${C_BLUE}Testing iCLASS emulator memory${C_NC} ${PM3BIN:=./pm3}"
if ! CheckFileExist "pm3 exists" "$PM3BIN"; then break; fi
if ! CheckExecute "hf iclass esetblk preserves emu" "$PM3BIN -c 'hf iclass eload -f traces/iclass/hf-iclass-dump.json; hw fpgaoff; hf iclass esetblk --blk 7 -d A55AC33C9669F00F; hf iclass eview -s 64' 2>&1 | LC_ALL=C tr -cd '\11\12\15\40-\176' | tr '\n' ' '" "0/0x00.*6D C2 5B 15 FE FF 12 E0.*7/0x07.*A5 5A C3 3C 96 69 F0 0F"; then break; fi
fi
if $TESTICLASSREADER; then
echo -e "\n${C_BLUE}Testing iCLASS reader verification${C_NC} ${PM3BIN:=./pm3}"
if ! CheckFileExist "pm3 exists" "$PM3BIN"; then break; fi