Repository navigation
feat(bep): T128 — Hold the proxy's keys in the TPM - #3343
Conversation
A key store that generates each proxy key in the TPM through tpm2-tools, as P-256 keys with fixedTPM, fixedParent and noDA, each with its own authorization value in a file only the proxy's user can read.
The test runs against the TPM that BEP_TPM_TCTI names, and returns early without it. It checks custody attributes, sign and agree in the TPM, reload from the key and authorization files, and a wrong authorization.
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
|
Reviewed: 3 findings, none blocking at Address the comments on the diff. Clobber: none: the diff only adds files and one |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The TPM store conforms to Gatehouse §6.10 line 837. Each proxy key is a P-256 key in the TPM with fixedTPM, fixedParent and noDA. It signs and agrees only in the TPM. Each key has its own 256-bit authorization value, which goes to tpm2-tools on stdin and lives in a 0600 file. Nobody ran the swtpm proof. C1 requires it to pass in the bep-tpm-integration job at this head. If it fails, fix the tpm2-tools call in tpm.rs and not the test. The store choice and the TPM failure sorting are filed residuals (#3322, #3326).
Ruled at ee851be against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
|
/revise arch note on thread PRRT_kwDOPdfcxM623xGN ( Evidence: the probe uses the signing key, and that key carries noDA itself. So the test passes even when the root key has no noDA (Gatehouse §6.10 line 837: the helper's keys are created with dictionary-attack protection off). Do:
|
…roxy-s-keys-in-the-tpm
The probe used the signing key, which has noDA itself, so it passed even when the root key lacked noDA. Restore the root key's authorization file and probe the root key. Pin TPM_RC_BAD_AUTH (0x000009a2) in each refusal.
|
Round 1 of 10 on a /revise note, pushed as
Verify Review threads the coder judged:
Against swtpm, the proxy's three keys are generated in the TPM, sign and agree there, carry fixedTPM and fixedParent so the TPM refuses to duplicate them, and load again from their key and authorization files alone. The integration test now also shows that the root key itself has noDA: five wrong authorizations each get TPM_RC_BAD_AUTH (0x000009a2), and after that the root key signs again with its own authorization file. Notes from the agent: Revise round 1: addressed the /revise note in crates/bep/tests/key_store_tpm_integration.rs only. The test saves the root key's authorization file, asserts that each refusal detail ends with 0x000009a2, restores the file, then probes the root key and checks one signature. The swtpm proof at line 30 is not relaxed. Deferred (lane: tpm): cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorization. This box has no swtpm or tpm2-tools, so I did not run it. The new assertion depends on swtpm returning the session-1 BAD_AUTH code 0x000009a2 for a noDA object, as the unit test of response_code in tpm.rs already expects. cargo clippy -p bep --all-targets is clean. |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The TPM key store conforms to Gatehouse §6.10 line 837 and to BEP-088. The new test now proves noDA on the key that receives the wrong authorization values. It asserts TPM_RC_BAD_AUTH, and then it uses that same key again. One condition is open. Nobody ran the TPM proof against a TPM. C1 requires the bep-tpm-integration job to pass on this head. If the job fails, fix the tpm2-tools arguments in tpm.rs. Do not change the assertions.
Ruled at 044f75a against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
A tool that exits before it reads standard input closed the pipe, and the broken pipe returned early. The stderr with the response code was lost and the child was never reaped. Ignore the broken pipe and wait. (T128)
|
Round 2 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
Against swtpm, the proxy's three keys are generated in the TPM, sign and agree there, are refused for duplication, and load again with only their key and authorization files. The integration test in crates/bep/tests/key_store_tpm_integration.rs checks this. This box has no swtpm and no tpm2-tools, so this round did not run it. A tpm2-tools command that fails before it reads its input now still reports the TPM response code. Notes from the agent: Revise round 2. In run_once, a broken pipe on the stdin write no longer returns early. The code waits for the child, reaps it, and reads the response code from stderr. A different write error is reported only when the tool exits with success. A unit test pins this with a 4 MiB input to |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The compare changes only TpmStore::run_once. A tool that closes its input now keeps its TPM response code, and the path still fails closed, because each caller reads the tool's output file after it. Gatehouse §6.10 line 837 still governs, and the store conforms to it. C1 stays open from the earlier rulings. The tpm lane must run the swtpm proof and record the pass.
Ruled at e701890 against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
A tpm2-tools command that blocks on the TPM held the key's lock for ever. It now stops after 120 seconds with a key-store error. A killed proxy left .work-<pid>-<n> directories behind; the store now removes those whose process is gone.
|
Round 3 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
Against swtpm, the proxy's three keys are generated in the TPM, sign and agree there, are refused for duplication, and load again with only their key and authorization files. This box has no TPM, so the swtpm run is still owed by the tpm lane. In this round, a tpm2-tools command that blocks is now stopped after 120 seconds with a key-store error. Stale work directories that a killed proxy left behind are now removed. Notes from the agent: Deferred (lane: tpm): cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorization. This box has no TPM and no swtpm. I did not run it. The sweep removes a .work-- directory only when /proc/ does not exist, so a second live proxy keeps its directories. The new timeout message is a key-store error detail: " did not finish within 120 seconds, so the proxy stopped it". |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The TPM key store conforms to Gatehouse §6.10 line 837, as the earlier ruling on this PR found. The new deadline and the work-directory sweep fail closed and do not change key custody. The TPM proof leg is still not run at this head, so it is open. Run just test-tpm for this head and record the result, as C1 says.
Ruled at d80142b against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
A failed tpm2_createprimary, or a load of the new key that the TPM refuses, now returns KeyError::Store, as KeyStore::generate_in promises. agree removes the ECDH output file on every return path.
|
Round 4 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
No change to the proof this round. The code gives the proxy's three keys to the TPM: they are generated there, sign and agree there, are refused for duplication, and load again from only their key and authorization files. Nobody saw this against swtpm at this head. The tpm lane must run the deferred integration test to show it. Notes from the agent: Revise round 4. A failed key generation now always returns KeyError::Store. This includes a tpm2_createprimary failure and a TPM refusal when the new key loads. agree now removes z.point on every return path through a drop guard. |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The TPM key store conforms to Gatehouse §6.10 line 837 and to BEP-088. The latest push makes every failed generation a store error and removes the ECDH output file on every path. Both changes are correct. Nobody ran the TPM proof on this head, and that leg is open. Run just test-tpm against swtpm and record the green result, as C1 states. The process-identity binding to a dedicated proxy user is filed as gominimal/inbox#1184.
Ruled at b33a590 against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
relabel renames the auth file before the key file. A proxy that dies between them left the key without its auth file. The store now moves the orphan auth file back when it next looks at the key.
|
Round 5 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
The swtpm proof in crates/bep/tests/key_store_tpm_integration.rs is still written but has not run. When the tpm lane runs it, it will show that the proxy's three keys are generated in the TPM, sign and agree there, are refused for duplication, and load again from only their key and authorization files. In this round, a proxy that dies in the middle of a key move gets its authorization file back on the next start. Notes from the agent: Deferred (lane: tpm): cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorization. This box has no swtpm and no tpm2-tools, so neither that test nor |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The new commit adds recover_auth. It puts back an authorization file that an interrupted relabel left in another slot. It acts only on exactly one orphan, and it returns KeyError::Store on every I/O failure, so it fails closed. It does not change key custody, so Gatehouse §6.10 line 837 still holds. The TPM proof is still deferred and never ran against swtpm. Run it on the tpm lane and record the result (C1).
Ruled at b3f712c against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
…roxy-s-keys-in-the-tpm
|
Round 7 of 10 on a /revise note, pushed as
Verify Review threads the coder judged:
Against swtpm, the proxy's three keys are generated in the TPM with fixedTPM, fixedParent and noDA, which the proof reads back from the TPM's public area. They sign and agree in the TPM, and load again from their key and authorization files alone. The fixedTPM and fixedParent bits are what stop duplication, and the proof no longer makes a tpm2_duplicate call that the TPM refuses for an unrelated reason. Notes from the agent: This round removes TpmKey::duplicate and the duplicate block in the TPM proof. It restores the module doc to say that the fixedTPM and fixedParent bits stop duplication. The commit reverts 2783114, with the doc text rewrapped. All other assertions stay, including the noDA root-key probe and 0x000009a2. |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The code at this head is the same as at b3f712cb, and it conforms to Gatehouse §6.10 line 837 for BEP-088. The revert removes the tpm2_duplicate probe correctly. A password session is refused for any key, so that probe did not test the custody bits. One leg stays open. Nobody ran the TPM proof against swtpm, and §6.10 needs keys that the TPM will not export. Get a green just test-tpm run on this head and record it, as C1 says.
Ruled at 5cc0514 against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
…roxy-s-keys-in-the-tpm
A proxy killed inside write_private leaves <file>.tmp-<pid> with an authorization value in it. The sweep now removes such files when their process is gone.
|
Round 8 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
Against swtpm, the proxy's three keys are generated in the TPM, sign and agree there, and carry fixedTPM and fixedParent in the public area the TPM reports. They load again with only their key and authorization files. On this box a person can see the key template test pass. The swtpm proof in crates/bep/tests/key_store_tpm_integration.rs still needs the tpm lane (just test-tpm) to run. Notes from the agent: Revise round 8. tpm.rs: sweep_work_dirs now also removes .tmp- files whose process is gone, and a new unit test a_stale_temporary_auth_file_is_swept_when_the_store_opens_a_key covers it. Deferred (lane: tpm): cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorization. This box has no swtpm and no tpm2-tools, so I did not run it or just test-tpm. |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The new commit sweeps stale <file>.tmp-<pid> auth files with the stale work directories. That conforms, and it keeps an auth value from lingering after a killed proxy. The TPM store conforms to Gatehouse §6.10 line 837 for BEP-088. The TPM proof still did not run. Run it on the tpm lane at this head, or file an issue for it, as C1 says.
Ruled at 6110ebb against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
There was a problem hiding this comment.
Read at 6110ebb against BEP-088. The lab ran b3f712c (prepush green, the swtpm proof ran and passed);
since then the branch merged main and changed bep only in sweep_work_dirs, which I read on this head. The design follows the spec and the PR touches only bep. Three things to change before it merges,
the first a real security bug.
1. tpm2-tools reads the auth as a C string, so about 1 key in 256 ends up with an empty auth. new_auth
makes 32 raw CSPRNG bytes and every command passes them as -p file:- on stdin. In tpm2-tools
(lib/tpm2_auth_util.c), get_auth_for_file_param strips trailing \n/\r bytes and hands the buffer to
handle_password, which falls through to handle_str_password: snprintf("%s", …). The auth the TPM
stores therefore stops at the first 0x00 byte: in ~1/256 keys the first byte is zero and the auth is empty
(usable by any member of tss, which is what the module doc says cannot happen); in ~6% it is shorter than
the 128 bits BEP-088 requires; an auth ending in 0x0a is shortened too. Creating and using the key go
through the same parsing, so every test passes, and the tests check the file's length, not what the TPM
got. The integration test has the matching 1-in-256 flake: its "wrong" auth is [0u8; 32], which parses to
the empty auth and matches a real auth that starts with 0x00. Fix: write hex:<64 hex chars> on stdin
(handle_password accepts the hex: prefix inside file content, and the buffer holds it), and pin in a
unit test that the stdin bytes are hex.
2. The ECDH shared secret is written to persistent disk under $HOME. agree has tpm2_ecdhzgen -o
write Z to <store>/.work-<pid>-<n>/z.point, reads it into Zeroizing, and RemoveOnDrop unlinks it.
An unlink does not erase it from a journaled filesystem or an SSD, and a SIGKILL between the write and the
unlink leaves it until the next sweep. Z is what decrypts a sealed value: it is the secret the TPM was
meant to keep off disk. Keep the per-call output files on tmpfs (a 0700 directory under $XDG_RUNTIME_DIR,
falling back to a memfd//dev/shm with a clear error); the key blobs and the auth file can stay where
they are.
3. The global flush on a TCTI without a resource manager races the other keys. run calls
tpm2_flushcontext -t, -l and -s after every command whenever tcti != "device:/dev/tpmrm0". That
flushes every transient object and session in the TPM, and the three keys each have their own mutex, so a
sealing agree can run while a signing sign is mid-command and flush its loaded object or HMAC session.
The proof is single-threaded and never sees it; on a real host device:/dev/tpm0 would also flush other
programs' objects. Either one store-wide lock around command plus flush when there is no resource manager,
or refuse any TCTI but a resource manager and swtpm.
Smaller:
- The PR body says the keys "are refused for duplication"; the test asserts the
fixedTPMand
fixedParentbits, which imply it. Say that. findandprobemap every response code toRefused, including a set owner auth and the transient
retry/testing/memory codes, and the start path treatsRefusedas a key to replace. Already #3326 (T129);
a note, not a new ask.sweep_work_dirskeeps a.work-<pid>or.tmp-<pid>whose pid now belongs to another process;
harmless, worth a comment.with_contextreloads and retries on every TPM error,TPM_RC_BAD_AUTHincluded, so a bad auth reaches
the TPM twice; harmless withnoDA, but the retry could skip the auth codes.- tpm2-tools is now a runtime dependency and nothing records it for packaging.
- The PR body still says the swtpm run is "not yet observed"; the CI job on this head ran it (1 test,
2.8 s), so C1 has its evidence.
Checked and fine: the template bits (fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth,
noDA, not restricted) and check_public re-checking them on every load; the 0x000009a2 assertion
(file auth opens an HMAC session as session 1, so noDA gives TPM_RC_BAD_AUTH); the auth never in argv or
logs, files 0600 in a 0700 directory by atomic rename; -f plain DER for der_signature; no silent
fallback (a missing tool or device is KeyError::Store); tests on tempfile, the integration test #[ignore]
behind BEP_TPM_TCTI, nothing under $HOME.
tpm2-tools reads a raw -p file:- value as a C string, so an auth with a zero byte reached the TPM short or empty. The tools now get the hex: form. The ECDH shared secret goes to a 0700 directory under $XDG_RUNTIME_DIR, or /dev/shm, never to the key directory on disk. Without a resource manager, one process-wide lock now covers each command and its global flush, so a flush cannot remove another key's object. An authorization failure is not retried after a reload. The integration test's wrong auth now differs from the real one in every byte.
…roxy-s-keys-in-the-tpm
|
Round 9 of 10 on a review requesting changes, pushed as
Verify Review threads the coder judged:
Against swtpm, the proxy's three keys are generated in the TPM. They sign and agree there, and carry fixedTPM and fixedParent in the public area the TPM reports, so the TPM never duplicates them. They load again with only their key and authorization files. In this round, every authorization value reaches the TPM whole as hex, and the ECDH shared secret no longer touches the disk. Notes from the agent: Review item 1: create, sign and ECDH now write |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The compare conforms to Gatehouse §6.10 line 837. The authorization value now reaches the TPM whole in the hex: form. The ECDH shared secret stays in a private directory in memory, and the store refuses when it has no such directory. The TPM-lane proof is not run, so it is open. C1 asks you to run it on this head and record the result. That leg also confirms the new hex: and -o tool assumptions.
Ruled at 6ed77ac against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
…roxy-s-keys-in-the-tpm
secret_root now checks the file system type with statfs. A runtime directory on the disk falls back to /dev/shm, and the store refuses when neither is in memory.
|
Round 10 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
Against swtpm, the proxy's three keys are generated in the TPM, sign and agree there, carry fixedTPM and fixedParent in the public area the TPM reports, and load again with only their key and authorization files. This box has no TPM and no tpm2-tools, so the swtpm proof did not run here. The unit tests show the key template and that the ECDH secret goes only to a tmpfs or ramfs directory. Notes from the agent: Revise round 10. Fixed the secret_root finding: secret_root_in now takes an in_memory predicate, and secret_root passes a statfs check for tmpfs or ramfs. A runtime directory on the disk falls back to /dev/shm. When neither is in memory, agree returns a store error. RAMFS_MAGIC is a local constant because libc does not export it. Deferred (lane: tpm): cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorization. This box has no swtpm and no tpm2-tools, so I did not run it. |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
BEP-088 still conforms to Gatehouse §6.10 line 837. The new commit keeps the ECDH shared secret only on tmpfs or ramfs. It refuses when neither directory is in memory, and that fails closed. One condition stays open. The deferred swtpm proof must pass in ci-linux-native on this head (C1).
Ruled at 23d5b55 against gominimal/arch@15b603e6afb8 by claude-opus-5-5.
There was a problem hiding this comment.
Babysitter review of 23d5b558 against T128's plan block (#3324, proof as amended to match arch ruling 1241) and its test lines.
Conforms
- Layers:
crates/bep/src/tpm.rs(new),crates/bep/src/lib.rs,crates/bep/tests/key_store_tpm_integration.rs(new). No file outside the layers. No crate dependency, per T127's record choosing thetpm2-toolscommands. - Template and custody:
fixedTPM,fixedParent,sensitiveDataOrigin,userWithAuth,noDA. The proof reads them from the public area the TPM reports, which is the amended proof's evidence that the TPM never duplicates the keys. - Authorization: CSPRNG value, passed to
tpm2-toolson stdin in thehex:form through-p file:-(lines 144-153), never in argv. Auth files are 0600 in a 0700 directory under~/.minimal/bep/tpm/, and stale.work-*and.tmp-<pid>files are swept when the store opens. - ECDH secrets are written only under a directory that
statfsreports as tmpfs or ramfs (secret_root), and are removed on every return path. - Observability: one
infoline per key loaded or generated withrole,fingerprintandstore = "tpm". - Test lines:
tpm_key_template_is_fixed_exempt_from_lockout_and_needs_authorizationexited 0. The deferredtpmline ran against swtpm at this head:a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorizationPASS, 1 run, 0 skipped (run 43470339191).
Deferred
- PRRT_kwDOPdfcxM63MwDD (LOW): the crash window between the two writes in
generate_files. Recorded in gominimal/inbox#1256, because T128 is at its revise cap.
No blocking findings.
|
@bryan-minimal, the three changes from your review 5894914451 (at
Smaller notes:
CI is green, arch passes (ruling 1257, C1 met by that run), and every thread is resolved. |
Dismissed on the owner's decision. All three required changes are in at 23d5b55: hex auth on stdin with a pin test (round 9, 0e74083), the ECDH secret only on tmpfs/ramfs (round 10), and a store-wide NO_RESOURCE_MANAGER lock around each command and flush. Mapping: #3343 (comment). mitodrummer approved this head.
T128 — Hold the proxy's keys in the TPM
slice: S18
kind: task
covers: BEP-088
size: L
est: 420 code, 400 tests
executor: agent
difficulty: unknown ground
model: strongest
diagnostics: a TPM key the store cannot create or use returns a key-store error naming the role and the TPM's response code, which the start refusals of T130 print to the person who started
bepobservability:
beplogs one line for each key it generates or loads from the TPM, with the role, the key's fingerprint andstore=tpm, through the existingtracingsubscriberlayers:
- store:
- crates/bep/src/tpm.rs (new): a key store that generates each proxy key under the TPM's storage key as a P-256 key with
fixedTPM,fixedParentandnoDA, with an authorization value of at least 128 bits from the OS CSPRNG that the proxy writes to a file only its user can read, keeps the key file and the authorization file in~/.minimal/bep/tpm/, loads both at start, and implementsHeldKey(agreethrough the TPM's ECDH) andCaKey(signthrough the TPM's ECDSA), through the interface T127's record names- crates/bep/src/lib.rs: declares the
tpmmodule for Linux targets- crates/bep/Cargo.toml: the TPM dependency T127's record names, under the Linux target
- Cargo.lock: the TPM dependency
test: cargo nextest run -p bep tpm_key_template_is_fixed_exempt_from_lockout_and_needs_authorization
- proof:
- crates/bep/tests/key_store_tpm_integration.rs (new): runs against the TPM that
BEP_TPM_TCTInames, and returns early without it, as the_root_integrationproofs dotest (deferred: tpm): cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorization
produces:
- crates/bep/src/tpm.rs
consumes:
- docs/spikes/2026-11-13-bep-tpm-interface.md
proof: Against
swtpm, the proxy's three keys are generated in the TPM, sign and agree there, are refused for duplication, and load again with only their key and authorization files.depends on:
- blocked by #3323
Proof
The bep crate has a Linux key store, bep::tpm::TpmStore. It generates each of the three proxy keys in the TPM as a P-256 key with fixedTPM, fixedParent, sensitiveDataOrigin, userWithAuth and noDA. Each key has its own 256-bit authorization value in a 0600 file. The sealing key agrees (tpm2_ecdhzgen) and the CA keys sign (tpm2_sign) in the TPM. A new store loads each key again from only its .key and .auth files in ~/.minimal/bep/tpm/. The integration test shows this against swtpm when BEP_TPM_TCTI is set. Nobody ran it against swtpm on this box, so the TPM half of the proof is not yet observed.
Notes from the agent: Deferred (lane: tpm): cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorization. This box has no TPM and no tpm2-tools, so I did not run it. The store was never run against a real TPM. The tpm2-tools argument shapes come from the spike record and the tools' documentation, and the tpm lane must confirm them: '-G ecc256:null:null' for tpm2_create, '-p file:-' (auth on stdin), 'tpm2_sign -d -f plain', and the TPM2B_ECC_POINT format for tpm2_ecdhzgen -u/-o. The parsers accept DER or raw r||s signatures, and TPM2B or bare-coordinate Z points. Cargo.toml and Cargo.lock are not changed. The T127 record (docs/spikes/2026-11-13-bep-tpm-interface.md) chose tpm2-tools as child processes, which is a runtime package and not a crate. Design choices for the next tasks: (1) The sealing key has only 'decrypt', and the CA keys have only 'sign'. probe() uses the key's own operation, as the keychain store does. (2) A failure with a TPM response code (ErrorCode 0x...) is KeyError::Refused, with the code in the detail. A tool or TCTI failure is KeyError::Store. A missing tpm2-tools names the tpm2-tools package. T129 owns the full sorting from spike finding 6. (3) The key file is the TPM2B_PUBLIC followed by the TPM2B_PRIVATE that tpm2_create wrote. find() and generate() check the TPM-reported attributes …[truncated]
Tests
cargo nextest run -p bep tpm_key_template_is_fixed_exempt_from_lockout_and_needs_authorizationVerify
min task run agent-verifypassed ([tasks.verify]).Deferred
The plan marked these test lines deferred: the executor lacks the lane, so nothing here ran them and they still owe evidence.
cargo nextest run -p bep --run-ignored ignored-only a_tpm_key_is_fixed_exempt_from_lockout_and_needs_its_authorizationCloses 8000 #3324