Create idsig file automatically
Before a VM is started, the idsig file is created (or updated) by the
virtualization service. This is needed because the idsig file is usually
not available, especially when the APK is downloaded from the store.
Note that the generated idsig file is not a signed one. Therefore, the
APK is first verified using the APK signature scheme V3 (or V2) over a
dm-verity device backed by the APK and the merkle tree (and root hash)
from the idsig file. Only if the verification is successful, the root
hash stored to the instance.img and then used for the subsequent boots
of the VM.
Bug: 193504400
Test: atest MicrodroidHostTestCases
Test: run MicrodroidDemoApp without having the idsig file in
/data/local/tmp/virt.
Change-Id: I9fad05ca9562ae0666431102a8147d0f76f04e6a
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index cf92d5a..c3b36ee 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -26,6 +26,7 @@
"libanyhow",
"libcommand_fds",
"libdisk",
+ "libidsig",
"liblog_rust",
"libmicrodroid_metadata",
"libmicrodroid_payload_config",
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
index 8affaad..d136465 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
@@ -35,6 +35,15 @@
void initializeWritablePartition(in ParcelFileDescriptor imageFd, long size);
/**
+ * Create or update an idsig file that digests the given APK file. The idsig file follows the
+ * idsig format that is defined by the APK Signature Scheme V4. The idsig file is not updated
+ * when it is up to date with the input file, which is checked by comparing the
+ * signing_info.apk_digest field in the idsig file with the signer.signed_data.digests.digest
+ * field in the input APK file.
+ */
+ void createOrUpdateIdsigFile(in ParcelFileDescriptor inputFd, in ParcelFileDescriptor idsigFd);
+
+ /**
* Get a list of all currently running VMs. This method is only intended for debug purposes,
* and as such is only permitted from the shell user.
*/
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 96e3c44..23a9c03 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -37,6 +37,7 @@
};
use anyhow::{bail, Context, Result};
use disk::QcowFile;
+use idsig::{V4Signature, HashAlgorithm};
use log::{debug, error, warn, info};
use microdroid_payload_config::VmPayloadConfig;
use std::convert::TryInto;
@@ -209,6 +210,24 @@
Ok(())
}
+ /// Creates or update the idsig file by digesting the input APK file.
+ fn createOrUpdateIdsigFile(
+ &self,
+ input_fd: &ParcelFileDescriptor,
+ idsig_fd: &ParcelFileDescriptor,
+ ) -> binder::Result<()> {
+ // TODO(b/193504400): do this only when (1) idsig_fd is empty or (2) the APK digest in
+ // idsig_fd is different from APK digest in input_fd
+
+ let mut input = clone_file(input_fd)?;
+ let mut sig = V4Signature::create(&mut input, 4096, &[], HashAlgorithm::SHA256).unwrap();
+
+ let mut output = clone_file(idsig_fd)?;
+ output.set_len(0).unwrap();
+ sig.write_into(&mut output).unwrap();
+ Ok(())
+ }
+
/// Get a list of all currently running VMs. This method is only intended for debug purposes,
/// and as such is only permitted from the shell user.
fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {