blob: ebfb667b46410026a97ebd973ced9e6c178cb5c5 [file] [log] [blame]
Alice Wangc2fec932023-02-23 16:24:02 +00001// 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
19use 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};
27use anyhow::{anyhow, Context, Result};
28use log::info;
29use std::fs::File;
30use std::time::Duration;
31use vmclient::VmInstance;
32
33const RIALTO_PATH: &str = "/apex/com.android.virt/etc/rialto.bin";
34
35pub(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 Parke6fb1672023-06-26 16:45:55 +090082 let vm = VmInstance::create(service.as_ref(), &config, None, None, None, None)
Alice Wangc2fec932023-02-23 16:24:02 +000083 .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}