blob: b77b777bd3c31ed3b893f3927c8f3293b4adfc8a [file] [log] [blame]
use ciborium::de::Error as CbError;
use coset::cbor::value::Value;
#[cfg(feature = "builtin-bcc")]
use coset::AsCborValue;
use coset::CoseError;
#[cfg(feature = "builtin-bcc")]
use kmr_wire::read_to_value;
pub mod cdi;
pub mod cwt;
pub mod dice;
pub mod gsc;
pub mod pub_key;
use crate::cdi::ConfigurationDescriptor;
use crate::dice::CdiCert;
use crate::dice::DiceHandover;
use crate::gsc::GscBootParams;
use crate::pub_key::SubjectPublicKey;
#[derive(Debug)]
pub enum Error {
NotAvailable,
}
#[allow(dead_code)]
pub struct BootParams {
pub dice: DiceHandover,
pub gsc_boot_params: GscBootParams,
}
impl Default for BootParams {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "builtin-bcc")]
const BOOT_PARAM_KEY: i32 = 2;
#[cfg(feature = "builtin-bcc")]
const DICE_KEY: i32 = 3;
#[allow(dead_code)]
impl BootParams {
/// Create a boot params struct from constant data.
#[cfg(feature = "builtin-bcc")]
pub fn new() -> Self {
let data = desktop_test_data::boot::BOOT_PARAM;
let data = read_to_value(data).unwrap();
let data = data.as_map().unwrap();
let dice = find_in_cbor_map(data, Value::Integer(DICE_KEY.into())).unwrap();
let dice = DiceHandover::from_cbor_value(dice.clone()).unwrap();
let gsc_boot_params =
find_in_cbor_map(data, Value::Integer(BOOT_PARAM_KEY.into())).unwrap();
let gsc_boot_params = GscBootParams::from_cbor_value(gsc_boot_params.clone()).unwrap();
Self { dice, gsc_boot_params }
}
#[cfg(not(feature = "builtin-bcc"))]
pub fn new() -> Self {
Self { dice: DiceHandover::default(), gsc_boot_params: GscBootParams::default() }
}
/// Returns the UDS public key for the device.
pub fn get_uds_public_key(&self) -> Result<&SubjectPublicKey, Error> {
Ok(&self.dice.uds_pubkey)
}
/// Returns the AP firmware CDI.
pub fn get_ap_fw_cdi(&self) -> Result<&ConfigurationDescriptor, Error> {
Ok(&self.dice.cdi_cert.cwt.cfg_descr)
}
/// Returns the attestation CDI certificate.
pub fn get_attestation_cdi_certificate(&self) -> Result<&CdiCert, Error> {
Ok(&self.dice.cdi_cert)
}
/// Returns the CDI keypair as a tuple (attest, seal).
fn get_cdi_keypair(&self) -> Result<(&[u8], &[u8]), Error> {
Ok((&self.dice.cdi_attest, &self.dice.cdi_seal))
}
}
/// Find a value in a CBOR map for the given key.
fn find_in_cbor_map(map: &[(Value, Value)], target: Value) -> coset::Result<&Value> {
for (key, val) in map.iter() {
if *key == target {
return Ok(val);
}
}
Err(CoseError::DecodeFailed(CbError::Syntax(0)))
}
/// Find a value in a CBOR map for the given key and attempt to parse it as an int.
fn get_cbor_int_from_map<T: std::convert::TryFrom<ciborium::value::Integer>>(
map: &[(Value, Value)],
key: i32,
) -> coset::Result<T> {
find_in_cbor_map(map, Value::Integer(key.into()))?
.as_integer()
.ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))?
.try_into()
.map_err(|_| CoseError::DecodeFailed(CbError::Syntax(0)))
}
/// Find a value in a CBOR map for the given key and attempt to parse it as a map.
fn get_cbor_array_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&Vec<Value>> {
find_in_cbor_map(map, Value::Integer(key.into()))?
.as_array()
.ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))
}
/// Find a value in a CBOR map for the given key and attempt to parse it as a Vec<u8>.
fn get_cbor_bytes_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&Vec<u8>> {
find_in_cbor_map(map, Value::Integer(key.into()))?
.as_bytes()
.ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))
}
/// Find a value in a CBOR map for the given key and attempt to parse it as a str.
fn get_cbor_string_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&str> {
find_in_cbor_map(map, Value::Integer(key.into()))?
.as_text()
.ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))
}
#[cfg(test)]
mod tests {
use super::*;
use coset::AsCborValue;
use kmr_wire::read_to_value;
test::init!();
#[test]
fn boot_params_test() {
let data = desktop_test_data::boot::BOOT_PARAM;
let data = read_to_value(data).unwrap();
let data = data.as_map().unwrap();
let dice = find_in_cbor_map(data, Value::Integer(2.into())).unwrap();
let _ = DiceHandover::from_cbor_value(dice.clone()).unwrap();
let gsc_boot_params = find_in_cbor_map(data, Value::Integer(3.into())).unwrap();
let _ = GscBootParams::from_cbor_value(gsc_boot_params.clone()).unwrap();
}
}