From 81a5211594cee73dac4291bf4f2afb711ed785c1 Mon Sep 17 00:00:00 2001 From: CinderSocket Date: Sun, 7 Jun 2026 16:32:17 -0700 Subject: [PATCH] Fix a situation where memory is improperly cleared --- CHANGELOG.md | 1 + armsrc/appmain.c | 8 ++------ armsrc/fpgaloader.c | 29 +++++++++++++++++++++++------ armsrc/fpgaloader.h | 1 + tools/pm3_online_tests.sh | 17 +++++++++++++++-- 5 files changed, 42 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55e11e25a..adfcc59dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b59b15018..9c669088d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -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); diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 2d97129ec..046c1e259 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -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); } //----------------------------------------------------------------------------- diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 05fed4b1a..191120155 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -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); diff --git a/tools/pm3_online_tests.sh b/tools/pm3_online_tests.sh index b5963414e..325e4b23b 100755 --- a/tools/pm3_online_tests.sh +++ b/tools/pm3_online_tests.sh @@ -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