fplearn.sh: a wipe step, and enrol refuses a finger the group already holds

Measured 2026-09-04: the trustlet's duplicated-finger check refuses to re-enrol
a finger it already has a template for -- 0 accepted of 7 presses, rc=0 on each,
while a never-enrolled finger progressed normally. Re-enrolment adds a template
and there is no trustlet-side remove, so a measured finger's old template has to
go before it can be enrolled again.

wipe does that the way it has been done by hand twice: backup first, daemon
stopped so the trustlet reloads from the store, only the template containers
removed, the group index kept because deleting it risks the RPMB anti-rollback
counters going stale, the name map cleared, then a restart and the sizes.

enrol checks the name map and refuses a finger that is already there, pointing
at wipe, so the refusal cannot be mistaken for bad pressing again.
This commit is contained in:
Jorijn van der Graaf 2026-09-04 23:06:45 +02:00
commit f5c7b6d3b5

View file

@ -2,11 +2,19 @@
# fplearn.sh -- the template-learning measurement, as a protocol rather than a
# pile of remembered commands.
#
# fplearn.sh enrol [finger] re-enrol at the config's sample count
# fplearn.sh wipe remove every stored template (backup first)
# fplearn.sh enrol [finger] enrol at the config's sample count
# fplearn.sh base [n] [w] trial with learning OFF (the baseline)
# fplearn.sh trend [n] [w] three trials with learning ON
# fplearn.sh sizes just print the template container sizes
#
# WIPE FIRST when re-enrolling a finger that is already in the group. Measured
# 2026-09-04: the duplicated-finger check refuses a finger the group already
# holds -- 0 accepted of 7 presses, rc=0 on every one, while a never-enrolled
# finger progressed normally. Re-enrolment ADDS a template and there is no
# trustlet-side remove, so the old one has to go first. `enrol` refuses a
# finger name that is already in the map and points here.
#
# WHY IT IS SHAPED LIKE THIS. Learning is cumulative: every matched press folds
# frames into the stored template, so a second run is not a repeat of the first
# and an A/B against a moving template is not an A/B at all. The only honest
@ -27,6 +35,7 @@
set -u
GROUP=/mnt/persist/data/RIY7A+mQm3EA4FsCUmkJo0b9dFUYP2YZ4P5hmMiZgeA_Alt
MAP=/var/lib/fingerprintd/fingers-10000.map
UNIT=fingerprintd-test
BIN=/tmp/fingerprintd
COMMON="--daemon --verbose --edge-wake --sfs-root=/var/lib/fingerprintd/sfs --sfs-writable --rpmb-write"
@ -58,8 +67,46 @@ case "${1:-}" in
sizes)
echo "template containers now:"; sizes ;;
wipe)
# The procedure of 2026-09-03 and 2026-09-04, and its reasoning: ONLY the
# template containers go (>200000 bytes; each template is stored twice).
# The 1588-byte group index is KEPT -- deleting it risks the RPMB
# anti-rollback counters going stale against object ids QTEE would then
# recreate, which already cost an index restore once -- and a missing
# template container is the known-good "not exist, skip" case. The daemon
# is stopped first so the trustlet reloads from the store, and a backup is
# taken first because a template is not reproducible without a finger.
echo "=== wipe: every stored template ==="
echo "before:"; sizes
D=$HOME/fp6-backups/$(date +%Y-%m-%d-%H%M)-pre-wipe
mkdir -p "$D"
sudo tar -cf "$D/persist-data.tar" -C /mnt/persist data
sudo cp "$MAP" "$D/" 2>/dev/null || true
sudo chown -R "$(id -u):$(id -g)" "$D"
echo "backup: $D ($(tar -tf "$D/persist-data.tar" | wc -l) entries, $(sha256sum "$D/persist-data.tar" | cut -c1-16))"
sudo systemctl stop "$UNIT" 2>/dev/null; sleep 2
n=0
for f in $(sudo ls "$GROUP"); do
sz=$(sudo stat -c %s "$GROUP/$f")
if [ "$sz" -gt 200000 ]; then sudo rm -f "$GROUP/$f"; n=$((n+1)); fi
done
sudo sync
sudo sh -c ": > $MAP"
echo "removed $n container(s); index and small containers kept; map cleared"
restart "--learn=1" || exit 1
fprintd-list user 2>&1 | tail -1
echo "after:"; sizes
echo; echo "next: fplearn.sh enrol <finger>" ;;
enrol)
F=${2:-right-middle-finger}
if sudo grep -q "^$F " "$MAP" 2>/dev/null; then
echo "$F is already enrolled (in $MAP)."
echo "The trustlet REFUSES to re-enrol a finger it already holds; run"
echo " fplearn.sh wipe"
echo "first. (Measured 2026-09-04: 0 accepted of 7 presses, rc=0 each.)"
exit 1
fi
echo "=== enrol $F ==="
echo "sizes before:"; sizes
restart "--learn=1" || exit 1
@ -94,5 +141,5 @@ trend)
echo "does not is noise, and the daemon's own 'learn:' lines say which." ;;
*)
sed -n '2,30p' "$0"; exit 1 ;;
sed -n '2,38p' "$0"; exit 1 ;;
esac