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
**The core is complete; the daemon does not run yet.** Everything was ported
out of the research harness that first made the sensor work (`utilities/fpta.c`
in the fp6 repo), one module at a time, each landing with its tests before the
next started.
**It works end to end through fprintd's own clients.** On the Fairphone 6, as a
systemd unit owning `net.reactivated.Fprint`:
```
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 |
|---|---|
| `: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 |
| `:Ta` | command surface, the 740-byte event context, capture flags, SAVE_DATA masks, enrol/auth payloads, the error table, the verdict rule |
| `:Engine` | baseline calibration, touch edges, enrolment progress, and the accounting |
| `: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, the accounting |
| `: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
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
recorded authentication runs.
it. Several replay real captures off the phone.
Next is the I/O shell — the TEE session, the sensor rail, the RPMB device and
the bus — which is the first part that cannot be validated without hardware.
Two policy decisions live in the daemon and both were forced by measurement.
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
with zero false accepts; the port exists to turn that into a service rather
than to rediscover it.
**Not done:** packaging (`provides="fprintd=…"` so this replaces the fprintd
daemon package while `fprintd-pam` stays), the shipped storage policy, polkit
(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