fingerprintd/tests/Ta/fixtures
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jorijn van der Graaf ffad29ba4e Port the trustlet command surface, and pin the counting rule to recorded runs
Fingerprintd:Ta is the second core module: request payloads, response fields,
the error table, and the rule that decides what a frame meant. Payload building
and response reading only -- no TEE, no transport.

Very little of this is guessable, so each constant carries where it came from.
Three were found only because QTEE recorded a fault naming the instruction that
read them:

  * the event context's scan-slot count at +712, which do_enroll branches on to
    skip the entire slot loop -- an all-zero payload logged "groups->,
    results->" and read exactly like a gate failing deep in the trustlet, when
    it was zero iterations;
  * CAPTURE_IMAGE's flags at payload+0x18, without which preprocessing, the
    classifier and the enrol grouper never run at all, whatever is on the
    sensor;
  * SYNC_STATISTICS, whose absence leaves g_statistics NULL so the first enrol
    frame that gets far enough takes a data abort and every later command
    answers -90.

The verdict rule gets the most attention because it was mislabelled three times
before the comparison producing it was read. A frame is one of three things and
only the third is a verdict: the poison intact means the matcher never ran,
rc=-11 means not identified yet with attempts remaining, and only rc=0 carries
a match or a rejection. The poison exists because a zero-initialised buffer
cannot tell a released finger from a rejected one.

The tests are in two halves that cannot prop each other up. Explicit wire
conditions pin the classifier; three recorded runs pin the counting policy,
which is what actually went wrong. In the stock-budget run 31 of 48 frames
answered "not identified yet" and every frame that carried an image matched --
counting those 31 as attempts turns 8-for-8 into 8-of-39 and reads as a flaky
sensor. The wrong-finger control pins zero false accepts.

Fixtures are verdict-line excerpts, not the 40 KB transcripts, which are thick
with the device's SFS container names the test has no use for.

Verified by mutation: classifying -11 as a rejection, dropping SYNC_STATISTICS
from the init chain, and forgetting the +0x10 response payload offset each fail
the suite.
2026-09-02 16:46:00 +02:00
..
auth-enrolled-finger.txt Port the trustlet command surface, and pin the counting rule to recorded runs 2026-09-02 16:46:00 +02:00
auth-stock-budget.txt Port the trustlet command surface, and pin the counting rule to recorded runs 2026-09-02 16:46:00 +02:00
auth-wrong-finger.txt Port the trustlet command surface, and pin the counting rule to recorded runs 2026-09-02 16:46:00 +02:00
README.md Port the trustlet command surface, and pin the counting rule to recorded runs 2026-09-02 16:46:00 +02:00

Recorded authentication verdicts

Verdict lines excerpted from three real authentication runs on the dev phone, 2026-09-02. Only the AUTH lines are carried: the full transcripts are ~40 KB each and are thick with the device's SFS container names, none of which this test needs. Originals are in the fp6 journal under journal/fingerprint/captures/.

file run recorded outcome
auth-enrolled-finger.txt the enrolled finger, max_authentication_rescan_times: 0 15 match, 5 rejected, 5 frames the matcher never saw
auth-wrong-finger.txt a different finger, same config 0 match, 19 rejected, 2 never ran
auth-stock-budget.txt the enrolled finger at the stock rescan budget 8 match, 31 "no match", 9 never ran

The third file is the important one and uses an older label: its 31 "no match" lines are rc=-11 frames, which mean not identified yet, attempts remain — not rejections. Counting them as rejections turns an 8-for-8 run into an apparent 8-of-39 and reads as a flaky sensor. That mislabelling happened three separate times before the comparison producing -11 was actually read, which is why the counting rule has a test at all.

The two forced-terminal runs set the rescan budget to 0 so every frame yields a verdict. Their 15/20 is therefore a per-frame figure measured with the retry mechanism disabled, not a shipping reject rate; per press it was 5 of 5.

fid=1296911490 is the enrolled template's identifier on one dev phone. It is an opaque id, not biometric data — a template is a separate 258850-byte QTEE-encrypted container that never leaves the TEE.