[dice] Replace DiceContext with OwnedDiceArtifacts in microdroid

The two structs have the same set of data and OwnedDiceArtifacts
is also more secure as it zeros out the DICE CDI values when it
is dropped.

Bug: 268587826
Test: atest microdroid_manager_test MicrodroidTests
Change-Id: I23a5c759af537e0784b9dfda00c2e8717bca4ec7
diff --git a/microdroid_manager/src/dice.rs b/microdroid_manager/src/dice.rs
index cf5e73e..9a2648f 100644
--- a/microdroid_manager/src/dice.rs
+++ b/microdroid_manager/src/dice.rs
@@ -17,7 +17,7 @@
 use anyhow::{bail, Context, Error, Result};
 use byteorder::{NativeEndian, ReadBytesExt};
 use diced_open_dice::{
-    retry_bcc_main_flow, Config, DiceMode, Hash, Hidden, InputValues, OwnedDiceArtifacts, CDI_SIZE,
+    retry_bcc_main_flow, Cdi, Config, DiceMode, Hash, Hidden, InputValues, OwnedDiceArtifacts,
 };
 use keystore2_crypto::ZVec;
 use libc::{c_void, mmap, munmap, MAP_FAILED, MAP_PRIVATE, PROT_READ};
@@ -29,33 +29,16 @@
 use std::ptr::null_mut;
 use std::slice;
 
-/// Artifacts that are kept in the process address space after the artifacts from the driver have
-/// been consumed.
-/// TODO(b/267575445): Replace with `OwnedDiceArtifacts` from the library `diced_open_dice`.
-pub struct DiceContext {
-    pub cdi_attest: [u8; CDI_SIZE],
-    pub cdi_seal: [u8; CDI_SIZE],
-    pub bcc: Vec<u8>,
-}
-
-impl From<OwnedDiceArtifacts> for DiceContext {
-    fn from(dice_artifacts: OwnedDiceArtifacts) -> Self {
-        Self {
-            cdi_attest: dice_artifacts.cdi_values.cdi_attest,
-            cdi_seal: dice_artifacts.cdi_values.cdi_seal,
-            bcc: dice_artifacts.bcc[..].to_vec(),
-        }
-    }
-}
-
-impl DiceContext {
-    pub fn get_sealing_key(&self, salt: &[u8], identifier: &[u8], keysize: u32) -> Result<ZVec> {
-        // Deterministically derive a key to use for sealing data based on salt. Use different salt
-        // for different keys.
-        let mut key = ZVec::new(keysize as usize)?;
-        hkdf(&mut key, Md::sha256(), &self.cdi_seal, salt, identifier)?;
-        Ok(key)
-    }
+/// Derives a sealing key from the DICE sealing CDI.
+pub fn derive_sealing_key(
+    cdi_seal: &Cdi,
+    salt: &[u8],
+    info: &[u8],
+    keysize: usize,
+) -> Result<ZVec> {
+    let mut key = ZVec::new(keysize)?;
+    hkdf(&mut key, Md::sha256(), cdi_seal, salt, info)?;
+    Ok(key)
 }
 
 /// Artifacts that are mapped into the process address space from the driver.
@@ -64,11 +47,11 @@
         driver_path: PathBuf,
         mmap_addr: *mut c_void,
         mmap_size: usize,
-        cdi_attest: &'a [u8; CDI_SIZE],
-        cdi_seal: &'a [u8; CDI_SIZE],
+        cdi_attest: &'a Cdi,
+        cdi_seal: &'a Cdi,
         bcc: &'a [u8],
     },
-    Fake(DiceContext),
+    Fake(OwnedDiceArtifacts),
 }
 
 impl DiceDriver<'_> {
@@ -81,7 +64,7 @@
             log::warn!("Using sample DICE values");
             let dice_artifacts = diced_sample_inputs::make_sample_bcc_and_cdis()
                 .expect("Failed to create sample dice artifacts.");
-            return Ok(Self::Fake(dice_artifacts.into()));
+            return Ok(Self::Fake(dice_artifacts));
         };
 
         let mut file = fs::File::open(driver_path)
@@ -133,12 +116,10 @@
         // input key material is already cryptographically strong.
         let cdi_seal = match self {
             Self::Real { cdi_seal, .. } => cdi_seal,
-            Self::Fake(fake) => &fake.cdi_seal,
+            Self::Fake(fake) => &fake.cdi_values.cdi_seal,
         };
         let salt = &[];
