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/lib.rs b/libs/dice/src/lib.rs
index 43d167f..9bbacc6 100644
--- a/libs/dice/src/lib.rs
+++ b/libs/dice/src/lib.rs
@@ -19,9 +19,19 @@
 #![no_std]
 
 use core::fmt;
+use core::mem;
+use core::ptr;
 use core::result;
 
+use open_dice_cbor_bindgen::DiceConfigType_kDiceConfigTypeDescriptor as DICE_CONFIG_TYPE_DESCRIPTOR;
+use open_dice_cbor_bindgen::DiceConfigType_kDiceConfigTypeInline as DICE_CONFIG_TYPE_INLINE;
 use open_dice_cbor_bindgen::DiceHash;
+use open_dice_cbor_bindgen::DiceInputValues;
+use open_dice_cbor_bindgen::DiceMode;
+use open_dice_cbor_bindgen::DiceMode_kDiceModeDebug as DICE_MODE_DEBUG;
+use open_dice_cbor_bindgen::DiceMode_kDiceModeMaintenance as DICE_MODE_MAINTENANCE;
+use open_dice_cbor_bindgen::DiceMode_kDiceModeNormal as DICE_MODE_NORMAL;
+use open_dice_cbor_bindgen::DiceMode_kDiceModeNotInitialized as DICE_MODE_NOT_INITIALIZED;
 use open_dice_cbor_bindgen::DiceResult;
 use open_dice_cbor_bindgen::DiceResult_kDiceResultBufferTooSmall as DICE_RESULT_BUFFER_TOO_SMALL;
 use open_dice_cbor_bindgen::DiceResult_kDiceResultInvalidInput as DICE_RESULT_INVALID_INPUT;
@@ -32,11 +42,17 @@
 
 const CDI_SIZE: usize = open_dice_cbor_bindgen::DICE_CDI_SIZE as usize;
 const HASH_SIZE: usize = open_dice_cbor_bindgen::DICE_HASH_SIZE as usize;
+const HIDDEN_SIZE: usize = open_dice_cbor_bindgen::DICE_HIDDEN_SIZE as usize;
+const INLINE_CONFIG_SIZE: usize = open_dice_cbor_bindgen::DICE_INLINE_CONFIG_SIZE as usize;
 
 /// Array type of CDIs.
 pub type Cdi = [u8; CDI_SIZE];
 /// Array type of hashes used by DICE.
 pub type Hash = [u8; HASH_SIZE];
+/// Array type of additional input.
+pub type Hidden = [u8; HIDDEN_SIZE];
+/// Array type of inline configuration values.
+pub type InlineConfig = [u8; INLINE_CONFIG_SIZE];
 
 /// Error type used by DICE.
 pub enum Error {
@@ -74,6 +90,79 @@
     }
 }
 
+/// DICE mode values.
+#[derive(Clone, Copy, Debug)]
+pub enum Mode {
+    /// At least one security mechanism has not been configured. Also acts as a catch-all.
+    /// Invalid mode values should be treated like this mode.
+    NotInitialized = DICE_MODE_NOT_INITIALIZED as _,
+    /// Indicates the device is operating normally under secure configuration.
+    Normal = DICE_MODE_NORMAL as _,
+    /// Indicates at least one criteria for Normal mode is not met.
+    Debug = DICE_MODE_DEBUG as _,
+    /// Indicates a recovery or maintenance mode of some kind.
+    Maintenance = DICE_MODE_MAINTENANCE as _,
+}
+
+impl From<Mode> for DiceMode {
+    fn from(mode: Mode) -> Self {
+        mode as Self
+    }
+}
+
+/// DICE configuration input type.
+#[derive(Debug)]
+pub enum ConfigType<'a> {
+    /// Uses the formatted 64-byte configuration input value (See the Open Profile for DICE).
+    Inline(InlineConfig),
+    /// Uses the 64-byte hash of more configuration data.
+    Descriptor(&'a [u8]),
+}
+
+/// Set of DICE inputs.
+#[repr(transparent)]
+#[derive(Clone, Debug)]
+pub struct InputValues(DiceInputValues);
+
+impl InputValues {
+    /// Wrap the DICE inputs in a InputValues, expected by bcc::main_flow().
+    pub fn new(
+        code_hash: &Hash,
+        code_descriptor: Option<&[u8]>,
+        config: &ConfigType,
+        auth_hash: Option<&Hash>,
+        auth_descriptor: Option<&[u8]>,
+        mode: Mode,
+        hidden: Option<&Hidden>,
+    ) -> Self {
+        const ZEROED_INLINE_CONFIG: InlineConfig = [0; INLINE_CONFIG_SIZE];
+        let (config_type, config_value, config_descriptor) = match config {
+            ConfigType::Inline(value) => (DICE_CONFIG_TYPE_INLINE, *value, None),
+            ConfigType::Descriptor(desc) => {
+                (DICE_CONFIG_TYPE_DESCRIPTOR, ZEROED_INLINE_CONFIG, Some(*desc))
+            }
+        };
+        let (code_descriptor, code_descriptor_size) = as_raw_parts(code_descriptor);
+        let (config_descriptor, config_descriptor_size) = as_raw_parts(config_descriptor);
+        let (authority_descriptor, authority_descriptor_size) = as_raw_parts(auth_descriptor);
+
+        Self(DiceInputValues {
+            code_hash: *code_hash,
+            code_descriptor,
+            code_descriptor_size,
+            config_type,
+            config_value,
+            config_descriptor,
+            config_descriptor_size,
+            authority_hash: auth_hash.map_or([0; mem::size_of::<Hash>()], |h| *h),
+            authority_descriptor,
+            authority_descriptor_size,
+            mode: mode.into(),
+            hidden: hidden.map_or([0; mem::size_of::<Hidden>()], |h| *h),
+        })
+    }
+}
+
 fn ctx() -> *mut core::ffi::c_void {
     core::ptr::null_mut()
 }
@@ -85,3 +174,10 @@
     check_call(unsafe { DiceHash(ctx(), bytes.as_ptr(), bytes.len(), output.as_mut_ptr()) })?;
     Ok(output)
 }
+
+fn as_raw_parts<T: Sized>(s: Option<&[T]>) -> (*const T, usize) {
+    match s {
+        Some(s) => (s.as_ptr(), s.len()),
+        None => (ptr::null(), 0),
+    }
+}