From 99919dcdc6d257e24df12ec4bcbd4890d9764809 Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Fri, 15 Nov 2024 11:17:38 -0800 Subject: [PATCH 1/3] runtime docs: Remove storage from cryptographic mailbox Mostly. We need to keep a limited amount of storage per AES-256-GCM key to track usage, since these keys can only be used a certain number of times due to their IV problems. For HMAC, we don't specify a key usage on the output MAC, since it has to be imported back into Caliptra to be used as a key, where its usage will have to be specified. We also fix a few other minor issues with the mailbox documentation: Fixes #1753 Fixes #1754 Fixes #1755 Fixes #1756 --- runtime/README.md | 180 +++++++++++++++++++++++----------------------- 1 file changed, 92 insertions(+), 88 deletions(-) diff --git a/runtime/README.md b/runtime/README.md index d1b970062d..3f601b3ba0 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -84,10 +84,12 @@ the Runtime Firmware binary. ## Cryptographic Mailbox Commands (new in 2.0) Cryptographic mailbox (CM) commands are a flexible set of mailbox commands that provide access to Caliptra's cryptographic cabilities. -This is meant for key storage and use, supporting protocols like SPDM and OCP LOCK. +This is meant for offline key storage and use, supporting protocols like SPDM and OCP LOCK. These commands are not meant to be high-performance as they are accessed via mailbox commands. +CM itself does not provide any storage for the keys: when generated, they are returned to the caller in encrypted form, and must be passed back to be used. + These mailbox commands provide SHA, HMAC, HKDF, AES, and RNG services. Asymmetric cryptographic services are currently only provided through DPE and the `ECDSA384_SIGNATURE_VERIFY` and `LMS_SIGNATURE_VERIFY` mailbox commands, which do not use the CM storage system. @@ -106,56 +108,50 @@ The contexts contain the internal structures necessary to resume operations to s These contexts are intended to be opaque to the user, and SHALL be encrypted and authenticated if they contain sensitive internal data. -### Data Storage - -The CM system has its own dedicated storage in DCCM. - -This storage is protected with authenticated encryption using internal keys that are randomly generated at power on and stored in the key vault. - -This storage is exposed to users through opaque 256-bit handles, called cryptographic mailbox IDs (CMIDs). These are mapped internally into DCCM storage blocks. - -Keys can be imported using `CM_IMPORT` and deleted via `CM_DELETE`. - -The entire contents can be cleared with `CM_CLEAR`. +### Keys -The status of the data storage can be queried with `CM_STATUS`. +Cryptographic Mailbox Key (CMKs) are used to store keys. Certain commands generate and return a new CMK. Most commands that use CMKs will also return a new CMK, as it is necessary to track CMKs so that they are not used beyond any relevant limits for their key type. -### Storage Design +Caliptra will keep a limited amount of usage -Data is stored in 16-byte blocks. +They are returned from commands that generate keys and must be passed back to Caliptra to be used. These keys are encrypted and opaque to the mailbox caller. -Each block's status is tracked in a bitfield, 1 bit per block, with a value of 1 indicating that block is in use. +Internally, the unecrypted CMKs have the following structure: -For example, if we have 32 KB of storage for CM, this requires 256 bytes of additional storage. +| **Name** | **Bits** | **Description** | +| ------------- | -------- | ------------------------------------------- | +| version | 32 | CMK version. Currently always 1. | +| key usage | 32 | represents which kind of key this is | +| id | 32 | ID number | +| usage counter | 64 | how many times this key has been used | +| length | 32 | how many bits of key material are used | +| padding | 64 | reserved for now | +| key material | 512 | bits used for the key material | -### CMIDs +The CMKs AES-256-GCM encrypted with a 128-bit IV and tag. The total size of the encrypted CMK is therefore 128 bytes. -CMIDs offload storage of key metadata to mailbox callers. They therefore impose no additional storage within Caliptra Core. +The key used to encrypt the CMKS is derived from CDIRT with the info of `"CMK"`. -Unecrypted CMIDs have the following structure: +#### Key Usage -| **Name** | **Bits** | **Description** | -| ------------ | -------- | ------------------------------------------- | -| padding | 80 | 0 | -| block offset | 24 | Starting block number | -| size | 24 | Size (in bytes) of the data stored. | -| | | Does not have to be a multiple of 16 bytes. | +The internal CMK structure and several commands use a key usage tag to specify how a key can be used: -Hence, data for a single CMID must be stored contiguously. +| **Value** | **Usage** | +| ---------- | ----------- | +| 0 | Reserved | +| 1 | HMAC | +| 2 | HKDF | +| 3 | AES-256-GCM | -Padding is kept for additional future features. +#### Replay Prevention and Deletion -The CMIDs are AES-256-GCM encrypted, with a 128-bit ciphertext concatenated with the 128-bit AES-GCM tag. +To prevent replay attacks, Caliptra will have a small table that maps a CMK's internal ID to its last known usage counters. +Whenever a CMK is used, this table is checked and updated. -### Storage Keys +This is necessary for AES-256-GCM in particular to ensure that keys are only used a certain number of times. +Only AES-256-GCM keys need to be tracked in this table. -The key for the data referenced by a CMID is unique and derived via HKDF from the CDIRT with the info being the concatenation of `"CMID" || block offset || size`. - -The IV is the concatenation of `block offset || size`. - -This scheme avoids having to store the IV while avoiding IV reuse problems. - -GCM prevents an adversary from changing internal CMID parameters, such as changing an AES key to an ECDSA key, which has sensitive internal structure (although ECDSA is not currently supported). +This requires 96 bits of storage per AES-256-GCM key. These can stored as a sorted list to the DCCM requirements. ## Manifest-Based Image Authorization (new in 1.2) @@ -268,7 +264,8 @@ All mailbox command codes are little endian. | `BAD_SIG` | `0x4253_4947` ("BSIG") | Generic signature check failure (for crypto offload) | `BAD_IMAGE` | `0x4249_4D47` ("BIMG") | Malformed input image | `BAD_CHKSUM` | `0x4243_484B` ("BCHK") | Checksum check failed on input arguments -| `CME_BAD_CMID` | `0x434D_4249` ("CMBI") | Invalid CMID +| `CME_BAD_CMK` | `0x434D_424B` ("CMBK") | Invalid CMK +| `CME_CMK_OFLW` | `0x434D_424F` ("CMBO") | CMK has been used too many times | `CME_BAD_CTXT` | `0x434D_4243` ("CMBC") | Bad context | `CME_FULL` | `0x434D_4546` ("CMEF") | Cryptographic Mailbox Full @@ -1126,7 +1123,7 @@ Command Code: `0x434D_4849` ("CMHI") | **Name** | **Type** | **Description** | | -------------- | -------- | -------------------------------------- | | chksum | u32 | | -| Key CMID | u8[32] | CMID of key to use | +| CMK | u8[128] | CMK use as key | | hash algorithm | u32 | Enum. | | | | 0 = reserved | | | | 1 = SHA2-256 | @@ -1217,7 +1214,7 @@ Command Code: `0x434D_4B54` ("CMKT") | | | Value 1 = SHA2-256 | | | | Value 2 = SHA2-384 | | | | Value 3 = SHA2-512 | -| IKM CMID | u8[32] | Input key material CMID | +| IKM CMK | u8[32] | Input key material CMK | | salt length | u32 | May be 0 | | salt | u8[...] | | @@ -1226,7 +1223,7 @@ Command Code: `0x434D_4B54` ("CMKT") | ----------- | -------- | ------------------------------------------- | | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| PRK CMID | u8[32] | CMID that refers to the output (PRK) to use | +| PRK CMK | u8[32] | CMK that stores the output (PRK) to use | | | | with HKDF-Expand | ### CM_HKDF_EXPAND @@ -1236,25 +1233,26 @@ Implements HKDF-Expand as specified in [RFC 5869](https://www.rfc-editor.org/rfc Command Code: `0x434D_4B50` ("CMKP") *Table: `CM_HKDF_EXPAND` input arguments* -| **Name** | **Type** | **Description** | -| -------------- | -------- | ------------------------- | -| chksum | u32 | | -| hash algorithm | u32 | Enum. | -| | | Value 0 = reserved | -| | | Value 1 = SHA2-256 | -| | | Value 2 = SHA2-384 | -| | | Value 3 = SHA2-512 | -| PRK CMID | u8[32] | | -| Info length | u32 | | -| Info | u8[...] | | -| Output length | u32 | Number of bytes to output | +| **Name** | **Type** | **Description** | +| -------------- | -------- | ------------------------------------------------ | +| chksum | u32 | | +| hash algorithm | u32 | Enum. | +| | | Value 0 = reserved | +| | | Value 1 = SHA2-256 | +| | | Value 2 = SHA2-384 | +| | | Value 3 = SHA2-512 | +| PRK CMK | u8[128] | | +| key usage | u32 | usage tag of the kind of key that will be output | +| Info length | u32 | | +| Info | u8[...] | | +| Output length | u32 | Number of bytes to output | *Table: `CM_HKDF_EXPAND` output arguments* -| **Name** | **Type** | **Description** | -| ----------- | -------- | -------------------------------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | -| OKM CMID | u8[32] | CMID that stores refers to the output key material | +| **Name** | **Type** | **Description** | +| ----------- | -------- | ----------------------------------------| +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| OKM CMK | u8[128] | CMK that stores the output key material | ### CM_AES_GCM_ENCRYPT @@ -1269,27 +1267,35 @@ Command Code: `0x434D_4745` ("CMGE") | **Name** | **Type** | **Description** | | -------------- | -------- | ---------------------------------------- | | chksum | u32 | | -| flags | u32 | Bit 0 = this is the final message | -| key CMID | u8[32] | CMID of the key to use | +| flags | u32 | Bit 0 = this is the first message | +| | | Bit 1 = this is the final message | +| CMK | u8[128] | CMK of the key to use to encrypt | | tag size | u32 | Number of bytes to return for tag. | | | | Can be 0, 1, ..., 16 | | context size | u32 | Size of the context | | context | u8[...] | | | aad size | u32 | Additional authenticated data size | -| | | Must be 0 if this is not the first block | +| | | MUST be 0 if this is not the first block | | aad | u8[...] | Additional authenticated data | | plaintext size | u32 | | | plaintext | u8[...] | Data to encrypt | *Table: `CM_AES_GCM_ENCRYPT` output arguments* -| **Name** | **Type** | **Description** | -| -------------- | -------- | ----------------------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | -| context size | u32 | SHALL be 0 if this is the final message | -| context | u8[...] | | -| cipertext size | u32 | MAY be 0 if this is not the final message | -| ciphertext | u8[...] | | +| **Name** | **Type** | **Description** | +| -------------- | -------- | ---------------------------------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| CMK | u8[128] | New CMK. SHALL be 0 if this is not the first message | +| context size | u32 | SHALL be 0 if this is the final message | +| context | u8[...] | | +| iv | u8[12] | SHALL be 0 if this is not the first message | +| cipertext size | u32 | MAY be 0 if this is not the final message | +| ciphertext | u8[...] | | + +The CMK returned on the first message must be used for all future encryptions (though +either the old CMK or the new CMK may be used for the subsequent commands for this +encrypted stream). + The encrypted and authenticated context's internal structure will be: @@ -1306,6 +1312,8 @@ The encrypted and authenticated context's internal structure will be: Currently only supports AES-256-GCM with a 96-bit IV. +If the key material is larger than 256 bits, then it will be truncated before use. + Command Code: `0x434D_4744` ("CMGD") *Table: `CM_AES_GCM_DECRYPT` input arguments* @@ -1313,15 +1321,14 @@ Command Code: `0x434D_4744` ("CMGD") | --------------- | -------- | ---------------------------------------- | | chksum | u32 | | | flags | u32 | Bit 0 = this is the final message | -| key CMID | u8[32] | CMID of the key to use | +| CMK | u8[128] | CMK to use for decryption | | tag size | u32 | Number of bytes in the tag. | | | | Can be 0, 1, ..., 16 | | | | Must be 0 if this is not the first block | | tag | u8[...] | | | context size | u32 | Size of the context | | context | u8[...] | | -| iv size | u32 | 12 (first message) or 0 (subsequent) | -| iv | u8[...] | | +| iv | u8[12] | Ignored if not the first message | | aad size | u32 | Additional authenticated data size | | | | Must be 0 if this is not the first block | | aad | u8[...] | Additional authenticated data | @@ -1358,7 +1365,7 @@ Currently only supports the NIST P-384 curve. The returned context must be passed to the `CM_ECDH_FINISH` command. The context contains the (encrypted) secret coefficient. -The returned exchange data format is the concatenation of the x- and y-coordinates of the public point. +The returned exchange data format is the concatenation of the x- and y-coordinates of the public point encoded as big-endian integers, padded to 48 bytes each. Command Code: `0x434D_4547` ("CMEG") @@ -1390,7 +1397,7 @@ Currently only supports the NIST P-384 curve. The context must be passed from the `CM_ECDH_GENERATE` command. -The incoming exchange data MUST be the concatenation of the x- and y- coordinates of the other side's public point. +The incoming exchange data MUST be the concatenation of the x- and y- coordinates of the other side's public point, encoded as big-endian integers, padded to 48 bytes each. The produced shared secret is 384 bits. @@ -1402,6 +1409,7 @@ Command Code: `0x434D_4546` ("CMEF") | chksum | u32 | | | context size | u32 | size of context | | context | u8[...] | This MUST come from the output of the `CM_ECDH_GENERATE` | +| key usage | u32 | usage tag of the kind of key that will be output | | incoming exchange data | u8[96] | the other side's public point | *Table: `CM_ECDH_FINISH` output arguments* @@ -1409,7 +1417,7 @@ Command Code: `0x434D_4546` ("CMEF") | ----------- | -------- | -------------------------------- | | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| output CMID | u8[32] | Output CMID of the shared secret | +| output CMK | u8[128] | Output CMK of the shared secret | ### CM_RANDOM_STIR @@ -1456,9 +1464,9 @@ Command Code: `0x434D_5247` ("CMRG") ### CM_IMPORT -Imports the specified data and returns a CMID for it. +Imports the specified key and returns a CMK for it. -Usage information is required so that the data can be verified and used appropriately. +Usage information is required so that the key can be verified and used appropriately. Command Code: `0x434D_494D` ("CMIM") @@ -1467,9 +1475,7 @@ Command Code: `0x434D_494D` ("CMIM") | **Name** | **Type** | **Description** | | ---------- | -------- | ------------------------------------------ | | chksum | u32 | | -| usage | u32 | Tag to specify how the data can be used | -| | | 0 - Can be used for HMAC, HKDF, AES | -| | | MUST be 0. | +| key usage | u32 | Tag to specify how the data can be used | | input size | u32 | | | input | u8[...] | | @@ -1478,7 +1484,7 @@ Command Code: `0x434D_494D` ("CMIM") | ----------- | -------- | ---------------------------- | | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| CMID | u8[32] | CMID containing imported key | +| CMK | u8[128] | CMK containing imported key | ### CM_DELETE @@ -1491,7 +1497,7 @@ Command Code: `0x434D_444C` ("CMDL") | **Name** | **Type** | **Description** | | -------- | -------- | -------------------------- | | chksum | u32 | | -| CMID | u8[32] | CMID of the data to delete | +| CMK | u8[128] | CMK to delete | *Table: `CM_DELETE` output arguments* | **Name** | **Type** | **Description** | @@ -1501,7 +1507,7 @@ Command Code: `0x434D_444C` ("CMDL") ### CM_CLEAR -The entire contents of the CM storage is wiped. +The entire contents of the CMK storage is wiped. All known keys will be invalidated. Command Code: `0x434D_434C` ("CMCL") @@ -1515,9 +1521,7 @@ Command Code: `0x434D_434C` ("CMCL") ### CM_STATUS -Queries the status of the data storage used by the cryptographic mailbox system. - -Note that the free blocks returned may not all be usable as they may not be contiguous, and the count may not reflect the storage overhead, e.g., a 16-byte GCM tag is used per block. +Queries the status cryptographic mailbox system. Command Code: `0x434D_5354` ("CMST") @@ -1528,8 +1532,8 @@ Command Code: `0x434D_5354` ("CMST") | ------------ | -------- | ------------------------- | | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| free blocks | u32 | Available 16-byte blocks | -| total blocks | u32 | Total 16-byte blocks | +| free CMKs | u32 | Available CMKs | +| total CMKs | u32 | Total CMKs | ### GET\_IDEVID\_CSR From c6b1916fa8f6f1983fb6660006038a5b9e69227b Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Tue, 19 Nov 2024 19:40:40 -0800 Subject: [PATCH 2/3] Address PR feedback --- runtime/README.md | 304 +++++++++++++++++++++++++++++++--------------- 1 file changed, 209 insertions(+), 95 deletions(-) diff --git a/runtime/README.md b/runtime/README.md index 3f601b3ba0..70af4e8d62 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -84,7 +84,7 @@ the Runtime Firmware binary. ## Cryptographic Mailbox Commands (new in 2.0) Cryptographic mailbox (CM) commands are a flexible set of mailbox commands that provide access to Caliptra's cryptographic cabilities. -This is meant for offline key storage and use, supporting protocols like SPDM and OCP LOCK. +This is meant for offloaded key storage and use, supporting protocols like SPDM and OCP LOCK. These commands are not meant to be high-performance as they are accessed via mailbox commands. @@ -112,8 +112,6 @@ These contexts are intended to be opaque to the user, and SHALL be encrypted and Cryptographic Mailbox Key (CMKs) are used to store keys. Certain commands generate and return a new CMK. Most commands that use CMKs will also return a new CMK, as it is necessary to track CMKs so that they are not used beyond any relevant limits for their key type. -Caliptra will keep a limited amount of usage - They are returned from commands that generate keys and must be passed back to Caliptra to be used. These keys are encrypted and opaque to the mailbox caller. Internally, the unecrypted CMKs have the following structure: @@ -128,9 +126,21 @@ Internally, the unecrypted CMKs have the following structure: | padding | 64 | reserved for now | | key material | 512 | bits used for the key material | -The CMKs AES-256-GCM encrypted with a 128-bit IV and tag. The total size of the encrypted CMK is therefore 128 bytes. +The encrypted CMKs have the structure: + +| **Name** | **Bits** | **Description** | +| ------------- | -------- | ------------------------------ | +| padding | 32 | reserved | +| iv | 96 | | +| ciphertext | 768 | encrypted CMK data (see above) | +| GCM tag | 128 | | + +The total size of the CMK is therefore 128 bytes. + +Only the encrypted CMKs will appear in mailbox messages. -The key used to encrypt the CMKS is derived from CDIRT with the info of `"CMK"`. +The key used to encrypt the CMKs is randomized on reset, which means that CMKS cannot be used between resets. +The iv is a randomized 1-up counter that is incremented for every key created. #### Key Usage @@ -148,7 +158,7 @@ The internal CMK structure and several commands use a key usage tag to specify h To prevent replay attacks, Caliptra will have a small table that maps a CMK's internal ID to its last known usage counters. Whenever a CMK is used, this table is checked and updated. -This is necessary for AES-256-GCM in particular to ensure that keys are only used a certain number of times. +This is necessary for AES-256-GCM in particular to ensure that keys are only used a certain number of times, as per [NIST SP 800-38D, Section 8.3](https://doi.org/10.6028/NIST.SP.800-38D). Only AES-256-GCM keys need to be tracked in this table. This requires 96 bits of storage per AES-256-GCM key. These can stored as a sorted list to the DCCM requirements. @@ -1117,13 +1127,15 @@ The sequence to use these are: For each command, the context from the previous command's output must be passed as an input. +The CMK must have been created for HMAC / HKDF usage. + Command Code: `0x434D_4849` ("CMHI") *Table: `CM_HMAC_INIT` input arguments* | **Name** | **Type** | **Description** | | -------------- | -------- | -------------------------------------- | | chksum | u32 | | -| CMK | u8[128] | CMK use as key | +| CMK | CMK | CMK use as key | | hash algorithm | u32 | Enum. | | | | 0 = reserved | | | | 1 = SHA2-256 | @@ -1203,6 +1215,8 @@ Command Code: `0x434D_4846` ("CMHF") Implements HKDF-Extract as specified in [RFC 5869](https://www.rfc-editor.org/rfc/rfc5869.html). +The CMK must have been created for HMAC / HKDF usage. + Command Code: `0x434D_4B54` ("CMKT") *Table: `CM_HKDF_EXTRACT` input arguments* @@ -1230,6 +1244,10 @@ Command Code: `0x434D_4B54` ("CMKT") Implements HKDF-Expand as specified in [RFC 5869](https://www.rfc-editor.org/rfc/rfc5869.html). +The CMK must have been created for HMAC / HKDF usage. + +The output length will be automatically chosen to match the key usage. + Command Code: `0x434D_4B50` ("CMKP") *Table: `CM_HKDF_EXPAND` input arguments* @@ -1241,121 +1259,217 @@ Command Code: `0x434D_4B50` ("CMKP") | | | Value 1 = SHA2-256 | | | | Value 2 = SHA2-384 | | | | Value 3 = SHA2-512 | -| PRK CMK | u8[128] | | +| PRK CMK | CMK | | | key usage | u32 | usage tag of the kind of key that will be output | | Info length | u32 | | | Info | u8[...] | | -| Output length | u32 | Number of bytes to output | *Table: `CM_HKDF_EXPAND` output arguments* | **Name** | **Type** | **Description** | | ----------- | -------- | ----------------------------------------| | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| OKM CMK | u8[128] | CMK that stores the output key material | +| OKM CMK | CMK | CMK that stores the output key material | -### CM_AES_GCM_ENCRYPT +### CM_AES_GCM_ENCRYPT_INIT Currently only supports AES-256-GCM with a random 96-bit IV. -If the key material is larger than 256 bits, then it will be truncated before use. +The CMK must have been created for AES usage. -Command Code: `0x434D_4745` ("CMGE") +Command Code: `0x434D_4749` ("CMGI") -*Table: `CM_AES_GCM_ENCRYPT` input arguments* +*Table: `CM_AES_GCM_ENCRYPT_INIT` input arguments* | **Name** | **Type** | **Description** | | -------------- | -------- | ---------------------------------------- | | chksum | u32 | | -| flags | u32 | Bit 0 = this is the first message | -| | | Bit 1 = this is the final message | -| CMK | u8[128] | CMK of the key to use to encrypt | -| tag size | u32 | Number of bytes to return for tag. | -| | | Can be 0, 1, ..., 16 | -| context size | u32 | Size of the context | -| context | u8[...] | | +| CMK | CMK | CMK of the key to use to encrypt | | aad size | u32 | Additional authenticated data size | -| | | MUST be 0 if this is not the first block | | aad | u8[...] | Additional authenticated data | | plaintext size | u32 | | | plaintext | u8[...] | Data to encrypt | -*Table: `CM_AES_GCM_ENCRYPT` output arguments* -| **Name** | **Type** | **Description** | -| -------------- | -------- | ---------------------------------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | -| CMK | u8[128] | New CMK. SHALL be 0 if this is not the first message | -| context size | u32 | SHALL be 0 if this is the final message | -| context | u8[...] | | -| iv | u8[12] | SHALL be 0 if this is not the first message | -| cipertext size | u32 | MAY be 0 if this is not the final message | -| ciphertext | u8[...] | | - -The CMK returned on the first message must be used for all future encryptions (though -either the old CMK or the new CMK may be used for the subsequent commands for this -encrypted stream). - +*Table: `CM_AES_GCM_ENCRYPT_INIT` output arguments* +| **Name** | **Type** | **Description** | +| -------------- | -------- | ------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| context size | u32 | | +| context | u8[...] | | +| iv | u8[12] | | +| cipertext size | u32 | MAY be 0 | +| ciphertext | u8[...] | | The encrypted and authenticated context's internal structure will be: -*Table: `CM_AES_GCM_ENCRYPT` internal context* +*Table: internal context for CM_AES_GCM_ENCRYPT_* operations* | **Name** | **Type** | **Description** | | --------------- | -------- | --------------- | -| tag size | u32 | | +| key | u8[32] | | | last length | u32 | | | last counter | u8[16] | | | last GHASH | u8[16] | | | last ciphertext | u8[16] | | -### CM_AES_GCM_DECRYPT +### CM_AES_GCM_ENCRYPT_UPDATE -Currently only supports AES-256-GCM with a 96-bit IV. +This continues an AES computation started by `CM_AES_GCM_ENCRYPT_INIT` or from another `CM_AES_GCM_ENCRYPT_UPDATE`. + +The context MUST be passed in from `CM_AES_GCM_ENCRYPT_INIT` or `CM_AES_GCM_ENCRYPT_UPDATE`. + +Command Code: `0x434D_4755` ("CMGU") + +*Table: `CM_AES_GCM_ENCRYPT_UPDATE` input arguments* +| **Name** | **Type** | **Description** | +| -------------- | -------- | ------------------- | +| chksum | u32 | | +| context size | u32 | Size of the context | +| context | u8[...] | | +| plaintext size | u32 | MUST be non-zero | +| plaintext | u8[...] | Data to encrypt | -If the key material is larger than 256 bits, then it will be truncated before use. - -Command Code: `0x434D_4744` ("CMGD") - -*Table: `CM_AES_GCM_DECRYPT` input arguments* -| **Name** | **Type** | **Description** | -| --------------- | -------- | ---------------------------------------- | -| chksum | u32 | | -| flags | u32 | Bit 0 = this is the final message | -| CMK | u8[128] | CMK to use for decryption | -| tag size | u32 | Number of bytes in the tag. | -| | | Can be 0, 1, ..., 16 | -| | | Must be 0 if this is not the first block | -| tag | u8[...] | | -| context size | u32 | Size of the context | -| context | u8[...] | | -| iv | u8[12] | Ignored if not the first message | -| aad size | u32 | Additional authenticated data size | -| | | Must be 0 if this is not the first block | -| aad | u8[...] | Additional authenticated data | -| ciphertext size | u32 | | -| ciphertext | u8[...] | Data to decrypt | - -*Table: `CM_AES_GCM_DECRYPT` output arguments* +*Table: `CM_AES_GCM_ENCRYPT_UPDATE` output arguments* +| **Name** | **Type** | **Description** | +| -------------- | -------- | ------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| context size | u32 | | +| context | u8[...] | | +| cipertext size | u32 | MAY be 0 | +| ciphertext | u8[...] | | + +### CM_AES_GCM_ENCRYPT_FINAL + +This finalizes the computation of the AES GCM encryption and produces the final ciphertext and tag. + +The context MUST be passed in from `CM_AES_GCM_ENCRYPT_INIT` or `CM_AES_GCM_ENCRYPT_UPDATE`. + +Command Code: `0x434D_4746` ("CMGF") + +*Table: `CM_AES_GCM_ENCRYPT_FINAL` input arguments* +| **Name** | **Type** | **Description** | +| -------------- | -------- | --------------------| +| chksum | u32 | | +| context size | u32 | Size of the context | +| context | u8[...] | | +| plaintext size | u32 | MAY be 0 | +| plaintext | u8[...] | Data to encrypt | + +*Table: `CM_AES_GCM_ENCRYPT_FINAL` output arguments* | **Name** | **Type** | **Description** | | -------------- | -------- | ----------------------------------------- | | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| context size | u32 | Can be 0 if this is the final message | -| context | u8[...] | | -| plaintext size | u32 | Can be 0 if this is not the final message | -| plaintext | u8[...] | | +| cipertext size | u32 | MAY be 0 if this is not the final message | +| ciphertext | u8[...] | | +| tag | u8[16] | | + +The tag returned will always be 16 bytes. Shorter tags can be constructed by truncating. + +### CM_AES_GCM_DECRYPT_INIT + +Starts an AES-256-GCM computation. + +Currently only supports AES-256-GCM with a 96-bit IV. + +The CMK must have been created for AES usage. + +Tags between 0 and 16 bytes are supported. + +Command Code: `0x434D_4449` ("CMDI") + +*Table: `CM_AES_GCM_DECRYPT_INIT` input arguments* +| **Name** | **Type** | **Description** | +| --------------- | -------- | ---------------------------------- | +| chksum | u32 | | +| CMK | CMK | CMK to use for decryption | +| tag size | u32 | Number of bytes in the tag. | +| | | Can be 0, 1, ..., 16 | +| tag | u8[...] | | +| iv | u8[12] | | +| aad size | u32 | Additional authenticated data size | +| | | | +| aad | u8[...] | Additional authenticated data | +| ciphertext size | u32 | | +| ciphertext | u8[...] | Data to decrypt | + +*Table: `CM_AES_GCM_DECRYPT_INIT` output arguments* +| **Name** | **Type** | **Description** | +| -------------- | -------- | ------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| context size | u32 | | +| context | u8[...] | | +| plaintext size | u32 | MAY be 0 | +| plaintext | u8[...] | | The encrypted and authenticated context's internal structure will be: -*Table: `CM_AES_GCM_DECRYPT` internal context* +*Table: internal context for `CM_AES_GCM_DECRYPT_*` operations* | **Name** | **Type** | **Description** | | --------------- | -------- | --------------- | | tag size | u32 | | +| tag | u8[16] | padded with 0s | | last length | u32 | | | last iv | u8[16] | | | last GHASH | u8[16] | | | last ciphertext | u8[16] | | +### CM_AES_GCM_DECRYPT_UPDATE + +This continues an AES computation started by `CM_AES_GCM_DECRYPT_INIT` or from another `CM_AES_GCM_DECRYPT_UPDATE`. + +The context MUST be passed in from `CM_AES_GCM_DECRYPT_INIT` or `CM_AES_GCM_DECRYPT_UPDATE`. + +Command Code: `0x434D_4455` ("CMDU") + +*Table: `CM_AES_GCM_DECRYPT_UPDATE` input arguments* +| **Name** | **Type** | **Description** | +| --------------- | -------- | ------------------- | +| chksum | u32 | | +| context size | u32 | Size of the context | +| context | u8[...] | | +| ciphertext size | u32 | MUST be non-zero | +| ciphertext | u8[...] | Data to decrypt | + +*Table: `CM_AES_GCM_DECRYPT_UPDATE` output arguments* +| **Name** | **Type** | **Description** | +| -------------- | -------- | ------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| context size | u32 | | +| context | u8[...] | | +| plaintext size | u32 | MAY be 0 | +| plaintext | u8[...] | | + +### CM_AES_GCM_DECRYPT_FINAL + +This finalizes the computation of the AES GCM decryption and produces the final ciphertext. + +The context MUST be passed in from `CM_AES_GCM_DECRYPT_INIT` or `CM_AES_GCM_DECRYPT_UPDATE`. + +Command Code: `0x434D_4446` ("CMDF") + +*Table: `CM_AES_GCM_DECRYPT_FINAL` input arguments* +| **Name** | **Type** | **Description** | +| --------------- | -------- | --------------------------------- | +| chksum | u32 | | +| flags | u32 | Bit 0 = this is the final message | +| context size | u32 | Size of the context | +| context | u8[...] | | +| ciphertext size | u32 | MAY be 0 | +| ciphertext | u8[...] | Data to decrypt | + +*Table: `CM_AES_GCM_DECRYPT_FINAL` output arguments* +| **Name** | **Type** | **Description** | +| -------------- | -------- | ------------------------------------ | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| tag verified | u32 | 1 if tags matched, 0 if they did not | +| tag | u8[16] | Computed tag | +| plaintext size | u32 | MAY be 0 | +| plaintext | u8[...] | | ### CM_ECDH_GENERATE @@ -1413,11 +1527,11 @@ Command Code: `0x434D_4546` ("CMEF") | incoming exchange data | u8[96] | the other side's public point | *Table: `CM_ECDH_FINISH` output arguments* -| **Name** | **Type** | **Description** | -| ----------- | -------- | -------------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | -| output CMK | u8[128] | Output CMK of the shared secret | +| **Name** | **Type** | **Description** | +| ----------- | -------- | ------------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| output CMK | CMK | Output CMK of the shared secret | ### CM_RANDOM_STIR @@ -1435,10 +1549,10 @@ Command Code: `0x434D_5253` ("CMRS") | input | u8[...] | | *Table: `CM_RANDOM_STIR` output arguments* -| **Name** | **Type** | **Description** | -| ----------- | -------- | ---------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | +| **Name** | **Type** | **Description** | +| ----------- | -------- | ------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | ### CM_RANDOM_GENERATE @@ -1472,19 +1586,19 @@ Command Code: `0x434D_494D` ("CMIM") *Table: `CM_IMPORT` input arguments* -| **Name** | **Type** | **Description** | -| ---------- | -------- | ------------------------------------------ | -| chksum | u32 | | -| key usage | u32 | Tag to specify how the data can be used | -| input size | u32 | | -| input | u8[...] | | +| **Name** | **Type** | **Description** | +| ---------- | -------- | --------------------------------------- | +| chksum | u32 | | +| key usage | u32 | Tag to specify how the data can be used | +| input size | u32 | | +| input | u8[...] | | *Table: `CM_IMPORT` output arguments* | **Name** | **Type** | **Description** | | ----------- | -------- | ---------------------------- | | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| CMK | u8[128] | CMK containing imported key | +| CMK | CMK | CMK containing imported key | ### CM_DELETE @@ -1494,16 +1608,16 @@ Command Code: `0x434D_444C` ("CMDL") *Table: `CM_DELETE` input arguments* -| **Name** | **Type** | **Description** | -| -------- | -------- | -------------------------- | -| chksum | u32 | | -| CMK | u8[128] | CMK to delete | +| **Name** | **Type** | **Description** | +| -------- | -------- | --------------- | +| chksum | u32 | | +| CMK | CMK | CMK to delete | *Table: `CM_DELETE` output arguments* -| **Name** | **Type** | **Description** | -| ----------- | -------- | ---------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | +| **Name** | **Type** | **Description** | +| ----------- | -------- | ------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | ### CM_CLEAR From 8d969d1833ef950bc6231d0ae67fec1bc001b6aa Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Mon, 9 Dec 2024 13:56:31 -0800 Subject: [PATCH 3/3] Address comments --- runtime/README.md | 91 ++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/runtime/README.md b/runtime/README.md index 70af4e8d62..1cd2564b2a 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -118,29 +118,30 @@ Internally, the unecrypted CMKs have the following structure: | **Name** | **Bits** | **Description** | | ------------- | -------- | ------------------------------------------- | -| version | 32 | CMK version. Currently always 1. | -| key usage | 32 | represents which kind of key this is | -| id | 32 | ID number | +| version | 16 | CMK version. Currently always 1. | +| length | 16 | how many bits of key material are used | +| key usage | 8 | represents which kind of key this is | +| id | 24 | ID number | | usage counter | 64 | how many times this key has been used | -| length | 32 | how many bits of key material are used | -| padding | 64 | reserved for now | +| | | This MAY only be tracked for AES keys | | key material | 512 | bits used for the key material | The encrypted CMKs have the structure: -| **Name** | **Bits** | **Description** | -| ------------- | -------- | ------------------------------ | -| padding | 32 | reserved | -| iv | 96 | | -| ciphertext | 768 | encrypted CMK data (see above) | -| GCM tag | 128 | | +| **Name** | **Bits** | **Description** | +| --------------- | -------- | ------------------------------ | +| domain | 32 | reserved | +| domain metadata | 128 | reserved +| iv | 96 | | +| ciphertext | 640 | encrypted CMK data (see above) | +| GCM tag | 128 | | The total size of the CMK is therefore 128 bytes. Only the encrypted CMKs will appear in mailbox messages. -The key used to encrypt the CMKs is randomized on reset, which means that CMKS cannot be used between resets. -The iv is a randomized 1-up counter that is incremented for every key created. +The key used to encrypt the CMKs is randomized on reset, which means that CMKs cannot be used between resets. +The IV is a randomized 1-up counter that is incremented for every key created. #### Key Usage @@ -159,9 +160,9 @@ To prevent replay attacks, Caliptra will have a small table that maps a CMK's in Whenever a CMK is used, this table is checked and updated. This is necessary for AES-256-GCM in particular to ensure that keys are only used a certain number of times, as per [NIST SP 800-38D, Section 8.3](https://doi.org/10.6028/NIST.SP.800-38D). -Only AES-256-GCM keys need to be tracked in this table. +Only AES-256-GCM keys need to be tracked in this table, but other keys MAY be tracked as well. -This requires 96 bits of storage per AES-256-GCM key. These can stored as a sorted list to the DCCM requirements. +This requires 96 bits of storage per AES-256-GCM key. These can stored as a sorted list in the DCCM. ## Manifest-Based Image Authorization (new in 1.2) @@ -1135,7 +1136,7 @@ Command Code: `0x434D_4849` ("CMHI") | **Name** | **Type** | **Description** | | -------------- | -------- | -------------------------------------- | | chksum | u32 | | -| CMK | CMK | CMK use as key | +| CMK | CMK | CMK to use as key | | hash algorithm | u32 | Enum. | | | | 0 = reserved | | | | 1 = SHA2-256 | @@ -1149,7 +1150,7 @@ Command Code: `0x434D_4849` ("CMHI") | ------------ | -------- | --------------------------------------- | | chksum | u32 | | | fips_status | u32 | FIPS approved or an error | -| context size | u32 | SHALL be 0 if this is the final message | +| context size | u32 | | | context | u8[...] | | *Table: `CM_HMAC_INIT` internal context* @@ -1291,15 +1292,15 @@ Command Code: `0x434D_4749` ("CMGI") | plaintext | u8[...] | Data to encrypt | *Table: `CM_AES_GCM_ENCRYPT_INIT` output arguments* -| **Name** | **Type** | **Description** | -| -------------- | -------- | ------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | -| context size | u32 | | -| context | u8[...] | | -| iv | u8[12] | | -| cipertext size | u32 | MAY be 0 | -| ciphertext | u8[...] | | +| **Name** | **Type** | **Description** | +| -------------- | -------- | -------------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| context size | u32 | | +| context | u8[...] | | +| iv | u8[12] | | +| cipertext size | u32 | MUST be equal to ciphertext size | +| ciphertext | u8[...] | | The encrypted and authenticated context's internal structure will be: @@ -1330,14 +1331,14 @@ Command Code: `0x434D_4755` ("CMGU") | plaintext | u8[...] | Data to encrypt | *Table: `CM_AES_GCM_ENCRYPT_UPDATE` output arguments* -| **Name** | **Type** | **Description** | -| -------------- | -------- | ------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | -| context size | u32 | | -| context | u8[...] | | -| cipertext size | u32 | MAY be 0 | -| ciphertext | u8[...] | | +| **Name** | **Type** | **Description** | +| -------------- | -------- | -------------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| context size | u32 | | +| context | u8[...] | | +| cipertext size | u32 | MUST be equal to ciphertext size | +| ciphertext | u8[...] | | ### CM_AES_GCM_ENCRYPT_FINAL @@ -1357,13 +1358,13 @@ Command Code: `0x434D_4746` ("CMGF") | plaintext | u8[...] | Data to encrypt | *Table: `CM_AES_GCM_ENCRYPT_FINAL` output arguments* -| **Name** | **Type** | **Description** | -| -------------- | -------- | ----------------------------------------- | -| chksum | u32 | | -| fips_status | u32 | FIPS approved or an error | -| cipertext size | u32 | MAY be 0 if this is not the final message | -| ciphertext | u8[...] | | -| tag | u8[16] | | +| **Name** | **Type** | **Description** | +| -------------- | -------- | --------------------------------- | +| chksum | u32 | | +| fips_status | u32 | FIPS approved or an error | +| cipertext size | u32 | MUST be equal to ciphertext size | +| ciphertext | u8[...] | | +| tag | u8[16] | | The tag returned will always be 16 bytes. Shorter tags can be constructed by truncating. @@ -1524,6 +1525,8 @@ Command Code: `0x434D_4546` ("CMEF") | context size | u32 | size of context | | context | u8[...] | This MUST come from the output of the `CM_ECDH_GENERATE` | | key usage | u32 | usage tag of the kind of key that will be output | +| | | Note that this must be compatible with the 384-bit key, | +| | | i.e., it should be HMAC or HKDF, and not AES | | incoming exchange data | u8[96] | the other side's public point | *Table: `CM_ECDH_FINISH` output arguments* @@ -1590,7 +1593,7 @@ Command Code: `0x434D_494D` ("CMIM") | ---------- | -------- | --------------------------------------- | | chksum | u32 | | | key usage | u32 | Tag to specify how the data can be used | -| input size | u32 | | +| input size | u32 | This MUST agree with the key usage | | input | u8[...] | | *Table: `CM_IMPORT` output arguments* @@ -1667,9 +1670,9 @@ Command Code: `0x4944_4352` ("IDCR") | data\_size | u32 | Length in bytes of the valid data in the data field. | | data | u8[...] | DER-encoded IDevID certificate signing request. | -The `mfg_flag_gen_idev_id_csr` manufacturing flag **MUST** have been set to generate a CSR. +The `mfg_flag_gen_idev_id_csr` manufacturing flag **MUST** have been set to generate a CSR. -When called from ROM, if the CSR was not previously provisioned this command will return `FW_PROC_MAILBOX_UNPROVISIONED_CSR(0x0102000A)`. +When called from ROM, if the CSR was not previously provisioned this command will return `FW_PROC_MAILBOX_UNPROVISIONED_CSR(0x0102000A)`. When called from runtime, if the CSR was not previously provisioned this command will return `RUNTIME_GET_IDEV_ID_UNPROVISIONED(0x000E0051)`. If the ROM did not support CSR generation, this command will return `RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM(0x000E0052)`.