blob: a72c1fce2b8a5031fc2a83db54b4f1c92dfb4aaa [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};
Andrew Walbran47d316e2024-11-28 18:41:09 +000027use zerocopy::Immutable;
28use zerocopy::IntoBytes;
29use zerocopy::KnownLayout;
Alice Wang1f0add02023-01-23 16:22:53 +000030
Shikha Panwar47e5b612024-05-20 19:50:02 +000031// pVM firmware (like other VM components) is expected to populate some fields in DICE
32// Configuration Descriptor. See dice_for_avf_guest.cddl
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000033const COMPONENT_NAME_KEY: i64 = -70002;
34const SECURITY_VERSION_KEY: i64 = -70005;
35const RKP_VM_MARKER_KEY: i64 = -70006;
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000036const INSTANCE_HASH_KEY: i64 = -71003;
37
38#[derive(Debug)]
39pub enum Error {
40 /// Error in CBOR operations
Stephen Hinese1b42892024-08-07 11:03:44 -070041 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000042 CborError(ciborium::value::Error),
43 /// Error in DICE operations
Stephen Hinese1b42892024-08-07 11:03:44 -070044 #[allow(dead_code)]
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000045 DiceError(diced_open_dice::DiceError),
46}
47
48impl From<ciborium::value::Error> for Error {
49 fn from(e: ciborium::value::Error) -> Self {
50 Self::CborError(e)
51 }
52}
53
54impl From<diced_open_dice::DiceError> for Error {
55 fn from(e: diced_open_dice::DiceError) -> Self {
56 Self::DiceError(e)
57 }
58}
59
60// DICE in pvmfw result type.
61type Result<T> = core::result::Result<T, Error>;
62
Alice Wang31226132023-01-31 12:44:39 +000063fn to_dice_mode(debug_level: DebugLevel) -> DiceMode {
Alice Wang1f0add02023-01-23 16:22:53 +000064 match debug_level {
Alice Wang31226132023-01-31 12:44:39 +000065 DebugLevel::None => DiceMode::kDiceModeNormal,
66 DebugLevel::Full => DiceMode::kDiceModeDebug,
Alice Wang1f0add02023-01-23 16:22:53 +000067 }
68}
69
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000070fn to_dice_hash(verified_boot_data: &VerifiedBootData) -> Result<Hash> {
Alice Wang1f0add02023-01-23 16:22:53 +000071 let mut digests = [0u8; size_of::<Digest>() * 2];
72 digests[..size_of::<Digest>()].copy_from_slice(&verified_boot_data.kernel_digest);
73 if let Some(initrd_digest) = verified_boot_data.initrd_digest {
74 digests[size_of::<Digest>()..].copy_from_slice(&initrd_digest);
75 }
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000076 Ok(hash(&digests)?)
Alice Wang1f0add02023-01-23 16:22:53 +000077}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000078
Shikha Panwarf3acfd12024-05-28 15:48:13 +000079#[derive(Clone)]
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000080pub struct PartialInputs {
Pierre-Clément Tosi1cc5eb72023-02-02 11:09:18 +000081 pub code_hash: Hash,
82 pub auth_hash: Hash,
83 pub mode: DiceMode,
Shikha Panwara26f16a2023-09-27 09:39:00 +000084 pub security_version: u64,
Alan Stokesa639b582023-11-22 13:14:27 +000085 pub rkp_vm_marker: bool,
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000086}
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000087
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000088impl PartialInputs {
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +000089 pub fn new(data: &VerifiedBootData) -> Result<Self> {
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000090 let code_hash = to_dice_hash(data)?;
91 let auth_hash = hash(data.public_key)?;
92 let mode = to_dice_mode(data.debug_level);
Shikha Panwara26f16a2023-09-27 09:39:00 +000093 // We use rollback_index from vbmeta as the security_version field in dice certificate.
94 let security_version = data.rollback_index;
Alan Stokesa639b582023-11-22 13:14:27 +000095 let rkp_vm_marker = data.has_capability(Capability::RemoteAttest);
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +000096
Alan Stokesa639b582023-11-22 13:14:27 +000097 Ok(Self { code_hash, auth_hash, mode, security_version, rkp_vm_marker })
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000098 }
99
Alan Stokesc4354b82023-05-04 16:06:52 +0100100 pub fn write_next_bcc(
Alice Wang843d8312023-02-15 09:47:06 +0000101 self,
Alan Stokesc4354b82023-05-04 16:06:52 +0100102 current_bcc_handover: &[u8],
Alice Wang843d8312023-02-15 09:47:06 +0000103 salt: &[u8; HIDDEN_SIZE],
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000104 instance_hash: Option<Hash>,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000105 deferred_rollback_protection: bool,
Alan Stokesc4354b82023-05-04 16:06:52 +0100106 next_bcc: &mut [u8],
Alice Wang87fbc4b2024-11-05 13:09:58 +0000107 context: DiceContext,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000108 ) -> Result<()> {
109 let config = self
110 .generate_config_descriptor(instance_hash)
111 .map_err(|_| diced_open_dice::DiceError::InvalidInput)?;
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000112
Alan Stokesc4354b82023-05-04 16:06:52 +0100113 let dice_inputs = InputValues::new(
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000114 self.code_hash,
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000115 Config::Descriptor(&config),
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000116 self.auth_hash,
117 self.mode,
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000118 self.make_hidden(salt, deferred_rollback_protection)?,
Alan Stokesc4354b82023-05-04 16:06:52 +0100119 );
Alice Wang87fbc4b2024-11-05 13:09:58 +0000120 let _ = bcc_handover_main_flow(current_bcc_handover, &dice_inputs, next_bcc, context)?;
Alan Stokesc4354b82023-05-04 16:06:52 +0100121 Ok(())
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +0000122 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000123
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000124 fn make_hidden(
125 &self,
126 salt: &[u8; HIDDEN_SIZE],
127 deferred_rollback_protection: bool,
128 ) -> diced_open_dice::Result<[u8; HIDDEN_SIZE]> {
Alan Stokesa17cfba2024-02-14 17:34:51 +0000129 // We want to make sure we get a different sealing CDI for:
130 // - VMs with different salt values
131 // - An RKP VM and any other VM (regardless of salt)
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000132 // - depending on whether rollback protection has been deferred to payload. This ensures the
133 // adversary cannot leak the secrets by using old images & setting
134 // `deferred_rollback_protection` to true.
Alan Stokesa17cfba2024-02-14 17:34:51 +0000135 // The hidden input for DICE affects the sealing CDI (but the values in the config
136 // descriptor do not).
137 // Since the hidden input has to be a fixed size, create it as a hash of the values we
138 // want included.
Andrew Walbran47d316e2024-11-28 18:41:09 +0000139 #[derive(Immutable, IntoBytes, KnownLayout)]
Alan Stokesa17cfba2024-02-14 17:34:51 +0000140 #[repr(C, packed)]
141 struct HiddenInput {
142 rkp_vm_marker: bool,
143 salt: [u8; HIDDEN_SIZE],
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000144 deferred_rollback_protection: bool,
Alan Stokesa17cfba2024-02-14 17:34:51 +0000145 }
Shikha Panwarffadd4d2024-05-28 13:47:56 +0000146 hash(
147 HiddenInput {
148 rkp_vm_marker: self.rkp_vm_marker,
149 salt: *salt,
150 deferred_rollback_protection,
151 }
152 .as_bytes(),
153 )
Alan Stokesa17cfba2024-02-14 17:34:51 +0000154 }
155
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000156 fn generate_config_descriptor(&self, instance_hash: Option<Hash>) -> Result<Vec<u8>> {
157 let mut config = Vec::with_capacity(4);
158 config.push((cbor!(COMPONENT_NAME_KEY)?, cbor!("vm_entry")?));
159 if cfg!(dice_changes) {
160 config.push((cbor!(SECURITY_VERSION_KEY)?, cbor!(self.security_version)?));
161 }
162 if self.rkp_vm_marker {
163 config.push((cbor!(RKP_VM_MARKER_KEY)?, Value::Null))
164 }
165 if let Some(instance_hash) = instance_hash {
166 config.push((cbor!(INSTANCE_HASH_KEY)?, Value::from(instance_hash.as_slice())));
167 }
168 let config = Value::Map(config);
169 Ok(cbor_util::serialize(&config).map_err(|e| {
170 ciborium::value::Error::Custom(format!("Error in serialization: {e:?}"))
171 })?)
Alan Stokesddb988c2023-11-27 11:13:06 +0000172 }
Pierre-Clément Tosi4f4f5eb2022-12-08 14:31:42 +0000173}
Pierre-Clément Tosibec84662023-01-04 14:25:33 +0000174
Alan Stokesddb988c2023-11-27 11:13:06 +0000175#[cfg(test)]
176mod tests {
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000177 use crate::{
178 Hash, PartialInputs, COMPONENT_NAME_KEY, INSTANCE_HASH_KEY, RKP_VM_MARKER_KEY,
179 SECURITY_VERSION_KEY,
180 };
Alan Stokesddb988c2023-11-27 11:13:06 +0000181 use ciborium::Value;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000182 use diced_open_dice::DiceArtifacts;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000183 use diced_open_dice::DiceContext;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000184 use diced_open_dice::DiceMode;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000185 use diced_open_dice::KeyAlgorithm;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000186 use diced_open_dice::HIDDEN_SIZE;
Alice Wang87fbc4b2024-11-05 13:09:58 +0000187 use diced_sample_inputs::make_sample_bcc_and_cdis;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000188 use pvmfw_avb::Capability;
189 use pvmfw_avb::DebugLevel;
190 use pvmfw_avb::Digest;
191 use pvmfw_avb::VerifiedBootData;
Alan Stokesddb988c2023-11-27 11:13:06 +0000192 use std::collections::HashMap;
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000193 use std::mem::size_of;
Alan Stokesddb988c2023-11-27 11:13:06 +0000194 use std::vec;
195
Alan Stokesddb988c2023-11-27 11:13:06 +0000196 const COMPONENT_VERSION_KEY: i64 = -70003;
197 const RESETTABLE_KEY: i64 = -70004;
Alan Stokesddb988c2023-11-27 11:13:06 +0000198 const BASE_VB_DATA: VerifiedBootData = VerifiedBootData {
199 debug_level: DebugLevel::None,
200 kernel_digest: [1u8; size_of::<Digest>()],
201 initrd_digest: Some([2u8; size_of::<Digest>()]),
202 public_key: b"public key",
203 capabilities: vec![],
204 rollback_index: 42,
Pierre-Clément Tosi938b4fb2024-11-26 12:59:47 +0000205 page_size: None,
Alan Stokesddb988c2023-11-27 11:13:06 +0000206 };
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000207 const HASH: Hash = *b"sixtyfourbyteslongsentencearerarebutletsgiveitatrycantbethathard";
Alan Stokesddb988c2023-11-27 11:13:06 +0000208
209 #[test]
210 fn base_data_conversion() {
211 let vb_data = BASE_VB_DATA;
212 let inputs = PartialInputs::new(&vb_data).unwrap();
213
214 assert_eq!(inputs.mode, DiceMode::kDiceModeNormal);
215 assert_eq!(inputs.security_version, 42);
216 assert!(!inputs.rkp_vm_marker);
217
218 // TODO(b/313608219): Consider checks for code_hash and possibly auth_hash.
219 }
220
221 #[test]
222 fn debuggable_conversion() {
223 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
224 let inputs = PartialInputs::new(&vb_data).unwrap();
225
226 assert_eq!(inputs.mode, DiceMode::kDiceModeDebug);
227 }
228
229 #[test]
230 fn rkp_vm_conversion() {
231 let vb_data =
232 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
233 let inputs = PartialInputs::new(&vb_data).unwrap();
234
235 assert!(inputs.rkp_vm_marker);
236 }
237
238 #[test]
239 fn base_config_descriptor() {
240 let vb_data = BASE_VB_DATA;
241 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000242 let config_map = decode_config_descriptor(&inputs, None);
Alan Stokesddb988c2023-11-27 11:13:06 +0000243
244 assert_eq!(config_map.get(&COMPONENT_NAME_KEY).unwrap().as_text().unwrap(), "vm_entry");
245 assert_eq!(config_map.get(&COMPONENT_VERSION_KEY), None);
246 assert_eq!(config_map.get(&RESETTABLE_KEY), None);
247 if cfg!(dice_changes) {
248 assert_eq!(
249 config_map.get(&SECURITY_VERSION_KEY).unwrap().as_integer().unwrap(),
250 42.into()
251 );
252 } else {
253 assert_eq!(config_map.get(&SECURITY_VERSION_KEY), None);
254 }
255 assert_eq!(config_map.get(&RKP_VM_MARKER_KEY), None);
256 }
257
258 #[test]
259 fn config_descriptor_with_rkp_vm() {
260 let vb_data =
261 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
262 let inputs = PartialInputs::new(&vb_data).unwrap();
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000263 let config_map = decode_config_descriptor(&inputs, Some(HASH));
Alan Stokesddb988c2023-11-27 11:13:06 +0000264
265 assert!(config_map.get(&RKP_VM_MARKER_KEY).unwrap().is_null());
266 }
267
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000268 #[test]
269 fn config_descriptor_with_instance_hash() {
270 let vb_data =
271 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
272 let inputs = PartialInputs::new(&vb_data).unwrap();
273 let config_map = decode_config_descriptor(&inputs, Some(HASH));
274 assert_eq!(*config_map.get(&INSTANCE_HASH_KEY).unwrap(), Value::from(HASH.as_slice()));
275 }
276
277 #[test]
278 fn config_descriptor_without_instance_hash() {
279 let vb_data =
280 VerifiedBootData { capabilities: vec![Capability::RemoteAttest], ..BASE_VB_DATA };
281 let inputs = PartialInputs::new(&vb_data).unwrap();
282 let config_map = decode_config_descriptor(&inputs, None);
Chris Wailese9579642024-05-29 18:25:19 -0700283 assert!(!config_map.contains_key(&INSTANCE_HASH_KEY));
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000284 }
285
286 fn decode_config_descriptor(
287 inputs: &PartialInputs,
288 instance_hash: Option<Hash>,
289 ) -> HashMap<i64, Value> {
290 let config_descriptor = inputs.generate_config_descriptor(instance_hash).unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000291
292 let cbor_map =
Shikha Panwar8f7fc1a2024-04-10 10:41:34 +0000293 cbor_util::deserialize::<Value>(&config_descriptor).unwrap().into_map().unwrap();
Alan Stokesddb988c2023-11-27 11:13:06 +0000294
295 cbor_map
296 .into_iter()
297 .map(|(k, v)| ((k.into_integer().unwrap().try_into().unwrap()), v))
298 .collect()
299 }
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000300
301 #[test]
302 fn changing_deferred_rpb_changes_secrets() {
303 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
304 let inputs = PartialInputs::new(&vb_data).unwrap();
305 let mut buffer_without_defer = [0; 4096];
306 let mut buffer_with_defer = [0; 4096];
307 let mut buffer_without_defer_retry = [0; 4096];
Alice Wang87fbc4b2024-11-05 13:09:58 +0000308 let context = DiceContext {
309 authority_algorithm: KeyAlgorithm::Ed25519,
310 subject_algorithm: KeyAlgorithm::Ed25519,
311 };
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000312
313 let sample_dice_input: &[u8] = &[
314 0xa3, // CDI attest
315 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CDI seal
318 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // DICE chain
321 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22,
322 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40,
323 // 8-bytes of trailing data that aren't part of the DICE chain.
324 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40,
325 ];
326
327 inputs
328 .clone()
329 .write_next_bcc(
330 sample_dice_input,
331 &[0u8; HIDDEN_SIZE],
332 Some([0u8; 64]),
333 false,
334 &mut buffer_without_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000335 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000336 )
337 .unwrap();
338 let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer_without_defer).unwrap();
339
340 inputs
341 .clone()
342 .write_next_bcc(
343 sample_dice_input,
344 &[0u8; HIDDEN_SIZE],
345 Some([0u8; 64]),
346 true,
347 &mut buffer_with_defer,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000348 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000349 )
350 .unwrap();
351 let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer_with_defer).unwrap();
352
353 inputs
354 .clone()
355 .write_next_bcc(
356 sample_dice_input,
357 &[0u8; HIDDEN_SIZE],
358 Some([0u8; 64]),
359 false,
360 &mut buffer_without_defer_retry,
Alice Wang87fbc4b2024-11-05 13:09:58 +0000361 context.clone(),
Shikha Panwarf3acfd12024-05-28 15:48:13 +0000362 )
363 .unwrap();
364 let bcc_handover3 =
365 diced_open_dice::bcc_handover_parse(&buffer_without_defer_retry).unwrap();
366
367 assert_ne!(bcc_handover1.cdi_seal(), bcc_handover2.cdi_seal());
368 assert_eq!(bcc_handover1.cdi_seal(), bcc_handover3.cdi_seal());
369 }
Alice Wang87fbc4b2024-11-05 13:09:58 +0000370
371 #[test]
372 fn dice_derivation_with_different_algorithms_is_valid() {
373 let dice_artifacts = make_sample_bcc_and_cdis().unwrap();
374 let bcc_handover0_bytes = to_bcc_handover(&dice_artifacts);
375 let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
376 let inputs = PartialInputs::new(&vb_data).unwrap();
377 let mut buffer = [0; 4096];
378
379 inputs
380 .clone()
381 .write_next_bcc(
382 &bcc_handover0_bytes,
383 &[0u8; HIDDEN_SIZE],
384 Some([0u8; 64]),
385 true,
386 &mut buffer,
387 DiceContext {
388 authority_algorithm: KeyAlgorithm::Ed25519,
389 subject_algorithm: KeyAlgorithm::EcdsaP256,
390 },
391 )
392 .expect("Failed to derive Ed25519 -> EcdsaP256 BCC");
393 let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
394 let bcc_handover1_bytes = to_bcc_handover(&bcc_handover1);
395 buffer.fill(0);
396
397 inputs
398 .clone()
399 .write_next_bcc(
400 &bcc_handover1_bytes,
401 &[0u8; HIDDEN_SIZE],
402 Some([0u8; 64]),
403 true,
404 &mut buffer,
405 DiceContext {
406 authority_algorithm: KeyAlgorithm::EcdsaP256,
407 subject_algorithm: KeyAlgorithm::EcdsaP384,
408 },
409 )
410 .expect("Failed to derive EcdsaP256 -> EcdsaP384 BCC");
411 let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
412 let bcc_handover2_bytes = to_bcc_handover(&bcc_handover2);
413 buffer.fill(0);
414
415 inputs
416 .clone()
417 .write_next_bcc(
418 &bcc_handover2_bytes,
419 &[0u8; HIDDEN_SIZE],
420 Some([0u8; 64]),
421 true,
422 &mut buffer,
423 DiceContext {
424 authority_algorithm: KeyAlgorithm::EcdsaP384,
425 subject_algorithm: KeyAlgorithm::Ed25519,
426 },
427 )
428 .expect("Failed to derive EcdsaP384 -> Ed25519 BCC");
429 let _bcc_handover3 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
430
431 // TODO(b/378813154): Check the DICE chain with `hwtrust` once the profile version
432 // is updated.
433 // The check cannot be done now because parsing the chain causes the following error:
434 // Invalid payload at index 3. Caused by:
435 // 0: opendice.example.p256
436 // 1: unknown profile version
437 }
438
439 fn to_bcc_handover(dice_artifacts: &dyn DiceArtifacts) -> Vec<u8> {
440 let dice_chain = cbor_util::deserialize::<Value>(dice_artifacts.bcc().unwrap()).unwrap();
441 let bcc_handover = Value::Map(vec![
442 (Value::Integer(1.into()), Value::Bytes(dice_artifacts.cdi_attest().to_vec())),
443 (Value::Integer(2.into()), Value::Bytes(dice_artifacts.cdi_seal().to_vec())),
444 (Value::Integer(3.into()), dice_chain),
445 ]);
446 cbor_util::serialize(&bcc_handover).unwrap()
447 }
Alan Stokesddb988c2023-11-27 11:13:06 +0000448}