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/apkverify/Android.bp b/apkverify/Android.bp
new file mode 100644
index 0000000..2187b77
--- /dev/null
+++ b/apkverify/Android.bp
@@ -0,0 +1,19 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_library {
+    name: "libapkverify",
+    host_supported: true,
+    crate_name: "apkverify",
+    srcs: ["src/lib.rs"],
+    prefer_rlib: true,
+    edition: "2018",
+    rustlibs: [
+        "libanyhow",
+        "libbyteorder",
+        "libbytes",
+        "liblog_rust",
+        "libzip",
+    ],
+}
diff --git a/apkverify/Cargo.toml b/apkverify/Cargo.toml
deleted file mode 100644
index 965dd9a..0000000
--- a/apkverify/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "apkverify"
-version = "0.1.0"
-authors = ["Jooyung Han <jooyung@google.com>"]
-edition = "2018"
-
-[dependencies]
-anyhow = { path = "../../../../external/rust/crates/anyhow" }
-bytes = { path = "../../../../external/rust/crates/bytes" }
-byteorder = { path = "../../../../external/rust/crates/byteorder" }
-zip = { version = "0.5", path = "../../../../external/rust/crates/zip" }
\ No newline at end of file
diff --git a/apkverify/src/sigutil.rs b/apkverify/src/sigutil.rs
index 564831f..43fbe67 100644
--- a/apkverify/src/sigutil.rs
+++ b/apkverify/src/sigutil.rs
@@ -128,19 +128,19 @@
 }
 
 pub fn is_supported_signature_algorithm(algorithm_id: u32) -> bool {
-    match algorithm_id {
+    matches!(
+        algorithm_id,
         SIGNATURE_RSA_PSS_WITH_SHA256
-        | SIGNATURE_RSA_PSS_WITH_SHA512
-        | SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256
-        | SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512
-        | SIGNATURE_ECDSA_WITH_SHA256
-        | SIGNATURE_ECDSA_WITH_SHA512
-        | SIGNATURE_DSA_WITH_SHA256
-        | SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256
-        | SIGNATURE_VERITY_ECDSA_WITH_SHA256
-        | SIGNATURE_VERITY_DSA_WITH_SHA256 => true,
-        _ => false,
-    }
+            | SIGNATURE_RSA_PSS_WITH_SHA512
+            | SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256
+            | SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512
+            | SIGNATURE_ECDSA_WITH_SHA256
+            | SIGNATURE_ECDSA_WITH_SHA512
+            | SIGNATURE_DSA_WITH_SHA256
+            | SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256
+            | SIGNATURE_VERITY_ECDSA_WITH_SHA256
+            | SIGNATURE_VERITY_DSA_WITH_SHA256
+    )
 }
 
 fn to_content_digest_algorithm(algorithm_id: u32) -> Result<u32> {
diff --git a/apkverify/src/v3.rs b/apkverify/src/v3.rs
index 0a292df..1bf8a61 100644
--- a/apkverify/src/v3.rs
+++ b/apkverify/src/v3.rs
@@ -16,6 +16,9 @@
 
 //! Verifies APK Signature Scheme V3
 
+// TODO(jooyung) remove this
+#![allow(dead_code)]
+
 use anyhow::{anyhow, bail, Result};
 use bytes::Bytes;
 use std::fs::File;
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index 0ea5d87..a082beb 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -10,6 +10,7 @@
     prefer_rlib: true,
     rustlibs: [
         "libanyhow",
+        "libapkverify",
         "libkernlog",
         "liblibc",
         "liblog_rust",
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)?;
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
index 338e9a2..75ba6c7 100644
--- a/virtualizationservice/src/payload.rs
+++ b/virtualizationservice/src/payload.rs
@@ -85,7 +85,12 @@
         version: 1,
         apexes: apexes
             .iter()
-            .map(|apex| ApexPayload { name: apex.name.clone(), ..Default::default() })
+            .enumerate()
+            .map(|(i, apex)| ApexPayload {
+                name: apex.name.clone(),
+                partition_name: format!("microdroid-apex-{}", i),
+                ..Default::default()
+            })
             .collect(),
         apk: Some(ApkPayload {
             name: "apk".to_owned(),