fingerprintd/README.md
Jorijn van der Graaf ac0a147e95
standby unlock: a locked session unlocks by finger without PAM
Phosh's lock screen cannot take a fingerprint: its PAM conversation
answers every prompt with the password. So the daemon follows the seat
session that is locked and in front (logind LockedHint + Active), runs a
verify of its own while the display is on (backlight bl_power), and
answers a match with logind's Session.Unlock.

Only fingers named in that session owner's map unlock. The map is
re-read at every arm and verdict, and a delete cancels a running standby
verify, so a finger deleted while locked stops counting at once. A
verdict from an earlier lock or another session is dropped. no-unlock
rules and FingerMatched apply as for a client match. A client Claim
cancels standby, and its Release, or a claim that fails while pending,
re-arms it. --standby-unlock=off disables it.

Tested on the dev phone before the review fixes (map re-read,
front-session tracking, cancel ordering, pending-claim re-arm): under
Phosh, six unlocks by two fingers and an unnamed template refused; under
Plasma, kscreenlocker's pam_fprintd unlocks while standby yields and
re-arms. With the fixes: suites 8/8, and a daemon restart under a lock
screen picks the locked session up. Not exercised: standby's own
Session.Unlock on kscreenlocker, user switching.
2026-09-23 17:53:11 +02:00

71 lines
No EOL
3 KiB
Markdown

# fingerprintd
Fingerprint daemon for the Fairphone 6 (`milos`, SM7635) on mainline Linux.
`fingerprintd-core` is a static library with no GLib, no libqcomtee and no
system headers. Everything in it is a wire format or a state machine that was
recovered by reverse-engineering, so all of it is pinned by tests that run on a
dev box with no phone, no TEE and no sensor. The daemon shell holds everything
that touches hardware.
## Build
```sh
crafter-build # bin/fingerprintd-<target>-<march>/fingerprintd
crafter-build test # the unit suites
```
Cross-compiling for the phone:
```sh
packaging/make-sysroot.sh
crafter-build -- --target=aarch64-alpine-linux-musl --sysroot=~/.cache/fingerprintd/sysroot-aarch64-alpine --march=armv8.6-a+fp16fml+aes+sha3+sm4 --mtune=cortex-a720
crafter-build test --target=aarch64-alpine-linux-musl --sysroot=~/.cache/fingerprintd/sysroot-aarch64-alpine --march=armv8.6-a+fp16fml+aes+sha3+sm4 --mtune=cortex-a720
```
Verified on the device: all five suites pass cross-built and run on the phone
itself, not only under emulation.
```
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
```
## Lock-screen unlock
Two routes, both on by default:
- **PAM.** The daemon provides `fprintd`, so a lock screen that runs
`pam_fprintd` beside its password prompt unlocks by finger the usual way.
Plasma's does (`kde-fingerprint`; the `fingerprint-auth` and `postlogin`
services it needs are shipped here). Phosh's cannot: its PAM conversation
answers every prompt with the password, so a fingerprint module in its stack
would only stall the password behind the fingerprint timeout.
- **Standby.** While the session in front on its seat is locked and the
display is on, the daemon runs a verify of its own and answers a match with
logind's `Session.Unlock`, which Phosh honours. No verify runs while the
display is off (an open verify polls the sensor at ~5 Hz; the display state
comes from the backlight's `bl_power` or the panel's DRM `dpms`, and a
device with neither is treated as always on). Any fprintd client takes
precedence: a `Claim` cancels the standby verify, a `Release` re-arms it.
Only fingers named in that session owner's map unlock, and the map is
re-read at every arm, so a finger deleted while locked stops counting at
once. Per-finger `no-unlock` rules apply here too, and every match is
announced as `FingerMatched` for the session agent. `--standby-unlock=off`
disables it.
## Runtime dependencies
The `focal64` trustlet is proprietary and is not in this repo. It is
extracted from the device's own stock Android partition on first boot by the
`fp6-vendor-blobs` mechanism, the same way other firmware in fp6-img is.
## License
GPL-3.0-only, see LICENSE.
## Copyright
Copyright (C) 2026 Catcrafts® catcrafts.net