Mode: Subsystem
Concern: Caliptra does not detect errors associated with multiple repeated attempts to program Field Entropy.
Hardware-level lock (real protection exists): program()'s last step always triggers a digest calculation, which locks the partition in the fuse_ctrl/OTP controller. Per the OTP controller's own register docs:
ERR_CODE = 0x5 ACCESS_ERROR: "This error indicates that a locked memory region has been accessed. The corresponding controller automatically recovers from this error when issuing a new command." otp_ctrl_registers
So once a partition is locked, the OTP macro itself rejects further writes to it — the underlying secret bits are not overwritten or corrupted by a repeat attempt.
But Caliptra firmware doesn't check for this. Reading uds_fe_programming.rs (program()) (the code behind the FE_PROG mailbox command) closely:
- It never reads
ERR_CODE or any partition-digest/lock status before or after issuing the write+digest DAI commands.
- Its only polling loop (
is_dai_idle()) checks the DAI_IDLE readiness bit, not error bits — and ACCESS_ERROR "auto-recovers" the DAI back to idle, so a rejected write looks identical to a successful one from firmware's point of view.
- There is no dedicated error code for this: the only FE-specific errors defined are
RUNTIME_FE_PROG_ILLEGAL_LIFECYCLE_STATE and RUNTIME_FE_PROG_INVALID_PARTITION (error/src/lib.rs:1652,1657) — nothing like ..._ALREADY_PROGRAMMED.
- Contrast this with the sibling
zeroize() function in the same file, which explicitly reads back and verifies each step (verify_cleared) — that defensive pattern was not applied to program().
- Test coverage (
test_fe_programming.rs) only covers the happy path and an out-of-range partition index — no test exercises calling FE_PROG twice on the same already-locked partition.
Practical consequence: If an authenticated caller invokes FE_PROG twice for the same partition, firmware will attempt the write+digest sequence again each time. The OTP hardware will reject the second attempt (data stays safe), but since firmware doesn't check for that rejection, it will likely still return a mailbox success response — a false-success/observability gap rather than a security hole.
One more nuance: there are 4 independent FE partitions (0–3), and the caller explicitly picks the partition index in the request — Caliptra does not auto-select "the first available slot" the way the abstract architecture doc describes (doc/Caliptra.md:1297). So requesting different partitions across separate legitimate events (e.g., successive ownership transfers) is normal intended reuse, not "multiple programming" of the same fuse — tracking which slot is next is left to the SoC/MCU caller, which the spec explicitly requires to "prohibit... re-burning of already burned Field Entropy entries" (CaliptraIntegrationSpecification.md:930) but which isn't currently enforced in Caliptra's own FE_PROG handler.
Mode: Subsystem
Concern: Caliptra does not detect errors associated with multiple repeated attempts to program Field Entropy.
Hardware-level lock (real protection exists):
program()'s last step always triggers a digest calculation, which locks the partition in thefuse_ctrl/OTP controller. Per the OTP controller's own register docs:So once a partition is locked, the OTP macro itself rejects further writes to it — the underlying secret bits are not overwritten or corrupted by a repeat attempt.
But Caliptra firmware doesn't check for this. Reading uds_fe_programming.rs (
program()) (the code behind theFE_PROGmailbox command) closely:ERR_CODEor any partition-digest/lock status before or after issuing the write+digest DAI commands.is_dai_idle()) checks theDAI_IDLEreadiness bit, not error bits — andACCESS_ERROR"auto-recovers" the DAI back to idle, so a rejected write looks identical to a successful one from firmware's point of view.RUNTIME_FE_PROG_ILLEGAL_LIFECYCLE_STATEandRUNTIME_FE_PROG_INVALID_PARTITION(error/src/lib.rs:1652,1657) — nothing like..._ALREADY_PROGRAMMED.zeroize()function in the same file, which explicitly reads back and verifies each step (verify_cleared) — that defensive pattern was not applied toprogram().test_fe_programming.rs) only covers the happy path and an out-of-range partition index — no test exercises callingFE_PROGtwice on the same already-locked partition.Practical consequence: If an authenticated caller invokes
FE_PROGtwice for the same partition, firmware will attempt the write+digest sequence again each time. The OTP hardware will reject the second attempt (data stays safe), but since firmware doesn't check for that rejection, it will likely still return a mailbox success response — a false-success/observability gap rather than a security hole.One more nuance: there are 4 independent FE partitions (0–3), and the caller explicitly picks the
partitionindex in the request — Caliptra does not auto-select "the first available slot" the way the abstract architecture doc describes (doc/Caliptra.md:1297). So requesting different partitions across separate legitimate events (e.g., successive ownership transfers) is normal intended reuse, not "multiple programming" of the same fuse — tracking which slot is next is left to the SoC/MCU caller, which the spec explicitly requires to "prohibit... re-burning of already burned Field Entropy entries" (CaliptraIntegrationSpecification.md:930) but which isn't currently enforced in Caliptra's ownFE_PROGhandler.