[rkp] Report request processing error from service VM to host

This cl moves the request processing error from the service VM
to the communication protocol library so that the service VM can
send the error the host.
This change is necessary to enable the service VM to send back
RKP service specific error later.

Bug: 299256925
Test: atest rialto_test
Change-Id: I2cd718d8606880188866e954ac7c4eb8bb732bb4
diff --git a/libs/service_vm_comm/Android.bp b/libs/service_vm_comm/Android.bp
index cdb8fc3..9bce2f4 100644
--- a/libs/service_vm_comm/Android.bp
+++ b/libs/service_vm_comm/Android.bp
@@ -21,6 +21,8 @@
         "libcore.rust_sysroot",
     ],
     rustlibs: [
+        "libcoset_nostd",
+        "liblog_rust_nostd",
         "libserde_nostd",
     ],
 }
@@ -29,6 +31,8 @@
     name: "libservice_vm_comm",
     defaults: ["libservice_vm_comm_defaults"],
     rustlibs: [
+        "libcoset",
+        "liblog_rust",
         "libserde",
     ],
     features: [
diff --git a/libs/service_vm_comm/src/lib.rs b/libs/service_vm_comm/src/lib.rs
index ca97ca1..d8f7bd7 100644
--- a/libs/service_vm_comm/src/lib.rs
+++ b/libs/service_vm_comm/src/lib.rs
@@ -23,6 +23,7 @@
 mod vsock;
 
 pub use message::{
-    EcdsaP256KeyPair, GenerateCertificateRequestParams, Request, Response, ServiceVmRequest,
+    EcdsaP256KeyPair, GenerateCertificateRequestParams, Request, RequestProcessingError, Response,
+    ServiceVmRequest,
 };
 pub use vsock::VmType;
diff --git a/libs/service_vm_comm/src/message.rs b/libs/service_vm_comm/src/message.rs
index 80956cb..407c5e5 100644
--- a/libs/service_vm_comm/src/message.rs
+++ b/libs/service_vm_comm/src/message.rs
@@ -15,8 +15,10 @@
 //! This module contains the requests and responses definitions exchanged
 //! between the host and the service VM.
 
+use alloc::string::String;
 use alloc::vec::Vec;
-
+use core::fmt;
+use log::error;
 use serde::{Deserialize, Serialize};
 
 type MacedPublicKey = Vec<u8>;
@@ -64,6 +66,41 @@
 
     /// Returns a CBOR Certificate Signing Request (Csr) serialized into a byte array.
     GenerateCertificateRequest(Vec<u8>),
+
+    /// Encountered an error during the request processing.
+    Err(RequestProcessingError),
+}
+
+/// Errors related to request processing.
+#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub enum RequestProcessingError {
+    /// Failed to invoke a BoringSSL API.
+    BoringSSLCallFailed(String),
+
+    /// An error happened during the interaction with coset.
+    CosetError,
+
+    /// Any key to sign lacks a valid MAC. Maps to `STATUS_INVALID_MAC`.
+    InvalidMac,
+}
+
+impl fmt::Display for RequestProcessingError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Self::BoringSSLCallFailed(api_name) => {
+                write!(f, "Failed to invoke a BoringSSL API: {api_name}")
+            }
+            Self::CosetError => write!(f, "Encountered an error with coset"),
+            Self::InvalidMac => write!(f, "A key to sign lacks a valid MAC."),
+        }
+    }
+}
+
+impl From<coset::CoseError> for RequestProcessingError {
+    fn from(e: coset::CoseError) -> Self {
+        error!("Coset error: {e}");
+        Self::CosetError
+    }
 }
 
 /// Represents the params passed to GenerateCertificateRequest
diff --git a/rialto/src/error.rs b/rialto/src/error.rs
index 911cb9b..d2bdbbe 100644
--- a/rialto/src/error.rs
+++ b/rialto/src/error.rs
@@ -20,6 +20,7 @@
 use fdtpci::PciError;
 use hyp::Error as HypervisorError;
 use libfdt::FdtError;
+use service_vm_comm::RequestProcessingError;
 use vmbase::{memory::MemoryTrackerError, virtio::pci};
 
 pub type Result<T> = result::Result<T, Error>;
@@ -53,6 +54,8 @@
     DeserializationFailed(CiboriumDeError),
     /// Failed DICE operation.
     DiceOperationFailed(DiceError),
