Skip to content

Commit

Permalink
Implement GetTaggedTci and TagTCI mailbox commands in RT
Browse files Browse the repository at this point in the history
  • Loading branch information
sree-revoori1 authored and jhand2 committed Nov 29, 2023
1 parent fe5dd1b commit 568cd14
Show file tree
Hide file tree
Showing 10 changed files with 380 additions and 21 deletions.
38 changes: 38 additions & 0 deletions api/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ impl CommandId {
pub const INVOKE_DPE: Self = Self(0x44504543); // "DPEC"
pub const DISABLE_ATTESTATION: Self = Self(0x4453424C); // "DSBL"
pub const FW_INFO: Self = Self(0x494E464F); // "INFO"
pub const DPE_TAG_TCI: Self = Self(0x54514754); // "TAGT"
pub const DPE_GET_TAGGED_TCI: Self = Self(0x47544744); // "GTGD"

// TODO: Remove this and merge with GET_LDEV_CERT once that is implemented
pub const TEST_ONLY_GET_LDEV_CERT: Self = Self(0x4345524c); // "CERL"
Expand Down Expand Up @@ -132,6 +134,7 @@ pub enum MailboxResp {
FipsVersion(FipsVersionResp),
FwInfo(FwInfoResp),
Capabilities(CapabilitiesResp),
GetTaggedTci(GetTaggedTciResp),
}

impl MailboxResp {
Expand All @@ -148,6 +151,7 @@ impl MailboxResp {
MailboxResp::FipsVersion(resp) => Ok(resp.as_bytes()),
MailboxResp::FwInfo(resp) => Ok(resp.as_bytes()),
MailboxResp::Capabilities(resp) => Ok(resp.as_bytes()),
MailboxResp::GetTaggedTci(resp) => Ok(resp.as_bytes()),
}
}

Expand All @@ -164,6 +168,7 @@ impl MailboxResp {
MailboxResp::FipsVersion(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::FwInfo(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::Capabilities(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::GetTaggedTci(resp) => Ok(resp.as_bytes_mut()),
}
}

Expand Down Expand Up @@ -213,6 +218,8 @@ pub enum MailboxReq {
FwInfo(MailboxReqHeader),
PopulateIdevCert(PopulateIdevCertReq),
GetIdevCert(GetIdevCertReq),
TagTci(TagTciReq),
GetTaggedTci(GetTaggedTciReq),

#[cfg(feature = "test_only_commands")]
TestHmacVerify(HmacVerifyReq),
Expand All @@ -232,6 +239,8 @@ impl MailboxReq {
MailboxReq::GetLdevCert(req) => Ok(req.as_bytes()),
MailboxReq::PopulateIdevCert(req) => req.as_bytes_partial(),
MailboxReq::GetIdevCert(req) => req.as_bytes_partial(),
MailboxReq::TagTci(req) => Ok(req.as_bytes()),
MailboxReq::GetTaggedTci(req) => Ok(req.as_bytes()),

#[cfg(feature = "test_only_commands")]
MailboxReq::TestGetFmcAliasCert(req) => Ok(req.as_bytes()),
Expand All @@ -251,6 +260,8 @@ impl MailboxReq {
MailboxReq::FwInfo(req) => Ok(req.as_bytes_mut()),
MailboxReq::PopulateIdevCert(req) => req.as_bytes_partial_mut(),
MailboxReq::GetIdevCert(req) => req.as_bytes_partial_mut(),
MailboxReq::TagTci(req) => Ok(req.as_bytes_mut()),
MailboxReq::GetTaggedTci(req) => Ok(req.as_bytes_mut()),

#[cfg(feature = "test_only_commands")]
MailboxReq::TestHmacVerify(req) => Ok(req.as_bytes_mut()),
Expand All @@ -270,6 +281,8 @@ impl MailboxReq {
MailboxReq::FwInfo(_) => CommandId::FW_INFO,
MailboxReq::PopulateIdevCert(_) => CommandId::POPULATE_IDEV_CERT,
MailboxReq::GetIdevCert(_) => CommandId::GET_IDEV_CERT,
MailboxReq::TagTci(_) => CommandId::DPE_TAG_TCI,
MailboxReq::GetTaggedTci(_) => CommandId::DPE_GET_TAGGED_TCI,

#[cfg(feature = "test_only_commands")]
MailboxReq::TestHmacVerify(_) => CommandId::TEST_ONLY_HMAC384_VERIFY,
Expand Down Expand Up @@ -706,6 +719,31 @@ impl Default for PopulateIdevCertReq {
}
}

// DPE_TAG_TCI
// No command-specific output args
#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct TagTciReq {
pub hdr: MailboxReqHeader,
pub handle: [u8; 16],
pub tag: u32,
}

// DPE_GET_TAGGED_TCI
#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct GetTaggedTciReq {
pub hdr: MailboxReqHeader,
pub tag: u32,
}
#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct GetTaggedTciResp {
pub hdr: MailboxRespHeader,
pub tci_cumulative: [u8; 48],
pub tci_current: [u8; 48],
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
11 changes: 9 additions & 2 deletions drivers/src/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::{marker::PhantomData, mem::size_of, ptr::addr_of};

use caliptra_image_types::ImageManifest;
#[cfg(feature = "runtime")]
use dpe::DpeInstance;
use dpe::{DpeInstance, U8Bool, MAX_HANDLES};
use zerocopy::{AsBytes, FromBytes};
use zeroize::Zeroize;

Expand Down Expand Up @@ -54,7 +54,14 @@ pub struct PersistentData {
#[cfg(feature = "runtime")]
pub dpe: DpeInstance,
#[cfg(feature = "runtime")]
reserved6: [u8; memory_layout::DPE_SIZE as usize - size_of::<DpeInstance>()],
pub context_tags: [u32; MAX_HANDLES],
#[cfg(feature = "runtime")]
pub context_has_tag: [U8Bool; MAX_HANDLES],
#[cfg(feature = "runtime")]
reserved6: [u8; memory_layout::DPE_SIZE as usize
- size_of::<DpeInstance>()
- size_of::<u32>() * MAX_HANDLES
- size_of::<U8Bool>() * MAX_HANDLES],
#[cfg(not(feature = "runtime"))]
dpe: [u8; memory_layout::DPE_SIZE as usize],
}
Expand Down
9 changes: 6 additions & 3 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,15 @@ impl CaliptraError {
CaliptraError::new_const(0x000E0021);
pub const RUNTIME_ADD_ROM_MEASUREMENTS_TO_DPE_FAILED: CaliptraError =
CaliptraError::new_const(0x000E0022);
pub const RUNTIME_TAGGING_FAILURE: CaliptraError = CaliptraError::new_const(0x000E0022);
pub const RUNTIME_DUPLICATE_TAG: CaliptraError = CaliptraError::new_const(0x000E0023);
pub const RUNTIME_CONTEXT_ALREADY_TAGGED: CaliptraError = CaliptraError::new_const(0x000E0024);
pub const RUNTIME_ADD_VALID_PAUSER_MEASUREMENT_TO_DPE_FAILED: CaliptraError =
CaliptraError::new_const(0x000E0023);
CaliptraError::new_const(0x000E0025);
pub const RUNTIME_MAILBOX_API_RESPONSE_DATA_LEN_TOO_LARGE: CaliptraError =
CaliptraError::new_const(0x000E0024);
CaliptraError::new_const(0x000E0026);
pub const RUNTIME_MAILBOX_API_REQUEST_DATA_LEN_TOO_LARGE: CaliptraError =
CaliptraError::new_const(0x000E0025);
CaliptraError::new_const(0x000E0027);

/// FMC Errors
pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001);
Expand Down
54 changes: 46 additions & 8 deletions runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,48 @@ Table: `INCREMENT_PCR_RESET_COUNTER` input arguments

`INCREMENT_PCR_RESET_COUNTER` returns no output arguments.

### DPE\_TAG\_TCI

Associates a unique tag with a DPE context

Command Code: `0x5451_4754` ("TAGT")

Table: `DPE_TAG_TCI` input arguments

| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian.
| handle | u8[16] | DPE context handle
| tag | u32 | A unique tag which the handle will be associated with

Table: `DPE_TAG_TCI` output arguments

| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| chksum | u32 | Checksum over other output arguments, computed by Caliptra. Little endian.
| fips_status | u32 | Indicates if the command is FIPS approved or an error

### DPE\_GET\_TAGGED\_TCI

Retrieves the TCI measurements corresponding to the tagged DPE context

Command Code: `0x4754_4744` ("GTGD")

Table: `DPE_GET_TAGGED_TCI` input arguments

| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian.
| tag | u32 | A unique tag corresponding to a DPE context

Table: `DPE_GET_TAGGED_TCI` output arguments

| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian.
| tci_cumulative | u8[48] | Hash of all the input data provided to the context
| tci_current | u8[48] | Most recent measurement made into the context

## Checksum

For every command, the request and response feature a checksum. This mitigates
Expand Down Expand Up @@ -550,7 +592,6 @@ details specific requirements for the Caliptra DPE implementation.
| Simulation Context Support | Yes | Whether Caliptra implements the optional Simulation Contexts feature
| Supports ExtendTci | Yes | Whether Caliptra implements the optional ExtendTci command
| Supports Auto Init | Yes | Whether Caliptra will automatically initialize the default DPE context.
| Supports Tagging | Yes | Whether Caliptra implements the optional TCI tagging feature.
| Supports Rotate Context | Yes | Whether Caliptra supports the optional RotateContextHandle command.
| CertifyKey Alias Key | Caliptra Runtime Alias Key | The key that will be used to sign certificates produced by the DPE CertifyKey command.

Expand All @@ -569,12 +610,10 @@ Caliptra DPE supports the following commands
* DestroyContext
* GetCertificateChain

In addition, Caliptra supports the following profile-defined commands:
In addition, Caliptra supports the following profile-defined command:

* ExtendTci: Extend a TCI measurement made by DeriveChild to provide additional
measurement data.
* TagTci: Associate a TCI node with a unique tag
* GetTaggedTci: Look up the measurements in a TCI node by tag

### DPE State Atomicity

Expand Down Expand Up @@ -639,11 +678,10 @@ To derive an asymmetric key for Sign and CertifyKey, RT will
| Byte Offset | Bits | Name | Description
| ----------- | ----- | ------------ | -------------
| 0x02 | 15:0 | Parent Index | Index of the TCI node that is the parent of this node. 0xFF if this node is the root.
| 0x04 | 31:0 | Node Tag | Tag of this node provided by the TagTci command.
| 0x08 | 159:0 | Context Handle | DPE context handle referring to this node
| 0x1C | 31 | Internal TCI | This TCI was measured by Runtime Firmware itself
| 0x04 | 159:0 | Context Handle | DPE context handle referring to this node
| 0x18 | 31 | Internal TCI | This TCI was measured by Runtime Firmware itself
| | 30:0 | Reserved | Reserved flag bits
| 0x20 | 383:0 | Latest TCI | The latest `INPUT_DATA` extended into this TCI by ExtendTci or DeriveChild
| 0x1C | 383:0 | Latest TCI | The latest `INPUT_DATA` extended into this TCI by ExtendTci or DeriveChild

Table: `TCI_NODE_DATA` for `DPE_PROFILE_IROT_P384_SHA384`

Expand Down
6 changes: 4 additions & 2 deletions runtime/doc/test-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ These tests are implemented in Go and test end-to-end DPE attestation behavior.
Test Scenario | Test Name | Go Error Code
---|---|---
Calls and tests behavior of the DPE command InitializeContext | **TestInitializeContext** | N/A
Calls and tests behavior of the DPE command InitializeContext with simulation contexts | **TestInitializeContextSimulation** | N/A
Calls and tests behavior of the DPE command InitializeContext with simulation contexts | **TestInitializeSimulation** | N/A
Calls the DPE command CertifyKey, verifies the structure of the resulting certificate by parsing and linting it, and checks that the desired extensions are present | **TestCertifyKey** | N/A
Calls the DPE command CertifyKey with a simulation context handle, verifies the structure of the resulting certificate by parsing and linting it, and checks that the desired extensions are present | **TestCertifyKey_SimulationMode** | N/A
Calls the DPE command GetCertificateChain and verifies the structure of each certificate in the chain by parsing and linting them | **TestGetCertificateChain** | N/A
Calls and tests behavior of the DPE command TagTci | **TestTagTCI** | N/A
Calls the DPE command ExtendTci and verifies the resulting TCI | **TestExtendTCI** | N/A
Calls the DPE command ExtendTci with a derived child context and verifies the resulting TCI | **TestExtendTciOnDerivedContexts** | N/A
Calls the DPE command GetProfile and verifies the DPE profile | **TestGetProfile** | N/A
Checks whether an error is reported when non-existent handle is passed as input to DPE commands | **TestInvalidHandle** | StatusInvalidHandle
Checks whether an error is reported when caller from one locality issues DPE commands in another locality | **TestWrongLocality** | StatusInvalidLocality
Expand All @@ -59,6 +60,7 @@ Checks that the get_idev_cert mailbox command succeeds and verifies the size of
Checks that the version mailbox command succeeds and validates the FIPS version response | **test_fips_cmd_api** | RUNTIME_SHUTDOWN
Check that the error register is cleared when a successful mailbox command runs after a failed mailbox command | **test_error_cleared** | RUNTIME_MAILBOX_INVALID_PARAMS
Calls the POPULATE_IDEV_CERT mailbox command and checks that the IDevId certificate is able to be parsed from the certificate chain | **test_populate_idev_cert_cmd** | N/A
Validates the behavior of the dpe_tag_tci and dpe_get_tagged_tci mailbox commands and verifies the contents of the current and cumulative TCI responses | **test_tagging** | N/A

<br><br>
# **Wycheproof Tests**
Expand Down
1 change: 1 addition & 0 deletions runtime/src/dpe_crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ impl<'a> Crypto for DpeCrypto<'a> {
Hmac384Tag::Array4x12(&mut tag),
)
.map_err(|e| CryptoError::CryptoLibError(u32::from(e)))?;
hmac_key.zeroize();
HmacSig::new(tag.as_bytes())
}
}
Expand Down
23 changes: 20 additions & 3 deletions runtime/src/invoke_dpe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use dpe::{
},
context::{Context, ContextState},
response::{Response, ResponseHdr},
DpeInstance,
DpeInstance, U8Bool, MAX_HANDLES,
};
use zerocopy::{AsBytes, FromBytes};

Expand Down Expand Up @@ -52,7 +52,10 @@ impl InvokeDpeCmd {
.map_err(|_| CaliptraError::RUNTIME_INVOKE_DPE_FAILED)?;
let flags = pdata.manifest1.header.flags;

let mut dpe = &mut drivers.persistent_data.get_mut().dpe;
let pdata_mut = drivers.persistent_data.get_mut();
let mut dpe = &mut pdata_mut.dpe;
let mut context_has_tag = &mut pdata_mut.context_has_tag;
let mut context_tags = &mut pdata_mut.context_tags;
let resp = match command {
Command::GetProfile => Ok(Response::GetProfile(
dpe.get_profile(&mut env.platform)
Expand Down Expand Up @@ -87,9 +90,23 @@ impl InvokeDpeCmd {
}
cmd.execute(dpe, &mut env, locality)
}
Command::DestroyCtx(cmd) => {
let destroy_ctx_resp = cmd.execute(dpe, &mut env, locality);
// clear tags for destroyed contexts
(0..MAX_HANDLES).for_each(|i| {
if i < dpe.contexts.len()
&& i < context_has_tag.len()
&& i < context_tags.len()
&& dpe.contexts[i].state != ContextState::Active
{
context_has_tag[i] = U8Bool::new(false);
context_tags[i] = 0;
}
});
destroy_ctx_resp
}
Command::Sign(cmd) => cmd.execute(dpe, &mut env, locality),
Command::RotateCtx(cmd) => cmd.execute(dpe, &mut env, locality),
Command::DestroyCtx(cmd) => cmd.execute(dpe, &mut env, locality),
Command::ExtendTci(cmd) => cmd.execute(dpe, &mut env, locality),
Command::GetCertificateChain(cmd) => cmd.execute(dpe, &mut env, locality),
};
Expand Down
4 changes: 4 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub use verify::EcdsaVerifyCmd;
pub mod packet;
use caliptra_common::mailbox_api::{CommandId, MailboxResp};
use packet::Packet;
pub mod tagging;
use tagging::{GetTaggedTciCmd, TagTciCmd};

use caliptra_common::cprintln;

Expand Down Expand Up @@ -137,6 +139,8 @@ fn handle_command(drivers: &mut Drivers) -> CaliptraResult<MboxStatusE> {
CommandId::STASH_MEASUREMENT => StashMeasurementCmd::execute(drivers, cmd_bytes),
CommandId::DISABLE_ATTESTATION => DisableAttestationCmd::execute(drivers),
CommandId::FW_INFO => FwInfoCmd::execute(drivers),
CommandId::DPE_TAG_TCI => TagTciCmd::execute(drivers, cmd_bytes),
CommandId::DPE_GET_TAGGED_TCI => GetTaggedTciCmd::execute(drivers, cmd_bytes),
CommandId::POPULATE_IDEV_CERT => PopulateIDevIdCertCmd::execute(drivers, cmd_bytes),
#[cfg(feature = "test_only_commands")]
CommandId::TEST_ONLY_GET_LDEV_CERT => GetLdevCertCmd::execute(drivers),
Expand Down
Loading

0 comments on commit 568cd14

Please sign in to comment.