Read the algorithm of the leaf public key in DICE chain in pvmfw
The leaf key algorithm will be used to select the authority key
algorithm in the multi-algorithm DICE handover derivation.
Bug: 357008987
Test: atest MicrodroidHostTests
Change-Id: I7cb93167cb97a7831fd26a2ffbf4cff6bc5748e1
diff --git a/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index 4586cca..a5b7494 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -16,6 +16,7 @@
"libcbor_util_nostd",
"libciborium_nostd",
"libciborium_io_nostd",
+ "libcoset_nostd",
"libcstr",
"libdiced_open_dice_nostd",
"liblibfdt_nostd",
diff --git a/guest/pvmfw/src/bcc.rs b/guest/pvmfw/src/bcc.rs
index 5317ce9..9260d7f 100644
--- a/guest/pvmfw/src/bcc.rs
+++ b/guest/pvmfw/src/bcc.rs
@@ -21,6 +21,7 @@
use ciborium::value::Value;
use core::fmt;
use core::mem::size_of;
+use coset::{iana, Algorithm, CborSerializable, CoseKey};
use diced_open_dice::{BccHandover, Cdi, DiceArtifacts, DiceMode};
use log::trace;
@@ -29,16 +30,24 @@
pub enum BccError {
CborDecodeError,
CborEncodeError,
+ CosetError(coset::CoseError),
DiceError(diced_open_dice::DiceError),
MalformedBcc(&'static str),
MissingBcc,
}
+impl From<coset::CoseError> for BccError {
+ fn from(e: coset::CoseError) -> Self {
+ Self::CosetError(e)
+ }
+}
+
impl fmt::Display for BccError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::CborDecodeError => write!(f, "Error parsing BCC CBOR"),
Self::CborEncodeError => write!(f, "Error encoding BCC CBOR"),
+ Self::CosetError(e) => write!(f, "Encountered an error with coset: {e}"),
Self::DiceError(e) => write!(f, "Dice error: {e:?}"),
Self::MalformedBcc(s) => {
write!(f, "BCC does not have the expected CBOR structure: {s}")
@@ -84,6 +93,7 @@
/// Represents a (partially) decoded BCC DICE chain.
pub struct Bcc {
is_debug_mode: bool,
+ leaf_subject_pubkey: PublicKey,
}
impl Bcc {
@@ -117,12 +127,18 @@
.collect::<Result<Vec<_>>>()?;
let is_debug_mode = is_any_payload_debug_mode(&payloads)?;
- Ok(Self { is_debug_mode })
+ // Safe to unwrap because we checked the length above.
+ let leaf_subject_pubkey = payloads.last().unwrap().subject_public_key()?;
+ Ok(Self { is_debug_mode, leaf_subject_pubkey })
}
pub fn is_debug_mode(&self) -> bool {
self.is_debug_mode
}
+
+ pub fn leaf_subject_pubkey(&self) -> &PublicKey {
+ &self.leaf_subject_pubkey
+ }
}
fn is_any_payload_debug_mode(payloads: &[BccPayload]) -> Result<bool> {
@@ -144,6 +160,13 @@
#[repr(transparent)]
struct BccPayload(Value);
+#[derive(Debug, Clone)]
+pub struct PublicKey {
+ /// The COSE key algorithm for the public key, representing the value of the `alg`
+ /// field in the COSE key format of the public key. See RFC 8152, section 7 for details.
+ pub cose_alg: iana::Algorithm,
+}
+
impl BccEntry {
pub fn new(entry: Value) -> Self {
Self(entry)
@@ -178,6 +201,7 @@
const KEY_MODE: i32 = -4670551;
const MODE_DEBUG: u8 = DiceMode::kDiceModeDebug as u8;
+const SUBJECT_PUBLIC_KEY: i32 = -4670552;
impl BccPayload {
pub fn is_debug_mode(&self) -> Result<bool> {
@@ -204,6 +228,21 @@
Ok(mode == MODE_DEBUG.into())
}
+ fn subject_public_key(&self) -> Result<PublicKey> {
+ // BccPayload = { ; CWT [RFC8392]
+ // ...
+ // -4670552 : bstr .cbor PubKeyEd25519 /
+ // bstr .cbor PubKeyECDSA256 /
+ // bstr .cbor PubKeyECDSA384, ; Subject Public Key
+ // ...
+ // }
+ self.value_from_key(SUBJECT_PUBLIC_KEY)
+ .ok_or(BccError::MalformedBcc("Subject public key missing"))?
+ .as_bytes()
+ .ok_or(BccError::MalformedBcc("Subject public key is not a byte string"))
+ .and_then(|v| PublicKey::from_slice(v))
+ }
+
fn value_from_key(&self, key: i32) -> Option<&Value> {
// BccPayload is just a map; we only use integral keys, but in general it's legitimate
// for other things to be present, or for the key we care about not to be present.
@@ -218,3 +257,13 @@
None
}
}
+
+impl PublicKey {
+ fn from_slice(slice: &[u8]) -> Result<Self> {
+ let key = CoseKey::from_slice(slice)?;
+ let Some(Algorithm::Assigned(cose_alg)) = key.alg else {
+ return Err(BccError::MalformedBcc("Invalid algorithm in public key"));
+ };
+ Ok(Self { cose_alg })
+ }
+}
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index 1e88c4b..aeced51 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -200,6 +200,8 @@
Cow::Owned(truncated_bcc_handover)
};
+ trace!("BCC leaf subject public key algorithm: {:?}", bcc.leaf_subject_pubkey().cose_alg);
+
dice_inputs
.write_next_bcc(
new_bcc_handover.as_ref(),