blob: 8317e48af467d3283211a6a91977451f91ecfdbd [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
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -080015//! Support for DICE derivation and DICE chain generation.
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000016extern crate alloc;
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000017
Pierre-Clément Tosif5d34852025-03-03 11:44:43 -080018pub(crate) mod chain;
19
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000020use alloc::format;
Pierre-Clément Tosi677de942025-02-11 18:23:44 +000021use alloc::string::String;
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000022use alloc::vec::Vec;
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -080023pub use chain::DiceChainInfo;
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000024use ciborium::cbor;
25use ciborium::Value;
Alice Wang1f0add02023-01-23 16:22:53 +000026use core::mem::size_of;
Alice Wang843d8312023-02-15 09:47:06 +000027use diced_open_dice::{
Alice Wang87fbc4b2024-11-05 13:09:58 +000028 bcc_handover_main_flow, hash, Config, DiceContext, DiceMode, Hash, InputValues, HIDDEN_SIZE,
Alice Wang843d8312023-02-15 09:47:06 +000029};
Alan Stokesa639b582023-11-22 13:14:27 +000030use pvmfw_avb::{Capability, DebugLevel, Digest, VerifiedBootData};
Andrew Walbran47d316e2024-11-28 18:41:09 +000031use zerocopy::Immutable;
32use zerocopy::IntoBytes;
33use zerocopy::KnownLayout;
Alice Wang1f0add02023-01-23 16:22:53 +000034
Shikha Panwar47e5b612024-05-20 19:50:02 +000035// pVM firmware (like other VM components) is expected to populate some fields in DICE
36// Configuration Descriptor. See dice_for_avf_guest.cddl
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000037const COMPONENT_NAME_KEY: i64 = -70002;
38const SECURITY_VERSION_KEY: i64 = -70005;
39const RKP_VM_MARKER_KEY: i64 = -70006;
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000040const INSTANCE_HASH_KEY: i64 = -71003;
41
42#[derive(Debug)]
43pub enum Error {
44 /// Error in CBOR operations
Stephen Hinese1b42892024-08-07 11:03:44 -070045 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000046 CborError(ciborium::value::Error),
47 /// Error in DICE operations
Stephen Hinese1b42892024-08-07 11:03:44 -070048 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000049 DiceError(diced_open_dice::DiceError),
50}
51
52impl From<ciborium::value::Error> for Error {
53 fn from(e: ciborium::value::Error) -> Self {
54 Self::CborError(e)
55 }
56}
57
58impl From<diced_open_dice::DiceError> for Error {
59 fn from(e: diced_open_dice::DiceError) -> Self {
60 Self::DiceError(e)
61 }
62}
63
64// DICE in pvmfw result type.
65type Result<T> = core::result::Result<T, Error>;
66
Alice Wang31226132023-01-31 12:44:39 +000067fn to_dice_mode(debug_level: DebugLevel) -> DiceMode {
Alice Wang1f0add02023-01-23 16:22:53 +000068 match debug_level {
Alice Wang31226132023-01-31 12:44:39 +000069 DebugLevel::None => DiceMode::kDiceModeNormal,
70 DebugLevel::Full => DiceMode::kDiceModeDebug,
Alice Wang1f0add02023-01-23 16:22:53 +000071 }
72}
73
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000074fn to_dice_hash(verified_boot_data: &VerifiedBootData) -> Result<Hash> {
Alice Wang1f0add02023-01-23 16:22:53 +000075 let mut digests = [0u8; size_of::<Digest>() * 2];
76 digests[..size_of::<Digest>()].copy_from_slice(&verified_boot_data.kernel_digest);
77 if let Some(initrd_digest) = verified_boot_data.initrd_digest {
78 digests[size_of::<Digest>()..].copy_from_slice(&initrd_digest);
79 }
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000080 Ok(hash(&digests)?)
Alice Wang1f0add02023-01-23 16:22:53 +000081}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000082
Shikha Panwarf3acfd12024-05-28 15:48:13 +000083#[derive(Clone)]
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000084pub struct PartialInputs {
Pierre-Clément Tosi1cc5eb72023-02-02 11:09:18 +000085 pub code_hash: Hash,
86 pub auth_hash: Hash,
87 pub mode: DiceMode,
Shikha Panwara26f16a2023-09-27 09:39:00 +000088 pub security_version: u64,
Alan Stokesa639b582023-11-22 13:14:27 +000089 pub rkp_vm_marker: bool,
Pierre-Clément Tosi677de942025-02-11 18:23:44 +000090 component_name: String,
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000091}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000092
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000093impl PartialInputs {
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000094 pub fn new(data: &VerifiedBootData) -> Result<Self> {
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000095 let code_hash = to_dice_hash(data)?;
96 let auth_hash = hash(data.public_key)?;
97 let mode = to_dice_mode(data.debug_level);
Pierre-Clément Tosi677de942025-02-11 18:23:44 +000098 let component_name = data.name.clone().unwrap_or(String::from("vm_entry"));
Shikha Panwara26f16a2023-09-27 09:39:00 +000099 // We use rollback_index from vbmeta as the security_version field in dice certificate.
100 let security_version = data.rollback_index;
Alice Wang8b5274a2025-01-17 09:31:43 +0000101 let rkp_vm_marker = data.has_capability(Capability::RemoteAttest)
102 || data.has_capability(Capability::TrustySecurityVm);
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000103
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000104 Ok(Self { code_hash, auth_hash, mode, security_version, rkp_vm_marker, component_name })
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000105 }
106
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800107 pub fn write_next_handover(
Alice Wang843d8312023-02-15 09:47:06 +0000108 self,
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800109 current_handover: &[u8],
Alice Wang843d8312023-02-15 09:47:06 +0000110 salt: &[u8; HIDDEN_SIZE],
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000111 instance_hash: Option<Hash>,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000112 deferred_rollback_protection: bool,
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800113 next_handover: &mut [u8],
Alice Wang87fbc4b2024-11-05 13:09:58 +0000114 context: DiceContext,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000115 ) -> Result<()> {
116 let config = self
117 .generate_config_descriptor(instance_hash)
118 .map_err(|_| diced_open_dice::DiceError::InvalidInput)?;
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000119
Alan Stokesc4354b82023-05-04 16:06:52 +0100120 let dice_inputs = InputValues::new(
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000121 self.code_hash,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000122 Config::Descriptor(&config),
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000123 self.auth_hash,
124 self.mode,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000125 self.make_hidden(salt, deferred_rollback_protection)?,
Alan Stokesc4354b82023-05-04 16:06:52 +0100126 );
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800127 let _ = bcc_handover_main_flow(current_handover, &dice_inputs, next_handover, context)?;
Alan Stokesc4354b82023-05-04 16:06:52 +0100128 Ok(())
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000129 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000130
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000131 fn make_hidden(
132 &self,
133 salt: &[u8; HIDDEN_SIZE],
134 deferred_rollback_protection: bool,
135 ) -> diced_open_dice::Result<[u8; HIDDEN_SIZE]> {
Alan Stokesa17cfba2024-02-14 17:34:51 +0000136 // We want to make sure we get a different sealing CDI for:
137 // - VMs with different salt values
138 // - An RKP VM and any other VM (regardless of salt)
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000139 // - depending on whether rollback protection has been deferred to payload. This ensures the
140 // adversary cannot leak the secrets by using old images & setting
141 // `deferred_rollback_protection` to true.
Alan Stokesa17cfba2024-02-14 17:34:51 +0000142 // The hidden input for DICE affects the sealing CDI (but the values in the config
143 // descriptor do not).
144 // Since the hidden input has to be a fixed size, create it as a hash of the values we
145 // want included.
Andrew Walbran47d316e2024-11-28 18:41:09 +0000146 #[derive(Immutable, IntoBytes, KnownLayout)]
Alan Stokesa17cfba2024-02-14 17:34:51 +0000147 #[repr(C, packed)]
148 struct HiddenInput {
149 rkp_vm_marker: bool,
150 salt: [u8; HIDDEN_SIZE],
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000151 deferred_rollback_protection: bool,
Alan Stokesa17cfba2024-02-14 17:34:51 +0000152 }
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000153 hash(
154 HiddenInput {
155 rkp_vm_marker: self.rkp_vm_marker,
156 salt: *salt,
157 deferred_rollback_protection,
158 }
159 .as_bytes(),
160 )
Alan Stokesa17cfba2024-02-14 17:34:51 +0000161 }
162
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000163 fn generate_config_descriptor(&self, instance_hash: Option<Hash>) -> Result<Vec<u8>> {
164 let mut config = Vec::with_capacity(4);
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000165 config.push((cbor!(COMPONENT_NAME_KEY)?, cbor!(self.component_name.as_str())?));
Alice Wangf13bc4b2025-01-17 10:11:09 +0000166 config.push((cbor!(SECURITY_VERSION_KEY)?, cbor!(self.security_version)?));
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000167 if self.rkp_vm_marker {
168 config.push((cbor!(RKP_VM_MARKER_KEY)?, Value::Null))
169 }
170 if let Some(instance_hash) = instance_hash {
171 config.push((cbor!(INSTANCE_HASH_KEY)?, Value::from(instance_hash.as_slice())));
172 }
173 let config = Value::Map(config);
174 Ok(cbor_util::serialize(&config).map_err(|e| {
175 ciborium::value::Error::Custom(format!("Error in serialization: {e:?}"))
176 })?)
Alan Stokesddb988c2023-11-27 11:13:06 +0000177 }
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000178}
Pierre-Clément Tosibec84662023-01-04 14:25:33 +0000179
Alan Stokesddb988c2023-11-27 11:13:06 +0000180#[cfg(test)]
181mod tests {
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000182 use crate::{
183 Hash, PartialInputs, COMPONENT_NAME_KEY, INSTANCE_HASH_KEY, RKP_VM_MARKER_KEY,
184 SECURITY_VERSION_KEY,
185 };
Alan Stokesddb988c2023-11-27 11:13:06 +0000186 use ciborium::Value;
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800187 use diced_open_dice::bcc_handover_parse;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000188 use diced_open_dice::DiceArtifacts;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000189 use diced_open_dice::DiceContext;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000190 use diced_open_dice::DiceMode;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000191 use diced_open_dice::KeyAlgorithm;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000192 use diced_open_dice::HIDDEN_SIZE;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000193 use diced_sample_inputs::make_sample_bcc_and_cdis;
Alice Wang4dc62912024-12-11 08:27:15 +0000194 use hwtrust::{dice, session::Session};
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000195 use pvmfw_avb::Capability;
196 use pvmfw_avb::DebugLevel;
197 use pvmfw_avb::Digest;
198 use pvmfw_avb::VerifiedBootData;
Alan Stokesddb988c2023-11-27 11:13:06 +0000199 use std::collections::HashMap;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000200 use std::mem::size_of;
Alan Stokesddb988c2023-11-27 11:13:06 +0000201 use std::vec;
202
Alan Stokesddb988c2023-11-27 11:13:06 +0000203 const COMPONENT_VERSION_KEY: i64 = -70003;
204 const RESETTABLE_KEY: i64 = -70004;
Alan Stokesddb988c2023-11-27 11:13:06 +0000205 const BASE_VB_DATA: VerifiedBootData = VerifiedBootData {
206 debug_level: DebugLevel::None,
207 kernel_digest: [1u8; size_of::<Digest>()],
208 initrd_digest: Some([2u8; size_of::<Digest>()]),
209 public_key: b"public key",
Pierre-Clément Tosif1369352024-12-02 18:55:08 +0000210 name: None,
Alan Stokesddb988c2023-11-27 11:13:06 +0000211 capabilities: vec![],
212 rollback_index: 42,
Pierre-Clément Tosi938b4fb2024-11-26 12:59:47 +0000213 page_size: None,
Alan Stokesddb988c2023-11-27 11:13:06 +0000214 };
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000215 const HASH: Hash = *b"sixtyfourbyteslongsentencearerarebutletsgiveitatrycantbethathard";
Alan Stokesddb988c2023-11-27 11:13:06 +0000216
217 #[test]
218 fn base_data_conversion() {
219 let vb_data = BASE_VB_DATA;
220 let inputs = PartialInputs::new(&vb_data).unwrap();
221
222 assert_eq!(inputs.mode, DiceMode::kDiceModeNormal);
223 assert_eq!(inputs.security_version, 42);
224 assert!(!inputs.rkp_vm_marker);
225
226 // TODO(b/313608219): Consider checks for code_hash and possibly auth_hash.
227 }
228
229 #[test]
230 fn debuggable_conversion() {
231 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
232 let inputs = PartialInputs::new(&vb_data).unwrap();
233
234 assert_eq!(inputs.mode, DiceMode::kDiceModeDebug);
235 }
236
237 #[test]
238 fn rkp_vm_conversion() {
239 let vb_data =
240 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
241 let inputs = PartialInputs::new(&vb_data).unwrap();
242
243 assert!(inputs.rkp_vm_marker);
244 }
245
246 #[test]
247 fn base_config_descriptor() {
248 let vb_data = BASE_VB_DATA;
249 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000250 let config_map = decode_config_descriptor(&inputs, None);
Alan Stokesddb988c2023-11-27 11:13:06 +0000251
252 assert_eq!(config_map.get(&COMPONENT_NAME_KEY).unwrap().as_text().unwrap(), "vm_entry");
253 assert_eq!(config_map.get(&COMPONENT_VERSION_KEY), None);
254 assert_eq!(config_map.get(&RESETTABLE_KEY), None);
Alice Wangf13bc4b2025-01-17 10:11:09 +0000255 assert_eq!(config_map.get(&SECURITY_VERSION_KEY).unwrap().as_integer().unwrap(), 42.into());
Alan Stokesddb988c2023-11-27 11:13:06 +0000256 assert_eq!(config_map.get(&RKP_VM_MARKER_KEY), None);
257 }
258
259 #[test]
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000260 fn rkp_vm_config_descriptor_has_rkp_vm_marker_and_component_name() {
Alan Stokesddb988c2023-11-27 11:13:06 +0000261 let vb_data =
262 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
263 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000264 let config_map = decode_config_descriptor(&inputs, Some(HASH));
Alan Stokesddb988c2023-11-27 11:13:06 +0000265
Pierre-Clément Tosi677de942025-02-11 18:23:44 +0000266 assert_eq!(config_map.get(&COMPONENT_NAME_KEY).unwrap().as_text().unwrap(), "vm_entry");
Alan Stokesddb988c2023-11-27 11:13:06 +0000267 assert!(config_map.get(&RKP_VM_MARKER_KEY).unwrap().is_null());
268 }
269
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000270 #[test]
Alice Wang8b5274a2025-01-17 09:31:43 +0000271 fn security_vm_config_descriptor_has_rkp_vm_marker() {
272 let vb_data =
273 VerifiedBootData { capabilities: vec![Capability::TrustySecurityVm], ..BASE_VB_DATA };
274 let inputs = PartialInputs::new(&vb_data).unwrap();
275 let config_map = decode_config_descriptor(&inputs, Some(HASH));
276
277 assert!(config_map.get(&RKP_VM_MARKER_KEY).unwrap().is_null());
278 }
279
280 #[test]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000281 fn config_descriptor_with_instance_hash() {
282 let vb_data =
283 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
284 let inputs = PartialInputs::new(&vb_data).unwrap();
285 let config_map = decode_config_descriptor(&inputs, Some(HASH));
286 assert_eq!(*config_map.get(&INSTANCE_HASH_KEY).unwrap(), Value::from(HASH.as_slice()));
287 }
288
289 #[test]
290 fn config_descriptor_without_instance_hash() {
291 let vb_data =
292 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
293 let inputs = PartialInputs::new(&vb_data).unwrap();
294 let config_map = decode_config_descriptor(&inputs, None);
Chris Wailese9579642024-05-29 18:25:19 -0700295 assert!(!config_map.contains_key(&INSTANCE_HASH_KEY));
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000296 }
297
298 fn decode_config_descriptor(
299 inputs: &PartialInputs,
300 instance_hash: Option<Hash>,
301 ) -> HashMap<i64, Value> {
302 let config_descriptor = inputs.generate_config_descriptor(instance_hash).unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000303
304 let cbor_map =
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000305 cbor_util::deserialize::<Value>(&config_descriptor).unwrap().into_map().unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000306
307 cbor_map
308 .into_iter()
309 .map(|(k, v)| ((k.into_integer().unwrap().try_into().unwrap()), v))
310 .collect()
311 }
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000312
313 #[test]
314 fn changing_deferred_rpb_changes_secrets() {
315 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
316 let inputs = PartialInputs::new(&vb_data).unwrap();
317 let mut buffer_without_defer = [0; 4096];
318 let mut buffer_with_defer = [0; 4096];
319 let mut buffer_without_defer_retry = [0; 4096];
Alice Wang87fbc4b2024-11-05 13:09:58 +0000320 let context = DiceContext {
321 authority_algorithm: KeyAlgorithm::Ed25519,
322 subject_algorithm: KeyAlgorithm::Ed25519,
323 };
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000324
325 let sample_dice_input: &[u8] = &[
326 0xa3, // CDI attest
327 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CDI seal
330 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // DICE chain
333 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22,
334 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40,
335 // 8-bytes of trailing data that aren't part of the DICE chain.
336 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40,
337 ];
338
339 inputs
340 .clone()
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800341 .write_next_handover(
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000342 sample_dice_input,
343 &[0u8; HIDDEN_SIZE],
344 Some([0u8; 64]),
345 false,
346 &mut buffer_without_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000347 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000348 )
349 .unwrap();
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800350 let handover1 = from_serialized_handover(&buffer_without_defer);
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000351
352 inputs
353 .clone()
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800354 .write_next_handover(
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000355 sample_dice_input,
356 &[0u8; HIDDEN_SIZE],
357 Some([0u8; 64]),
358 true,
359 &mut buffer_with_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000360 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000361 )
362 .unwrap();
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800363 let handover2 = from_serialized_handover(&buffer_with_defer);
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000364
365 inputs
366 .clone()
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800367 .write_next_handover(
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000368 sample_dice_input,
369 &[0u8; HIDDEN_SIZE],
370 Some([0u8; 64]),
371 false,
372 &mut buffer_without_defer_retry,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000373 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000374 )
375 .unwrap();
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800376 let handover3 = from_serialized_handover(&buffer_without_defer_retry);
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000377
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800378 assert_ne!(handover1.cdi_seal(), handover2.cdi_seal());
379 assert_eq!(handover1.cdi_seal(), handover3.cdi_seal());
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000380 }
Alice Wang87fbc4b2024-11-05 13:09:58 +0000381
382 #[test]
383 fn dice_derivation_with_different_algorithms_is_valid() {
384 let dice_artifacts = make_sample_bcc_and_cdis().unwrap();
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800385 let handover0_bytes = to_serialized_handover(&dice_artifacts);
Alice Wang87fbc4b2024-11-05 13:09:58 +0000386 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
387 let inputs = PartialInputs::new(&vb_data).unwrap();
388 let mut buffer = [0; 4096];
389
390 inputs
391 .clone()
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800392 .write_next_handover(
393 &handover0_bytes,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000394 &[0u8; HIDDEN_SIZE],
395 Some([0u8; 64]),
396 true,
397 &mut buffer,
398 DiceContext {
399 authority_algorithm: KeyAlgorithm::Ed25519,
400 subject_algorithm: KeyAlgorithm::EcdsaP256,
401 },
402 )
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800403 .expect("Failed to derive Ed25519 -> EcdsaP256 DICE chain");
404 let handover1 = from_serialized_handover(&buffer);
405 let handover1_bytes = to_serialized_handover(&handover1);
Alice Wang87fbc4b2024-11-05 13:09:58 +0000406 buffer.fill(0);
407
408 inputs
409 .clone()
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800410 .write_next_handover(
411 &handover1_bytes,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000412 &[0u8; HIDDEN_SIZE],
413 Some([0u8; 64]),
414 true,
415 &mut buffer,
416 DiceContext {
417 authority_algorithm: KeyAlgorithm::EcdsaP256,
418 subject_algorithm: KeyAlgorithm::EcdsaP384,
419 },
420 )
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800421 .expect("Failed to derive EcdsaP256 -> EcdsaP384 DICE chain");
422 let handover2 = from_serialized_handover(&buffer);
423 let handover2_bytes = to_serialized_handover(&handover2);
Alice Wang87fbc4b2024-11-05 13:09:58 +0000424 buffer.fill(0);
425
426 inputs
427 .clone()
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800428 .write_next_handover(
429 &handover2_bytes,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000430 &[0u8; HIDDEN_SIZE],
431 Some([0u8; 64]),
432 true,
433 &mut buffer,
434 DiceContext {
435 authority_algorithm: KeyAlgorithm::EcdsaP384,
436 subject_algorithm: KeyAlgorithm::Ed25519,
437 },
438 )
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800439 .expect("Failed to derive EcdsaP384 -> Ed25519 DICE chain");
440 let handover3 = from_serialized_handover(&buffer);
Alice Wang87fbc4b2024-11-05 13:09:58 +0000441
Alice Wang4dc62912024-12-11 08:27:15 +0000442 let mut session = Session::default();
443 session.set_allow_any_mode(true);
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800444 let _chain = dice::Chain::from_cbor(&session, handover3.bcc().unwrap()).unwrap();
Alice Wang87fbc4b2024-11-05 13:09:58 +0000445 }
446
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800447 fn to_serialized_handover(dice_artifacts: &dyn DiceArtifacts) -> Vec<u8> {
Alice Wang87fbc4b2024-11-05 13:09:58 +0000448 let dice_chain = cbor_util::deserialize::<Value>(dice_artifacts.bcc().unwrap()).unwrap();
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800449 let handover = Value::Map(vec![
Alice Wang87fbc4b2024-11-05 13:09:58 +0000450 (Value::Integer(1.into()), Value::Bytes(dice_artifacts.cdi_attest().to_vec())),
451 (Value::Integer(2.into()), Value::Bytes(dice_artifacts.cdi_seal().to_vec())),
452 (Value::Integer(3.into()), dice_chain),
453 ]);
Pierre-Clément Tosi520664c2025-03-03 11:51:53 -0800454 cbor_util::serialize(&handover).unwrap()
455 }
456
457 fn from_serialized_handover(bytes: &[u8]) -> diced_open_dice::BccHandover {
458 bcc_handover_parse(bytes).unwrap()
Alice Wang87fbc4b2024-11-05 13:09:58 +0000459 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000460}