blob: e758ae20b0a9a0054c09da6e8ed47b26cf9171b3 [file] [log] [blame] [view]
# ROM_EXT Manifest Format
Based on the requirements outlined in [boot.md](./boot)
```
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ROM_EXT Manifest Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Image Signature (3072 bits) +
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Image Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Image Version |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Image Timestamp +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Signature Algorithm Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Signature Exponent |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Usage Constraints (TBC) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Peripheral Lockdown Info (TBC) +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Signature Public Key (3072 bits) +
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension0 Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension0 Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension1 Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension1 Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension2 Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension2 Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension3 Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extension3 Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Code Image +
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```
Notes:
* All Offsets in the manifest are specified in bytes from the beginning of the
`ROM_EXT Manifest Identifier` field.
* All numeric and enumeration field values are stored little-endian. Fields
below are noted as one of:
* a N-bit (signed or unsigned) numeric value;
* a N-bit enumeration value;
* a sequence of N-bit (signed or unsigned) numeric values; or
* a sequence of bytes.
All numeric and enumeration values are stored little-endian.
A byte only ever means an 8-bit data value, whose interpretation is
undefined.
* All fields below are 32-bit (4-byte) aligned unless otherwise specified.
**Open Q**: The ordering below is still subject to alignment requirements
for different fields, and may change in future.
* The `Image Signature`, `ROM_EXT Signature Public Key` and `Image` are not
shown to scale. This is denoted using `~~~ break ~~~` lines, which specify a
truncation of field size displayed in the diagram, not that a new field has
started.
* The Signature and Public Key are each 3072 bits long (they are
notionally `int32_t[96]`s).
* The Code Image itself is variable length, where the length of the entire
image (including the manifest) is given in the `Length` field.
* Reserved areas are not documented below. Conforming implementations will not
parse these fields, but will produce images where those bits are all zero.
Reserved areas remain read-only, as they are signed as part of the image.
Updating these fields will fail validation.
Reserved fields have fixed size and unspecified alignment.
## Field Descriptions
1. **ROM_EXT Manifest Identifier** This is a 32-bit enumeration value which is
used by the Mask ROM to identify that an image with the above format is
resident in flash. A particular Mask ROM version can only parse one ROM_EXT
image format, there is no expected support for differing behaviour based on
this field, beyond erroring when ROM_EXT images are missing from flash
storage.
This is used by any ROM_EXT image parsers to identify a ROM_EXT image.
1. **Image Signature** This is a RSA 3k signature of all the fields that follow
the signature. This a sequence of 32-bit values. There is no data in the
image which is not signed, except the signature itself and the ROM_EXT
manifest identifier.
This is used by the Mask ROM during secure boot to validate that a ROM_EXT
image has been produced by a Silicon Creator for this chip. This is also
validated at other times, including during firmware update.
If the image signature is a sequence of all zeroes, the image is unsigned.
Unsigned images **must not** be booted.
1. **Image Length** This denotes the Offset of the end of the image, in bytes.
As with other offsets, this is calculated from the start of the `ROM_EXT
Manifest Identifier` field. This is a 32-bit unsigned numeric value.
This is used when signing, validating, and loading the image. This happens
in the Mask ROM, as well as during firmware update.
1. **Image Version** This is a version number for the ROM_EXT image. It
is a 32-bit unsigned numeric value.
**Open Q** How will we use this?
1. **Image Timestamp** This is a Unix Timestamp describing when the ROM_EXT
image was prepared, in seconds since 00:00:00 UTC on 1 January 1970 (the
Unix Epoch). This is a 64-bit signed numeric value.
This is not used by the Mask ROM when validating the image.
*Alignment* This is 64-bit aligned.
1. **Signature Algorithm Identifier** This identifies which algorithm has been
used to sign the ROM_EXT Image. This is a 32-bit enumeration value.
This is used when signing and validating the image. This happens in the
Mask ROM, as well as during firmware update.
`0x0` denotes an unsigned image. Unsigned images **must not** be booted.
The initial version of the Mask ROM will support the following message
digest algorithms:
* SHA2-265
* SHA2-384
* SHA2-512
The specific signature scheme is as yet undefined, but will be based on
RSA-3k, and one of the message digest algorithms above.
1. **Signature Exponent** This is the RSA exponent to be used during the RSA
3K Signature Scheme. This is a 32-bit numeric value.
This is used when signing and validating the image. This happens in the
Mask ROM, as well as during firmware update.
1. **Usage Constraints** This is a 32-bit enumeration value which denotes what
kinds of devices the ROM_EXT image may be used on.
This is used by the Mask ROM to validate the image is running on the right
kind of hardware.
**Open Q** What possible values should this have?
1. **Peripheral Lockdown Info** This is a 128-bit value which describes how
some peripherals should be configured, before the write-enable bits for
their configuration registers are cleared.
This is used by the Mask ROM to configure specific peripherals (including,
for example, pinmux and padctrl), in such a way that their configuration
cannot be updated by the ROM_EXT or any other later firmware.
**Open Q** We don't have inifnite space for this, so what configurations
might we want to make and then lock?
**Open Q** Required Alignment. Assuming 32-bit for the moment. We're
currently tight for space, so this may turn into an Offset to later in the
image.
1. **Signature Public Key** This is a RSA 3k public key, as used by the image
signature. This is a sequence of 32-bit values.
This is used when signing and validating the image. This happens in the
Mask ROM, as well as during firmware update.
1. **Extensions** This is a sequence of 4 `(Offset, Checksum)` pairs. These
allow for the ROM_EXT manifest format to be extended without redesigning the
manifest entirely.
Extensions are ignored by the Mask ROM. They may be parsed by the ROM_EXT
itself and any later firmware stages.
The Offset field denotes the byte offset in the image (including the
manifest) where the extension can be found. The length of the respective
data is defined by the extension itself (it can have either a static or
variable length), but the manifest includes a Checksum field which must be
used to store a checksum of the extension's data, using CRC32.
Each Offset field is a 32-bit unsigned numeric value. Each Checksum field is
a 32-bit numeric value.
Extension pairs may be *allocated* a specific use. These fields should be
treated as Reserved until they are allocated. Once an extension pair has an
allocated use, it will not be used for any other use, unless the Manifest
Image Identifier also changes (In this way, the Identifier also works as a
versioning token for the manifest format). When an extension pair is
allocated, the extension may define an alignment requirement for the its
data. The extension's data must be at least byte-aligned.
**Open Q** We could allocate more of these pairs, as we have quite a few
bytes between the end of the last pair, and the first 256-byte-aligned
address in the code image (see the Code Image field description.). Do we
want to?
1. **Code Image** This is a sequence of bytes that make up the code and data of
the ROM_EXT image. This data will include any data required for Extensions.
Execution begins at the address 128 (`0x80`) bytes beyond the first
256-byte (`0x100`-byte) aligned offset at the start of the ROM_EXT code
image (measuring the offset from the start of the ROM_EXT image). This
leaves the possibility of the Mask ROM initializing `mtvec` with the first
256-byte aligned offset in the ROM_EXT code image, before jumping into
ROM_EXT code. This matches how Ibex boots.
The total manifest length is currently `0x358` (856) bytes, so the first
valid mtvec address is at offset `0x400` (1024) bytes from the beginning of
the ROM_EXT image, and **the entry address is therefore `0x480` (1152) bytes
from the beginning of the ROM_EXT image**.
This does leave 168 (`0xa8`) bytes between the end of the manifest and the
first valid mtvec. It is up to the image as to how this is used--it could be
used for extension data or for routines. We could also reserve this space so
the manifest can be extended later, but this is the intention of the
Extension entries.
**Open Q** Do we want to relax the requirement to match how ibex boots? We
still want a static entry address so we don't have to validate that it is in
bounds.
**Open Q** Do we want to set `mtvec` before jumping to the ROM_EXT? This
could cause double fault issues if ROM_EXT is not unlocked by the comparator
before the jump happens.
### Data Not in the Header
* `.data` + `.bss` section sizes, for establishing PMP regions. The PMP
regions should be established by the ROM_EXT image as it sets up its own
execution. This is not the responsibility of Mask ROM, as of yet.
* `.idata` section offset, for copying initialization values into `.data`
section in RAM, as again, this is the responsibility of the ROM_EXT image,
not Mask ROM.
* **Software Binding Tag** (aka **ROM_EXT Security Descriptor**)
A 256-bit input is needed to help seed the CreatorRootKey, as part of
preparing the key manager for later use.
There was originally a proposal to have the party that prepared the image
set the software binding tag explicitly, using a field in the manifest.
However, we have chosen to always use a 256-bit digest of the ROM_EXT image
itself.
This means future ROM_EXTs can not read data encrypted with a previous
ROM_EXT's key. A different ROM_EXT image will result in a different
CreatorRootKey.
This would have been used by the Mask ROM as an input for the key manager.
## Development Versions (Subject to Change)
**ROM_EXT Manifest Identifier**: `0x4552544F` (Reads "OTRE" when Disassembled --
OpenTitan ROM_EXT)
**Signature Algorithm Identifier**: TBC
**Signature Exponent**: TBC
**Signature Key Pair**: TBC. We will create a dummy key pair for development,
but this will not be used in production software.
**Extension Allocation**:
| Identifier | Pair | Use | Length | Alignment |
|--------------|------|---------------|--------|-----------|
| `0x4552544F` | 0 | *Unallocated* | | |
| `0x4552544F` | 1 | *Unallocated* | | |
| `0x4552544F` | 2 | *Unallocated* | | |
| `0x4552544F` | 3 | *Unallocated* | | |
## Software Deliverables
* A C Library for parsing/extracting this image format on-device.
This should take a Base Address, and parse using offsets from that, rather
than a fixed address at the start of flash. This is so we can parse both
ROM_EXT Slot A and Slot B using the same library.
* A linker script (and assembly files) that can create a ROM_EXT ELF file
containing all the code and data.
The aim is to use absolute addresses for the stack and any in-RAM data, so
that we end up mostly position-independent.
**Open Q**: The ROM_EXT may need to be told which address the current image
starts at when it boots.
* A developer utility for taking a ROM_EXT ELF file and turning it into
a correctly signed image for loading into either slot using the existing
spiflash utility. This utility should also be able to validate a signed
ROM_EXT image, to ensure that what we signed can be validated both on- and
off-device.
This utility will also have to take a Software Binding Tag and other
metadata as input, for injecting into the image. It should almost certainly
also create a receipt of the information it just signed, in a
machine-parseable format.
* (Potentially) a developer utility for assembling binary images that contain
the entire contents of flash (ROM_EXT + BL0 + Owner Firmware + Persisted
Data, for each of Slot A and B), for testing.
**Open Q** There are lots of open questions about position-independent code
issues and requirements, as we want to load the same image into Slot A or Slot
B, without having to re-link or re-compile the image (note we only have one
entry address). At least initially, we will only create images that can work
from Slot A, and later we will add support ensuring these images are linked in
a way that they can run from Slot B without modification.