Port the RPMB listener's wire format, guard included

Fingerprintd:Rpmb is the other half of QTEE's storage. Where gpfile moves the
container bytes, RPMB is the anti-rollback: an authenticated, monotonically
counted area of the UFS device that lets QTEE tell a genuine store from an old
one replayed back at it. Framing and policy only; the SCSI transport stays in
the daemon shell.

The guard is the reason this module has tests rather than just constants.
req_resp 0x0001 is Authentication Key Programming, and the RPMB key is one-time
programmable in the UFS device -- relaying such a frame destroys that part's
RPMB permanently and no reflash recovers it. QTEE has no legitimate reason to
send one, so it is refused unconditionally, whatever the write policy says. It
is tested for scanning every frame rather than the first, and for refusing a
request that claims more frames than the buffer holds instead of reading past
the end.

The out-parameter at +0x08 is the field that failed every RPMB transaction for
a week. librpmb passes it by address, so it reports bytes transferred, and QTEE
compares it against what it expected and rejects the transaction on a mismatch.
A read posts one request frame however large nblocks is while a write posts
nblocks * 512, so the two directions genuinely do not report the same thing --
tested as such, because leaving the request's frame size there is the bug.

+0x0c is kept exactly as the request supplied it. QTEE looks for the response
frames at req + req[0x0c] and the request arrives with 0x18; librpmb's
hardcoded 20 points four bytes early.

Chunking refuses a remainder rather than following the reference, which
silently drops one -- a partial authenticated write leaves the store
inconsistent with a counter that cannot be moved back.

Verified by mutation: checking only the first frame for key programming,
reporting a flat frame size as bytes transferred, and admitting a remainder
each fail the suite.
This commit is contained in:
Jorijn van der Graaf 2026-09-02 16:48:57 +02:00
commit 1db0762078
4 changed files with 459 additions and 1 deletions

View file

@ -21,9 +21,10 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
ApplyStandardArgs(*Core, args);
Core->type = ConfigurationType::LibraryStatic;
{
std::array<fs::path, 3> ifaces = {
std::array<fs::path, 4> ifaces = {
"interfaces/Fingerprintd",
"interfaces/Fingerprintd-Sfs",
"interfaces/Fingerprintd-Rpmb",
"interfaces/Fingerprintd-Ta",
};
std::array<fs::path, 0> impls = {};
@ -46,6 +47,7 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
}
cfg.AddTest("Sfs").Dependencies({ Core.get() });
cfg.AddTest("Rpmb").Dependencies({ Core.get() });
cfg.AddTest("Ta").Dependencies({ Core.get() });
ProjectLint::AddProjectLintRules(cfg);