Add CompOsKeyService to ICompOsService

ICompOsService is renamed from ICompService in this change. The
implementation starts to include a CompOsKeyService, but it has not
started to use it.

Bug: 194717985
Bug: 161471326
Test: ComposHostTestCases
Change-Id: Ifddd1109f387e061989dba7292b629c04b07fa34
diff --git a/compos/Android.bp b/compos/Android.bp
index 7f4f55c..a626103 100644
--- a/compos/Android.bp
+++ b/compos/Android.bp
@@ -30,6 +30,8 @@
     name: "compsvc",
     srcs: ["src/compsvc_main.rs"],
     rustlibs: [
+        "android.hardware.security.keymint-V1-rust",
+        "android.system.keystore2-V1-rust",
         "authfs_aidl_interface-rust",
         "compos_aidl_interface-rust",
         "libandroid_logger",
@@ -39,6 +41,8 @@
         "libclap",
         "liblog_rust",
         "libminijail_rust",
+        "libring",
+        "libscopeguard",
     ],
     prefer_rlib: true,
     shared_libs: [
diff --git a/compos/aidl/com/android/compos/ICompOsKeyService.aidl b/compos/aidl/com/android/compos/ICompOsKeyService.aidl
index eb2caa7..7e0fe25 100644
--- a/compos/aidl/com/android/compos/ICompOsKeyService.aidl
+++ b/compos/aidl/com/android/compos/ICompOsKeyService.aidl
@@ -17,7 +17,7 @@
 package com.android.compos;
 
 import com.android.compos.CompOsKeyData;
-import com.android.compos.ICompService;
+import com.android.compos.ICompOsService;
 
 /** {@hide} */
 interface ICompOsKeyService {
@@ -51,11 +51,11 @@
     byte[] sign(in byte[] keyBlob, in byte[] data);
 
     /**
-     * Return an instance of ICompService that will sign output files with a given encrypted
+     * Return an instance of ICompOsService that will sign output files with a given encrypted
      * private key.
      *
      * @param keyBlob The encrypted blob containing the private key, as returned by
      *                generateSigningKey().
      */
-    ICompService getCompService(in byte[] keyBlob);
+    ICompOsService getCompOsService(in byte[] keyBlob);
 }
diff --git a/compos/aidl/com/android/compos/ICompService.aidl b/compos/aidl/com/android/compos/ICompOsService.aidl
similarity index 97%
rename from compos/aidl/com/android/compos/ICompService.aidl
rename to compos/aidl/com/android/compos/ICompOsService.aidl
index 0e18442..c9cd9ae 100644
--- a/compos/aidl/com/android/compos/ICompService.aidl
+++ b/compos/aidl/com/android/compos/ICompOsService.aidl
@@ -19,7 +19,7 @@
 import com.android.compos.Metadata;
 
 /** {@hide} */
-interface ICompService {
+interface ICompOsService {
     /**
      * Execute a command composed of the args, in a context that may be specified in the Metadata,
      * e.g. with file descriptors pre-opened. The service is responsible to decide what executables
diff --git a/compos/src/compos_key_service.rs b/compos/src/compos_key_service.rs
index 35c04d7..dd28faa 100644
--- a/compos/src/compos_key_service.rs
+++ b/compos/src/compos_key_service.rs
@@ -31,7 +31,7 @@
 use compos_aidl_interface::aidl::com::android::compos::{
     CompOsKeyData::CompOsKeyData,
     ICompOsKeyService::{BnCompOsKeyService, ICompOsKeyService},
-    ICompService::ICompService,
+    ICompOsService::ICompOsService,
 };
 use compos_aidl_interface::binder::{
     self, wait_for_interface, BinderFeatures, ExceptionCode, Interface, Status, Strong,
@@ -54,18 +54,9 @@
 
 /// Constructs a binder object that implements ICompOsKeyService. namespace is the Keystore2 namespace to
 /// use for the keys.
+#[allow(dead_code)] // for compsvc
 pub fn new(namespace: KeystoreNamespace) -> Result<Strong<dyn ICompOsKeyService>> {
-    let keystore_service = wait_for_interface::<dyn IKeystoreService>(KEYSTORE_SERVICE_NAME)
-        .context("No Keystore service")?;
-
-    let service = CompOsKeyService {
-        namespace,
-        random: SystemRandom::new(),
-        security_level: keystore_service
-            .getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT)
-            .context("Getting SecurityLevel failed")?,
-    };
-
+    let service = CompOsKeyService::new(namespace)?;
     Ok(BnCompOsKeyService::new_binder(service, BinderFeatures::default()))
 }
 
@@ -90,8 +81,9 @@
 const BLOB_KEY_DESCRIPTOR: KeyDescriptor =
     KeyDescriptor { domain: Domain::BLOB, nspace: 0, alias: None, blob: None };
 
+/// An internal service for CompOS key management.
 #[derive(Clone)]
-struct CompOsKeyService {
+pub struct CompOsKeyService {
     namespace: KeystoreNamespace,
     random: SystemRandom,
     security_level: Strong<dyn IKeystoreSecurityLevel>,
@@ -119,10 +111,12 @@
             .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
     }
 
-    fn getCompService(&self, key_blob: &[u8]) -> binder::Result<Strong<dyn ICompService>> {
+    fn getCompOsService(&self, key_blob: &[u8]) -> binder::Result<Strong<dyn ICompOsService>> {
         let signer =
             Box::new(CompOsSigner { key_blob: key_blob.to_owned(), key_service: self.clone() });
-        Ok(compsvc::new_binder(Some(signer)))
+        let rpc_binder = true; // don't care
+        compsvc::new_binder(rpc_binder, Some(signer))
+            .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
     }
 }
 
@@ -143,6 +137,19 @@
 }
 
 impl CompOsKeyService {
+    pub fn new(namespace: KeystoreNamespace) -> Result<Self> {
+        let keystore_service = wait_for_interface::<dyn IKeystoreService>(KEYSTORE_SERVICE_NAME)
+            .context("No Keystore service")?;
+
+        Ok(CompOsKeyService {
+            namespace,
+            random: SystemRandom::new(),
+            security_level: keystore_service
+                .getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT)
+                .context("Getting SecurityLevel failed")?,
+        })
+    }
+
     fn do_generate(&self) -> Result<CompOsKeyData> {
         let key_descriptor = KeyDescriptor { nspace: self.namespace as i64, ..BLOB_KEY_DESCRIPTOR };
         let key_parameters =
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index f22c785..b69b053 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -18,38 +18,49 @@
 //! file descriptors backed by authfs (via authfs_service) and pass the file descriptors to the
 //! actual compiler.
 
+use anyhow::Result;
+use std::ffi::CString;
 use std::path::PathBuf;
 
 use crate::compilation::compile;
+use crate::compos_key_service::{CompOsKeyService, KeystoreNamespace};
 use crate::signer::Signer;
 use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
-use compos_aidl_interface::aidl::com::android::compos::ICompService::{
-    BnCompService, ICompService,
+use compos_aidl_interface::aidl::com::android::compos::ICompOsService::{
+    BnCompOsService, ICompOsService,
 };
 use compos_aidl_interface::aidl::com::android::compos::Metadata::Metadata;
 use compos_aidl_interface::binder::{
     BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, Strong,
 };
-use std::ffi::CString;
 
 const AUTHFS_SERVICE_NAME: &str = "authfs_service";
 const DEX2OAT_PATH: &str = "/apex/com.android.art/bin/dex2oat64";
 
-/// Constructs a binder object that implements ICompService.
-pub fn new_binder(signer: Option<Box<dyn Signer>>) -> Strong<dyn ICompService> {
-    let service = CompService { dex2oat_path: PathBuf::from(DEX2OAT_PATH), signer };
-    BnCompService::new_binder(service, BinderFeatures::default())
+/// Constructs a binder object that implements ICompOsService.
+pub fn new_binder(
+    rpc_binder: bool,
+    signer: Option<Box<dyn Signer>>,
+) -> Result<Strong<dyn ICompOsService>> {
+    let namespace =
+        if rpc_binder { KeystoreNamespace::VmPayload } else { KeystoreNamespace::Odsign };
+    let key_service = CompOsKeyService::new(namespace)?;
+
+    let service = CompOsService { dex2oat_path: PathBuf::from(DEX2OAT_PATH), signer, key_service };
+    Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
 }
 
-struct CompService {
+struct CompOsService {
     dex2oat_path: PathBuf,
     #[allow(dead_code)] // TODO: Make use of this
     signer: Option<Box<dyn Signer>>,
+    #[allow(dead_code)] // TODO: Make use of this
+    key_service: CompOsKeyService,
 }
 
-impl Interface for CompService {}
+impl Interface for CompOsService {}
 
-impl ICompService for CompService {
+impl ICompOsService for CompOsService {
     fn execute(&self, args: &[String], metadata: &Metadata) -> BinderResult<i8> {
         let authfs_service = get_authfs_service()?;
         compile(&self.dex2oat_path, args, authfs_service, metadata).map_err(|e| {
diff --git a/compos/src/compsvc_main.rs b/compos/src/compsvc_main.rs
index 8f68949..5c5da22 100644
--- a/compos/src/compsvc_main.rs
+++ b/compos/src/compsvc_main.rs
@@ -19,6 +19,7 @@
 
 mod common;
 mod compilation;
+mod compos_key_service;
 mod compsvc;
 mod signer;
 
@@ -48,7 +49,7 @@
     );
 
     let config = parse_args()?;
-    let mut service = compsvc::new_binder(None).as_binder();
+    let mut service = compsvc::new_binder(config.rpc_binder, /* signer */ None)?.as_binder();
     if config.rpc_binder {
         debug!("compsvc is starting as a rpc service.");
         // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
diff --git a/compos/src/pvm_exec.rs b/compos/src/pvm_exec.rs
index 03fbf72..2218d10 100644
--- a/compos/src/pvm_exec.rs
+++ b/compos/src/pvm_exec.rs
@@ -36,7 +36,7 @@
 use std::process::exit;
 
 use compos_aidl_interface::aidl::com::android::compos::{
-    ICompService::ICompService, InputFdAnnotation::InputFdAnnotation, Metadata::Metadata,
+    ICompOsService::ICompOsService, InputFdAnnotation::InputFdAnnotation, Metadata::Metadata,
     OutputFdAnnotation::OutputFdAnnotation,
 };
 use compos_aidl_interface::binder::Strong;
@@ -46,18 +46,18 @@
 
 const FD_SERVER_BIN: &str = "/apex/com.android.virt/bin/fd_server";
 
-fn get_local_service() -> Result<Strong<dyn ICompService>> {
+fn get_local_service() -> Result<Strong<dyn ICompOsService>> {
     compos_aidl_interface::binder::get_interface(SERVICE_NAME).context("get local binder")
 }
 
-fn get_rpc_binder(cid: u32) -> Result<Strong<dyn ICompService>> {
+fn get_rpc_binder(cid: u32) -> Result<Strong<dyn ICompOsService>> {
     // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can be
     // safely taken by new_spibinder.
     let ibinder = unsafe {
         new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, VSOCK_PORT) as *mut AIBinder)
     };
     if let Some(ibinder) = ibinder {
-        <dyn ICompService>::try_from(ibinder).context("Cannot connect to RPC service")
+        <dyn ICompOsService>::try_from(ibinder).context("Cannot connect to RPC service")
     } else {
         bail!("Invalid raw AIBinder")
     }