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.
54 lines
1.9 KiB
C++
54 lines
1.9 KiB
C++
// SPDX-License-Identifier: GPL-3.0-only
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
|
|
|
// lint-disable-file no-char-pointer
|
|
import std;
|
|
import Crafter.Build;
|
|
#include "lint-rules.h"
|
|
namespace fs = std::filesystem;
|
|
using namespace Crafter;
|
|
|
|
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
|
// fingerprintd-core — the wire formats and state machines as a static
|
|
// library of pure C++ modules. Deliberately free of GLib, libqcomtee and
|
|
// every system header: the byte-level decisions in here were the whole
|
|
// cost of this project, so they are pinned by tests that run on a dev box
|
|
// with no phone, no TEE and no sensor.
|
|
static auto Core = std::make_unique<Configuration>();
|
|
Core->path = "./";
|
|
Core->name = "fingerprintd-core";
|
|
Core->outputName = "fingerprintd-core";
|
|
ApplyStandardArgs(*Core, args);
|
|
Core->type = ConfigurationType::LibraryStatic;
|
|
{
|
|
std::array<fs::path, 3> ifaces = {
|
|
"interfaces/Fingerprintd",
|
|
"interfaces/Fingerprintd-Sfs",
|
|
"interfaces/Fingerprintd-Ta",
|
|
};
|
|
std::array<fs::path, 0> impls = {};
|
|
Core->GetInterfacesAndImplementations(ifaces, impls);
|
|
}
|
|
|
|
// fingerprintd — the daemon: sensor rail, QTEE session, the gpfile and
|
|
// RPMB listeners, and the bus surface, wrapped around the core.
|
|
Configuration cfg;
|
|
cfg.path = "./";
|
|
cfg.name = "fingerprintd";
|
|
cfg.outputName = "fingerprintd";
|
|
ApplyStandardArgs(cfg, args);
|
|
cfg.type = ConfigurationType::Executable;
|
|
cfg.dependencies = { Core.get() };
|
|
{
|
|
std::array<fs::path, 0> ifaces = {};
|
|
std::array<fs::path, 1> impls = { "implementations/main" };
|
|
cfg.GetInterfacesAndImplementations(ifaces, impls);
|
|
}
|
|
|
|
cfg.AddTest("Sfs").Dependencies({ Core.get() });
|
|
cfg.AddTest("Ta").Dependencies({ Core.get() });
|
|
|
|
ProjectLint::AddProjectLintRules(cfg);
|
|
|
|
return cfg;
|
|
}
|