Data written to instance.img has schema

... so that we can store structured data. Currently the data is encoded
in CBOR.

Bug: 193504400
Test: atest MicrodroidHostTestCases
Change-Id: I271b40f7d2c42fc42d793c36e27ca65cfaa9ba25
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 9cbcaf1..4f192dc 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -18,7 +18,7 @@
 mod ioutil;
 mod metadata;
 
-use crate::instance::InstanceDisk;
+use crate::instance::{ApkData, InstanceDisk, MicrodroidData, RootHash};
 use anyhow::{anyhow, bail, Context, Result};
 use apkverify::verify;
 use binder::unstable_api::{new_spibinder, AIBinder};
@@ -92,27 +92,24 @@
 
     let metadata = metadata::load()?;
 
-    // Try to read roothash from the instance disk.
-    // TODO(jiyong): the data should have an internal structure.
     let mut instance = InstanceDisk::new()?;
-    let saved_roothash = instance.read_microdroid_data().context("Failed to read identity data")?;
-    let saved_roothash = saved_roothash.as_deref();
+    let data = instance.read_microdroid_data().context("Failed to read identity data")?;
+    let saved_root_hash: Option<&[u8]> =
+        if let Some(data) = data.as_ref() { Some(&data.apk_data.root_hash) } else { None };
 
     // Verify the payload before using it.
-    let verified_roothash =
-        verify_payload(saved_roothash).context("Payload verification failed")?;
-    if let Some(saved_roothash) = saved_roothash {
-        if saved_roothash == verified_roothash.as_ref() {
-            info!("Saved roothash is verified.");
+    let verified_root_hash =
+        verify_payload(saved_root_hash).context("Payload verification failed")?;
+    if let Some(saved_root_hash) = saved_root_hash {
+        if saved_root_hash == verified_root_hash.as_ref() {
+            info!("Saved root_hash is verified.");
         } else {
             bail!("Detected an update of the APK which isn't supported yet.");
         }
     } else {
-        info!("Saving APK roothash: {}", to_hex_string(verified_roothash.as_ref()));
-        // TODO(jiyong): the data should have an internal structure.
-        instance
-            .write_microdroid_data(verified_roothash.as_ref())
-            .context("Failed to write identity data")?;
+        info!("Saving APK root_hash: {}", to_hex_string(verified_root_hash.as_ref()));
+        let data = MicrodroidData { apk_data: ApkData { root_hash: verified_root_hash } };
+        instance.write_microdroid_data(&data).context("Failed to write identity data")?;
     }
 
     wait_for_apex_config_done()?;
@@ -141,42 +138,40 @@
     Ok(())
 }
 
-type Roothash = [u8];
-
-// Verify payload before executing it. Full verification (which is slow) is done when the roothash
+// Verify payload before executing it. Full verification (which is slow) is done when the root_hash
 // values from the idsig file and the instance disk are different. This function returns the
-// verified roothash that can be saved to the instance disk.
-fn verify_payload(roothash: Option<&Roothash>) -> Result<Box<Roothash>> {
+// verified root hash that can be saved to the instance disk.
+fn verify_payload(root_hash: Option<&RootHash>) -> Result<Box<RootHash>> {
     let start_time = SystemTime::now();
 
-    let roothash_from_idsig = get_apk_roothash_from_idsig()?;
-    let roothash_trustful = roothash == Some(&roothash_from_idsig);
+    let root_hash_from_idsig = get_apk_root_hash_from_idsig()?;
+    let root_hash_trustful = root_hash == Some(&root_hash_from_idsig);
 
-    // If roothash can be trusted, pass it to apkdmverity so that it uses the passed roothash
+    // If root_hash can be trusted, pass it to apkdmverity so that it uses the passed root_hash
     // instead of the value read from the idsig file.
-    if roothash_trustful {
-        let roothash = to_hex_string(roothash.unwrap());
-        system_properties::write("microdroid_manager.apk_roothash", &roothash)?;
+    if root_hash_trustful {
+        let root_hash = to_hex_string(root_hash.unwrap());
+        system_properties::write("microdroid_manager.apk_root_hash", &root_hash)?;
     }
 
     // Start apkdmverity and wait for the dm-verify block
     system_properties::write("ctl.start", "apkdmverity")?;
     ioutil::wait_for_file(DM_MOUNTED_APK_PATH, WAIT_TIMEOUT)?;
 
-    // Do the full verification if the roothash is un-trustful. This requires the full scanning of
+    // Do the full verification if the root_hash is un-trustful. This requires the full scanning of
     // the APK file and therefore can be very slow if the APK is large. Note that this step is
-    // taken only when the roothash is un-trustful which can be either when this is the first boot
+    // taken only when the root_hash is un-trustful which can be either when this is the first boot
     // of the VM or APK was updated in the host.
     // TODO(jooyung): consider multithreading to make this faster
-    if !roothash_trustful {
+    if !root_hash_trustful {
         verify(DM_MOUNTED_APK_PATH).context(format!("failed to verify {}", DM_MOUNTED_APK_PATH))?;
     }
 
     info!("payload verification successful. took {:#?}", start_time.elapsed().unwrap());
 
-    // At this point, we can ensure that the roothash from the idsig file is trusted, either by
-    // fully verifying the APK or by comparing it with the saved roothash.
-    Ok(roothash_from_idsig)
+    // At this point, we can ensure that the root_hash from the idsig file is trusted, either by
+    // fully verifying the APK or by comparing it with the saved root_hash.
+    Ok(root_hash_from_idsig)
 }
 
 // Waits until linker config is generated
@@ -192,7 +187,7 @@
     Ok(())
 }
 
-fn get_apk_roothash_from_idsig() -> Result<Box<Roothash>> {
+fn get_apk_root_hash_from_idsig() -> Result<Box<RootHash>> {
     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)