+    /// Failed to process request.
+    RequestProcessingFailed(RequestProcessingError),
 }
 
 impl fmt::Display for Error {
@@ -76,6 +79,7 @@
             Self::SerializationFailed(e) => write!(f, "Failed to serialize: {e}"),
             Self::DeserializationFailed(e) => write!(f, "Failed to deserialize: {e}"),
             Self::DiceOperationFailed(e) => write!(f, "Failed DICE operation: {e}"),
+            Self::RequestProcessingFailed(e) => write!(f, "Failed to process request: {e}"),
         }
     }
 }
@@ -133,3 +137,9 @@
         Self::DiceOperationFailed(e)
     }
 }
+
+impl From<RequestProcessingError> for Error {
+    fn from(e: RequestProcessingError) -> Self {
+        Self::RequestProcessingFailed(e)
+    }
+}
diff --git a/rialto/src/requests/api.rs b/rialto/src/requests/api.rs
index c4b2d8e..5ea0106 100644
--- a/rialto/src/requests/api.rs
+++ b/rialto/src/requests/api.rs
@@ -25,14 +25,10 @@
 pub fn process_request(request: Request) -> Result<Response> {
     let response = match request {
         Request::Reverse(v) => Response::Reverse(reverse(v)),
-        Request::GenerateEcdsaP256KeyPair => {
-            let res = rkp::generate_ecdsa_p256_key_pair()?;
-            Response::GenerateEcdsaP256KeyPair(res)
-        }
-        Request::GenerateCertificateRequest(p) => {
-            let res = rkp::generate_certificate_request(p)?;
-            Response::GenerateCertificateRequest(res)
-        }
+        Request::GenerateEcdsaP256KeyPair => rkp::generate_ecdsa_p256_key_pair()
+            .map_or_else(Response::Err, Response::GenerateEcdsaP256KeyPair),
+        Request::GenerateCertificateRequest(p) => rkp::generate_certificate_request(p)
+            .map_or_else(Response::Err, Response::GenerateCertificateRequest),
     };
     Ok(response)
 }
diff --git a/rialto/src/requests/rkp.rs b/rialto/src/requests/rkp.rs
index 5977bfb..d74bb43 100644
--- a/rialto/src/requests/rkp.rs
+++ b/rialto/src/requests/rkp.rs
@@ -15,9 +15,11 @@
 //! This module contains functions related to the attestation of the
 //! service VM via the RKP (Remote Key Provisionning) server.
 
-use crate::error::Result;
 use alloc::vec::Vec;
-use service_vm_comm::{EcdsaP256KeyPair, GenerateCertificateRequestParams};
+use core::result;
+use service_vm_comm::{EcdsaP256KeyPair, GenerateCertificateRequestParams, RequestProcessingError};
+
+type Result<T> = result::Result<T, RequestProcessingError>;
 
 pub(super) fn generate_ecdsa_p256_key_pair() -> Result<EcdsaP256KeyPair> {
     // TODO(b/299055662): Generate the key pair.
diff --git a/virtualizationservice/src/remote_provisioning.rs b/virtualizationservice/src/remote_provisioning.rs
index 1c8d1e6..a9a07a5 100644
--- a/virtualizationservice/src/remote_provisioning.rs
+++ b/virtualizationservice/src/remote_provisioning.rs
@@ -19,7 +19,7 @@
     DeviceInfo::DeviceInfo,
     IRemotelyProvisionedComponent::{
         BnRemotelyProvisionedComponent, IRemotelyProvisionedComponent, STATUS_FAILED,
-        STATUS_REMOVED,
+        STATUS_INVALID_MAC, STATUS_REMOVED,
     },
     MacedPublicKey::MacedPublicKey,
     ProtectedData::ProtectedData,
@@ -28,6 +28,7 @@
 use anyhow::Context;
 use avflog::LogResult;
 use binder::{BinderFeatures, Interface, IntoBinderResult, Result as BinderResult, Status, Strong};
+use service_vm_comm::{RequestProcessingError, Response};
 
 /// Constructs a binder object that implements `IRemotelyProvisionedComponent`.
 pub(crate) fn new_binder() -> Strong<dyn IRemotelyProvisionedComponent> {
@@ -65,12 +66,18 @@
             ))
             .with_log();
         }
