1 use anyhow::Result;
2 use openssl::x509::X509;
3 use std::{collections::HashMap, fmt};
4
5 use crate::dice::ChainForm;
6
7 /// The CSR V2 payload that is encrypted with an Endpoint Encryption Key (EEK).
8 #[derive(Clone, Eq, PartialEq)]
9 pub struct ProtectedData {
10 mac_key: Vec<u8>,
11 dice_chain: ChainForm,
12 uds_certs: Option<UdsCerts>,
13 }
14
15 #[derive(Clone, Debug, Default, Eq, PartialEq)]
16 pub struct UdsCerts(pub(crate) HashMap<String, UdsCertsEntry>);
17
18 /// Represent entries in the UDS certs mapping as an enum to support special cases in the future
19 /// where the input is not actually x.509 certs.
20 #[derive(Clone, Eq, PartialEq)]
21 pub enum UdsCertsEntry {
22 /// A chain of X.509 certificates that certify the UDS
23 X509Chain(Vec<Vec<u8>>),
24 }
25
26 impl ProtectedData {
27 /// Constructs a new `ProtectedData` with a MAC key, DICE chain, and optional UDS certificates.
new(mac_key: Vec<u8>, dice_chain: ChainForm, uds_certs: Option<UdsCerts>) -> Self28 pub fn new(mac_key: Vec<u8>, dice_chain: ChainForm, uds_certs: Option<UdsCerts>) -> Self {
29 Self { mac_key, dice_chain, uds_certs }
30 }
31
32 /// Returns the DICE chain.
dice_chain(&self) -> ChainForm33 pub fn dice_chain(&self) -> ChainForm {
34 self.dice_chain.clone()
35 }
36
37 /// Returns the UDS certificates.
uds_certs(&self) -> Option<UdsCerts>38 pub fn uds_certs(&self) -> Option<UdsCerts> {
39 self.uds_certs.clone()
40 }
41 }
42
43 impl UdsCerts {
new() -> Self44 pub fn new() -> Self {
45 Self(HashMap::new())
46 }
47 }
48
49 impl UdsCertsEntry {
new_x509_chain(der_encoded_chain: Vec<Vec<u8>>) -> Result<Self>50 pub(crate) fn new_x509_chain(der_encoded_chain: Vec<Vec<u8>>) -> Result<Self> {
51 Ok(Self::X509Chain(der_encoded_chain))
52 }
53 }
54
55 impl fmt::Debug for ProtectedData {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result56 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
57 fmt.debug_struct("ProtectedData")
58 .field("mac_key", &hex::encode(&self.mac_key))
59 .field("dice_chain", &self.dice_chain)
60 .field("uds_certs", &self.uds_certs)
61 .finish()
62 }
63 }
64
65 impl fmt::Debug for UdsCertsEntry {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result66 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
67 match self {
68 Self::X509Chain(v) => format_x509_chain(fmt, v),
69 }
70 }
71 }
72
format_x509_chain(fmt: &mut fmt::Formatter, chain: &Vec<Vec<u8>>) -> fmt::Result73 fn format_x509_chain(fmt: &mut fmt::Formatter, chain: &Vec<Vec<u8>>) -> fmt::Result {
74 for c in chain {
75 fmt.write_str(&x509_der_to_pem(c).unwrap_or("[INVALID CERTIFICATE]".to_string()))?;
76 }
77 Ok(())
78 }
79
x509_der_to_pem(der: &[u8]) -> Result<String>80 fn x509_der_to_pem(der: &[u8]) -> Result<String> {
81 let utf8 = X509::from_der(der)?.to_pem()?;
82 Ok(std::str::from_utf8(&utf8)?.to_string())
83 }
84