Alice Wang | c2fec93 | 2023-02-23 16:24:02 +0000 | [diff] [blame] | 1 | // Copyright 2023, 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 | //! Handles the RKP (Remote Key Provisioning) VM and host communication. |
| 16 | //! The RKP VM will be recognized and attested by the RKP server periodically and |
| 17 | //! serves as a trusted platform to attest a client VM. |
| 18 | |
| 19 | use android_system_virtualizationservice::{ |
| 20 | aidl::android::system::virtualizationservice::{ |
| 21 | CpuTopology::CpuTopology, DiskImage::DiskImage, Partition::Partition, |
| 22 | PartitionType::PartitionType, VirtualMachineConfig::VirtualMachineConfig, |
| 23 | VirtualMachineRawConfig::VirtualMachineRawConfig, |
| 24 | }, |
| 25 | binder::{ParcelFileDescriptor, ProcessState}, |
| 26 | }; |
| 27 | use anyhow::{anyhow, Context, Result}; |
| 28 | use log::info; |
| 29 | use std::fs::File; |
| 30 | use std::time::Duration; |
| 31 | use vmclient::VmInstance; |
| 32 | |
| 33 | const RIALTO_PATH: &str = "/apex/com.android.virt/etc/rialto.bin"; |
| 34 | |
| 35 | pub(crate) fn request_certificate( |
| 36 | csr: &[u8], |
| 37 | instance_img_fd: &ParcelFileDescriptor, |
| 38 | ) -> Result<Vec<u8>> { |
| 39 | // We need to start the thread pool for Binder to work properly, especially link_to_death. |
| 40 | ProcessState::start_thread_pool(); |
| 41 | |
| 42 | let virtmgr = vmclient::VirtualizationService::new().context("Failed to spawn virtmgr")?; |
| 43 | let service = virtmgr.connect().context("virtmgr failed to connect")?; |
| 44 | info!("service_vm: Connected to VirtualizationService"); |
| 45 | // TODO(b/272226230): Either turn rialto into the service VM or use an empty payload here. |
| 46 | // If using an empty payload, the service code will be part of pvmfw. |
| 47 | let rialto = File::open(RIALTO_PATH).context("Failed to open Rialto kernel binary")?; |
| 48 | |
| 49 | // TODO(b/272226230): Initialize the partition from virtualization manager. |
| 50 | const INSTANCE_IMG_SIZE_BYTES: i64 = 1 << 20; // 1MB |
| 51 | service |
| 52 | .initializeWritablePartition( |
| 53 | instance_img_fd, |
| 54 | INSTANCE_IMG_SIZE_BYTES, |
| 55 | PartitionType::ANDROID_VM_INSTANCE, |
| 56 | ) |
| 57 | .context("Failed to initialize instange.img")?; |
| 58 | let instance_img = |
| 59 | instance_img_fd.as_ref().try_clone().context("Failed to clone instance.img")?; |
| 60 | let instance_img = ParcelFileDescriptor::new(instance_img); |
| 61 | let writable_partitions = vec![Partition { |
| 62 | label: "vm-instance".to_owned(), |
| 63 | image: Some(instance_img), |
| 64 | writable: true, |
| 65 | }]; |
| 66 | info!("service_vm: Finished initializing instance.img..."); |
| 67 | |
| 68 | let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig { |
| 69 | name: String::from("Service VM"), |
| 70 | kernel: None, |
| 71 | initrd: None, |
| 72 | params: None, |
| 73 | bootloader: Some(ParcelFileDescriptor::new(rialto)), |
| 74 | disks: vec![DiskImage { image: None, partitions: writable_partitions, writable: true }], |
| 75 | protectedVm: true, |
| 76 | memoryMib: 300, |
| 77 | cpuTopology: CpuTopology::ONE_CPU, |
| 78 | platformVersion: "~1.0".to_string(), |
| 79 | taskProfiles: vec![], |
| 80 | gdbPort: 0, // No gdb |
| 81 | }); |
Jiyong Park | e6fb167 | 2023-06-26 16:45:55 +0900 | [diff] [blame] | 82 | let vm = VmInstance::create(service.as_ref(), &config, None, None, None, None) |
Alice Wang | c2fec93 | 2023-02-23 16:24:02 +0000 | [diff] [blame] | 83 | .context("Failed to create service VM")?; |
| 84 | |
| 85 | info!("service_vm: Starting Service VM..."); |
| 86 | vm.start().context("Failed to start service VM")?; |
| 87 | |
| 88 | // TODO(b/274441673): The host can send the CSR to the RKP VM for attestation. |
| 89 | // Wait for VM to finish. |
| 90 | vm.wait_for_death_with_timeout(Duration::from_secs(10)) |
| 91 | .ok_or_else(|| anyhow!("Timed out waiting for VM exit"))?; |
| 92 | |
| 93 | info!("service_vm: Finished getting the certificate"); |
| 94 | Ok([b"Return: ", csr].concat()) |
| 95 | } |