Store apk root hash to the instance disk
The instance disk has been created, but hasn't actually been used. This
CL is the first step towards actually using it. Specifically, this CL
* provides routines for navigating the instance disk. The disk consists
of a disk header, followed by partitions each of which consists of a
header and payload. Each partition is dedicated to a program loader like
pVM firmware, Android Boot Loader, and microdroid_manager. A partition
is identified by UUID and this CL provides a routine to locate the
partition for a given UUID.
* provides routines for reading and writing on payload in a partition.
The data is stored encrypted when it is written and is decrypted when
read. The key is currently hard-coded but, it will eventually be derived
from the sealing CDI from the previous stage.
* Root hash of an apk extracted from the idsig file is stored to the
disk. Note that the stored root hash is not yet used by apkdmverity. It
shall be done in a follow-up change.
Bug: 193504400
Test: boot microdroid twice. check that the root hash is written to the
disk during the first boot, and then read during the second boot. Also
check that the two root hashes are the same.
Change-Id: Ia1afcda4d8444ad52a47ebcc659b2698159da816
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index ee0e797..06dd3c6 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -14,14 +14,17 @@
//! Microdroid Manager
+mod instance;
mod ioutil;
mod metadata;
+use crate::instance::InstanceDisk;
use anyhow::{anyhow, bail, Context, Result};
use apkverify::verify;
use binder::unstable_api::{new_spibinder, AIBinder};
use binder::{FromIBinder, Strong};
-use log::{error, info, warn};
+use idsig::V4Signature;
+use log::{debug, error, info, warn};
use microdroid_payload_config::{Task, TaskType, VmPayloadConfig};
use nix::ioctl_read_bad;
use rustutils::system_properties::PropertyWatcher;
@@ -94,6 +97,18 @@
return Err(err);
}
+ let mut instance = InstanceDisk::new()?;
+ // TODO(jiyong): the data should have an internal structure
+ if let Some(data) = instance.read_microdroid_data().context("Failed to read identity data")? {
+ debug!("read apk root hash: {}", to_hex_string(&data));
+ //TODO(jiyong) apkdmverity should use this root hash instead of the one read from the idsig
+ //file, if the root hash is found in the instance image.
+ } else {
+ let data = get_apk_roothash()?;
+ debug!("write apk root hash: {}", to_hex_string(&data));
+ instance.write_microdroid_data(data.as_ref()).context("Failed to write identity data")?;
+ }
+
let service = get_vms_rpc_binder().expect("cannot connect to VirtualMachineService");
if !metadata.payload_config_path.is_empty() {
@@ -129,6 +144,12 @@
Ok(())
}
+fn get_apk_roothash() -> Result<Box<[u8]>> {
+ let mut idsig = File::open("/dev/block/by-name/microdroid-apk-idsig")?;
+ let idsig = V4Signature::from(&mut idsig)?;
+ Ok(idsig.hashing_info.raw_root_hash)
+}
+
fn load_config(path: &Path) -> Result<VmPayloadConfig> {
info!("loading config from {:?}...", path);
let file = ioutil::wait_for_file(path, WAIT_TIMEOUT)?;
@@ -208,3 +229,7 @@
Ok(path)
}
+
+fn to_hex_string(buf: &[u8]) -> String {
+ buf.iter().map(|b| format!("{:02X}", b)).collect()
+}