embedded_tls/handshake/
certificate.rs1use crate::TlsError;
2use crate::buffer::CryptoBuffer;
3use crate::extensions::messages::CertificateExtension;
4use crate::parse_buffer::ParseBuffer;
5use heapless::Vec;
6
7#[derive(Debug)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub struct CertificateRef<'a> {
10 raw_entries: &'a [u8],
11 request_context: &'a [u8],
12
13 pub entries: Vec<CertificateEntryRef<'a>, 16>,
14}
15
16impl<'a> CertificateRef<'a> {
17 pub fn with_context(request_context: &'a [u8]) -> Self {
18 Self {
19 raw_entries: &[],
20 request_context,
21 entries: Vec::new(),
22 }
23 }
24
25 pub fn add(&mut self, entry: CertificateEntryRef<'a>) -> Result<(), TlsError> {
26 self.entries.push(entry).map_err(|_| {
27 error!("CertificateRef: InsufficientSpace");
28 TlsError::InsufficientSpace
29 })
30 }
31
32 pub fn parse(buf: &mut ParseBuffer<'a>) -> Result<Self, TlsError> {
33 let request_context_len = buf.read_u8().map_err(|_| TlsError::InvalidCertificate)?;
34 let request_context = buf
35 .slice(request_context_len as usize)
36 .map_err(|_| TlsError::InvalidCertificate)?;
37 let entries_len = buf.read_u24().map_err(|_| TlsError::InvalidCertificate)?;
38 let mut raw_entries = buf
39 .slice(entries_len as usize)
40 .map_err(|_| TlsError::InvalidCertificate)?;
41
42 let entries = CertificateEntryRef::parse_vector(&mut raw_entries)?;
43
44 Ok(Self {
45 raw_entries: raw_entries.as_slice(),
46 request_context: request_context.as_slice(),
47 entries,
48 })
49 }
50
51 pub(crate) fn encode(&self, buf: &mut CryptoBuffer<'_>) -> Result<(), TlsError> {
52 buf.with_u8_length(|buf| buf.extend_from_slice(self.request_context))?;
53 buf.with_u24_length(|buf| {
54 for entry in &self.entries {
55 entry.encode(buf)?;
56 }
57 Ok(())
58 })?;
59
60 Ok(())
61 }
62}
63
64#[derive(Debug)]
65#[cfg_attr(feature = "defmt", derive(defmt::Format))]
66pub enum CertificateEntryRef<'a> {
67 X509(&'a [u8]),
68 RawPublicKey(&'a [u8]),
69}
70
71impl<'a> CertificateEntryRef<'a> {
72 pub fn parse(buf: &mut ParseBuffer<'a>) -> Result<Self, TlsError> {
73 let entry_len = buf
74 .read_u24()
75 .map_err(|_| TlsError::InvalidCertificateEntry)?;
76 let cert = buf
77 .slice(entry_len as usize)
78 .map_err(|_| TlsError::InvalidCertificateEntry)?;
79
80 let entry = CertificateEntryRef::X509(cert.as_slice());
81
82 CertificateExtension::parse_vector::<2>(buf)?;
84
85 Ok(entry)
86 }
87
88 pub fn parse_vector<const N: usize>(
89 buf: &mut ParseBuffer<'a>,
90 ) -> Result<Vec<Self, N>, TlsError> {
91 let mut result = Vec::new();
92
93 while !buf.is_empty() {
94 result
95 .push(Self::parse(buf)?)
96 .map_err(|_| TlsError::DecodeError)?;
97 }
98
99 Ok(result)
100 }
101
102 pub(crate) fn encode(&self, buf: &mut CryptoBuffer<'_>) -> Result<(), TlsError> {
103 match *self {
104 CertificateEntryRef::RawPublicKey(_key) => {
105 todo!("ASN1_subjectPublicKeyInfo encoding?");
106 }
108 CertificateEntryRef::X509(cert) => {
109 buf.with_u24_length(|buf| buf.extend_from_slice(cert))?;
110 }
111 }
112
113 buf.push_u16(0)?;
115 Ok(())
116 }
117}
118
119impl<'a, D: AsRef<[u8]>> From<&'a crate::config::Certificate<D>> for CertificateEntryRef<'a> {
120 fn from(cert: &'a crate::config::Certificate<D>) -> Self {
121 match cert {
122 crate::config::Certificate::X509(data) => CertificateEntryRef::X509(data.as_ref()),
123 crate::config::Certificate::RawPublicKey(data) => {
124 CertificateEntryRef::RawPublicKey(data.as_ref())
125 }
126 }
127 }
128}
129
130#[derive(Debug)]
131#[cfg_attr(feature = "defmt", derive(defmt::Format))]
132pub struct Certificate<const N: usize> {
133 request_context: Vec<u8, 256>,
134 entries_data: Vec<u8, N>,
135}
136
137impl<const N: usize> Certificate<N> {
138 pub fn request_context(&self) -> &[u8] {
139 &self.request_context[..]
140 }
141}
142
143impl<'a, const N: usize> TryFrom<CertificateRef<'a>> for Certificate<N> {
144 type Error = TlsError;
145 fn try_from(cert: CertificateRef<'a>) -> Result<Self, Self::Error> {
146 let mut request_context = Vec::new();
147 request_context
148 .extend_from_slice(cert.request_context)
149 .map_err(|_| TlsError::OutOfMemory)?;
150 let mut entries_data = Vec::new();
151 entries_data
152 .extend_from_slice(cert.raw_entries)
153 .map_err(|_| TlsError::OutOfMemory)?;
154
155 Ok(Self {
156 request_context,
157 entries_data,
158 })
159 }
160}
161
162impl<'a, const N: usize> TryFrom<&'a Certificate<N>> for CertificateRef<'a> {
163 type Error = TlsError;
164 fn try_from(cert: &'a Certificate<N>) -> Result<Self, Self::Error> {
165 let request_context = cert.request_context();
166 let entries =
167 CertificateEntryRef::parse_vector(&mut ParseBuffer::from(&cert.entries_data[..]))?;
168 Ok(Self {
169 raw_entries: &cert.entries_data[..],
170 request_context,
171 entries,
172 })
173 }
174}