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(),