blob: 0f593508767d7bae19ddb0516d0c08d9d9d0f2b2 [file] [log] [blame]
David Brazdil66fc1202022-07-04 21:48:45 +01001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Integration test for Rialto.
16
17use android_system_virtualizationservice::{
18 aidl::android::system::virtualizationservice::{
Alice Wanga6357692023-09-07 14:59:37 +000019 VirtualMachineConfig::VirtualMachineConfig,
David Brazdil66fc1202022-07-04 21:48:45 +010020 VirtualMachineRawConfig::VirtualMachineRawConfig,
21 },
22 binder::{ParcelFileDescriptor, ProcessState},
23};
Alice Wang9646fb32023-09-08 10:01:31 +000024use anyhow::{bail, Context, Result};
Alice Wangf7c0f942023-09-14 09:33:04 +000025use ciborium::value::Value;
Alice Wangde6bee52023-11-10 09:58:40 +000026use client_vm_csr::generate_attestation_key_and_csr;
David Brazdil66fc1202022-07-04 21:48:45 +010027use log::info;
Alice Wang9646fb32023-09-08 10:01:31 +000028use service_vm_comm::{
Alice Wang74eb78b2023-11-09 16:13:10 +000029 ClientVmAttestationParams, EcdsaP256KeyPair, GenerateCertificateRequestParams, Request,
30 RequestProcessingError, Response, VmType,
Alice Wang9646fb32023-09-08 10:01:31 +000031};
Alice Wang17dc76e2023-09-06 09:43:52 +000032use service_vm_manager::ServiceVm;
David Brazdil66fc1202022-07-04 21:48:45 +010033use std::fs::File;
Alice Wangf7c0f942023-09-14 09:33:04 +000034use std::io;
David Brazdil66fc1202022-07-04 21:48:45 +010035use std::panic;
Alice Wang17dc76e2023-09-06 09:43:52 +000036use std::path::PathBuf;
Alice Wang17dc76e2023-09-06 09:43:52 +000037use vmclient::VmInstance;
Alice Wang4e082c32023-07-11 07:41:50 +000038
Alice Wang9a8b39f2023-04-12 15:31:48 +000039const UNSIGNED_RIALTO_PATH: &str = "/data/local/tmp/rialto_test/arm64/rialto_unsigned.bin";
40const INSTANCE_IMG_PATH: &str = "/data/local/tmp/rialto_test/arm64/instance.img";
David Brazdil66fc1202022-07-04 21:48:45 +010041
Alice Wang9a8b39f2023-04-12 15:31:48 +000042#[test]
Alice Wange910b902023-09-07 10:35:12 +000043fn process_requests_in_protected_vm() -> Result<()> {
Alice Wang9646fb32023-09-08 10:01:31 +000044 check_processing_requests(VmType::ProtectedVm)
Alice Wang9a8b39f2023-04-12 15:31:48 +000045}
46
Alice Wange910b902023-09-07 10:35:12 +000047#[test]
48fn process_requests_in_non_protected_vm() -> Result<()> {
Alice Wang9646fb32023-09-08 10:01:31 +000049 check_processing_requests(VmType::NonProtectedVm)
50}
51
52fn check_processing_requests(vm_type: VmType) -> Result<()> {
53 let mut vm = start_service_vm(vm_type)?;
Alice Wange910b902023-09-07 10:35:12 +000054
55 check_processing_reverse_request(&mut vm)?;
Alice Wang74eb78b2023-11-09 16:13:10 +000056 let key_pair = check_processing_generating_key_pair_request(&mut vm)?;
57 check_processing_generating_certificate_request(&mut vm, &key_pair.maced_public_key)?;
58 check_attestation_request(&mut vm, &key_pair.key_blob)?;
Alice Wange910b902023-09-07 10:35:12 +000059 Ok(())
60}
61
62fn check_processing_reverse_request(vm: &mut ServiceVm) -> Result<()> {
Alice Wang0486e252023-10-06 14:30:49 +000063 let message = "abc".repeat(500);
Alice Wange910b902023-09-07 10:35:12 +000064 let request = Request::Reverse(message.as_bytes().to_vec());
65
Alice Wangfbdc85b2023-09-07 12:56:46 +000066 let response = vm.process_request(request)?;
67 info!("Received response: {response:?}.");
Alice Wange910b902023-09-07 10:35:12 +000068
69 let expected_response: Vec<u8> = message.as_bytes().iter().rev().cloned().collect();
70 assert_eq!(Response::Reverse(expected_response), response);
71 Ok(())
72}
73
Alice Wang74eb78b2023-11-09 16:13:10 +000074fn check_processing_generating_key_pair_request(vm: &mut ServiceVm) -> Result<EcdsaP256KeyPair> {
Alice Wang9646fb32023-09-08 10:01:31 +000075 let request = Request::GenerateEcdsaP256KeyPair;
76
77 let response = vm.process_request(request)?;
78 info!("Received response: {response:?}.");
79
80 match response {
Alice Wang74eb78b2023-11-09 16:13:10 +000081 Response::GenerateEcdsaP256KeyPair(key_pair) => {
82 assert_array_has_nonzero(&key_pair.maced_public_key);
83 assert_array_has_nonzero(&key_pair.key_blob);
84 Ok(key_pair)
Alice Wanga78d3f02023-09-13 12:39:16 +000085 }
Alice Wangff5592d2023-09-13 15:27:39 +000086 _ => bail!("Incorrect response type: {response:?}"),
Alice Wang9646fb32023-09-08 10:01:31 +000087 }
88}
89
Alice Wanga78d3f02023-09-13 12:39:16 +000090fn assert_array_has_nonzero(v: &[u8]) {
91 assert!(v.iter().any(|&x| x != 0))
92}
93
Alice Wangff5592d2023-09-13 15:27:39 +000094fn check_processing_generating_certificate_request(
95 vm: &mut ServiceVm,
Alice Wang74eb78b2023-11-09 16:13:10 +000096 maced_public_key: &[u8],
Alice Wangff5592d2023-09-13 15:27:39 +000097) -> Result<()> {
98 let params = GenerateCertificateRequestParams {
Alice Wang74eb78b2023-11-09 16:13:10 +000099 keys_to_sign: vec![maced_public_key.to_vec()],
Alice Wangff5592d2023-09-13 15:27:39 +0000100 challenge: vec![],
101 };
Alice Wang9646fb32023-09-08 10:01:31 +0000102 let request = Request::GenerateCertificateRequest(params);
103
104 let response = vm.process_request(request)?;
105 info!("Received response: {response:?}.");
106
107 match response {
Alice Wangf7c0f942023-09-14 09:33:04 +0000108 Response::GenerateCertificateRequest(csr) => check_csr(csr),
Alice Wangff5592d2023-09-13 15:27:39 +0000109 _ => bail!("Incorrect response type: {response:?}"),
Alice Wang9646fb32023-09-08 10:01:31 +0000110 }
111}
112
Alice Wang74eb78b2023-11-09 16:13:10 +0000113fn check_attestation_request(vm: &mut ServiceVm, key_blob: &[u8]) -> Result<()> {
Alice Wangde6bee52023-11-10 09:58:40 +0000114 /// The following data was generated randomly with urandom.
115 const CHALLENGE: [u8; 16] = [
116 0x7d, 0x86, 0x58, 0x79, 0x3a, 0x09, 0xdf, 0x1c, 0xa5, 0x80, 0x80, 0x15, 0x2b, 0x13, 0x17,
117 0x5c,
118 ];
119 let dice_artifacts = diced_sample_inputs::make_sample_bcc_and_cdis()?;
120 let attestation_data = generate_attestation_key_and_csr(&CHALLENGE, &dice_artifacts)?;
121
122 let params = ClientVmAttestationParams {
123 csr: attestation_data.csr.into_cbor_vec()?,
124 remotely_provisioned_key_blob: key_blob.to_vec(),
125 };
Alice Wang74eb78b2023-11-09 16:13:10 +0000126 let request = Request::RequestClientVmAttestation(params);
127
128 let response = vm.process_request(request)?;
129 info!("Received response: {response:?}.");
130
131 match response {
132 // TODO(b/309441500): Check the certificate once it is implemented.
133 Response::Err(RequestProcessingError::OperationUnimplemented) => Ok(()),
134 _ => bail!("Incorrect response type: {response:?}"),
135 }
136}
137
Alice Wangf7c0f942023-09-14 09:33:04 +0000138/// TODO(b/300625792): Check the CSR with libhwtrust once the CSR is complete.
139fn check_csr(csr: Vec<u8>) -> Result<()> {
140 let mut reader = io::Cursor::new(csr);
141 let csr: Value = ciborium::from_reader(&mut reader)?;
142 match csr {
143 Value::Array(arr) => {
144 assert_eq!(4, arr.len());
145 }
146 _ => bail!("Incorrect CSR format: {csr:?}"),
147 }
148 Ok(())
149}
150
Alice Wange910b902023-09-07 10:35:12 +0000151fn start_service_vm(vm_type: VmType) -> Result<ServiceVm> {
David Brazdil66fc1202022-07-04 21:48:45 +0100152 android_logger::init_once(
153 android_logger::Config::default().with_tag("rialto").with_min_level(log::Level::Debug),
154 );
David Brazdil66fc1202022-07-04 21:48:45 +0100155 // Redirect panic messages to logcat.
156 panic::set_hook(Box::new(|panic_info| {
157 log::error!("{}", panic_info);
158 }));
David Brazdil66fc1202022-07-04 21:48:45 +0100159 // We need to start the thread pool for Binder to work properly, especially link_to_death.
160 ProcessState::start_thread_pool();
Alice Wange910b902023-09-07 10:35:12 +0000161 ServiceVm::start_vm(vm_instance(vm_type)?, vm_type)
Alice Wang17dc76e2023-09-06 09:43:52 +0000162}
163
Alice Wange910b902023-09-07 10:35:12 +0000164fn vm_instance(vm_type: VmType) -> Result<VmInstance> {
Alice Wanga6357692023-09-07 14:59:37 +0000165 match vm_type {
Alice Wang1d9a5872023-09-06 14:32:36 +0000166 VmType::ProtectedVm => {
Alice Wanga6357692023-09-07 14:59:37 +0000167 service_vm_manager::protected_vm_instance(PathBuf::from(INSTANCE_IMG_PATH))
Alice Wang1d9a5872023-09-06 14:32:36 +0000168 }
Alice Wanga6357692023-09-07 14:59:37 +0000169 VmType::NonProtectedVm => nonprotected_vm_instance(),
170 }
171}
172
173fn nonprotected_vm_instance() -> Result<VmInstance> {
174 let rialto = File::open(UNSIGNED_RIALTO_PATH).context("Failed to open Rialto kernel binary")?;
David Brazdil66fc1202022-07-04 21:48:45 +0100175 let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig {
Alice Wanga6357692023-09-07 14:59:37 +0000176 name: String::from("Non protected rialto"),
David Brazdil66fc1202022-07-04 21:48:45 +0100177 bootloader: Some(ParcelFileDescriptor::new(rialto)),
Alice Wanga6357692023-09-07 14:59:37 +0000178 protectedVm: false,
David Brazdil66fc1202022-07-04 21:48:45 +0100179 memoryMib: 300,
David Brazdil66fc1202022-07-04 21:48:45 +0100180 platformVersion: "~1.0".to_string(),
Inseob Kim6ef80972023-07-20 17:23:36 +0900181 ..Default::default()
David Brazdil66fc1202022-07-04 21:48:45 +0100182 });
Alice Wanga6357692023-09-07 14:59:37 +0000183 let console = Some(service_vm_manager::android_log_fd()?);
184 let log = Some(service_vm_manager::android_log_fd()?);
185 let virtmgr = vmclient::VirtualizationService::new().context("Failed to spawn VirtMgr")?;
186 let service = virtmgr.connect().context("Failed to connect to VirtMgr")?;
187 info!("Connected to VirtMgr for service VM");
188 VmInstance::create(service.as_ref(), &config, console, /* consoleIn */ None, log, None)
189 .context("Failed to create VM")
David Brazdil66fc1202022-07-04 21:48:45 +0100190}