1 use ciborium::de::Error as CbError;
2 use coset::cbor::value::Value;
3 #[cfg(feature = "builtin-bcc")]
4 use coset::AsCborValue;
5 use coset::CoseError;
6 #[cfg(feature = "builtin-bcc")]
7 use kmr_wire::read_to_value;
8
9 pub mod cdi;
10 pub mod cwt;
11 pub mod dice;
12 pub mod gsc;
13 pub mod pub_key;
14
15 use crate::cdi::ConfigurationDescriptor;
16 use crate::dice::CdiCert;
17 use crate::dice::DiceHandover;
18 use crate::gsc::GscBootParams;
19 use crate::pub_key::SubjectPublicKey;
20
21 #[derive(Debug)]
22 pub enum Error {
23 NotAvailable,
24 }
25
26 #[allow(dead_code)]
27 pub struct BootParams {
28 pub dice: DiceHandover,
29 pub gsc_boot_params: GscBootParams,
30 }
31
32 impl Default for BootParams {
default() -> Self33 fn default() -> Self {
34 Self::new()
35 }
36 }
37
38 #[cfg(feature = "builtin-bcc")]
39 const BOOT_PARAM_KEY: i32 = 2;
40 #[cfg(feature = "builtin-bcc")]
41 const DICE_KEY: i32 = 3;
42
43 #[allow(dead_code)]
44 impl BootParams {
45 /// Create a boot params struct from constant data.
46 #[cfg(feature = "builtin-bcc")]
new() -> Self47 pub fn new() -> Self {
48 let data = desktop_test_data::boot::BOOT_PARAM;
49 let data = read_to_value(data).unwrap();
50 let data = data.as_map().unwrap();
51
52 let dice = find_in_cbor_map(data, Value::Integer(DICE_KEY.into())).unwrap();
53 let dice = DiceHandover::from_cbor_value(dice.clone()).unwrap();
54
55 let gsc_boot_params =
56 find_in_cbor_map(data, Value::Integer(BOOT_PARAM_KEY.into())).unwrap();
57 let gsc_boot_params = GscBootParams::from_cbor_value(gsc_boot_params.clone()).unwrap();
58
59 Self { dice, gsc_boot_params }
60 }
61
62 #[cfg(not(feature = "builtin-bcc"))]
new() -> Self63 pub fn new() -> Self {
64 Self { dice: DiceHandover::default(), gsc_boot_params: GscBootParams::default() }
65 }
66
67 /// Returns the UDS public key for the device.
get_uds_public_key(&self) -> Result<&SubjectPublicKey, Error>68 pub fn get_uds_public_key(&self) -> Result<&SubjectPublicKey, Error> {
69 Ok(&self.dice.uds_pubkey)
70 }
71
72 /// Returns the AP firmware CDI.
get_ap_fw_cdi(&self) -> Result<&ConfigurationDescriptor, Error>73 pub fn get_ap_fw_cdi(&self) -> Result<&ConfigurationDescriptor, Error> {
74 Ok(&self.dice.cdi_cert.cwt.cfg_descr)
75 }
76
77 /// Returns the attestation CDI certificate.
get_attestation_cdi_certificate(&self) -> Result<&CdiCert, Error>78 pub fn get_attestation_cdi_certificate(&self) -> Result<&CdiCert, Error> {
79 Ok(&self.dice.cdi_cert)
80 }
81
82 /// Returns the CDI keypair as a tuple (attest, seal).
get_cdi_keypair(&self) -> Result<(&[u8], &[u8]), Error>83 fn get_cdi_keypair(&self) -> Result<(&[u8], &[u8]), Error> {
84 Ok((&self.dice.cdi_attest, &self.dice.cdi_seal))
85 }
86 }
87
88 /// Find a value in a CBOR map for the given key.
find_in_cbor_map(map: &[(Value, Value)], target: Value) -> coset::Result<&Value>89 fn find_in_cbor_map(map: &[(Value, Value)], target: Value) -> coset::Result<&Value> {
90 for (key, val) in map.iter() {
91 if *key == target {
92 return Ok(val);
93 }
94 }
95 Err(CoseError::DecodeFailed(CbError::Syntax(0)))
96 }
97
98 /// Find a value in a CBOR map for the given key and attempt to parse it as an int.
get_cbor_int_from_map<T: std::convert::TryFrom<ciborium::value::Integer>>( map: &[(Value, Value)], key: i32, ) -> coset::Result<T>99 fn get_cbor_int_from_map<T: std::convert::TryFrom<ciborium::value::Integer>>(
100 map: &[(Value, Value)],
101 key: i32,
102 ) -> coset::Result<T> {
103 find_in_cbor_map(map, Value::Integer(key.into()))?
104 .as_integer()
105 .ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))?
106 .try_into()
107 .map_err(|_| CoseError::DecodeFailed(CbError::Syntax(0)))
108 }
109
110 /// Find a value in a CBOR map for the given key and attempt to parse it as a map.
get_cbor_array_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&Vec<Value>>111 fn get_cbor_array_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&Vec<Value>> {
112 find_in_cbor_map(map, Value::Integer(key.into()))?
113 .as_array()
114 .ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))
115 }
116
117 /// Find a value in a CBOR map for the given key and attempt to parse it as a Vec<u8>.
get_cbor_bytes_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&Vec<u8>>118 fn get_cbor_bytes_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&Vec<u8>> {
119 find_in_cbor_map(map, Value::Integer(key.into()))?
120 .as_bytes()
121 .ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))
122 }
123
124 /// Find a value in a CBOR map for the given key and attempt to parse it as a str.
get_cbor_string_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&str>125 fn get_cbor_string_from_map(map: &[(Value, Value)], key: i32) -> coset::Result<&str> {
126 find_in_cbor_map(map, Value::Integer(key.into()))?
127 .as_text()
128 .ok_or(CoseError::DecodeFailed(CbError::Syntax(0)))
129 }
130
131 #[cfg(test)]
132 mod tests {
133 use super::*;
134 use coset::AsCborValue;
135 use kmr_wire::read_to_value;
136
137 test::init!();
138
139 #[test]
boot_params_test()140 fn boot_params_test() {
141 let data = desktop_test_data::boot::BOOT_PARAM;
142 let data = read_to_value(data).unwrap();
143 let data = data.as_map().unwrap();
144
145 let dice = find_in_cbor_map(data, Value::Integer(2.into())).unwrap();
146 let _ = DiceHandover::from_cbor_value(dice.clone()).unwrap();
147
148 let gsc_boot_params = find_in_cbor_map(data, Value::Integer(3.into())).unwrap();
149 let _ = GscBootParams::from_cbor_value(gsc_boot_params.clone()).unwrap();
150 }
151 }
152