Merge changes from topic "derive-microdroid-vendor-dice-node" into main
* changes:
Add DiceDrive::from_file factory method
Move dice_driver to libs/dice/driver
Add derive_microdroid_vendor_dice_node binary
Add microdroid_resources directory to ramdisk & system images
Add a simple hearder-only library to expose build time flags to C++
diff --git a/Android.bp b/Android.bp
index f50007f..2091a90 100644
--- a/Android.bp
+++ b/Android.bp
@@ -68,6 +68,7 @@
module_type: "cc_defaults",
config_namespace: "ANDROID",
bool_variables: [
+ "release_avf_enable_dice_changes",
"release_avf_enable_virt_cpufreq",
],
properties: [
@@ -78,6 +79,9 @@
avf_flag_aware_cc_defaults {
name: "avf_build_flags_cc",
soong_config_variables: {
+ release_avf_enable_dice_changes: {
+ cflags: ["-DAVF_OPEN_DICE_CHANGES=1"],
+ },
release_avf_enable_virt_cpufreq: {
cflags: ["-DAVF_ENABLE_VIRT_CPUFREQ=1"],
},
diff --git a/flags/cpp/Android.bp b/flags/cpp/Android.bp
new file mode 100644
index 0000000..da4158a
--- /dev/null
+++ b/flags/cpp/Android.bp
@@ -0,0 +1,13 @@
+cc_library_static {
+ name: "libavf_cc_flags",
+ defaults: ["avf_build_flags_cc"],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
+
+ export_include_dirs: ["include"],
+ local_include_dirs: ["include"],
+ ramdisk_available: true,
+ recovery_available: true,
+}
diff --git a/flags/cpp/include/android/avf_cc_flags.h b/flags/cpp/include/android/avf_cc_flags.h
new file mode 100644
index 0000000..536ea9f
--- /dev/null
+++ b/flags/cpp/include/android/avf_cc_flags.h
@@ -0,0 +1,31 @@
+// Copyright 2024, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+// TODO(b/309090563): remove this file once build flags are exposed to aconfig.
+
+namespace android {
+namespace virtualization {
+
+inline bool IsOpenDiceChangesFlagEnabled() {
+#ifdef AVF_OPEN_DICE_CHANGES
+ return AVF_OPEN_DICE_CHANGES;
+#else
+ return false;
+#endif
+}
+
+} // namespace virtualization
+} // namespace android
diff --git a/libs/dice/driver/Android.bp b/libs/dice/driver/Android.bp
new file mode 100644
index 0000000..c93bd7d
--- /dev/null
+++ b/libs/dice/driver/Android.bp
@@ -0,0 +1,50 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+ name: "libdice_driver_defaults",
+ crate_name: "dice_driver",
+ defaults: [
+ "avf_build_flags_rust",
+ ],
+ srcs: ["src/lib.rs"],
+ edition: "2021",
+ prefer_rlib: true,
+ rustlibs: [
+ "libanyhow",
+ "libbyteorder",
+ "libcoset",
+ "libdice_policy_builder",
+ "libdiced_open_dice",
+ "libdiced_sample_inputs",
+ "libkeystore2_crypto_rust",
+ "liblibc",
+ "liblog_rust",
+ "libnix",
+ "libonce_cell",
+ "libopenssl",
+ "libthiserror",
+ "libserde_cbor",
+ ],
+ multilib: {
+ lib32: {
+ enabled: false,
+ },
+ },
+}
+
+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/microdroid_manager/src/dice_driver.rs b/libs/dice/driver/src/lib.rs
similarity index 70%
rename from microdroid_manager/src/dice_driver.rs
rename to libs/dice/driver/src/lib.rs
index 229f3e0..79edb51 100644
--- a/microdroid_manager/src/dice_driver.rs
+++ b/libs/dice/driver/src/lib.rs
@@ -32,13 +32,26 @@
/// Artifacts that are mapped into the process address space from the driver.
pub enum DiceDriver<'a> {
+ /// Implementation that reads bcc handover from the dice driver.
Real {
+ /// Path to the driver character device (e.g. /dev/open-dice0).
driver_path: PathBuf,
+ /// Address of the memory to mmap driver to.
mmap_addr: *mut c_void,
+ /// Size of the mmap.
mmap_size: usize,
+ /// BCC handover.
bcc_handover: BccHandover<'a>,
},
+ /// 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<'_> {
@@ -46,13 +59,15 @@
match self {
Self::Real { bcc_handover, .. } => bcc_handover,
Self::Fake(owned_dice_artifacts) => owned_dice_artifacts,
+ Self::FromFile { dice_artifacts, .. } => dice_artifacts,
}
}
- pub fn new(driver_path: &Path) -> Result<Self> {
+ /// Creates a new dice driver from the given driver_path.
+ pub fn new(driver_path: &Path, is_strict_boot: bool) -> Result<Self> {
if driver_path.exists() {
log::info!("Using DICE values from driver");
- } else if super::is_strict_boot() {
+ } else if is_strict_boot {
bail!("Strict boot requires DICE value from driver but none were found");
} else {
log::warn!("Using sample DICE values");
@@ -90,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
@@ -101,6 +125,7 @@
Ok(key)
}
+ /// Derives a new dice chain.
pub fn derive(
self,
code_hash: Hash,
@@ -147,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,
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 999dc52..e19a343 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -49,10 +49,12 @@
module_type: "android_system_image",
config_namespace: "ANDROID",
bool_variables: [
+ "release_avf_enable_dice_changes",
"release_avf_enable_multi_tenant_microdroid_vm",
],
properties: [
"deps",
+ "dirs",
],
}
@@ -154,6 +156,14 @@
// Below are dependencies that are conditionally enabled depending on value of build flags.
soong_config_variables: {
+ release_avf_enable_dice_changes: {
+ deps: [
+ "derive_microdroid_vendor_dice_node",
+ ],
+ dirs: [
+ "microdroid_resources",
+ ],
+ },
release_avf_enable_multi_tenant_microdroid_vm: {
deps: [
"microdroid_etc_passwd",
@@ -295,7 +305,19 @@
},
}
-android_filesystem {
+soong_config_module_type {
+ name: "flag_aware_microdroid_filesystem",
+ module_type: "android_filesystem",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "release_avf_enable_dice_changes",
+ ],
+ properties: [
+ "dirs",
+ ],
+}
+
+flag_aware_microdroid_filesystem {
name: "microdroid_ramdisk",
deps: [
"init_first_stage.microdroid",
@@ -305,14 +327,23 @@
"proc",
"sys",
- // TODO(jiyong): remove these
"mnt",
"debug_ramdisk",
"second_stage_resources",
],
type: "compressed_cpio",
+
+ // Below are dependencies that are conditionally enabled depending on value of build flags.
+ soong_config_variables: {
+ release_avf_enable_dice_changes: {
+ dirs: [
+ "microdroid_resources",
+ ],
+ },
+ },
}
+// TODO(ioffe): rename to microdroid_first_stage_ramdisk
android_filesystem {
name: "microdroid_fstab_ramdisk",
deps: [
diff --git a/microdroid/derive_microdroid_vendor_dice_node/Android.bp b/microdroid/derive_microdroid_vendor_dice_node/Android.bp
new file mode 100644
index 0000000..de1bef7
--- /dev/null
+++ b/microdroid/derive_microdroid_vendor_dice_node/Android.bp
@@ -0,0 +1,22 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+ name: "derive_microdroid_vendor_dice_node_defaults",
+ crate_name: "derive_microdroid_vendor_dice_node",
+ defaults: ["avf_build_flags_rust"],
+ srcs: ["src/main.rs"],
+ rustlibs: [
+ "libanyhow",
+ "libclap",
+ ],
+ bootstrap: true,
+ prefer_rlib: true,
+}
+
+rust_binary {
+ name: "derive_microdroid_vendor_dice_node",
+ defaults: ["derive_microdroid_vendor_dice_node_defaults"],
+ stem: "derive_microdroid_vendor_dice_node",
+}
diff --git a/microdroid/derive_microdroid_vendor_dice_node/src/main.rs b/microdroid/derive_microdroid_vendor_dice_node/src/main.rs
new file mode 100644
index 0000000..1d5db0d
--- /dev/null
+++ b/microdroid/derive_microdroid_vendor_dice_node/src/main.rs
@@ -0,0 +1,38 @@
+// Copyright 2024, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Derives microdroid vendor dice node.
+
+use anyhow::Error;
+use clap::Parser;
+use std::path::PathBuf;
+
+#[derive(Parser)]
+struct Args {
+ /// Path to the dice driver (e.g. /dev/open-dice0)
+ #[arg(long)]
+ dice_driver: PathBuf,
+ /// Path to the microdroid-vendor.img disk image.
+ #[arg(long)]
+ microdroid_vendor_disk_image: PathBuf,
+ /// File to save resulting dice chain to.
+ #[arg(long)]
+ output: PathBuf,
+}
+
+fn main() -> Result<(), Error> {
+ let args = Args::parse();
+ eprintln!("{:?} {:?} {:?}", args.dice_driver, args.microdroid_vendor_disk_image, args.output);
+ Ok(())
+}
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index 81bb409..9c9a3d0 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -29,6 +29,7 @@
"libclient_vm_csr",
"libciborium",
"libcoset",
+ "libdice_driver",
"libdice_policy_builder",
"libdiced_open_dice",
"libdiced_sample_inputs",
diff --git a/microdroid_manager/src/dice.rs b/microdroid_manager/src/dice.rs
index a8b88aa..7f65159 100644
--- a/microdroid_manager/src/dice.rs
+++ b/microdroid_manager/src/dice.rs
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate::dice_driver::DiceDriver;
use crate::instance::{ApexData, ApkData};
use crate::{is_debuggable, MicrodroidData};
use anyhow::{bail, Context, Result};
use ciborium::{cbor, Value};
use coset::CborSerializable;
+use dice_driver::DiceDriver;
use diced_open_dice::OwnedDiceArtifacts;
use microdroid_metadata::PayloadMetadata;
use openssl::sha::{sha512, Sha512};
diff --git a/microdroid_manager/src/instance.rs b/microdroid_manager/src/instance.rs
index 7a9f0e0..888c451 100644
--- a/microdroid_manager/src/instance.rs
+++ b/microdroid_manager/src/instance.rs
@@ -33,11 +33,11 @@
//! The payload of a partition is encrypted/signed by a key that is unique to the loader and to the
//! VM as well. Failing to decrypt/authenticate a partition by a loader stops the boot process.
-use crate::dice_driver::DiceDriver;
use crate::ioutil;
use anyhow::{anyhow, bail, Context, Result};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
+use dice_driver::DiceDriver;
use openssl::symm::{decrypt_aead, encrypt_aead, Cipher};
use serde::{Deserialize, Serialize};
use std::fs::{File, OpenOptions};
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 0d67632..8d2c629 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -15,7 +15,6 @@
//! Microdroid Manager
mod dice;
-mod dice_driver;
mod instance;
mod ioutil;
mod payload;
@@ -33,12 +32,12 @@
};
use crate::dice::dice_derivation;
-use crate::dice_driver::DiceDriver;
use crate::instance::{InstanceDisk, MicrodroidData};
use crate::verify::verify_payload;
use crate::vm_payload_service::register_vm_payload_service;
use anyhow::{anyhow, bail, ensure, Context, Error, Result};
use binder::Strong;
+use dice_driver::DiceDriver;
use keystore2_crypto::ZVec;
use libc::VMADDR_CID_HOST;
use log::{error, info};
@@ -241,7 +240,8 @@
vm_payload_service_fd: OwnedFd,
) -> Result<i32> {
let metadata = load_metadata().context("Failed to load payload metadata")?;
- let dice = DiceDriver::new(Path::new("/dev/open-dice0")).context("Failed to load DICE")?;
+ let dice = DiceDriver::new(Path::new("/dev/open-dice0"), is_strict_boot())
+ .context("Failed to load DICE")?;
let mut instance = InstanceDisk::new().context("Failed to load instance.img")?;
let saved_data =