[attestation] Validate vendor module loaded by client VM in RKP VM
This cl added the following tasks to the RKP VM:
- Parses a client VM DICE chain containing an additional vendor
module entry.
- Validates the code hash in the vendor module DICE entry against
the code hash read from the device tree.
The cl also adds a CTS test that triggers the VM attestation from
a VM with vendor module.
Bug: 330678211
Test: atest MicrodroidTests
Change-Id: Id56c6edd8baa32bae6a8ad7b5bca7b18ce167022
diff --git a/rialto/src/fdt.rs b/rialto/src/fdt.rs
index 09cdd36..b220f41 100644
--- a/rialto/src/fdt.rs
+++ b/rialto/src/fdt.rs
@@ -24,3 +24,8 @@
let node = node.next_compatible(cstr!("google,open-dice"))?.ok_or(FdtError::NotFound)?;
node.first_reg()?.try_into()
}
+
+pub(crate) fn read_vendor_hashtree_root_digest(fdt: &Fdt) -> libfdt::Result<Option<&[u8]>> {
+ let node = fdt.node(cstr!("/avf"))?.ok_or(FdtError::NotFound)?;
+ node.getprop(cstr!("vendor_hashtree_descriptor_root_digest"))
+}
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 48b69b3..025edff 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -26,7 +26,7 @@
use crate::communication::VsockStream;
use crate::error::{Error, Result};
-use crate::fdt::read_dice_range_from;
+use crate::fdt::{read_dice_range_from, read_vendor_hashtree_root_digest};
use alloc::boxed::Box;
use bssl_sys::CRYPTO_library_init;
use ciborium_io::Write;
@@ -39,7 +39,7 @@
use log::{debug, error, info};
use service_vm_comm::{ServiceVmRequest, VmType};
use service_vm_fake_chain::service_vm;
-use service_vm_requests::process_request;
+use service_vm_requests::{process_request, RequestContext};
use virtio_drivers::{
device::socket::{VsockAddr, VMADDR_CID_HOST},
transport::{pci::bus::PciRoot, DeviceType, Transport},
@@ -174,11 +174,14 @@
debug!("PCI root: {pci_root:#x?}");
let socket_device = find_socket_device::<HalImpl>(&mut pci_root)?;
debug!("Found socket device: guest cid = {:?}", socket_device.guest_cid());
+ let vendor_hashtree_root_digest = read_vendor_hashtree_root_digest(fdt)?;
+ let request_context =
+ RequestContext { dice_artifacts: bcc_handover.as_ref(), vendor_hashtree_root_digest };
let mut vsock_stream = VsockStream::new(socket_device, host_addr())?;
while let ServiceVmRequest::Process(req) = vsock_stream.read_request()? {
info!("Received request: {}", req.name());
- let response = process_request(req, bcc_handover.as_ref());
+ let response = process_request(req, &request_context);
info!("Sending response: {}", response.name());
vsock_stream.write_response(&response)?;
vsock_stream.flush()?;
diff --git a/service_vm/comm/src/message.rs b/service_vm/comm/src/message.rs
index 9f83b78..c9aa711 100644
--- a/service_vm/comm/src/message.rs
+++ b/service_vm/comm/src/message.rs
@@ -158,6 +158,12 @@
/// The DICE chain from the client VM is invalid.
InvalidDiceChain,
+
+ /// Cannot find the vendor hash tree root digest in the device tree.
+ NoVendorHashTreeRootDigestInDT,
+
+ /// The vendor partition loaded by the client VM is invalid.
+ InvalidVendorPartition,
}
impl fmt::Display for RequestProcessingError {
@@ -186,6 +192,12 @@
Self::InvalidDiceChain => {
write!(f, "The DICE chain from the client VM is invalid")
}
+ Self::NoVendorHashTreeRootDigestInDT => {
+ write!(f, "Cannot find the vendor hash tree root digest in the device tree")
+ }
+ Self::InvalidVendorPartition => {
+ write!(f, "The vendor partition loaded by the client VM is invalid")
+ }
}
}
}
diff --git a/service_vm/requests/src/api.rs b/service_vm/requests/src/api.rs
index 315d2af..9eca20f 100644
--- a/service_vm/requests/src/api.rs
+++ b/service_vm/requests/src/api.rs
@@ -21,22 +21,38 @@
use service_vm_comm::{Request, Response};
/// Processes a request and returns the corresponding response.
-/// This function serves as the entry point for the request processing
-/// module.
-pub fn process_request(request: Request, dice_artifacts: &dyn DiceArtifacts) -> Response {
+/// This function serves as the entry point for the request processing module.
+pub fn process_request(request: Request, context: &RequestContext) -> Response {
match request {
Request::Reverse(v) => Response::Reverse(reverse(v)),
- Request::GenerateEcdsaP256KeyPair => rkp::generate_ecdsa_p256_key_pair(dice_artifacts)
- .map_or_else(Response::Err, Response::GenerateEcdsaP256KeyPair),
+ Request::GenerateEcdsaP256KeyPair => {
+ rkp::generate_ecdsa_p256_key_pair(context.dice_artifacts)
+ .map_or_else(Response::Err, Response::GenerateEcdsaP256KeyPair)
+ }
Request::GenerateCertificateRequest(p) => {
- rkp::generate_certificate_request(p, dice_artifacts)
+ rkp::generate_certificate_request(p, context.dice_artifacts)
.map_or_else(Response::Err, Response::GenerateCertificateRequest)
}
- Request::RequestClientVmAttestation(p) => client_vm::request_attestation(p, dice_artifacts)
- .map_or_else(Response::Err, Response::RequestClientVmAttestation),
+ Request::RequestClientVmAttestation(p) => client_vm::request_attestation(
+ p,
+ context.dice_artifacts,
+ context.vendor_hashtree_root_digest,
+ )
+ .map_or_else(Response::Err, Response::RequestClientVmAttestation),
}
}
+/// The context for the request processing.
+///
+/// This struct contains the reference data used during the request processing.
+pub struct RequestContext<'a> {
+ /// The reference DICE artifacts.
+ pub dice_artifacts: &'a dyn DiceArtifacts,
+
+ /// The reference hash tree root digest of the vendor partition if exists.
+ pub vendor_hashtree_root_digest: Option<&'a [u8]>,
+}
+
fn reverse(payload: Vec<u8>) -> Vec<u8> {
payload.into_iter().rev().collect()
}
diff --git a/service_vm/requests/src/client_vm.rs b/service_vm/requests/src/client_vm.rs
index 15a3bd0..d2e674b 100644
--- a/service_vm/requests/src/client_vm.rs
+++ b/service_vm/requests/src/client_vm.rs
@@ -16,9 +16,7 @@
//! client VM.
use crate::cert;
-use crate::dice::{
- validate_client_vm_dice_chain_prefix_match, ClientVmDiceChain, DiceChainEntryPayload,
-};
+use crate::dice::{ClientVmDiceChain, DiceChainEntryPayload};
use crate::keyblob::decrypt_private_key;
use alloc::vec::Vec;
use bssl_avf::{rand_bytes, sha256, Digester, EcKey, PKey};
@@ -28,7 +26,7 @@
use coset::{AsCborValue, CborSerializable, CoseSign, CoseSign1};
use der::{Decode, Encode};
use diced_open_dice::{DiceArtifacts, HASH_SIZE};
-use log::{error, info};
+use log::{debug, error, info};
use microdroid_kernel_hashes::{HASH_SIZE as KERNEL_HASH_SIZE, OS_HASHES};
use service_vm_comm::{ClientVmAttestationParams, Csr, CsrPayload, RequestProcessingError};
use x509_cert::{certificate::Certificate, name::Name};
@@ -41,6 +39,7 @@
pub(super) fn request_attestation(
params: ClientVmAttestationParams,
dice_artifacts: &dyn DiceArtifacts,
+ vendor_hashtree_root_digest_from_dt: Option<&[u8]>,
) -> Result<Vec<u8>> {
let csr = Csr::from_cbor_slice(¶ms.csr)?;
let cose_sign = CoseSign::from_slice(&csr.signed_csr_payload)?;
@@ -50,22 +49,11 @@
})?;
let csr_payload = CsrPayload::from_cbor_slice(csr_payload)?;
- // Validates the prefix of the Client VM DICE chain in the CSR.
- let service_vm_dice_chain =
- dice_artifacts.bcc().ok_or(RequestProcessingError::MissingDiceChain)?;
- let service_vm_dice_chain = parse_value_array(service_vm_dice_chain, "service_vm_dice_chain")?;
- let client_vm_dice_chain = parse_value_array(&csr.dice_cert_chain, "client_vm_dice_chain")?;
- validate_client_vm_dice_chain_prefix_match(&client_vm_dice_chain, &service_vm_dice_chain)?;
- // Validates the signatures in the Client VM DICE chain and extracts the partially decoded
- // DiceChainEntryPayloads.
- let client_vm_dice_chain =
- ClientVmDiceChain::validate_signatures_and_parse_dice_chain(client_vm_dice_chain)?;
-
- // The last entry in the service VM DICE chain describes the service VM, which should
- // be signed with the same key as the kernel image.
- let service_vm_entry = service_vm_dice_chain.last().unwrap();
- validate_kernel_authority_hash(client_vm_dice_chain.microdroid_kernel(), service_vm_entry)?;
- validate_kernel_code_hash(&client_vm_dice_chain)?;
+ let client_vm_dice_chain = validate_client_vm_dice_chain(
+ &csr.dice_cert_chain,
+ dice_artifacts.bcc().ok_or(RequestProcessingError::MissingDiceChain)?,
+ vendor_hashtree_root_digest_from_dt,
+ )?;
// AAD is empty as defined in service_vm/comm/client_vm_csr.cddl.
let aad = &[];
@@ -140,6 +128,83 @@
key.ecdsa_sign(&digest)
}
+fn validate_service_vm_dice_chain_length(service_vm_dice_chain: &[Value]) -> Result<()> {
+ if service_vm_dice_chain.len() < 3 {
+ // The service VM's DICE chain must contain the root key and at least two other entries
+ // that describe:
+ // - pvmfw
+ // - Service VM kernel
+ error!(
+ "The service VM DICE chain must contain at least three entries. Got '{}' entries",
+ service_vm_dice_chain.len()
+ );
+ return Err(RequestProcessingError::InternalError);
+ }
+ Ok(())
+}
+
+/// Validates the client VM DICE chain against the reference service VM DICE chain and
+/// the reference `vendor_hashtree_root_digest`.
+///
+/// Returns the valid `ClientVmDiceChain` if the validation succeeds.
+fn validate_client_vm_dice_chain(
+ client_vm_dice_chain: &[u8],
+ service_vm_dice_chain: &[u8],
+ vendor_hashtree_root_digest: Option<&[u8]>,
+) -> Result<ClientVmDiceChain> {
+ let service_vm_dice_chain = parse_value_array(service_vm_dice_chain, "service_vm_dice_chain")?;
+ validate_service_vm_dice_chain_length(&service_vm_dice_chain)?;
+
+ let client_vm_dice_chain = parse_value_array(client_vm_dice_chain, "client_vm_dice_chain")?;
+ validate_client_vm_dice_chain_prefix_match(&client_vm_dice_chain, &service_vm_dice_chain)?;
+
+ // Validates the signatures in the Client VM DICE chain and extracts the partially decoded
+ // DiceChainEntryPayloads.
+ let client_vm_dice_chain = ClientVmDiceChain::validate_signatures_and_parse_dice_chain(
+ client_vm_dice_chain,
+ service_vm_dice_chain.len(),
+ )?;
+ validate_vendor_partition_code_hash_if_exists(
+ &client_vm_dice_chain,
+ vendor_hashtree_root_digest,
+ )?;
+
+ // The last entry in the service VM DICE chain describes the service VM, which should
+ // be signed with the same key as the kernel image.
+ let service_vm_entry = service_vm_dice_chain.last().unwrap();
+ validate_kernel_authority_hash(client_vm_dice_chain.microdroid_kernel(), service_vm_entry)?;
+ validate_kernel_code_hash(&client_vm_dice_chain)?;
+
+ info!("The client VM DICE chain validation succeeded");
+ Ok(client_vm_dice_chain)
+}
+
+fn validate_vendor_partition_code_hash_if_exists(
+ client_vm_dice_chain: &ClientVmDiceChain,
+ vendor_hashtree_root_digest: Option<&[u8]>,
+) -> Result<()> {
+ let Some(vendor_partition) = client_vm_dice_chain.vendor_partition() else {
+ debug!("The vendor partition is not present in the Client VM DICE chain");
+ return Ok(());
+ };
+ let Some(expected_root_digest) = vendor_hashtree_root_digest else {
+ error!(
+ "The vendor partition is present in the DICE chain, \
+ but the vendor_hashtree_root_digest is not provided in the DT"
+ );
+ return Err(RequestProcessingError::NoVendorHashTreeRootDigestInDT);
+ };
+ if Digester::sha512().digest(expected_root_digest)? == vendor_partition.code_hash {
+ Ok(())
+ } else {
+ error!(
+ "The vendor partition code hash in the Client VM DICE chain does \
+ not match the expected value from the DT"
+ );
+ Err(RequestProcessingError::InvalidVendorPartition)
+ }
+}
+
/// Validates that the authority hash of the Microdroid kernel in the Client VM DICE chain
/// matches the authority hash of the service VM entry in the service VM DICE chain, because
/// the Microdroid kernel is signed with the same key as the one used for the service VM.
@@ -198,3 +263,20 @@
let service_vm = DiceChainEntryPayload::from_slice(&payload)?;
Ok(service_vm.authority_hash)
}
+
+fn validate_client_vm_dice_chain_prefix_match(
+ client_vm_dice_chain: &[Value],
+ service_vm_dice_chain: &[Value],
+) -> Result<()> {
+ // Ignores the last entry that describes service VM
+ let entries_up_to_pvmfw = &service_vm_dice_chain[0..(service_vm_dice_chain.len() - 1)];
+ if client_vm_dice_chain.get(0..entries_up_to_pvmfw.len()) == Some(entries_up_to_pvmfw) {
+ Ok(())
+ } else {
+ error!(
+ "The client VM's DICE chain does not match service VM's DICE chain up to \
+ the pvmfw entry"
+ );
+ Err(RequestProcessingError::InvalidDiceChain)
+ }
+}
diff --git a/service_vm/requests/src/dice.rs b/service_vm/requests/src/dice.rs
index 657e482..df29676 100644
--- a/service_vm/requests/src/dice.rs
+++ b/service_vm/requests/src/dice.rs
@@ -31,7 +31,7 @@
Label,
};
use diced_open_dice::{DiceMode, HASH_SIZE};
-use log::error;
+use log::{debug, error, info};
use service_vm_comm::RequestProcessingError;
type Result<T> = result::Result<T, RequestProcessingError>;
@@ -50,7 +50,8 @@
const SUB_COMPONENT_CODE_HASH: i64 = 3;
const SUB_COMPONENT_AUTHORITY_HASH: i64 = 4;
-const MICRODROID_KERNEL_COMPONENT_NAME: &str = "vm_entry";
+const KERNEL_COMPONENT_NAME: &str = "vm_entry";
+const VENDOR_PARTITION_COMPONENT_NAME: &str = "Microdroid vendor";
const MICRODROID_PAYLOAD_COMPONENT_NAME: &str = "Microdroid payload";
/// Represents a partially decoded `DiceCertChain` from the client VM.
@@ -63,6 +64,10 @@
#[derive(Debug, Clone)]
pub(crate) struct ClientVmDiceChain {
payloads: Vec<DiceChainEntryPayload>,
+ /// The index of the vendor partition entry in the DICE chain if it exists.
+ vendor_partition_index: Option<usize>,
+ /// The index of the kernel entry in the DICE chain.
+ kernel_index: usize,
}
impl ClientVmDiceChain {
@@ -75,7 +80,11 @@
/// Returns a partially decoded client VM's DICE chain if the verification succeeds.
pub(crate) fn validate_signatures_and_parse_dice_chain(
mut client_vm_dice_chain: Vec<Value>,
+ service_vm_dice_chain_len: usize,
) -> Result<Self> {
+ let has_vendor_partition =
+ vendor_partition_exists(client_vm_dice_chain.len(), service_vm_dice_chain_len)?;
+
let root_public_key =
CoseKey::from_cbor_value(client_vm_dice_chain.remove(0))?.try_into()?;
@@ -93,45 +102,62 @@
payloads.push(payload);
previous_public_key = &payloads.last().unwrap().subject_public_key;
}
- // After successfully calling `validate_client_vm_dice_chain_prefix_match`, we can be
- // certain that the client VM's DICE chain must contain at least three entries that
- // describe:
- // - pvmfw
- // - Microdroid kernel
- // - Apk/Apexes
- assert!(
- payloads.len() >= 3,
- "The client VM DICE chain must contain at least three DiceChainEntryPayloads"
- );
- let chain = Self { payloads };
- chain.validate_microdroid_components_names()?;
- Ok(chain)
+
+ Self::build(payloads, has_vendor_partition)
}
- fn validate_microdroid_components_names(&self) -> Result<()> {
- let microdroid_kernel_name = &self.microdroid_kernel().config_descriptor.component_name;
- if MICRODROID_KERNEL_COMPONENT_NAME != microdroid_kernel_name {
- error!(
- "The second to last entry in the client VM DICE chain must describe the \
- Microdroid kernel. Got {}",
- microdroid_kernel_name
- );
- return Err(RequestProcessingError::InvalidDiceChain);
- }
- let microdroid_payload_name = &self.microdroid_payload().config_descriptor.component_name;
+ fn build(
+ dice_entry_payloads: Vec<DiceChainEntryPayload>,
+ has_vendor_partition: bool,
+ ) -> Result<Self> {
+ let microdroid_payload_name =
+ &dice_entry_payloads[dice_entry_payloads.len() - 1].config_descriptor.component_name;
if MICRODROID_PAYLOAD_COMPONENT_NAME != microdroid_payload_name {
error!(
"The last entry in the client VM DICE chain must describe the Microdroid \
- payload. Got {}",
+ payload. Got '{}'",
microdroid_payload_name
);
return Err(RequestProcessingError::InvalidDiceChain);
}
- Ok(())
+
+ let (vendor_partition_index, kernel_index) = if has_vendor_partition {
+ let index = dice_entry_payloads.len() - 2;
+ let vendor_partition_name =
+ &dice_entry_payloads[index].config_descriptor.component_name;
+ if VENDOR_PARTITION_COMPONENT_NAME != vendor_partition_name {
+ error!(
+ "The vendor partition entry in the client VM DICE chain must describe the \
+ vendor partition. Got '{}'",
+ vendor_partition_name,
+ );
+ return Err(RequestProcessingError::InvalidDiceChain);
+ }
+ (Some(index), index - 1)
+ } else {
+ (None, dice_entry_payloads.len() - 2)
+ };
+
+ let kernel_name = &dice_entry_payloads[kernel_index].config_descriptor.component_name;
+ if KERNEL_COMPONENT_NAME != kernel_name {
+ error!(
+ "The microdroid kernel entry in the client VM DICE chain must describe the \
+ Microdroid kernel. Got '{}'",
+ kernel_name,
+ );
+ return Err(RequestProcessingError::InvalidDiceChain);
+ }
+
+ debug!("All entries in the client VM DICE chain have correct component names");
+ Ok(Self { payloads: dice_entry_payloads, vendor_partition_index, kernel_index })
}
pub(crate) fn microdroid_kernel(&self) -> &DiceChainEntryPayload {
- &self.payloads[self.payloads.len() - 2]
+ &self.payloads[self.kernel_index]
+ }
+
+ pub(crate) fn vendor_partition(&self) -> Option<&DiceChainEntryPayload> {
+ self.vendor_partition_index.map(|i| &self.payloads[i])
}
pub(crate) fn microdroid_payload(&self) -> &DiceChainEntryPayload {
@@ -148,39 +174,33 @@
}
}
-/// Validates that the `client_vm_dice_chain` matches the `service_vm_dice_chain` up to the pvmfw
-/// entry.
-///
-/// Returns `Ok(())` if the verification succeeds.
-pub(crate) fn validate_client_vm_dice_chain_prefix_match(
- client_vm_dice_chain: &[Value],
- service_vm_dice_chain: &[Value],
-) -> Result<()> {
- if service_vm_dice_chain.len() < 3 {
- // The service VM's DICE chain must contain the root key and at least two other entries
- // that describe:
- // - pvmfw
- // - Service VM kernel
- error!("The service VM DICE chain must contain at least three entries");
- return Err(RequestProcessingError::InternalError);
+fn vendor_partition_exists(
+ client_vm_dice_chain_len: usize,
+ service_vm_dice_chain_len: usize,
+) -> Result<bool> {
+ let entries_up_to_pvmfw_len = service_vm_dice_chain_len - 1;
+ // Client VM DICE chain = entries_up_to_pvmfw
+ // + Vendor module entry (exists only when the vendor partition is present)
+ // + Microdroid kernel entry (added in pvmfw)
+ // + Apk/Apexes entry (added in microdroid)
+ match client_vm_dice_chain_len.checked_sub(entries_up_to_pvmfw_len) {
+ Some(2) => {
+ debug!("The vendor partition entry is not present in the client VM's DICE chain");
+ Ok(false)
+ }
+ Some(3) => {
+ info!("The vendor partition entry is present in the client VM's DICE chain");
+ Ok(true)
+ }
+ _ => {
+ error!(
+ "The client VM's DICE chain must contain two or three extra entries. \
+ Service VM DICE chain: {} entries, client VM DICE chain: {} entries",
+ service_vm_dice_chain_len, client_vm_dice_chain_len
+ );
+ Err(RequestProcessingError::InvalidDiceChain)
+ }
}
- // Ignores the last entry that describes service VM
- let entries_up_to_pvmfw = &service_vm_dice_chain[0..(service_vm_dice_chain.len() - 1)];
- if entries_up_to_pvmfw.len() + 2 != client_vm_dice_chain.len() {
- // Client VM DICE chain = entries_up_to_pvmfw
- // + Microdroid kernel entry (added in pvmfw)
- // + Apk/Apexes entry (added in microdroid)
- error!("The client VM's DICE chain must contain exactly two extra entries");
- return Err(RequestProcessingError::InvalidDiceChain);
- }
- if entries_up_to_pvmfw != &client_vm_dice_chain[0..entries_up_to_pvmfw.len()] {
- error!(
- "The client VM's DICE chain does not match service VM's DICE chain up to \
- the pvmfw entry"
- );
- return Err(RequestProcessingError::InvalidDiceChain);
- }
- Ok(())
}
#[derive(Debug, Clone)]
diff --git a/service_vm/requests/src/lib.rs b/service_vm/requests/src/lib.rs
index 0dfac09..36b006f 100644
--- a/service_vm/requests/src/lib.rs
+++ b/service_vm/requests/src/lib.rs
@@ -26,4 +26,4 @@
mod pub_key;
mod rkp;
-pub use api::process_request;
+pub use api::{process_request, RequestContext};
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 29e9014..966e7bf 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -247,6 +247,24 @@
@Test
@CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
+ public void vmAttestationWithVendorPartitionWhenSupported() throws Exception {
+ // pVM remote attestation is only supported on protected VMs.
+ assumeProtectedVM();
+ assumeFeatureEnabled(VirtualMachineManager.FEATURE_REMOTE_ATTESTATION);
+ assume().withMessage("Test needs Remote Attestation support")
+ .that(getVirtualMachineManager().isRemoteAttestationSupported())
+ .isTrue();
+ File vendorDiskImage = new File("/vendor/etc/avf/microdroid/microdroid_vendor.img");
+ assumeTrue("Microdroid vendor image doesn't exist, skip", vendorDiskImage.exists());
+ VirtualMachineConfig config =
+ buildVmConfigWithVendor(vendorDiskImage, VM_ATTESTATION_PAYLOAD_PATH);
+ VirtualMachine vm =
+ forceCreateNewVirtualMachine("cts_attestation_with_vendor_module", config);
+ checkVmAttestationWithValidChallenge(vm);
+ }
+
+ @Test
+ @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
public void vmAttestationWhenRemoteAttestationIsSupported() throws Exception {
// pVM remote attestation is only supported on protected VMs.
assumeProtectedVM();
@@ -272,6 +290,10 @@
.isEqualTo(AttestationStatus.ERROR_INVALID_CHALLENGE);
// Check with a valid challenge.
+ checkVmAttestationWithValidChallenge(vm);
+ }
+
+ private void checkVmAttestationWithValidChallenge(VirtualMachine vm) throws Exception {
byte[] challenge = new byte[32];
Arrays.fill(challenge, (byte) 0xac);
SigningResult signingResult =
@@ -2265,6 +2287,11 @@
}
private VirtualMachineConfig buildVmConfigWithVendor(File vendorDiskImage) throws Exception {
+ return buildVmConfigWithVendor(vendorDiskImage, "MicrodroidTestNativeLib.so");
+ }
+
+ private VirtualMachineConfig buildVmConfigWithVendor(File vendorDiskImage, String binaryPath)
+ throws Exception {
assumeSupportedDevice();
// TODO(b/325094712): Boot fails with vendor partition in Cuttlefish.
assumeFalse(
@@ -2275,7 +2302,7 @@
"boot with vendor partition is failing in HWASAN enabled Microdroid.", isHwasan());
assumeFeatureEnabled(VirtualMachineManager.FEATURE_VENDOR_MODULES);
VirtualMachineConfig config =
- newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+ newVmConfigBuilderWithPayloadBinary(binaryPath)
.setVendorDiskImage(vendorDiskImage)
.setDebugLevel(DEBUG_LEVEL_FULL)
.build();