Large GET DATA returns 61 xx. Concatenate clear 00 C0 bodies before
unwrap so 255-byte AES and 2K3DES objects print instead of exit 246.
Co-Authored-By: Cursor Grok 4.6 <noreply@cursor.com>
The hardcoded openssl@3.6 include path fails macOS CI when that formula
is absent. Ask brew for the installed OpenSSL prefix and use it for
both headers and libraries.
Built all three mfd_aes_brute tools with Clang and GCC 16 against
OpenSSL 3 and 4 on macOS. Existing linker deprecation warnings remain.
GCC 8.5 emits COMMON globals by default. Apply -fno-common in the shared
Make and CMake flags so it covers the OS, bootrom and PM5 armlib. Also
remove bootrom archives on clean to avoid reusing old library objects.
Built OS and bootrom for PM5/RDV4 with GCC 8.5/13.3 using Make and CMake.
No COMMON object symbols remain; PM5 CDC state is inside BSS. Existing
build warnings remain. No hardware was flashed.
hf seos pacs on 2K3DES cards exited 236 with no message after mutual
auth. Print ExchangeAPDU14a failures, check mbedtls DES-CMAC without
mutating the caller key, decode SELECT 85 at its real length, and emit
short-form 85 when the cryptogram is under 128 bytes.
Co-Authored-By: Cursor Grok 4.6 <noreply@cursor.com>
The bootrom linker script defines __bss_end__ before COMMON symbols are
placed. Startup clears only up to that boundary. On PM5 with ARM GCC 8.5,
this leaves the entire 92-byte USB CDC structure outside the zeroed area,
even though bootrom sources themselves are built with -fno-common.
Place COMMON inside .bss before setting __bss_end__, and assert that the
boundary covers the whole section. The shared script applies to PM5 and
RDV4. On the tested PM5 build, stack addresses, the shared communication
area and the entry point remain unchanged.
Built both targets with ARM GCC 8.5 and ran bootrom/check. Checked ELF
boundaries and the 16 KiB boot partition; removing COMMON placement
triggers the new assertion. No compiler warnings; the existing PM5 RWX
LOAD-segment linker warning remains. CMake and BWM builds were not tested.
Flashed the bootrom alone on PM5 and verified readback against the image.
All internal flash bytes from the OS start onward matched the pre-flash
backup. Cold startup and five software reset cycles passed. Five complete
bootloader/read/reset cycles also passed after fixing the client's dump
cleanup separately. FPGA was not written. This corrects initialization;
it does not establish a fix for the USB-controller failures in #3642.
Bootloader memory-dump cleanup sends CMD_PING to wake the communication
thread after clearing its run flag. The thread can be waiting for another
transmit after the dump ACK, so it sends this command before exiting.
The non-BWM bootrom does not handle CMD_PING: its default dispatch enters
Fatal(), leaving the device unresponsive even though the dump succeeded.
Use CMD_DEVICE_INFO for the wakeup instead. It is already supported by the
bootloader and used to identify it before the dump. Keep the wakeup so
closing the client does not leave the communication thread waiting.
Reproduced on PM5: the dump completed, but the following reset and device
probe failed. With only the rebuilt client changed, the same test script
passed five OS-to-bootloader, memory-dump and reset-to-OS cycles, with a
successful ping after each. No firmware was flashed for this comparison.
Built the client with AppleClang through Make, CMake and experimental_lib;
client/check passed. GCC 16 compiled the changed translation unit with
-Wall -Werror. Existing macOS linker warnings remain. The full GCC host
build was not repeated because of the previously observed Apple SDK
alignment error. Linux and Windows were not tested; this change replaces
an existing protocol command without changing platform-specific code.
Problem
The native hf mfu countertear used a device-side
CMD_HF_MFU_COUNTER_TEAROFF path with a static increment payload,
decided once per run. The pyscript mfuev1_counter_reset.py implements
the same attack with auto-calibration, a 3-phase attack loop,
per-attempt BD delay tuning (hunting) and stuck-value handling,
which the native command lacked.
Change
- rewrite the client command around the generic tear-off hook
(hw tearoff) and raw INCREASE_CNT frames, mirroring the pyscript
step by step: preflight checks, CHECK_TEARING_EVENT support gate,
targeted repair/normalize, BD sweep calibration (working delay
accepted only on 0xBD), and the DECREMENT -> PREPARE (0x00FFFF)
-> RESET phases with the same increment payloads (000100 for
decrement steps, 010000 for reset/repair)
- same delay tuning on counter movement: +1 when unchanged, -1 when
a jump exceeds 10, delay locked after a successful decrement
- remove CMD_HF_MFU_COUNTER_TEAROFF usage from the client; device
side stays untouched
- add Lua port client/luascripts/mfuev1_counter_reset.lua with the
same behaviour, using core.console capture and Enter-to-stop
- regenerate doc/commands.md and doc/commands.json
Behaviour change
Same CLI shape as the pyscript (-c/-f/--DelayBD/--Delay00, legacy
-i/-l/-s/-x options removed). Console output now matches the pyscript.
Testing
gcc warningless for client, armsrc and bootrom (RDV4). make check
green. doc regenerated with GD enabled. Verified 1:1 against the
pyscript and the new Lua port on hardware (EV1 card). Not tested
here: clang, Windows/ProxSpace and macOS. No build files are touched,
so the usual client-side review applies.
Co-Authored-By: opencode agent (GLM-5.3-Flash-Free) <noreply@opencode.ai>
Validate counter choices 0-2, treat only 0x00/0xBD as valid
CHECK_TEARING_EVENT answers, and detect NACK replies from the raw
payload, so retry logic does not mistake a NACK for a real answer.
Building the client with -march=x86-64-v3 (the CentOS/RHEL 10
baseline) fails with gcc 14:
src/emv/emvcore.c:211:24: error: writing 32 bytes into a region of
size 22 [-Werror=stringop-overflow=]
gcc vectorizes the dash fill loop in aidlist_rule() into 32-byte
stores and loses the pos + 2 < dstlen bound. The bound was correct.
Compute the dash count with the same limit and fill it with memset,
so there is no vectorized loop store to mis-size. Output is unchanged.
Reported in #3671.
Co-Authored-By: Grok Bot <noreply@users.noreply.github.com>
SPI1 is full-duplex with no RX FIFO. Every byte cep_spi_write_sync()
clocks out on MISO also shifts a byte in on MOSI that nothing reads,
and AT32F435/437 RM ch 13.2.9 says the first such byte freezes in
SPI_DT until read - not "newest overwrites oldest" as assumed before.
A frozen byte then gets misread by cep_spi_data_available() as part of
the next frame's length header, forcing a resync. Clear ROERR once
after the write (before the read path can touch it) and once at the
top of the read path (for freezes from other main-loop gaps).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>