blob: 02a5a28388f12142648b2f5adf7b4bcc3e12a4a6 [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 Wangeb77f7d2023-12-01 09:13:58 +000025use bssl_avf::{sha256, EcKey, PKey};
Alice Wangf7c0f942023-09-14 09:33:04 +000026use ciborium::value::Value;
Alice Wangde6bee52023-11-10 09:58:40 +000027use client_vm_csr::generate_attestation_key_and_csr;
Alice Wang20b8ebc2023-11-17 09:54:47 +000028use coset::{CborSerializable, CoseMac0, CoseSign};
David Brazdil66fc1202022-07-04 21:48:45 +010029use log::info;
Alice Wang9646fb32023-09-08 10:01:31 +000030use service_vm_comm::{
Alice Wang20b8ebc2023-11-17 09:54:47 +000031 ClientVmAttestationParams, Csr, CsrPayload, EcdsaP256KeyPair, GenerateCertificateRequestParams,
Alice Wangd3a96402023-11-24 15:37:39 +000032 Request, RequestProcessingError, Response, VmType,
Alice Wang9646fb32023-09-08 10:01:31 +000033};
Alice Wang1cc13502023-12-05 11:05:34 +000034use service_vm_fake_chain::client_vm::{
35 fake_client_vm_dice_artifacts, fake_sub_components, SubComponent,
36};
Alice Wang17dc76e2023-09-06 09:43:52 +000037use service_vm_manager::ServiceVm;
Alice Wang20b8ebc2023-11-17 09:54:47 +000038use std::fs;
David Brazdil66fc1202022-07-04 21:48:45 +010039use std::fs::File;
Alice Wangf7c0f942023-09-14 09:33:04 +000040use std::io;
David Brazdil66fc1202022-07-04 21:48:45 +010041use std::panic;
Alice Wang17dc76e2023-09-06 09:43:52 +000042use std::path::PathBuf;
Alice Wang17dc76e2023-09-06 09:43:52 +000043use vmclient::VmInstance;
Alice Wang20b8ebc2023-11-17 09:54:47 +000044use x509_parser::{
45 certificate::X509Certificate,
Alice Wang1cc13502023-12-05 11:05:34 +000046 der_parser::{ber::BerObject, der::parse_der, oid, oid::Oid},
Alice Wang20b8ebc2023-11-17 09:54:47 +000047 prelude::FromDer,
48 x509::{AlgorithmIdentifier, SubjectPublicKeyInfo, X509Version},
49};
Alice Wang4e082c32023-07-11 07:41:50 +000050
Alice Wang9a8b39f2023-04-12 15:31:48 +000051const UNSIGNED_RIALTO_PATH: &str = "/data/local/tmp/rialto_test/arm64/rialto_unsigned.bin";
52const INSTANCE_IMG_PATH: &str = "/data/local/tmp/rialto_test/arm64/instance.img";
Alice Wang20b8ebc2023-11-17 09:54:47 +000053const TEST_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
David Brazdil66fc1202022-07-04 21:48:45 +010054
Alice Wang9a8b39f2023-04-12 15:31:48 +000055#[test]
Alice Wange910b902023-09-07 10:35:12 +000056fn process_requests_in_protected_vm() -> Result<()> {
Alice Wang9646fb32023-09-08 10:01:31 +000057 check_processing_requests(VmType::ProtectedVm)
Alice Wang9a8b39f2023-04-12 15:31:48 +000058}
59
Alice Wange910b902023-09-07 10:35:12 +000060#[test]
61fn process_requests_in_non_protected_vm() -> Result<()> {
Alice Wang9646fb32023-09-08 10:01:31 +000062 check_processing_requests(VmType::NonProtectedVm)
63}
64
65fn check_processing_requests(vm_type: VmType) -> Result<()> {
66 let mut vm = start_service_vm(vm_type)?;
Alice Wange910b902023-09-07 10:35:12 +000067
68 check_processing_reverse_request(&mut vm)?;
Alice Wang74eb78b2023-11-09 16:13:10 +000069 let key_pair = check_processing_generating_key_pair_request(&mut vm)?;
70 check_processing_generating_certificate_request(&mut vm, &key_pair.maced_public_key)?;
Alice Wangd3a96402023-11-24 15:37:39 +000071 check_attestation_request(&mut vm, &key_pair, vm_type)?;
Alice Wange910b902023-09-07 10:35:12 +000072 Ok(())
73}
74
75fn check_processing_reverse_request(vm: &mut ServiceVm) -> Result<()> {
Alice Wang0486e252023-10-06 14:30:49 +000076 let message = "abc".repeat(500);
Alice Wange910b902023-09-07 10:35:12 +000077 let request = Request::Reverse(message.as_bytes().to_vec());
78
Alice Wangfbdc85b2023-09-07 12:56:46 +000079 let response = vm.process_request(request)?;
80 info!("Received response: {response:?}.");
Alice Wange910b902023-09-07 10:35:12 +000081
82 let expected_response: Vec<u8> = message.as_bytes().iter().rev().cloned().collect();
83 assert_eq!(Response::Reverse(expected_response), response);
84 Ok(())
85}
86
Alice Wang74eb78b2023-11-09 16:13:10 +000087fn check_processing_generating_key_pair_request(vm: &mut ServiceVm) -> Result<EcdsaP256KeyPair> {
Alice Wang9646fb32023-09-08 10:01:31 +000088 let request = Request::GenerateEcdsaP256KeyPair;
89
90 let response = vm.process_request(request)?;
91 info!("Received response: {response:?}.");
92
93 match response {
Alice Wang74eb78b2023-11-09 16:13:10 +000094 Response::GenerateEcdsaP256KeyPair(key_pair) => {
95 assert_array_has_nonzero(&key_pair.maced_public_key);
96 assert_array_has_nonzero(&key_pair.key_blob);
97 Ok(key_pair)
Alice Wanga78d3f02023-09-13 12:39:16 +000098 }
Alice Wangff5592d2023-09-13 15:27:39 +000099 _ => bail!("Incorrect response type: {response:?}"),
Alice Wang9646fb32023-09-08 10:01:31 +0000100 }
101}
102
Alice Wanga78d3f02023-09-13 12:39:16 +0000103fn assert_array_has_nonzero(v: &[u8]) {
104 assert!(v.iter().any(|&x| x != 0))
105}
106
Alice Wangff5592d2023-09-13 15:27:39 +0000107fn check_processing_generating_certificate_request(
108 vm: &mut ServiceVm,
Alice Wang74eb78b2023-11-09 16:13:10 +0000109 maced_public_key: &[u8],
Alice Wangff5592d2023-09-13 15:27:39 +0000110) -> Result<()> {
111 let params = GenerateCertificateRequestParams {
Alice Wang74eb78b2023-11-09 16:13:10 +0000112 keys_to_sign: vec![maced_public_key.to_vec()],
Alice Wangff5592d2023-09-13 15:27:39 +0000113 challenge: vec![],
114 };
Alice Wang9646fb32023-09-08 10:01:31 +0000115 let request = Request::GenerateCertificateRequest(params);
116
117 let response = vm.process_request(request)?;
118 info!("Received response: {response:?}.");
119
120 match response {
Alice Wangf7c0f942023-09-14 09:33:04 +0000121 Response::GenerateCertificateRequest(csr) => check_csr(csr),
Alice Wangff5592d2023-09-13 15:27:39 +0000122 _ => bail!("Incorrect response type: {response:?}"),
Alice Wang9646fb32023-09-08 10:01:31 +0000123 }
124}
125
Alice Wang20b8ebc2023-11-17 09:54:47 +0000126fn check_attestation_request(
127 vm: &mut ServiceVm,
128 remotely_provisioned_key_pair: &EcdsaP256KeyPair,
Alice Wangd3a96402023-11-24 15:37:39 +0000129 vm_type: VmType,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000130) -> Result<()> {
Alice Wangde6bee52023-11-10 09:58:40 +0000131 /// The following data was generated randomly with urandom.
132 const CHALLENGE: [u8; 16] = [
133 0x7d, 0x86, 0x58, 0x79, 0x3a, 0x09, 0xdf, 0x1c, 0xa5, 0x80, 0x80, 0x15, 0x2b, 0x13, 0x17,
134 0x5c,
135 ];
Alice Wang4ac9c8b2023-12-05 16:23:14 +0000136 let dice_artifacts = fake_client_vm_dice_artifacts()?;
Alice Wangde6bee52023-11-10 09:58:40 +0000137 let attestation_data = generate_attestation_key_and_csr(&CHALLENGE, &dice_artifacts)?;
Alice Wang20b8ebc2023-11-17 09:54:47 +0000138 let cert_chain = fs::read(TEST_CERT_CHAIN_PATH)?;
139 let (remaining, cert) = X509Certificate::from_der(&cert_chain)?;
Alice Wangde6bee52023-11-10 09:58:40 +0000140
Alice Wang20b8ebc2023-11-17 09:54:47 +0000141 // Builds the mock parameters for the client VM attestation.
142 // The `csr` and `remotely_provisioned_key_blob` parameters are extracted from the same
143 // libraries as in production.
144 // The `remotely_provisioned_cert` parameter is an RKP certificate extracted from a test
145 // certificate chain retrieved from RKPD.
Alice Wangde6bee52023-11-10 09:58:40 +0000146 let params = ClientVmAttestationParams {
Alice Wang20b8ebc2023-11-17 09:54:47 +0000147 csr: attestation_data.csr.clone().into_cbor_vec()?,
148 remotely_provisioned_key_blob: remotely_provisioned_key_pair.key_blob.to_vec(),
149 remotely_provisioned_cert: cert_chain[..(cert_chain.len() - remaining.len())].to_vec(),
Alice Wangde6bee52023-11-10 09:58:40 +0000150 };
Alice Wang74eb78b2023-11-09 16:13:10 +0000151 let request = Request::RequestClientVmAttestation(params);
152
153 let response = vm.process_request(request)?;
154 info!("Received response: {response:?}.");
155
156 match response {
Alice Wang20b8ebc2023-11-17 09:54:47 +0000157 Response::RequestClientVmAttestation(certificate) => {
Alice Wangd3a96402023-11-24 15:37:39 +0000158 // The end-to-end test for non-protected VM attestation works because both the service
159 // VM and the client VM use the same fake DICE chain.
160 assert_eq!(vm_type, VmType::NonProtectedVm);
Alice Wang20b8ebc2023-11-17 09:54:47 +0000161 check_certificate_for_client_vm(
162 &certificate,
163 &remotely_provisioned_key_pair.maced_public_key,
164 &attestation_data.csr,
165 &cert,
166 )?;
167 Ok(())
168 }
Alice Wangd3a96402023-11-24 15:37:39 +0000169 Response::Err(RequestProcessingError::InvalidDiceChain) => {
170 // The end-to-end test for protected VM attestation doesn't work because the service VM
171 // compares the fake DICE chain in the CSR with the real DICE chain.
172 // We cannot generate a valid DICE chain with the same payloads up to pvmfw.
173 assert_eq!(vm_type, VmType::ProtectedVm);
174 Ok(())
175 }
Alice Wang74eb78b2023-11-09 16:13:10 +0000176 _ => bail!("Incorrect response type: {response:?}"),
177 }
178}
179
Alice Wang1cc13502023-12-05 11:05:34 +0000180fn check_vm_components(vm_components: &[BerObject]) -> Result<()> {
181 let expected_components = fake_sub_components();
182 assert_eq!(expected_components.len(), vm_components.len());
183 for i in 0..expected_components.len() {
184 check_vm_component(&vm_components[i], &expected_components[i])?;
185 }
186 Ok(())
187}
188
189fn check_vm_component(vm_component: &BerObject, expected_component: &SubComponent) -> Result<()> {
190 let vm_component = vm_component.as_sequence()?;
191 assert_eq!(4, vm_component.len());
192 assert_eq!(expected_component.name, vm_component[0].as_str()?);
193 assert_eq!(expected_component.version, vm_component[1].as_u64()?);
194 assert_eq!(expected_component.code_hash, vm_component[2].as_slice()?);
195 assert_eq!(expected_component.authority_hash, vm_component[3].as_slice()?);
196 Ok(())
197}
198
Alice Wang20b8ebc2023-11-17 09:54:47 +0000199fn check_certificate_for_client_vm(
200 certificate: &[u8],
201 maced_public_key: &[u8],
202 csr: &Csr,
203 parent_certificate: &X509Certificate,
204) -> Result<()> {
205 let cose_mac = CoseMac0::from_slice(maced_public_key)?;
Alice Wangbe7a4b12023-12-01 11:53:36 +0000206 let authority_public_key =
207 EcKey::from_cose_public_key_slice(&cose_mac.payload.unwrap()).unwrap();
Alice Wang20b8ebc2023-11-17 09:54:47 +0000208 let (remaining, cert) = X509Certificate::from_der(certificate)?;
209 assert!(remaining.is_empty());
210
211 // Checks the certificate signature against the authority public key.
212 const ECDSA_WITH_SHA_256: Oid<'static> = oid!(1.2.840 .10045 .4 .3 .2);
213 let expected_algorithm =
214 AlgorithmIdentifier { algorithm: ECDSA_WITH_SHA_256, parameters: None };
215 assert_eq!(expected_algorithm, cert.signature_algorithm);
216 let digest = sha256(cert.tbs_certificate.as_ref()).unwrap();
217 authority_public_key
218 .ecdsa_verify(cert.signature_value.as_ref(), &digest)
219 .expect("Failed to verify the certificate signature with the authority public key");
220
221 // Checks that the certificate's subject public key is equal to the key in the CSR.
222 let cose_sign = CoseSign::from_slice(&csr.signed_csr_payload)?;
223 let csr_payload =
224 cose_sign.payload.as_ref().and_then(|v| CsrPayload::from_cbor_slice(v).ok()).unwrap();
Alice Wangbe7a4b12023-12-01 11:53:36 +0000225 let subject_public_key = EcKey::from_cose_public_key_slice(&csr_payload.public_key).unwrap();
Alice Wang20b8ebc2023-11-17 09:54:47 +0000226 let expected_spki_data =
Alice Wangeb77f7d2023-12-01 09:13:58 +0000227 PKey::try_from(subject_public_key).unwrap().subject_public_key_info().unwrap();
Alice Wang20b8ebc2023-11-17 09:54:47 +0000228 let (remaining, expected_spki) = SubjectPublicKeyInfo::from_der(&expected_spki_data)?;
229 assert!(remaining.is_empty());
230 assert_eq!(&expected_spki, cert.public_key());
231
232 // Checks the certificate extension.
233 const ATTESTATION_EXTENSION_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .11129 .2 .1 .29 .1);
234 let extensions = cert.extensions();
235 assert_eq!(1, extensions.len());
236 let extension = &extensions[0];
237 assert_eq!(ATTESTATION_EXTENSION_OID, extension.oid);
238 assert!(!extension.critical);
239 let (remaining, extension) = parse_der(extension.value)?;
240 assert!(remaining.is_empty());
241 let attestation_ext = extension.as_sequence()?;
Alice Wang1cc13502023-12-05 11:05:34 +0000242 assert_eq!(3, attestation_ext.len());
Alice Wang20b8ebc2023-11-17 09:54:47 +0000243 assert_eq!(csr_payload.challenge, attestation_ext[0].as_slice()?);
Alice Wangd3a96402023-11-24 15:37:39 +0000244 let is_vm_secure = attestation_ext[1].as_bool()?;
245 assert!(
246 !is_vm_secure,
247 "The VM shouldn't be secure as the last payload added in the test is in Debug mode"
248 );
Alice Wang1cc13502023-12-05 11:05:34 +0000249 let vm_components = attestation_ext[2].as_sequence()?;
250 check_vm_components(vm_components)?;
Alice Wang20b8ebc2023-11-17 09:54:47 +0000251
252 // Checks other fields on the certificate
253 assert_eq!(X509Version::V3, cert.version());
254 assert_eq!(parent_certificate.validity(), cert.validity());
255 assert_eq!(
256 String::from("CN=Android Protected Virtual Machine Key"),
257 cert.subject().to_string()
258 );
259 assert_eq!(parent_certificate.subject(), cert.issuer());
260
261 Ok(())
262}
263
Alice Wangf7c0f942023-09-14 09:33:04 +0000264/// TODO(b/300625792): Check the CSR with libhwtrust once the CSR is complete.
265fn check_csr(csr: Vec<u8>) -> Result<()> {
266 let mut reader = io::Cursor::new(csr);
267 let csr: Value = ciborium::from_reader(&mut reader)?;
268 match csr {
269 Value::Array(arr) => {
270 assert_eq!(4, arr.len());
271 }
272 _ => bail!("Incorrect CSR format: {csr:?}"),
273 }
274 Ok(())
275}
276
Alice Wange910b902023-09-07 10:35:12 +0000277fn start_service_vm(vm_type: VmType) -> Result<ServiceVm> {
David Brazdil66fc1202022-07-04 21:48:45 +0100278 android_logger::init_once(
279 android_logger::Config::default().with_tag("rialto").with_min_level(log::Level::Debug),
280 );
David Brazdil66fc1202022-07-04 21:48:45 +0100281 // Redirect panic messages to logcat.
282 panic::set_hook(Box::new(|panic_info| {
283 log::error!("{}", panic_info);
284 }));
David Brazdil66fc1202022-07-04 21:48:45 +0100285 // We need to start the thread pool for Binder to work properly, especially link_to_death.
286 ProcessState::start_thread_pool();
Alice Wange910b902023-09-07 10:35:12 +0000287 ServiceVm::start_vm(vm_instance(vm_type)?, vm_type)
Alice Wang17dc76e2023-09-06 09:43:52 +0000288}
289
Alice Wange910b902023-09-07 10:35:12 +0000290fn vm_instance(vm_type: VmType) -> Result<VmInstance> {
Alice Wanga6357692023-09-07 14:59:37 +0000291 match vm_type {
Alice Wang1d9a5872023-09-06 14:32:36 +0000292 VmType::ProtectedVm => {
Alice Wanga6357692023-09-07 14:59:37 +0000293 service_vm_manager::protected_vm_instance(PathBuf::from(INSTANCE_IMG_PATH))
Alice Wang1d9a5872023-09-06 14:32:36 +0000294 }
Alice Wanga6357692023-09-07 14:59:37 +0000295 VmType::NonProtectedVm => nonprotected_vm_instance(),
296 }
297}
298
299fn nonprotected_vm_instance() -> Result<VmInstance> {
300 let rialto = File::open(UNSIGNED_RIALTO_PATH).context("Failed to open Rialto kernel binary")?;
David Brazdil66fc1202022-07-04 21:48:45 +0100301 let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig {
Alice Wanga6357692023-09-07 14:59:37 +0000302 name: String::from("Non protected rialto"),
David Brazdil66fc1202022-07-04 21:48:45 +0100303 bootloader: Some(ParcelFileDescriptor::new(rialto)),
Alice Wanga6357692023-09-07 14:59:37 +0000304 protectedVm: false,
David Brazdil66fc1202022-07-04 21:48:45 +0100305 memoryMib: 300,
David Brazdil66fc1202022-07-04 21:48:45 +0100306 platformVersion: "~1.0".to_string(),
Inseob Kim6ef80972023-07-20 17:23:36 +0900307 ..Default::default()
David Brazdil66fc1202022-07-04 21:48:45 +0100308 });
Alice Wanga6357692023-09-07 14:59:37 +0000309 let console = Some(service_vm_manager::android_log_fd()?);
310 let log = Some(service_vm_manager::android_log_fd()?);
311 let virtmgr = vmclient::VirtualizationService::new().context("Failed to spawn VirtMgr")?;
312 let service = virtmgr.connect().context("Failed to connect to VirtMgr")?;
313 info!("Connected to VirtMgr for service VM");
314 VmInstance::create(service.as_ref(), &config, console, /* consoleIn */ None, log, None)
315 .context("Failed to create VM")
David Brazdil66fc1202022-07-04 21:48:45 +0100316}