[dice] Support multi key algorithm switch in pvmfw

Bug: 357008987
Bug: 341630707
Test: atest MicrodroidHostTests
Test: atest libpvmfw.dice.test
Change-Id: Id8803e071004e5622ca537d35cb532203a60758a
diff --git a/libs/dice/open_dice/Android.bp b/libs/dice/open_dice/Android.bp
index 3c5b6ea..4241c47 100644
--- a/libs/dice/open_dice/Android.bp
+++ b/libs/dice/open_dice/Android.bp
@@ -19,6 +19,9 @@
         "libopen_dice_cbor_bindgen_nostd",
         "libzeroize_nostd",
     ],
+    features: [
+        "multialg",
+    ],
     whole_static_libs: [
         "libcrypto_baremetal",
     ],
@@ -172,7 +175,11 @@
         "libopen_dice_cbor_bindgen.rust_defaults",
         "libopen_dice_bindgen_nostd.rust_defaults",
     ],
-    whole_static_libs: ["libopen_dice_cbor_baremetal"],
+    bindgen_flags: [
+        "--rustified-enum DiceKeyAlgorithm",
+        "--allowlist-type=DiceContext",
+    ],
+    whole_static_libs: ["libopen_dice_cbor_baremetal_multialg"],
 }
 
 rust_defaults {
@@ -228,7 +235,7 @@
     rustlibs: [
         "libopen_dice_cbor_bindgen_nostd",
     ],
-    whole_static_libs: ["libopen_dice_android_baremetal"],
+    whole_static_libs: ["libopen_dice_android_baremetal_multialg"],
 }
 
 rust_test {
diff --git a/libs/dice/open_dice/src/bcc.rs b/libs/dice/open_dice/src/bcc.rs
index 9c9545b..fabd7c7 100644
--- a/libs/dice/open_dice/src/bcc.rs
+++ b/libs/dice/open_dice/src/bcc.rs
@@ -14,13 +14,13 @@
 
 //! This module mirrors the content in open-dice/include/dice/android.h
 
-use crate::dice::{Cdi, CdiValues, DiceArtifacts, InputValues, CDI_SIZE};
+use crate::dice::{context, Cdi, CdiValues, DiceArtifacts, InputValues, CDI_SIZE};
 use crate::error::{check_result, DiceError, Result};
 use open_dice_android_bindgen::{
-    DiceAndroidConfigValues, DiceAndroidFormatConfigDescriptor, DiceAndroidHandoverMainFlow,
-    DiceAndroidHandoverParse, DiceAndroidMainFlow, DICE_ANDROID_CONFIG_COMPONENT_NAME,
-    DICE_ANDROID_CONFIG_COMPONENT_VERSION, DICE_ANDROID_CONFIG_RESETTABLE,
-    DICE_ANDROID_CONFIG_RKP_VM_MARKER, DICE_ANDROID_CONFIG_SECURITY_VERSION,
+    DiceAndroidConfigValues, DiceAndroidFormatConfigDescriptor, DiceAndroidHandoverParse,
+    DiceAndroidMainFlow, DICE_ANDROID_CONFIG_COMPONENT_NAME, DICE_ANDROID_CONFIG_COMPONENT_VERSION,
+    DICE_ANDROID_CONFIG_RESETTABLE, DICE_ANDROID_CONFIG_RKP_VM_MARKER,
+    DICE_ANDROID_CONFIG_SECURITY_VERSION,
 };
 use std::{ffi::CStr, ptr};
 
@@ -101,10 +101,11 @@
         // SAFETY: `DiceAndroidMainFlow` only reads the `current_chain` and CDI values and writes
         // to `next_chain` and next CDI values within its bounds. It also reads `input_values` as a
         // constant input and doesn't store any pointer.
-        // The first argument can be null and is not used in the current implementation.
+        // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
+        // and a null pointer otherwise.
         unsafe {
             DiceAndroidMainFlow(
-                ptr::null_mut(), // context
+                context(),
                 current_cdi_attest.as_ptr(),
                 current_cdi_seal.as_ptr(),
                 current_chain.as_ptr(),
@@ -127,20 +128,23 @@
 /// A handover combines the DICE chain and CDIs in a single CBOR object.
 /// This function takes the current boot stage's handover bundle and produces a
 /// bundle for the next stage.
+#[cfg(feature = "multialg")]
 pub fn bcc_handover_main_flow(
     current_handover: &[u8],
     input_values: &InputValues,
     next_handover: &mut [u8],
+    ctx: crate::dice::DiceContext,
 ) -> Result<usize> {
     let mut next_handover_size = 0;
+    let mut ctx: open_dice_cbor_bindgen::DiceContext_ = ctx.into();
     check_result(
         // SAFETY: The function only reads `current_handover` and writes to `next_handover`
         // within its bounds,
         // It also reads `input_values` as a constant input and doesn't store any pointer.
-        // The first argument can be null and is not used in the current implementation.
+        // The first argument is a pointer to a valid |DiceContext_| object.
         unsafe {
-            DiceAndroidHandoverMainFlow(
-                ptr::null_mut(), // context
+            open_dice_android_bindgen::DiceAndroidHandoverMainFlow(
+                &mut ctx as *mut _ as *mut std::ffi::c_void,
                 current_handover.as_ptr(),
                 current_handover.len(),
                 input_values.as_ptr(),
diff --git a/libs/dice/open_dice/src/dice.rs b/libs/dice/open_dice/src/dice.rs
index 6404508..206769c 100644
--- a/libs/dice/open_dice/src/dice.rs
+++ b/libs/dice/open_dice/src/dice.rs
@@ -15,7 +15,7 @@
 //! Structs and functions about the types used in DICE.
 //! This module mirrors the content in open-dice/include/dice/dice.h
 
-use crate::error::{check_result, Result};
+use crate::error::{check_result, DiceError, Result};
 use coset::iana;
 pub use open_dice_cbor_bindgen::DiceMode;
 use open_dice_cbor_bindgen::{
@@ -23,9 +23,11 @@
     DiceMainFlow, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE, DICE_ID_SIZE,
     DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
 };
+#[cfg(feature = "multialg")]
+use open_dice_cbor_bindgen::{DiceContext_, DiceKeyAlgorithm};
 #[cfg(feature = "serde_derive")]
 use serde_derive::{Deserialize, Serialize};
-use std::{marker::PhantomData, ptr};
+use std::{ffi::c_void, marker::PhantomData, ptr};
 use zeroize::{Zeroize, ZeroizeOnDrop};
 
 /// The size of a DICE hash.
@@ -114,6 +116,69 @@
     }
 }
 
+impl TryFrom<iana::Algorithm> for KeyAlgorithm {
+    type Error = DiceError;
+
+    fn try_from(alg: iana::Algorithm) -> Result<Self> {
+        match alg {
+            iana::Algorithm::EdDSA => Ok(KeyAlgorithm::Ed25519),
+            iana::Algorithm::ES256 => Ok(KeyAlgorithm::EcdsaP256),
+            iana::Algorithm::ES384 => Ok(KeyAlgorithm::EcdsaP384),
+            other => Err(DiceError::UnsupportedKeyAlgorithm(other)),
+        }
+    }
+}
+
+#[cfg(feature = "multialg")]
+impl From<KeyAlgorithm> for DiceKeyAlgorithm {
+    fn from(alg: KeyAlgorithm) -> Self {
+        match alg {
+            KeyAlgorithm::Ed25519 => DiceKeyAlgorithm::kDiceKeyAlgorithmEd25519,
+            KeyAlgorithm::EcdsaP256 => DiceKeyAlgorithm::kDiceKeyAlgorithmP256,
+            KeyAlgorithm::EcdsaP384 => DiceKeyAlgorithm::kDiceKeyAlgorithmP384,
+        }
+    }
+}
+
+/// Represents the context used for DICE operations.
+#[cfg(feature = "multialg")]
+#[derive(Debug, Clone)]
+pub struct DiceContext {
+    /// The algorithm used for the authority key.
+    pub authority_algorithm: KeyAlgorithm,
+    /// The algorithm used for the subject key.
+    pub subject_algorithm: KeyAlgorithm,
+}
+
+#[cfg(feature = "multialg")]
+impl From<DiceContext> for DiceContext_ {
+    fn from(ctx: DiceContext) -> Self {
+        DiceContext_ {
+            authority_algorithm: ctx.authority_algorithm.into(),
+            subject_algorithm: ctx.subject_algorithm.into(),
+        }
+    }
+}
+
+#[cfg(feature = "multialg")]
+const VM_DICE_CONTEXT: DiceContext_ = DiceContext_ {
+    authority_algorithm: DiceKeyAlgorithm::kDiceKeyAlgorithmEd25519,
+    subject_algorithm: DiceKeyAlgorithm::kDiceKeyAlgorithmEd25519,
+};
+
+/// Returns the pointer points to |DiceContext_| for DICE operations when `multialg`
+/// feature is enabled.
+#[cfg(feature = "multialg")]
+pub(crate) fn context() -> *mut c_void {
+    &VM_DICE_CONTEXT as *const DiceContext_ as *mut c_void
+}
+
+/// Returns a null pointer when `multialg` feature is disabled.
+#[cfg(not(feature = "multialg"))]
+pub(crate) fn context() -> *mut c_void {
+    ptr::null_mut()
+}
+
 /// A trait for types that represent Dice artifacts, which include:
 ///
 /// - Attestation CDI
@@ -322,10 +387,9 @@
     check_result(
         // SAFETY: The function only reads the current CDI values and inputs and writes
         // to `next_cdi_certificate` and next CDI values within its bounds.
-        // The first argument can be null and is not used in the current implementation.
         unsafe {
             DiceMainFlow(
-                ptr::null_mut(), // context
+                context(),
                 current_cdi_attest.as_ptr(),
                 current_cdi_seal.as_ptr(),
                 input_values.as_ptr(),
diff --git a/libs/dice/open_dice/src/error.rs b/libs/dice/open_dice/src/error.rs
index bef9a9c..9089432 100644
--- a/libs/dice/open_dice/src/error.rs
+++ b/libs/dice/open_dice/src/error.rs
@@ -29,6 +29,8 @@
     BufferTooSmall(usize),
     /// Platform error.
     PlatformError,
+    /// Unsupported key algorithm.
+    UnsupportedKeyAlgorithm(coset::iana::Algorithm),
 }
 
 /// This makes `DiceError` accepted by anyhow.
@@ -43,6 +45,9 @@
                 write!(f, "Buffer too small; need {buffer_required_size} bytes")
             }
             Self::PlatformError => write!(f, "Platform error"),
+            Self::UnsupportedKeyAlgorithm(algorithm) => {
+                write!(f, "Unsupported key algorithm: {algorithm:?}")
+            }
         }
     }
 }
diff --git a/libs/dice/open_dice/src/lib.rs b/libs/dice/open_dice/src/lib.rs
index a347d46..4d05255 100644
--- a/libs/dice/open_dice/src/lib.rs
+++ b/libs/dice/open_dice/src/lib.rs
@@ -28,10 +28,13 @@
 mod ops;
 mod retry;
 
+#[cfg(feature = "multialg")]
+pub use bcc::bcc_handover_main_flow;
 pub use bcc::{
-    bcc_format_config_descriptor, bcc_handover_main_flow, bcc_handover_parse, bcc_main_flow,
-    BccHandover, DiceConfigValues,
+    bcc_format_config_descriptor, bcc_handover_parse, bcc_main_flow, BccHandover, DiceConfigValues,
 };
+#[cfg(feature = "multialg")]
+pub use dice::DiceContext;
 pub use dice::{
     derive_cdi_certificate_id, derive_cdi_private_key_seed, dice_main_flow, Cdi, CdiValues, Config,
     DiceArtifacts, DiceMode, Hash, Hidden, InlineConfig, InputValues, KeyAlgorithm, PrivateKey,
diff --git a/libs/dice/open_dice/src/ops.rs b/libs/dice/open_dice/src/ops.rs
index 7bc0ee5..41951bf 100644
--- a/libs/dice/open_dice/src/ops.rs
+++ b/libs/dice/open_dice/src/ops.rs
@@ -17,7 +17,7 @@
 //! main DICE functions depend on.
 
 use crate::dice::{
-    derive_cdi_private_key_seed, DiceArtifacts, Hash, InputValues, PrivateKey, HASH_SIZE,
+    context, derive_cdi_private_key_seed, DiceArtifacts, Hash, InputValues, PrivateKey, HASH_SIZE,
     PRIVATE_KEY_SEED_SIZE, PRIVATE_KEY_SIZE, VM_KEY_ALGORITHM,
 };
 use crate::error::{check_result, DiceError, Result};
@@ -83,11 +83,12 @@
     let principal = DicePrincipal::kDicePrincipalSubject;
     check_result(
         // SAFETY: The function writes to the `public_key` and `private_key` within the given
-        // bounds, and only reads the `seed`. The first argument context is not used in this
-        // function.
+        // bounds, and only reads the `seed`.
+        // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
+        // and a null pointer otherwise.
         unsafe {
             DiceKeypairFromSeed(
-                ptr::null_mut(), // context
+                context(),
                 principal,
                 seed.as_ptr(),
                 public_key.as_mut_ptr(),
@@ -118,11 +119,12 @@
     let mut signature = vec![0u8; VM_KEY_ALGORITHM.signature_size()];
     check_result(
         // SAFETY: The function writes to the `signature` within the given bounds, and only reads
-        // the message and the private key. The first argument context is not used in this
-        // function.
+        // the message and the private key.
+        // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
+        // and a null pointer otherwise.
         unsafe {
             DiceSign(
-                ptr::null_mut(), // context
+                context(),
                 message.as_ptr(),
                 message.len(),
                 private_key.as_ptr(),
@@ -143,10 +145,11 @@
     }
     check_result(
         // SAFETY: only reads the messages, signature and public key as constant values.
-        // The first argument context is not used in this function.
+        // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
+        // and a null pointer otherwise.
         unsafe {
             DiceVerify(
-                ptr::null_mut(), // context
+                context(),
                 message.as_ptr(),
                 message.len(),
                 signature.as_ptr(),
@@ -171,11 +174,12 @@
     let mut certificate_actual_size = 0;
     check_result(
         // SAFETY: The function writes to the `certificate` within the given bounds, and only reads
-        // the input values and the key seeds. The first argument context is not used in this
-        // function.
+        // the input values and the key seeds.
+        // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
+        // and a null pointer otherwise.
         unsafe {
             DiceGenerateCertificate(
-                ptr::null_mut(), // context
+                context(),
                 subject_private_key_seed.as_ptr(),
                 authority_private_key_seed.as_ptr(),
                 input_values.as_ptr(),