Init
This commit is contained in:
174
src/handshake/certificate.rs
Normal file
174
src/handshake/certificate.rs
Normal file
@@ -0,0 +1,174 @@
|
||||
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<CertificateEntryRef<'a>, 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<Self, ProtocolError> {
|
||||
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<Self, ProtocolError> {
|
||||
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());
|
||||
|
||||
// Validate extensions
|
||||
CertificateExtension::parse_vector::<2>(buf)?;
|
||||
|
||||
Ok(entry)
|
||||
}
|
||||
|
||||
pub fn parse_vector<const N: usize>(
|
||||
buf: &mut ParseBuffer<'a>,
|
||||
) -> Result<Vec<Self, N>, 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?");
|
||||
// buf.with_u24_length(|buf| buf.extend_from_slice(key))?;
|
||||
}
|
||||
CertificateEntryRef::X509(cert) => {
|
||||
buf.with_u24_length(|buf| buf.extend_from_slice(cert))?;
|
||||
}
|
||||
}
|
||||
|
||||
// Zero extensions for now
|
||||
buf.push_u16(0)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, D: AsRef<[u8]>> From<&'a crate::config::Certificate<D>> for CertificateEntryRef<'a> {
|
||||
fn from(cert: &'a crate::config::Certificate<D>) -> 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<const N: usize> {
|
||||
request_context: Vec<u8, 256>,
|
||||
entries_data: Vec<u8, N>,
|
||||
}
|
||||
|
||||
impl<const N: usize> Certificate<N> {
|
||||
pub fn request_context(&self) -> &[u8] {
|
||||
&self.request_context[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize> TryFrom<CertificateRef<'a>> for Certificate<N> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(cert: CertificateRef<'a>) -> Result<Self, Self::Error> {
|
||||
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<N>> for CertificateRef<'a> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(cert: &'a Certificate<N>) -> Result<Self, Self::Error> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user