Merge "Allow preinstalled apps to use the AVF APIs" into main
diff --git a/libs/libfdt/src/iterators.rs b/libs/libfdt/src/iterators.rs
index 05fdb4a..280257b 100644
--- a/libs/libfdt/src/iterators.rs
+++ b/libs/libfdt/src/iterators.rs
@@ -14,6 +14,7 @@
 
 //! Iterators over cells, and various layers on top of them.
 
+use crate::FdtError;
 use crate::{AddrCells, SizeCells};
 use core::marker::PhantomData;
 use core::{mem::size_of, ops::Range, slice::ChunksExact};
@@ -59,6 +60,21 @@
     pub size: Option<T>,
 }
 
+impl<T: TryInto<usize>> TryFrom<Reg<T>> for Range<usize> {
+    type Error = FdtError;
+
+    fn try_from(reg: Reg<T>) -> Result<Self, Self::Error> {
+        let addr = to_usize(reg.addr)?;
+        let size = to_usize(reg.size.ok_or(FdtError::NotFound)?)?;
+        let end = addr.checked_add(size).ok_or(FdtError::BadValue)?;
+        Ok(addr..end)
+    }
+}
+
+fn to_usize<T: TryInto<usize>>(num: T) -> Result<usize, FdtError> {
+    num.try_into().map_err(|_| FdtError::BadValue)
+}
+
 impl<'a> RegIterator<'a> {
     pub(crate) fn new(
         cells: CellIterator<'a>,
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index a305e03..1bf285e 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -341,7 +341,8 @@
         self.fdt
     }
 
-    fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
+    /// Returns the compatible node of the given name that is next after this node.
+    pub fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
         // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
         let ret = unsafe {
             libfdt_bindgen::fdt_node_offset_by_compatible(
@@ -354,6 +355,11 @@
         Ok(fdt_err_or_option(ret)?.map(|offset| Self { fdt: self.fdt, offset }))
     }
 
+    /// Returns the first range of `reg` in this node.
+    pub fn first_reg(&self) -> Result<Reg<u64>> {
+        self.reg()?.ok_or(FdtError::NotFound)?.next().ok_or(FdtError::NotFound)
+    }
+
     fn address_cells(&self) -> Result<AddrCells> {
         // SAFETY: Accesses are constrained to the DT totalsize (validated by ctor).
         unsafe { libfdt_bindgen::fdt_address_cells(self.fdt.as_ptr(), self.offset) }
@@ -526,7 +532,7 @@
         Ok(FdtNode { fdt: &*self.fdt, offset: fdt_err(ret)? })
     }
 
-    /// Return the compatible node of the given name that is next to this node
+    /// Returns the compatible node of the given name that is next after this node
     pub fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
         // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
         let ret = unsafe {
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/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index 61de423..1f87dcc 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -443,7 +443,7 @@
 fn read_serial_info_from(fdt: &Fdt) -> libfdt::Result<SerialInfo> {
     let mut addrs: ArrayVec<[u64; SerialInfo::MAX_SERIALS]> = Default::default();
     for node in fdt.compatible_nodes(cstr!("ns16550a"))?.take(SerialInfo::MAX_SERIALS) {
-        let reg = node.reg()?.ok_or(FdtError::NotFound)?.next().ok_or(FdtError::NotFound)?;
+        let reg = node.first_reg()?;
         addrs.push(reg.addr);
     }
     Ok(SerialInfo { addrs })
diff --git a/rialto/Android.bp b/rialto/Android.bp
index d8e4536..1df18f6 100644
--- a/rialto/Android.bp
+++ b/rialto/Android.bp
@@ -11,6 +11,7 @@
         "libaarch64_paging",
         "libciborium_io_nostd",
         "libciborium_nostd",
+        "libdiced_open_dice_nostd",
         "libhyp",
         "libfdtpci",
         "liblibfdt",
diff --git a/rialto/src/error.rs b/rialto/src/error.rs
index 23667ed..d2bdbbe 100644
--- a/rialto/src/error.rs
+++ b/rialto/src/error.rs
@@ -16,9 +16,11 @@
 
 use aarch64_paging::MapError;
 use core::{fmt, result};
+use diced_open_dice::DiceError;
 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>;
@@ -50,6 +52,10 @@
     SerializationFailed(CiboriumSerError),
     /// Failed to deserialize.
     DeserializationFailed(CiboriumDeError),
+    /// Failed DICE operation.
+    DiceOperationFailed(DiceError),
+    /// Failed to process request.
+    RequestProcessingFailed(RequestProcessingError),
 }
 
 impl fmt::Display for Error {
@@ -72,6 +78,8 @@
             }
             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}"),
         }
     }
 }
@@ -123,3 +131,15 @@
         Self::DeserializationFailed(e)
     }
 }
+
+impl From<DiceError> for Error {
+    fn from(e: DiceError) -> Self {
+        Self::DiceOperationFailed(e)
+    }
+}
+
+impl From<RequestProcessingError> for Error {
+    fn from(e: RequestProcessingError) -> Self {
+        Self::RequestProcessingFailed(e)
+    }
+}
diff --git a/rialto/src/fdt.rs b/rialto/src/fdt.rs
new file mode 100644
index 0000000..8bb40c3
--- /dev/null
+++ b/rialto/src/fdt.rs
@@ -0,0 +1,26 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! High-level FDT functions.
+
+use core::ops::Range;
+use libfdt::{Fdt, FdtError};
+use vmbase::cstr;
+
+/// Reads the DICE data range from the given `fdt`.
+pub fn read_dice_range_from(fdt: &Fdt) -> libfdt::Result<Range<usize>> {
+    let node = fdt.node(cstr!("/reserved-memory"))?.ok_or(FdtError::NotFound)?;
+    let node = node.next_compatible(cstr!("google,open-dice"))?.ok_or(FdtError::NotFound)?;
+    node.first_reg()?.try_into()
+}
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 4e91574..f8f6d51 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -20,12 +20,14 @@
 mod communication;
 mod error;
 mod exceptions;
+mod fdt;
 mod requests;
 
 extern crate alloc;
 
 use crate::communication::VsockStream;
 use crate::error::{Error, Result};
+use crate::fdt::read_dice_range_from;
 use ciborium_io::Write;
 use core::num::NonZeroUsize;
 use core::slice;
@@ -130,6 +132,17 @@
             e
         })?;
     }
+    let _bcc_handover = match vm_type() {
+        VmType::ProtectedVm => {
+            let dice_range = read_dice_range_from(fdt)?;
+            info!("DICE range: {dice_range:#x?}");
+            // TODO(b/287233786): Read the bcc_handover from the given range.
+            Some(dice_range)
+        }
+        // Currently, no DICE data is retrieved for non-protected VMs, as these VMs are solely
+        // intended for debugging purposes.
+        VmType::NonProtectedVm => None,
+    };
 
     let pci_info = PciInfo::from_fdt(fdt)?;
     debug!("PCI: {pci_info:#x?}");
@@ -140,6 +153,7 @@
     debug!("Found socket device: guest cid = {:?}", socket_device.guest_cid());
 
     let mut vsock_stream = VsockStream::new(socket_device, host_addr())?;
+    // TODO(b/287233786): Pass the bcc_handover to process_request.
     while let ServiceVmRequest::Process(req) = vsock_stream.read_request()? {
         let response = requests::process_request(req)?;
         vsock_stream.write_response(&response)?;
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")
 }