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
This commit is contained in:
Jooyung Han 2021-08-06 14:08:16 +09:00
parent 5d94bfcd79
commit 19c1d6c70e
7 changed files with 63 additions and 25 deletions

19
apkverify/Android.bp Normal file
View File

@ -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",
],
}

View File

@ -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" }

View File

@ -128,19 +128,19 @@ fn find_signature_scheme_block(buf: Bytes, block_id: u32) -> Result<Bytes> {
}
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> {

View File

@ -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;

View File

@ -10,6 +10,7 @@ rust_defaults {
prefer_rlib: true,
rustlibs: [
"libanyhow",
"libapkverify",
"libkernlog",
"liblibc",
"liblog_rust",

View File

@ -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 std::time::Duration;
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 @@ fn main() -> Result<()> {
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)?;

View File

@ -85,7 +85,12 @@ fn make_metadata_file(
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(),