blob: 49a38077d5da6d55943f6f399aead4301a5809fd [file] [log] [blame]
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +00001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Support for DICE derivation and BCC generation.
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000016extern crate alloc;
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000017
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000018use alloc::format;
Pierre-Clément Tosi677de942025-02-11 18:23:44 +000019use alloc::string::String;
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000020use alloc::vec::Vec;
21use ciborium::cbor;
22use ciborium::Value;
Alice Wang1f0add02023-01-23 16:22:53 +000023use core::mem::size_of;
Alice Wang843d8312023-02-15 09:47:06 +000024use diced_open_dice::{
Alice Wang87fbc4b2024-11-05 13:09:58 +000025 bcc_handover_main_flow, hash, Config, DiceContext, DiceMode, Hash, InputValues, HIDDEN_SIZE,
Alice Wang843d8312023-02-15 09:47:06 +000026};
Alan Stokesa639b582023-11-22 13:14:27 +000027use pvmfw_avb::{Capability, DebugLevel, Digest, VerifiedBootData};
Andrew Walbran47d316e2024-11-28 18:41:09 +000028use zerocopy::Immutable;
29use zerocopy::IntoBytes;
30use zerocopy::KnownLayout;
Alice Wang1f0add02023-01-23 16:22:53 +000031
Shikha Panwar47e5b612024-05-20 19:50:02 +000032// pVM firmware (like other VM components) is expected to populate some fields in DICE
33// Configuration Descriptor. See dice_for_avf_guest.cddl
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000034const COMPONENT_NAME_KEY: i64 = -70002;
35const SECURITY_VERSION_KEY: i64 = -70005;
36const RKP_VM_MARKER_KEY: i64 = -70006;
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000037const INSTANCE_HASH_KEY: i64 = -71003;
38
39#[derive(Debug)]
40pub enum Error {
41 /// Error in CBOR operations
Stephen Hinese1b42892024-08-07 11:03:44 -070042 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000043 CborError(ciborium::value::Error),
44 /// Error in DICE operations
Stephen Hinese1b42892024-08-07 11:03:44 -070045 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000046 DiceError(diced_open_dice::DiceError),
47}
48
49impl From<ciborium::value::Error> for Error {
50 fn from(e: ciborium::value::Error) -> Self {
51 Self::CborError(e)
52 }
53}
54
55impl From<diced_open_dice::DiceError> for Error {
56 fn from(e: diced_open_dice::DiceError) -> Self {
57 Self::DiceError(e)
58 }
59}
60
61// DICE in pvmfw result type.
62type Result<T> = core::result::Result<T, Error>;
63
Alice Wang31226132023-01-31 12:44:39 +000064fn to_dice_mode(debug_level: DebugLevel) -> DiceMode {
Alice Wang1f0add02023-01-23 16:22:53 +000065 match debug_level {
Alice Wang31226132023-01-31 12:44:39 +000066 DebugLevel::None => DiceMode::kDiceModeNormal,
67 DebugLevel::Full => DiceMode::kDiceModeDebug,
Alice Wang1f0add02023-01-23 16:22:53 +000068 }
69}
70
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000071fn to_dice_hash(verified_boot_data: &VerifiedBootData) -> Result<Hash> {
Alice Wang1f0add02023-01-23 16:22:53 +000072 let mut digests = [0u8; size_of::<Digest>() * 2];
73 digests[..size_of::<Digest>()].copy_from_slice(&verified_boot_data.kernel_digest);
74 if let Some(initrd_digest) = verified_boot_data.initrd_digest {
75 digests[size_of::<Digest>()..].copy_from_slice(&initrd_digest);
76 }
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000077 Ok(hash(&digests)?)
Alice Wang1f0add02023-01-23 16:22:53 +000078}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000079
Shikha Panwarf3acfd12024-05-28 15:48:13 +000080#[derive(Clone)]
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000081pub struct PartialInputs {
Pierre-Clément Tosi1cc5eb72023-02-02 11:09:18 +000082 pub code_hash: Hash,
83 pub auth_hash: Hash,
84 pub mode: DiceMode,
Shikha Panwara26f16a2023-09-27 09:39:00 +000085 pub security_version: u64,
Alan Stokesa639b582023-11-22 13:14:27 +000086 pub rkp_vm_marker: bool,
Pierre-Clément Tosi677de942025-02-11 18:23:44 +000087 component_name: String,
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000088}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000089
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000090impl PartialInputs {
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000091 pub fn new(data: &VerifiedBootData) -> Result<Self> {
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000092 let code_hash = to_dice_hash(data)?;
93 let auth_hash = hash(data.public_key)?;
94 let mode = to_dice_mode(data.debug_level);
Pierre-Clément Tosi677de942025-02-11 18:23:44 +000095 let component_name = data.name.clone().unwrap_or(String::from("vm_entry"));
Shikha Panwara26f16a2023-09-27 09:39:00 +000096 // We use rollback_index from vbmeta as the security_version field in dice certificate.
97 let security_version = data.rollback_index;
Alice Wang8b5274a2025-01-17 09:31:43 +000098 let rkp_vm_marker = data.has_capability(Capability::RemoteAttest)
99 || data.has_capability(Capability::TrustySecurityVm);
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000100
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000101 Ok(Self { code_hash, auth_hash, mode, security_version, rkp_vm_marker, component_name })
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000102 }
103
Alan Stokesc4354b82023-05-04 16:06:52 +0100104 pub fn write_next_bcc(
Alice Wang843d8312023-02-15 09:47:06 +0000105 self,
Alan Stokesc4354b82023-05-04 16:06:52 +0100106 current_bcc_handover: &[u8],
Alice Wang843d8312023-02-15 09:47:06 +0000107 salt: &[u8; HIDDEN_SIZE],
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000108 instance_hash: Option<Hash>,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000109 deferred_rollback_protection: bool,
Alan Stokesc4354b82023-05-04 16:06:52 +0100110 next_bcc: &mut [u8],
Alice Wang87fbc4b2024-11-05 13:09:58 +0000111 context: DiceContext,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000112 ) -> Result<()> {
113 let config = self
114 .generate_config_descriptor(instance_hash)
115 .map_err(|_| diced_open_dice::DiceError::InvalidInput)?;
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000116
Alan Stokesc4354b82023-05-04 16:06:52 +0100117 let dice_inputs = InputValues::new(
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000118 self.code_hash,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000119 Config::Descriptor(&config),
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000120 self.auth_hash,
121 self.mode,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000122 self.make_hidden(salt, deferred_rollback_protection)?,
Alan Stokesc4354b82023-05-04 16:06:52 +0100123 );
Alice Wang87fbc4b2024-11-05 13:09:58 +0000124 let _ = bcc_handover_main_flow(current_bcc_handover, &dice_inputs, next_bcc, context)?;
Alan Stokesc4354b82023-05-04 16:06:52 +0100125 Ok(())
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000126 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000127
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000128 fn make_hidden(
129 &self,
130 salt: &[u8; HIDDEN_SIZE],
131 deferred_rollback_protection: bool,
132 ) -> diced_open_dice::Result<[u8; HIDDEN_SIZE]> {
Alan Stokesa17cfba2024-02-14 17:34:51 +0000133 // We want to make sure we get a different sealing CDI for:
134 // - VMs with different salt values
135 // - An RKP VM and any other VM (regardless of salt)
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000136 // - depending on whether rollback protection has been deferred to payload. This ensures the
137 // adversary cannot leak the secrets by using old images & setting
138 // `deferred_rollback_protection` to true.
Alan Stokesa17cfba2024-02-14 17:34:51 +0000139 // The hidden input for DICE affects the sealing CDI (but the values in the config
140 // descriptor do not).
141 // Since the hidden input has to be a fixed size, create it as a hash of the values we
142 // want included.
Andrew Walbran47d316e2024-11-28 18:41:09 +0000143 #[derive(Immutable, IntoBytes, KnownLayout)]
Alan Stokesa17cfba2024-02-14 17:34:51 +0000144 #[repr(C, packed)]
145 struct HiddenInput {
146 rkp_vm_marker: bool,
147 salt: [u8; HIDDEN_SIZE],
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000148 deferred_rollback_protection: bool,
Alan Stokesa17cfba2024-02-14 17:34:51 +0000149 }
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000150 hash(
151 HiddenInput {
152 rkp_vm_marker: self.rkp_vm_marker,
153 salt: *salt,
154 deferred_rollback_protection,
155 }
156 .as_bytes(),
157 )
Alan Stokesa17cfba2024-02-14 17:34:51 +0000158 }
159
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000160 fn generate_config_descriptor(&self, instance_hash: Option<Hash>) -> Result<Vec<u8>> {
161 let mut config = Vec::with_capacity(4);
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000162 config.push((cbor!(COMPONENT_NAME_KEY)?, cbor!(self.component_name.as_str())?));
Alice Wangf13bc4b2025-01-17 10:11:09 +0000163 config.push((cbor!(SECURITY_VERSION_KEY)?, cbor!(self.security_version)?));
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000164 if self.rkp_vm_marker {
165 config.push((cbor!(RKP_VM_MARKER_KEY)?, Value::Null))
166 }
167 if let Some(instance_hash) = instance_hash {
168 config.push((cbor!(INSTANCE_HASH_KEY)?, Value::from(instance_hash.as_slice())));
169 }
170 let config = Value::Map(config);
171 Ok(cbor_util::serialize(&config).map_err(|e| {
172 ciborium::value::Error::Custom(format!("Error in serialization: {e:?}"))
173 })?)
Alan Stokesddb988c2023-11-27 11:13:06 +0000174 }
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000175}
Pierre-Clément Tosibec84662023-01-04 14:25:33 +0000176
Alan Stokesddb988c2023-11-27 11:13:06 +0000177#[cfg(test)]
178mod tests {
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000179 use crate::{
180 Hash, PartialInputs, COMPONENT_NAME_KEY, INSTANCE_HASH_KEY, RKP_VM_MARKER_KEY,
181 SECURITY_VERSION_KEY,
182 };
Alan Stokesddb988c2023-11-27 11:13:06 +0000183 use ciborium::Value;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000184 use diced_open_dice::DiceArtifacts;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000185 use diced_open_dice::DiceContext;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000186 use diced_open_dice::DiceMode;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000187 use diced_open_dice::KeyAlgorithm;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000188 use diced_open_dice::HIDDEN_SIZE;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000189 use diced_sample_inputs::make_sample_bcc_and_cdis;
Alice Wang4dc62912024-12-11 08:27:15 +0000190 use hwtrust::{dice, session::Session};
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000191 use pvmfw_avb::Capability;
192 use pvmfw_avb::DebugLevel;
193 use pvmfw_avb::Digest;
194 use pvmfw_avb::VerifiedBootData;
Alan Stokesddb988c2023-11-27 11:13:06 +0000195 use std::collections::HashMap;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000196 use std::mem::size_of;
Alan Stokesddb988c2023-11-27 11:13:06 +0000197 use std::vec;
198
Alan Stokesddb988c2023-11-27 11:13:06 +0000199 const COMPONENT_VERSION_KEY: i64 = -70003;
200 const RESETTABLE_KEY: i64 = -70004;
Alan Stokesddb988c2023-11-27 11:13:06 +0000201 const BASE_VB_DATA: VerifiedBootData = VerifiedBootData {
202 debug_level: DebugLevel::None,
203 kernel_digest: [1u8; size_of::<Digest>()],
204 initrd_digest: Some([2u8; size_of::<Digest>()]),
205 public_key: b"public key",
Pierre-Clément Tosif1369352024-12-02 18:55:08 +0000206 name: None,
Alan Stokesddb988c2023-11-27 11:13:06 +0000207 capabilities: vec![],
208 rollback_index: 42,
Pierre-Clément Tosi938b4fb2024-11-26 12:59:47 +0000209 page_size: None,
Alan Stokesddb988c2023-11-27 11:13:06 +0000210 };
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000211 const HASH: Hash = *b"sixtyfourbyteslongsentencearerarebutletsgiveitatrycantbethathard";
Alan Stokesddb988c2023-11-27 11:13:06 +0000212
213 #[test]
214 fn base_data_conversion() {
215 let vb_data = BASE_VB_DATA;
216 let inputs = PartialInputs::new(&vb_data).unwrap();
217
218 assert_eq!(inputs.mode, DiceMode::kDiceModeNormal);
219 assert_eq!(inputs.security_version, 42);
220 assert!(!inputs.rkp_vm_marker);
221
222 // TODO(b/313608219): Consider checks for code_hash and possibly auth_hash.
223 }
224
225 #[test]
226 fn debuggable_conversion() {
227 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
228 let inputs = PartialInputs::new(&vb_data).unwrap();
229
230 assert_eq!(inputs.mode, DiceMode::kDiceModeDebug);
231 }
232
233 #[test]
234 fn rkp_vm_conversion() {
235 let vb_data =
236 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
237 let inputs = PartialInputs::new(&vb_data).unwrap();
238
239 assert!(inputs.rkp_vm_marker);
240 }
241
242 #[test]
243 fn base_config_descriptor() {
244 let vb_data = BASE_VB_DATA;
245 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000246 let config_map = decode_config_descriptor(&inputs, None);
Alan Stokesddb988c2023-11-27 11:13:06 +0000247
248 assert_eq!(config_map.get(&COMPONENT_NAME_KEY).unwrap().as_text().unwrap(), "vm_entry");
249 assert_eq!(config_map.get(&COMPONENT_VERSION_KEY), None);
250 assert_eq!(config_map.get(&RESETTABLE_KEY), None);
Alice Wangf13bc4b2025-01-17 10:11:09 +0000251 assert_eq!(config_map.get(&SECURITY_VERSION_KEY).unwrap().as_integer().unwrap(), 42.into());
Alan Stokesddb988c2023-11-27 11:13:06 +0000252 assert_eq!(config_map.get(&RKP_VM_MARKER_KEY), None);
253 }
254
255 #[test]
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000256 fn rkp_vm_config_descriptor_has_rkp_vm_marker_and_component_name() {
Alan Stokesddb988c2023-11-27 11:13:06 +0000257 let vb_data =
258 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
259 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000260 let config_map = decode_config_descriptor(&inputs, Some(HASH));
Alan Stokesddb988c2023-11-27 11:13:06 +0000261
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000262 assert_eq!(config_map.get(&COMPONENT_NAME_KEY).unwrap().as_text().unwrap(), "vm_entry");
Alan Stokesddb988c2023-11-27 11:13:06 +0000263 assert!(config_map.get(&RKP_VM_MARKER_KEY).unwrap().is_null());
264 }
265
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000266 #[test]
Alice Wang8b5274a2025-01-17 09:31:43 +0000267 fn security_vm_config_descriptor_has_rkp_vm_marker() {
268 let vb_data =
269 VerifiedBootData { capabilities: vec![Capability::TrustySecurityVm], ..BASE_VB_DATA };
270 let inputs = PartialInputs::new(&vb_data).unwrap();
271 let config_map = decode_config_descriptor(&inputs, Some(HASH));
272
273 assert!(config_map.get(&RKP_VM_MARKER_KEY).unwrap().is_null());
274 }
275
276 #[test]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000277 fn config_descriptor_with_instance_hash() {
278 let vb_data =
279 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
280 let inputs = PartialInputs::new(&vb_data).unwrap();
281 let config_map = decode_config_descriptor(&inputs, Some(HASH));
282 assert_eq!(*config_map.get(&INSTANCE_HASH_KEY).unwrap(), Value::from(HASH.as_slice()));
283 }
284
285 #[test]
286 fn config_descriptor_without_instance_hash() {
287 let vb_data =
288 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
289 let inputs = PartialInputs::new(&vb_data).unwrap();
290 let config_map = decode_config_descriptor(&inputs, None);
Chris Wailese9579642024-05-29 18:25:19 -0700291 assert!(!config_map.contains_key(&INSTANCE_HASH_KEY));
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000292 }
293
294 fn decode_config_descriptor(
295 inputs: &PartialInputs,
296 instance_hash: Option<Hash>,
297 ) -> HashMap<i64, Value> {
298 let config_descriptor = inputs.generate_config_descriptor(instance_hash).unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000299
300 let cbor_map =
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000301 cbor_util::deserialize::<Value>(&config_descriptor).unwrap().into_map().unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000302
303 cbor_map
304 .into_iter()
305 .map(|(k, v)| ((k.into_integer().unwrap().try_into().unwrap()), v))
306 .collect()
307 }
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000308
309 #[test]
310 fn changing_deferred_rpb_changes_secrets() {
311 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
312 let inputs = PartialInputs::new(&vb_data).unwrap();
313 let mut buffer_without_defer = [0; 4096];
314 let mut buffer_with_defer = [0; 4096];
315 let mut buffer_without_defer_retry = [0; 4096];
Alice Wang87fbc4b2024-11-05 13:09:58 +0000316 let context = DiceContext {
317 authority_algorithm: KeyAlgorithm::Ed25519,
318 subject_algorithm: KeyAlgorithm::Ed25519,
319 };
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000320
321 let sample_dice_input: &[u8] = &[
322 0xa3, // CDI attest
323 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CDI seal
326 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // DICE chain
329 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22,
330 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40,
331 // 8-bytes of trailing data that aren't part of the DICE chain.
332 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40,
333 ];
334
335 inputs
336 .clone()
337 .write_next_bcc(
338 sample_dice_input,
339 &[0u8; HIDDEN_SIZE],
340 Some([0u8; 64]),
341 false,
342 &mut buffer_without_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000343 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000344 )
345 .unwrap();
346 let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer_without_defer).unwrap();
347
348 inputs
349 .clone()
350 .write_next_bcc(
351 sample_dice_input,
352 &[0u8; HIDDEN_SIZE],
353 Some([0u8; 64]),
354 true,
355 &mut buffer_with_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000356 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000357 )
358 .unwrap();
359 let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer_with_defer).unwrap();
360
361 inputs
362 .clone()
363 .write_next_bcc(
364 sample_dice_input,
365 &[0u8; HIDDEN_SIZE],
366 Some([0u8; 64]),
367 false,
368 &mut buffer_without_defer_retry,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000369 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000370 )
371 .unwrap();
372 let bcc_handover3 =
373 diced_open_dice::bcc_handover_parse(&buffer_without_defer_retry).unwrap();
374
375 assert_ne!(bcc_handover1.cdi_seal(), bcc_handover2.cdi_seal());
376 assert_eq!(bcc_handover1.cdi_seal(), bcc_handover3.cdi_seal());
377 }
Alice Wang87fbc4b2024-11-05 13:09:58 +0000378
379 #[test]
380 fn dice_derivation_with_different_algorithms_is_valid() {
381 let dice_artifacts = make_sample_bcc_and_cdis().unwrap();
382 let bcc_handover0_bytes = to_bcc_handover(&dice_artifacts);
383 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
384 let inputs = PartialInputs::new(&vb_data).unwrap();
385 let mut buffer = [0; 4096];
386
387 inputs
388 .clone()
389 .write_next_bcc(
390 &bcc_handover0_bytes,
391 &[0u8; HIDDEN_SIZE],
392 Some([0u8; 64]),
393 true,
394 &mut buffer,
395 DiceContext {
396 authority_algorithm: KeyAlgorithm::Ed25519,
397 subject_algorithm: KeyAlgorithm::EcdsaP256,
398 },
399 )
400 .expect("Failed to derive Ed25519 -> EcdsaP256 BCC");
401 let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
402 let bcc_handover1_bytes = to_bcc_handover(&bcc_handover1);
403 buffer.fill(0);
404
405 inputs
406 .clone()
407 .write_next_bcc(
408 &bcc_handover1_bytes,
409 &[0u8; HIDDEN_SIZE],
410 Some([0u8; 64]),
411 true,
412 &mut buffer,
413 DiceContext {
414 authority_algorithm: KeyAlgorithm::EcdsaP256,
415 subject_algorithm: KeyAlgorithm::EcdsaP384,
416 },
417 )
418 .expect("Failed to derive EcdsaP256 -> EcdsaP384 BCC");
419 let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
420 let bcc_handover2_bytes = to_bcc_handover(&bcc_handover2);
421 buffer.fill(0);
422
423 inputs
424 .clone()
425 .write_next_bcc(
426 &bcc_handover2_bytes,
427 &[0u8; HIDDEN_SIZE],
428 Some([0u8; 64]),
429 true,
430 &mut buffer,
431 DiceContext {
432 authority_algorithm: KeyAlgorithm::EcdsaP384,
433 subject_algorithm: KeyAlgorithm::Ed25519,
434 },
435 )
436 .expect("Failed to derive EcdsaP384 -> Ed25519 BCC");
Alice Wang4dc62912024-12-11 08:27:15 +0000437 let bcc_handover3 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
Alice Wang87fbc4b2024-11-05 13:09:58 +0000438
Alice Wang4dc62912024-12-11 08:27:15 +0000439 let mut session = Session::default();
440 session.set_allow_any_mode(true);
441 let _chain = dice::Chain::from_cbor(&session, bcc_handover3.bcc().unwrap()).unwrap();
Alice Wang87fbc4b2024-11-05 13:09:58 +0000442 }
443
444 fn to_bcc_handover(dice_artifacts: &dyn DiceArtifacts) -> Vec<u8> {
445 let dice_chain = cbor_util::deserialize::<Value>(dice_artifacts.bcc().unwrap()).unwrap();
446 let bcc_handover = Value::Map(vec![
447 (Value::Integer(1.into()), Value::Bytes(dice_artifacts.cdi_attest().to_vec())),
448 (Value::Integer(2.into()), Value::Bytes(dice_artifacts.cdi_seal().to_vec())),
449 (Value::Integer(3.into()), dice_chain),
450 ]);
451 cbor_util::serialize(&bcc_handover).unwrap()
452 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000453}