Changes to ROM Specification

Comparing version 2.0 to 1.2
+858 additions -309 deletions
@@ -1,9 +1,11 @@
11 <div style="font-size: 0.85em; color: #656d76; margin-bottom: 1em; padding: 0.5em; background: #f6f8fa; border-radius: 4px;">
2-📄 Source: <a href="https://github.com/chipsalliance/caliptra-sw/blob/e6e5db26702ee88d530d2789ac87749472a6641c/rom/dev/README.md" target="_blank">chipsalliance/caliptra-sw/rom/dev/README.md</a> @ <code>e6e5db2</code>
2+📄 Source: <a href="https://github.com/chipsalliance/caliptra-sw/blob/e56467181b5313e53cf6cdc92f705a4127480fc2/rom/dev/README.md" target="_blank">chipsalliance/caliptra-sw/rom/dev/README.md</a> @ <code>e564671</code>
33 </div>
44
55
6-# Caliptra - ROM Specification v1.0
6+# Caliptra - ROM Specification v2.0.1
7+
8+*Spec Version: 1.0*
79
810 ## Scope
911
@@ -11,7 +13,7 @@
1113 for Caliptra Read Only Memory Code (ROM). As an architecture specification for ROM, this document describes the
1214 following topics:
1315
14-1. Provide high level architecture and requirements
16+1. Provide high level architecture
1517 2. Describe ROM DICE Layering Architecture
1618 3. Describe ROM functionality
1719 4. Define ROM boot flows
@@ -22,6 +24,9 @@
2224 - Unknown/Spurious Reset Flow
2325
2426 5. Cryptographic Derivations
27+
28+## Spec Opens
29+- Describe in-memory logs
2530
2631 ## Glossary
2732
@@ -31,11 +36,13 @@
3136 | CSR | Certificate Signing Request |
3237 | DCCM | Data Closely Coupled Memory |
3338 | DICE | Device Identifier Composition Engine |
39+| ECC | Elliptic Curve Cryptography |
3440 | FHT | Firmware Handoff Table |
3541 | FMC | First Mutable Code |
3642 | FW | Firmware |
3743 | ICCM | Instruction Closely Coupled Memory |
3844 | IDEVID | Initial Device ID DICE Layer |
45+| MLDSA | Module-Lattice-Based Digital Signature Algorithm |
3946 | RoT | Root of Trust |
4047 | RT | Runtime |
4148 | RTM | Root of Trust for Measurement |
@@ -49,33 +56,61 @@
4956
5057 Following are the main FUSE & Architectural Registers used by the Caliptra ROM for DICE Derivations:
5158
59+### Fuse Registers
5260 | Register | Width (bits) | Description |
5361 | :------------------------------ | :------------ | :----------------------------------------------------- |
54-| CPTRA_SECURITY_STATE | 32 | Security State of the device. Contains two fields: <br> **LIFECYCLE_STATE**: Unprovisioned, Manufacturing or Production <br> **DEBUG_ENABLED**: Boolean indicating if debug is enabled or not |
55-| FUSE_UDS_SEED | 384 | Obfuscated UDS |
62+| FUSE_UDS_SEED | 512 | Obfuscated UDS |
5663 | FUSE_FIELD_ENTROPY | 256 | Obfuscated Field Entropy |
57-| FUSE_KEY_MANIFEST_PK_HASH | 384 | Hash of the four ECC and thirty-two LMS Manufacturer Public Keys |
58-| FUSE_KEY_MANIFEST_PK_HASH_MASK | 32 | Manufacturer ECC Public Key Revocation Mask |
64+| FUSE_VENDOR_PK_HASH | 384 | Hash of the ECC and LMS or MLDSA Manufacturer Public Key Descriptors |
65+| FUSE_ECC_REVOCATION | 4 | Manufacturer ECC Public Key Revocation Mask |
5966 | FUSE_LMS_REVOCATION | 32 | Manufacturer LMS Public Key Revocation Mask |
60-| FUSE_LMS_VERIFY | 32 | LMS Verification flag: <br> **0** - Verify Caliptra firmware images with ECDSA-only <br> **1** - Verify Caliptra firmware images with both ECDSA and LMS |
61-| FUSE_OWNER_PK_HASH | 384 | Owner ECC and LMS Public Key Hash |
62-| FUSE_FMC_KEY_MANIFEST_SVN | 32 | FMC Security Version Number |
63-| FUSE_RUNTIME_SVN | 128 | Runtime Security Version Number |
64-| FUSE_ANTI_ROLLBACK_DISABLE | 1 | Disable SVN checking for FMC & Runtime when bit is set |
65-| FUSE_IDEVID_CERT_ATTR | 768 | FUSE containing information for generating IDEVID CSR <br> **Word 0**: X509 Key Id Algorithm (2 bits) 1: SHA1, 2: SHA256, 2: SHA384, 3: Fuse <br> **Word 1,2,3,4,5**: Subject Key Id <br> **Word 6**: UEID type as defined in [IETF RATS specification](https://www.ietf.org/archive/id/draft-ietf-rats-eat-21.html#section-4.2.1.1) <br> **Words 7,8,9,10**: Manufacturer Serial Number |
66-| CPTRA_DBG_MANUF_SERVICE_REG | 16 | Manufacturing Services: <br> **Bit 0**: IDEVID CSR upload <br> **Bit 1**: Random Number Generator Unavailable <br> **Bit 15:8**: FIPS test hook code <br> **Bit 30**: Fake ROM enable in production lifecycle mode <br> **Bit 31**: Fake ROM image verify enable |
67-
67+| FUSE_MLDSA_REVOCATION | 4 | Manufacturer MLDSA Public Key Revocation Mask |
68+| FUSE_FIRMWARE_SVN | 128 | Firmware Security Version Number |
69+| FUSE_ANTI_ROLLBACK_DISABLE | 1 | Disable SVN checking for firmware when bit is set |
70+| FUSE_IDEVID_CERT_ATTR | 768 | FUSE containing information for generating IDEVID CSR <br> **Word 0:bits[0-2]**: ECDSA X509 Key Id Algorithm (3 bits) 0: SHA1, 1: SHA256, 2: SHA384, 3: SHA512, 4: Fuse <br> **Word 0:bits[3-5]**: MLDSA X509 Key Id Algorithm (3 bits) 0: SHA1, 1: SHA256, 2: SHA384, 3: SHA512, 4: Fuse <br> **Word 1,2,3,4,5**: ECDSA Subject Key Id <br> **Word 6,7,8,9,10**: MLDSA Subject Key Id <br> **Words 11**: UEID type as defined in [IETF RATS specification](https://www.ietf.org/archive/id/draft-ietf-rats-eat-21.html#section-4.2.1.1) <br> **Words 12,13,14,15**: Manufacturer Serial Number |
71+| FUSE_MANUF_DEBUG_UNLOCK_TOKEN | 512 | SHA-512 digest of secret value for manufacturing debug unlock authorization |
72+| FUSE_PQC_KEY_TYPE | 2 | One-hot encoded selection of PQC key type for firmware validation. <br> **Bit 0**: MLDSA <br> **Bit 1**: LMS |
73+
74+
75+### Architectural Registers
76+| Register | Width (bits) | Description |
77+| :------------------------------ | :------------ | :----------------------------------------------------- |
78+| CPTRA_OWNER_PK_HASH | 384 | Owner ECC and LMS or MLDSA Public Key Hash |
79+
80+
81+### Entropy Source Configuration Registers
82+
83+The ROM configures the entropy source (CSRNG) during initialization using the following registers:
84+
85+| Register | Field/Bits | Description |
86+| :------------------------------- | :------------ | :------------------------------------------------------ |
87+| SS_STRAP_GENERIC[2] | [15:0] | Health test window size for FIPS mode (default: 512). This is the window size for all health tests when entropy is tested in FIPS mode. |
88+| SS_STRAP_GENERIC[2] | [31] | Entropy bypass mode. When set to 1, enables bypass mode (`es_type`) to allow entropy characterization directly without passing through conditioning. |
89+| CPTRA_I_TRNG_ENTROPY_CONFIG_0 | [15:0] | Adaptive Proportion test high threshold (default: 1536). The test fails if any window has more than this threshold of 1's. |
90+| CPTRA_I_TRNG_ENTROPY_CONFIG_0 | [31:16] | Adaptive Proportion test low threshold (default: 512). The test fails if any window has less than this threshold of 1's. |
91+| CPTRA_I_TRNG_ENTROPY_CONFIG_1 | [15:0] | Repetition Count test threshold (default: 41). The test fails if an RNG wire repeats the same bit this many times in a row. |
92+| CPTRA_I_TRNG_ENTROPY_CONFIG_1 | [31:16] | Alert threshold (default: 2). Number of health check failures before an alert is triggered. |
93+
94+
95+**Notes:**
96+- If any threshold value is set to 0, the ROM uses the default value specified above.
97+- These configuration values are stored in persistent storage after first read to prevent malicious modification (reloaded on cold reset).
98+- In debug mode (`debug_locked == false`), entropy source configuration registers remain unlocked for characterization.
99+- In production mode, ROM locks the entropy source configuration after programming to prevent modification.
100+
101+For a comprehensive overview of the SOC interface registers, please refer to the following link::
102+https://chipsalliance.github.io/caliptra-rtl/main/external-regs/?p=caliptra_top_reg.generic_and_fuse_reg
68103
69104 ## Firmware image bundle
70105
71106 The Caliptra Firmware image has two main components:
72107
73-- ### **Firmware manifest**
74-
75-- ### **Firmware images**
108+- **Firmware manifest**
109+
110+- **Firmware images**
76111
77112 The firmware manifest is a combination of preamble and a signed header. It has
78-public keys, signatures and table of contents which refer to the various
113+public keys, public key hashes, signatures and table of contents which refer to the various
79114 firmware images contained in the bundle.
80115
81116 ![Firmware Image Bundle](../images/caliptra-sw/rom/dev/doc/svg/fw-img-bundle.svg)
@@ -89,33 +124,53 @@
89124 It is the unsigned portion of the manifest. Preamble contains the signing public keys and signatures. ROM is responsible for parsing the preamble. ROM performs the following steps:
90125
91126 - Loads the preamble from the mailbox.
92-- Calculates the hash of the four Manufacturer ECC and thirty-two LMS (if LMS verification is enabled) Public Keys in the preamble and compares it against the hash in the fuse (FUSE_KEY_MANIFEST_PK_HASH). If the hashes do not match, the boot fails.
93-- Selects the appropriate Manufacturer Public Key(s) based on fuse (FUSE_KEY_MANIFEST_PK_HASH_MASK for ECC public key, FUSE_LMS_REVOCATION for LMS public key)
127+- Calculates the hash of ECC and LMS or MLDSA [Public Key Descriptors](#Public-Key-Descriptor) in the preamble and compares it against the hash in the fuse (FUSE_VENDOR_PK_HASH). If the hashes do not match, the boot fails.
128+- Verifies the active Manufacturer Public Key(s) based on fuse (FUSE_ECC_REVOCATION for ECC public key, FUSE_LMS_REVOCATION for LMS public key or FUSE_MLDSA_REVOCATION for MLDSA public key)
94129
95130 *Note: All fields are little endian unless specified*
131+
132+*Preamble*
96133
97134 | Field | Size (bytes) | Description |
98135 | ------- | -------- | ------------ |
99-| Firmware Manifest Marker | 4 | Magic Number marking the start of the package manifest. The value must be 0x434D414E (‘CMAN’ in ASCII) |
136+| Firmware Manifest Marker | 4 | Magic Number marking the start of the package manifest. The value must be 0x434D4E32 (‘CMN2’ in ASCII) |
100137 | Firmware Manifest Size | 4 | Size of the full manifest structure |
101-| Manufacturer ECC Public Key 1 | 96 | ECC P-384 public key used to verify the Firmware Manifest Header Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
102-| Manufacturer ECC Public Key 2 | 96 | ECC P-384 public key used to verify the Firmware Manifest Header Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
103-| Manufacturer ECC Public Key 3 | 96 | ECC P-384 public key used to verify the Firmware Manifest Header Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
104-| Manufacturer ECC Public Key 4 | 96 | ECC P-384 public key used to verify the Firmware Manifest Header Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
105-| Manufacturer LMS Public Key 1 | 48 | LMS public key used to verify the Firmware Manifest Header Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes) <br> **otstype:** LMS Ots Algorithm Type (4 bytes) <br> **id:** (16 bytes) <br> **digest:** (24 bytes) |
106-| Manufacturer LMS Public Key 2 | 48 | LMS public key used to verify the Firmware Manifest Header Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes) <br> **otstype:** LMS Ots Algorithm Type (4 bytes) <br> **id:** (16 bytes) <br> **digest:** (24 bytes) |
107-| ...<Manufacturer LMS Public Key 32> |||
108-| ECC Public Key Index Hint | 4 | The hint to ROM to indicate which ECC public key it should first use. |
109-| LMS Public Key Index Hint | 4 | The hint to ROM to indicate which LMS public key it should first use. |
110-| Manufacturer ECC Signature | 96 | Manufacturer ECDSA P-384 signature of the Firmware Manifest header hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes) |
111-| Manufacturer LMS Signature | 1620 | Manufacturer LMS signature of the Firmware Manifest header hashed using SHA2-384. <br> **q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes) <br> **ots:** Lmots Signature (1252 bytes) <br> **tree_type:** Lms Algorithm Type (4 bytes) <br> **tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes) |
138+| Firmware Manifest Type | 4 | **Byte0:** - Type <br> 0x1 – ECC & MLDSA Keys <br> 0x3 – ECC & LMS Keys <br> **Byte1-Byte3:** Reserved |
139+| Manufacturer ECC Key Descriptor | 196 | Public Key Descriptor for ECC keys |
140+| Manufacturer LMS or MLDSA Key Descriptor | 1540 | Public Key Descriptor for LMS (1540 bytes) or MLDSA (196 bytes + 1344 unused bytes) keys |
141+| Active ECC Key Index | 4 | Public Key Hash Index for the active ECC key |
142+| Active ECC Key | 96 | ECC P-384 public key used to verify the Firmware Manifest Header Signature <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes, big endian) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes, big endian) |
143+| Active LMS or MLDSA Key Index | 4 | Public Key Hash Index for the active LMS or MLDSA key |
144+| Active LMS or MLDSA Key | 2592 | LMS public key (48 bytes + 2544 unused bytes) used to verify the Firmware Manifest Header Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes, big endian) Must equal 12. <br> **otstype:** LM-OTS Algorithm Type (4 bytes, big endian) Must equal 7. <br> **id:** (16 bytes) <br> **digest:** (24 bytes) <br><br>**OR**<br><br>MLDSA-87 public key used to verify the Firmware Manifest Header Signature. <br> (2592 bytes, little endian) |
145+| Manufacturer ECC Signature | 96 | Manufacturer ECC P-384 signature of the Firmware Manifest header hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes) |
146+| Manufacturer LMS or MLDSA Signature | 4628 | Manufacturer LMS signature (1620 bytes + 3008 unused bytes) of the Firmware Manifest header hashed using SHA2-384. <br> **q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes) <br> **ots:** Lmots Signature (1252 bytes) <br> **tree_type:** Lms Algorithm Type (4 bytes) <br> **tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes) <br><br>**OR**<br><br> Vendor MLDSA-87 signature of the Firmware Manifest header hashed using SHA2-512 (4627 bytes + 1 Reserved byte, little endian) |
112147 | Owner ECC Public Key | 96 | ECC P-384 public key used to verify the Firmware Manifest Header Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
113-| Owner LMS Public Key | 48 | LMS public key used to verify the Firmware Manifest Header Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes) <br> **otstype:** LMS Ots Algorithm Type (4 bytes) <br> **id:** (16 bytes) <br> **digest:** (24 bytes) |
114-| Owner ECC Signature | 96 | Manufacturer ECDSA P-384 signature of the Firmware Manifest header hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes) |
115-| Owner LMS Signature | 1620 | Owner LMS signature of the Firmware Manifest header hashed using SHA2-384. <br> **q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes) <br> **ots:** Lmots Signature (1252 bytes) <br> **tree_type:** Lms Algorithm Type (4 bytes) <br> **tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes) |
148+| Owner LMS or MLDSA Public Key | 2592 | LMS public key (48 bytes + 2544 unused bytes) used to verify the Firmware Manifest Header Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes) <br> **otstype:** LMS Ots Algorithm Type (4 bytes) <br> **id:** (16 bytes) <br> **digest:** (24 bytes) <br><br>**OR**<br><br>MLDSA-87 public key used to verify the Firmware Manifest Header Signature. <br> (2592 bytes, little endian) |
149+| Owner ECC Signature | 96 | Manufacturer ECC P-384 signature of the Firmware Manifest header hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes) |
150+| Owner LMS or MLDSA Signature | 4628 | Owner LMS signature (1620 bytes + 3008 unused bytes) of the Firmware Manifest header hashed using SHA2-384. <br> **q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes) <br> **ots:** Lmots Signature (1252 bytes) <br> **tree_type:** Lms Algorithm Type (4 bytes) <br> **tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes) <br><br>**OR**<br><br> Owner MLDSA-87 signature of the Firmware Manifest header hashed using SHA2-512 (4627 bytes + 1 Reserved byte, little endian) |
116151 | Reserved | 8 | Reserved 8 bytes |
117152
118153 <br>
154+
155+#### ECC Manufacturer Public Key Descriptor
156+
157+| Field | Size (bytes) | Description |
158+| ------- | -------- | ------------ |
159+| Key Descriptor Version | 2 | Version of the Key Descriptor. The value must be 0x1 for Caliptra 2.x |
160+| Reserved | 1 | Reserved |
161+| Key Hash Count | 1 | Number of valid public key hashes |
162+| Public Key Hash(es) | 48 * n | List of valid and invalid (if any) SHA2-384 public key hashes. ECDSA: n = 4 |
163+
164+
165+#### PQC Manufacturer Public Key Descriptor
166+
167+| Field | Size (bytes) | Description |
168+| ------- | -------- | ------------ |
169+| Key Descriptor Version | 2 | Version of the Key Descriptor. The value must be 0x1 for Caliptra 2.x |
170+| Key Type | 1 | Type of the key in the descriptor <br> 0x1 - MLDSA <br> 0x3 - LMS |
171+| Key Hash Count | 1 | Number of valid public key hashes |
172+| Public Key Hash(es) | 48 * n | List of valid and invalid (if any) SHA2-384 public key hashes. LMS: n = 32, MLDSA: n = 4 |
173+
119174
120175 #### Header
121176
@@ -124,14 +179,14 @@
124179 | Field | Size (bytes) | Description |
125180 | ------- | -------- | ------------ |
126181 | Revision | 8 | 8-byte version of the firmware image bundle |
127-| Vendor ECC public key index | 4 | The hint to ROM to indicate which ECC public key it should first use. |
128-| Vendor LMS public key index | 4 | The hint to ROM to indicate which LMS public key it should first use. |
182+| Vendor ECC public key hash index | 4 | The hint to ROM to indicate which ECC public key hash it should use to validate the active ECC public key. |
183+| Vendor LMS or MLDSA public key hash index | 4 | The hint to ROM to indicate which LMS or MLDSA public key hash it should use to validate the active public key. |
129184 | Flags | 4 | Feature flags. <br> **Bit0:** - Interpret the pl0_pauser field. If not set, all PAUSERs are PL1 <br>**Bit1-Bit31:** Reserved |
130185 | TOC Entry Count | 4 | Number of entries in TOC. |
131186 | PL0 PAUSER | 4 | The PAUSER with PL0 privileges. |
132187 | TOC Digest | 48 | SHA2-384 Digest of table of contents. |
133-| Vendor Data | 40 | Vendor Data. <br> **Not Before:** Vendor Start Date [ASN1 Time Format] For LDEV-Id certificate (15 bytes) <br> **Not After:** Vendor End Date [ASN1 Time Format] For LDEV-Id certificate (15 bytes) <br> **Reserved:** (10 bytes) |
134-| Owner Data | 40 | Owner Data. <br> **Not Before:** Owner Start Date [ASN1 Time Format] For LDEV-Id certificate. Takes preference over vendor start date (15 bytes) <br> **Not After:** Owner End Date [ASN1 Time Format] For LDEV-Id certificate. Takes preference over vendor end date (15 bytes) <br> **Reserved:** (10 bytes) |
188+| Vendor Data | 40 | Vendor Data. <br> **Not Before:** Vendor Start Date [ASN1 Time Format] For Alias FMC and Alias RT certificates (15 bytes) <br> **Not After:** Vendor End Date [ASN1 Time Format] For Alias FMC and Alias RT certificates (15 bytes) <br> **Reserved:** (10 bytes) |
189+| Owner Data | 40 | Owner Data. <br> **Not Before:** Owner Start Date [ASN1 Time Format] For Alias FMC and Alias RT certificates. Takes preference over vendor start date (15 bytes) <br> **Not After:** Owner End Date [ASN1 Time Format] For Alias FMC and Alias RT certificates. Takes preference over vendor end date (15 bytes) <br> **Reserved:** (10 bytes) |
135190
136191
137192 #### Table of contents
@@ -143,7 +198,7 @@
143198 | Image Type | 4 | Image Type that defines format of the image section <br> **0x0000_0001:** Executable |
144199 | Image Revision | 20 | Git Commit hash of the build |
145200 | Image Version | 4 | Firmware release number |
146-| Image SVN | 4 | Security Version Number for the Image. This field is compared against the fuses (FMC SVN or RUNTIME SVN) |
201+| Image SVN | 4 | Security Version Number for the image. It is compared to FW SVN fuses. FMC TOC entry's SVN field is ignored. |
147202 | Reserved | 4 | Reserved field |
148203 | Image Load Address | 4 | Load address |
149204 | Image Entry Point | 4 | Entry point to start the execution from |
@@ -168,11 +223,16 @@
168223 | Deobfuscation Engine | `doe_decrypt_uds(kv_slot, iv)` | Decrypt UDS to the specified key vault slot with specified initialization vector<br>**Input**:<br> ***kv_slot*** - key vault slot to decrypt the uds to<br>***iv*** - initialization vector |
169224 || `doe_decrypt_fe(kv_slot, iv)` | Decrypt Field Entropy to the specified key vault slot with specified initialization vector <br>**Input**:<br>***kv_slot*** - key vault slot to decrypt the field entropy to<br>***iv*** - initialization vector |
170225 || `doe_clear_secrets()` | Clear UDS Fuse Register, Field Entropy Fuse Register and Obfuscation key |
171-| Hashed Message Authentication Code | `hmac384_mac(key,data,mac_kv_slot)` | Calculate the mac using a caller provided key and data. The resultant mac is stored in key vault slot<br>**Input**:<br>***key*** - caller specified key<br>data - data<br>***mac_kv_slot*** - key vault slot to store the mac to |
172-|| `hmac384_mac(kv_slot,data,mac_kv_slot)` | Calculate the mac using a caller provided key and data. The resultant mac is stored in key vault slot <br>**Input**: <br>***kv_slot*** - key vault slot to use the key from<br>***data*** - data<br>***mac_kv_slot*** - key vault slot to store the mac to |
226+| Hashed Message Authentication Code | `hmac_mac(key,data,mac_kv_slot,mode)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot<br>**Input**:<br>***key*** - caller specified key<br>data - data<br>***mac_kv_slot*** - key vault slot to store the MAC to<br>***mode*** - HMAC384 or HMAC512 |
227+|| `hmac_mac(kv_slot,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot <br>**Input**: <br>***kv_slot*** - key vault slot to use the key from<br>***data*** - data<br>***mac_kv_slot*** - key vault slot to store the MAC to<br>***mode*** - HMAC384 or HMAC512 |
228+|| `hmac512_mac(key,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot<br>**Input**:<br>***key*** - caller specified key<br>data - data<br>***mac_kv_slot*** - key vault slot to store the MAC to |
229+|| `hmac512_mac(kv_slot,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot <br>**Input**: <br>***kv_slot*** - key vault slot to use the key from<br>***data*** - data<br>***mac_kv_slot*** - key vault slot to store the MAC to |
173230 | Elliptic Curve Cryptography | `ecc384_keygen(seed_kv_slot, priv_kv_slot) -> pub_key` | Generate ECC384 Key Pair.<br>**Input**:<br>***seed_key_slot*** - key vault slot to use as seed for key generation<br>***priv_kv_slot*** - key vault slot to store the private key to<br>**Output**:<br>***pub-key*** - public key associated with the private key |
174231 || `ecc384_sign(priv_kv_slot, data) -> sig` | ECC384 signing operation<br>**Input**:<br>***priv_kv_slot*** - key vault slot to use a private key from<br>***data*** - data to sign<br>**Output**:<br>***sig*** - signature |
175232 || `ecc384_verify(pub_key, data, sig) -> CaliptraResult<Array4xN<12, 48>>` | ECC384 verify operation<br>**Input**:<br>***pub-key*** -public key<br>data - data to verify<br>sig - signature<br>**Output**:<br>***Ecc384Result*** - verify.r value on success, else an error |
233+| Module-Lattice-Based Digital Signature Algorithm | `mldsa87_keygen(seed_kv_slot) -> pub_key` | Generate Mldsa87 Key Pair.<br>**Input**:<br>***seed_key_slot*** - key vault slot to use as seed for key generation<br>**Output**:<br>***pub-key*** - public key associated with the private key |
234+|| `mldsa87_sign(seed_kv_slot, data) -> sig` | Mldsa87 signing operation<br>**Input**:<br>***seed_kv_slot*** - key vault slot to use as seed for key generation for signing<br>***data*** - data to sign<br>**Output**:<br>***sig*** - signature |
235+|| `mldsa87_verify(pub_key, data, sig) -> Mldsa87Result` | Mldsa87 verify operation<br>**Input**:<br>***pub-key*** -public key<br>data - data to verify<br>sig - signature<br>**Output**:<br>***Mldsa87Result*** - '0xAAAAAAAA' value on success, '0x55555555' on error |
176236 | Secure Hash Algorithm | `sha384_digest(data) -> digest` | Calculate the digest of the data<br>**Input**:<br>***data*** - data to verify<br>**Output**:<br>***digest*** - digest of the data |
177237 | Key Vault | `kv_clear(kv_slot)` | Key Vault slot to clear<br>**Input**:<br>***kv_slot*** - key vault slot to clear |
178238 | Data Vault | `dv48_store(data, dv_slot)` | Store the 48-byte data in the specified data vault slot<br>**Input**:<br>***data*** - data to store<br>***dv_slot*** - data vault slot |
@@ -216,6 +276,171 @@
216276 - Zeros ICCM & DCCM memories (to initialize ECC)
217277 - Jumps to Rust entry point
218278
279+The following flows are conducted exclusively when the ROM is operating in SUBSYSTEM mode.
280+
281+### Manufacturing Flows:
282+The following flows are conducted when the ROM is operating in the manufacturing mode, indicated by a value of `DEVICE_MANUFACTURING` (0x1) in the `CPTRA_SECURITY_STATE` register `device_lifecycle` bits.
283+
284+#### UDS Provisioning
285+1. On reset, the ROM checks if the `UDS_PROGRAM_REQ` bit in the `SS_DBG_MANUF_SERVICE_REG_REQ` register is set. If the bit is set, ROM initiates the UDS seed programming flow by setting the `UDS_PROGRAM_IN_PROGRESS` bit in the `SS_DBG_MANUF_SERVICE_REG_RSP` register. If the flow fails at some point past reading the REQ bits, the flow will be aborted and an error returned.
286+
287+2. ROM then retrieves the following values:
288+ - A 512-bit value from the iTRNG.
289+ - The UDS Seed programming base address from the `SS_UDS_SEED_BASE_ADDR_L` and `SS_UDS_SEED_BASE_ADDR_H` registers.
290+ - The Fuse Controller's base address from the `SS_OTP_FC_BASE_ADDR_L` and `SS_OTP_FC_BASE_ADDR_H` registers.
291+
292+3. ROM then retrieves the UDS granularity from the `CPTRA_GENERIC_INPUT_WIRES` register0 Bit31 to learn if the fuse row is accessible with 32-bit or 64-bit granularity. If the bit is reset, it indicates 64-bit granularity; otherwise, it indicates 32-bit granularity.
293+
294+4. ROM computes the following values:
295+ - DAI_IDLE bit offset: (`SS_STRAP_GENERIC` register0 >> 16) & 0xFFFF
296+ - `DIRECT_ACCESS_CMD` offset: (`SS_STRAP_GENERIC` register1) & 0xFFFF + Fuse Controller's base address.
297+
298+4. ROM then performs the following steps until all the 512 bits of the UDS seed are programmed:
299+ 1. The ROM verifies the idle state of the DAI by reading the `STATUS` register `DAI_IDLE` bit (offset retrieved above) of the Fuse Controller, located at offset 0x10 from the Fuse Controller's base address.
300+ 2. If the granularity is 32-bit, the ROM writes the next word from the UDS seed to the `DIRECT_ACCESS_WDATA_0` register. If the granularity is 64-bit, the ROM writes the next two words to `the DIRECT_ACCESS_WDATA_0` and `DIRECT_ACCESS_WDATA_1` registers, located at offsets 0x8 and 0xC respectively from the `DIRECT_ACCESS_CMD` register.
301+ 3. The ROM writes the lower 32 bits of the UDS Seed programming base address to the `DIRECT_ACCESS_ADDRESS` register, located at offset 0x4 from the `DIRECT_ACCESS_CMD` register.
302+ 4. The ROM triggers the UDS seed write command by writing 0x2 to the `DIRECT_ACCESS_CMD` register..
303+ 5. The ROM increments the `DIRECT_ACCESS_ADDRESS` register by 4 for 32-bit granularity or 8 for 64-bit granularity and repeats the process for the remaining words of the UDS seed.
304+
305+5. The ROM continuously polls the Fuse Controller's `STATUS` register until the DAI state returns to idle.
306+
307+6. After completing the write operation, ROM triggers the partition digest operation performing the following steps:
308+ 1. The ROM writes the lower 32 bits of the UDS Seed programming base address to the `DIRECT_ACCESS_ADDRESS` register.
309+ 2. The ROM triggers the digest calculation command by writing 0x4 to the `DIRECT_ACCESS_CMD` register.
310+ 3. The ROM continuously polls the Fuse Controller's `STATUS` register until the DAI state returns to idle.
311+
312+7. ROM updates the `UDS_PROGRAM_SUCCESS` or the `UDS_PROGRAM_FAIL` bit in the `SS_DBG_MANUF_SERVICE_REG_RSP` register to indicate the outcome of the operation.
313+
314+8. ROM then resets the `UDS_PROGRAM_IN_PROGRESS` bit in the `SS_DBG_MANUF_SERVICE_REG_RSP` register to indicate completion of the programming.
315+
316+9. The manufacturing process then polls this bit and continues with the fuse burning flow as outlined by the fuse controller specifications and SOC-specific VR methodologies.
317+
318+#### Debug Unlock
319+
320+**Note:** All mailbox command requests start with a 4-byte `MailboxReqHeader` (containing a checksum field), while response payloads start with an 8-byte `MailboxRespHeader` (containing checksum and FIPS status fields).
321+
322+1. On reset, the ROM checks if the `MANUF_DBG_UNLOCK_REQ` bit in the `SS_DBG_MANUF_SERVICE_REG_REQ` register and the `DEBUG_INTENT` bit in `SS_DEBUG_INTENT` register are set.
323+
324+2. If they are set, the ROM sets the `TAP_MAILBOX_AVAILABLE` & `MANUF_DBG_UNLOCK_IN_PROGRESS` bits in the `SS_DBG_MANUF_SERVICE_REG_RSP` register, then enters a loop, awaiting a `TOKEN` command on the mailbox. The payload of this command is a 256-bit value.
325+
326+3. The ROM performs a SHA-512 operation on the token to generate the input token digest.
327+
328+4. The ROM compares the `FUSE_MANUF_DBG_UNLOCK_TOKEN` fuse register with the input token digest.
329+
330+5. The ROM completes the mailbox command.
331+
332+6. If the input token digest and fuse token digests match, the ROM authorizes the debug unlock by setting the `SS_DBG_MANUF_SERVICE_REG_RSP` register `MANUF_DBG_UNLOCK_SUCCESS` bit to 1.
333+
334+7. If the token digests do not match, the ROM blocks the debug unlock by setting the the `SS_DBG_MANUF_SERVICE_REG_RSP` register `MANUF_DBG_UNLOCK_FAIL` bit to 1.
335+
336+8. The ROM sets the `SS_DBG_MANUF_SERVICE_REG_RSP` register `MANUF_DBG_UNLOCK_IN_PROGRESS` and `TAP_MAILBOX_AVAILABLE` bits to 0.
337+
338+
339+### Production Flows
340+The following flows are conducted when the ROM is operating in the production mode, indicated by a value of `DEVICE_PRODUCTION` (0x3) in the `CPTRA_SECURITY_STATE` register `device_lifecycle` bits.
341+
342+#### Debug Unlock
343+
344+**Note:** All mailbox command requests start with a 4-byte `MailboxReqHeader` (containing a checksum field), while response payloads start with an 8-byte `MailboxRespHeader` (containing checksum and FIPS status fields).
345+
346+1. On reset, the ROM checks if the `PROD_DEBUG_UNLOCK_REQ` bit in the `SS_DBG_MANUF_SERVICE_REG_REQ` register and the `DEBUG_INTENT` in `SS_DEBUG_INTENT` register are set.
347+
348+2. If they are set, the ROM sets the `TAP_MAILBOX_AVAILABLE` & `PROD_DBG_UNLOCK_IN_PROGRESS` bits in the `SS_DBG_MANUF_SERVICE_REG_RSP` register.
349+
350+3. ROM enters a polling loop, awaiting a `AUTH_DEBUG_UNLOCK_REQ` command (Id: 0x50445552) on the mailbox. The payload for this command is of the following format:
351+
352+| Field | Size (bytes) | Description |
353+| ------------------ | -------------- | ---------------------------------------------------- |
354+| Length | 4 | Length of the message in DWORDs. This should be 2. |
355+| Unlock Level | 1 | Debug unlock Level (Number 1-8). |
356+| Reserved | 3 | Reserved field. |
357+
358+
359+3. On failure, ROM does the following:
360+ - `PROD_DBG_UNLOCK_FAIL` bit in `SS_DBG_MANUF_SERVICE_REG_RSP` register to 1.
361+ - `PROD_DBG_UNLOCK_IN_PROGRESS` bit in `SS_DBG_MANUF_SERVICE_REG_RSP` register to 0.
362+
363+4. The ROM validates the payload and on successful validation sends the following payload as the response:
364+
365+| Field | Size (bytes) | Description |
366+| -------------------------- | -------------- | ---------------------------------------------------- |
367+| Length | 4 | Length of the message in DWORDs. This should be 21. |
368+| Unique Device Identifier | 32 | Device identifier of the Caliptra Device. |
369+| Challenge | 48 | Random number. |
370+
371+
372+5. On failure, ROM sets the registers outlined in step 3.
373+
374+6. The SOC then sends the following payload via the `AUTH_DEBUG_UNLOCK_TOKEN` mailbox command (0x50445554):
375+
376+| Field | Size (bytes) | Description |
377+| -------------------------- | -------------- | --------------------------------------------------------------------------------------- |
378+| Length | 4 | Length of the message in DWORDs. This should be 0x753. |
379+| Unique Device Identifier | 32 | Device identifier sent in `AUTH_DEBUG_UNLOCK_CHALLENGE` mailbox command payload. |
380+| Unlock Level | 1 | Debug unlock Level (Number 1-8). |
381+| Reserved | 3 | Reserved field. |
382+| Challenge | 48 | Random number sent in `AUTH_DEBUG_UNLOCK_CHALLENGE` mailbox command payload. |
383+| ECC Public Key | 96 | ECC P-384 public key used to verify the Message Signature <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes, big endian) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes, big endian) |
384+| MLDSA Public Key | 2592 | MLDSA-87 public key used to verify the Message Signature. |
385+| ECC Signature | 96 | ECC P-384 signature of the Message hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes). |
386+| MLDSA Signature | 4628 | MLDSA signature of the Message hashed using SHA2-512. (4627 bytes + 1 Reserved byte). |
387+
388+
389+7. On receiving this payload, ROM performs the following validations:
390+ - Ensures the value in the `Length` field matches the size of the payload.
391+ - Confirms that the `Debug unlock level` is not zero and does not exceed the value specified in the `SS_NUM_OF_PROD_DEBUG_UNLOCK_AUTH_PK_HASHES` register.
392+ - Calculates the address of the public key hash fuse as follows: <br>
393+ **SS_PROD_DEBUG_UNLOCK_AUTH_PK_HASH_REG_BANK_OFFSET register value + ( (Debug Unlock Level - 1) * SHA2-384 hash size (48 bytes) )**
394+ - Retrieves the SHA2-384 hash (48 bytes) from the calculated address using DMA assist.
395+ - Computes the SHA2-384 hash of the message formed by concatenating the ECC and MLDSA public keys in the payload.
396+ - Compares the retrieved and computed hashes. It the comparison fails, the ROM blocks the debug unlock request by setting the registers outlined in step 3.
397+ - Upon hash comparison failure, the ROM exits the payload validation flow and completes the mailbox command.
398+
399+4. The ROM proceeds with payload validation by verifying the ECC and MLDSA signatures over the `Challenge`, `Device Identifier`, `Reserved` and `Unlock Category` fields within the payload. Should the validation fail, the ROM blocks the debug unlock by setting the registers outlined in item 3. Conversely, if the signature validation succeeds, the ROM authorizes the debug unlock by configuring the following settings:
400+
401+ - `PROD_DBG_UNLOCK_SUCCESS` bit in `SS_DBG_MANUF_SERVICE_REG_RSP` register to 1.
402+ - Setting the Debug unlock level in the `SS_SOC_DBG_UNLOCK_LEVEL` register as one hot encoded value (1 << (Level - 1))
403+ - `PROD_DBG_UNLOCK_IN_PROGRESS` bit in `SS_DBG_MANUF_SERVICE_REG_RSP` register to 0.
404+
405+5. ROM then completes the mailbox command with success.
406+
407+6. The ROM sets the `SS_DBG_MANUF_SERVICE_REG_RSP` register `PROD_DBG_UNLOCK_IN_PROGRESS` and `TAP_MAILBOX_AVAILABLE` bits to 0.
408+
409+### Known Answer Test (KAT)
410+
411+To certify a cryptographic module, pre-operational self-tests must be performed when the system is booted. Implementing KATs is required for FIPS certification. However, regardless of FIPS certification, it is considered a security best practice to ensure that the supported cryptographic algorithms are functioning properly to guarantee correct security posture.
412+
413+KAT execution is described as two types:
414+
415+* Pre-operational Self-Test (POST)
416+* Conditional Algorithm Self-Test (CAST)
417+
418+ROM performs the following POST tests to ensure that needed cryptographic modules are functioning correctly and are operational before any cryptographic operations are performed:
419+
420+ - SHA1
421+ - SHA2-256
422+ - SHA2-384
423+ - SHA2-512
424+ - SHA2-512-ACC
425+ - ECC-384
426+ - ECDH
427+ - HMAC-384Kdf
428+ - HMAC-512Kdf
429+ - HKDF-384
430+ - HKDF-512
431+ - KDF-CMAC
432+ - LMS
433+ - MLDSA-87
434+ - AES-256-ECB
435+ - AES-256-CBC
436+ - AES-256-CMAC
437+ - AES-256-CTR
438+ - AES-256-GCM
439+
440+### DICE Flow
441+
442+![DICE Flow](../images/caliptra-sw/rom/dev/doc/svg/dice-diagram.svg)
443+
219444 ### Decrypt secrets
220445
221446 DICE Unique Device Secret (UDS) is stored in an SOC backed fuse (or derived from PUF). The raw UDS is not directly used. UDS is deobfuscated using Deobfuscation Engine. UDS is provisioned by the Silicon Vendor.
@@ -229,9 +454,9 @@
229454 - Caliptra subsystem is being cold reset
230455 - Obfuscation Key loaded in deobfuscation engine
231456 - UDS and Field Entropy loaded in Caliptra Fuse Registers
232-- Keys Slot 0 - 31 are empty and Usage Bits are all cleared
457+- Keys Slot 0 - 23 are empty and Usage Bits are all cleared
233458 - PCR 0 - 31 are all cleared
234-- Data Vault is all cleared
459+- DCCM datavault is cleared
235460
236461 **Actions:**
237462
@@ -241,7 +466,7 @@
241466
242467 2. Decrypt Field Entropy to Key Vault Slot 1
243468
244- `doe_decrypt_uds(KvSlot1, DOE_IV)`
469+ `doe_decrypt_fe(KvSlot1, DOE_IV)`
245470
246471 3. Clear class secrets (Clears UDS, Field Entropy and Obfuscation Key cleared)
247472
@@ -253,155 +478,283 @@
253478 - Obfuscation Key cleared from Deobfuscation Engine
254479 - Vault State is as follows:
255480
256-| Slot | Key Vault | PCR Bank | Data Vault 48 Byte (Sticky) | Data Vault 4 Byte (Sticky) |
257-| ------ | ----------- | ---------- | ----------------------------- | ---------------------------- |
258-| 0 | UDS (48 bytes) ||||
259-| 1 | Field Entropy (32 bytes) ||||
481+| Slot | Key Vault |
482+| ------ | ----------------------- |
483+| 0 | UDS (64 bytes) |
484+| 1 | Field Entropy (32 bytes) |
260485
261486
262487 ### Initial Device ID DICE layer
263488
264-Initial Device ID Layer is used to generate Manufacturer CDI & Private Key. This layer represents the manufacturer or silicon vendor DICE Identity. During manufacturing, ROM can be requested to create Certificate Signing Request (CSR) via JTAG.
489+Initial Device ID Layer is used to generate Manufacturer CDI & Private Keys. This layer represents the manufacturer or silicon vendor DICE Identity. During manufacturing, ROM can be requested to create Certificate Signing Request (CSR) via JTAG.
265490
266491 **Pre-conditions:**
267492
268-- UDS is loaded in Key Vault Slot 0
493+- UDS is in Key Vault Slot 0
269494
270495 **Actions:**
271496
272-1. Derive the CDI using ROM specified label and UDS in Slot 0 as data and store the resultant mac in KeySlot6
273-
274- `hmac384_kdf(KvSlot0, b"idevid_cdi", KvSlot6)`
275-
276-2. Clear the UDS in key vault
497+1. Derive the CDI using ROM specified label and UDS in Key Vault Slot 0 as data and store the resultant MAC in Key Vault Slot 6.
498+
499+ `hmac512_kdf(KvSlot0, b"idevid_cdi", KvSlot6)`
500+
501+2. Clear the UDS in the key vault.
277502
278503 `kv_clear(KvSlot0)`
279504
280-3. Derive ECC Key Pair using CDI in Key Vault Slot6 and store the generated private key in KeySlot7
281-
282- `IDevIDSeed = hmac384_kdf(KvSlot6, b"idevid_keygen", KvSlot3)`
283- `IDevIdPubKey = ecc384_keygen(KvSlot3, KvSlot7)`
505+3. Derive ECC Key Pair using CDI in Key Vault Slot 6 and store the generated private key in Key Vault Slot 7.
506+
507+ `IDevIDSeedEcdsa = hmac512_kdf(KvSlot6, b"idevid_ecc_key", KvSlot3)`
508+
509+ `IDevIdPubKeyEcdsa = ecc384_keygen(KvSlot3, KvSlot7)`
510+
284511 `kv_clear(KvSlot3)`
285512
286-*(Note: Steps 4-7 are performed if CSR download is requested via CPTRA_DBG_MANUF_SERVICE_REG register)*
287-
288-4. Generate the `To Be Signed` DER Blob of the IDevId CSR
289-
290- `IDevIdTbs = gen_tbs(IDEVID_CSR, IDevIdPubKey)`
291-
292-5. Sign the IDevID `To Be Signed` DER Blob with IDevId Private Key in Key Vault Slot 7
293-
294- `IDevIdTbsDigest = sha384_digest(IDevIdTbs)`
295- `IDevIdCertSig = ecc384_sign(KvSlot7, IDevIdTbsDigest)`
296-
297-6. Verify the signature of IDevID `To Be Signed` Blob
298-
299- `IDevIdTbsDigest = sha384_digest(IDevIdTbs)`
300- `Result = ecc384_verify(IDevIdPubKey, IDevIdTbsDigest, IDevIdCertSig)`
301-
302-7. Upload the CSR to mailbox and wait for JTAG to read the CSR out of the mailbox.
513+ Derive the MLDSA Key Pair using CDI in Key Vault Slot 6 and store the key generation seed in Key Vault Slot 8.
514+
515+ `IDevIDSeedMldsa = hmac512_kdf(KvSlot6, b"idevid_mldsa_key", KvSlot8)`
516+
517+ `IDevIdPubKeyMldsa = mldsa87_keygen(KvSlot8)`
518+
519+*(Note: Steps 4-12 are performed if CSR download is requested via CPTRA_DBG_MANUF_SERVICE_REG register)*
520+
521+4. Generate the `To Be Signed` DER Blob of the IDevId CSR with the ECDSA public key.
522+
523+ `IDevIdTbsEcdsa = gen_tbs(IDEVID_CSR, IDevIdPubKeyEcdsa)`
524+
525+5. Sign the IDevID `To Be Signed` DER Blob with IDevId ECDSA Private Key in Key Vault Slot 7.
526+
527+ `IDevIdTbsDigestEcdsa = sha384_digest(IDevIdTbsEcdsa)`
528+
529+ `IDevIdCertSigEcdsa = ecc384_sign(KvSlot7, IDevIdTbsDigestEcdsa)`
530+
531+6. Verify the signature of IDevID `To Be Signed` Blob.
532+
533+ `Result = ecc384_verify(IDevIdPubKeyEcdsa, IDevIdTbsDigestEcdsa, IDevIdCertSigEcdsa)`
534+
535+7. Generate the `To Be Signed` DER Blob of the IDevId CSR with the MLDSA public key.
536+
537+ `IDevIdTbsMldsa = gen_tbs(IDEVID_CSR, IDevIdPubKeyMldsa)`
538+
539+8. Sign the IDevID `To Be Signed` DER Blob with IDevId MLDSA Private Key generated from the seed in Key Vault Slot 8.
540+
541+ `IDevIdTbsDigestMldsa = sha512_digest(IDevIdTbsMldsa)`
542+
543+ `IDevIdCertSigMldsa = mldsa87_sign(KvSlot8, IDevIdTbsDigestMldsa)`
544+
545+9. Verify the signature of IDevID `To Be Signed` Blob.
546+
547+ `Result = mldsa87_verify(IDevIdPubKeyMldsa, IDevIdTbsDigestMldsa, IDevIdCertSigMldsa)`
548+
549+10. Generate the MACs over the tbs digests as follows:
550+
551+ `IDevIdTbsEcdsaMac = hmac_mac(VendorSecretKvSlot, b"idevid_ecc_csr", IDevIdTbsDigestEcdsa, HmacMode::Hmac384)`
552+
553+ `IDevIdTbsMldsaMac = hmac512_mac(VendorSecretKvSlot, b"idevid_mldsa_csr",IDevIdTbsDigestMldsa, HmacMode::Hmac512)`
554+
555+11. Upload the CSR(s) to mailbox and wait for JTAG to read the CSR out of the mailbox. Format of the CSR payload is documented below:
556+
557+#### IDevID CSR Format
558+
559+*Note: All fields are little endian unless specified*
560+
561+| Field | Size (bytes) | Description |
562+| ---------------- | -------------- | ------------------------------------------------------------------------------------------------- |
563+| Marker | 4 | Magic Number marking the start of the CSR payload. The value must be 0x435352 (‘CSR’ in ASCII). |
564+| Size | 4 | Size of the entire CSR payload. |
565+| ECC CSR Size | 4 | Size of the ECC CSR in bytes. |
566+| ECC CSR | 512 | ECC CSR buffer. Actual CSR size is indicated by 'ECC CSR Size'. |
567+| MLDSA CSR Size | 4 | Size of the MLDSA CSR in bytes. |
568+| MLDSA CSR | 7680 | MLDSA CSR bytes. Actual CSR size is indicated by 'MLDSA CSR Size'. |
569+| CSR MAC | 64 | HMAC-512 MAC, computed over the envelope bytes up to but not including this field. |
570+
303571
304572 **Post-conditions:**
305573
306-- Vault state as follows:
307-
308-| Slot | Key Vault | PCR Bank | Data Vault 48 Byte (Sticky) | Data Vault 4 Byte (Sticky) |
309-| ------ | ----------- | ---------- | ----------------------------- | ---------------------------- |
310-| 1 | Field Entropy (32 bytes) ||||
311-| 6 | IDevID CDI (48 bytes) ||||
312-| 7 | IDevID Private Key (48 bytes) ||||
574+- Vault state is as follows:
575+
576+| Slot | Key Vault |
577+| ------ | --------------------------------------- |
578+| 1 | Field Entropy (32 bytes) |
579+| 6 | IDevID CDI (64 bytes) |
580+| 7 | IDevID ECDSA Private Key (48 bytes) |
581+| 8 | IDevID MLDSA Key Pair Seed (32 bytes) |
582+
583+
584+| DCCM Datavault |
585+| -------------------------------- |
586+| 🔒IDevID Cert ECDSA Signature |
587+| 🔒IDevID ECDSA Pub Key |
588+| 🔒IDevID Cert MLDSA Signature |
589+| 🔒IDevID MLDSA Pub Key |
313590
314591
315592 ### Local Device ID DICE layer
316593
317-Local Device ID Layer derives the Owner CDI & ECC Keys. This layer represents the owner DICE Identity as it is mixed with the Field Entropy programmed by the Owner.
594+Local Device ID Layer derives the Owner CDI, ECC and MLDSA Keys. This layer represents the owner DICE Identity as it is mixed with the Field Entropy programmed by the Owner.
318595
319596 **Pre-conditions:**
320597
321598 - Field Entropy is loaded in Key Vault Slot 1
322599 - IDevID CDI is stored in Key Vault Slot 6
323600 - IDevID Private Key is stored in Key Vault Slot 7
601+- IDevID MLDSA Key Generation Seed is stored in Key Vault Slot 8
324602
325603 **Actions:**
326604
327-1. Derive the CDI using IDevID CDI in Key Vault Slot6 as HMAC Key and Field Entropy stored in Key Vault Slot1 as data. The resultant mac is stored back in Slot 6
328-
329- `hmac384_mac(KvSlot6, b"ldevid_cdi", KvSlot6)`
330- `hmac384_mac(KvSlot6, KvSlot1, KvSlot6)`
605+1. Derive the stable identity root secret from IDevID and store the resultant MAC in Key Vault Slot 0.
606+
607+ `hmac512_mac(KvSlot0, b"stable_identity_root_idev", KvSlot6)`
608+
609+2. Derive the LDevID CDI using IDevID CDI in Key Vault Slot 6 as HMAC Key and Field Entropy stored in Key Vault Slot 1 as data. The resultant MAC is stored back in Key Vault Slot 6.
610+
611+ `hmac512_mac(KvSlot6, b"ldevid_cdi", KvSlot6)`
612+
613+ `hmac512_mac(KvSlot6, KvSlot1, KvSlot6)`
331614
332615 *(Note: this uses a pair of HMACs to incorporate the diversification label, rather than a single KDF invocation, due to hardware limitations when passing KV data to the HMAC hardware as a message.)*
333616
334-2. Clear the Field Entropy in Key Vault Slot 1
617+3. Clear the Field Entropy in Key Vault Slot 1.
335618
336619 `kv_clear(KvSlot1)`
337620
338-3. Derive ECC Key Pair using CDI in Key Vault Slot6 and store the generated private key in KeySlot5.
339-
340- `LDevIDSeed = hmac384_kdf(KvSlot6, b"ldevid_keygen", KvSlot3)`
341- `LDevIdPubKey = ecc384_keygen(KvSlot3, KvSlot5)`
621+4. Derive the stable identity root secret from LDevID and store the resultant MAC in Key Vault Slot 1.
622+
623+ `hmac512_mac(KvSlot1, b"stable_identity_root_ldev", KvSlot6)`
624+
625+5. Derive ECDSA Key Pair using CDI in Key Vault Slot 6 and store the generated private key in Key Vault Slot 5.
626+
627+ `LDevIDSeed = hmac512_kdf(KvSlot6, b"ldevid_ecc_key", KvSlot3)`
628+
629+ `LDevIdPubKeyEcdsa = ecc384_keygen(KvSlot3, KvSlot5)`
630+
342631 `kv_clear(KvSlot3)`
343632
344-4. Store and lock (for write) the LDevID Public Key in Data Vault (48 bytes) Slot 2 and Slot 3
345-
346- `dv48_store(LDevIdPubKey.X, Dv48Slot2)`
347- `dv48_lock_wr(Dv48Slot2)`
348- `dv48_store(LDevIdPubKey.Y, Dv48Slot3)`
349- `dv48_lock_wr(Dv48Slot3)`
350-
351-5. Generate the `To Be Signed` DER Blob of the LDevId Certificate
352-
353- `LDevIdTbs = gen_cert_tbs(LDEVID_CERT, IDevIdPubKey, LDevIdPubKey)`
354-
355-6. Sign the LDevID `To Be Signed` DER Blob with IDevId Private Key in Key Vault Slot 7
356-
357- `LDevIdTbsDigest = sha384_digest(LDevIdTbs)`
358- `LDevIdCertSig = ecc384_sign(KvSlot7, LDevIdTbsDigest)`
359-
360-7. Clear the IDevId Private Key in Key Vault Slot 7
633+6. Derive the MLDSA Key Pair using CDI in Key Vault Slot 6 and store the key generation seed in Key Vault Slot 4.
634+
635+ `LDevIDSeed = hmac512_kdf(KvSlot6, b"ldevid_mldsa_key", KvSlot4)`
636+
637+ `LDevIdPubKeyMldsa = mldsa87_keygen(KvSlot4)`
638+
639+7. Store and lock (for write) the LDevID ECDSA and MLDSA Public Keys in the DCCM datavault.
640+
641+8. Generate the `To Be Signed` DER Blob of the ECDSA LDevId Certificate.
642+
643+ `LDevIdTbsEcdsa = gen_cert_tbs(LDEVID_CERT, IDevIdPubKeyEcdsa, LDevIdPubKeyEcdsa)`
644+
645+9. Sign the LDevID `To Be Signed` DER Blob with IDevId ECDSA Private Key in Key Vault Slot 7.
646+
647+ `LDevIdTbsDigestEcdsa = sha384_digest(LDevIdTbsEcdsa)`
648+
649+ `LDevIdCertSigEcdsa = ecc384_sign(KvSlot7, LDevIdTbsDigestEcdsa)`
650+
651+10. Clear the IDevId ECDSA Private Key in Key Vault Slot 7.
361652
362653 `kv_clear(KvSlot7)`
363654
364-8. Verify the signature of LDevID `To Be Signed` Blob
365-
366- `LDevIdTbsDigest = sha384_digest(LDevIdTbs)`
367- `Result = ecc384_verify(LDevIdPubKey, LDevIdTbsDigest, LDevIdCertSig)`
368-
369-9. Store and lock (for write) the LDevID Certificate Signature in the sticky Data Vault (48 bytes) Slot 0 & Slot 1
370-
371- `dv48_store(LDevIdCertSig.R, Dv48Slot0)`
372- `dv48_lock_wr(Dv48Slot0)`
373- `dv48_store(LDevIdCertSig.S, Dv48Slot1)`
374- `dv48_lock_wr(Dv48Slot1)`
655+11. Verify the signature of LDevID `To Be Signed` Blob.
656+
657+ `Result = ecc384_verify(IDevIdPubKeyEcdsa, LDevIdTbsDigestEcdsa, LDevIdCertSigEcdsa)`
658+
659+12. Generate the `To Be Signed` DER Blob of the MLDSA LDevId Certificate.
660+
661+ `LDevIdTbsMldsa = gen_cert_tbs(LDEVID_CERT, IDevIdPubKeyMldsa, LDevIdPubKeyMldsa)`
662+
663+13. Sign the LDevID `To Be Signed` DER Blob with the IDevId MLDSA Private Key derived from the seed in Key Vault Slot 8.
664+
665+ `LDevIdTbsDigestMldsa = sha512_digest(LDevIdTbsMldsa)`
666+
667+ `LDevIdCertSigMldsa = mldsa87_sign(KvSlot8, LDevIdTbsDigestMldsa)`
668+
669+14. Clear the IDevId Mldsa seed in Key Vault Slot 8.
670+
671+ `kv_clear(KvSlot8)`
672+
673+15. Verify the signature of LDevID `To Be Signed` Blob.
674+
675+ `Result = mldsa87_verify(IDevIdPubKeyMldsa, LDevIdTbsDigestMldsa, LDevIdCertSigMldsa)`
676+
677+16. Store and lock (for write) the LDevID Certificate ECDSA and MLDSA Signatures in the DCCM datavault.
678+
375679
376680 **Post-conditions:**
377681
378-- Vault state as follows:
379-
380-| Slot | Key Vault | PCR Bank | Data Vault 48 Byte (Sticky) | Data Vault 4 Byte (Sticky) |
381-| ------ | ----------- | ---------- | ----------------------------- | ---------------------------- |
382-| 0 ||| 🔒LDevID Cert Signature R ||
383-| 1 ||| 🔒LDevID Cert Signature S ||
384-| 2 ||| 🔒LDevID Pub Key X ||
385-| 3 ||| 🔒LDevID Pub Key Y ||
386-| 5 | LDevID Private Key (48 bytes) ||||
387-| 6 | LDevID CDI (48 bytes) ||||
388-
389-
390-### Handling commands from mailbox
391-
392-ROM supports the following set of commands before handling the FW_DOWNLOAD command (described in section 9.6). Once the FW_DOWNLOAD is issued, ROM stops processing any additional mailbox commands.
393-
394-1. **STASH_MEASUREMENT**: Up to eight measurements can be sent to the ROM for recording. Sending more than eight measurements will result in an FW_PROC_MAILBOX_STASH_MEASUREMENT_MAX_LIMIT fatal error. Format of a measurement is documented at [Stash Measurement command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#stash_measurement).
395-2. **VERSION**: Get version info about the module. [Version command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#version).
396-3. **SELF_TEST_START**: This command is used to invoke the FIPS Known-Answer-Tests (aka KAT) on demand. [Self Test Start command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#self_test_start).
397-4. **SELF_TEST_GET_RESULTS**: This command is used to check if a SELF_TEST command is in progress. [Self Test Get Results command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#self_test_get_results).
398-5. **SHUTDOWN**: This command is used clear the hardware crypto blocks including the keyvault. [Shutdown command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#shutdown).
399-6. **CAPABILITIES**: This command is used to query the ROM capabilities. Capabilities is a 128-bit value with individual bits indicating a specific capability. Currently, the only capability supported is ROM_BASE (bit 0). [Capabilities command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#capabilities).
400-7. **GET_IDEVID_CSR**: This command is used to fetch the IDevID CSR from ROM. [Fetch IDevIDCSR command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#get_idevid_csr).
401-
402-### Downloading images from mailbox
403-
404-The following is the sequence of the steps that are required to download the parts of firmware image from mailbox.
682+- Vault state is as follows:
683+
684+| Slot | Key Vault |
685+| ------ | ----------------------------------------------- |
686+| 0 | Stable identity root IDevID secret (64 bytes) |
687+| 1 | Stable identity root LDevID secret (64 bytes) |
688+| 4 | LDevID Key Pair Seed - MLDSA (32 bytes) |
689+| 5 | LDevID Private Key - ECDSA (48 bytes) |
690+| 6 | LDevID CDI (64 bytes) |
691+
692+
693+| DCCM Datavault |
694+| -------------------------------- |
695+| 🔒IDevID Cert ECDSA Signature |
696+| 🔒IDevID ECDSA Pub Key |
697+| 🔒IDevID Cert MLDSA Signature |
698+| 🔒IDevID MLDSA Pub Key |
699+| 🔒LDevID Cert ECDSA Signature |
700+| 🔒LDevID ECDSA Pub Key |
701+| 🔒LDevID Cert MLDSA Signature |
702+| 🔒LDevID MLDSA Pub Key |
703+
704+
705+### Firmware Processor Stage
706+During this phase, the ROM executes specific mailbox commands. Based on the operational mode (SUBSYSTEM versus PASSIVE), the ROM also initiates the download of the firmware image. This download is conducted either through a mailbox command or via the Recovery Register Interface.
707+
708+#### Handling commands from mailbox
709+
710+ROM supports the following set of commands before handling the FW_DOWNLOAD command in PASSIVE mode (described in section 9.6) or RI_DOWNLOAD_FIRMWARE command in SUBSYSTEM mode. Once the FW_DOWNLOAD or RI_DOWNLOAD_FIRMWARE is issued, ROM stops processing any additional mailbox commands.
711+
712+1. **STASH_MEASUREMENT**: Up to eight measurements can be sent to the ROM for recording. Sending more than eight measurements will result in an FW_PROC_MAILBOX_STASH_MEASUREMENT_MAX_LIMIT fatal error. Format of a measurement is documented at [Stash Measurement command](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#stash_measurement).
713+2. **VERSION**: Get version info about the module. [Version command](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#version).
714+3. **SELF_TEST_START**: This command is used to invoke the FIPS Known-Answer-Tests (aka KAT) on demand. [Self Test Start command](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#self_test_start).
715+4. **SELF_TEST_GET_RESULTS**: This command is used to check if a SELF_TEST command is in progress. [Self Test Get Results command](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#self_test_get_results).
716+5. **SHUTDOWN**: This command is used clear the hardware crypto blocks including the keyvault. [Shutdown command](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#shutdown).
717+6. **CAPABILITIES**: This command is used to query the ROM capabilities. Capabilities is a 128-bit value with individual bits indicating a specific capability. Currently, the only capability supported is ROM_BASE (bit 0). [Capabilities command](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#capabilities).
718+7. **GET_IDEVID_CSR**: This command is used to fetch the IDevID CSR from ROM. [Fetch IDevIDCSR command](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#get_idevid_csr).
719+8. **CM_DERIVE_STABLE_KEY**: This command is used to derive a stable key for Device Ownership Transfer or other flows. Note that in Caliptra 2.0 in subsystem mode, derived stable keys, their derivatives, and commands using them will be marked with a FIPS status of invalid since the UDS and FE cannot be completely zeroized. See [CM_DERIVE_STABLE_KEY](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#cm_derive_stable_key).
720+9. **CM_HMAC**: This command uses derived stable keys for Device Ownership Transfer or other flows. [CM_HMAC](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#cm_hmac)
721+10. **ECDSA384_SIGNATURE_VERIFY**: This command verifies ECDSA384 signatures for Device Ownership Transfer or other flows. [ECDSA384_SIGNATURE_VERIFY](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#ecdsa384_signature_verify)
722+11. **MLDSA87_SIGNATURE_VERIFY**: This command verifies MLDSA87 signatures for Device Ownership Transfer or other flows. [MLDSA87_SIGNATURE_VERIFY](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#mldsa87_signature_verify)
723+12. **CM_RANDOM_GENERATE**: This command returns random numbers from Caliptra's RNG for Device Ownership Transfer or other flows. [CM_RANDOM_GENERATE](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime/README.md#cm_random_generate)
724+13. **CM_SHA**: This ROM-only command (ROM 2.0.1+ only) computes a SHA-384 or SHA-512 hash of input data in a single operation. This is useful for MCU ROM to verify signatures and hashes against Vendor PK hash without needing its own hash implementation. Unlike the runtime CM_SHA_INIT/CM_SHA_UPDATE/CM_SHA_FINAL commands, this is a one-shot operation that does not support streaming or contexts. See [CM_SHA](#cm_sha) below for details.
725+14. **GET_LDEV_ECC384_CERT**: This command fetches an LDevID ECC384 certificate signed by the ECC384 IDevID private key. [GET_LDEV_ECC384_CERT](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime#get_ldev_ecc384_cert)
726+15. **GET_LDEV_MLDSA87_CERT**: This command fetches an LDevID MLDSA87 certificate signed by the MLDSA87 IDevID private key. [GET_LDEV_MLDSA87_CERT](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime#get_ldev_mldsa87_cert)
727+16. **INSTALL_OWNER_PK_HASH**: This command saves the owner public key hash to persistent data. [INSTALL_OWNER_PK_HASH](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/runtime#install_owner_pk_hash)
728+
729+#### CM_SHA
730+
731+This ROM-only command computes a SHA-384 or SHA-512 hash of input data in a single one-shot operation. This command is designed for MCU ROM to verify signatures and hashes (e.g., against Vendor PK hash) without requiring its own hash implementation.
732+
733+**Note:** This command is only available in ROM. Runtime firmware should use the streaming CM_SHA_INIT, CM_SHA_UPDATE, and CM_SHA_FINAL commands instead, which support contexts and incremental hashing.
734+
735+Command Code: `0x434D_5348` ("CMSH")
736+
737+*Table: `CM_SHA` input arguments*
738+
739+| **Name** | **Type** | **Description**
740+| -------------- | ------------- | ---------------
741+| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian.
742+| hash_algorithm | u32 | Hash algorithm: 1 = SHA-384, 2 = SHA-512. Value 0 is reserved and will return an error.
743+| input_size | u32 | Size of input data in bytes. Maximum 262,132 bytes (256 KB minus 12-byte header overhead).
744+| input | u8[input_size]| Input data to hash. Variable size up to the mailbox capacity.
745+
746+*Table: `CM_SHA` output arguments*
747+
748+| **Name** | **Type** | **Description**
749+| ------------- | ------------- | ---------------
750+| chksum | u32 | Checksum over other output arguments, computed by Caliptra. Little endian.
751+| fips_status | u32 | FIPS status. 0 = approved mode.
752+| data_len | u32 | Length of hash output in bytes. 48 for SHA-384, 64 for SHA-512.
753+| hash | u8[data_len] | The computed hash value. Variable size based on algorithm.
754+
755+#### Downloading firmware image from mailbox
756+
757+There are two modes in which the ROM executes: PASSIVE mode or SUBSYSTEM mode. Following is the sequence of the steps that are performed to download the firmware image from mailbox in PASSIVE mode.
405758
406759 - ROM asserts READY_FOR_FIRMWARE signal.
407760 - Poll for the execute bit to be set. This bit is set as the last step to transfer the control of the command to the Caliptra ROM.
@@ -414,10 +767,79 @@
414767
415768 ![DATA FROM MBOX FLOW](../images/caliptra-sw/rom/dev/doc/svg/data-from-mbox.svg)
416769
417-### Image validation
770+Following is the sequence of steps that are performed to download the firmware image into the mailbox in SUBSYSTEM mode.
771+
772+1. On receiving the RI_DOWNLOAD_FIRMWARE mailbox command, set the RI PROT_CAP2 register version to 1.1 and the `Agent Capability` field bits:
773+ - `Device ID`
774+ - `Device Status`
775+ - `Push C-image support`
776+ - `Flashless boot`
777+ - `FIFO CMS support`
778+2. Set the RI DEVICE_STATUS_0 register, `Device Status` field to 0x3 ('Recovery mode - ready to accept recovery image') and
779+`Recovery Reason Code` field to 0x12 ('Flashless/Streaming Boot (FSB)').
780+3. Set the RI RECOVERY_STATUS register, `Device Recovery Status` field to 0x1 ('Awaiting recovery image') and `Recovery Image Index` field to 0 (Firmware Image).
781+4. Loop on the `payload_available` bit in the `DMA Status0` register for the firmware image info to be available.
782+5. Read the image size from RI INDIRECT_FIFO_CTRL_1 register. Image size is in DWORDs.
783+6. Initiate image download from the recovery interface to the mailbox sram:
784+ a. Write the payload length to the DMA widget 'Byte Count' register.
785+ b. Write the block size with a value of 256 to the DMA widget 'Block Size' register.
786+ c. Write the source address to the DMA widget 'Source Address - Low' and 'Source Address - High' registers.
787+ d. Acquire the mailbox lock.
788+ e. Write DMA widget 'Control' register.
789+ - Set `Read Route` bits to 0x1 (AXI RD -> Mailbox)
790+ - Set `Read Addr fixed` bit.
791+ - Set Bit0 (GO)
792+ f. Read DMA widget `Status0` register in a loop if `Busy' bit is 0.
793+ g. Image is downloaded into mailbox sram.
794+7. Set RI `DEVICE_STATUS` register, `Device Status` field to 0x4 (`Recovery Pending (waiting for activation)`)
795+8. Loop on RI `RECOVERY_CTRL` register `Activate Recovery Image` field to wait for processing the image.
796+9. Set RI `RECOVERY_STATUS` register `Device Recovery Status` field to 0x2 (`Booting recovery image`).
797+10. Validate the image per the [Image Validation Process](#firmware-image-validation-process).
798+11. Reset the `RECOVERY_CTRL` register `Activate Recovery Image` field by writing 0x1.
799+12. If the validation is succesful, set the `DEVICE_STATUS` register `Device Status` field to 0x5 (`Running Recovery Image ( Recover Reason Code not populated)`)
800+13. If the validation fails, set the `RECOVERY_STATUS` register `Device Recovery Status` field to 0xc (`Recovery failed`) and `DEVICE_STATUS` register `Device Status` field to 0xF (`Fatal Error (Recover Reason Code not populated)`).
801+14. Release the mailbox lock.
802+
803+#### Image validation
418804
419805 See Firmware [Image Validation Process](#firmware-image-validation-process).
420806
807+### Derivation of the key ladder for Stable Identity
808+
809+Stable Identity calls for a secret that remains stable across firmware updates, but which can ratchet forward when major firmware vulnerabilities are fixed. Caliptra ROM implements this feature in terms of a "key ladder".
810+
811+The key ladder is initialized from the LDevID CDI during cold-boot. The key ladder length is inversely related to the firmware's SVN. Each step of the ladder is an SVN-unique key. The key for SVN X can be obtained by applying a one-way cryptographic operation to the key for SVN X+1. In this manner, firmware with a given SVN can wield keys bound to its SVN or older, but cannot wield keys bound to newer SVNs.
812+
813+To comply with FIPS, the one-way cryptographic operation used to compute keys is an SP 800-108 KDF.
814+
815+When the key ladder is initialized at cold-boot, it is bound to the lifecycle state and debug-locked. This ensures that the keys of the ladder will change across lifecycle or debug state transtions.
816+
817+Across update-resets, ROM tracks the minimum SVN that has run since cold-boot. It ensures that the ladder's length always corresponds to that minimum SVN. The key ladder can only be shortened (and thereby give access to newer SVNs' keys) by cold-booting into firmware with a newer SVN and re-initializing the ladder.
818+
819+#### Cold-boot
820+
821+ROM initializes a key ladder for the firmware. LDevID CDI in Key Vault Slot6 is used as an HMAC Key, and the data is a fixed string. The resultant MAC is stored in Slot 2.
822+
823+ KeyLadderContext = lifecycle state || debug_locked state
824+
825+ hmac512_kdf(KvSlot6, label: b"si_init", context: KeyLadderContext, KvSlot2)
826+
827+ Loop (MAX_FIRMWARE_SVN - (current firmware SVN)) times:
828+
829+ hmac512_kdf(KvSlot2, label: b"si_extend", context: None, KvSlot2)
830+
831+#### Update-reset
832+
833+During update-reset, the key ladder initialized at cold boot is lengthened if necessary, such that its length always corresponds with the minimum SVN since cold boot.
834+
835+ old_min_svn = [retrieved from data vault]
836+ new_min_svn = min(old_min_svn, new_fw_svn)
837+ [store new_min_svn in data vault]
838+
839+ Loop (`old_min_svn` - `new_min_svn`) times:
840+
841+ hmac512_kdf(KvSlot2, label: b"si_extend", context: None, KvSlot2)
842+
421843 ### Alias FMC DICE layer & PCR extension
422844
423845 Alias FMC Layer includes the measurement of the FMC and other security states. This layer is used to assert a composite identity which includes the security state, FMC measurement along with the previous layer identities.
@@ -425,11 +847,12 @@
425847 **Pre-conditions:**
426848
427849 - LDevID CDI is stored in Key Vault Slot 6
428-- LDevID Private Key is stored in Key Vault Slot 5
850+- LDevID MLDSA Key Pair Seed is stored in Key Vault Slot 4
851+- LDevID ECDSA Private Key is stored in Key Vault Slot 5
429852 - Firmware Image Bundle is successfully loaded and verified from the Mailbox
430853 - ROM has following information from Firmware Image Bundle
431854 - FMC_DIGEST - Digest of the FMC
432-- FMC_SVN - SVN for FMC
855+- FW_SVN - SVN for the firmware
433856 - MANUFACTURER_PK - Manufacturer Public Key(s) used to verify the firmware image bundle
434857 - MANUFACTURER_PK_INDEX - Index of the MANUFACTURER_PK in the firmware image bundle
435858
@@ -443,11 +866,11 @@
443866 CPTRA_SECURITY_STATE.LIFECYCLE_STATE,
444867 CPTRA_SECURITY_STATE.DEBUG_ENABLED,
445868 FUSE_ANTI_ROLLBACK_DISABLE,
446- ECC_VENDOR_PK_INDEX,
447- FMC_SVN,
448- FMC_FUSE_SVN (or 0 if `FUSE_ANTI_ROLLBACK_DISABLE`),
449- LMS_VENDOR_PK_INDEX,
450- ROM_VERIFY_CONFIG,
869+ VENDOR_ECC_PK_INDEX,
870+ FW_SVN,
871+ FW_FUSE_SVN (or 0 if `FUSE_ANTI_ROLLBACK_DISABLE`),
872+ VENDOR_PQC_PK_INDEX,
873+ PQC_KEY_TYPE,
451874 OWNER_PK_HASH_FROM_FUSES (0 or 1),
452875 ])
453876 pcr_extend(Pcr0 && Pcr1, MANUFACTURER_PK)
@@ -456,93 +879,176 @@
456879 pcr_lock_clear(Pcr0 && Pcr1)
457880 ```
458881
459-2. CDI for Alias is derived from PCR0. For the Alias FMC CDI Derivation, LDevID CDI in Key Vault Slot6 is used as HMAC Key and contents of PCR0 are used as data. The resultant mac is stored back in Slot 6.
882+2. CDI for Alias is derived from PCR0. For the Alias FMC CDI Derivation, LDevID CDI in Key Vault Slot6 is used as HMAC Key and contents of PCR0 are used as data. The resultant MAC is stored back in Slot 6.
460883
461884 `Pcr0Measurement = pcr_read(Pcr0)`
462- `hmac384_kdf(KvSlot6, b"fmc_alias_cdi", Pcr0Measurement, KvSlot6)`
463-
464-3. Derive Alias FMC ECC Key Pair using CDI in Key Vault Slot6 and store the generated private key in KeySlot7.
465-
466- `AliasFmcSeed = hmac384_kdf(KvSlot6, b"fmc_alias_keygen", KvSlot3)`
467- `AliasFmcPubKey = ecc384_keygen(KvSlot3, KvSlot7)`
885+
886+ `hmac512_kdf(KvSlot6, label: b"alias_fmc_cdi", context: Pcr0Measurement, KvSlot6)`
887+
888+3. Derive Alias FMC ECDSA Key Pair using CDI in Key Vault Slot 6 and store the generated private key in Key Vault Slot 7.
889+
890+ `AliasFmcSeedEcdsa = hmac512_kdf(KvSlot6, b"fmc_alias_ecc_key", KvSlot3)`
891+
892+ `AliasFmcPubKeyEcdsa = ecc384_keygen(KvSlot3, KvSlot7)`
893+
468894 `kv_clear(KvSlot3)`
469895
470-4. Store and lock (for write) the FMC Public Key in Data Vault (48 bytes) Slot 6 & Slot 7
471-
472- `dv48_store(FmcPubKey.X, Dv48Slot6)`
473- `dv48_lock_wr(Dv48Slot6)`
474- `dv48_store(FmcPubKey.Y, Dv48Slot7)`
475- `dv48_lock_wr(Dv48Slot7)`
476-
477-5. Generate the `To Be Signed` DER Blob of the Alias FMC Certificate
478-
479- `AliasFmcTbs = gen_cert_tbs(ALIAS_FMC_CERT, LDevIdPubKey, AliasFmcPubKey)`
480-
481-6. Sign the Alias FMC `To Be Signed` DER Blob with LDevId Private Key in Key Vault Slot 5
482-
483- `AliasFmcTbsDigest = sha384_digest(AliasFmcTbs)`
484- `AliasFmcTbsCertSig = ecc384_sign(KvSlot5, AliasFmcTbsDigest)`
485-
486-7. Clear the LDevId Private Key in Key Vault Slot 5
896+ Derive the Alias FMC MLDSA Key Pair using CDI in Key Vault Slot 6 and store the key pair generation seed in Key Vault Slot 8.
897+
898+ `AliasFmcSeedMldsa = hmac512_kdf(KvSlot6, b"fmc_alias_mldsa_key", KvSlot8)`
899+
900+ `AliasFmcPubKeyMldsa = mldsa87_keygen(KvSlot8)`
901+
902+4. Store and lock (for write) the FMC ECDSA and MLDSA Public Keys in the DCCM datavault.
903+
904+5. Generate the `To Be Signed` DER Blob of the ECDSA Alias FMC Certificate.
905+
906+ `AliasFmcTbsEcdsa = gen_cert_tbs(ALIAS_FMC_CERT, LDevIdPubKeyEcdsa, AliasFmcPubKeyEcdsa)`
907+
908+6. Sign the Alias FMC `To Be Signed` DER Blob with the LDevId ECDSA Private Key in Key Vault Slot 5.
909+
910+ `AliasFmcTbsDigestEcdsa = sha384_digest(AliasFmcTbsEcdsa)`
911+
912+ `AliasFmcTbsCertSigEcdsa = ecc384_sign(KvSlot5, AliasFmcTbsDigestEcdsa)`
913+
914+7. Clear the LDevId Private Key in Key Vault Slot 5.
487915
488916 `kv_clear(KvSlot5)`
489917
490-8. Verify the signature of Alias FMC `To Be Signed` Blob
491-
492- `AliasFmcTbsDigest = sha384_digest(AliasFmcTbs)`
493- `Result = ecc384_verify(AliasFmcPubKey, AliasFmcDigest , AliasFmcTbsCertSig)`
494-
495-9. Store and lock (for write) the LDevID Certificate Signature in the sticky Data Vault (48 bytes) Slot 4 and Slot 5
496-
497- `dv48_store(FmcTbsCertSig.R, Dv48Slot4)`
498- `dv48_lock_wr(Dv48Slot4)`
499-
500- `dv48_store(FmcTbsCertSig.S, Dv48Slot5)`
501- `dv48_lock_wr(Dv48Slot5)`
502-
503-10. Lock critical state needed for warm and update reset in Data Vault
504-
505- `dv48_store(FMC_DIGEST, Dv48Slot8)`
506- `dv48_lock_wr(Dv48Slot8)`
507-
508- `dv4_store(FMC_SVN, Dv4Slot0)`
509- `dv4_lock_wr(Dv4Slot0)`
510-
511- `dv48_store(FUSE_OWNER_PK_HASH, Dv48Slot9)`
512- `dv48_lock_wr(Dv48Slot9)`
513-
514- `dv4_store(MANUFACTURER_ECC_PK_INDEX, Dv4Slot3)`
515- `dv4_lock_wr(Dv4Slot3)`
516-
517- `dv4_store(MANUFACTURER_LMS_PK_INDEX, Dv4Slot4)`
518- `dv4_lock_wr(Dv4Slot4)`
519- **Note**: If LMS validation is not enabled, a value of 0xFFFFFFFF is stored.
520-
521- `dv4_store(ROM_COLD_BOOT_STATUS, Dv4Slot1)`
522- `dv4_lock_wr(Dv4Slot1)`
918+8. Verify the signature of Alias FMC `To Be Signed` ECDSA Blob.
919+
920+ `Result = ecc384_verify(LDevIdPubKeyEcdsa, AliasFmcDigestEcdsa, AliasFmcTbsCertSigEcdsa)`
921+
922+9. Generate the `To Be Signed` DER Blob of the MLDSA Alias FMC Certificate.
923+
924+ `AliasFmcTbsMldsa = gen_cert_tbs(ALIAS_FMC_CERT, LDevIdPubKeyMldsa, AliasFmcPubKeyMldsa)`
925+
926+10. Sign the Alias FMC `To Be Signed` DER Blob with the LDevId MLDSA Private Key generated from the seed in Key Vault Slot 4.
927+
928+ `AliasFmcTbsDigestMldsa = sha512_digest(AliasFmcTbsMldsa)`
929+
930+ `AliasFmcTbsCertSigMldsa = mldsa87_sign(KvSlot4, AliasFmcTbsDigestMldsa)`
931+
932+11. Clear the LDevId MLDSA key generation seed in Key Vault Slot 4.
933+
934+ `kv_clear(KvSlot4)`
935+
936+12. Verify the signature of Alias FMC `To Be Signed` MLDSA Blob.
937+
938+ `Result = mldsa87_verify(LDevIdPubKeyMldsa, AliasFmcDigestMldsa, AliasFmcTbsCertSigMldsa)`
939+
940+13. Store and lock (for write) the Alias FMC Certificate ECDSA and MLDSA Signatures in the DCCM datavault.
941+
942+14. Lock critical state needed for warm and update reset in the DCCM datavault.
943+
944+ `dccm_dv_store(FMC_DIGEST, lock_for_wr)`
945+
946+ `dccm_dv_store(FW_SVN, lock_for_wr)`
947+
948+ `dccm_dv_store(FUSE_OWNER_PK_HASH, lock_for_wr)`
949+
950+ `dccm_dv_store(MANUFACTURER_ECC_PK_INDEX, lock_for_wr)`
951+
952+ `dccm_dv_store(MANUFACTURER_PQC_PK_INDEX, lock_for_wr)`
953+
954+ `dccm_dv_store(ROM_COLD_BOOT_STATUS, lock_for_wr)`
955+
523956 **Note**: A value of 0x140 is stored on a successful cold boot.
524957
525958 **Post-conditions:**
526959
527960 - Vault state as follows:
528961
529-| Slot | Key Vault | Data Vault 48 Byte (Sticky) | Data Vault 4 Byte (Sticky) |
530-| ------ | ---------------------------------- | ------------------------------- | ---------------------------- |
531-| 0 || 🔒LDevID Cert Signature R | 🔒FMC SVN |
532-| 1 || 🔒LDevID Cert Signature S | 🔒ROM Cold Boot Status |
533-| 2 || 🔒LDevID Pub Key X | 🔒FMC Entry Point |
534-| 3 || 🔒LDevID Pub Key Y | 🔒Manufacturer ECC Public Key Index |
535-| 4 || 🔒Alias FMC Cert Signature R | 🔒Manufacturer LMS Public Key Index |
536-| 5 || 🔒Alias FMC Cert Signature S ||
537-| 6 | Alias FMC CDI (48 bytes) | 🔒Alias FMC Pub Key X ||
538-| 7 | Alias FMC Private Key (48 bytes) | 🔒Alias FMC Pub Key Y ||
539-| 8 || 🔒FMC Digest ||
540-| 9 || 🔒Owner PK Hash ||
541-
962+| Slot | Key Vault |
963+| ------ | ----------------------------------------------- |
964+| 0 | Stable identity root IDevID secret (64 bytes) |
965+| 1 | Stable identity root LDevID secret (64 bytes) |
966+| 6 | Alias FMC CDI (48 bytes) |
967+| 7 | Alias FMC Private Key - ECDSA (48 bytes) |
968+| 8 | Alias FMC Key Pair Seed - MLDSA (32 bytes) |
969+
970+
971+| DCCM datavault |
972+| ---------------------------------------- |
973+| 🔒IDevID Cert ECDSA Signature |
974+| 🔒IDevID ECDSA Pub Key |
975+| 🔒IDevID Cert MLDSA Signature |
976+| 🔒IDevID MLDSA Pub Key |
977+| 🔒LDevID Cert ECDSA Signature R |
978+| 🔒LDevID Cert ECDSA Signature S |
979+| 🔒LDevID Cert MLDSA Signature |
980+| 🔒LDevID Pub Key ECDSA X |
981+| 🔒LDevID Pub Key ECDSA Y |
982+| 🔒LDevID Pub Key MLDSA |
983+| 🔒Alias FMC Cert ECDSA Signature R |
984+| 🔒Alias FMC Cert ECDSA Signature S |
985+| 🔒Alias FMC Cert MLDSA Signature |
986+| 🔒FW SVN |
987+| 🔒ROM Cold Boot Status |
988+| 🔒FMC Entry Point |
989+| 🔒Manufacturer ECDSA Public Key Index |
990+| 🔒Manufacturer PQC Public Key Index |
991+| 🔒Alias FMC ECDSA Pub Key X |
992+| 🔒Alias FMC ECDSA Pub Key Y |
993+| 🔒Alias FMC MLDSA Pub Key |
994+| 🔒FMC Digest |
995+| 🔒Owner PK Hash |
996+
997+
998+### Locking of memory regions and registers
999+ ROM locks the following entities to prevent any updates:
1000+
1001+ - **Cold Reset Unlockable values:**
1002+ These values are unlocked on a Cold Reset:
1003+ - FMC TCI
1004+ - FMC Entry Point
1005+ - Owner Pub Key Hash
1006+ - Ecc Vendor Pub Key Index
1007+ - PQC Vendor Pub Key Index
1008+ - ROM Cold Boot Status
1009+
1010+ - **Warm Reset unlockable values:**
1011+ These values are unlocked on a Warm or Cold Reset:
1012+ - RT TCI
1013+ - RT Entry Point
1014+ - FW SVN
1015+ - Manifest Addr
1016+ - ROM Update Reset Status
1017+
1018+ - **PCR values**
1019+ - FMC_CURRENT
1020+ - FMC_JOURNEY
1021+ - STASH_MEASUREMENT
1022+
1023+ - **ICCM**
1024+
1025+### Launch FMC
1026+The ROM initializes and populates the Firmware Handoff Table (FHT) to relay essential parameters to the FMC. The format of the FHT is documented [here](https://github.com/chipsalliance/caliptra-sw/blob/main-2.x/fmc/README.md#firmware-handoff-table). Upon successful population, the ROM transfers execution control to the FMC.
5421027
5431028 ## Warm reset flow
1029+ROM does not perform any DICE derivations or firmware validation during warm reset.
5441030
5451031 ![WARM RESET](../images/caliptra-sw/rom/dev/doc/svg/warm-reset.svg)
1032+
1033+### Initialization
1034+ROM performs the same initialization sequence as specified [here](#Initialization)
1035+
1036+### Locking of memory regions and registers
1037+ROM locks the following entities to prevent any updates:
1038+
1039+ - **Warm Reset unlockable values:**
1040+ - RT TCI
1041+ - RT Entry Point
1042+ - FW SVN
1043+ - Manifest Addr
1044+ - ROM Update Reset Status
1045+
1046+ - **PCR values**
1047+ - FMC_CURRENT
1048+ - FMC_JOURNEY
1049+ - STASH_MEASUREMENT
1050+
1051+ - **ICCM**
5461052
5471053 ## Update reset flow
5481054
@@ -551,30 +1057,48 @@
5511057
5521058 ## Unknown/spurious reset flow
5531059
1060+### Initialization
1061+ROM performs the same initialization sequence as specified [here](#Initialization)
1062+
1063+### Error handling
1064+The ROM executes the following operations:
1065+ - Updates the `cptra_fw_error_fatal` and `cptra_fw_error_non_fatal` registers with the error code ROM_UNKNOWN_RESET_FLOW (0x01040020) error code.
1066+ - Zeroizes the following cryptographic hardware modules:
1067+ - Ecc384
1068+ - Hmac384
1069+ - Sha256
1070+ - Sha384
1071+ - Sha2-512-384Acc
1072+ - KeyVault
1073+ - Stops the WatchDog Timer.
1074+ - Enters an infinite loop, awaiting a reset.
1075+<br><br>
1076+
5541077 ![UNKNOWN RESET](../images/caliptra-sw/rom/dev/doc/svg/unknown-reset.svg)
5551078
5561079 ## Firmware image validation process
5571080
5581081 The basic flow for validating the firmware involves the following:
5591082
560-- Validate the manufacturing keys in the preamble
561-- Validate the owner keys in the preamble
562-- Select the manufacturer keys
563-- Once both the validations are complete, download the header from the mailbox.
564-- Validate the Manifest Header using the selected Manufacturer keys against the manufacturer signature.
565-- Validate the Manifest Header using the owner key(s) against the owner signature.
566-- On the completion of the last two validations, it is assured that the header portion is authentic.
567-- Load both the TOC entries from the mailbox.
568-- Validate the downloaded TOC data against the TOC hash in the header.
569-- This marks the TOC data as valid. The next step is to use the TOC Hash to validate image sections.
570-- Download the FMC Image portion of the Image.
571-- Validate the FMC Image against the hash in the TOC entry for the FMC.
1083+- Validating the manufacturer key descriptors in the preamble.
1084+- Validating the active manufacturer keys with the corresponding hash in the key descriptors.
1085+- Validating the owner key descriptors in the preamble.
1086+- Validating the owner keys with the hash in the key descriptors.
1087+- Validating the active manufacturer keys against the key revocation fuses.
1088+- Validating the Manifest Header using the active manufacturer keys against the manufacturer signatures.
1089+- Validating the Manifest Header using the owner keys against the owner signatures.
1090+- On the completion of these validations, it is assured that the header portion is authentic.
1091+- Loading the FMC and Rutime (RT) TOC entries from the mailbox.
1092+- Validating the TOCs against the TOC hash in the header.
1093+- On successful validation, it is assured that the TOCs are valid. The next step is to use the Hash entry in the TOCs to validate the image sections.
1094+- Downloading the FMC Image portion of the firmware Image.
1095+- Validating the FMC Image against the hash in the TOC entry for the FMC.
5721096 - If this is a cold reset, the FMC version number should be stored in a register.
573-- Download the RT Image part of the firmware Image.
574-- Validate the RT Image against the hash in the TOC entry for the RT.
575-- If all the above validations are complete, the entire image is validated.
576-- Let the SOC know that the firmware download command is complete.
577-- On failure, a non-zero status code will be reported in the `CPTRA_FW_ERROR_FATAL` register
1097+- Downloading the RT Image part of the firmware Image.
1098+- Validating the RT Image against the hash in the TOC entry for the RT.
1099+- On the successful completion of these validations, the entire image is validated.
1100+- Indicating to the SOC of validation success by completing the mailbox command.
1101+- On validation failure, reporting the appropriate error in the `CPTRA_FW_ERROR_FATAL` register and invoking the [error handler](#Error-handling)
5781102
5791103 ### **Overall validation flow**
5801104
@@ -586,13 +1110,13 @@
5861110
5871111 - Caliptra has transitioned through the BOOTFSM and all the fuses that are required for the validation are already populated by SOC.
5881112 - The FUSES programmed by the soc are
589- - fuse_key_manifest_pk_hash : This fuse contains the hash of the manufacturer keys present in preamble.
590- - fuse_key_manifest_pk_hash_mask : This is the bitmask of the ECC keys which are revoked.
1113+ - fuse_vendor_pk_hash : This fuse contains the hash of the manufacturer key descriptors present in the preamble.
1114+ - fuse_ecc_revocation : This is the bitmask of the ECC keys which are revoked.
5911115 - fuse_lms_revocation : This is the bitmask of the LMS keys which are revoked.
592- - fuse_owner_pk_hash : The hash of the owner public key(s) in preamble.
593- - fuse_lms_verify: This fuse indicates if verification with LMS key is enabled.
594- - fuse_key_manifest_svn : Used in FMC validation to make sure that the version number is good.
595- - fuse_runtime_svn : Used in RT validation to make sure that the runtime image's version number is good.
1116+ - fuse_mldsa_revocation : This is the bitmask of the MLDSA keys which are revoked.
1117+ - fuse_owner_pk_hash : The hash of the owner public keys in preamble.
1118+ - fuse_firmware_svn : Used in FW validation to make sure that the firmware image's SVN is good.
1119+ - fuse_pqc_key_type: This bitmask specifies the enabled PQC key type for firmware validation, indicating either MLDSA or LMS.
5961120 - The SOC has written the data to the mailbox.
5971121 - The SOC has written the data length in the DLEN mailbox register.
5981122 - The SOC has put the FW_DOWNLOAD command in the command register.
@@ -602,32 +1126,29 @@
6021126 ## Preamble validation: Validate the manufacturing keys
6031127
6041128 - Load the preamble bytes from the mailbox.
605-- There are four ECC and thirty-two LMS manufacturing keys in the preamble.
606-- fuse_key_manifest_pk_hash is the fuse that contains the hash of all the ECC and LMS manufacturing keys.
607-- To validate the key region, take the hash of all the ECC and LMS keys and compare it against the hash in fuse.
608-- If the hash does not match, fail the image validation.
609-- If the hash matches, all the ECC and LMS keys are validated.
610-
611-### Preamble validation: Manufacturing key selection
612-
613-- Since there are four ECC key slots in the preamble, we will need to select one key out of four.
614-- fuse_key_manifest_pk_hash_mask is the mask which revokes an ECC key.
615- - If bit-0 is set, that key is disabled. All other higher bits which are zeros, are still enabled.
616- - If all the bits are zeros, all the keys are enabled.
617- - If bit-0 and bit-1 are set, all higher slot bits (2 and 3) are enabled.
618-- Select the key using the Public Key Index Hint field in the preamble. This key should not be disabled using the fuse_key_manifest_pk_hash_mask fuse.
619- - If the key is disabled, fail the validation.
620- - If the key is enabled, select the key.
621-- Repeat the above procedure for LMS keys using the fuse_lms_revocation for key revocation.
622-- At this time, we have validated all the four ECC and thirty-two LMS keys and selected the ECC and LMS key that will be used for validation of the header against the manufacturer header signature field.
623-
624-### Preamble validation: Validate the owner key
625-
626-- There is one slot each for the owner ECC and LMS keys in the image preamble.
627-- fuse_owner_pk_hash contains the hash of the owner public keys.
628-- The validation of owner public keys is done by hashing the owner public keys from the preamble and comparing the hash against the value in the fuse_owner_pk_hash.
629-- If the hash matches, the owner public keys are valid.
630-- If the hash match fails, fail the image validation.
1129+- Based on the firmware image type, the image includes an ECC key descriptor and either an LMS or MLDSA key descriptor within the preamble. The ECC descriptor encapsulates up to four ECC public key hashes, the LMS descriptor up to 32 public key hashes, and the MLDSA descriptor up to four MLDSA public key hashes.
1130+- The firmware image, depending on its type, incorporates an ECC key and either an LMS or MLDSA manufacturing public key within the preamble. These constitute the active public keys.
1131+- The fuse_vendor_pk_hash fuse holds the SHA2-384 hash of the ECC, and LMS or MLDSA manufacturing key descriptors.
1132+- The key descriptors are validated by generating a SHA2-384 hash of the ECC and LMS or MLDSA key descriptors and comparing it against the hash stored in the fuse. If the hashes do not match, the image validation fails.
1133+- Upon a successful hash match, the ECC, and LMS or MLDSA key descriptors are deemed valid.
1134+- Subsequently, the active manufacturer public keys are validated against one of the hashes in the key descriptors. The specific hash for comparison is identified by the active key indices.
1135+
1136+### Preamble validation: Manufacturing key validation
1137+
1138+- fuse_ecc_revocation serves as the bitmask for revoking ECC keys.
1139+ - If bit-n is set, the nth key is disabled. All other higher bits that are zeros indicate the keys are still enabled.
1140+ - If all the bits are zeros, all ECC keys remain enabled.
1141+- Ensure that the Active Key Index in the preamble is not disabled by the fuse_ecc_revocation fuse.
1142+ - If the key is disabled, the validation process fails.
1143+- Repeat the above procedure for LMS or MLDSA keys using the fuse_lms_revocation or fuse_mldsa_revocation fuses, respectively, for key revocation.
1144+
1145+### Preamble validation: Validate the Owner key
1146+
1147+- The preamble includes a designated slot for the owner ECC key and a slot for either LMS or MLDSA keys.
1148+- The fuse_owner_pk_hash contains the hash of the owner public keys.
1149+- The validation process for owner public keys involves generating a SHA2-384 hash from the owner public keys within the preamble and comparing it to the hash stored in the fuse_owner_pk_hash register.
1150+- If the computed hash matches the value in fuse_owner_pk_hash, the owner public keys are deemed valid.
1151+- If there is a hash mismatch, the image validation process fails.
6311152
6321153 ## Preamble validation steps
6331154
@@ -635,13 +1156,15 @@
6351156
6361157 ## Header validation
6371158
638-- Load the header portion of the firmware image from the mailbox.
639-- Header is the only signed component. There are two signatures generated for the header.
640-- First signature is generated using one of the manufacturing keys.
641-- Second signature is generated using the owner public key.
642-- To validate the header, hash and then verify that the ECC manufacturer signature in the preamble is for the hash.
643-- If the manufacturer signature matches, proceed with the owner signature validation. If the signature does not match, fail the validation. Repeat the same procedure with LMS manufacturer key if LMS verification is enabled.
644-- The hash is already generated. Verify the signature for the above hash using the ECC owner public key. Repeat the same procedure with LMS owner key if LMS verification is enabled.
1159+- Retrieve the header portion of the firmware image from the mailbox.
1160+- Note that the header is the sole signed component, featuring two distinct signatures pairs.
1161+- The first signature pair is generated using the active ECC and LMS or MLDSA manufacturing keys.
1162+- The second signature pair is generated using the owner ECC and LMS or MLDSA public keys.
1163+- To validate the header:
1164+ - Compute the SHA2-384 hash of the header.
1165+ - Verify the ECC manufacturer signature in the preamble against the computed hash.
1166+ - If the ECC manufacturer signature is invalid, fail the validation process. If the ECC manufacturer signature is valid, apply the same procedure using the LMS or MLDSA manufacturer key.
1167+ - Similarly, utilize the precomputed hash to verify the signature with the ECC owner public key. Repeat the process using the LMS or MLDSA owner key.
6451168
6461169 ## Header validation steps
6471170
@@ -649,13 +1172,12 @@
6491172
6501173 ## Table of contents validation
6511174
652-- At this point all the previous steps of validation are complete.
653-- The Preamble and the header are validated.
654-- Load both the TOCs (FMC TOC and RT TOC) from the mailbox.
655-- Generate the hash of the entire TOC data.
656-- Compare the hash of the TOC data with the hash in the header.
657-- If the hash matches, the TOC data is valid.
658-- Ensure that Fw.Svn >= Fuse.Svn.
1175+- At this point both the Preamble and the Header have been validated.
1176+- Load the TOC entries (FMC TOC and RT TOC) from the mailbox.
1177+- Compute the SHA2-384 hash of the complete TOC data.
1178+- Compare the computed TOC hash with the hash embedded in the Header.
1179+ - If the hashes match, the TOC data is validated.
1180+- Ensure that Fw.Svn is greater than or equal to Fuse.Svn.
6591181
6601182 <br> *(Note: Same SVN Validation is done for the FMC and RT)
6611183
@@ -667,16 +1189,16 @@
6671189
6681190 ## Validating image sections
6691191
670-- Once the TOC is validated, the image section associated with each TOC needs validation.
671-- The hash for each image section is stored in the TOC data.
672-- Load the FMC Image section. The Offset and the size of the section is present in TOC.
673-- Calculate the SHA-384 hash of the FMC image section.
674-- Compare the hash with the hash available in the FMC TOC.
675-- If the hash matches, the FMC image section is validated. If the hash does not match, reject the image.
676-- Load the RT Image section from the mail box. The offset and the size of the section is present in the TOC.
677-- Calculate the SHA-384 hash of the RT image section.
678-- Compare the hash with the hash in the RT TOC.
679-- If the hash matches, the RT image section is validated. If the hash does not match, reject the image.
1192+- Upon successful validation of the TOC, each image section corresponding to the TOC requires validation.
1193+- The hash for each image section is encapsulated within the TOC data.
1194+- Retrieve the FMC Image section. The offset and size of the section are specified in the TOC.
1195+- Compute the SHA2-384 hash for the FMC image section.
1196+- Compare the computed hash with the hash specified in the FMC TOC.
1197+ - If the hashes match, the FMC image section is considered validated. If the hashes do not match, the image is rejected.
1198+- Retrieve the RT Image section from the mailbox. The offset and size of the section are specified in the TOC.
1199+- Compute the SHA2-384 hash for the RT image section.
1200+Compare the computed hash with the hash specified in the RT TOC.
1201+ - If the hashes match, the RT image section is considered validated. If the hashes do not match, the image is rejected.
6801202
6811203 ## Image section validation steps
6821204
@@ -693,17 +1215,21 @@
6931215 - Save the hash of the FMC portion of the image in a separate register.
6941216 - Copy the FMC and RT image's text and data section in the appropriate ICCM and DCCM memory regions.
6951217 - The data vault is saved with the following values:-
696- - LDevId Dice Signature.
697- - LDevId Dice Public Key.
698- - Fmc Dice Signature.
699- - Fmc Public Key.
1218+ - LDevId Dice ECDSA Signature.
1219+ - LDevId Dice MLDSA Signature.
1220+ - LDevId Dice ECDSA Public Key.
1221+ - LDevId Dice MLDSA Public Key.
1222+ - Alias FMC Dice ECDSA Signature.
1223+ - Alias FMC Dice MLDSA Signature.
1224+ - Alias FMC Public ECDSA Key.
1225+ - Alias FMC Public MLDSA Key.
7001226 - Digest of the FMC part of the image.
701- - Digest of the ECC and LMS owner public keys portion of preamble.
702- - FMC SVN.
1227+ - Digest of the ECC and LMS or MLDSA owner public keys portion of preamble.
1228+ - FW SVN.
7031229 - ROM Cold Boot Status.
704- - Fmc Entry Point.
1230+ - FMC Entry Point.
7051231 - ECC Vendor public key index.
706- - LMS Vendor public key index.
1232+ - LMS or MLDSA Vendor public key index.
7071233 - Warm Boot Mode
7081234 - In this mode there is no validation or load required for any parts of the image.
7091235 - All the contents of ICCM and DCCM are preserved.
@@ -718,6 +1244,8 @@
7181244 - Validate the toc exactly like in cold boot.
7191245 - We still need to make sure that the digest of the FMC which was stored in the data vault register at cold boot
7201246 still matches the FMC image section.
1247+ - Store the minimum firmware SVN that has run since cold-boot in the data vault.
1248+ - Ratchet the key ladder if necessary.
7211249 - If validation fails during ROM boot, the new RT image will not be copied from
7221250 the mailbox. ROM will boot the existing FMC/Runtime images. Validation
7231251 errors will be reported via the CPTRA_FW_ERROR_NON_FATAL register.
@@ -742,3 +1270,24 @@
7421270 - The image builder exposes the argument "fake" that can be used to generate the fake versions
7431271
7441272 To fully boot to runtime, the fake version of FMC should also be used. Details can be found in the FMC readme.
1273+
1274+## Optional UART via Generic Output Wires
1275+
1276+For debugging and development purposes, the ROM (when built with the `emu` feature) can output log messages using the `CPTRA_GENERIC_OUTPUT_WIRES[0]` register as an optional UART interface. This provides a simple mechanism for observing ROM execution without requiring a dedicated UART peripheral.
1277+
1278+### Protocol
1279+
1280+The UART output uses the following encoding in `CPTRA_GENERIC_OUTPUT_WIRES[0]`:
1281+
1282+| Bits | Description |
1283+| :------ | :-------------------------------------------------------------------------- |
1284+| [7:0] | Character data (ASCII printable characters 0x20-0x7E, newline 0x0A, tab 0x09). Non-printable characters are replaced with 0xFE. |
1285+| [8] | Toggle bit. This bit is toggled every time a new character is written, allowing external observers to detect new characters without introspecting internal signals. |
1286+| [31:9] | Reserved |
1287+
1288+
1289+### Usage
1290+
1291+- The SOC or testbench can monitor `CPTRA_GENERIC_OUTPUT_WIRES[0]` and detect new characters by observing changes to bit 8.
1292+- When bit 8 changes, the new character is available in bits [7:0].
1293+- If desired, this can be wired to a FIFO or other mechanism for output.