Merge "Ignore identity if the debug policy is turned on"
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index fa064a7..531c707 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -18,7 +18,7 @@
 mod ioutil;
 mod payload;
 
-use crate::instance::{ApkData, InstanceDisk, MicrodroidData, RootHash};
+use crate::instance::{ApexData, ApkData, InstanceDisk, MicrodroidData, RootHash};
 use android_hardware_security_dice::aidl::android::hardware::security::dice::{
     Config::Config, InputValues::InputValues, Mode::Mode,
 };
@@ -64,6 +64,8 @@
 const ZIPFUSE_BIN: &str = "/system/bin/zipfuse";
 const AVF_STRICT_BOOT: &str = "/sys/firmware/devicetree/base/chosen/avf,strict-boot";
 const AVF_NEW_INSTANCE: &str = "/sys/firmware/devicetree/base/chosen/avf,new-instance";
+const DEBUG_MICRODROID_NO_VERIFIED_BOOT: &str =
+    "/sys/firmware/devicetree/base/virtualization/guest/debug-microdroid,no-verified-boot";
 
 /// The CID representing the host VM
 const VMADDR_CID_HOST: u32 = 2;
@@ -243,6 +245,10 @@
     Path::new(AVF_NEW_INSTANCE).exists()
 }
 
+fn is_verified_boot() -> bool {
+    !Path::new(DEBUG_MICRODROID_NO_VERIFIED_BOOT).exists()
+}
+
 fn try_run_payload(service: &Strong<dyn IVirtualMachineService>) -> Result<i32> {
     let metadata = load_metadata().context("Failed to load payload metadata")?;
 
@@ -268,18 +274,29 @@
     let verified_data = verify_payload(&metadata, saved_data.as_ref())
         .context("Payload verification failed")
         .map_err(|e| MicrodroidError::PayloadVerificationFailed(e.to_string()))?;
-    if let Some(saved_data) = saved_data {
-        ensure!(
-            saved_data == verified_data,
-            MicrodroidError::PayloadChanged(String::from(
-                "Detected an update of the payload which isn't supported yet."
-            ))
-        );
-        info!("Saved data is verified.");
+
+    // In case identity is ignored (by debug policy), we should reuse existing payload data, even
+    // when the payload is changed. This is to keep the derived secret same as before.
+    let verified_data = if let Some(saved_data) = saved_data {
+        if !is_verified_boot() {
+            if saved_data != verified_data {
+                info!("Detected an update of the payload, but continue (regarding debug policy)")
+            }
+        } else {
+            ensure!(
+                saved_data == verified_data,
+                MicrodroidError::PayloadChanged(String::from(
+                    "Detected an update of the payload which isn't supported yet."
+                ))
+            );
+            info!("Saved data is verified.");
+        }
+        saved_data
     } else {
         info!("Saving verified data.");
         instance.write_microdroid_data(&verified_data).context("Failed to write identity data")?;
-    }
+        verified_data
+    };
 
     // To minimize the exposure to untrusted data, derive dice profile as soon as possible.
     info!("DICE derivation for payload");
@@ -371,6 +388,29 @@
         .context("Spawn zipfuse")
 }
 
+fn write_apex_payload_data(
+    saved_data: Option<&MicrodroidData>,
+    apex_data_from_payload: &[ApexData],
+) -> Result<()> {
+    if let Some(saved_apex_data) = saved_data.map(|d| &d.apex_data) {
+        // We don't support APEX updates. (assuming that update will change root digest)
+        ensure!(
+            saved_apex_data == apex_data_from_payload,
+            MicrodroidError::PayloadChanged(String::from("APEXes have changed."))
+        );
+        let apex_metadata = to_metadata(apex_data_from_payload);
+        // Pass metadata(with public keys and root digests) to apexd so that it uses the passed
+        // metadata instead of the default one (/dev/block/by-name/payload-metadata)
+        OpenOptions::new()
+            .create_new(true)
+            .write(true)
+            .open("/apex/vm-payload-metadata")
+            .context("Failed to open /apex/vm-payload-metadata")
+            .and_then(|f| write_metadata(&apex_metadata, f))?;
+    }
+    Ok(())
+}
+
 // Verify payload before executing it. For APK payload, 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 root hash (for APK payload) and pubkeys (for APEX payloads) that can be
@@ -465,22 +505,13 @@
     // While waiting for apkdmverity to mount APK, gathers public keys and root digests from
     // APEX payload.
     let apex_data_from_payload = get_apex_data_from_payload(metadata)?;
-    if let Some(saved_data) = saved_data.map(|d| &d.apex_data) {
-        // We don't support APEX updates. (assuming that update will change root digest)
-        ensure!(
-            saved_data == &apex_data_from_payload,
-            MicrodroidError::PayloadChanged(String::from("APEXes have changed."))
-        );
-        let apex_metadata = to_metadata(&apex_data_from_payload);
-        // Pass metadata(with public keys and root digests) to apexd so that it uses the passed
-        // metadata instead of the default one (/dev/block/by-name/payload-metadata)
-        OpenOptions::new()
-            .create_new(true)
-            .write(true)
-            .open("/apex/vm-payload-metadata")
-            .context("Failed to open /apex/vm-payload-metadata")
-            .and_then(|f| write_metadata(&apex_metadata, f))?;
+
+    // Writing /apex/vm-payload-metadata is to verify that the payload isn't changed.
+    // Skip writing it if the debug policy ignoring identity is on
+    if is_verified_boot() {
+        write_apex_payload_data(saved_data, &apex_data_from_payload)?;
     }
+
     // Start apexd to activate APEXes
     system_properties::write("ctl.start", "apexd-vm")?;