microdroid_manager: verify APK/APEXes

Even though libapkverify doesn't do much verification for now, having
it in use would make CI detect errors in the future.

TODO:
- zipfuse should wait until APK is verified.
- boot should abort when verification fails.

Bug: 190343842
Test: MicrodroidHostTestCases
Change-Id: I221be1c7d9a0bfcd312593d3958f950311b67af5
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 2586737..fa456e8 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -17,7 +17,8 @@
 mod ioutil;
 mod metadata;
 
-use anyhow::{anyhow, bail, Result};
+use anyhow::{anyhow, bail, Context, Result};
+use apkverify::verify;
 use log::{error, info, warn};
 use microdroid_payload_config::{Task, TaskType, VmPayloadConfig};
 use rustutils::system_properties::PropertyWatcher;
@@ -30,12 +31,19 @@
 use vsock::VsockStream;
 
 const WAIT_TIMEOUT: Duration = Duration::from_secs(10);
+const DM_MOUNTED_APK_PATH: &str = "/dev/block/mapper/microdroid-apk";
 
 fn main() -> Result<()> {
     kernlog::init()?;
     info!("started.");
 
     let metadata = metadata::load()?;
+
+    if let Err(err) = verify_payloads() {
+        error!("failed to verify payload: {}", err);
+        // TODO(jooyung): should stop the boot process if verification fails
+    }
+
     if !metadata.payload_config_path.is_empty() {
         let config = load_config(Path::new(&metadata.payload_config_path))?;
 
@@ -56,6 +64,19 @@
     Ok(())
 }
 
+// TODO(jooyung): v2/v3 full verification can be slow. Consider multithreading.
+fn verify_payloads() -> Result<()> {
+    // We don't verify APEXes since apexd does.
+
+    // should wait APK to be dm-verity mounted by apkdmverity
+    ioutil::wait_for_file(DM_MOUNTED_APK_PATH, WAIT_TIMEOUT)?;
+    verify(DM_MOUNTED_APK_PATH).context(format!("failed to verify {}", DM_MOUNTED_APK_PATH))?;
+
+    info!("payload verification succeeded.");
+    // TODO(jooyung): collect public keys and store them in instance.img
+    Ok(())
+}
+
 fn load_config(path: &Path) -> Result<VmPayloadConfig> {
     info!("loading config from {:?}...", path);
     let file = ioutil::wait_for_file(path, WAIT_TIMEOUT)?;