Commit Graph

2 Commits

Author SHA1 Message Date
michael
e4a3aec46f feat(lf): FSK stack + HID Prox demod (faithful lfdemod.c port)
New pm3py/lf/fsk.py — a function-for-function Python port of the Proxmark FSK
stack (firmware/common/lfdemod.c): fsk_wave_demod (count samples between 0->1
transitions: short wave = fc/8, long = fc/10) + aggregate_bits (runs -> clock-
resolution bits) = fskdemod, plus preamble_search, HIDdemodFSK, detectAWID hooks.
Ported to track the C reference (and thus real-tag output), not reinvented.

protocols.decode_hid: FSK2a + Manchester -> Wiegand. Format is told by frame
structure, not parity alone — the 26-bit H10301 wire frame carries a 0x20 header
at bit 37 + a sentinel 1 at bit 26 (per firmware add_HID_preamble); the 37-bit
H10304 frame is header-less (37-bit Manchester count, no 0x20). Each candidate is
still parity-validated by re-encoding through the shipped HIDProxTag, so a false
alignment can't slip through. Added to the identify decoder chain after EM4100.

Synthetic HID tests build the real add_HID_preamble framing (header+sentinel for
26-bit, bare 37-bit) and render fc/8/fc/10 square waves, so a green test means the
demod inverts what a real HID card / PM3 sim emits. Full suite 1232 green.

AWID (96-bit) framing decode + PSK/Indala + biphase/FDX-B queued next.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 14:14:54 -07:00
michael
3c56d40667 feat(lf): Python LF demod stack — ASK/EM4100 + T55xx config; wire into identify
The firmware returns raw ADC envelope samples for LF reads (T55xx readbl replies
PM3_SUCCESS with NULL data); demodulation was always the C client's job, so pm3py
had none and LF identify could never see a tag. This adds the missing DSP stack in
Python — new pm3py.lf package:

- dsp.py: modulation-agnostic primitives — robust threshold, edge-interval clock
  recovery, ASK binarize, half-bit resample, Manchester + biphase decode.
- protocols.py: EM4100 (ASK/Manchester -> 40-bit ID, validated by EM4100Code's own
  header/row/col/stop parity checks) and best-effort T55xx block-0 config read
  (find the repeating 32-bit word, score by T5577Config sanity, name the emulation).
- capture.py: live-device orchestration — read the emitted stream + probe a T55xx via
  block-0 read, combine into "is it a T5577, and what is it (emulating)?".

rawcli identify now demodulates LF instead of the dead readbl-only probe: reports
"T5577 (EM4100 / EM4102)" for an emulator, "EM4100 <id>" for a bare credential.

Fully self-testing without hardware: the LF transponder models already encode these
protocols, so a synthetic envelope built from an encoder round-trips through the
demod. 17 demod tests (EM4100 across IDs/rates/mid-frame/noise, T55xx config, mocked
identify) + updated rawcli LF tests. Full suite 1225 green.

FSK/HID + PSK/Indala + biphase/FDX-B decoders queued (same dsp primitives).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 13:58:51 -07:00