This describes how ROM has chosen to implement the initial parts of the OpenTitan Secure Boot specification.
This should be read in conjunction with the [Secure Boot specification][csm-secure-boot]. References to that document are included.
The ROM is the first boot stage in the Reference Secure Boot implementation, and starts executing at device reset. The ROM is programmed into the chip's ROM during manufacturing, and cannot be changed. The ROM needs to prepare the OpenTitan chip for executing a ROM_EXT, including ensuring the loaded ROM_EXT is allowed to be executed on this chip.
Power on (entirely in hardware)
Open Q: Whether SW has to configure PMP initial region.
Execution Begins with ROM stage:
CRT Startup Code (Written in Assembly)
Disable Interrupts and set well-defined exception handler. This should keep initial execution deterministic.
Clean Device State Part 1. This includes enabling SRAM Scrambling.
Setup structures for C execution (CRT: .data
, .bss
sections, stack).
Jump into C code
Main ROM Secure Boot Software (Written in C)
Execution Enters ROM_EXT stage.
Not covered by this document. Refer to [Secure Boot][csm-secure-boot] document instead.
We've tried to divide the ROM into self-contained modules that can be tested separately, rather than having to test the whole boot system at once.
The module descriptions below also include descriptions of: the dependencies that are required for that module to be implemented fully; the functionality expected at various stages of the ROM's development; and, optionally, pseudo-code for any subroutines that make up their implementation.
This manages reading the boot policy, updating the boot policy if required, and making decisions based on that policy. Most Boot Policy choices also depend on the Boot Reason, so reading and acting on that is part of this module's responsibility too.
Dependencies:
This manages reading and parsing ROM_EXT manifests.
The manifest format is defined in [ROM_EXT Manifest Format][rom-ext-manifest]
Dependencies:
This manages boot-strapping, chip recovery, and manufacturer loading of ROM_EXT images.
Dependencies:
This is where, depending on lifecycle state, new flash images may be loaded onto the device (usually during manufacturing).
This manages public key selection (for ROM_EXT validation), and calculating the digest and signature of the ROM_EXT image itself.
Dependencies:
This deals with how to initialize and clear any chip-specific hardware.
Dependencies:
This is responsible for managing the read (R), write (W) and execute (X) permissions for memory regions.
Dependencies:
This deals with taking the system state measurements which are used to derive the CreatorRootKey
. Some of these measurements may cause boot to be halted.
Dependencies:
Part of this process is done before we can execute any C code. In particular, we have to clear all registers and all of the main RAM before we setup the CRT (which allows us to execute any C code). This has to be done in assembly, as we cannot execute C without setting up the CRT.
We want to do as little as possible in the hand-written assembly, because it is so hard to verify and to test. Additionally, we want to use drivers written in C because we have verified them, rather than duplicating their functionality in assembly, if at all possible. So this means we wait until we are executing C to do the final parts of chip reset, especially parts that may depend on reading or writing any device state.
Unfortunately, it looks like we will have to enable SRAM scrambling (which requires entropy and the AST) from assembly.
This sets up execution so we can run C functions. We cannot execute any C code until we have setup the CRT.
Dependencies: None
Setting up the CRT involves: loading the .data
and .bss
sections, and setting up the stack and gp
(gp
may be used for referencing some data).
There is some data that is accessed by more than just the ROM:
In order to keep the ROM simple, a particular ROM version will only support one version each of the following structures. This means they must be carefully designed to be extensible if the other systems accessing them may require additional data in these formats.
This is the storage for the IDs of keys that are used to sign a ROM_EXT. The ROM_EXT image contains the full key, this stores only the key id (which can be computed from the full key), and uses OTPs to decide whether a key is allowed to be used to validate a ROM_EXT.
Accessed by:
Needs to contain:
Stored In: OTP and ROM
Extensibility: None. A ROM_EXT can disable the use of a key, but cannot add new valid root key IDs. There will be a fixed set of root key IDs as part of a given ROM version.
This is the in-flash structure that defines which ROM_EXT should be booted next, whether it should fall back to the other ROM_EXT if it fails to boot, and/or whether it should be marked as the primary ROM_EXT if it succeeds to validate.
This structure merely controls which ROM_EXT is validated and executed -- it does not contain any executable code. This means it does not need to be protected as securely as the ROM_EXT images, which contain code and are signed and validated before execution.
Accessed by:
Needs to contain:
Identifier (so we know we're reading the right thing)
This also acts like a version number, because the ROM code that parses the boot policy can never be updated. Conversely, any changes to this structure require new ROM parsing code, which should be denoted with a new identifier.
Which ROM_EXT slot should be chosen first (2.b, 2.c.i).
What to do if ROM_EXT does not validate (2.c.ii, 2.c.iii):
What to do if ROM_EXT validates successfully, just before jumping to ROM_EXT:
Checksum (of everything else).
Stored in: Flash (Info Partition)
Extensibility: None. This info only controls the actions of the ROM. You cannot add functionality to the ROM of a given chip, so there's no way to add other information to this structure.
The in-RAM representation also contains the boot reason (reset manager), because it needs to be checked most times the boot policy is also read.
Accessed by:
The manifest format is defined in [ROM_EXT Manifest Format][rom-ext-manifest].
Stored in: Flash (at one of two fixed, memory-mapped, addresses)
Extensibility:
[csm-secure-boot]: {{< relref “doc/security/specs/secure_boot” >}} [rom-ext-manifest]: {{< relref “sw/device/silicon_creator/rom_ext/docs/manifest” >}}