use super::layout::{len, take_v16, v8};
use crate::tls::{error::TlsParseError, types::TlsPskKeyExchangeMode};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PskKeyExchangeModes<'a> {
bytes: &'a [u8],
}
impl<'a> PskKeyExchangeModes<'a> {
pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
Ok(Self { bytes: v8(b, 1)? })
}
pub fn iter(&self) -> impl Iterator<Item = TlsPskKeyExchangeMode> + 'a {
self.bytes.iter().copied().map(TlsPskKeyExchangeMode::new)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ClientPreSharedKey<'a> {
identities: &'a [u8],
binders: &'a [u8],
}
impl<'a> ClientPreSharedKey<'a> {
pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
let (i, rest) = take_v16(b, 7)?;
let (x, rest) = take_v16(rest, 33)?;
if !rest.is_empty() {
return Err(TlsParseError::TrailingBytes);
}
let identity_count = ids_ok(i)?;
let binder_count = binders_ok(x)?;
if identity_count != binder_count {
return Err(TlsParseError::InvalidValue);
}
Ok(Self {
identities: i,
binders: x,
})
}
pub fn identities(&self) -> PskIdentityIter<'a> {
PskIdentityIter {
bytes: self.identities,
}
}
pub fn binders(&self) -> PskBinderIter<'a> {
PskBinderIter {
bytes: self.binders,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PskIdentity<'a> {
identity: &'a [u8],
age: u32,
}
impl<'a> PskIdentity<'a> {
pub const fn identity(self) -> &'a [u8] {
self.identity
}
pub const fn obfuscated_ticket_age(self) -> u32 {
self.age
}
}
#[derive(Clone, Debug)]
pub struct PskIdentityIter<'a> {
bytes: &'a [u8],
}
impl<'a> Iterator for PskIdentityIter<'a> {
type Item = Result<PskIdentity<'a>, TlsParseError>;
fn next(&mut self) -> Option<Self::Item> {
if self.bytes.is_empty() {
return None;
}
match id(self.bytes) {
Ok((x, n)) => {
self.bytes = &self.bytes[n..];
Some(Ok(x))
}
Err(e) => {
self.bytes = &[];
Some(Err(e))
}
}
}
}
fn id(b: &[u8]) -> Result<(PskIdentity<'_>, usize), TlsParseError> {
if b.len() < 6 {
return Err(TlsParseError::Incomplete {
required: 6,
available: b.len(),
});
}
let n = usize::from(u16::from_be_bytes([b[0], b[1]]));
if n == 0 {
return Err(TlsParseError::InvalidValue);
}
if b.len() < n + 6 {
return Err(TlsParseError::Incomplete {
required: n + 6,
available: b.len(),
});
}
Ok((
PskIdentity {
identity: &b[2..n + 2],
age: u32::from_be_bytes([b[n + 2], b[n + 3], b[n + 4], b[n + 5]]),
},
n + 6,
))
}
fn ids_ok(mut b: &[u8]) -> Result<usize, TlsParseError> {
let mut count = 0usize;
while !b.is_empty() {
let (_, n) = id(b)?;
b = &b[n..];
count += 1;
}
Ok(count)
}
#[derive(Clone, Debug)]
pub struct PskBinderIter<'a> {
bytes: &'a [u8],
}
impl<'a> Iterator for PskBinderIter<'a> {
type Item = Result<&'a [u8], TlsParseError>;
fn next(&mut self) -> Option<Self::Item> {
if self.bytes.is_empty() {
return None;
}
let n = usize::from(self.bytes[0]);
if n < 32 {
self.bytes = &[];
return Some(Err(TlsParseError::InvalidValue));
}
if self.bytes.len() < n + 1 {
let available = self.bytes.len();
self.bytes = &[];
return Some(Err(TlsParseError::Incomplete {
required: n + 1,
available,
}));
}
let x = &self.bytes[1..n + 1];
self.bytes = &self.bytes[n + 1..];
Some(Ok(x))
}
}
fn binders_ok(mut b: &[u8]) -> Result<usize, TlsParseError> {
let mut count = 0usize;
while !b.is_empty() {
let n = usize::from(b[0]);
if n < 32 {
return Err(TlsParseError::InvalidValue);
}
if b.len() < n + 1 {
return Err(TlsParseError::Incomplete {
required: n + 1,
available: b.len(),
});
}
b = &b[n + 1..];
count += 1;
}
Ok(count)
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ServerPreSharedKey(u16);
impl ServerPreSharedKey {
pub(super) fn parse(b: &[u8]) -> Result<Self, TlsParseError> {
if b.len() != 2 {
return Err(len(2, b.len()));
}
Ok(Self(u16::from_be_bytes([b[0], b[1]])))
}
pub const fn selected_identity(self) -> u16 {
self.0
}
}