David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 1 | // 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 | |
| 17 | use android_system_virtualizationservice::{ |
| 18 | aidl::android::system::virtualizationservice::{ |
Alice Wang | a635769 | 2023-09-07 14:59:37 +0000 | [diff] [blame] | 19 | VirtualMachineConfig::VirtualMachineConfig, |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 20 | VirtualMachineRawConfig::VirtualMachineRawConfig, |
| 21 | }, |
| 22 | binder::{ParcelFileDescriptor, ProcessState}, |
| 23 | }; |
Alice Wang | 9646fb3 | 2023-09-08 10:01:31 +0000 | [diff] [blame] | 24 | use anyhow::{bail, Context, Result}; |
Alice Wang | b76b66f | 2024-03-26 08:16:23 +0000 | [diff] [blame] | 25 | use bssl_avf::{rand_bytes, sha256, EcKey, PKey}; |
Alice Wang | de6bee5 | 2023-11-10 09:58:40 +0000 | [diff] [blame] | 26 | use client_vm_csr::generate_attestation_key_and_csr; |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 27 | use coset::{CborSerializable, CoseMac0, CoseSign}; |
Alice Wang | 7eddbf4 | 2024-10-16 09:50:54 +0000 | [diff] [blame] | 28 | use hwtrust::{ |
| 29 | rkp, |
| 30 | session::{RkpInstance, Session}, |
| 31 | }; |
Nikita Ioffe | bd2e2e4 | 2024-07-05 15:04:49 +0000 | [diff] [blame] | 32 | use log::{info, warn}; |
Alice Wang | 9646fb3 | 2023-09-08 10:01:31 +0000 | [diff] [blame] | 33 | use service_vm_comm::{ |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 34 | ClientVmAttestationParams, Csr, CsrPayload, EcdsaP256KeyPair, GenerateCertificateRequestParams, |
Alice Wang | d3a9640 | 2023-11-24 15:37:39 +0000 | [diff] [blame] | 35 | Request, RequestProcessingError, Response, VmType, |
Alice Wang | 9646fb3 | 2023-09-08 10:01:31 +0000 | [diff] [blame] | 36 | }; |
Alice Wang | 1cc1350 | 2023-12-05 11:05:34 +0000 | [diff] [blame] | 37 | use service_vm_fake_chain::client_vm::{ |
| 38 | fake_client_vm_dice_artifacts, fake_sub_components, SubComponent, |
| 39 | }; |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 40 | use service_vm_manager::{ServiceVm, VM_MEMORY_MB}; |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 41 | use std::fs; |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 42 | use std::fs::File; |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 43 | use std::panic; |
Alice Wang | 17dc76e | 2023-09-06 09:43:52 +0000 | [diff] [blame] | 44 | use std::path::PathBuf; |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 45 | use std::str::FromStr; |
Alice Wang | 17dc76e | 2023-09-06 09:43:52 +0000 | [diff] [blame] | 46 | use vmclient::VmInstance; |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 47 | use x509_cert::{ |
| 48 | certificate::{Certificate, Version}, |
| 49 | der::{self, asn1, Decode, Encode}, |
| 50 | name::Name, |
| 51 | spki::{AlgorithmIdentifier, ObjectIdentifier, SubjectPublicKeyInfo}, |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 52 | }; |
Alice Wang | 4e082c3 | 2023-07-11 07:41:50 +0000 | [diff] [blame] | 53 | |
Alice Wang | 9a8b39f | 2023-04-12 15:31:48 +0000 | [diff] [blame] | 54 | const UNSIGNED_RIALTO_PATH: &str = "/data/local/tmp/rialto_test/arm64/rialto_unsigned.bin"; |
| 55 | const INSTANCE_IMG_PATH: &str = "/data/local/tmp/rialto_test/arm64/instance.img"; |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 56 | const TEST_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der"; |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 57 | |
Alice Wang | 0472f46 | 2024-02-06 08:53:19 +0000 | [diff] [blame] | 58 | #[cfg(dice_changes)] |
Alice Wang | 9a8b39f | 2023-04-12 15:31:48 +0000 | [diff] [blame] | 59 | #[test] |
Alice Wang | e910b90 | 2023-09-07 10:35:12 +0000 | [diff] [blame] | 60 | fn process_requests_in_protected_vm() -> Result<()> { |
Nikita Ioffe | bd2e2e4 | 2024-07-05 15:04:49 +0000 | [diff] [blame] | 61 | if hypervisor_props::is_protected_vm_supported()? { |
| 62 | // The test is skipped if the feature flag |dice_changes| is not enabled, because when |
| 63 | // the flag is off, the DICE chain is truncated in the pvmfw, and the service VM cannot |
| 64 | // verify the chain due to the missing entries in the chain. |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 65 | check_processing_requests(VmType::ProtectedVm, None) |
Nikita Ioffe | bd2e2e4 | 2024-07-05 15:04:49 +0000 | [diff] [blame] | 66 | } else { |
| 67 | warn!("pVMs are not supported on device, skipping test"); |
| 68 | Ok(()) |
| 69 | } |
Alice Wang | 9a8b39f | 2023-04-12 15:31:48 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Alice Wang | e910b90 | 2023-09-07 10:35:12 +0000 | [diff] [blame] | 72 | #[test] |
| 73 | fn process_requests_in_non_protected_vm() -> Result<()> { |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 74 | const MEMORY_MB: i32 = 300; |
Pierre-Clément Tosi | d60a1d1 | 2024-08-28 20:04:24 +0100 | [diff] [blame] | 75 | check_processing_requests(VmType::NonProtectedVm, Some(MEMORY_MB))?; |
| 76 | check_processing_requests(VmType::NonProtectedVm, None) |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 77 | } |
| 78 | |
| 79 | fn check_processing_requests(vm_type: VmType, vm_memory_mb: Option<i32>) -> Result<()> { |
| 80 | let mut vm = start_service_vm(vm_type, vm_memory_mb)?; |
Alice Wang | e910b90 | 2023-09-07 10:35:12 +0000 | [diff] [blame] | 81 | |
| 82 | check_processing_reverse_request(&mut vm)?; |
Alice Wang | 74eb78b | 2023-11-09 16:13:10 +0000 | [diff] [blame] | 83 | let key_pair = check_processing_generating_key_pair_request(&mut vm)?; |
Karuna Wadhera | c8fb3bf | 2024-07-01 12:54:25 +0000 | [diff] [blame] | 84 | check_processing_generating_certificate_request(&mut vm, &key_pair.maced_public_key)?; |
Alice Wang | d3a9640 | 2023-11-24 15:37:39 +0000 | [diff] [blame] | 85 | check_attestation_request(&mut vm, &key_pair, vm_type)?; |
Alice Wang | e910b90 | 2023-09-07 10:35:12 +0000 | [diff] [blame] | 86 | Ok(()) |
| 87 | } |
| 88 | |
| 89 | fn check_processing_reverse_request(vm: &mut ServiceVm) -> Result<()> { |
Alice Wang | 0486e25 | 2023-10-06 14:30:49 +0000 | [diff] [blame] | 90 | let message = "abc".repeat(500); |
Alice Wang | e910b90 | 2023-09-07 10:35:12 +0000 | [diff] [blame] | 91 | let request = Request::Reverse(message.as_bytes().to_vec()); |
| 92 | |
Alice Wang | fbdc85b | 2023-09-07 12:56:46 +0000 | [diff] [blame] | 93 | let response = vm.process_request(request)?; |
| 94 | info!("Received response: {response:?}."); |
Alice Wang | e910b90 | 2023-09-07 10:35:12 +0000 | [diff] [blame] | 95 | |
| 96 | let expected_response: Vec<u8> = message.as_bytes().iter().rev().cloned().collect(); |
| 97 | assert_eq!(Response::Reverse(expected_response), response); |
| 98 | Ok(()) |
| 99 | } |
| 100 | |
Alice Wang | 74eb78b | 2023-11-09 16:13:10 +0000 | [diff] [blame] | 101 | fn check_processing_generating_key_pair_request(vm: &mut ServiceVm) -> Result<EcdsaP256KeyPair> { |
Alice Wang | 9646fb3 | 2023-09-08 10:01:31 +0000 | [diff] [blame] | 102 | let request = Request::GenerateEcdsaP256KeyPair; |
| 103 | |
| 104 | let response = vm.process_request(request)?; |
| 105 | info!("Received response: {response:?}."); |
| 106 | |
| 107 | match response { |
Alice Wang | 74eb78b | 2023-11-09 16:13:10 +0000 | [diff] [blame] | 108 | Response::GenerateEcdsaP256KeyPair(key_pair) => { |
| 109 | assert_array_has_nonzero(&key_pair.maced_public_key); |
| 110 | assert_array_has_nonzero(&key_pair.key_blob); |
| 111 | Ok(key_pair) |
Alice Wang | a78d3f0 | 2023-09-13 12:39:16 +0000 | [diff] [blame] | 112 | } |
Alice Wang | ff5592d | 2023-09-13 15:27:39 +0000 | [diff] [blame] | 113 | _ => bail!("Incorrect response type: {response:?}"), |
Alice Wang | 9646fb3 | 2023-09-08 10:01:31 +0000 | [diff] [blame] | 114 | } |
| 115 | } |
| 116 | |
Alice Wang | a78d3f0 | 2023-09-13 12:39:16 +0000 | [diff] [blame] | 117 | fn assert_array_has_nonzero(v: &[u8]) { |
| 118 | assert!(v.iter().any(|&x| x != 0)) |
| 119 | } |
| 120 | |
Alice Wang | ff5592d | 2023-09-13 15:27:39 +0000 | [diff] [blame] | 121 | fn check_processing_generating_certificate_request( |
| 122 | vm: &mut ServiceVm, |
Alice Wang | 74eb78b | 2023-11-09 16:13:10 +0000 | [diff] [blame] | 123 | maced_public_key: &[u8], |
Alice Wang | ff5592d | 2023-09-13 15:27:39 +0000 | [diff] [blame] | 124 | ) -> Result<()> { |
| 125 | let params = GenerateCertificateRequestParams { |
Alice Wang | 74eb78b | 2023-11-09 16:13:10 +0000 | [diff] [blame] | 126 | keys_to_sign: vec![maced_public_key.to_vec()], |
Alice Wang | ff5592d | 2023-09-13 15:27:39 +0000 | [diff] [blame] | 127 | challenge: vec![], |
| 128 | }; |
Alice Wang | 9646fb3 | 2023-09-08 10:01:31 +0000 | [diff] [blame] | 129 | let request = Request::GenerateCertificateRequest(params); |
| 130 | |
| 131 | let response = vm.process_request(request)?; |
| 132 | info!("Received response: {response:?}."); |
| 133 | |
| 134 | match response { |
Karuna Wadhera | c8fb3bf | 2024-07-01 12:54:25 +0000 | [diff] [blame] | 135 | Response::GenerateCertificateRequest(csr) => check_csr(csr), |
Alice Wang | ff5592d | 2023-09-13 15:27:39 +0000 | [diff] [blame] | 136 | _ => bail!("Incorrect response type: {response:?}"), |
Alice Wang | 9646fb3 | 2023-09-08 10:01:31 +0000 | [diff] [blame] | 137 | } |
| 138 | } |
| 139 | |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 140 | fn check_attestation_request( |
| 141 | vm: &mut ServiceVm, |
| 142 | remotely_provisioned_key_pair: &EcdsaP256KeyPair, |
Alice Wang | d3a9640 | 2023-11-24 15:37:39 +0000 | [diff] [blame] | 143 | vm_type: VmType, |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 144 | ) -> Result<()> { |
Alice Wang | de6bee5 | 2023-11-10 09:58:40 +0000 | [diff] [blame] | 145 | /// The following data was generated randomly with urandom. |
| 146 | const CHALLENGE: [u8; 16] = [ |
| 147 | 0x7d, 0x86, 0x58, 0x79, 0x3a, 0x09, 0xdf, 0x1c, 0xa5, 0x80, 0x80, 0x15, 0x2b, 0x13, 0x17, |
| 148 | 0x5c, |
| 149 | ]; |
Alice Wang | 4ac9c8b | 2023-12-05 16:23:14 +0000 | [diff] [blame] | 150 | let dice_artifacts = fake_client_vm_dice_artifacts()?; |
Alice Wang | de6bee5 | 2023-11-10 09:58:40 +0000 | [diff] [blame] | 151 | let attestation_data = generate_attestation_key_and_csr(&CHALLENGE, &dice_artifacts)?; |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 152 | let cert_chain = fs::read(TEST_CERT_CHAIN_PATH)?; |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 153 | // The certificate chain contains several certificates, but we only need the first one. |
| 154 | // Parsing the data with trailing data always fails with a `TrailingData` error. |
| 155 | let cert_len: usize = match Certificate::from_der(&cert_chain).unwrap_err().kind() { |
| 156 | der::ErrorKind::TrailingData { decoded, .. } => decoded.try_into().unwrap(), |
| 157 | e => bail!("Unexpected error: {e}"), |
| 158 | }; |
Alice Wang | de6bee5 | 2023-11-10 09:58:40 +0000 | [diff] [blame] | 159 | |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 160 | // Builds the mock parameters for the client VM attestation. |
| 161 | // The `csr` and `remotely_provisioned_key_blob` parameters are extracted from the same |
| 162 | // libraries as in production. |
| 163 | // The `remotely_provisioned_cert` parameter is an RKP certificate extracted from a test |
| 164 | // certificate chain retrieved from RKPD. |
Alice Wang | de6bee5 | 2023-11-10 09:58:40 +0000 | [diff] [blame] | 165 | let params = ClientVmAttestationParams { |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 166 | csr: attestation_data.csr.clone().into_cbor_vec()?, |
| 167 | remotely_provisioned_key_blob: remotely_provisioned_key_pair.key_blob.to_vec(), |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 168 | remotely_provisioned_cert: cert_chain[..cert_len].to_vec(), |
Alice Wang | de6bee5 | 2023-11-10 09:58:40 +0000 | [diff] [blame] | 169 | }; |
Alice Wang | 74eb78b | 2023-11-09 16:13:10 +0000 | [diff] [blame] | 170 | let request = Request::RequestClientVmAttestation(params); |
| 171 | |
| 172 | let response = vm.process_request(request)?; |
| 173 | info!("Received response: {response:?}."); |
| 174 | |
| 175 | match response { |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 176 | Response::RequestClientVmAttestation(certificate) => { |
Alice Wang | d3a9640 | 2023-11-24 15:37:39 +0000 | [diff] [blame] | 177 | // The end-to-end test for non-protected VM attestation works because both the service |
| 178 | // VM and the client VM use the same fake DICE chain. |
| 179 | assert_eq!(vm_type, VmType::NonProtectedVm); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 180 | check_certificate_for_client_vm( |
| 181 | &certificate, |
| 182 | &remotely_provisioned_key_pair.maced_public_key, |
| 183 | &attestation_data.csr, |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 184 | &Certificate::from_der(&cert_chain[..cert_len]).unwrap(), |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 185 | )?; |
| 186 | Ok(()) |
| 187 | } |
Alice Wang | d3a9640 | 2023-11-24 15:37:39 +0000 | [diff] [blame] | 188 | Response::Err(RequestProcessingError::InvalidDiceChain) => { |
| 189 | // The end-to-end test for protected VM attestation doesn't work because the service VM |
| 190 | // compares the fake DICE chain in the CSR with the real DICE chain. |
| 191 | // We cannot generate a valid DICE chain with the same payloads up to pvmfw. |
| 192 | assert_eq!(vm_type, VmType::ProtectedVm); |
| 193 | Ok(()) |
| 194 | } |
Alice Wang | 74eb78b | 2023-11-09 16:13:10 +0000 | [diff] [blame] | 195 | _ => bail!("Incorrect response type: {response:?}"), |
| 196 | } |
| 197 | } |
| 198 | |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 199 | fn check_vm_components(vm_components: &asn1::SequenceOf<asn1::Any, 4>) -> Result<()> { |
Alice Wang | 1cc1350 | 2023-12-05 11:05:34 +0000 | [diff] [blame] | 200 | let expected_components = fake_sub_components(); |
| 201 | assert_eq!(expected_components.len(), vm_components.len()); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 202 | for (i, expected_component) in expected_components.iter().enumerate() { |
| 203 | check_vm_component(vm_components.get(i).unwrap(), expected_component)?; |
Alice Wang | 1cc1350 | 2023-12-05 11:05:34 +0000 | [diff] [blame] | 204 | } |
| 205 | Ok(()) |
| 206 | } |
| 207 | |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 208 | fn check_vm_component(vm_component: &asn1::Any, expected_component: &SubComponent) -> Result<()> { |
| 209 | let vm_component = vm_component.decode_as::<asn1::SequenceOf<asn1::Any, 4>>().unwrap(); |
Alice Wang | 1cc1350 | 2023-12-05 11:05:34 +0000 | [diff] [blame] | 210 | assert_eq!(4, vm_component.len()); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 211 | let name = vm_component.get(0).unwrap().decode_as::<asn1::Utf8StringRef>().unwrap(); |
Alice Wang | 7eddbf4 | 2024-10-16 09:50:54 +0000 | [diff] [blame] | 212 | let name_str: &str = name.as_ref(); |
| 213 | assert_eq!(expected_component.name, name_str); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 214 | let version = vm_component.get(1).unwrap().decode_as::<u64>().unwrap(); |
| 215 | assert_eq!(expected_component.version, version); |
| 216 | let code_hash = vm_component.get(2).unwrap().decode_as::<asn1::OctetString>().unwrap(); |
| 217 | assert_eq!(expected_component.code_hash, code_hash.as_bytes()); |
| 218 | let authority_hash = vm_component.get(3).unwrap().decode_as::<asn1::OctetString>().unwrap(); |
| 219 | assert_eq!(expected_component.authority_hash, authority_hash.as_bytes()); |
Alice Wang | 1cc1350 | 2023-12-05 11:05:34 +0000 | [diff] [blame] | 220 | Ok(()) |
| 221 | } |
| 222 | |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 223 | fn check_certificate_for_client_vm( |
| 224 | certificate: &[u8], |
| 225 | maced_public_key: &[u8], |
| 226 | csr: &Csr, |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 227 | parent_certificate: &Certificate, |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 228 | ) -> Result<()> { |
| 229 | let cose_mac = CoseMac0::from_slice(maced_public_key)?; |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame] | 230 | let authority_public_key = |
| 231 | EcKey::from_cose_public_key_slice(&cose_mac.payload.unwrap()).unwrap(); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 232 | let cert = Certificate::from_der(certificate).unwrap(); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 233 | |
| 234 | // Checks the certificate signature against the authority public key. |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 235 | const ECDSA_WITH_SHA_256: ObjectIdentifier = |
| 236 | ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.2"); |
| 237 | let expected_algorithm = AlgorithmIdentifier { oid: ECDSA_WITH_SHA_256, parameters: None }; |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 238 | assert_eq!(expected_algorithm, cert.signature_algorithm); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 239 | let tbs_cert = cert.tbs_certificate; |
| 240 | let digest = sha256(&tbs_cert.to_der().unwrap()).unwrap(); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 241 | authority_public_key |
Alan Stokes | b2f52fb | 2024-05-09 10:12:55 +0100 | [diff] [blame] | 242 | .ecdsa_verify_der(cert.signature.raw_bytes(), &digest) |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 243 | .expect("Failed to verify the certificate signature with the authority public key"); |
| 244 | |
| 245 | // Checks that the certificate's subject public key is equal to the key in the CSR. |
| 246 | let cose_sign = CoseSign::from_slice(&csr.signed_csr_payload)?; |
| 247 | let csr_payload = |
| 248 | cose_sign.payload.as_ref().and_then(|v| CsrPayload::from_cbor_slice(v).ok()).unwrap(); |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame] | 249 | let subject_public_key = EcKey::from_cose_public_key_slice(&csr_payload.public_key).unwrap(); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 250 | let expected_spki_data = |
Alice Wang | eb77f7d | 2023-12-01 09:13:58 +0000 | [diff] [blame] | 251 | PKey::try_from(subject_public_key).unwrap().subject_public_key_info().unwrap(); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 252 | let expected_spki = SubjectPublicKeyInfo::from_der(&expected_spki_data).unwrap(); |
| 253 | assert_eq!(expected_spki, tbs_cert.subject_public_key_info); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 254 | |
| 255 | // Checks the certificate extension. |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 256 | const ATTESTATION_EXTENSION_OID: ObjectIdentifier = |
| 257 | ObjectIdentifier::new_unwrap("1.3.6.1.4.1.11129.2.1.29.1"); |
| 258 | let extensions = tbs_cert.extensions.unwrap(); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 259 | assert_eq!(1, extensions.len()); |
| 260 | let extension = &extensions[0]; |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 261 | assert_eq!(ATTESTATION_EXTENSION_OID, extension.extn_id); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 262 | assert!(!extension.critical); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 263 | let attestation_ext = |
| 264 | asn1::SequenceOf::<asn1::Any, 3>::from_der(extension.extn_value.as_bytes()).unwrap(); |
Alice Wang | 1cc1350 | 2023-12-05 11:05:34 +0000 | [diff] [blame] | 265 | assert_eq!(3, attestation_ext.len()); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 266 | let challenge = attestation_ext.get(0).unwrap().decode_as::<asn1::OctetString>().unwrap(); |
| 267 | assert_eq!(csr_payload.challenge, challenge.as_bytes()); |
| 268 | let is_vm_secure = attestation_ext.get(1).unwrap().decode_as::<bool>().unwrap(); |
Alice Wang | d3a9640 | 2023-11-24 15:37:39 +0000 | [diff] [blame] | 269 | assert!( |
| 270 | !is_vm_secure, |
| 271 | "The VM shouldn't be secure as the last payload added in the test is in Debug mode" |
| 272 | ); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 273 | let vm_components = |
| 274 | attestation_ext.get(2).unwrap().decode_as::<asn1::SequenceOf<asn1::Any, 4>>().unwrap(); |
| 275 | check_vm_components(&vm_components)?; |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 276 | |
| 277 | // Checks other fields on the certificate |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 278 | assert_eq!(Version::V3, tbs_cert.version); |
| 279 | assert_eq!(parent_certificate.tbs_certificate.validity, tbs_cert.validity); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 280 | assert_eq!( |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 281 | Name::from_str("CN=Android Protected Virtual Machine Key").unwrap(), |
| 282 | tbs_cert.subject |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 283 | ); |
Alice Wang | 6a504ef | 2023-12-21 15:37:55 +0000 | [diff] [blame] | 284 | assert_eq!(parent_certificate.tbs_certificate.subject, tbs_cert.issuer); |
Alice Wang | 20b8ebc | 2023-11-17 09:54:47 +0000 | [diff] [blame] | 285 | |
| 286 | Ok(()) |
| 287 | } |
| 288 | |
Karuna Wadhera | c8fb3bf | 2024-07-01 12:54:25 +0000 | [diff] [blame] | 289 | fn check_csr(csr: Vec<u8>) -> Result<()> { |
Karuna Wadhera | d0792e8 | 2024-07-08 17:22:04 +0000 | [diff] [blame] | 290 | let mut session = Session::default(); |
| 291 | session.set_allow_any_mode(true); |
Alice Wang | 7eddbf4 | 2024-10-16 09:50:54 +0000 | [diff] [blame] | 292 | session.set_rkp_instance(RkpInstance::Avf); |
Karuna Wadhera | d0792e8 | 2024-07-08 17:22:04 +0000 | [diff] [blame] | 293 | let _csr = rkp::Csr::from_cbor(&session, &csr[..]).context("Failed to parse CSR")?; |
Alice Wang | f7c0f94 | 2023-09-14 09:33:04 +0000 | [diff] [blame] | 294 | Ok(()) |
| 295 | } |
| 296 | |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 297 | fn start_service_vm(vm_type: VmType, vm_memory_mb: Option<i32>) -> Result<ServiceVm> { |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 298 | android_logger::init_once( |
Jeff Vander Stoep | d9dda0c | 2024-02-07 14:27:06 +0100 | [diff] [blame] | 299 | android_logger::Config::default() |
| 300 | .with_tag("rialto") |
| 301 | .with_max_level(log::LevelFilter::Debug), |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 302 | ); |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 303 | // Redirect panic messages to logcat. |
| 304 | panic::set_hook(Box::new(|panic_info| { |
| 305 | log::error!("{}", panic_info); |
| 306 | })); |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 307 | // We need to start the thread pool for Binder to work properly, especially link_to_death. |
| 308 | ProcessState::start_thread_pool(); |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 309 | ServiceVm::start_vm(vm_instance(vm_type, vm_memory_mb)?, vm_type) |
Alice Wang | 17dc76e | 2023-09-06 09:43:52 +0000 | [diff] [blame] | 310 | } |
| 311 | |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 312 | fn vm_instance(vm_type: VmType, vm_memory_mb: Option<i32>) -> Result<VmInstance> { |
Alice Wang | a635769 | 2023-09-07 14:59:37 +0000 | [diff] [blame] | 313 | match vm_type { |
Alice Wang | 1d9a587 | 2023-09-06 14:32:36 +0000 | [diff] [blame] | 314 | VmType::ProtectedVm => { |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 315 | assert!(vm_memory_mb.is_none()); |
Alice Wang | a635769 | 2023-09-07 14:59:37 +0000 | [diff] [blame] | 316 | service_vm_manager::protected_vm_instance(PathBuf::from(INSTANCE_IMG_PATH)) |
Alice Wang | 1d9a587 | 2023-09-06 14:32:36 +0000 | [diff] [blame] | 317 | } |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 318 | VmType::NonProtectedVm => nonprotected_vm_instance(vm_memory_mb.unwrap_or(VM_MEMORY_MB)), |
Alice Wang | a635769 | 2023-09-07 14:59:37 +0000 | [diff] [blame] | 319 | } |
| 320 | } |
| 321 | |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 322 | fn nonprotected_vm_instance(memory_mib: i32) -> Result<VmInstance> { |
Alice Wang | a635769 | 2023-09-07 14:59:37 +0000 | [diff] [blame] | 323 | let rialto = File::open(UNSIGNED_RIALTO_PATH).context("Failed to open Rialto kernel binary")?; |
Alice Wang | b76b66f | 2024-03-26 08:16:23 +0000 | [diff] [blame] | 324 | // Do not use `#allocateInstanceId` to generate the instance ID because the method |
| 325 | // also adds an instance ID to the database it manages. |
| 326 | // This is not necessary for this test. |
| 327 | let mut instance_id = [0u8; 64]; |
| 328 | rand_bytes(&mut instance_id).unwrap(); |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 329 | let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig { |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 330 | name: format!("Non protected rialto ({memory_mib}MiB)"), |
Frederick Mayle | 7584240 | 2024-08-05 19:32:08 -0700 | [diff] [blame] | 331 | kernel: Some(ParcelFileDescriptor::new(rialto)), |
Alice Wang | a635769 | 2023-09-07 14:59:37 +0000 | [diff] [blame] | 332 | protectedVm: false, |
Pierre-Clément Tosi | 311de8e | 2024-08-14 10:10:49 +0100 | [diff] [blame] | 333 | memoryMib: memory_mib, |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 334 | platformVersion: "~1.0".to_string(), |
Alice Wang | b76b66f | 2024-03-26 08:16:23 +0000 | [diff] [blame] | 335 | instanceId: instance_id, |
Inseob Kim | 6ef8097 | 2023-07-20 17:23:36 +0900 | [diff] [blame] | 336 | ..Default::default() |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 337 | }); |
Alice Wang | a635769 | 2023-09-07 14:59:37 +0000 | [diff] [blame] | 338 | let console = Some(service_vm_manager::android_log_fd()?); |
| 339 | let log = Some(service_vm_manager::android_log_fd()?); |
| 340 | let virtmgr = vmclient::VirtualizationService::new().context("Failed to spawn VirtMgr")?; |
| 341 | let service = virtmgr.connect().context("Failed to connect to VirtMgr")?; |
| 342 | info!("Connected to VirtMgr for service VM"); |
Elie Kheirallah | 5c807a2 | 2024-09-23 20:40:42 +0000 | [diff] [blame] | 343 | VmInstance::create( |
| 344 | service.as_ref(), |
| 345 | &config, |
| 346 | console, |
| 347 | /* consoleIn */ None, |
| 348 | log, |
| 349 | /* dump_dt */ None, |
| 350 | None, |
| 351 | ) |
| 352 | .context("Failed to create VM") |
David Brazdil | 66fc120 | 2022-07-04 21:48:45 +0100 | [diff] [blame] | 353 | } |