Update manifest format documentation
Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/silicon_creator/rom_exts/docs/manifest.md b/sw/device/silicon_creator/rom_exts/docs/manifest.md
index 53571d9..e416378 100644
--- a/sw/device/silicon_creator/rom_exts/docs/manifest.md
+++ b/sw/device/silicon_creator/rom_exts/docs/manifest.md
@@ -8,457 +8,87 @@
Status: Draft
</p>
-This describes the signed image format for a ROM_EXT image.
-This format is based on the requirements outlined in the [Reference Mask ROM Secure Boot Description][mask-rom-description].
+This document describes the manifest format for boot stage images stored in flash.
-ROM_EXTs are the second boot stage in the Reference Secure Boot implementation.
-ROM_EXTs are supplied by the Silicon Creator.
-ROM_EXTs are programmed into the chip's flash.
+OpenTitan secure boot, at a minimum, consists of three boot stages: `ROM`,
+`ROM_EXT`, and the first owner boot stage, e.g. `BL0`. `ROM` is stored in the
+read-only Mask ROM while remaining stages are stored in flash. `ROM` and
+`ROM_EXT` require the manifest described in this document to be at the start of
+`ROM_EXT` and first owner boot stage images so that they can verify the
+integrity and authenticity of the next stage and configure peripherals as
+needed before handing over execution. Use of this manifest for stages following
+the first owner boot stage is optional.
+The following table lists the fields of the manifest along with their sizes,
+alignments, and offsets from the start of the manifest in bytes. The last
+column provides the corresponding C data type of each field for illustration
+purposes. All manifest fields are stored little-endian and the total size of
+the manifest is 848 bytes.
-<!--
-The following ascii art diagram is generated with the following command,
-and changes are manually committed to this file.
+| Field | Size (bytes) | Alignment (bytes) | Offset (bytes) | C Data Type |
+| ----------------- | ------------ | ----------------- | -------------- | -------------- |
+| `signature` | 384 | 4 | 0 | `uint32_t[96]` |
+| `modulus` | 384 | 4 | 384 | `uint32_t[96]` |
+| `exponent` | 4 | 4 | 768 | `uint32_t` |
+| `identifier` | 4 | 4 | 772 | `uint32_t` |
+| `length` | 4 | 4 | 776 | `uint32_t` |
+| `version_major` | 4 | 4 | 780 | `uint32_t` |
+| `version_minor` | 4 | 4 | 784 | `uint32_t` |
+| `security_vesion` | 4 | 4 | 788 | `uint32_t` |
+| `timestamp` | 8 | 8 | 792 | `uint64_t` |
+| `binding_value` | 32 | 4 | 800 | `uint32_t[8]` |
+| `max_key_version` | 4 | 4 | 832 | `uint32_t` |
+| `code_start` | 4 | 4 | 836 | `uint32_t` |
+| `code_end` | 4 | 4 | 840 | `uint32_t` |
+| `entry_point` | 4 | 4 | 844 | `uint32_t` |
-```
-$ util/rom-ext-manifest-generator.py \
- --input-dir sw/device/silicon_creator/rom_exts/ \
- --output-dir ${OUT_DIR} \
- --output-files=format
-```
-
-At which point you can find the format in `${OUT_DIR}/manifest.txt`
--->
-
-```
- 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
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| manifest_identifier |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| - reserved - |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| |
-+ +
-| |
-+ image_signature (3072 bits) +
-| |
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-| |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| image_length |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| image_version |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| |
-+ image_timestamp +
-| |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| signature_key_public_exponent |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| - reserved - |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| |
-+ +
-| |
-+ usage_constraints (256 bits) +
-| |
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-| |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| |
-+ +
-| |
-+ peripheral_lockdown_info +
-| |
-+ +
-| |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| |
-+ +
-| |
-+ signature_key_modulus (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 Key Modulus` 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 Modulus 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.
+* `signature`: [`RSASSA-PKCS1-v1_5`][rsassa_pkcs1_v1_5] signature of the
+ image generated using a 3072-bit RSA private key and the SHA-256 hash
+ function. The signed region of an image starts immediately after this
+ field and extends to the end of the image.
- This is used by any ROM_EXT image parsers to identify a ROM_EXT image.
+* `modulus`: Modulus of the signer's 3072-bit RSA public key.
-1. **Image Signature** This is a RSA-3072 signature of the hash of all the
- fields that follow the signature. This is a sequence of 32-bit values. The
- signed area of the image starts immediately after this field, and runs to
- the end of the image (as defined by the image length). All content outside
- that range is unsigned (including the Manifest Identifier, and the Image
- Signature itself).
+* `exponent`: Exponent of the signer's RSA public key. The only values
+ supported by OpenTitan are 3 and 65537.
- 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.
+* `identifier`: Image identifier used to identify boot stage images. The
+ value of this field must be `0x4552544f` (ASCII: "OTRE") for a `ROM_EXT`
+ image and `0x3042544f` (ASCII: "OTB0") for the first owner stage.
- If the image signature is a sequence of all zeroes, the image is unsigned.
- Unsigned images **must not** be booted.
+* `length`: Length of the image (including the manifest) in bytes.
-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.
+* `version_major`: Major version of the image.
- This is used when signing, validating, and loading the image. This happens
- in the Mask ROM, as well as during firmware update.
+* `version_minor`: Minor version of the image.
-1. **Image Version** This is a version number for the ROM_EXT image. It
- is a 32-bit unsigned numeric value.
+* `security_version`: Security version of the image used for anti-rollback
+ protection. Must be a monotonically increasing integer.
- **Open Q** How will we use this?
+* `timestamp`: Unix timestamp that gives the creation time of the image,
+ seconds since 00:00:00 on January 1, 1970 UTC (the Unix Epoch).
-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.
+* `binding_value`: Binding value used by the [key manager][key_manager] to
+ derive secret values. A change in this value changes the secret value of
+ the key manager, and consequently, the versioned keys and identity seeds
+ generated at subsequent boot stages.
- This is not used by the Mask ROM when validating the image, but is part of
- the signed image.
+* `max_key_version`: Maximum allowed version for keys generated by the
+ [key manager][key_manager] at the next boot stage.
- *Alignment* This is 64-bit aligned.
+* `code_start`: Offset of the start of the executable region of the image
+ from the start of the manifest in bytes. Must be 4-byte word aligned.
-1. **Signature Key Public Exponent** This is the RSA public exponent to be used
- during signature verification. This is a 32-bit numeric value.
+* `code_end`: Offset of the end of the executable region of the image
+ (exclusive) from the start of the manifest in bytes. Note that the range
+ from `code_start` to `code_end` must cover all machine instructions, i.e.
+ .vectors, .crt, and .text, in the image. Must be 4-byte word aligned.
- This is used when validating the image. This happens in the Mask ROM, as
- well as during firmware update.
+* `entry_point`: Offset of the first instruction to execute in the image from
+ the start of the manifest in bytes. Must be 4-byte word aligned.
-1. **Usage Constraint** This is a 256-bit unsigned numeric value.
-
- This allows the ROM_EXT author to constrain a ROM_EXT to a single device or
- a group of devices, such that the ROM_EXT will not validate (and therefore
- will not boot) on devices not in that group.
-
- The Mask ROM will use this value to calculate a 1024-byte "device usage
- value" which is used when validating the signature of a ROM_EXT. The exact
- interpretation of the Usage Constraints value is left as an implementation
- detail.
-
-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 Key Modulus** This is a RSA-3072 modulus, used in both the
- signing and signature verification operations. 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 `0x370` (880) 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 144 (`0x90`) 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.
-
-* **Signature Algorithm Identifier** We originally planned to have this field
- in the ROM_EXT manifest, but with the padding scheme, it is redundant, so it
- has been removed.
-
-## Development Versions (Subject to Change)
-
-**ROM_EXT Manifest Identifier**: `0x4552544F` (Reads "OTRE" when Disassembled --
-OpenTitan ROM_EXT)
-
-**Signature Algorithm Identifier**: TBC
-
-**Signature Key Public Exponent**: TBC
-
-**Development 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.
-
-
-# How To Validate a ROM_EXT Image {#how-to-validate}
-
-Below we provide an abstract definition of how to sign and verify a ROM_EXT
-image. This description is provided so that there is a specification of what the
-signing and validation systems are implementing, so that alternate
-implementations may be produced if necessary.
-
-Notation:
-
-* `rom_ext` - ROM_EXT Image, including manifest and contents (Variable Length)
- `signed_area(rom_ext)` denotes just the area between the start of the signed
- contents and the end of the image.
-* `device_usage_value` - Device-Calculated Usage Constraint Value (1024
- bytes). This is the "device usage value" described above, as calculated by
- the Mask ROM.
-* `system_state_value` - Device System State Value (32 bytes). This is a Mask
- ROM calculated value that summarises the current device state.
-* `private_key` - RSA Private Key
-* `public_key` - RSA Public Key
-* `signature` - ROM_EXT RSA Signature,
-* `||` - Denotes concatenation without a delimiter.
-* `:=` - Denotes assignment.
-
-## Algorithms
-
-* We primarily use [`RSASSA-PKCS1-V1_5-SIGN`][RSASSA-PKCS1-V1_5-SIGN] and
- [`RSASSA-PKCS1-V1_5-VERIFY`][RSASSA-PKCS1-V1_5-VERIFY] for signatures and
- verification.
-* RSA Signing and Verification is done with 3072-bit keys.
-* The `Hash` operation may be done with SHA2-256, SHA3-256, SHA3-384, or
- SHA3-512, depending on the Signature Algorithm Identifier provided in the
- manifest. The `Hash` operation is required to provide a security level
- equivalent to that provided by the signature.
-
-## Signing
-
-This is usually done on a host machine, which does not have access to a real OT
-device. Thus there has to be a way for the host signer to predict the value of
-`device_usage_value` and `system_state_value`, as they would be calculated
-on-device.
-
-The `private_key` is never available on-device, in this scheme.
-
-```
-system_state_value := predict_system_state_value()
-device_usage_value := predict_device_usage_value(rom_ext.usage_constraint)
-
-message := system_state_value || device_usage_value || signed_area(rom_ext)
-signature := RSASSA-PKCS1-V1_5-SIGN(private_key, message)
-```
-
-## Validation
-
-Usually, validation is done on-device, where `device_usage_value` and
-`system_state_value` can be calculated.
-
-However, we also want to be able to validate the signature off-device, so still
-need a way to predict the value of `device_usage_value` and
-`system_state_value`. Off-device, we will use the same `predict_` systems as
-used above.
-
-This document does not cover how a device should ensure that `public_key` is
-allowed to validate images for a given device.
-
-```
-system_state_value := calculate_system_state_value()
-device_usage_value := calculate_device_usage_value(rom_ext.usage_constraint)
-signature := rom_ext.signature
-
-message := system_state_value || device_usage_value || signed_area(rom_ext)
-result := RSASSA-PKCS1-V1_5-VERIFY(public_key, message, signature)
-```
-
-
-[mask-rom-description]: {{< relref "sw/device/silicon_creator/mask_rom/docs" >}}
-[RSASSA-PKCS1-V1_5-SIGN]: https://tools.ietf.org/html/rfc3447#section-8.2.1
-[RSASSA-PKCS1-V1_5-VERIFY]: https://tools.ietf.org/html/rfc3447#section-8.2.2
+[rsassa_pkcs1_v1_5]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2
+[key_manager]: https://docs.opentitan.org/hw/ip/keymgr/doc/