Skip to content

Commit e07b0af

Browse files
authored
Support signing with an exported CDI after a warm reset (#2125)
1 parent 39461a6 commit e07b0af

File tree

13 files changed

+411
-42
lines changed

13 files changed

+411
-42
lines changed

drivers/src/key_vault.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ use bitfield::bitfield;
1717
use crate::{CaliptraError, CaliptraResult};
1818
use caliptra_registers::kv::KvReg;
1919

20+
use zerocopy::{IntoBytes, KnownLayout, TryFromBytes};
21+
2022
/// Key Identifier
21-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23+
#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromBytes, IntoBytes, KnownLayout)]
24+
#[repr(u8)]
2225
pub enum KeyId {
2326
KeyId0 = 0,
2427
KeyId1 = 1,
@@ -54,6 +57,13 @@ pub enum KeyId {
5457
KeyId31 = 31,
5558
}
5659

60+
impl zeroize::Zeroize for KeyId {
61+
fn zeroize(&mut self) {
62+
// This is a NOP as these enums are just a handle.
63+
// This trait is implemented so the slots can be serialized into `PersistentData`.
64+
}
65+
}
66+
5767
impl TryFrom<u8> for KeyId {
5868
type Error = ();
5969
fn try_from(original: u8) -> Result<Self, Self::Error> {

drivers/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub use pcr_bank::{PcrBank, PcrId};
8888
pub use pcr_reset::PcrResetCounter;
8989
pub use persistent::fmc_alias_csr::FmcAliasCsr;
9090
#[cfg(feature = "runtime")]
91-
pub use persistent::AuthManifestImageMetadataList;
91+
pub use persistent::{AuthManifestImageMetadataList, ExportedCdiEntry, ExportedCdiHandles};
9292

9393
pub use persistent::{
9494
FuseLogArray, IdevIdCsr, PcrLogArray, PersistentData, PersistentDataAccessor,

drivers/src/persistent.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use caliptra_auth_man_types::{
1010
use caliptra_error::{CaliptraError, CaliptraResult};
1111
use caliptra_image_types::ImageManifest;
1212
#[cfg(feature = "runtime")]
13-
use dpe::{DpeInstance, U8Bool, MAX_HANDLES};
13+
use dpe::{DpeInstance, ExportedCdiHandle, U8Bool, MAX_HANDLES};
1414
use zerocopy::{IntoBytes, KnownLayout, TryFromBytes};
1515
use zeroize::Zeroize;
1616

@@ -26,7 +26,7 @@ use crate::{
2626
use crate::FmcAliasCsr;
2727

2828
#[cfg(feature = "runtime")]
29-
use crate::pcr_reset::PcrResetCounter;
29+
use crate::{pcr_reset::PcrResetCounter, KeyId};
3030

3131
pub const MAX_CSR_SIZE: usize = 512;
3232
pub const MAN1_SIZE: u32 = 6 * 1024;
@@ -49,12 +49,31 @@ pub const PCR_LOG_MAX_COUNT: usize = 17;
4949
pub const FUSE_LOG_MAX_COUNT: usize = 62;
5050
pub const MEASUREMENT_MAX_COUNT: usize = 8;
5151

52+
#[cfg(feature = "runtime")]
53+
// Currently only can export CDI once, but in the future we may want to support multiple exported
54+
// CDI handles at the cost of using more KeyVault slots.
55+
pub const EXPORTED_HANDLES_NUM: usize = 1;
56+
#[cfg(feature = "runtime")]
57+
#[derive(Clone, TryFromBytes, IntoBytes, KnownLayout, Zeroize)]
58+
pub struct ExportedCdiEntry {
59+
pub key: KeyId,
60+
pub handle: ExportedCdiHandle,
61+
pub active: U8Bool,
62+
}
63+
64+
#[cfg(feature = "runtime")]
65+
#[derive(Clone, TryFromBytes, IntoBytes, KnownLayout, Zeroize)]
66+
pub struct ExportedCdiHandles {
67+
pub entries: [ExportedCdiEntry; EXPORTED_HANDLES_NUM],
68+
}
69+
5270
#[cfg(feature = "runtime")]
5371
const DPE_DCCM_STORAGE: usize = size_of::<DpeInstance>()
5472
+ size_of::<u32>() * MAX_HANDLES
5573
+ size_of::<U8Bool>() * MAX_HANDLES
5674
+ size_of::<U8Bool>()
57-
+ size_of::<U8Bool>();
75+
+ size_of::<U8Bool>()
76+
+ size_of::<ExportedCdiHandles>();
5877

5978
#[cfg(feature = "runtime")]
6079
const _: () = assert!(DPE_DCCM_STORAGE < DPE_SIZE as usize);
@@ -242,6 +261,8 @@ pub struct PersistentData {
242261
#[cfg(feature = "runtime")]
243262
pub runtime_cmd_active: U8Bool,
244263
#[cfg(feature = "runtime")]
264+
pub exported_cdi_slots: ExportedCdiHandles,
265+
#[cfg(feature = "runtime")]
245266
reserved6: [u8; DPE_SIZE as usize - DPE_DCCM_STORAGE],
246267
#[cfg(not(feature = "runtime"))]
247268
dpe: [u8; DPE_SIZE as usize],

runtime/src/certify_key_extended.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl CertifyKeyExtendedCmd {
5757
&mut pdata.fht.rt_dice_pub_key,
5858
key_id_rt_cdi,
5959
key_id_rt_priv_key,
60-
&mut drivers.exported_cdi_slots,
60+
&mut pdata.exported_cdi_slots,
6161
);
6262
let pl0_pauser = pdata.manifest1.header.pl0_pauser;
6363
let (nb, nf) = Drivers::get_cert_validity_info(&pdata.manifest1);

runtime/src/dpe_crypto.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,17 @@ use caliptra_common::keyids::{
2020
KEY_ID_DPE_CDI, KEY_ID_DPE_PRIV_KEY, KEY_ID_EXPORTED_DPE_CDI, KEY_ID_TMP,
2121
};
2222
use caliptra_drivers::{
23-
cprintln, hmac384_kdf, Array4x12, Ecc384, Ecc384PrivKeyIn, Ecc384PubKey, Ecc384Scalar,
24-
Ecc384Seed, Hmac384, Hmac384Data, Hmac384Key, Hmac384Tag, KeyId, KeyReadArgs, KeyUsage,
25-
KeyVault, KeyWriteArgs, Sha384, Sha384DigestOp, Trng,
23+
hmac384_kdf, Array4x12, Ecc384, Ecc384PrivKeyIn, Ecc384PubKey, Ecc384Scalar, Ecc384Seed,
24+
ExportedCdiEntry, ExportedCdiHandles, Hmac384, Hmac384Data, Hmac384Key, Hmac384Tag, KeyId,
25+
KeyReadArgs, KeyUsage, KeyVault, KeyWriteArgs, Sha384, Sha384DigestOp, Trng,
2626
};
2727
use crypto::{AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, EcdsaSig, Hasher};
2828
use dpe::{
29-
response::DpeErrorCode, x509::MeasurementData, ExportedCdiHandle, MAX_EXPORTED_CDI_SIZE,
29+
response::DpeErrorCode, x509::MeasurementData, ExportedCdiHandle, U8Bool, MAX_EXPORTED_CDI_SIZE,
3030
};
3131
use zerocopy::IntoBytes;
3232
use zeroize::Zeroize;
3333

34-
// Currently only can export CDI once, but in the future we may want to support multiple exported
35-
// CDI handles at the cost of using more KeyVault slots.
36-
pub const EXPORTED_HANDLES_NUM: usize = 1;
37-
pub type ExportedCdiHandles = [Option<(KeyId, ExportedCdiHandle)>; EXPORTED_HANDLES_NUM];
38-
3934
pub struct DpeCrypto<'a> {
4035
sha384: &'a mut Sha384,
4136
trng: &'a mut Trng,
@@ -156,9 +151,13 @@ impl<'a> DpeCrypto<'a> {
156151
&mut self,
157152
exported_cdi_handle: &[u8; MAX_EXPORTED_CDI_SIZE],
158153
) -> Option<<DpeCrypto<'a> as crypto::Crypto>::Cdi> {
159-
for cdi_slot in self.exported_cdi_slots.iter() {
154+
for cdi_slot in self.exported_cdi_slots.entries.iter() {
160155
match cdi_slot {
161-
Some((cdi, handle)) if handle == exported_cdi_handle => return Some(*cdi),
156+
ExportedCdiEntry {
157+
key,
158+
handle,
159+
active,
160+
} if active.get() && handle == exported_cdi_handle => return Some(*key),
162161
_ => (),
163162
}
164163
}
@@ -243,18 +242,30 @@ impl<'a> Crypto for DpeCrypto<'a> {
243242
// Currently we only use one slot for export CDIs.
244243
let cdi_slot = KEY_ID_EXPORTED_DPE_CDI;
245244
// Copy the CDI slots to work around the borrow checker.
246-
let mut slots_clone = *self.exported_cdi_slots;
245+
let mut slots_clone = self.exported_cdi_slots.clone();
247246

248-
for slot in slots_clone.iter_mut() {
247+
for slot in slots_clone.entries.iter_mut() {
249248
match slot {
250249
// Matching existing slot
251-
Some((cached_cdi, handle)) if *cached_cdi == cdi_slot => {
250+
ExportedCdiEntry {
251+
key,
252+
handle,
253+
active,
254+
} if active.get() && *key == cdi_slot => {
252255
Err(CryptoError::ExportedCdiHandleDuplicateCdi)?
253256
}
254-
// Empty slot
255-
None => {
257+
ExportedCdiEntry {
258+
key,
259+
handle,
260+
active,
261+
} if !active.get() => {
262+
// Empty slot
256263
let cdi = self.derive_cdi_inner(algs, measurement, info, cdi_slot)?;
257-
*slot = Some((cdi, exported_cdi_handle));
264+
*slot = ExportedCdiEntry {
265+
key: cdi,
266+
handle: exported_cdi_handle,
267+
active: U8Bool::new(true),
268+
};
258269
// We need to update `self.exported_cdi_slots` with our mutation.
259270
*self.exported_cdi_slots = slots_clone;
260271
return Ok(exported_cdi_handle);
@@ -298,10 +309,14 @@ impl<'a> Crypto for DpeCrypto<'a> {
298309
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError> {
299310
let cdi = {
300311
let mut cdi = None;
301-
for cdi_slot in self.exported_cdi_slots.iter() {
312+
for cdi_slot in self.exported_cdi_slots.entries.iter() {
302313
match cdi_slot {
303-
Some((stored_cdi, stored_handle)) if stored_handle == exported_handle => {
304-
cdi = Some(*stored_cdi);
314+
ExportedCdiEntry {
315+
key,
316+
handle,
317+
active,
318+
} if active.get() && handle == exported_handle => {
319+
cdi = Some(*key);
305320
break;
306321
}
307322
_ => (),

runtime/src/drivers.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::{
2323
PL1_DPE_ACTIVE_CONTEXT_THRESHOLD,
2424
};
2525

26-
use crate::dpe_crypto::{ExportedCdiHandles, EXPORTED_HANDLES_NUM};
2726
use arrayvec::ArrayVec;
2827
use caliptra_cfi_derive_git::{cfi_impl_fn, cfi_mod_fn};
2928
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_assert_eq_12_words, cfi_launder};
@@ -110,7 +109,6 @@ pub struct Drivers {
110109
pub is_shutdown: bool,
111110

112111
pub dmtf_device_info: Option<ArrayVec<u8, { AddSubjectAltNameReq::MAX_DEVICE_INFO_LEN }>>,
113-
pub exported_cdi_slots: ExportedCdiHandles,
114112
}
115113

116114
impl Drivers {
@@ -149,7 +147,6 @@ impl Drivers {
149147
cert_chain: ArrayVec::new(),
150148
is_shutdown: false,
151149
dmtf_device_info: None,
152-
exported_cdi_slots: [None; EXPORTED_HANDLES_NUM],
153150
})
154151
}
155152

@@ -388,7 +385,7 @@ impl Drivers {
388385
&mut pdata.fht.rt_dice_pub_key,
389386
key_id_rt_cdi,
390387
key_id_rt_priv_key,
391-
&mut drivers.exported_cdi_slots,
388+
&mut pdata.exported_cdi_slots,
392389
);
393390

394391
let (nb, nf) = Self::get_cert_validity_info(&pdata.manifest1);

runtime/src/invoke_dpe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl InvokeDpeCmd {
6060
&mut pdata.fht.rt_dice_pub_key,
6161
key_id_rt_cdi,
6262
key_id_rt_priv_key,
63-
&mut drivers.exported_cdi_slots,
63+
&mut pdata.exported_cdi_slots,
6464
);
6565
let pl0_pauser = pdata.manifest1.header.pl0_pauser;
6666
let (nb, nf) = Drivers::get_cert_validity_info(&pdata.manifest1);

runtime/src/revoke_exported_cdi_handle.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_launder};
1010
use caliptra_common::mailbox_api::{
1111
MailboxResp, MailboxRespHeader, RevokeExportedCdiHandleReq, RevokeExportedCdiHandleResp,
1212
};
13+
use caliptra_drivers::ExportedCdiEntry;
1314
use caliptra_error::{CaliptraError, CaliptraResult};
1415

16+
use dpe::U8Bool;
1517
use zerocopy::{FromBytes, IntoBytes};
18+
use zeroize::Zeroize;
1619

1720
pub struct RevokeExportedCdiHandleCmd;
1821
impl RevokeExportedCdiHandleCmd {
@@ -30,13 +33,26 @@ impl RevokeExportedCdiHandleCmd {
3033
}
3134
}
3235

33-
for slot in drivers.exported_cdi_slots.iter_mut() {
36+
for slot in drivers
37+
.persistent_data
38+
.get_mut()
39+
.exported_cdi_slots
40+
.entries
41+
.iter_mut()
42+
{
3443
match slot {
35-
Some((cdi, handle)) if *handle == cmd.exported_cdi_handle => {
44+
ExportedCdiEntry {
45+
key,
46+
handle,
47+
active,
48+
} if *handle == cmd.exported_cdi_handle && active.get() => {
3649
#[cfg(not(feature = "no-cfi"))]
3750
cfi_assert!(*handle == cmd.exported_cdi_handle);
3851

39-
*slot = None;
52+
// Setting to false is redundant with zeroize but included for clarity.
53+
*active = U8Bool::new(false);
54+
slot.zeroize();
55+
4056
return Ok(MailboxResp::RevokeExportedCdiHandle(
4157
RevokeExportedCdiHandleResp::default(),
4258
));

runtime/src/sign_with_exported_ecdsa.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,18 @@ impl SignWithExportedEcdsaCmd {
7171

7272
let key_id_rt_cdi = Drivers::get_key_id_rt_cdi(drivers)?;
7373
let key_id_rt_priv_key = Drivers::get_key_id_rt_priv_key(drivers)?;
74+
let pdata = drivers.persistent_data.get_mut();
7475

7576
let mut crypto = DpeCrypto::new(
7677
&mut drivers.sha384,
7778
&mut drivers.trng,
7879
&mut drivers.ecc384,
7980
&mut drivers.hmac384,
8081
&mut drivers.key_vault,
81-
&mut drivers.persistent_data.get_mut().fht.rt_dice_pub_key,
82+
&mut pdata.fht.rt_dice_pub_key,
8283
key_id_rt_cdi,
8384
key_id_rt_priv_key,
84-
&mut drivers.exported_cdi_slots,
85+
&mut pdata.exported_cdi_slots,
8586
);
8687

8788
let digest = Digest::new(&cmd.tbs)

0 commit comments

Comments
 (0)