API Reference
Register-level API documentation for the zeroRISC root-of-trust IP block. All registers are 32-bit, accessible via the AHB-Lite or AXI4-Lite slave interface at the base address configured by the OEM SoC integration.
attestation_get_cert()
Initiates the full DICE attestation chain generation and retrieves a specified certificate. Hardware function — triggered by register write, not a software call.
// ATTEST_CTRL register — Write command opcode
// Base + 0x000
//
// [7:0] CMD — Command opcode:
// 0x01 = ATTEST_FULL_CHAIN (generate all 3 certs)
// 0x02 = ATTEST_CDI0_ONLY
// 0x03 = ATTEST_CDI1_ONLY
// 0x04 = ATTEST_APP_CERT_ONLY
// 0xFF = ATTEST_RESET (wipe SRAM buffer)
REG32(ATTEST_BASE + 0x000) = 0x01;
lifecycle_transition()
Initiates an OTP-backed lifecycle state transition. Requires an HMAC-SHA256 authentication token computed over the transition command and nonce.
// LC_TRANSITION_CMD register
// Base + 0x100
//
// [3:0] TARGET_STATE — target lifecycle state:
// 0x1 = DEV → PROD
// 0x2 = PROD → LOCKED
// 0x3 = PROD → RMA
// 0x4 = LOCKED → RMA
// 0x5 = RMA → EOL
//
// LC_AUTH_TOKEN register [Base + 0x104..0x113]
// 256-bit HMAC-SHA256 token (8 x 32-bit registers)
//
// Write TARGET_STATE last — triggers transition attempt
REG32(LC_BASE + 0x104) = token_word[0]; // write token
// ... write remaining 7 token words
REG32(LC_BASE + 0x100) = 0x1; // DEV → PROD
otp_read()
Reads a word from OTP. Only allowed partitions are accessible post-provisioning (lifecycle and HW config partitions). Secret partitions return an error if read from the host bus.
// OTP_CTRL_STATUS register — Base + 0x200
// OTP_RDATA register — Base + 0x208
//
// Write partition offset to OTP_ADDR_H (Base + 0x204):
REG32(OTP_BASE + 0x204) = otp_offset; // byte offset
REG32(OTP_BASE + 0x200) = 0x01; // issue read command
// Poll OTP_CTRL_STATUS[0] (DONE) = 1, [1] (ERR) = 0
while (!(REG32(OTP_BASE + 0x200) & 0x1));
uint32_t data = REG32(OTP_BASE + 0x208);
hmac_compute()
Computes HMAC-SHA256 using the hardware accelerator. Key material is loaded from a lifecycle-gated key register — not accessible from the host bus in PROD/LOCKED state.
// HMAC_CMD register — Base + 0x300
// [0] START — write 1 to start HMAC
// [1] PROCESS — write 1 to process queued message block
// [2] STOP — write 1 to finalize and produce digest
// Load message (128-byte FIFO, Base + 0x310..0x38F)
for (int i = 0; i < msg_words; i++)
REG32(HMAC_BASE + 0x310 + i*4) = msg[i];
REG32(HMAC_BASE + 0x300) = 0x1; // START
REG32(HMAC_BASE + 0x300) = 0x2; // PROCESS
REG32(HMAC_BASE + 0x300) = 0x4; // STOP
// Poll HMAC_STATUS (Base + 0x304) DONE bit
while (!(REG32(HMAC_BASE + 0x304) & 0x1));
// Read 256-bit digest (8 registers at Base + 0x390)
for (int i = 0; i < 8; i++)
digest[i] = REG32(HMAC_BASE + 0x390 + i*4);