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