use crate::{
Buf,
BufError::{self},
BufMut, BufResult, Codec, Cursor,
tls::{LengthPrefix, ProtocolVersion, TlsVec, u24},
tls1_0::CipherSuite,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum HandshakeType {
HelloRequest = 0,
ClientHello = 1,
ServerHello = 2,
Certificate = 11,
ServerKeyExchange = 12,
CertificateRequest = 13,
ServerHelloDone = 14,
CertificateVerify = 15,
ClientKeyExchange = 16,
Finished = 20,
}
impl Codec for HandshakeType {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
(*self as u8).encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
match u8::decode(reader, ())? {
x if x == (Self::HelloRequest as u8) => Ok(Self::HelloRequest),
x if x == (Self::ClientHello as u8) => Ok(Self::ClientHello),
x if x == (Self::ServerHello as u8) => Ok(Self::ServerHello),
x if x == (Self::Certificate as u8) => Ok(Self::Certificate),
x if x == (Self::ServerKeyExchange as u8) => Ok(Self::ServerKeyExchange),
x if x == (Self::CertificateRequest as u8) => Ok(Self::CertificateRequest),
x if x == (Self::ServerHelloDone as u8) => Ok(Self::ServerHelloDone),
x if x == (Self::CertificateVerify as u8) => Ok(Self::CertificateVerify),
x if x == (Self::ClientKeyExchange as u8) => Ok(Self::ClientKeyExchange),
x if x == (Self::Finished as u8) => Ok(Self::Finished),
_ => Err(BufError::UnexpectedValue),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Handshake {
pub msg_type: HandshakeType,
pub msg: Vec<u8>,
}
impl Codec for Handshake {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.msg_type.encode(writer, ())?;
let len = u24::from_usize(self.msg.len())?;
len.encode(writer, ())?;
writer.write_slice(&self.msg)
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
let msg_type = HandshakeType::decode(reader, ())?;
let length_u24 = u24::decode(reader, ())?;
let length = length_u24.as_usize();
if reader.remaining() < length {
return Err(BufError::UnexpectedEof);
}
let mut msg = vec![0u8; length];
reader.read_into(&mut msg)?;
Ok(Self { msg_type, msg })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct HelloRequest;
impl Codec for HelloRequest {
fn encode<W: BufMut>(&self, _writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Ok(())
}
fn decode<R: Buf>(_reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Random(pub [u8; 32]);
impl Random {
pub fn random() -> Self {
Self([0x32u8; 32])
}
}
impl Codec for Random {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
writer.write_array(&self.0)
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(reader.read_array::<32>()?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SessionId(pub TlsVec<u8, u8>);
impl Codec for SessionId {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u8>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum CompressionMethod {
Null = 0,
}
impl Codec for CompressionMethod {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
(*self as u8).encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
match u8::decode(reader, ())? {
x if x == (Self::Null as u8) => Ok(Self::Null),
_ => Err(BufError::UnexpectedValue),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ClientHello {
pub client_version: ProtocolVersion,
pub random: Random,
pub session_id: SessionId,
pub cipher_suites: TlsVec<CipherSuite, u16>,
pub compression_methods: TlsVec<CompressionMethod, u8>,
}
impl Codec for ClientHello {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.client_version.encode(writer, ())?;
self.random.encode(writer, ())?;
self.session_id.encode(writer, ())?;
self.cipher_suites.encode(writer, ())?;
self.compression_methods.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
client_version: ProtocolVersion::decode(reader, ())?,
random: Random::decode(reader, ())?,
session_id: SessionId::decode(reader, ())?,
cipher_suites: TlsVec::<CipherSuite, u16>::decode(reader, ())?,
compression_methods: TlsVec::<CompressionMethod, u8>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ServerHello {
pub server_version: ProtocolVersion,
pub random: Random,
pub session_id: SessionId,
pub cipher_suite: CipherSuite,
pub compression_method: CompressionMethod,
}
impl Codec for ServerHello {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.server_version.encode(writer, ())?;
self.random.encode(writer, ())?;
self.session_id.encode(writer, ())?;
self.cipher_suite.encode(writer, ())?;
self.compression_method.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
server_version: ProtocolVersion::decode(reader, ())?,
random: Random::decode(reader, ())?,
session_id: SessionId::decode(reader, ())?,
cipher_suite: CipherSuite::decode(reader, ())?,
compression_method: CompressionMethod::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Asn1Cert(pub TlsVec<u8, u24>);
impl Codec for Asn1Cert {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u24>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Certificate {
pub certificate_list: TlsVec<Asn1Cert, u24>,
}
impl Codec for Certificate {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.certificate_list.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
certificate_list: TlsVec::<Asn1Cert, u24>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum KeyExchangeAlgorithm {
Rsa = 0,
DiffieHellman = 1,
}
impl Codec for KeyExchangeAlgorithm {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
(*self as u8).encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
match u8::decode(reader, ())? {
x if x == (Self::Rsa as u8) => Ok(Self::Rsa),
x if x == (Self::DiffieHellman as u8) => Ok(Self::DiffieHellman),
_ => Err(BufError::UnexpectedValue),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum SignatureAlgorithm {
Anonymous = 0,
Rsa = 1,
Dsa = 2,
}
impl Codec for SignatureAlgorithm {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
(*self as u8).encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
match u8::decode(reader, ())? {
x if x == (Self::Anonymous as u8) => Ok(Self::Anonymous),
x if x == (Self::Rsa as u8) => Ok(Self::Rsa),
x if x == (Self::Dsa as u8) => Ok(Self::Dsa),
_ => Err(BufError::UnexpectedValue),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum ClientCertificateType {
RsaSign = 1,
DssSign = 2,
RsaFixedDh = 3,
DssFixedDh = 4,
}
impl Codec for ClientCertificateType {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
(*self as u8).encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
match u8::decode(reader, ())? {
x if x == (Self::RsaSign as u8) => Ok(Self::RsaSign),
x if x == (Self::DssSign as u8) => Ok(Self::DssSign),
x if x == (Self::RsaFixedDh as u8) => Ok(Self::RsaFixedDh),
x if x == (Self::DssFixedDh as u8) => Ok(Self::DssFixedDh),
_ => Err(BufError::UnexpectedValue),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Signature(pub TlsVec<u8, u16>);
impl Codec for Signature {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DistinguishedName(pub TlsVec<u8, u16>);
impl Codec for DistinguishedName {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(TlsVec::<u8, u16>::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CertificateRequest {
pub certificate_types: TlsVec<ClientCertificateType, u8>,
pub certificate_authorities: TlsVec<DistinguishedName, u16>,
}
impl Codec for CertificateRequest {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.certificate_types.encode(writer, ())?;
self.certificate_authorities.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
certificate_types: TlsVec::<ClientCertificateType, u8>::decode(reader, ())?,
certificate_authorities: TlsVec::<DistinguishedName, u16>::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ServerHelloDone;
impl Codec for ServerHelloDone {
fn encode<W: BufMut>(&self, _writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Ok(())
}
fn decode<R: Buf>(_reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CertificateVerify {
pub signature: Signature,
}
impl Codec for CertificateVerify {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.signature.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
signature: Signature::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Finished {
pub verify_data: [u8; 12],
}
impl Codec for Finished {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.verify_data.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
verify_data: reader.read_array::<12>()?,
})
}
}
#[cfg(test)]
mod tests {
use core::fmt::Debug;
use super::{HandshakeType, HelloRequest};
use crate::{Codec, Cursor};
fn codec_roundtrip<T: Codec<C> + Debug + Eq, C: Copy>(
etalon_struct: T,
etalon_bytes: &[u8],
context: C,
) {
let mut encoded_bytes = vec![];
{
let writer = &mut Cursor::new(&mut encoded_bytes);
etalon_struct.encode(writer, context).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
let decoded_struct = {
let reader = &mut Cursor::new(&mut encoded_bytes);
T::decode(reader, context).unwrap()
};
assert_eq!(etalon_struct, decoded_struct);
encoded_bytes.fill(0x00);
{
let writer = &mut Cursor::new(&mut encoded_bytes);
decoded_struct.encode(writer, context).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
}
#[test]
fn handshake_type() {
let etalon_bytes = &[0x01];
let etalon_struct = HandshakeType::ClientHello;
codec_roundtrip(etalon_struct, etalon_bytes, ());
}
#[test]
fn hello_request() {
let etalon_bytes = &[];
let etalon_struct = HelloRequest;
codec_roundtrip(etalon_struct, etalon_bytes, ());
}
}