blob: 66948816f9efa5b8bea3c14619e5cd960f85884a [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;
19use alloc::vec::Vec;
20use ciborium::cbor;
21use ciborium::Value;
Alice Wang1f0add02023-01-23 16:22:53 +000022use core::mem::size_of;
Alice Wang843d8312023-02-15 09:47:06 +000023use diced_open_dice::{
Alice Wang87fbc4b2024-11-05 13:09:58 +000024 bcc_handover_main_flow, hash, Config, DiceContext, DiceMode, Hash, InputValues, HIDDEN_SIZE,
Alice Wang843d8312023-02-15 09:47:06 +000025};
Alan Stokesa639b582023-11-22 13:14:27 +000026use pvmfw_avb::{Capability, DebugLevel, Digest, VerifiedBootData};
Alan Stokesa17cfba2024-02-14 17:34:51 +000027use zerocopy::AsBytes;
Alice Wang1f0add02023-01-23 16:22:53 +000028
Shikha Panwar47e5b612024-05-20 19:50:02 +000029// pVM firmware (like other VM components) is expected to populate some fields in DICE
30// Configuration Descriptor. See dice_for_avf_guest.cddl
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000031const COMPONENT_NAME_KEY: i64 = -70002;
32const SECURITY_VERSION_KEY: i64 = -70005;
33const RKP_VM_MARKER_KEY: i64 = -70006;
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000034const INSTANCE_HASH_KEY: i64 = -71003;
35
36#[derive(Debug)]
37pub enum Error {
38 /// Error in CBOR operations
Stephen Hinese1b42892024-08-07 11:03:44 -070039 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000040 CborError(ciborium::value::Error),
41 /// Error in DICE operations
Stephen Hinese1b42892024-08-07 11:03:44 -070042 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000043 DiceError(diced_open_dice::DiceError),
44}
45
46impl From<ciborium::value::Error> for Error {
47 fn from(e: ciborium::value::Error) -> Self {
48 Self::CborError(e)
49 }
50}
51
52impl From<diced_open_dice::DiceError> for Error {
53 fn from(e: diced_open_dice::DiceError) -> Self {
54 Self::DiceError(e)
55 }
56}
57
58// DICE in pvmfw result type.
59type Result<T> = core::result::Result<T, Error>;
60
Alice Wang31226132023-01-31 12:44:39 +000061fn to_dice_mode(debug_level: DebugLevel) -> DiceMode {
Alice Wang1f0add02023-01-23 16:22:53 +000062 match debug_level {
Alice Wang31226132023-01-31 12:44:39 +000063 DebugLevel::None => DiceMode::kDiceModeNormal,
64 DebugLevel::Full => DiceMode::kDiceModeDebug,
Alice Wang1f0add02023-01-23 16:22:53 +000065 }
66}
67
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000068fn to_dice_hash(verified_boot_data: &VerifiedBootData) -> Result<Hash> {
Alice Wang1f0add02023-01-23 16:22:53 +000069 let mut digests = [0u8; size_of::<Digest>() * 2];
70 digests[..size_of::<Digest>()].copy_from_slice(&verified_boot_data.kernel_digest);
71 if let Some(initrd_digest) = verified_boot_data.initrd_digest {
72 digests[size_of::<Digest>()..].copy_from_slice(&initrd_digest);
73 }
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000074 Ok(hash(&digests)?)
Alice Wang1f0add02023-01-23 16:22:53 +000075}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000076
Shikha Panwarf3acfd12024-05-28 15:48:13 +000077#[derive(Clone)]
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000078pub struct PartialInputs {
Pierre-Clément Tosi1cc5eb72023-02-02 11:09:18 +000079 pub code_hash: Hash,
80 pub auth_hash: Hash,
81 pub mode: DiceMode,
Shikha Panwara26f16a2023-09-27 09:39:00 +000082 pub security_version: u64,
Alan Stokesa639b582023-11-22 13:14:27 +000083 pub rkp_vm_marker: bool,
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000084}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000085
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000086impl PartialInputs {
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000087 pub fn new(data: &VerifiedBootData) -> Result<Self> {
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000088 let code_hash = to_dice_hash(data)?;
89 let auth_hash = hash(data.public_key)?;
90 let mode = to_dice_mode(data.debug_level);
Shikha Panwara26f16a2023-09-27 09:39:00 +000091 // We use rollback_index from vbmeta as the security_version field in dice certificate.
92 let security_version = data.rollback_index;
Alan Stokesa639b582023-11-22 13:14:27 +000093 let rkp_vm_marker = data.has_capability(Capability::RemoteAttest);
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000094
Alan Stokesa639b582023-11-22 13:14:27 +000095 Ok(Self { code_hash, auth_hash, mode, security_version, rkp_vm_marker })
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000096 }
97
Alan Stokesc4354b82023-05-04 16:06:52 +010098 pub fn write_next_bcc(
Alice Wang843d8312023-02-15 09:47:06 +000099 self,
Alan Stokesc4354b82023-05-04 16:06:52 +0100100 current_bcc_handover: &[u8],
Alice Wang843d8312023-02-15 09:47:06 +0000101 salt: &[u8; HIDDEN_SIZE],
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000102 instance_hash: Option<Hash>,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000103 deferred_rollback_protection: bool,
Alan Stokesc4354b82023-05-04 16:06:52 +0100104 next_bcc: &mut [u8],
Alice Wang87fbc4b2024-11-05 13:09:58 +0000105 context: DiceContext,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000106 ) -> Result<()> {
107 let config = self
108 .generate_config_descriptor(instance_hash)
109 .map_err(|_| diced_open_dice::DiceError::InvalidInput)?;
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000110
Alan Stokesc4354b82023-05-04 16:06:52 +0100111 let dice_inputs = InputValues::new(
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000112 self.code_hash,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000113 Config::Descriptor(&config),
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000114 self.auth_hash,
115 self.mode,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000116 self.make_hidden(salt, deferred_rollback_protection)?,
Alan Stokesc4354b82023-05-04 16:06:52 +0100117 );
Alice Wang87fbc4b2024-11-05 13:09:58 +0000118 let _ = bcc_handover_main_flow(current_bcc_handover, &dice_inputs, next_bcc, context)?;
Alan Stokesc4354b82023-05-04 16:06:52 +0100119 Ok(())
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000120 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000121
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000122 fn make_hidden(
123 &self,
124 salt: &[u8; HIDDEN_SIZE],
125 deferred_rollback_protection: bool,
126 ) -> diced_open_dice::Result<[u8; HIDDEN_SIZE]> {
Alan Stokesa17cfba2024-02-14 17:34:51 +0000127 // We want to make sure we get a different sealing CDI for:
128 // - VMs with different salt values
129 // - An RKP VM and any other VM (regardless of salt)
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000130 // - depending on whether rollback protection has been deferred to payload. This ensures the
131 // adversary cannot leak the secrets by using old images & setting
132 // `deferred_rollback_protection` to true.
Alan Stokesa17cfba2024-02-14 17:34:51 +0000133 // The hidden input for DICE affects the sealing CDI (but the values in the config
134 // descriptor do not).
135 // Since the hidden input has to be a fixed size, create it as a hash of the values we
136 // want included.
137 #[derive(AsBytes)]
138 #[repr(C, packed)]
139 struct HiddenInput {
140 rkp_vm_marker: bool,
141 salt: [u8; HIDDEN_SIZE],
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000142 deferred_rollback_protection: bool,
Alan Stokesa17cfba2024-02-14 17:34:51 +0000143 }
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000144 hash(
145 HiddenInput {
146 rkp_vm_marker: self.rkp_vm_marker,
147 salt: *salt,
148 deferred_rollback_protection,
149 }
150 .as_bytes(),
151 )
Alan Stokesa17cfba2024-02-14 17:34:51 +0000152 }
153
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000154 fn generate_config_descriptor(&self, instance_hash: Option<Hash>) -> Result<Vec<u8>> {
155 let mut config = Vec::with_capacity(4);
156 config.push((cbor!(COMPONENT_NAME_KEY)?, cbor!("vm_entry")?));
157 if cfg!(dice_changes) {
158 config.push((cbor!(SECURITY_VERSION_KEY)?, cbor!(self.security_version)?));
159 }
160 if self.rkp_vm_marker {
161 config.push((cbor!(RKP_VM_MARKER_KEY)?, Value::Null))
162 }
163 if let Some(instance_hash) = instance_hash {
164 config.push((cbor!(INSTANCE_HASH_KEY)?, Value::from(instance_hash.as_slice())));
165 }
166 let config = Value::Map(config);
167 Ok(cbor_util::serialize(&config).map_err(|e| {
168 ciborium::value::Error::Custom(format!("Error in serialization: {e:?}"))
169 })?)
Alan Stokesddb988c2023-11-27 11:13:06 +0000170 }
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000171}
Pierre-Clément Tosibec84662023-01-04 14:25:33 +0000172
Alan Stokesddb988c2023-11-27 11:13:06 +0000173#[cfg(test)]
174mod tests {
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000175 use crate::{
176 Hash, PartialInputs, COMPONENT_NAME_KEY, INSTANCE_HASH_KEY, RKP_VM_MARKER_KEY,
177 SECURITY_VERSION_KEY,
178 };
Alan Stokesddb988c2023-11-27 11:13:06 +0000179 use ciborium::Value;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000180 use diced_open_dice::DiceArtifacts;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000181 use diced_open_dice::DiceContext;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000182 use diced_open_dice::DiceMode;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000183 use diced_open_dice::KeyAlgorithm;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000184 use diced_open_dice::HIDDEN_SIZE;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000185 use diced_sample_inputs::make_sample_bcc_and_cdis;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000186 use pvmfw_avb::Capability;
187 use pvmfw_avb::DebugLevel;
188 use pvmfw_avb::Digest;
189 use pvmfw_avb::VerifiedBootData;
Alan Stokesddb988c2023-11-27 11:13:06 +0000190 use std::collections::HashMap;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000191 use std::mem::size_of;
Alan Stokesddb988c2023-11-27 11:13:06 +0000192 use std::vec;
193
Alan Stokesddb988c2023-11-27 11:13:06 +0000194 const COMPONENT_VERSION_KEY: i64 = -70003;
195 const RESETTABLE_KEY: i64 = -70004;
Alan Stokesddb988c2023-11-27 11:13:06 +0000196 const BASE_VB_DATA: VerifiedBootData = VerifiedBootData {
197 debug_level: DebugLevel::None,
198 kernel_digest: [1u8; size_of::<Digest>()],
199 initrd_digest: Some([2u8; size_of::<Digest>()]),
200 public_key: b"public key",
201 capabilities: vec![],
202 rollback_index: 42,
Pierre-Clément Tosi938b4fb2024-11-26 12:59:47 +0000203 page_size: None,
Alan Stokesddb988c2023-11-27 11:13:06 +0000204 };
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000205 const HASH: Hash = *b"sixtyfourbyteslongsentencearerarebutletsgiveitatrycantbethathard";
Alan Stokesddb988c2023-11-27 11:13:06 +0000206
207 #[test]
208 fn base_data_conversion() {
209 let vb_data = BASE_VB_DATA;
210 let inputs = PartialInputs::new(&vb_data).unwrap();
211
212 assert_eq!(inputs.mode, DiceMode::kDiceModeNormal);
213 assert_eq!(inputs.security_version, 42);
214 assert!(!inputs.rkp_vm_marker);
215
216 // TODO(b/313608219): Consider checks for code_hash and possibly auth_hash.
217 }
218
219 #[test]
220 fn debuggable_conversion() {
221 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
222 let inputs = PartialInputs::new(&vb_data).unwrap();
223
224 assert_eq!(inputs.mode, DiceMode::kDiceModeDebug);
225 }
226
227 #[test]
228 fn rkp_vm_conversion() {
229 let vb_data =
230 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
231 let inputs = PartialInputs::new(&vb_data).unwrap();
232
233 assert!(inputs.rkp_vm_marker);
234 }
235
236 #[test]
237 fn base_config_descriptor() {
238 let vb_data = BASE_VB_DATA;
239 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000240 let config_map = decode_config_descriptor(&inputs, None);
Alan Stokesddb988c2023-11-27 11:13:06 +0000241
242 assert_eq!(config_map.get(&COMPONENT_NAME_KEY).unwrap().as_text().unwrap(), "vm_entry");
243 assert_eq!(config_map.get(&COMPONENT_VERSION_KEY), None);
244 assert_eq!(config_map.get(&RESETTABLE_KEY), None);
245 if cfg!(dice_changes) {
246 assert_eq!(
247 config_map.get(&SECURITY_VERSION_KEY).unwrap().as_integer().unwrap(),
248 42.into()
249 );
250 } else {
251 assert_eq!(config_map.get(&SECURITY_VERSION_KEY), None);
252 }
253 assert_eq!(config_map.get(&RKP_VM_MARKER_KEY), None);
254 }
255
256 #[test]
257 fn config_descriptor_with_rkp_vm() {
258 let vb_data =
259 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
260 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000261 let config_map = decode_config_descriptor(&inputs, Some(HASH));
Alan Stokesddb988c2023-11-27 11:13:06 +0000262
263 assert!(config_map.get(&RKP_VM_MARKER_KEY).unwrap().is_null());
264 }
265
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000266 #[test]
267 fn config_descriptor_with_instance_hash() {
268 let vb_data =
269 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
270 let inputs = PartialInputs::new(&vb_data).unwrap();
271 let config_map = decode_config_descriptor(&inputs, Some(HASH));
272 assert_eq!(*config_map.get(&INSTANCE_HASH_KEY).unwrap(), Value::from(HASH.as_slice()));
273 }
274
275 #[test]
276 fn config_descriptor_without_instance_hash() {
277 let vb_data =
278 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
279 let inputs = PartialInputs::new(&vb_data).unwrap();
280 let config_map = decode_config_descriptor(&inputs, None);
Chris Wailese9579642024-05-29 18:25:19 -0700281 assert!(!config_map.contains_key(&INSTANCE_HASH_KEY));
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000282 }
283
284 fn decode_config_descriptor(
285 inputs: &PartialInputs,
286 instance_hash: Option<Hash>,
287 ) -> HashMap<i64, Value> {
288 let config_descriptor = inputs.generate_config_descriptor(instance_hash).unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000289
290 let cbor_map =
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000291 cbor_util::deserialize::<Value>(&config_descriptor).unwrap().into_map().unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000292
293 cbor_map
294 .into_iter()
295 .map(|(k, v)| ((k.into_integer().unwrap().try_into().unwrap()), v))
296 .collect()
297 }
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000298
299 #[test]
300 fn changing_deferred_rpb_changes_secrets() {
301 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
302 let inputs = PartialInputs::new(&vb_data).unwrap();
303 let mut buffer_without_defer = [0; 4096];
304 let mut buffer_with_defer = [0; 4096];
305 let mut buffer_without_defer_retry = [0; 4096];
Alice Wang87fbc4b2024-11-05 13:09:58 +0000306 let context = DiceContext {
307 authority_algorithm: KeyAlgorithm::Ed25519,
308 subject_algorithm: KeyAlgorithm::Ed25519,
309 };
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000310
311 let sample_dice_input: &[u8] = &[
312 0xa3, // CDI attest
313 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CDI seal
316 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // DICE chain
319 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22,
320 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40,
321 // 8-bytes of trailing data that aren't part of the DICE chain.
322 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40,
323 ];
324
325 inputs
326 .clone()
327 .write_next_bcc(
328 sample_dice_input,
329 &[0u8; HIDDEN_SIZE],
330 Some([0u8; 64]),
331 false,
332 &mut buffer_without_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000333 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000334 )
335 .unwrap();
336 let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer_without_defer).unwrap();
337
338 inputs
339 .clone()
340 .write_next_bcc(
341 sample_dice_input,
342 &[0u8; HIDDEN_SIZE],
343 Some([0u8; 64]),
344 true,
345 &mut buffer_with_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000346 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000347 )
348 .unwrap();
349 let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer_with_defer).unwrap();
350
351 inputs
352 .clone()
353 .write_next_bcc(
354 sample_dice_input,
355 &[0u8; HIDDEN_SIZE],
356 Some([0u8; 64]),
357 false,
358 &mut buffer_without_defer_retry,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000359 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000360 )
361 .unwrap();
362 let bcc_handover3 =
363 diced_open_dice::bcc_handover_parse(&buffer_without_defer_retry).unwrap();
364
365 assert_ne!(bcc_handover1.cdi_seal(), bcc_handover2.cdi_seal());
366 assert_eq!(bcc_handover1.cdi_seal(), bcc_handover3.cdi_seal());
367 }
Alice Wang87fbc4b2024-11-05 13:09:58 +0000368
369 #[test]
370 fn dice_derivation_with_different_algorithms_is_valid() {
371 let dice_artifacts = make_sample_bcc_and_cdis().unwrap();
372 let bcc_handover0_bytes = to_bcc_handover(&dice_artifacts);
373 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
374 let inputs = PartialInputs::new(&vb_data).unwrap();
375 let mut buffer = [0; 4096];
376
377 inputs
378 .clone()
379 .write_next_bcc(
380 &bcc_handover0_bytes,
381 &[0u8; HIDDEN_SIZE],
382 Some([0u8; 64]),
383 true,
384 &mut buffer,
385 DiceContext {
386 authority_algorithm: KeyAlgorithm::Ed25519,
387 subject_algorithm: KeyAlgorithm::EcdsaP256,
388 },
389 )
390 .expect("Failed to derive Ed25519 -> EcdsaP256 BCC");
391 let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
392 let bcc_handover1_bytes = to_bcc_handover(&bcc_handover1);
393 buffer.fill(0);
394
395 inputs
396 .clone()
397 .write_next_bcc(
398 &bcc_handover1_bytes,
399 &[0u8; HIDDEN_SIZE],
400 Some([0u8; 64]),
401 true,
402 &mut buffer,
403 DiceContext {
404 authority_algorithm: KeyAlgorithm::EcdsaP256,
405 subject_algorithm: KeyAlgorithm::EcdsaP384,
406 },
407 )
408 .expect("Failed to derive EcdsaP256 -> EcdsaP384 BCC");
409 let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
410 let bcc_handover2_bytes = to_bcc_handover(&bcc_handover2);
411 buffer.fill(0);
412
413 inputs
414 .clone()
415 .write_next_bcc(
416 &bcc_handover2_bytes,
417 &[0u8; HIDDEN_SIZE],
418 Some([0u8; 64]),
419 true,
420 &mut buffer,
421 DiceContext {
422 authority_algorithm: KeyAlgorithm::EcdsaP384,
423 subject_algorithm: KeyAlgorithm::Ed25519,
424 },
425 )
426 .expect("Failed to derive EcdsaP384 -> Ed25519 BCC");
427 let _bcc_handover3 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
428
429 // TODO(b/378813154): Check the DICE chain with `hwtrust` once the profile version
430 // is updated.
431 // The check cannot be done now because parsing the chain causes the following error:
432 // Invalid payload at index 3. Caused by:
433 // 0: opendice.example.p256
434 // 1: unknown profile version
435 }
436
437 fn to_bcc_handover(dice_artifacts: &dyn DiceArtifacts) -> Vec<u8> {
438 let dice_chain = cbor_util::deserialize::<Value>(dice_artifacts.bcc().unwrap()).unwrap();
439 let bcc_handover = Value::Map(vec![
440 (Value::Integer(1.into()), Value::Bytes(dice_artifacts.cdi_attest().to_vec())),
441 (Value::Integer(2.into()), Value::Bytes(dice_artifacts.cdi_seal().to_vec())),
442 (Value::Integer(3.into()), dice_chain),
443 ]);
444 cbor_util::serialize(&bcc_handover).unwrap()
445 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000446}