-        let mut key = ZVec::new(32)?;
-        hkdf(&mut key, Md::sha256(), cdi_seal, salt, identifier)?;
-        Ok(key)
+        derive_sealing_key(cdi_seal, salt, identifier, 32)
     }
 
     pub fn derive(
@@ -148,7 +129,7 @@
         authority_hash: Hash,
         debug: bool,
         hidden: Hidden,
-    ) -> Result<DiceContext> {
+    ) -> Result<OwnedDiceArtifacts> {
         let input_values = InputValues::new(
             code_hash,
             Config::Descriptor(config_desc),
@@ -158,7 +139,9 @@
         );
         let (cdi_attest, cdi_seal, bcc) = match &self {
             Self::Real { cdi_attest, cdi_seal, bcc, .. } => (*cdi_attest, *cdi_seal, *bcc),
-            Self::Fake(fake) => (&fake.cdi_attest, &fake.cdi_seal, fake.bcc.as_slice()),
+            Self::Fake(fake) => {
+                (&fake.cdi_values.cdi_attest, &fake.cdi_values.cdi_seal, fake.bcc.as_slice())
+            }
         };
         let dice_artifacts = retry_bcc_main_flow(cdi_attest, cdi_seal, bcc, &input_values)
             .context("DICE derive from driver")?;
@@ -168,7 +151,7 @@
             fs::write(driver_path, "wipe")
                 .map_err(|err| Error::new(err).context("Wiping driver"))?;
         }
-        Ok(dice_artifacts.into())
+        Ok(dice_artifacts)
     }
 }
 
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 777a42c..7ca0d3c 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -21,7 +21,7 @@
 mod swap;
 mod vm_payload_service;
 
-use crate::dice::{DiceContext, DiceDriver};
+use crate::dice::{DiceDriver, derive_sealing_key};
 use crate::instance::{ApexData, ApkData, InstanceDisk, MicrodroidData, RootHash};
 use crate::vm_payload_service::register_vm_payload_service;
 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode;
@@ -34,6 +34,7 @@
 use anyhow::{anyhow, bail, ensure, Context, Error, Result};
 use apkverify::{get_public_key_der, verify, V4Signature};
 use binder::Strong;
+use diced_open_dice::OwnedDiceArtifacts;
 use diced_utils::cbor::{encode_header, encode_number};
 use glob::glob;
 use itertools::sorted;
@@ -88,7 +89,7 @@
 
 const ENCRYPTEDSTORE_BACKING_DEVICE: &str = "/dev/block/by-name/encryptedstore";
 const ENCRYPTEDSTORE_KEY_IDENTIFIER: &str = "encryptedstore_key";
-const ENCRYPTEDSTORE_KEYSIZE: u32 = 32;
+const ENCRYPTEDSTORE_KEYSIZE: usize = 32;
 
 #[derive(thiserror::Error, Debug)]
 enum MicrodroidError {
@@ -268,7 +269,7 @@
     dice: DiceDriver,
     verified_data: &MicrodroidData,
     payload_metadata: &PayloadMetadata,
-) -> Result<DiceContext> {
+) -> Result<OwnedDiceArtifacts> {
     // Calculate compound digests of code and authorities
     let mut code_hash_ctx = Sha512::new();
     let mut authority_hash_ctx = Sha512::new();
@@ -413,12 +414,12 @@
 
     // To minimize the exposure to untrusted data, derive dice profile as soon as possible.
     info!("DICE derivation for payload");
-    let dice_context = dice_derivation(dice, &verified_data, &payload_metadata)?;
+    let dice_artifacts = dice_derivation(dice, &verified_data, &payload_metadata)?;
 
     // Run encryptedstore binary to prepare the storage
     let encryptedstore_child = if Path::new(ENCRYPTEDSTORE_BACKING_DEVICE).exists() {
         info!("Preparing encryptedstore ...");
-        Some(prepare_encryptedstore(&dice_context).context("encryptedstore run")?)
+        Some(prepare_encryptedstore(&dice_artifacts).context("encryptedstore run")?)
     } else {
         None
     };
@@ -473,7 +474,7 @@
     // Wait until zipfuse has mounted the APKs so we can access the payload
     zipfuse.wait_until_done()?;
 
-    register_vm_payload_service(allow_restricted_apis, service.clone(), dice_context)?;
+    register_vm_payload_service(allow_restricted_apis, service.clone(), dice_artifacts)?;
 
     // Wait for encryptedstore to finish mounting the storage (if enabled) before setting
     // microdroid_manager.init_done. Reason is init stops uneventd after that.
@@ -907,7 +908,7 @@
     buf.iter().map(|b| format!("{:02X}", b)).collect()
 }
 
