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,