Sign artifacts after compilation

If compilation succeeds, pass over all the artifacts we generated and
produce an OdsignInfo file with all the names and digests and a
signature of it using the CompOS key.

Various refactorings along the way to make it eaiser:
- Extract the odrefresh ExitCode enum for reuse
- Extracted a Signer, distinct from an ArtifactSigner
- Defined OdrefreshContext to stop the linter complaining about a
  function with >7 arguments.

Also added more debugging to help fix my various silly mistakes.

Bug: 161471326
Test: composd_cmd forced-odrefresh -> signature file produced
Change-Id: Ia6a6abd9e28158f4767e7752727635087f9bb566
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index 4540cd8..aa4b9bd 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -26,8 +26,8 @@
 use std::path::PathBuf;
 use std::sync::RwLock;
 
-use crate::compilation::{compile_cmd, odrefresh, CompilerOutput};
-use crate::compos_key_service::CompOsKeyService;
+use crate::compilation::{compile_cmd, odrefresh, CompilerOutput, OdrefreshContext};
+use crate::compos_key_service::{CompOsKeyService, Signer};
 use crate::fsverity;
 use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
 use compos_aidl_interface::aidl::com::android::compos::{
@@ -39,10 +39,10 @@
 use compos_aidl_interface::binder::{
     BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong,
 };
+use compos_common::odrefresh::ODREFRESH_PATH;
 
 const AUTHFS_SERVICE_NAME: &str = "authfs_service";
 const DEX2OAT_PATH: &str = "/apex/com.android.art/bin/dex2oat64";
-const ODREFRESH_PATH: &str = "/apex/com.android.art/bin/odrefresh";
 
 /// Constructs a binder object that implements ICompOsService.
 pub fn new_binder() -> Result<Strong<dyn ICompOsService>> {
@@ -65,14 +65,21 @@
 impl CompOsService {
     fn generate_raw_fsverity_signature(
         &self,
-        key_blob: &[u8],
         fsverity_digest: &fsverity::Sha256Digest,
-    ) -> Vec<u8> {
+    ) -> BinderResult<Vec<u8>> {
         let formatted_digest = fsverity::to_formatted_digest(fsverity_digest);
-        self.key_service.sign(key_blob, &formatted_digest[..]).unwrap_or_else(|e| {
-            warn!("Failed to sign the fsverity digest, returning empty signature.  Error: {}", e);
-            Vec::new()
-        })
+        self.new_signer()?
+            .sign(&formatted_digest[..])
+            .map_err(|e| new_binder_exception(ExceptionCode::SERVICE_SPECIFIC, e.to_string()))
+    }
+
+    fn new_signer(&self) -> BinderResult<Signer> {
+        let key = &*self.key_blob.read().unwrap();
+        if key.is_empty() {
+            Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Key is not initialized"))
+        } else {
+            Ok(self.key_service.new_signer(key))
+        }
     }
 }
 
@@ -110,36 +117,27 @@
         target_dir_name: &str,
         zygote_arch: &str,
     ) -> BinderResult<i8> {
-        if system_dir_fd < 0 || output_dir_fd < 0 || staging_dir_fd < 0 {
-            return Err(new_binder_exception(
-                ExceptionCode::ILLEGAL_ARGUMENT,
-                "The remote FDs are expected to be non-negative",
-            ));
-        }
-        if zygote_arch != "zygote64" && zygote_arch != "zygote64_32" {
-            return Err(new_binder_exception(
-                ExceptionCode::ILLEGAL_ARGUMENT,
-                "Invalid zygote arch",
-            ));
-        }
-
-        let authfs_service = get_authfs_service()?;
-        odrefresh(
-            &self.odrefresh_path,
-            target_dir_name,
+        let context = OdrefreshContext::new(
             system_dir_fd,
             output_dir_fd,
             staging_dir_fd,
+            target_dir_name,
             zygote_arch,
-            authfs_service,
         )
-        .map_err(|e| {
-            warn!("odrefresh failed: {}", e);
-            new_binder_exception(
-                ExceptionCode::SERVICE_SPECIFIC,
-                format!("odrefresh failed: {}", e),
-            )
-        })
+        .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, e.to_string()))?;
+
+        let authfs_service = get_authfs_service()?;
+        let exit_code =
+            odrefresh(&self.odrefresh_path, context, authfs_service, self.new_signer()?).map_err(
+                |e| {
+                    warn!("odrefresh failed: {:?}", e);
+                    new_binder_exception(
+                        ExceptionCode::SERVICE_SPECIFIC,
+                        format!("odrefresh failed: {}", e),
+                    )
+                },
+            )?;
+        Ok(exit_code as i8)
     }
 
     fn compile_cmd(
@@ -157,23 +155,15 @@
             })?;
         match output {
             CompilerOutput::Digests { oat, vdex, image } => {
-                let key = &*self.key_blob.read().unwrap();
-                if key.is_empty() {
-                    Err(new_binder_exception(
-                        ExceptionCode::ILLEGAL_STATE,
-                        "Key is not initialized",
-                    ))
-                } else {
-                    let oat_signature = self.generate_raw_fsverity_signature(key, &oat);
-                    let vdex_signature = self.generate_raw_fsverity_signature(key, &vdex);
-                    let image_signature = self.generate_raw_fsverity_signature(key, &image);
-                    Ok(CompilationResult {
-                        exitCode: 0,
-                        oatSignature: oat_signature,
-                        vdexSignature: vdex_signature,
-                        imageSignature: image_signature,
-                    })
-                }
+                let oat_signature = self.generate_raw_fsverity_signature(&oat)?;
+                let vdex_signature = self.generate_raw_fsverity_signature(&vdex)?;
+                let image_signature = self.generate_raw_fsverity_signature(&image)?;
+                Ok(CompilationResult {
+                    exitCode: 0,
+                    oatSignature: oat_signature,
+                    vdexSignature: vdex_signature,
+                    imageSignature: image_signature,
+                })
             }
             CompilerOutput::ExitCode(exit_code) => {
                 Ok(CompilationResult { exitCode: exit_code, ..Default::default() })
@@ -201,14 +191,9 @@
     }
 
     fn sign(&self, data: &[u8]) -> BinderResult<Vec<u8>> {
-        let key = &*self.key_blob.read().unwrap();
-        if key.is_empty() {
-            Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Key is not initialized"))
-        } else {
-            self.key_service
-                .sign(key, data)
-                .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
-        }
+        self.new_signer()?
+            .sign(data)
+            .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
     }
 }