README: it works end to end through fprintd's own clients

This commit is contained in:
Jorijn van der Graaf 2026-09-02 22:29:59 +02:00
commit 1368b2f474

View file

@ -75,30 +75,46 @@ itself**, not only under emulation.
## Status ## Status
**The core is complete; the daemon does not run yet.** Everything was ported **It works end to end through fprintd's own clients.** On the Fairphone 6, as a
out of the research harness that first made the sensor work (`utilities/fpta.c` systemd unit owning `net.reactivated.Fprint`:
in the fp6 repo), one module at a time, each landing with its tests before the
next started. ```
fprintd-enroll -f right-index-finger user ten stages, enroll-completed
fprintd-list user - #0: right-index-finger
fprintd-verify user (wrong finger) verify-no-match, on the first press
fprintd-verify user (enrolled finger) verify-match, on the first press
```
Nothing in fprintd was modified; the daemon speaks its interface.
| module | what it holds | | module | what it holds |
|---|---| |---|---|
| `:Sfs` | the gpfile frame — the read/write offset split, the `O_TRUNC` guard, root mapping, path-traversal rejection | | `:Sfs` | the gpfile frame — the read/write offset split, the `O_TRUNC` guard, root mapping, path-traversal rejection |
| `:Rpmb` | request/reply framing, the bytes-transferred out-parameter, JEDEC result codes, chunking, the one-time-programmable key guard | | `:Rpmb` | request/reply framing, the bytes-transferred out-parameter, JEDEC result codes, chunking, the one-time-programmable key guard |
| `:Ta` | command surface, the 740-byte event context, capture flags, SAVE_DATA masks, enrol/auth payloads, the error table, the verdict rule | | `:Ta` | command surface, the 740-byte event context, capture flags, save masks, enrol/auth payloads, the error table, the verdict rule |
| `:Engine` | baseline calibration, touch edges, enrolment progress, and the accounting | | `:Engine` | baseline calibration, touch edges, enrolment progress, the accounting |
| `:Store` | the finger name map | | `:Store` | the finger name map |
| `:Tee` | QTEE service/op numbers, the listener table, the 13-byte CBOR credentials blob |
| `:Sensor` | the pins, the timings, and the XPU guard |
Every constant that was recovered by reverse-engineering carries where it came Every constant that was recovered by reverse-engineering carries where it came
from, and the tests are written to fail if it is undone rather than to restate from, and the tests are written to fail if it is undone rather than to restate
it. Several replay real captures: two SFS containers off the phone, and three it. Several replay real captures off the phone.
recorded authentication runs.
Next is the I/O shell — the TEE session, the sensor rail, the RPMB device and Two policy decisions live in the daemon and both were forced by measurement.
the bus — which is the first part that cannot be validated without hardware. Verification is judged **per press**: any matching frame wins, only rejections
is no-match — both correct presses in the acceptance run had rejected frames
before the one that matched, so a first-frame rule would have failed them. And
the shipped config sets `max_authentication_rescan_times` to 0, because at the
stock budget a wrong finger never yields a terminal frame and a PAM client
waits forever for the `verify-no-match` it needs.
The working reference enrols a finger, keeps it across a reboot, and matches it **Not done:** packaging (`provides="fprintd=…"` so this replaces the fprintd
with zero false accepts; the port exists to turn that into a service rather daemon package while `fprintd-pam` stays), the shipped storage policy, polkit
than to rediscover it. (a caller-uid rule stands in), trustlet-side template removal (deletes drop the
name only), cleanup when a claiming client vanishes from the bus, and the
kernel config change — `CONFIG_QCOMTEE`, which selects the SHM bridge — that
gates any public image.
## Runtime dependencies, not carried here ## Runtime dependencies, not carried here