Add DiceDrive::from_file factory method

This new function will be used in microdroid_manager to read the dice
chain written during first_stage_init for Microdroid VMs with microdroid
vendor partition.

This patch also adds a simple unit test to ensure that a dice chain read
from the file is equal to the one written to it.

Bug: 287593065
Test: atest libdice_driver_test
Change-Id: I5fa10a4b405b23f2c1980a920f0e72077623c01c
diff --git a/libs/dice/driver/Android.bp b/libs/dice/driver/Android.bp
index 4a17334..c93bd7d 100644
--- a/libs/dice/driver/Android.bp
+++ b/libs/dice/driver/Android.bp
@@ -2,8 +2,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-rust_library {
-    name: "libdice_driver",
+rust_defaults {
+    name: "libdice_driver_defaults",
     crate_name: "dice_driver",
     defaults: [
         "avf_build_flags_rust",
@@ -25,6 +25,7 @@
         "libonce_cell",
         "libopenssl",
         "libthiserror",
+        "libserde_cbor",
     ],
     multilib: {
         lib32: {
@@ -32,3 +33,18 @@
         },
     },
 }
+
+rust_library {
+    name: "libdice_driver",
+    defaults: ["libdice_driver_defaults"],
+}
+
+rust_test {
+    name: "libdice_driver_test",
+    defaults: ["libdice_driver_defaults"],
+    test_suites: ["general-tests"],
+    rustlibs: [
+        "libhex",
+        "libtempfile",
+    ],
+}
diff --git a/libs/dice/driver/src/lib.rs b/libs/dice/driver/src/lib.rs
index ec87ae2..79edb51 100644
--- a/libs/dice/driver/src/lib.rs
+++ b/libs/dice/driver/src/lib.rs
@@ -32,7 +32,7 @@
 
 /// Artifacts that are mapped into the process address space from the driver.
 pub enum DiceDriver<'a> {
-    /// Real implementation
+    /// Implementation that reads bcc handover from the dice driver.
     Real {
         /// Path to the driver character device (e.g. /dev/open-dice0).
         driver_path: PathBuf,
@@ -45,6 +45,13 @@
     },
     /// Fake implementation used in tests and non-protected VMs.
     Fake(OwnedDiceArtifacts),
+    /// Implementation that reads bcc handover from the file.
+    FromFile {
+        /// Path to the file to read dice chain from,
+        file_path: PathBuf,
+        /// Dice artifacts read from file_path,
+        dice_artifacts: OwnedDiceArtifacts,
+    },
 }
 
 impl DiceDriver<'_> {
@@ -52,6 +59,7 @@
         match self {
             Self::Real { bcc_handover, .. } => bcc_handover,
             Self::Fake(owned_dice_artifacts) => owned_dice_artifacts,
+            Self::FromFile { dice_artifacts, .. } => dice_artifacts,
         }
     }
 
@@ -97,6 +105,15 @@
         })
     }
 
+    /// Create a new dice driver that reads dice_artifacts from the given file.
+    pub fn from_file(file_path: &Path) -> Result<Self> {
+        let file =
+            fs::File::open(file_path).map_err(|error| Error::new(error).context("open file"))?;
+        let dice_artifacts = serde_cbor::from_reader(file)
+            .map_err(|error| Error::new(error).context("read file"))?;
+        Ok(Self::FromFile { file_path: file_path.to_path_buf(), dice_artifacts })
+    }
+
     /// Derives a sealing key of `key_length` bytes from the DICE sealing CDI.
     pub fn get_sealing_key(&self, identifier: &[u8], key_length: usize) -> Result<ZVec> {
         // Deterministically derive a key to use for sealing data, rather than using the CDI
@@ -155,3 +172,36 @@
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn assert_eq_bytes(expected: &[u8], actual: &[u8]) {
+        assert_eq!(
+            expected,
+            actual,
+            "Expected {}, got {}",
+            hex::encode(expected),
+            hex::encode(actual)
+        )
+    }
+
+    #[test]
+    fn test_write_bcc_to_file_read_from_file() -> Result<()> {
+        let dice_artifacts = diced_sample_inputs::make_sample_bcc_and_cdis()?;
+
+        let test_file = tempfile::NamedTempFile::new()?;
+        serde_cbor::to_writer(test_file.as_file(), &dice_artifacts)?;
+        test_file.as_file().sync_all()?;
+
+        let dice = DiceDriver::from_file(test_file.as_ref())?;
+
+        let dice_artifacts2 = dice.dice_artifacts();
+        assert_eq_bytes(dice_artifacts.cdi_attest(), dice_artifacts2.cdi_attest());
+        assert_eq_bytes(dice_artifacts.cdi_seal(), dice_artifacts2.cdi_seal());
+        assert_eq_bytes(dice_artifacts.bcc().expect("bcc"), dice_artifacts2.bcc().expect("bcc"));
+
+        Ok(())
+    }
+}
diff --git a/libs/dice/open_dice/Android.bp b/libs/dice/open_dice/Android.bp
index 79d0b96..ecc40f7 100644
--- a/libs/dice/open_dice/Android.bp
+++ b/libs/dice/open_dice/Android.bp
@@ -39,12 +39,15 @@
     rustlibs: [
         "libopen_dice_android_bindgen",
         "libopen_dice_cbor_bindgen",
+        "libserde",
         "libzeroize",
     ],
     features: [
         "alloc",
+        "serde_derive",
         "std",
     ],
+    proc_macros: ["libserde_derive"],
     shared_libs: [
         "libcrypto",
     ],
diff --git a/libs/dice/open_dice/src/dice.rs b/libs/dice/open_dice/src/dice.rs
index e42e373..e330e00 100644
--- a/libs/dice/open_dice/src/dice.rs
+++ b/libs/dice/open_dice/src/dice.rs
@@ -23,6 +23,8 @@
     DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
     DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE,
 };
+#[cfg(feature = "serde_derive")]
+use serde_derive::{Deserialize, Serialize};
 use std::{marker::PhantomData, ptr};
 use zeroize::{Zeroize, ZeroizeOnDrop};
 
@@ -82,6 +84,7 @@
 /// for sensitive data like CDI values and private key.
 /// CDI Values.
 #[derive(Debug, Zeroize, ZeroizeOnDrop, Default)]
+#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
 pub struct CdiValues {
     /// Attestation CDI.
     pub cdi_attest: [u8; CDI_SIZE],
diff --git a/libs/dice/open_dice/src/retry.rs b/libs/dice/open_dice/src/retry.rs
index a6303bd..d9551f3 100644
--- a/libs/dice/open_dice/src/retry.rs
+++ b/libs/dice/open_dice/src/retry.rs
@@ -25,12 +25,15 @@
 use crate::ops::generate_certificate;
 #[cfg(feature = "alloc")]
 use alloc::vec::Vec;
+#[cfg(feature = "serde_derive")]
+use serde_derive::{Deserialize, Serialize};
 
 /// Artifacts stores a set of dice artifacts comprising CDI_ATTEST, CDI_SEAL,
 /// and the BCC formatted attestation certificate chain.
 /// As we align with the DICE standards today, this is the certificate chain
 /// is also called DICE certificate chain.
 #[derive(Debug)]
+#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
 pub struct OwnedDiceArtifacts {
     /// CDI Values.
     cdi_values: CdiValues,