use crate::ProtocolError; use crate::buffer::CryptoBuffer; use crate::extensions::messages::CertificateExtension; use crate::parse_buffer::ParseBuffer; use heapless::Vec; #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CertificateRef<'a> { raw_entries: &'a [u8], request_context: &'a [u8], pub entries: Vec, 16>, } impl<'a> CertificateRef<'a> { pub fn with_context(request_context: &'a [u8]) -> Self { Self { raw_entries: &[], request_context, entries: Vec::new(), } } pub fn add(&mut self, entry: CertificateEntryRef<'a>) -> Result<(), ProtocolError> { self.entries.push(entry).map_err(|_| { error!("CertificateRef: InsufficientSpace"); ProtocolError::InsufficientSpace }) } pub fn parse(buf: &mut ParseBuffer<'a>) -> Result { let request_context_len = buf.read_u8().map_err(|_| ProtocolError::InvalidCertificate)?; let request_context = buf .slice(request_context_len as usize) .map_err(|_| ProtocolError::InvalidCertificate)?; let entries_len = buf.read_u24().map_err(|_| ProtocolError::InvalidCertificate)?; let mut raw_entries = buf .slice(entries_len as usize) .map_err(|_| ProtocolError::InvalidCertificate)?; let entries = CertificateEntryRef::parse_vector(&mut raw_entries)?; Ok(Self { raw_entries: raw_entries.as_slice(), request_context: request_context.as_slice(), entries, }) } pub(crate) fn encode(&self, buf: &mut CryptoBuffer<'_>) -> Result<(), ProtocolError> { buf.with_u8_length(|buf| buf.extend_from_slice(self.request_context))?; buf.with_u24_length(|buf| { for entry in &self.entries { entry.encode(buf)?; } Ok(()) })?; Ok(()) } } #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum CertificateEntryRef<'a> { X509(&'a [u8]), RawPublicKey(&'a [u8]), } impl<'a> CertificateEntryRef<'a> { pub fn parse(buf: &mut ParseBuffer<'a>) -> Result { let entry_len = buf .read_u24() .map_err(|_| ProtocolError::InvalidCertificateEntry)?; let cert = buf .slice(entry_len as usize) .map_err(|_| ProtocolError::InvalidCertificateEntry)?; let entry = CertificateEntryRef::X509(cert.as_slice()); CertificateExtension::parse_vector::<2>(buf)?; Ok(entry) } pub fn parse_vector( buf: &mut ParseBuffer<'a>, ) -> Result, ProtocolError> { let mut result = Vec::new(); while !buf.is_empty() { result .push(Self::parse(buf)?) .map_err(|_| ProtocolError::DecodeError)?; } Ok(result) } pub(crate) fn encode(&self, buf: &mut CryptoBuffer<'_>) -> Result<(), ProtocolError> { match *self { CertificateEntryRef::RawPublicKey(_key) => { todo!("ASN1_subjectPublicKeyInfo encoding?"); } CertificateEntryRef::X509(cert) => { buf.with_u24_length(|buf| buf.extend_from_slice(cert))?; } } buf.push_u16(0)?; Ok(()) } } impl<'a, D: AsRef<[u8]>> From<&'a crate::config::Certificate> for CertificateEntryRef<'a> { fn from(cert: &'a crate::config::Certificate) -> Self { match cert { crate::config::Certificate::X509(data) => CertificateEntryRef::X509(data.as_ref()), crate::config::Certificate::RawPublicKey(data) => { CertificateEntryRef::RawPublicKey(data.as_ref()) } } } } #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Certificate { request_context: Vec, entries_data: Vec, } impl Certificate { pub fn request_context(&self) -> &[u8] { &self.request_context[..] } } impl<'a, const N: usize> TryFrom> for Certificate { type Error = ProtocolError; fn try_from(cert: CertificateRef<'a>) -> Result { let mut request_context = Vec::new(); request_context .extend_from_slice(cert.request_context) .map_err(|_| ProtocolError::OutOfMemory)?; let mut entries_data = Vec::new(); entries_data .extend_from_slice(cert.raw_entries) .map_err(|_| ProtocolError::OutOfMemory)?; Ok(Self { request_context, entries_data, }) } } impl<'a, const N: usize> TryFrom<&'a Certificate> for CertificateRef<'a> { type Error = ProtocolError; fn try_from(cert: &'a Certificate) -> Result { let request_context = cert.request_context(); let entries = CertificateEntryRef::parse_vector(&mut ParseBuffer::from(&cert.entries_data[..]))?; Ok(Self { raw_entries: &cert.entries_data[..], request_context, entries, }) } }