[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/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index 5c767a3..51f7802 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -118,6 +118,7 @@
"libciborium",
"libdiced_open_dice_nostd",
"libpvmfw_avb_nostd",
+ "libdiced_sample_inputs_nostd",
"libzerocopy_nostd",
"libhex",
],
diff --git a/guest/pvmfw/src/dice.rs b/guest/pvmfw/src/dice.rs
index f3a2337..b597309 100644
--- a/guest/pvmfw/src/dice.rs
+++ b/guest/pvmfw/src/dice.rs
@@ -21,7 +21,7 @@
use ciborium::Value;
use core::mem::size_of;
use diced_open_dice::{
- bcc_handover_main_flow, hash, Config, DiceMode, Hash, InputValues, HIDDEN_SIZE,
+ bcc_handover_main_flow, hash, Config, DiceContext, DiceMode, Hash, InputValues, HIDDEN_SIZE,
};
use pvmfw_avb::{Capability, DebugLevel, Digest, VerifiedBootData};
use zerocopy::AsBytes;
@@ -102,6 +102,7 @@
instance_hash: Option<Hash>,
deferred_rollback_protection: bool,
next_bcc: &mut [u8],
+ context: DiceContext,
) -> Result<()> {
let config = self
.generate_config_descriptor(instance_hash)
@@ -114,7 +115,7 @@
self.mode,
self.make_hidden(salt, deferred_rollback_protection)?,
);
- let _ = bcc_handover_main_flow(current_bcc_handover, &dice_inputs, next_bcc)?;
+ let _ = bcc_handover_main_flow(current_bcc_handover, &dice_inputs, next_bcc, context)?;
Ok(())
}
@@ -177,8 +178,11 @@
};
use ciborium::Value;
use diced_open_dice::DiceArtifacts;
+ use diced_open_dice::DiceContext;
use diced_open_dice::DiceMode;
+ use diced_open_dice::KeyAlgorithm;
use diced_open_dice::HIDDEN_SIZE;
+ use diced_sample_inputs::make_sample_bcc_and_cdis;
use pvmfw_avb::Capability;
use pvmfw_avb::DebugLevel;
use pvmfw_avb::Digest;
@@ -298,6 +302,10 @@
let mut buffer_without_defer = [0; 4096];
let mut buffer_with_defer = [0; 4096];
let mut buffer_without_defer_retry = [0; 4096];
+ let context = DiceContext {
+ authority_algorithm: KeyAlgorithm::Ed25519,
+ subject_algorithm: KeyAlgorithm::Ed25519,
+ };
let sample_dice_input: &[u8] = &[
0xa3, // CDI attest
@@ -321,6 +329,7 @@
Some([0u8; 64]),
false,
&mut buffer_without_defer,
+ context.clone(),
)
.unwrap();
let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer_without_defer).unwrap();
@@ -333,6 +342,7 @@
Some([0u8; 64]),
true,
&mut buffer_with_defer,
+ context.clone(),
)
.unwrap();
let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer_with_defer).unwrap();
@@ -345,6 +355,7 @@
Some([0u8; 64]),
false,
&mut buffer_without_defer_retry,
+ context.clone(),
)
.unwrap();
let bcc_handover3 =
@@ -353,4 +364,82 @@
assert_ne!(bcc_handover1.cdi_seal(), bcc_handover2.cdi_seal());
assert_eq!(bcc_handover1.cdi_seal(), bcc_handover3.cdi_seal());
}
+
+ #[test]
+ fn dice_derivation_with_different_algorithms_is_valid() {
+ let dice_artifacts = make_sample_bcc_and_cdis().unwrap();
+ let bcc_handover0_bytes = to_bcc_handover(&dice_artifacts);
+ let vb_data = VerifiedBootData { debug_level: DebugLevel::Full, ..BASE_VB_DATA };
+ let inputs = PartialInputs::new(&vb_data).unwrap();
+ let mut buffer = [0; 4096];
+
+ inputs
+ .clone()
+ .write_next_bcc(
+ &bcc_handover0_bytes,
+ &[0u8; HIDDEN_SIZE],
+ Some([0u8; 64]),
+ true,
+ &mut buffer,
+ DiceContext {
+ authority_algorithm: KeyAlgorithm::Ed25519,
+ subject_algorithm: KeyAlgorithm::EcdsaP256,
+ },
+ )
+ .expect("Failed to derive Ed25519 -> EcdsaP256 BCC");
+ let bcc_handover1 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
+ let bcc_handover1_bytes = to_bcc_handover(&bcc_handover1);
+ buffer.fill(0);
+
+ inputs
+ .clone()
+ .write_next_bcc(
+ &bcc_handover1_bytes,
+ &[0u8; HIDDEN_SIZE],
+ Some([0u8; 64]),
+ true,
+ &mut buffer,
+ DiceContext {
+ authority_algorithm: KeyAlgorithm::EcdsaP256,
+ subject_algorithm: KeyAlgorithm::EcdsaP384,
+ },
+ )
+ .expect("Failed to derive EcdsaP256 -> EcdsaP384 BCC");
+ let bcc_handover2 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
+ let bcc_handover2_bytes = to_bcc_handover(&bcc_handover2);
+ buffer.fill(0);
+
+ inputs
+ .clone()
+ .write_next_bcc(
+ &bcc_handover2_bytes,
+ &[0u8; HIDDEN_SIZE],
+ Some([0u8; 64]),
+ true,
+ &mut buffer,
+ DiceContext {
+ authority_algorithm: KeyAlgorithm::EcdsaP384,
+ subject_algorithm: KeyAlgorithm::Ed25519,
+ },
+ )
+ .expect("Failed to derive EcdsaP384 -> Ed25519 BCC");
+ let _bcc_handover3 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
+
+ // TODO(b/378813154): Check the DICE chain with `hwtrust` once the profile version
+ // is updated.
+ // The check cannot be done now because parsing the chain causes the following error:
+ // Invalid payload at index 3. Caused by:
+ // 0: opendice.example.p256
+ // 1: unknown profile version
+ }
+
+ fn to_bcc_handover(dice_artifacts: &dyn DiceArtifacts) -> Vec<u8> {
+ let dice_chain = cbor_util::deserialize::<Value>(dice_artifacts.bcc().unwrap()).unwrap();
+ let bcc_handover = Value::Map(vec![
+ (Value::Integer(1.into()), Value::Bytes(dice_artifacts.cdi_attest().to_vec())),
+ (Value::Integer(2.into()), Value::Bytes(dice_artifacts.cdi_seal().to_vec())),
+ (Value::Integer(3.into()), dice_chain),
+ ]);
+ cbor_util::serialize(&bcc_handover).unwrap()
+ }
}
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index aeced51..2c1eba9 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -45,7 +45,7 @@
use bssl_avf::Digester;
use core::ops::Range;
use cstr::cstr;
-use diced_open_dice::{bcc_handover_parse, DiceArtifacts, Hidden};
+use diced_open_dice::{bcc_handover_parse, DiceArtifacts, DiceContext, Hidden, VM_KEY_ALGORITHM};
use libfdt::{Fdt, FdtNode};
use log::{debug, error, info, trace, warn};
use pvmfw_avb::verify_payload;
@@ -202,6 +202,13 @@
trace!("BCC leaf subject public key algorithm: {:?}", bcc.leaf_subject_pubkey().cose_alg);
+ let dice_context = DiceContext {
+ authority_algorithm: bcc.leaf_subject_pubkey().cose_alg.try_into().map_err(|e| {
+ error!("{e}");
+ RebootReason::InternalError
+ })?,
+ subject_algorithm: VM_KEY_ALGORITHM,
+ };
dice_inputs
.write_next_bcc(
new_bcc_handover.as_ref(),
@@ -209,6 +216,7 @@
instance_hash,
defer_rollback_protection,
next_bcc,
+ dice_context,
)
.map_err(|e| {
error!("Failed to derive next-stage DICE secrets: {e:?}");