pvmfw: Perform DICE derivation

Integrate DICE derivation into pvmfw and fail if the operation fails.

Note that we still need to get the salt ("hidden" DICE input) from the
instance.img or TRNG and pass the result to the next stage.

Bug: 256827715
Test: atest MicrodroidHostTests
Change-Id: Ibebaf526fd6055b9d05ce6017b560fb8814471e5
diff --git a/libs/dice/src/bcc.rs b/libs/dice/src/bcc.rs
index 849dfa0..6dc0cc3 100644
--- a/libs/dice/src/bcc.rs
+++ b/libs/dice/src/bcc.rs
@@ -16,19 +16,29 @@
 
 //! Wrapper around dice/android/bcc.h.
 
+use core::ffi::CStr;
 use core::mem;
 use core::ptr;
 
+use open_dice_bcc_bindgen::BccConfigValues;
+use open_dice_bcc_bindgen::BccFormatConfigDescriptor;
+use open_dice_bcc_bindgen::BccHandoverMainFlow;
 use open_dice_bcc_bindgen::BccHandoverParse;
+use open_dice_bcc_bindgen::DiceInputValues;
+use open_dice_bcc_bindgen::BCC_INPUT_COMPONENT_NAME;
+use open_dice_bcc_bindgen::BCC_INPUT_COMPONENT_VERSION;
+use open_dice_bcc_bindgen::BCC_INPUT_RESETTABLE;
 
 use crate::check_call;
 use crate::Cdi;
 use crate::Error;
+use crate::InputValues;
 use crate::Result;
 
 /// Boot Chain Certificate handover format combining the BCC and CDIs in a single CBOR object.
 #[derive(Clone, Debug)]
 pub struct Handover<'a> {
+    buffer: &'a [u8],
     /// Attestation CDI.
     pub cdi_attest: &'a Cdi,
     /// Sealing CDI.
@@ -75,8 +85,80 @@
             Some(buffer.get(i..(i + bcc_size)).ok_or(Error::PlatformError)?)
         };
 
-        Ok(Self { cdi_attest, cdi_seal, bcc })
+        Ok(Self { buffer, cdi_attest, cdi_seal, bcc })
     }
+
+    /// Executes the main BCC handover flow.
+    pub fn main_flow(&self, input_values: &InputValues, buffer: &mut [u8]) -> Result<usize> {
+        let context = ptr::null_mut();
+        let mut size: usize = 0;
+        // SAFETY - The function only reads `self.buffer`, writes to `buffer` within its bounds,
+        // reads `input_values` as a constant input and doesn't store any pointer.
+        check_call(unsafe {
+            BccHandoverMainFlow(
+                context,
+                self.buffer.as_ptr(),
+                self.buffer.len(),
+                input_values as *const _ as *const DiceInputValues,
+                buffer.len(),
+                buffer.as_mut_ptr(),
+                &mut size as *mut usize,
+            )
+        })?;
+
+        Ok(size)
+    }
+}
+
+/// Formats a configuration descriptor following the BCC's specification.
+///
+/// ```
+/// BccConfigDescriptor = {
+///   ? -70002 : tstr,     ; Component name
+///   ? -70003 : int,      ; Component version
+///   ? -70004 : null,     ; Resettable
+/// }
+/// ```
+pub fn format_config_descriptor(
+    buffer: &mut [u8],
+    name: Option<&CStr>,
+    version: Option<u64>,
+    resettable: bool,
+) -> Result<usize> {
+    let mut inputs = 0;
+
+    if name.is_some() {
+        inputs |= BCC_INPUT_COMPONENT_NAME;
+    }
+
+    if version.is_some() {
+        inputs |= BCC_INPUT_COMPONENT_VERSION;
+    }
+
+    if resettable {
+        inputs |= BCC_INPUT_RESETTABLE;
+    }
+
+    let values = BccConfigValues {
+        inputs,
+        component_name: name.map_or(ptr::null(), |p| p.as_ptr()),
+        component_version: version.unwrap_or(0),
+    };
+
+    let mut buffer_size = 0;
+
+    // SAFETY - The function writes to the buffer, within the given bounds, and only reads the
+    // input values. It writes its result to buffer_size.
+    check_call(unsafe {
+        BccFormatConfigDescriptor(
+            &values as *const _,
+            buffer.len(),
+            buffer.as_mut_ptr(),
+            &mut buffer_size as *mut _,
+        )
+    })?;
+
+    Ok(buffer_size)
 }
 
 fn index_from_ptr(slice: &[u8], pointer: *const u8) -> Option<usize> {