1 use anyhow::Result;
2 use openssl::x509::X509;
3 use std::{collections::HashMap, fmt};
4
5 use crate::dice::ChainForm;
6
7 #[derive(Clone, Eq, PartialEq)]
8 pub struct ProtectedData {
9 mac_key: Vec<u8>,
10 dice_chain: ChainForm,
11 uds_certs: Option<UdsCerts>,
12 }
13
14 #[derive(Clone, Debug, Default, Eq, PartialEq)]
15 pub struct UdsCerts(pub(crate) HashMap<String, UdsCertsEntry>);
16
17 /// Represent entries in the UDS certs mapping as an enum to support special cases in the future
18 /// where the input is not actually x.509 certs.
19 #[derive(Clone, Eq, PartialEq)]
20 pub enum UdsCertsEntry {
21 /// A chain of X.509 certificates that certify the UDS
22 X509Chain(Vec<Vec<u8>>),
23 }
24
25 impl ProtectedData {
new(mac_key: Vec<u8>, dice_chain: ChainForm, uds_certs: Option<UdsCerts>) -> Self26 pub fn new(mac_key: Vec<u8>, dice_chain: ChainForm, uds_certs: Option<UdsCerts>) -> Self {
27 Self { mac_key, dice_chain, uds_certs }
28 }
29
dice_chain(&self) -> ChainForm30 pub fn dice_chain(&self) -> ChainForm {
31 self.dice_chain.clone()
32 }
33 }
34
35 impl UdsCerts {
new() -> Self36 pub fn new() -> Self {
37 Self(HashMap::new())
38 }
39 }
40
41 impl UdsCertsEntry {
new_x509_chain(der_encoded_chain: Vec<Vec<u8>>) -> Result<Self>42 pub(crate) fn new_x509_chain(der_encoded_chain: Vec<Vec<u8>>) -> Result<Self> {
43 Ok(Self::X509Chain(der_encoded_chain))
44 }
45 }
46
47 impl fmt::Debug for ProtectedData {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result48 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
49 fmt.debug_struct("ProtectedData")
50 .field("mac_key", &hex::encode(&self.mac_key))
51 .field("dice_chain", &self.dice_chain)
52 .field("uds_certs", &self.uds_certs)
53 .finish()
54 }
55 }
56
57 impl fmt::Debug for UdsCertsEntry {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result58 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
59 match self {
60 Self::X509Chain(v) => format_x509_chain(fmt, v),
61 }
62 }
63 }
64
format_x509_chain(fmt: &mut fmt::Formatter, chain: &Vec<Vec<u8>>) -> fmt::Result65 fn format_x509_chain(fmt: &mut fmt::Formatter, chain: &Vec<Vec<u8>>) -> fmt::Result {
66 for c in chain {
67 fmt.write_str(&x509_der_to_pem(c).unwrap_or("[INVALID CERTIFICATE]".to_string()))?;
68 }
69 Ok(())
70 }
71
x509_der_to_pem(der: &[u8]) -> Result<String>72 fn x509_der_to_pem(der: &[u8]) -> Result<String> {
73 let utf8 = X509::from_der(der)?.to_pem()?;
74 Ok(std::str::from_utf8(&utf8)?.to_string())
75 }
76