-        let key_pair = rkpvm::generate_ecdsa_p256_key_pair()
+        let res = rkpvm::generate_ecdsa_p256_key_pair()
             .context("Failed to generate ECDSA P-256 key pair")
             .with_log()
             .or_service_specific_exception(STATUS_FAILED)?;
-        macedPublicKey.macedKey = key_pair.maced_public_key;
-        Ok(key_pair.key_blob)
+        match res {
+            Response::GenerateEcdsaP256KeyPair(key_pair) => {
+                macedPublicKey.macedKey = key_pair.maced_public_key;
+                Ok(key_pair.key_blob)
+            }
+            _ => Err(to_service_specific_error(res)),
+        }
+        .with_log()
     }
 
     fn generateCertificateRequest(
@@ -104,10 +111,32 @@
             return Err(Status::new_service_specific_error_str(STATUS_FAILED, Some(message)))
                 .with_log();
         }
-        // TODO(b/299259624): Validate the MAC of the keys to certify.
-        rkpvm::generate_certificate_request(keysToSign, challenge)
+        let res = rkpvm::generate_certificate_request(keysToSign, challenge)
             .context("Failed to generate certificate request")
             .with_log()
-            .or_service_specific_exception(STATUS_FAILED)
+            .or_service_specific_exception(STATUS_FAILED)?;
+        match res {
+            Response::GenerateCertificateRequest(res) => Ok(res),
+            _ => Err(to_service_specific_error(res)),
+        }
+        .with_log()
+    }
+}
+
+fn to_service_specific_error(response: Response) -> Status {
+    match response {
+        Response::Err(e) => match e {
+            RequestProcessingError::InvalidMac => {
+                Status::new_service_specific_error_str(STATUS_INVALID_MAC, Some(format!("{e}")))
+            }
+            _ => Status::new_service_specific_error_str(
+                STATUS_FAILED,
+                Some(format!("Failed to process request: {e}.")),
+            ),
+        },
+        other => Status::new_service_specific_error_str(
+            STATUS_FAILED,
+            Some(format!("Incorrect response type: {other:?}")),
+        ),
     }
 }
diff --git a/virtualizationservice/src/rkpvm.rs b/virtualizationservice/src/rkpvm.rs
index 80953b5..d6e87eb 100644
--- a/virtualizationservice/src/rkpvm.rs
+++ b/virtualizationservice/src/rkpvm.rs
@@ -18,7 +18,7 @@
 
 use android_hardware_security_rkp::aidl::android::hardware::security::keymint::MacedPublicKey::MacedPublicKey;
 use anyhow::{bail, Context, Result};
-use service_vm_comm::{EcdsaP256KeyPair, GenerateCertificateRequestParams, Request, Response};
+use service_vm_comm::{GenerateCertificateRequestParams, Request, Response};
 use service_vm_manager::ServiceVm;
 
 pub(crate) fn request_certificate(csr: &[u8]) -> Result<Vec<u8>> {
@@ -33,19 +33,16 @@
     }
 }
 
-pub(crate) fn generate_ecdsa_p256_key_pair() -> Result<EcdsaP256KeyPair> {
+pub(crate) fn generate_ecdsa_p256_key_pair() -> Result<Response> {
     let mut vm = ServiceVm::start()?;
     let request = Request::GenerateEcdsaP256KeyPair;
-    match vm.process_request(request).context("Failed to process request")? {
-        Response::GenerateEcdsaP256KeyPair(key_pair) => Ok(key_pair),
-        _ => bail!("Incorrect response type"),
-    }
+    vm.process_request(request).context("Failed to process request")
 }
 
 pub(crate) fn generate_certificate_request(
     keys_to_sign: &[MacedPublicKey],
     challenge: &[u8],
-) -> Result<Vec<u8>> {
+) -> Result<Response> {
     let params = GenerateCertificateRequestParams {
         keys_to_sign: keys_to_sign.iter().map(|v| v.macedKey.to_vec()).collect(),
         challenge: challenge.to_vec(),
@@ -53,8 +50,5 @@
     let request = Request::GenerateCertificateRequest(params);
 
     let mut vm = ServiceVm::start()?;
-    match vm.process_request(request).context("Failed to process request")? {
-        Response::GenerateCertificateRequest(csr) => Ok(csr),
-        _ => bail!("Incorrect response type"),
-    }
+    vm.process_request(request).context("Failed to process request")
 }