-fn prepare_encryptedstore(dice: &DiceContext) -> Result<Child> {
+fn prepare_encryptedstore(dice_artifacts: &OwnedDiceArtifacts) -> Result<Child> {
     // Use a fixed salt to scope the derivation to this API.
     // Generated using hexdump -vn32 -e'14/1 "0x%02X, " 1 "\n"' /dev/urandom
     // TODO(b/241541860) : Move this (& other salts) to a salt container, i.e. a global enum
@@ -916,7 +917,8 @@
         0x6F, 0xB3, 0xF9, 0x40, 0xCE, 0xDD, 0x99, 0x40, 0xAA, 0xA7, 0x0E, 0x92, 0x73, 0x90, 0x86,
         0x4A, 0x75,
     ];
-    let key = dice.get_sealing_key(
+    let key = derive_sealing_key(
+        &dice_artifacts.cdi_values.cdi_seal,
         &salt,
         ENCRYPTEDSTORE_KEY_IDENTIFIER.as_bytes(),
         ENCRYPTEDSTORE_KEYSIZE,
diff --git a/microdroid_manager/src/vm_payload_service.rs b/microdroid_manager/src/vm_payload_service.rs
index 98b9f2b..ac8f60a 100644
--- a/microdroid_manager/src/vm_payload_service.rs
+++ b/microdroid_manager/src/vm_payload_service.rs
@@ -14,12 +14,12 @@
 
 //! Implementation of the AIDL interface `IVmPayloadService`.
 
-use crate::dice::DiceContext;
 use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{
     BnVmPayloadService, IVmPayloadService, VM_PAYLOAD_SERVICE_SOCKET_NAME};
 use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::IVirtualMachineService;
 use anyhow::Result;
 use binder::{Interface, BinderFeatures, ExceptionCode, Status, Strong};
+use diced_open_dice::OwnedDiceArtifacts;
 use log::{error, info};
 use openssl::hkdf::hkdf;
 use openssl::md::Md;
@@ -29,7 +29,7 @@
 struct VmPayloadService {
     allow_restricted_apis: bool,
     virtual_machine_service: Strong<dyn IVirtualMachineService>,
-    dice: DiceContext,
+    dice: OwnedDiceArtifacts,
 }
 
 impl IVmPayloadService for VmPayloadService {
@@ -48,10 +48,11 @@
             0xB7, 0xA8, 0x43, 0x92,
         ];
         let mut secret = vec![0; size.try_into().unwrap()];
-        hkdf(&mut secret, Md::sha256(), &self.dice.cdi_seal, &salt, identifier).map_err(|e| {
-            error!("Failed to derive VM instance secret: {:?}", e);
-            Status::new_service_specific_error(-1, None)
-        })?;
+        hkdf(&mut secret, Md::sha256(), &self.dice.cdi_values.cdi_seal, &salt, identifier)
+            .map_err(|e| {
+                error!("Failed to derive VM instance secret: {:?}", e);
+                Status::new_service_specific_error(-1, None)
+            })?;
         Ok(secret)
     }
 
@@ -62,7 +63,7 @@
 
     fn getDiceAttestationCdi(&self) -> binder::Result<Vec<u8>> {
         self.check_restricted_apis_allowed()?;
-        Ok(self.dice.cdi_attest.to_vec())
+        Ok(self.dice.cdi_values.cdi_attest.to_vec())
     }
 }
 
@@ -73,7 +74,7 @@
     fn new(
         allow_restricted_apis: bool,
         vm_service: Strong<dyn IVirtualMachineService>,
-        dice: DiceContext,
+        dice: OwnedDiceArtifacts,
     ) -> Self {
         Self { allow_restricted_apis, virtual_machine_service: vm_service, dice }
     }
@@ -92,7 +93,7 @@
 pub(crate) fn register_vm_payload_service(
     allow_restricted_apis: bool,
     vm_service: Strong<dyn IVirtualMachineService>,
-    dice: DiceContext,
+    dice: OwnedDiceArtifacts,
 ) -> Result<()> {
     let vm_payload_binder = BnVmPayloadService::new_binder(
         VmPayloadService::new(allow_restricted_apis, vm_service, dice),