From eadf776da34ef1f07ca45168766adca729cc858e Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 21 Oct 2020 18:18:54 +0800 Subject: [PATCH] fix tab/space --- Cargo.toml | 1 + src/buffer.rs | 436 +++++++++--------- src/key.rs | 10 +- src/lib.rs | 7 +- src/main.rs | 91 ++-- src/session.rs | 1112 ++++++++++++++++++++++----------------------- src/tls.rs | 780 +++++++++++++++---------------- src/tls_packet.rs | 938 +++++++++++++++++++------------------- 8 files changed, 1689 insertions(+), 1686 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d99dfd1..3e774b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ num_enum = { version = "0.5.1", default-features = false } log = "0.4.11" generic-array = "0.14.4" heapless = "0.5.6" +asn1_der = { version = "0.7.1", features = [ "native_types", "no_std" ] } [dependencies.aes-gcm] version = "0.8.0" diff --git a/src/buffer.rs b/src/buffer.rs index 6fae4b6..5ee358a 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -13,252 +13,252 @@ use crate::key::*; // Only designed to support read or write the entire buffer // TODO: Stricter visibility pub struct TlsBuffer<'a> { - buffer: &'a mut [u8], - index: RefCell, + buffer: &'a mut [u8], + index: RefCell, } impl<'a> Into<&'a [u8]> for TlsBuffer<'a> { - fn into(self) -> &'a [u8] { - &self.buffer[0..self.index.into_inner()] - } + fn into(self) -> &'a [u8] { + &self.buffer[0..self.index.into_inner()] + } } impl<'a> TlsBuffer<'a> { - pub fn new(buffer: &'a mut [u8]) -> Self { - Self { - buffer, - index: RefCell::new(0), - } - } + pub fn new(buffer: &'a mut [u8]) -> Self { + Self { + buffer, + index: RefCell::new(0), + } + } - pub(crate) fn get_size(&self) -> usize { - self.index.clone().into_inner() - } + pub(crate) fn get_size(&self) -> usize { + self.index.clone().into_inner() + } - pub(crate) fn write(&mut self, data: &[u8]) -> Result<()> { - let mut index = self.index.borrow_mut(); - if (self.buffer.len() - *index) < data.len() { - return Err(Error::Exhausted); - } - let next_index = *index + data.len(); - self.buffer[*index..next_index].copy_from_slice(data); - *index = next_index; - Ok(()) - } + pub(crate) fn write(&mut self, data: &[u8]) -> Result<()> { + let mut index = self.index.borrow_mut(); + if (self.buffer.len() - *index) < data.len() { + return Err(Error::Exhausted); + } + let next_index = *index + data.len(); + self.buffer[*index..next_index].copy_from_slice(data); + *index = next_index; + Ok(()) + } - pub(crate) fn write_u8(&mut self, data: u8) -> Result<()> { - let mut index = self.index.borrow_mut(); - if (self.buffer.len() - *index) < 1 { - return Err(Error::Exhausted); - } - self.buffer[*index] = data; - *index += 1; - Ok(()) - } + pub(crate) fn write_u8(&mut self, data: u8) -> Result<()> { + let mut index = self.index.borrow_mut(); + if (self.buffer.len() - *index) < 1 { + return Err(Error::Exhausted); + } + self.buffer[*index] = data; + *index += 1; + Ok(()) + } - pub(crate) fn read_u8(&mut self) -> Result { - let mut index = self.index.borrow_mut(); - if (self.buffer.len() - *index) < 1 { - return Err(Error::Exhausted); - } - let data = self.buffer[*index]; - *index += 1; - Ok(data) - } + pub(crate) fn read_u8(&mut self) -> Result { + let mut index = self.index.borrow_mut(); + if (self.buffer.len() - *index) < 1 { + return Err(Error::Exhausted); + } + let data = self.buffer[*index]; + *index += 1; + Ok(data) + } - pub(crate) fn read_all(self) -> &'a [u8] { - &self.buffer[self.index.into_inner()..] - } + pub(crate) fn read_all(self) -> &'a [u8] { + &self.buffer[self.index.into_inner()..] + } - pub(crate) fn read_slice(&self, length: usize) -> Result<&[u8]> { - let mut index = self.index.borrow_mut(); - if (self.buffer.len() - *index) < length { - return Err(Error::Exhausted); - } - let next_index = *index + length; - let slice = &self.buffer[*index..next_index]; - *index = next_index; - Ok(slice) - } + pub(crate) fn read_slice(&self, length: usize) -> Result<&[u8]> { + let mut index = self.index.borrow_mut(); + if (self.buffer.len() - *index) < length { + return Err(Error::Exhausted); + } + let next_index = *index + length; + let slice = &self.buffer[*index..next_index]; + *index = next_index; + Ok(slice) + } - pub(crate) fn enqueue_tls_repr(&mut self, tls_repr: TlsRepr<'a>) -> Result<()> { - self.write_u8(tls_repr.content_type.into())?; - self.write_u16(tls_repr.version.into())?; - self.write_u16(tls_repr.length)?; - if let Some(app_data) = tls_repr.payload { - self.write(app_data.as_slice())?; - } else if let Some(handshake_repr) = tls_repr.handshake { - // Queue handshake_repr into buffer - self.enqueue_handshake_repr(handshake_repr)?; - } else { - return Err(Error::Malformed); - } - Ok(()) - } + pub(crate) fn enqueue_tls_repr(&mut self, tls_repr: TlsRepr<'a>) -> Result<()> { + self.write_u8(tls_repr.content_type.into())?; + self.write_u16(tls_repr.version.into())?; + self.write_u16(tls_repr.length)?; + if let Some(app_data) = tls_repr.payload { + self.write(app_data.as_slice())?; + } else if let Some(handshake_repr) = tls_repr.handshake { + // Queue handshake_repr into buffer + self.enqueue_handshake_repr(handshake_repr)?; + } else { + return Err(Error::Malformed); + } + Ok(()) + } - fn enqueue_handshake_repr(&mut self, handshake_repr: HandshakeRepr<'a>) -> Result<()> { - self.write_u8(handshake_repr.msg_type.into())?; - self.write_u24(handshake_repr.length)?; - self.enqueue_handshake_data(handshake_repr.handshake_data) - } + fn enqueue_handshake_repr(&mut self, handshake_repr: HandshakeRepr<'a>) -> Result<()> { + self.write_u8(handshake_repr.msg_type.into())?; + self.write_u24(handshake_repr.length)?; + self.enqueue_handshake_data(handshake_repr.handshake_data) + } - fn enqueue_handshake_data(&mut self, handshake_data: HandshakeData<'a>) -> Result<()> { - match handshake_data { - HandshakeData::ClientHello(client_hello) => { - self.enqueue_client_hello(client_hello) - } - HandshakeData::ServerHello(server_hello) => { - self.euqueue_server_hello(server_hello) - } - _ => { - Err(Error::Unrecognized) - } - } - } + fn enqueue_handshake_data(&mut self, handshake_data: HandshakeData<'a>) -> Result<()> { + match handshake_data { + HandshakeData::ClientHello(client_hello) => { + self.enqueue_client_hello(client_hello) + } + HandshakeData::ServerHello(server_hello) => { + self.euqueue_server_hello(server_hello) + } + _ => { + Err(Error::Unrecognized) + } + } + } - fn enqueue_client_hello(&mut self, client_hello: ClientHello<'a>) -> Result<()> { - self.write_u16(client_hello.version.into())?; - self.write(&client_hello.random)?; - self.write_u8(client_hello.session_id_length)?; - self.write(&client_hello.session_id)?; - self.write_u16(client_hello.cipher_suites_length)?; - for suite in client_hello.cipher_suites.iter() { - self.write_u16((*suite).into())?; - } - self.write_u8(client_hello.compression_method_length)?; - self.write_u8(client_hello.compression_methods)?; - self.write_u16(client_hello.extension_length)?; - self.enqueue_extensions(client_hello.extensions) - } + fn enqueue_client_hello(&mut self, client_hello: ClientHello<'a>) -> Result<()> { + self.write_u16(client_hello.version.into())?; + self.write(&client_hello.random)?; + self.write_u8(client_hello.session_id_length)?; + self.write(&client_hello.session_id)?; + self.write_u16(client_hello.cipher_suites_length)?; + for suite in client_hello.cipher_suites.iter() { + self.write_u16((*suite).into())?; + } + self.write_u8(client_hello.compression_method_length)?; + self.write_u8(client_hello.compression_methods)?; + self.write_u16(client_hello.extension_length)?; + self.enqueue_extensions(client_hello.extensions) + } - fn euqueue_server_hello(&mut self, server_hello: ServerHello<'a>) -> Result<()> { - self.write_u16(server_hello.version.into())?; - self.write(&server_hello.random)?; - self.write_u8(server_hello.session_id_echo_length)?; - self.write(&server_hello.session_id_echo)?; - self.write_u16(server_hello.cipher_suite.into())?; - self.write_u8(server_hello.compression_method)?; - self.write_u16(server_hello.extension_length)?; - self.enqueue_extensions(server_hello.extensions) - } + fn euqueue_server_hello(&mut self, server_hello: ServerHello<'a>) -> Result<()> { + self.write_u16(server_hello.version.into())?; + self.write(&server_hello.random)?; + self.write_u8(server_hello.session_id_echo_length)?; + self.write(&server_hello.session_id_echo)?; + self.write_u16(server_hello.cipher_suite.into())?; + self.write_u8(server_hello.compression_method)?; + self.write_u16(server_hello.extension_length)?; + self.enqueue_extensions(server_hello.extensions) + } - fn enqueue_extensions(&mut self, extensions: Vec) -> Result<()> { - for extension in extensions { - self.write_u16(extension.extension_type.into())?; - self.write_u16(extension.length)?; - self.enqueue_extension_data(extension.extension_data)?; - } - Ok(()) - } + fn enqueue_extensions(&mut self, extensions: Vec) -> Result<()> { + for extension in extensions { + self.write_u16(extension.extension_type.into())?; + self.write_u16(extension.length)?; + self.enqueue_extension_data(extension.extension_data)?; + } + Ok(()) + } - fn enqueue_extension_data(&mut self, extension_data: ExtensionData) -> Result<()> { - use crate::tls_packet::ExtensionData::*; - match extension_data { - SupportedVersions(s) => { - use crate::tls_packet::SupportedVersions::*; - match s { - ClientHello { length, versions } => { - self.write_u8(length)?; - for version in versions.iter() { - self.write_u16((*version).into())?; - } - }, - ServerHello { selected_version } => { - self.write_u16(selected_version.into())?; - } - } - }, - SignatureAlgorithms(s) => { - self.write_u16(s.length)?; - for sig_alg in s.supported_signature_algorithms.iter() { - self.write_u16((*sig_alg).into())?; - } - }, - NegotiatedGroups(n) => { - self.write_u16(n.length)?; - for group in n.named_group_list.iter() { - self.write_u16((*group).into())?; - } - }, - KeyShareEntry(k) => { - let mut key_share_entry_into = |buffer: &mut TlsBuffer, entry: crate::tls_packet::KeyShareEntry| { - buffer.write_u16(entry.group.into())?; - buffer.write_u16(entry.length)?; - buffer.write(entry.key_exchange.as_slice()) - }; + fn enqueue_extension_data(&mut self, extension_data: ExtensionData) -> Result<()> { + use crate::tls_packet::ExtensionData::*; + match extension_data { + SupportedVersions(s) => { + use crate::tls_packet::SupportedVersions::*; + match s { + ClientHello { length, versions } => { + self.write_u8(length)?; + for version in versions.iter() { + self.write_u16((*version).into())?; + } + }, + ServerHello { selected_version } => { + self.write_u16(selected_version.into())?; + } + } + }, + SignatureAlgorithms(s) => { + self.write_u16(s.length)?; + for sig_alg in s.supported_signature_algorithms.iter() { + self.write_u16((*sig_alg).into())?; + } + }, + NegotiatedGroups(n) => { + self.write_u16(n.length)?; + for group in n.named_group_list.iter() { + self.write_u16((*group).into())?; + } + }, + KeyShareEntry(k) => { + let mut key_share_entry_into = |buffer: &mut TlsBuffer, entry: crate::tls_packet::KeyShareEntry| { + buffer.write_u16(entry.group.into())?; + buffer.write_u16(entry.length)?; + buffer.write(entry.key_exchange.as_slice()) + }; - use crate::tls_packet::KeyShareEntryContent::*; - match k { - KeyShareClientHello { length, client_shares } => { - self.write_u16(length)?; - for share in client_shares.iter() { - self.enqueue_key_share_entry(share)?; - } - } - KeyShareHelloRetryRequest { selected_group } => { - self.write_u16(selected_group.into())?; - } - KeyShareServerHello { server_share } => { - self.enqueue_key_share_entry(&server_share)?; - } - } - }, + use crate::tls_packet::KeyShareEntryContent::*; + match k { + KeyShareClientHello { length, client_shares } => { + self.write_u16(length)?; + for share in client_shares.iter() { + self.enqueue_key_share_entry(share)?; + } + } + KeyShareHelloRetryRequest { selected_group } => { + self.write_u16(selected_group.into())?; + } + KeyShareServerHello { server_share } => { + self.enqueue_key_share_entry(&server_share)?; + } + } + }, - // TODO: Implement buffer formatting for other extensions - _ => todo!() - }; - Ok(()) - } + // TODO: Implement buffer formatting for other extensions + _ => todo!() + }; + Ok(()) + } - fn enqueue_key_share_entry(&mut self, entry: &crate::tls_packet::KeyShareEntry) -> Result<()> { - self.write_u16(entry.group.into())?; - self.write_u16(entry.length)?; - self.write(entry.key_exchange.as_slice()) - } + fn enqueue_key_share_entry(&mut self, entry: &crate::tls_packet::KeyShareEntry) -> Result<()> { + self.write_u16(entry.group.into())?; + self.write_u16(entry.length)?; + self.write(entry.key_exchange.as_slice()) + } - pub fn enqueue_hkdf_label(&mut self, hkdf_label: HkdfLabel) -> Result<()> { - self.write_u16(hkdf_label.length)?; - self.write_u8(hkdf_label.label_length)?; - self.write(hkdf_label.label)?; - self.write_u8(hkdf_label.context_length)?; - self.write(hkdf_label.context) - } + pub fn enqueue_hkdf_label(&mut self, hkdf_label: HkdfLabel) -> Result<()> { + self.write_u16(hkdf_label.length)?; + self.write_u8(hkdf_label.label_length)?; + self.write(hkdf_label.label)?; + self.write_u8(hkdf_label.context_length)?; + self.write(hkdf_label.context) + } } macro_rules! export_byte_order_fn { - ($($write_fn_name: ident, $read_fn_name: ident, $data_type: ty, $data_size: literal),+) => { - impl<'a> TlsBuffer<'a> { - $( - pub(crate) fn $write_fn_name(&mut self, data: $data_type) -> Result<()> { - let mut index = self.index.borrow_mut(); - if (self.buffer.len() - *index) < $data_size { - return Err(Error::Exhausted); - } - let next_index = *index + $data_size; - NetworkEndian::$write_fn_name(&mut self.buffer[*index..next_index], data); - *index = next_index; - Ok(()) - } + ($($write_fn_name: ident, $read_fn_name: ident, $data_type: ty, $data_size: literal),+) => { + impl<'a> TlsBuffer<'a> { + $( + pub(crate) fn $write_fn_name(&mut self, data: $data_type) -> Result<()> { + let mut index = self.index.borrow_mut(); + if (self.buffer.len() - *index) < $data_size { + return Err(Error::Exhausted); + } + let next_index = *index + $data_size; + NetworkEndian::$write_fn_name(&mut self.buffer[*index..next_index], data); + *index = next_index; + Ok(()) + } - pub(crate) fn $read_fn_name(&self) -> Result<$data_type> { - let mut index = self.index.borrow_mut(); - if (self.buffer.len() - *index) < $data_size { - return Err(Error::Exhausted); - } - let next_index = *index + $data_size; - let data = NetworkEndian::$read_fn_name(&self.buffer[*index..next_index]); - *index = next_index; - Ok(data) - } - )+ - } - } + pub(crate) fn $read_fn_name(&self) -> Result<$data_type> { + let mut index = self.index.borrow_mut(); + if (self.buffer.len() - *index) < $data_size { + return Err(Error::Exhausted); + } + let next_index = *index + $data_size; + let data = NetworkEndian::$read_fn_name(&self.buffer[*index..next_index]); + *index = next_index; + Ok(data) + } + )+ + } + } } export_byte_order_fn!( - write_u16, read_u16, u16, 2, - write_u24, read_u24, u32, 3, - write_u32, read_u32, u32, 4, - write_u48, read_u48, u64, 6, - write_u64, read_u64, u64, 8 + write_u16, read_u16, u16, 2, + write_u24, read_u24, u32, 3, + write_u32, read_u32, u32, 4, + write_u48, read_u48, u64, 6, + write_u64, read_u64, u64, 8 ); diff --git a/src/key.rs b/src/key.rs index fb4cc24..f3fe58a 100644 --- a/src/key.rs +++ b/src/key.rs @@ -10,12 +10,12 @@ use core::convert::TryFrom; #[derive(Debug, Clone)] pub struct HkdfLabel<'a> { - // Length of hash function - pub length: u16, - // Label vector: "tls13 " + label + // Length of hash function + pub length: u16, + // Label vector: "tls13 " + label pub label_length: u8, - pub label: &'a [u8], - // Context vector: Hashed message + pub label: &'a [u8], + // Context vector: Hashed message pub context_length: u8, pub context: &'a [u8], } diff --git a/src/lib.rs b/src/lib.rs index c239d62..a9b938f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,13 +9,16 @@ pub mod parse; pub mod buffer; pub mod key; pub mod session; +pub mod certificate; + +use nom::error::ParseError; // TODO: Implement errors // Details: Encapsulate smoltcp & nom errors pub enum Error { PropagatedError(smoltcp::Error), - ParsingError, + ParsingError(nom::error::ErrorKind), EncryptionError, DecryptionError, CapacityError, -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 7a948b6..af112f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,31 +22,30 @@ use hkdf::Hkdf; use smoltcp_tls::key::*; use smoltcp_tls::buffer::TlsBuffer; -use asn1_der::{ - DerObject, - typed::{ DerEncodable, DerDecodable } -}; +use smoltcp_tls::certificate::*; +use asn1_der::DerObject; +use smoltcp_tls::parse::*; struct CountingRng(u64); impl RngCore for CountingRng { - fn next_u32(&mut self) -> u32 { - self.next_u64() as u32 - } + fn next_u32(&mut self) -> u32 { + self.next_u64() as u32 + } - fn next_u64(&mut self) -> u64 { - self.0 += 1; - self.0 - } + fn next_u64(&mut self) -> u64 { + self.0 += 1; + self.0 + } - fn fill_bytes(&mut self, dest: &mut [u8]) { - impls::fill_bytes_via_next(self, dest) - } + fn fill_bytes(&mut self, dest: &mut [u8]) { + impls::fill_bytes_via_next(self, dest) + } - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - Ok(self.fill_bytes(dest)) - } + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + Ok(self.fill_bytes(dest)) + } } impl CryptoRng for CountingRng {} @@ -54,40 +53,40 @@ impl CryptoRng for CountingRng {} static mut RNG: CountingRng = CountingRng(0); fn main() { - let mut socket_set_entries: [_; 8] = Default::default(); - let mut sockets = SocketSet::new(&mut socket_set_entries[..]); + let mut socket_set_entries: [_; 8] = Default::default(); + let mut sockets = SocketSet::new(&mut socket_set_entries[..]); - let mut tx_storage = [0; 4096]; - let mut rx_storage = [0; 4096]; + let mut tx_storage = [0; 4096]; + let mut rx_storage = [0; 4096]; - let mut tls_socket = unsafe { - let tx_buffer = TcpSocketBuffer::new(&mut tx_storage[..]); - let rx_buffer = TcpSocketBuffer::new(&mut rx_storage[..]); - TlsSocket::new( - &mut sockets, - rx_buffer, - tx_buffer, - &mut RNG, - ) - }; + let mut tls_socket = unsafe { + let tx_buffer = TcpSocketBuffer::new(&mut tx_storage[..]); + let rx_buffer = TcpSocketBuffer::new(&mut rx_storage[..]); + TlsSocket::new( + &mut sockets, + rx_buffer, + tx_buffer, + &mut RNG, + ) + }; - tls_socket.tcp_connect( - &mut sockets, - (Ipv4Address::new(192, 168, 1, 125), 1883), - 49600 - ).unwrap(); - -// tls_socket.tls_connect(&mut sockets).unwrap(); - let object = DerObject::decode(&CERT).expect("Failed to decode object"); - println!("raw: {:2X?},\nheader: {:2X?},\ntag: {:2X?},\nvalue: {:2X?}\n", - object.raw(), - object.header(), - object.tag(), - object.value() - ); + tls_socket.tcp_connect( + &mut sockets, + (Ipv4Address::new(192, 168, 1, 125), 1883), + 49600 + ).unwrap(); +// tls_socket.tls_connect(&mut sockets).unwrap(); + let (rest, result) = parse_asn1_der_certificate(&CERT).unwrap(); + println!( + "{:X?}\n{:X?}\n{:X?}\n{:X?}", + rest, + result.0, + result.1, + result.2 + ); } const CERT: [u8; 805] = [ - 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x09, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x15, 0x5a, 0x92, 0xad, 0xc2, 0x04, 0x8f, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x30, 0x2b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0x80, 0x36, 0x06, 0xba, 0xe7, 0x47, 0x6b, 0x08, 0x94, 0x04, 0xec, 0xa7, 0xb6, 0x91, 0x04, 0x3f, 0xf7, 0x92, 0xbc, 0x19, 0xee, 0xfb, 0x7d, 0x74, 0xd7, 0xa8, 0x0d, 0x00, 0x1e, 0x7b, 0x4b, 0x3a, 0x4a, 0xe6, 0x0f, 0xe8, 0xc0, 0x71, 0xfc, 0x73, 0xe7, 0x02, 0x4c, 0x0d, 0xbc, 0xf4, 0xbd, 0xd1, 0x1d, 0x39, 0x6b, 0xba, 0x70, 0x46, 0x4a, 0x13, 0xe9, 0x4a, 0xf8, 0x3d, 0xf3, 0xe1, 0x09, 0x59, 0x54, 0x7b, 0xc9, 0x55, 0xfb, 0x41, 0x2d, 0xa3, 0x76, 0x52, 0x11, 0xe1, 0xf3, 0xdc, 0x77, 0x6c, 0xaa, 0x53, 0x37, 0x6e, 0xca, 0x3a, 0xec, 0xbe, 0xc3, 0xaa, 0xb7, 0x3b, 0x31, 0xd5, 0x6c, 0xb6, 0x52, 0x9c, 0x80, 0x98, 0xbc, 0xc9, 0xe0, 0x28, 0x18, 0xe2, 0x0b, 0xf7, 0xf8, 0xa0, 0x3a, 0xfd, 0x17, 0x04, 0x50, 0x9e, 0xce, 0x79, 0xbd, 0x9f, 0x39, 0xf1, 0xea, 0x69, 0xec, 0x47, 0x97, 0x2e, 0x83, 0x0f, 0xb5, 0xca, 0x95, 0xde, 0x95, 0xa1, 0xe6, 0x04, 0x22, 0xd5, 0xee, 0xbe, 0x52, 0x79, 0x54, 0xa1, 0xe7, 0xbf, 0x8a, 0x86, 0xf6, 0x46, 0x6d, 0x0d, 0x9f, 0x16, 0x95, 0x1a, 0x4c, 0xf7, 0xa0, 0x46, 0x92, 0x59, 0x5c, 0x13, 0x52, 0xf2, 0x54, 0x9e, 0x5a, 0xfb, 0x4e, 0xbf, 0xd7, 0x7a, 0x37, 0x95, 0x01, 0x44, 0xe4, 0xc0, 0x26, 0x87, 0x4c, 0x65, 0x3e, 0x40, 0x7d, 0x7d, 0x23, 0x07, 0x44, 0x01, 0xf4, 0x84, 0xff, 0xd0, 0x8f, 0x7a, 0x1f, 0xa0, 0x52, 0x10, 0xd1, 0xf4, 0xf0, 0xd5, 0xce, 0x79, 0x70, 0x29, 0x32, 0xe2, 0xca, 0xbe, 0x70, 0x1f, 0xdf, 0xad, 0x6b, 0x4b, 0xb7, 0x11, 0x01, 0xf4, 0x4b, 0xad, 0x66, 0x6a, 0x11, 0x13, 0x0f, 0xe2, 0xee, 0x82, 0x9e, 0x4d, 0x02, 0x9d, 0xc9, 0x1c, 0xdd, 0x67, 0x16, 0xdb, 0xb9, 0x06, 0x18, 0x86, 0xed, 0xc1, 0xba, 0x94, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x52, 0x30, 0x50, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x89, 0x4f, 0xde, 0x5b, 0xcc, 0x69, 0xe2, 0x52, 0xcf, 0x3e, 0xa3, 0x00, 0xdf, 0xb1, 0x97, 0xb8, 0x1d, 0xe1, 0xc1, 0x46, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0x16, 0x45, 0xa6, 0x9a, 0x2e, 0x37, 0x79, 0xe4, 0xf6, 0xdd, 0x27, 0x1a, 0xba, 0x1c, 0x0b, 0xfd, 0x6c, 0xd7, 0x55, 0x99, 0xb5, 0xe7, 0xc3, 0x6e, 0x53, 0x3e, 0xff, 0x36, 0x59, 0x08, 0x43, 0x24, 0xc9, 0xe7, 0xa5, 0x04, 0x07, 0x9d, 0x39, 0xe0, 0xd4, 0x29, 0x87, 0xff, 0xe3, 0xeb, 0xdd, 0x09, 0xc1, 0xcf, 0x1d, 0x91, 0x44, 0x55, 0x87, 0x0b, 0x57, 0x1d, 0xd1, 0x9b, 0xdf, 0x1d, 0x24, 0xf8, 0xbb, 0x9a, 0x11, 0xfe, 0x80, 0xfd, 0x59, 0x2b, 0xa0, 0x39, 0x8c, 0xde, 0x11, 0xe2, 0x65, 0x1e, 0x61, 0x8c, 0xe5, 0x98, 0xfa, 0x96, 0xe5, 0x37, 0x2e, 0xef, 0x3d, 0x24, 0x8a, 0xfd, 0xe1, 0x74, 0x63, 0xeb, 0xbf, 0xab, 0xb8, 0xe4, 0xd1, 0xab, 0x50, 0x2a, 0x54, 0xec, 0x00, 0x64, 0xe9, 0x2f, 0x78, 0x19, 0x66, 0x0d, 0x3f, 0x27, 0xcf, 0x20, 0x9e, 0x66, 0x7f, 0xce, 0x5a, 0xe2, 0xe4, 0xac, 0x99, 0xc7, 0xc9, 0x38, 0x18, 0xf8, 0xb2, 0x51, 0x07, 0x22, 0xdf, 0xed, 0x97, 0xf3, 0x2e, 0x3e, 0x93, 0x49, 0xd4, 0xc6, 0x6c, 0x9e, 0xa6, 0x39, 0x6d, 0x74, 0x44, 0x62, 0xa0, 0x6b, 0x42, 0xc6, 0xd5, 0xba, 0x68, 0x8e, 0xac, 0x3a, 0x01, 0x7b, 0xdd, 0xfc, 0x8e, 0x2c, 0xfc, 0xad, 0x27, 0xcb, 0x69, 0xd3, 0xcc, 0xdc, 0xa2, 0x80, 0x41, 0x44, 0x65, 0xd3, 0xae, 0x34, 0x8c, 0xe0, 0xf3, 0x4a, 0xb2, 0xfb, 0x9c, 0x61, 0x83, 0x71, 0x31, 0x2b, 0x19, 0x10, 0x41, 0x64, 0x1c, 0x23, 0x7f, 0x11, 0xa5, 0xd6, 0x5c, 0x84, 0x4f, 0x04, 0x04, 0x84, 0x99, 0x38, 0x71, 0x2b, 0x95, 0x9e, 0xd6, 0x85, 0xbc, 0x5c, 0x5d, 0xd6, 0x45, 0xed, 0x19, 0x90, 0x94, 0x73, 0x40, 0x29, 0x26, 0xdc, 0xb4, 0x0e, 0x34, 0x69, 0xa1, 0x59, 0x41, 0xe8, 0xe2, 0xcc, 0xa8, 0x4b, 0xb6, 0x08, 0x46, 0x36, 0xa0 + 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x09, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x15, 0x5a, 0x92, 0xad, 0xc2, 0x04, 0x8f, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x30, 0x2b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0x80, 0x36, 0x06, 0xba, 0xe7, 0x47, 0x6b, 0x08, 0x94, 0x04, 0xec, 0xa7, 0xb6, 0x91, 0x04, 0x3f, 0xf7, 0x92, 0xbc, 0x19, 0xee, 0xfb, 0x7d, 0x74, 0xd7, 0xa8, 0x0d, 0x00, 0x1e, 0x7b, 0x4b, 0x3a, 0x4a, 0xe6, 0x0f, 0xe8, 0xc0, 0x71, 0xfc, 0x73, 0xe7, 0x02, 0x4c, 0x0d, 0xbc, 0xf4, 0xbd, 0xd1, 0x1d, 0x39, 0x6b, 0xba, 0x70, 0x46, 0x4a, 0x13, 0xe9, 0x4a, 0xf8, 0x3d, 0xf3, 0xe1, 0x09, 0x59, 0x54, 0x7b, 0xc9, 0x55, 0xfb, 0x41, 0x2d, 0xa3, 0x76, 0x52, 0x11, 0xe1, 0xf3, 0xdc, 0x77, 0x6c, 0xaa, 0x53, 0x37, 0x6e, 0xca, 0x3a, 0xec, 0xbe, 0xc3, 0xaa, 0xb7, 0x3b, 0x31, 0xd5, 0x6c, 0xb6, 0x52, 0x9c, 0x80, 0x98, 0xbc, 0xc9, 0xe0, 0x28, 0x18, 0xe2, 0x0b, 0xf7, 0xf8, 0xa0, 0x3a, 0xfd, 0x17, 0x04, 0x50, 0x9e, 0xce, 0x79, 0xbd, 0x9f, 0x39, 0xf1, 0xea, 0x69, 0xec, 0x47, 0x97, 0x2e, 0x83, 0x0f, 0xb5, 0xca, 0x95, 0xde, 0x95, 0xa1, 0xe6, 0x04, 0x22, 0xd5, 0xee, 0xbe, 0x52, 0x79, 0x54, 0xa1, 0xe7, 0xbf, 0x8a, 0x86, 0xf6, 0x46, 0x6d, 0x0d, 0x9f, 0x16, 0x95, 0x1a, 0x4c, 0xf7, 0xa0, 0x46, 0x92, 0x59, 0x5c, 0x13, 0x52, 0xf2, 0x54, 0x9e, 0x5a, 0xfb, 0x4e, 0xbf, 0xd7, 0x7a, 0x37, 0x95, 0x01, 0x44, 0xe4, 0xc0, 0x26, 0x87, 0x4c, 0x65, 0x3e, 0x40, 0x7d, 0x7d, 0x23, 0x07, 0x44, 0x01, 0xf4, 0x84, 0xff, 0xd0, 0x8f, 0x7a, 0x1f, 0xa0, 0x52, 0x10, 0xd1, 0xf4, 0xf0, 0xd5, 0xce, 0x79, 0x70, 0x29, 0x32, 0xe2, 0xca, 0xbe, 0x70, 0x1f, 0xdf, 0xad, 0x6b, 0x4b, 0xb7, 0x11, 0x01, 0xf4, 0x4b, 0xad, 0x66, 0x6a, 0x11, 0x13, 0x0f, 0xe2, 0xee, 0x82, 0x9e, 0x4d, 0x02, 0x9d, 0xc9, 0x1c, 0xdd, 0x67, 0x16, 0xdb, 0xb9, 0x06, 0x18, 0x86, 0xed, 0xc1, 0xba, 0x94, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x52, 0x30, 0x50, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x89, 0x4f, 0xde, 0x5b, 0xcc, 0x69, 0xe2, 0x52, 0xcf, 0x3e, 0xa3, 0x00, 0xdf, 0xb1, 0x97, 0xb8, 0x1d, 0xe1, 0xc1, 0x46, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0x16, 0x45, 0xa6, 0x9a, 0x2e, 0x37, 0x79, 0xe4, 0xf6, 0xdd, 0x27, 0x1a, 0xba, 0x1c, 0x0b, 0xfd, 0x6c, 0xd7, 0x55, 0x99, 0xb5, 0xe7, 0xc3, 0x6e, 0x53, 0x3e, 0xff, 0x36, 0x59, 0x08, 0x43, 0x24, 0xc9, 0xe7, 0xa5, 0x04, 0x07, 0x9d, 0x39, 0xe0, 0xd4, 0x29, 0x87, 0xff, 0xe3, 0xeb, 0xdd, 0x09, 0xc1, 0xcf, 0x1d, 0x91, 0x44, 0x55, 0x87, 0x0b, 0x57, 0x1d, 0xd1, 0x9b, 0xdf, 0x1d, 0x24, 0xf8, 0xbb, 0x9a, 0x11, 0xfe, 0x80, 0xfd, 0x59, 0x2b, 0xa0, 0x39, 0x8c, 0xde, 0x11, 0xe2, 0x65, 0x1e, 0x61, 0x8c, 0xe5, 0x98, 0xfa, 0x96, 0xe5, 0x37, 0x2e, 0xef, 0x3d, 0x24, 0x8a, 0xfd, 0xe1, 0x74, 0x63, 0xeb, 0xbf, 0xab, 0xb8, 0xe4, 0xd1, 0xab, 0x50, 0x2a, 0x54, 0xec, 0x00, 0x64, 0xe9, 0x2f, 0x78, 0x19, 0x66, 0x0d, 0x3f, 0x27, 0xcf, 0x20, 0x9e, 0x66, 0x7f, 0xce, 0x5a, 0xe2, 0xe4, 0xac, 0x99, 0xc7, 0xc9, 0x38, 0x18, 0xf8, 0xb2, 0x51, 0x07, 0x22, 0xdf, 0xed, 0x97, 0xf3, 0x2e, 0x3e, 0x93, 0x49, 0xd4, 0xc6, 0x6c, 0x9e, 0xa6, 0x39, 0x6d, 0x74, 0x44, 0x62, 0xa0, 0x6b, 0x42, 0xc6, 0xd5, 0xba, 0x68, 0x8e, 0xac, 0x3a, 0x01, 0x7b, 0xdd, 0xfc, 0x8e, 0x2c, 0xfc, 0xad, 0x27, 0xcb, 0x69, 0xd3, 0xcc, 0xdc, 0xa2, 0x80, 0x41, 0x44, 0x65, 0xd3, 0xae, 0x34, 0x8c, 0xe0, 0xf3, 0x4a, 0xb2, 0xfb, 0x9c, 0x61, 0x83, 0x71, 0x31, 0x2b, 0x19, 0x10, 0x41, 0x64, 0x1c, 0x23, 0x7f, 0x11, 0xa5, 0xd6, 0x5c, 0x84, 0x4f, 0x04, 0x04, 0x84, 0x99, 0x38, 0x71, 0x2b, 0x95, 0x9e, 0xd6, 0x85, 0xbc, 0x5c, 0x5d, 0xd6, 0x45, 0xed, 0x19, 0x90, 0x94, 0x73, 0x40, 0x29, 0x26, 0xdc, 0xb4, 0x0e, 0x34, 0x69, 0xa1, 0x59, 0x41, 0xe8, 0xe2, 0xcc, 0xa8, 0x4b, 0xb6, 0x08, 0x46, 0x36, 0xa0 ]; diff --git a/src/session.rs b/src/session.rs index 0e342fa..82eec62 100644 --- a/src/session.rs +++ b/src/session.rs @@ -20,630 +20,630 @@ use crate::Error; type Aes128Ccm = Ccm; pub(crate) struct Session { - state: TlsState, - role: TlsRole, - // Session ID for this session - session_id: Option<[u8; 32]>, - // Changed cipher spec - changed_cipher_spec: bool, - // Handshake secret, Master secret - // Early secret is computed right before HS - // TLS standard: Secrets should not be stored unnecessarily - latest_secret: Option>, - // Hash functions needed - hash: Hash, - // Ephemeral secret for ECDHE key exchange - ecdhe_secret: Option, - // Block ciphers for client & server - client_cipher: Option, - server_cipher: Option, - // Traffic secret for client & server - // Keeping traffic secret for key re-computation - client_traffic_secret: Option>, - server_traffic_secret: Option>, - // Nonce (IV) for client & server - // Always 12 bytes long - client_nonce: Option>, - server_nonce: Option>, - // Sequence number: Start from 0, 64 bits - // Increment by one per record processed (read OR write) - // Reset to 0 on rekey AND key exchange - // TODO: Force rekey if sequence_number need to wrap - sequence_number: u64, + state: TlsState, + role: TlsRole, + // Session ID for this session + session_id: Option<[u8; 32]>, + // Changed cipher spec + changed_cipher_spec: bool, + // Handshake secret, Master secret + // Early secret is computed right before HS + // TLS standard: Secrets should not be stored unnecessarily + latest_secret: Option>, + // Hash functions needed + hash: Hash, + // Ephemeral secret for ECDHE key exchange + ecdhe_secret: Option, + // Block ciphers for client & server + client_cipher: Option, + server_cipher: Option, + // Traffic secret for client & server + // Keeping traffic secret for key re-computation + client_traffic_secret: Option>, + server_traffic_secret: Option>, + // Nonce (IV) for client & server + // Always 12 bytes long + client_nonce: Option>, + server_nonce: Option>, + // Sequence number: Start from 0, 64 bits + // Increment by one per record processed (read OR write) + // Reset to 0 on rekey AND key exchange + // TODO: Force rekey if sequence_number need to wrap + sequence_number: u64, } impl Session { - pub(crate) fn new(role: TlsRole) -> Self { - let hash = Hash::Undetermined { - sha256: Sha256::new(), - sha384: Sha384::new(), - }; - Self { - state: TlsState::START, - role, - session_id: None, - changed_cipher_spec: false, - latest_secret: None, - hash, - ecdhe_secret: None, - client_cipher: None, - server_cipher: None, - client_traffic_secret: None, - server_traffic_secret: None, - client_nonce: None, - server_nonce: None, - sequence_number: 0, - } - } + pub(crate) fn new(role: TlsRole) -> Self { + let hash = Hash::Undetermined { + sha256: Sha256::new(), + sha384: Sha384::new(), + }; + Self { + state: TlsState::START, + role, + session_id: None, + changed_cipher_spec: false, + latest_secret: None, + hash, + ecdhe_secret: None, + client_cipher: None, + server_cipher: None, + client_traffic_secret: None, + server_traffic_secret: None, + client_nonce: None, + server_nonce: None, + sequence_number: 0, + } + } - // State transition from START to WAIT_SH - pub(crate) fn client_update_for_ch( - &mut self, - ecdhe_secret: EphemeralSecret, - session_id: [u8; 32], - ch_slice: &[u8] - ) { - // Handle inappropriate call to move state - if self.state != TlsState::START || self.role != TlsRole::Client { - todo!() - } - self.ecdhe_secret = Some(ecdhe_secret); - self.session_id = Some(session_id); - self.hash.update(ch_slice); - self.state = TlsState::WAIT_SH; - } + // State transition from START to WAIT_SH + pub(crate) fn client_update_for_ch( + &mut self, + ecdhe_secret: EphemeralSecret, + session_id: [u8; 32], + ch_slice: &[u8] + ) { + // Handle inappropriate call to move state + if self.state != TlsState::START || self.role != TlsRole::Client { + todo!() + } + self.ecdhe_secret = Some(ecdhe_secret); + self.session_id = Some(session_id); + self.hash.update(ch_slice); + self.state = TlsState::WAIT_SH; + } - // State transition from WAIT_SH to WAIT_EE - // TODO: Memory allocation - // It current dumps too much memory onto the stack on invocation - pub(crate) fn client_update_for_sh( - &mut self, - cipher_suite: CipherSuite, - encoded_point: EncodedPoint, - sh_slice: &[u8] - ) { - // Handle inappropriate call to move state - if self.state != TlsState::WAIT_SH || self.role != TlsRole::Client { - todo!() - } - // Generate ECDHE shared secret - // Remove private secret - let ecdhe_shared_secret = - self.ecdhe_secret - .take() - .unwrap() - .diffie_hellman(&encoded_point) - .unwrap(); + // State transition from WAIT_SH to WAIT_EE + // TODO: Memory allocation + // It current dumps too much memory onto the stack on invocation + pub(crate) fn client_update_for_sh( + &mut self, + cipher_suite: CipherSuite, + encoded_point: EncodedPoint, + sh_slice: &[u8] + ) { + // Handle inappropriate call to move state + if self.state != TlsState::WAIT_SH || self.role != TlsRole::Client { + todo!() + } + // Generate ECDHE shared secret + // Remove private secret + let ecdhe_shared_secret = + self.ecdhe_secret + .take() + .unwrap() + .diffie_hellman(&encoded_point) + .unwrap(); - // Generate Handshake secret - match cipher_suite { - CipherSuite::TLS_AES_128_GCM_SHA256 | - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 | - CipherSuite::TLS_AES_128_CCM_SHA256 => { - // Select 1 hash function, then update the hash - self.hash = Hash::select_sha256(self.hash.clone()); - self.hash.update(sh_slice); + // Generate Handshake secret + match cipher_suite { + CipherSuite::TLS_AES_128_GCM_SHA256 | + CipherSuite::TLS_CHACHA20_POLY1305_SHA256 | + CipherSuite::TLS_AES_128_CCM_SHA256 => { + // Select 1 hash function, then update the hash + self.hash = Hash::select_sha256(self.hash.clone()); + self.hash.update(sh_slice); - // Find early secret in terms wrapped in HKDF - let empty_psk: GenericArray::OutputSize> = Default::default(); - let early_secret_hkdf = - Hkdf::::new(None, &empty_psk); + // Find early secret in terms wrapped in HKDF + let empty_psk: GenericArray::OutputSize> = Default::default(); + let early_secret_hkdf = + Hkdf::::new(None, &empty_psk); - // Find handshake secret - let empty_hash = Sha256::new().chain(""); - let derived_secret = derive_secret( - &early_secret_hkdf, - "derived", - empty_hash - ); + // Find handshake secret + let empty_hash = Sha256::new().chain(""); + let derived_secret = derive_secret( + &early_secret_hkdf, + "derived", + empty_hash + ); - let (handshake_secret, handshake_secret_hkdf) = - Hkdf::::extract( - Some(&derived_secret), - ecdhe_shared_secret.as_bytes() - ); + let (handshake_secret, handshake_secret_hkdf) = + Hkdf::::extract( + Some(&derived_secret), + ecdhe_shared_secret.as_bytes() + ); - // Store the handshake secret - self.latest_secret.replace( - Vec::from_slice(&handshake_secret) - .unwrap() - ); + // Store the handshake secret + self.latest_secret.replace( + Vec::from_slice(&handshake_secret) + .unwrap() + ); - let client_handshake_traffic_secret = derive_secret( - &handshake_secret_hkdf, - "c hs traffic", - self.hash.get_sha256_clone() - ); + let client_handshake_traffic_secret = derive_secret( + &handshake_secret_hkdf, + "c hs traffic", + self.hash.get_sha256_clone() + ); - let server_handshake_traffic_secret = derive_secret( - &handshake_secret_hkdf, - "s hs traffic", - self.hash.get_sha256_clone() - ); + let server_handshake_traffic_secret = derive_secret( + &handshake_secret_hkdf, + "s hs traffic", + self.hash.get_sha256_clone() + ); - let client_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&client_handshake_traffic_secret).unwrap(); - let server_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&server_handshake_traffic_secret).unwrap(); + let client_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&client_handshake_traffic_secret).unwrap(); + let server_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&server_handshake_traffic_secret).unwrap(); - // Prepare holder for key and IV - let client_handshake_key: Vec = { - let mut client_handshake_key_holder: Vec = match cipher_suite { - // 16 bytes key size - CipherSuite::TLS_AES_128_GCM_SHA256 | - CipherSuite::TLS_AES_128_CCM_SHA256 => { - Vec::from_slice(&[0; 16]).unwrap() - }, - // 32 bytes key size - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { - Vec::from_slice(&[0; 32]).unwrap() - }, - // Not using Sha256 (AES_GCM_256) / not supported (CCM_8) - _ => unreachable!() - }; - hkdf_expand_label( - &client_handshake_traffic_secret_hkdf, - "key", - "", - &mut client_handshake_key_holder - ); - client_handshake_key_holder - }; + // Prepare holder for key and IV + let client_handshake_key: Vec = { + let mut client_handshake_key_holder: Vec = match cipher_suite { + // 16 bytes key size + CipherSuite::TLS_AES_128_GCM_SHA256 | + CipherSuite::TLS_AES_128_CCM_SHA256 => { + Vec::from_slice(&[0; 16]).unwrap() + }, + // 32 bytes key size + CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { + Vec::from_slice(&[0; 32]).unwrap() + }, + // Not using Sha256 (AES_GCM_256) / not supported (CCM_8) + _ => unreachable!() + }; + hkdf_expand_label( + &client_handshake_traffic_secret_hkdf, + "key", + "", + &mut client_handshake_key_holder + ); + client_handshake_key_holder + }; - let client_handshake_iv: Vec = { - let mut client_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); - hkdf_expand_label( - &client_handshake_traffic_secret_hkdf, - "iv", - "", - &mut client_handshake_iv_holder - ); - client_handshake_iv_holder - }; + let client_handshake_iv: Vec = { + let mut client_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); + hkdf_expand_label( + &client_handshake_traffic_secret_hkdf, + "iv", + "", + &mut client_handshake_iv_holder + ); + client_handshake_iv_holder + }; - let server_handshake_key: Vec = { - let mut server_handshake_key_holder: Vec = match cipher_suite { - // 16 bytes key size - CipherSuite::TLS_AES_128_GCM_SHA256 | - CipherSuite::TLS_AES_128_CCM_SHA256 => { - Vec::from_slice(&[0; 16]).unwrap() - }, - // 32 bytes key size - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { - Vec::from_slice(&[0; 32]).unwrap() - }, - // Not using Sha256 (AES_GCM_256) / not supported (CCM_8) - _ => unreachable!() - }; - hkdf_expand_label( - &server_handshake_traffic_secret_hkdf, - "key", - "", - &mut server_handshake_key_holder - ); - server_handshake_key_holder - }; + let server_handshake_key: Vec = { + let mut server_handshake_key_holder: Vec = match cipher_suite { + // 16 bytes key size + CipherSuite::TLS_AES_128_GCM_SHA256 | + CipherSuite::TLS_AES_128_CCM_SHA256 => { + Vec::from_slice(&[0; 16]).unwrap() + }, + // 32 bytes key size + CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { + Vec::from_slice(&[0; 32]).unwrap() + }, + // Not using Sha256 (AES_GCM_256) / not supported (CCM_8) + _ => unreachable!() + }; + hkdf_expand_label( + &server_handshake_traffic_secret_hkdf, + "key", + "", + &mut server_handshake_key_holder + ); + server_handshake_key_holder + }; - let server_handshake_iv: Vec = { - let mut server_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); - hkdf_expand_label( - &server_handshake_traffic_secret_hkdf, - "iv", - "", - &mut server_handshake_iv_holder - ); - server_handshake_iv_holder - }; + let server_handshake_iv: Vec = { + let mut server_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); + hkdf_expand_label( + &server_handshake_traffic_secret_hkdf, + "iv", + "", + &mut server_handshake_iv_holder + ); + server_handshake_iv_holder + }; - // Store nonce - self.client_nonce = Some(client_handshake_iv); - self.server_nonce = Some(server_handshake_iv); + // Store nonce + self.client_nonce = Some(client_handshake_iv); + self.server_nonce = Some(server_handshake_iv); - // Construct cipher from key & IV for client & server - // Store the ciphers - match cipher_suite { - CipherSuite::TLS_AES_128_GCM_SHA256 => { - let client_handshake_cipher = Aes128Gcm::new( - GenericArray::from_slice(&client_handshake_key) - ); - let server_handshake_cipher = Aes128Gcm::new( - GenericArray::from_slice(&server_handshake_key) - ); - self.client_cipher = Some( - Cipher::Aes128Gcm { - aes128gcm: client_handshake_cipher - } - ); - self.server_cipher = Some( - Cipher::Aes128Gcm { - aes128gcm: server_handshake_cipher - } - ); - }, - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { - let client_handshake_cipher = ChaCha20Poly1305::new( - GenericArray::from_slice(&client_handshake_key) - ); - let server_handshake_cipher = ChaCha20Poly1305::new( - GenericArray::from_slice(&server_handshake_key) - ); - self.client_cipher = Some( - Cipher::Chacha20poly1305 { - chacha20poly1305: client_handshake_cipher - } - ); - self.server_cipher = Some( - Cipher::Chacha20poly1305 { - chacha20poly1305: server_handshake_cipher - } - ); - }, - CipherSuite::TLS_AES_128_CCM_SHA256 => { - let client_handshake_cipher = Aes128Ccm::new( - GenericArray::from_slice(&client_handshake_key) - ); - let server_handshake_cipher = Aes128Ccm::new( - GenericArray::from_slice(&server_handshake_key) - ); - self.client_cipher = Some( - Cipher::Ccm { - ccm: client_handshake_cipher - } - ); - self.server_cipher = Some( - Cipher::Ccm { - ccm: server_handshake_cipher - } - ); - }, - _ => unreachable!() - } - }, - CipherSuite::TLS_AES_256_GCM_SHA384 => { - // Select 1 hash function, then update the hash - self.hash = Hash::select_sha384(self.hash.clone()); - self.hash.update(sh_slice); + // Construct cipher from key & IV for client & server + // Store the ciphers + match cipher_suite { + CipherSuite::TLS_AES_128_GCM_SHA256 => { + let client_handshake_cipher = Aes128Gcm::new( + GenericArray::from_slice(&client_handshake_key) + ); + let server_handshake_cipher = Aes128Gcm::new( + GenericArray::from_slice(&server_handshake_key) + ); + self.client_cipher = Some( + Cipher::Aes128Gcm { + aes128gcm: client_handshake_cipher + } + ); + self.server_cipher = Some( + Cipher::Aes128Gcm { + aes128gcm: server_handshake_cipher + } + ); + }, + CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { + let client_handshake_cipher = ChaCha20Poly1305::new( + GenericArray::from_slice(&client_handshake_key) + ); + let server_handshake_cipher = ChaCha20Poly1305::new( + GenericArray::from_slice(&server_handshake_key) + ); + self.client_cipher = Some( + Cipher::Chacha20poly1305 { + chacha20poly1305: client_handshake_cipher + } + ); + self.server_cipher = Some( + Cipher::Chacha20poly1305 { + chacha20poly1305: server_handshake_cipher + } + ); + }, + CipherSuite::TLS_AES_128_CCM_SHA256 => { + let client_handshake_cipher = Aes128Ccm::new( + GenericArray::from_slice(&client_handshake_key) + ); + let server_handshake_cipher = Aes128Ccm::new( + GenericArray::from_slice(&server_handshake_key) + ); + self.client_cipher = Some( + Cipher::Ccm { + ccm: client_handshake_cipher + } + ); + self.server_cipher = Some( + Cipher::Ccm { + ccm: server_handshake_cipher + } + ); + }, + _ => unreachable!() + } + }, + CipherSuite::TLS_AES_256_GCM_SHA384 => { + // Select 1 hash function, then update the hash + self.hash = Hash::select_sha384(self.hash.clone()); + self.hash.update(sh_slice); - // Find early secret in terms wrapped in HKDF - let empty_psk: GenericArray::OutputSize> = Default::default(); - let early_secret_hkdf = - Hkdf::::new(None, &empty_psk); + // Find early secret in terms wrapped in HKDF + let empty_psk: GenericArray::OutputSize> = Default::default(); + let early_secret_hkdf = + Hkdf::::new(None, &empty_psk); - // Find handshake secret - let empty_hash = Sha384::new().chain(""); - let derived_secret = derive_secret( - &early_secret_hkdf, - "derived", - empty_hash - ); + // Find handshake secret + let empty_hash = Sha384::new().chain(""); + let derived_secret = derive_secret( + &early_secret_hkdf, + "derived", + empty_hash + ); - let (handshake_secret, handshake_secret_hkdf) = - Hkdf::::extract( - Some(&derived_secret), - ecdhe_shared_secret.as_bytes() - ); + let (handshake_secret, handshake_secret_hkdf) = + Hkdf::::extract( + Some(&derived_secret), + ecdhe_shared_secret.as_bytes() + ); - // Store the handshake secret - self.latest_secret.replace( - Vec::from_slice(&handshake_secret) - .unwrap() - ); + // Store the handshake secret + self.latest_secret.replace( + Vec::from_slice(&handshake_secret) + .unwrap() + ); - let client_handshake_traffic_secret = derive_secret( - &handshake_secret_hkdf, - "c hs traffic", - self.hash.get_sha384_clone() - ); + let client_handshake_traffic_secret = derive_secret( + &handshake_secret_hkdf, + "c hs traffic", + self.hash.get_sha384_clone() + ); - let server_handshake_traffic_secret = derive_secret( - &handshake_secret_hkdf, - "s hs traffic", - self.hash.get_sha384_clone() - ); + let server_handshake_traffic_secret = derive_secret( + &handshake_secret_hkdf, + "s hs traffic", + self.hash.get_sha384_clone() + ); - let client_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&client_handshake_traffic_secret).unwrap(); - let server_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&server_handshake_traffic_secret).unwrap(); + let client_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&client_handshake_traffic_secret).unwrap(); + let server_handshake_traffic_secret_hkdf = Hkdf::::from_prk(&server_handshake_traffic_secret).unwrap(); - // Prepare holder for key and IV - let client_handshake_key: Vec = { - // 32 bytes key size - let mut client_handshake_key_holder: Vec = - Vec::from_slice(&[0; 32]).unwrap(); + // Prepare holder for key and IV + let client_handshake_key: Vec = { + // 32 bytes key size + let mut client_handshake_key_holder: Vec = + Vec::from_slice(&[0; 32]).unwrap(); - hkdf_expand_label( - &client_handshake_traffic_secret_hkdf, - "key", - "", - &mut client_handshake_key_holder - ); - client_handshake_key_holder - }; + hkdf_expand_label( + &client_handshake_traffic_secret_hkdf, + "key", + "", + &mut client_handshake_key_holder + ); + client_handshake_key_holder + }; - let client_handshake_iv: Vec = { - let mut client_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); - hkdf_expand_label( - &client_handshake_traffic_secret_hkdf, - "iv", - "", - &mut client_handshake_iv_holder - ); - client_handshake_iv_holder - }; + let client_handshake_iv: Vec = { + let mut client_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); + hkdf_expand_label( + &client_handshake_traffic_secret_hkdf, + "iv", + "", + &mut client_handshake_iv_holder + ); + client_handshake_iv_holder + }; - let server_handshake_key: Vec = { - // 32 bytes key size - let mut server_handshake_key_holder: Vec = - Vec::from_slice(&[0; 32]).unwrap(); + let server_handshake_key: Vec = { + // 32 bytes key size + let mut server_handshake_key_holder: Vec = + Vec::from_slice(&[0; 32]).unwrap(); - hkdf_expand_label( - &server_handshake_traffic_secret_hkdf, - "key", - "", - &mut server_handshake_key_holder - ); - server_handshake_key_holder - }; + hkdf_expand_label( + &server_handshake_traffic_secret_hkdf, + "key", + "", + &mut server_handshake_key_holder + ); + server_handshake_key_holder + }; - let server_handshake_iv: Vec = { - let mut server_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); - hkdf_expand_label( - &server_handshake_traffic_secret_hkdf, - "iv", - "", - &mut server_handshake_iv_holder - ); - server_handshake_iv_holder - }; + let server_handshake_iv: Vec = { + let mut server_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap(); + hkdf_expand_label( + &server_handshake_traffic_secret_hkdf, + "iv", + "", + &mut server_handshake_iv_holder + ); + server_handshake_iv_holder + }; - // Store nonce - self.client_nonce = Some(client_handshake_iv); - self.server_nonce = Some(server_handshake_iv); + // Store nonce + self.client_nonce = Some(client_handshake_iv); + self.server_nonce = Some(server_handshake_iv); - let client_handshake_cipher = Aes256Gcm::new( - GenericArray::from_slice(&client_handshake_key) - ); - let server_handshake_cipher = Aes256Gcm::new( - GenericArray::from_slice(&server_handshake_key) - ); - self.client_cipher = Some( - Cipher::Aes256Gcm { - aes256gcm: client_handshake_cipher - } - ); - self.server_cipher = Some( - Cipher::Aes256Gcm { - aes256gcm: server_handshake_cipher - } - ); + let client_handshake_cipher = Aes256Gcm::new( + GenericArray::from_slice(&client_handshake_key) + ); + let server_handshake_cipher = Aes256Gcm::new( + GenericArray::from_slice(&server_handshake_key) + ); + self.client_cipher = Some( + Cipher::Aes256Gcm { + aes256gcm: client_handshake_cipher + } + ); + self.server_cipher = Some( + Cipher::Aes256Gcm { + aes256gcm: server_handshake_cipher + } + ); - }, - CipherSuite::TLS_AES_128_CCM_8_SHA256 => { - unreachable!() - } - }; - self.state = TlsState::WAIT_EE; + }, + CipherSuite::TLS_AES_128_CCM_8_SHA256 => { + unreachable!() + } + }; + self.state = TlsState::WAIT_EE; - // Key exchange occurred, set seq_num to 0. - self.sequence_number = 0; - } + // Key exchange occurred, set seq_num to 0. + self.sequence_number = 0; + } - pub(crate) fn client_update_for_ee(&mut self) { - self.state = TlsState::WAIT_CERT_CR; - } + pub(crate) fn client_update_for_ee(&mut self) { + self.state = TlsState::WAIT_CERT_CR; + } - pub(crate) fn verify_session_id_echo(&self, session_id_echo: &[u8]) -> bool { - if let Some(session_id_inner) = self.session_id { - session_id_inner == session_id_echo - } else { - false - } - } + pub(crate) fn verify_session_id_echo(&self, session_id_echo: &[u8]) -> bool { + if let Some(session_id_inner) = self.session_id { + session_id_inner == session_id_echo + } else { + false + } + } - pub(crate) fn get_tls_state(&self) -> TlsState { - self.state - } + pub(crate) fn get_tls_state(&self) -> TlsState { + self.state + } - pub(crate) fn has_completed_handshake(&self) -> bool { - self.state == TlsState::CONNECTED - } + pub(crate) fn has_completed_handshake(&self) -> bool { + self.state == TlsState::CONNECTED + } - pub(crate) fn receive_change_cipher_spec(&mut self) { - self.changed_cipher_spec = true; - } + pub(crate) fn receive_change_cipher_spec(&mut self) { + self.changed_cipher_spec = true; + } - pub(crate) fn encrypt_in_place( - &self, - associated_data: &[u8], - buffer: &mut dyn Buffer - ) -> Result<(), Error> { - let (nonce, cipher): (&Vec, &Cipher) = match self.role { - TlsRole::Client => {( - self.client_nonce.as_ref().unwrap(), - self.client_cipher.as_ref().unwrap() - )}, - TlsRole::Server => {( - self.server_nonce.as_ref().unwrap(), - self.server_cipher.as_ref().unwrap() - )}, - }; + pub(crate) fn encrypt_in_place( + &self, + associated_data: &[u8], + buffer: &mut dyn Buffer + ) -> Result<(), Error> { + let (nonce, cipher): (&Vec, &Cipher) = match self.role { + TlsRole::Client => {( + self.client_nonce.as_ref().unwrap(), + self.client_cipher.as_ref().unwrap() + )}, + TlsRole::Server => {( + self.server_nonce.as_ref().unwrap(), + self.server_cipher.as_ref().unwrap() + )}, + }; - // Calculate XOR'ed nonce - let nonce: u128 = NetworkEndian::read_uint128(nonce, 12); - let clipped_seq_num: u128 = self.sequence_number.into(); - let mut processed_nonce: [u8; 12] = [0; 12]; - NetworkEndian::write_uint128(&mut processed_nonce, nonce ^ clipped_seq_num, 12); + // Calculate XOR'ed nonce + let nonce: u128 = NetworkEndian::read_uint128(nonce, 12); + let clipped_seq_num: u128 = self.sequence_number.into(); + let mut processed_nonce: [u8; 12] = [0; 12]; + NetworkEndian::write_uint128(&mut processed_nonce, nonce ^ clipped_seq_num, 12); - cipher.encrypt_in_place( - &GenericArray::from_slice(&processed_nonce), - associated_data, - buffer - ) - } + cipher.encrypt_in_place( + &GenericArray::from_slice(&processed_nonce), + associated_data, + buffer + ) + } - pub(crate) fn decrypt_in_place( - &self, - associated_data: &[u8], - buffer: &mut dyn Buffer - ) -> Result<(), Error> { - let (nonce, cipher): (&Vec, &Cipher) = match self.role { - TlsRole::Server => {( - self.client_nonce.as_ref().unwrap(), - self.client_cipher.as_ref().unwrap() - )}, - TlsRole::Client => {( - self.server_nonce.as_ref().unwrap(), - self.server_cipher.as_ref().unwrap() - )}, - }; + pub(crate) fn decrypt_in_place( + &self, + associated_data: &[u8], + buffer: &mut dyn Buffer + ) -> Result<(), Error> { + let (nonce, cipher): (&Vec, &Cipher) = match self.role { + TlsRole::Server => {( + self.client_nonce.as_ref().unwrap(), + self.client_cipher.as_ref().unwrap() + )}, + TlsRole::Client => {( + self.server_nonce.as_ref().unwrap(), + self.server_cipher.as_ref().unwrap() + )}, + }; - // Calculate XOR'ed nonce - let nonce: u128 = NetworkEndian::read_uint128(nonce, 12); - let clipped_seq_num: u128 = self.sequence_number.into(); - let mut processed_nonce: [u8; 12] = [0; 12]; - NetworkEndian::write_uint128(&mut processed_nonce, nonce ^ clipped_seq_num, 12); + // Calculate XOR'ed nonce + let nonce: u128 = NetworkEndian::read_uint128(nonce, 12); + let clipped_seq_num: u128 = self.sequence_number.into(); + let mut processed_nonce: [u8; 12] = [0; 12]; + NetworkEndian::write_uint128(&mut processed_nonce, nonce ^ clipped_seq_num, 12); - cipher.decrypt_in_place( - &GenericArray::from_slice(&processed_nonce), - associated_data, - buffer - ) - } + cipher.decrypt_in_place( + &GenericArray::from_slice(&processed_nonce), + associated_data, + buffer + ) + } - pub(crate) fn increment_sequence_number(&mut self) { - self.sequence_number += 1; - } + pub(crate) fn increment_sequence_number(&mut self) { + self.sequence_number += 1; + } } #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub(crate) enum TlsRole { - Client, - Server, + Client, + Server, } #[derive(Debug, Clone)] pub(crate) enum Hash { - Undetermined { - sha256: Sha256, - sha384: Sha384, - }, - Sha256 { - sha256: Sha256 - }, - Sha384 { - sha384: Sha384 - }, + Undetermined { + sha256: Sha256, + sha384: Sha384, + }, + Sha256 { + sha256: Sha256 + }, + Sha384 { + sha384: Sha384 + }, } impl Hash { - pub(crate) fn update(&mut self, data: &[u8]) { - match self { - Self::Undetermined { sha256, sha384 } => { - sha256.update(data); - sha384.update(data); - }, - Self::Sha256 { sha256 } => { - sha256.update(data); - }, - Self::Sha384 { sha384 } => { - sha384.update(data); - }, - } - } + pub(crate) fn update(&mut self, data: &[u8]) { + match self { + Self::Undetermined { sha256, sha384 } => { + sha256.update(data); + sha384.update(data); + }, + Self::Sha256 { sha256 } => { + sha256.update(data); + }, + Self::Sha384 { sha384 } => { + sha384.update(data); + }, + } + } - pub(crate) fn select_sha256(self) -> Self { - match self { - Self::Undetermined { sha256, sha384 } => { - Self::Sha256 { - sha256 - } - }, - _ => unreachable!() - } - } + pub(crate) fn select_sha256(self) -> Self { + match self { + Self::Undetermined { sha256, sha384 } => { + Self::Sha256 { + sha256 + } + }, + _ => unreachable!() + } + } - pub(crate) fn select_sha384(self) -> Self { - match self { - Self::Undetermined { sha256, sha384 } => { - Self::Sha384 { - sha384 - } - }, - _ => unreachable!() - } - } + pub(crate) fn select_sha384(self) -> Self { + match self { + Self::Undetermined { sha256, sha384 } => { + Self::Sha384 { + sha384 + } + }, + _ => unreachable!() + } + } - pub(crate) fn get_sha256_clone(&mut self) -> Sha256 { - if let Self::Sha256 { sha256 } = self { - sha256.clone() - } else { - unreachable!() - } - } + pub(crate) fn get_sha256_clone(&mut self) -> Sha256 { + if let Self::Sha256 { sha256 } = self { + sha256.clone() + } else { + unreachable!() + } + } - pub(crate) fn get_sha384_clone(&mut self) -> Sha384 { - if let Self::Sha384 { sha384 } = self { - sha384.clone() - } else { - unreachable!() - } - } + pub(crate) fn get_sha384_clone(&mut self) -> Sha384 { + if let Self::Sha384 { sha384 } = self { + sha384.clone() + } else { + unreachable!() + } + } } pub(crate) enum Cipher { - Aes128Gcm { - aes128gcm: Aes128Gcm - }, - Aes256Gcm { - aes256gcm: Aes256Gcm - }, - Chacha20poly1305 { - chacha20poly1305: ChaCha20Poly1305 - }, - Ccm { - ccm: Aes128Ccm - }, + Aes128Gcm { + aes128gcm: Aes128Gcm + }, + Aes256Gcm { + aes256gcm: Aes256Gcm + }, + Chacha20poly1305 { + chacha20poly1305: ChaCha20Poly1305 + }, + Ccm { + ccm: Aes128Ccm + }, } impl Cipher { - pub(crate) fn encrypt_in_place( - &self, - nonce: &GenericArray, - associated_data: &[u8], - buffer: &mut dyn Buffer - ) -> Result<(), Error> { - match self { - Cipher::Aes128Gcm { aes128gcm } => { - aes128gcm.encrypt_in_place(nonce, associated_data, buffer) - }, - Cipher::Aes256Gcm { aes256gcm } => { - aes256gcm.encrypt_in_place(nonce, associated_data, buffer) - }, - Cipher::Chacha20poly1305 { chacha20poly1305 } => { - chacha20poly1305.encrypt_in_place(nonce, associated_data, buffer) - }, - Cipher::Ccm { ccm } => { - ccm.encrypt_in_place(nonce, associated_data, buffer) - } - }.map_err(|_| Error::EncryptionError) - } + pub(crate) fn encrypt_in_place( + &self, + nonce: &GenericArray, + associated_data: &[u8], + buffer: &mut dyn Buffer + ) -> Result<(), Error> { + match self { + Cipher::Aes128Gcm { aes128gcm } => { + aes128gcm.encrypt_in_place(nonce, associated_data, buffer) + }, + Cipher::Aes256Gcm { aes256gcm } => { + aes256gcm.encrypt_in_place(nonce, associated_data, buffer) + }, + Cipher::Chacha20poly1305 { chacha20poly1305 } => { + chacha20poly1305.encrypt_in_place(nonce, associated_data, buffer) + }, + Cipher::Ccm { ccm } => { + ccm.encrypt_in_place(nonce, associated_data, buffer) + } + }.map_err(|_| Error::EncryptionError) + } - pub(crate) fn decrypt_in_place( - &self, - nonce: &GenericArray, - associated_data: &[u8], - buffer: &mut dyn Buffer - ) -> Result<(), Error> { - match self { - Cipher::Aes128Gcm { aes128gcm } => { - aes128gcm.decrypt_in_place(nonce, associated_data, buffer) - }, - Cipher::Aes256Gcm { aes256gcm } => { - aes256gcm.decrypt_in_place(nonce, associated_data, buffer) - }, - Cipher::Chacha20poly1305 { chacha20poly1305 } => { - chacha20poly1305.decrypt_in_place(nonce, associated_data, buffer) - }, - Cipher::Ccm { ccm } => { - ccm.decrypt_in_place(nonce, associated_data, buffer) - } - }.map_err(|_| Error::DecryptionError) - } + pub(crate) fn decrypt_in_place( + &self, + nonce: &GenericArray, + associated_data: &[u8], + buffer: &mut dyn Buffer + ) -> Result<(), Error> { + match self { + Cipher::Aes128Gcm { aes128gcm } => { + aes128gcm.decrypt_in_place(nonce, associated_data, buffer) + }, + Cipher::Aes256Gcm { aes256gcm } => { + aes256gcm.decrypt_in_place(nonce, associated_data, buffer) + }, + Cipher::Chacha20poly1305 { chacha20poly1305 } => { + chacha20poly1305.decrypt_in_place(nonce, associated_data, buffer) + }, + Cipher::Ccm { ccm } => { + ccm.decrypt_in_place(nonce, associated_data, buffer) + } + }.map_err(|_| Error::DecryptionError) + } } \ No newline at end of file diff --git a/src/tls.rs b/src/tls.rs index 3eee0ed..f048337 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -41,443 +41,443 @@ use crate::session::{Session, TlsRole}; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[allow(non_camel_case_types)] pub(crate) enum TlsState { - START, - WAIT_SH, - WAIT_EE, - WAIT_CERT_CR, - WAIT_CERT, - WAIT_CV, - WAIT_FINISHED, - CONNECTED, + START, + WAIT_SH, + WAIT_EE, + WAIT_CERT_CR, + WAIT_CERT, + WAIT_CV, + WAIT_FINISHED, + CONNECTED, } // TODO: Group up all session_specific parameters into a separate structure pub struct TlsSocket { - tcp_handle: SocketHandle, - rng: R, - session: RefCell, + tcp_handle: SocketHandle, + rng: R, + session: RefCell, } impl TlsSocket { - pub fn new<'a, 'b, 'c>( - sockets: &mut SocketSet<'a, 'b, 'c>, - rx_buffer: TcpSocketBuffer<'b>, - tx_buffer: TcpSocketBuffer<'b>, - rng: R, - ) -> Self - where - 'b: 'c, - { - let tcp_socket = TcpSocket::new(rx_buffer, tx_buffer); - let tcp_handle = sockets.add(tcp_socket); - TlsSocket { - tcp_handle, - rng, - session: RefCell::new( - Session::new(TlsRole::Client) - ), - } - } + pub fn new<'a, 'b, 'c>( + sockets: &mut SocketSet<'a, 'b, 'c>, + rx_buffer: TcpSocketBuffer<'b>, + tx_buffer: TcpSocketBuffer<'b>, + rng: R, + ) -> Self + where + 'b: 'c, + { + let tcp_socket = TcpSocket::new(rx_buffer, tx_buffer); + let tcp_handle = sockets.add(tcp_socket); + TlsSocket { + tcp_handle, + rng, + session: RefCell::new( + Session::new(TlsRole::Client) + ), + } + } - pub fn tcp_connect( - &mut self, - sockets: &mut SocketSet, - remote_endpoint: T, - local_endpoint: U, - ) -> Result<()> - where - T: Into, - U: Into, - { - let mut tcp_socket = sockets.get::(self.tcp_handle); - if tcp_socket.state() == TcpState::Established { - Ok(()) - } else { - tcp_socket.connect(remote_endpoint, local_endpoint) - } - } + pub fn tcp_connect( + &mut self, + sockets: &mut SocketSet, + remote_endpoint: T, + local_endpoint: U, + ) -> Result<()> + where + T: Into, + U: Into, + { + let mut tcp_socket = sockets.get::(self.tcp_handle); + if tcp_socket.state() == TcpState::Established { + Ok(()) + } else { + tcp_socket.connect(remote_endpoint, local_endpoint) + } + } - pub fn tls_connect( - &mut self, - iface: &mut EthernetInterface, - sockets: &mut SocketSet, - now: Instant - ) -> Result - where - DeviceT: for<'d> Device<'d> - { - // Check tcp_socket connectivity - { - let mut tcp_socket = sockets.get::(self.tcp_handle); - tcp_socket.set_keep_alive(Some(smoltcp::time::Duration::from_millis(1000))); - if tcp_socket.state() != TcpState::Established { - return Ok(false); - } - } + pub fn tls_connect( + &mut self, + iface: &mut EthernetInterface, + sockets: &mut SocketSet, + now: Instant + ) -> Result + where + DeviceT: for<'d> Device<'d> + { + // Check tcp_socket connectivity + { + let mut tcp_socket = sockets.get::(self.tcp_handle); + tcp_socket.set_keep_alive(Some(smoltcp::time::Duration::from_millis(1000))); + if tcp_socket.state() != TcpState::Established { + return Ok(false); + } + } - // Handle TLS handshake through TLS states - let tls_state = { - self.session.borrow().get_tls_state() - }; - match tls_state { - // Initiate TLS handshake - TlsState::START => { - // Prepare field that is randomised, - // Supply it to the TLS repr builder. - let ecdh_secret = EphemeralSecret::random(&mut self.rng); - let mut random: [u8; 32] = [0; 32]; - let mut session_id: [u8; 32] = [0; 32]; - self.rng.fill_bytes(&mut random); - self.rng.fill_bytes(&mut session_id); - let repr = TlsRepr::new() - .client_hello(&ecdh_secret, random, session_id.clone()); + // Handle TLS handshake through TLS states + let tls_state = { + self.session.borrow().get_tls_state() + }; + match tls_state { + // Initiate TLS handshake + TlsState::START => { + // Prepare field that is randomised, + // Supply it to the TLS repr builder. + let ecdh_secret = EphemeralSecret::random(&mut self.rng); + let mut random: [u8; 32] = [0; 32]; + let mut session_id: [u8; 32] = [0; 32]; + self.rng.fill_bytes(&mut random); + self.rng.fill_bytes(&mut session_id); + let repr = TlsRepr::new() + .client_hello(&ecdh_secret, random, session_id.clone()); - // Update hash function with client hello handshake - let mut array = [0; 512]; - let mut buffer = TlsBuffer::new(&mut array); - buffer.enqueue_tls_repr(repr)?; - let slice: &[u8] = buffer.into(); + // Update hash function with client hello handshake + let mut array = [0; 512]; + let mut buffer = TlsBuffer::new(&mut array); + buffer.enqueue_tls_repr(repr)?; + let slice: &[u8] = buffer.into(); - // Send the packet - self.send_tls_slice(sockets, slice)?; + // Send the packet + self.send_tls_slice(sockets, slice)?; - // Update TLS session - self.session.borrow_mut().client_update_for_ch( - ecdh_secret, - session_id, - &slice[5..] - ); - }, + // Update TLS session + self.session.borrow_mut().client_update_for_ch( + ecdh_secret, + session_id, + &slice[5..] + ); + }, - // TLS Client wait for Server Hello - // No need to send anything - TlsState::WAIT_SH => {}, + // TLS Client wait for Server Hello + // No need to send anything + TlsState::WAIT_SH => {}, - // TLS Client wait for certificate from TLS server - // No need to send anything - // Note: TLS server should normally send SH alongside EE - // TLS client should jump from WAIT_SH directly to WAIT_CERT_CR directly. - TlsState::WAIT_EE => {}, + // TLS Client wait for certificate from TLS server + // No need to send anything + // Note: TLS server should normally send SH alongside EE + // TLS client should jump from WAIT_SH directly to WAIT_CERT_CR directly. + TlsState::WAIT_EE => {}, - // TLS Client wait for server's certificate - // No need to send anything - TlsState::WAIT_CERT_CR => {}, + // TLS Client wait for server's certificate + // No need to send anything + TlsState::WAIT_CERT_CR => {}, - _ => todo!() - } + _ => todo!() + } - // Poll the network interface - iface.poll(sockets, now); + // Poll the network interface + iface.poll(sockets, now); - // Read for TLS packet - let mut array: [u8; 2048] = [0; 2048]; - let mut tls_repr_vec = self.recv_tls_repr(sockets, &mut array)?; + // Read for TLS packet + let mut array: [u8; 2048] = [0; 2048]; + let mut tls_repr_vec = self.recv_tls_repr(sockets, &mut array)?; - // Take the TLS representation out of the vector, - // Process as a queue - let tls_repr_vec_size = tls_repr_vec.len(); - for index in 0..tls_repr_vec_size { - let repr = tls_repr_vec.remove(0); - self.process(repr)?; - } + // Take the TLS representation out of the vector, + // Process as a queue + let tls_repr_vec_size = tls_repr_vec.len(); + for index in 0..tls_repr_vec_size { + let repr = tls_repr_vec.remove(0); + self.process(repr)?; + } - Ok(self.session.borrow().has_completed_handshake()) - } + Ok(self.session.borrow().has_completed_handshake()) + } - // Process TLS ingress during handshake - fn process(&self, mut repr: TlsRepr) -> Result<()> { - // Change_cipher_spec check: - // Must receive CCS before recv peer's FINISH message - // i.e. Must happen after START and before CONNECTED - // - // CCS message only exist for compatibility reason, - // Drop the message and update `received_change_cipher_spec` - // Note: CSS doesn't count as a proper record, no need to increment sequence number - if repr.is_change_cipher_spec() { - let mut session = self.session.borrow_mut(); - session.receive_change_cipher_spec(); - return Ok(()) - } + // Process TLS ingress during handshake + fn process(&self, mut repr: TlsRepr) -> Result<()> { + // Change_cipher_spec check: + // Must receive CCS before recv peer's FINISH message + // i.e. Must happen after START and before CONNECTED + // + // CCS message only exist for compatibility reason, + // Drop the message and update `received_change_cipher_spec` + // Note: CSS doesn't count as a proper record, no need to increment sequence number + if repr.is_change_cipher_spec() { + let mut session = self.session.borrow_mut(); + session.receive_change_cipher_spec(); + return Ok(()) + } - let tls_state = { - self.session.borrow().get_tls_state() - }; - match tls_state { - // During WAIT_SH for a TLS client, client should wait for ServerHello - TlsState::WAIT_SH => { - // Legacy_protocol must be TLS 1.2 - if repr.version != TlsVersion::Tls12 { - // Abort communication - todo!() - } + let tls_state = { + self.session.borrow().get_tls_state() + }; + match tls_state { + // During WAIT_SH for a TLS client, client should wait for ServerHello + TlsState::WAIT_SH => { + // Legacy_protocol must be TLS 1.2 + if repr.version != TlsVersion::Tls12 { + // Abort communication + todo!() + } - // TODO: Validate SH - if repr.is_server_hello() { - // Check SH content: - // random: Cannot represent HelloRequestRetry - // (TODO: Support other key shares, e.g. X25519) - // session_id_echo: should be same as the one sent by client - // cipher_suite: Store - // (TODO: Check if such suite was offered) - // compression_method: Must be null, not supported in TLS 1.3 - // - // Check extensions: - // supported_version: Must be TLS 1.3 - // key_share: Store key, must be in secp256r1 - // (TODO: Support other key shares ^) + // TODO: Validate SH + if repr.is_server_hello() { + // Check SH content: + // random: Cannot represent HelloRequestRetry + // (TODO: Support other key shares, e.g. X25519) + // session_id_echo: should be same as the one sent by client + // cipher_suite: Store + // (TODO: Check if such suite was offered) + // compression_method: Must be null, not supported in TLS 1.3 + // + // Check extensions: + // supported_version: Must be TLS 1.3 + // key_share: Store key, must be in secp256r1 + // (TODO: Support other key shares ^) - // "Cache" for ECDHE server public info - let mut server_public: Option = None; - let mut selected_cipher: Option = None; + // "Cache" for ECDHE server public info + let mut server_public: Option = None; + let mut selected_cipher: Option = None; - // Process the handshake data within ServerHello - let handshake_data = &repr.handshake.as_ref().unwrap().handshake_data; - if let HandshakeData::ServerHello(server_hello) = handshake_data { + // Process the handshake data within ServerHello + let handshake_data = &repr.handshake.as_ref().unwrap().handshake_data; + if let HandshakeData::ServerHello(server_hello) = handshake_data { - // Check random: Cannot be SHA-256 of "HelloRetryRequest" - if server_hello.random == HRR_RANDOM { - // Abort communication - todo!() - } + // Check random: Cannot be SHA-256 of "HelloRetryRequest" + if server_hello.random == HRR_RANDOM { + // Abort communication + todo!() + } - // Check session_id_echo - // The socket should have a session_id after moving from START state - if !self.session.borrow().verify_session_id_echo(server_hello.session_id_echo) { - // Abort communication - todo!() - } + // Check session_id_echo + // The socket should have a session_id after moving from START state + if !self.session.borrow().verify_session_id_echo(server_hello.session_id_echo) { + // Abort communication + todo!() + } - // Note the selected cipher suite - selected_cipher.replace(server_hello.cipher_suite); + // Note the selected cipher suite + selected_cipher.replace(server_hello.cipher_suite); - // TLSv13 forbidden key compression - if server_hello.compression_method != 0 { - // Abort communciation - todo!() - } + // TLSv13 forbidden key compression + if server_hello.compression_method != 0 { + // Abort communciation + todo!() + } - for extension in server_hello.extensions.iter() { - if extension.extension_type == ExtensionType::SupportedVersions { - if let ExtensionData::SupportedVersions( - SupportedVersions::ServerHello { - selected_version - } - ) = extension.extension_data { - if selected_version != TlsVersion::Tls13 { - // Abort for choosing not offered TLS version - todo!() - } - } else { - // Abort for illegal extension - todo!() - } - } + for extension in server_hello.extensions.iter() { + if extension.extension_type == ExtensionType::SupportedVersions { + if let ExtensionData::SupportedVersions( + SupportedVersions::ServerHello { + selected_version + } + ) = extension.extension_data { + if selected_version != TlsVersion::Tls13 { + // Abort for choosing not offered TLS version + todo!() + } + } else { + // Abort for illegal extension + todo!() + } + } - if extension.extension_type == ExtensionType::KeyShare { - if let ExtensionData::KeyShareEntry( - KeyShareEntryContent::KeyShareServerHello { - server_share - } - ) = &extension.extension_data { - // TODO: Use legitimate checking to ensure the chosen - // group is indeed acceptable, when allowing more (EC)DHE - // key sharing - if server_share.group != NamedGroup::secp256r1 { - // Abort for wrong key sharing - todo!() - } - // Store key - // It is surely from secp256r1, no other groups are permitted - // Convert untagged bytes into encoded point on p256 eliptic curve - // Slice the first byte out of the bytes - server_public.replace( - EncodedPoint::from_untagged_bytes( - GenericArray::from_slice(&server_share.key_exchange[1..]) - ) - ); - } - } - } + if extension.extension_type == ExtensionType::KeyShare { + if let ExtensionData::KeyShareEntry( + KeyShareEntryContent::KeyShareServerHello { + server_share + } + ) = &extension.extension_data { + // TODO: Use legitimate checking to ensure the chosen + // group is indeed acceptable, when allowing more (EC)DHE + // key sharing + if server_share.group != NamedGroup::secp256r1 { + // Abort for wrong key sharing + todo!() + } + // Store key + // It is surely from secp256r1, no other groups are permitted + // Convert untagged bytes into encoded point on p256 eliptic curve + // Slice the first byte out of the bytes + server_public.replace( + EncodedPoint::from_untagged_bytes( + GenericArray::from_slice(&server_share.key_exchange[1..]) + ) + ); + } + } + } - } else { - // Handle invalid TLS packet - todo!() - } + } else { + // Handle invalid TLS packet + todo!() + } - // Check that both selected_cipher and server_public were received - if selected_cipher.is_none() || server_public.is_none() { - // Abort communication - todo!() - } + // Check that both selected_cipher and server_public were received + if selected_cipher.is_none() || server_public.is_none() { + // Abort communication + todo!() + } - // This is indeed a desirable ServerHello TLS repr - // Reprocess ServerHello into a slice - // Update session with required parameter - let mut array = [0; 512]; - let mut buffer = TlsBuffer::new(&mut array); - buffer.enqueue_tls_repr(repr)?; - let slice: &[u8] = buffer.into(); - let mut session = self.session.borrow_mut(); - session.client_update_for_sh( - selected_cipher.unwrap(), - server_public.unwrap(), - &slice[5..] - ); - // Key exchange occurred, seq_num is set to 0 - // Do NOT update seq_num again. Early return. - return Ok(()); - } - }, + // This is indeed a desirable ServerHello TLS repr + // Reprocess ServerHello into a slice + // Update session with required parameter + let mut array = [0; 512]; + let mut buffer = TlsBuffer::new(&mut array); + buffer.enqueue_tls_repr(repr)?; + let slice: &[u8] = buffer.into(); + let mut session = self.session.borrow_mut(); + session.client_update_for_sh( + selected_cipher.unwrap(), + server_public.unwrap(), + &slice[5..] + ); + // Key exchange occurred, seq_num is set to 0 + // Do NOT update seq_num again. Early return. + return Ok(()); + } + }, - // Expect encrypted extensions after receiving SH - TlsState::WAIT_EE => { - // Check that the packet is classified as application data - if !repr.is_application_data() { - // Abort communication, this affect IV calculation - todo!() - } + // Expect encrypted extensions after receiving SH + TlsState::WAIT_EE => { + // Check that the packet is classified as application data + if !repr.is_application_data() { + // Abort communication, this affect IV calculation + todo!() + } - // ExcepytedExtensions are disguised as ApplicationData - // Pull out the `payload` from TlsRepr, decrypt as EE - let mut payload = repr.payload.take().unwrap(); - log::info!("Encrypted payload: {:?}", payload); - let mut array: [u8; 5] = [0; 5]; - let mut buffer = TlsBuffer::new(&mut array); - buffer.write_u8(repr.content_type.into())?; - buffer.write_u16(repr.version.into())?; - buffer.write_u16(repr.length)?; - let associated_data: &[u8] = buffer.into(); - log::info!("Associated Data: {:?}", associated_data); - { - self.session.borrow_mut().decrypt_in_place( - associated_data, - &mut payload - ); - } - log::info!("decrypted EE"); - log::info!("{:?}", payload); + // ExcepytedExtensions are disguised as ApplicationData + // Pull out the `payload` from TlsRepr, decrypt as EE + let mut payload = repr.payload.take().unwrap(); + log::info!("Encrypted payload: {:?}", payload); + let mut array: [u8; 5] = [0; 5]; + let mut buffer = TlsBuffer::new(&mut array); + buffer.write_u8(repr.content_type.into())?; + buffer.write_u16(repr.version.into())?; + buffer.write_u16(repr.length)?; + let associated_data: &[u8] = buffer.into(); + log::info!("Associated Data: {:?}", associated_data); + { + self.session.borrow_mut().decrypt_in_place( + associated_data, + &mut payload + ); + } + log::info!("decrypted EE"); + log::info!("{:?}", payload); - // TODO: Parse payload of EE - let parse_result = parse_handshake(&payload); - let (_, encrypted_extensions_handshake) = parse_result - .map_err(|_| Error::Unrecognized)?; - // TODO: Process payload - // Practically, nothing will be done about cookies/server name - // Extension processing is therefore skipped - log::info!("Parsed EE"); - self.session.borrow_mut().client_update_for_ee(); - }, + // TODO: Parse payload of EE + let parse_result = parse_handshake(&payload); + let (_, encrypted_extensions_handshake) = parse_result + .map_err(|_| Error::Unrecognized)?; + // TODO: Process payload + // Practically, nothing will be done about cookies/server name + // Extension processing is therefore skipped + log::info!("Parsed EE"); + self.session.borrow_mut().client_update_for_ee(); + }, - // In this stage, wait for a certificate from server - // Parse the certificate and check its content - TlsState::WAIT_CERT_CR => { - // Check that the packet is classified as application data - // Certificates transfer is disguised as application data - if !repr.is_application_data() { - // Abort communication, this affect IV calculation - todo!() - } + // In this stage, wait for a certificate from server + // Parse the certificate and check its content + TlsState::WAIT_CERT_CR => { + // Check that the packet is classified as application data + // Certificates transfer is disguised as application data + if !repr.is_application_data() { + // Abort communication, this affect IV calculation + todo!() + } - // Pull out the `payload` from TlsRepr, decrypt as EE - let mut payload = repr.payload.take().unwrap(); + // Pull out the `payload` from TlsRepr, decrypt as EE + let mut payload = repr.payload.take().unwrap(); - // Instantiate associated data and decrypt - let mut array: [u8; 5] = [0; 5]; - let mut buffer = TlsBuffer::new(&mut array); - buffer.write_u8(repr.content_type.into())?; - buffer.write_u16(repr.version.into())?; - buffer.write_u16(repr.length)?; - let associated_data: &[u8] = buffer.into(); - { - self.session.borrow_mut().decrypt_in_place( - associated_data, - &mut payload - ); - } - log::info!("Decrypted payload {:?}", payload); - }, + // Instantiate associated data and decrypt + let mut array: [u8; 5] = [0; 5]; + let mut buffer = TlsBuffer::new(&mut array); + buffer.write_u8(repr.content_type.into())?; + buffer.write_u16(repr.version.into())?; + buffer.write_u16(repr.length)?; + let associated_data: &[u8] = buffer.into(); + { + self.session.borrow_mut().decrypt_in_place( + associated_data, + &mut payload + ); + } + log::info!("Decrypted payload {:?}", payload); + }, - _ => {}, - } + _ => {}, + } - // A TLS Record was received and processed and verified - // Increment sequence number - self.session.borrow_mut().increment_sequence_number(); + // A TLS Record was received and processed and verified + // Increment sequence number + self.session.borrow_mut().increment_sequence_number(); - Ok(()) - } + Ok(()) + } - // Generic inner send method, through TCP socket - fn send_tls_repr(&self, sockets: &mut SocketSet, tls_repr: TlsRepr) -> Result<()> { - let mut tcp_socket = sockets.get::(self.tcp_handle); - if !tcp_socket.can_send() { - return Err(Error::Illegal); - } - let mut array = [0; 2048]; - let mut buffer = TlsBuffer::new(&mut array); - buffer.enqueue_tls_repr(tls_repr)?; - let buffer_size = buffer.get_size(); + // Generic inner send method, through TCP socket + fn send_tls_repr(&self, sockets: &mut SocketSet, tls_repr: TlsRepr) -> Result<()> { + let mut tcp_socket = sockets.get::(self.tcp_handle); + if !tcp_socket.can_send() { + return Err(Error::Illegal); + } + let mut array = [0; 2048]; + let mut buffer = TlsBuffer::new(&mut array); + buffer.enqueue_tls_repr(tls_repr)?; + let buffer_size = buffer.get_size(); - // Force send to return if send is unsuccessful - // Only update sequence number if the send is successful - tcp_socket.send_slice(buffer.into()) - .and_then( - |size| if size == buffer_size { - Ok(()) - } else { - Err(Error::Truncated) - } - )?; - self.session.borrow_mut().increment_sequence_number(); - Ok(()) - } + // Force send to return if send is unsuccessful + // Only update sequence number if the send is successful + tcp_socket.send_slice(buffer.into()) + .and_then( + |size| if size == buffer_size { + Ok(()) + } else { + Err(Error::Truncated) + } + )?; + self.session.borrow_mut().increment_sequence_number(); + Ok(()) + } - // Generic inner send method for buffer IO, through TCP socket - // Usage: Push a slice representation of ONE TLS packet - // This function will only increment sequence number by 1 - // Repeatedly call this function if sending multiple TLS packets is needed - fn send_tls_slice(&self, sockets: &mut SocketSet, slice: &[u8]) -> Result<()> { - let mut tcp_socket = sockets.get::(self.tcp_handle); - if !tcp_socket.can_send() { - return Err(Error::Illegal); - } - let buffer_size = slice.len(); - tcp_socket.send_slice(slice) - .and_then( - |size| if size == buffer_size { - Ok(()) - } else { - Err(Error::Truncated) - } - )?; - self.session.borrow_mut().increment_sequence_number(); - Ok(()) - } + // Generic inner send method for buffer IO, through TCP socket + // Usage: Push a slice representation of ONE TLS packet + // This function will only increment sequence number by 1 + // Repeatedly call this function if sending multiple TLS packets is needed + fn send_tls_slice(&self, sockets: &mut SocketSet, slice: &[u8]) -> Result<()> { + let mut tcp_socket = sockets.get::(self.tcp_handle); + if !tcp_socket.can_send() { + return Err(Error::Illegal); + } + let buffer_size = slice.len(); + tcp_socket.send_slice(slice) + .and_then( + |size| if size == buffer_size { + Ok(()) + } else { + Err(Error::Truncated) + } + )?; + self.session.borrow_mut().increment_sequence_number(); + Ok(()) + } - // Generic inner recv method, through TCP socket - // A TCP packet can contain multiple TLS records (including 0) - // Therefore, sequence nubmer incrementation is not completed here - fn recv_tls_repr<'a>(&'a self, sockets: &mut SocketSet, byte_array: &'a mut [u8]) -> Result> { - let mut tcp_socket = sockets.get::(self.tcp_handle); - if !tcp_socket.can_recv() { - return Ok((Vec::new())); - } - let array_size = tcp_socket.recv_slice(byte_array)?; - let mut vec: Vec = Vec::new(); - let mut bytes: &[u8] = &byte_array[..array_size]; - loop { - match parse_tls_repr(bytes) { - Ok((rest, repr)) => { - vec.push(repr); - if rest.len() == 0 { - return Ok(vec); - } else { - bytes = rest; - } - }, - _ => return Err(Error::Unrecognized), - }; - } - } + // Generic inner recv method, through TCP socket + // A TCP packet can contain multiple TLS records (including 0) + // Therefore, sequence nubmer incrementation is not completed here + fn recv_tls_repr<'a>(&'a self, sockets: &mut SocketSet, byte_array: &'a mut [u8]) -> Result> { + let mut tcp_socket = sockets.get::(self.tcp_handle); + if !tcp_socket.can_recv() { + return Ok((Vec::new())); + } + let array_size = tcp_socket.recv_slice(byte_array)?; + let mut vec: Vec = Vec::new(); + let mut bytes: &[u8] = &byte_array[..array_size]; + loop { + match parse_tls_repr(bytes) { + Ok((rest, repr)) => { + vec.push(repr); + if rest.len() == 0 { + return Ok(vec); + } else { + bytes = rest; + } + }, + _ => return Err(Error::Unrecognized), + }; + } + } } diff --git a/src/tls_packet.rs b/src/tls_packet.rs index dc9d6e7..e68b4fc 100644 --- a/src/tls_packet.rs +++ b/src/tls_packet.rs @@ -13,664 +13,664 @@ use core::convert::TryInto; use alloc::vec::Vec; pub(crate) const HRR_RANDOM: [u8; 32] = [ - 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, - 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, - 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, - 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C + 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C ]; #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub(crate) enum TlsContentType { - #[num_enum(default)] - Invalid = 0, - ChangeCipherSpec = 20, - Alert = 21, - Handshake = 22, - ApplicationData = 23 + #[num_enum(default)] + Invalid = 0, + ChangeCipherSpec = 20, + Alert = 21, + Handshake = 22, + ApplicationData = 23 } #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[repr(u16)] pub(crate) enum TlsVersion { - #[num_enum(default)] - Unknown = 0x0000, - Tls10 = 0x0301, - Tls11 = 0x0302, - Tls12 = 0x0303, - Tls13 = 0x0304, + #[num_enum(default)] + Unknown = 0x0000, + Tls10 = 0x0301, + Tls11 = 0x0302, + Tls12 = 0x0303, + Tls13 = 0x0304, } #[derive(Debug, Clone)] pub(crate) struct TlsRepr<'a> { - pub(crate) content_type: TlsContentType, - pub(crate) version: TlsVersion, - pub(crate) length: u16, - pub(crate) payload: Option>, - pub(crate) handshake: Option> + pub(crate) content_type: TlsContentType, + pub(crate) version: TlsVersion, + pub(crate) length: u16, + pub(crate) payload: Option>, + pub(crate) handshake: Option> } impl<'a> TlsRepr<'a> { - pub(crate) fn new() -> Self { - TlsRepr { - content_type: TlsContentType::Invalid, - version: TlsVersion::Tls12, - length: 0, - payload: None, - handshake: None, - } - } + pub(crate) fn new() -> Self { + TlsRepr { + content_type: TlsContentType::Invalid, + version: TlsVersion::Tls12, + length: 0, + payload: None, + handshake: None, + } + } - pub(crate) fn client_hello(mut self, secret: &EphemeralSecret, random: [u8; 32], session_id: [u8; 32]) -> Self { - self.content_type = TlsContentType::Handshake; - self.version = TlsVersion::Tls10; - let handshake_repr = { - let mut repr = HandshakeRepr::new(); - repr.msg_type = HandshakeType::ClientHello; - repr.handshake_data = HandshakeData::ClientHello({ - ClientHello::new(secret, random, session_id) - }); - repr.length = repr.handshake_data.get_length().try_into().unwrap(); - repr - }; - self.length = handshake_repr.get_length(); - self.handshake = Some(handshake_repr); - self - } + pub(crate) fn client_hello(mut self, secret: &EphemeralSecret, random: [u8; 32], session_id: [u8; 32]) -> Self { + self.content_type = TlsContentType::Handshake; + self.version = TlsVersion::Tls10; + let handshake_repr = { + let mut repr = HandshakeRepr::new(); + repr.msg_type = HandshakeType::ClientHello; + repr.handshake_data = HandshakeData::ClientHello({ + ClientHello::new(secret, random, session_id) + }); + repr.length = repr.handshake_data.get_length().try_into().unwrap(); + repr + }; + self.length = handshake_repr.get_length(); + self.handshake = Some(handshake_repr); + self + } - pub(crate) fn is_server_hello(&self) -> bool { - self.content_type == TlsContentType::Handshake && - self.payload.is_none() && - self.handshake.is_some() && - { - if let Some(repr) = &self.handshake { - repr.msg_type == HandshakeType::ServerHello - } else { - false - } - } - } + pub(crate) fn is_server_hello(&self) -> bool { + self.content_type == TlsContentType::Handshake && + self.payload.is_none() && + self.handshake.is_some() && + { + if let Some(repr) = &self.handshake { + repr.msg_type == HandshakeType::ServerHello + } else { + false + } + } + } - pub(crate) fn is_change_cipher_spec(&self) -> bool { - self.content_type == TlsContentType::ChangeCipherSpec && - self.handshake.is_none() && - self.payload.is_some() && - { - if let Some(data) = &self.payload { - data[0] == 0x01 && - data.len() == 1 - } else { - false - } - } - } + pub(crate) fn is_change_cipher_spec(&self) -> bool { + self.content_type == TlsContentType::ChangeCipherSpec && + self.handshake.is_none() && + self.payload.is_some() && + { + if let Some(data) = &self.payload { + data[0] == 0x01 && + data.len() == 1 + } else { + false + } + } + } - pub(crate) fn is_application_data(&self) -> bool { - self.content_type == TlsContentType::ApplicationData && - self.handshake.is_none() && - self.payload.is_some() - } + pub(crate) fn is_application_data(&self) -> bool { + self.content_type == TlsContentType::ApplicationData && + self.handshake.is_none() && + self.payload.is_some() + } - pub(crate) fn decrypt_ee(&self, shared_secret: &SharedSecret) -> HandshakeRepr { - todo!() - } + pub(crate) fn decrypt_ee(&self, shared_secret: &SharedSecret) -> HandshakeRepr { + todo!() + } } #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub(crate) enum HandshakeType { - #[num_enum(default)] - Unknown = 0, - ClientHello = 1, - ServerHello = 2, - NewSessionTicket = 4, - EndOfEarlyData = 5, - EncryptedExtensions = 8, - Certificate = 11, - CertificateRequest = 13, - CertificateVerify = 15, - Finished = 20, - KeyUpdate = 24, - MessageHash = 254, + #[num_enum(default)] + Unknown = 0, + ClientHello = 1, + ServerHello = 2, + NewSessionTicket = 4, + EndOfEarlyData = 5, + EncryptedExtensions = 8, + Certificate = 11, + CertificateRequest = 13, + CertificateVerify = 15, + Finished = 20, + KeyUpdate = 24, + MessageHash = 254, } #[derive(Debug, Clone)] pub(crate) struct HandshakeRepr<'a> { - pub(crate) msg_type: HandshakeType, - pub(crate) length: u32, - pub(crate) handshake_data: HandshakeData<'a>, + pub(crate) msg_type: HandshakeType, + pub(crate) length: u32, + pub(crate) handshake_data: HandshakeData<'a>, } impl<'a, 'b> HandshakeRepr<'a> { - pub(self) fn new() -> Self { - HandshakeRepr { - msg_type: HandshakeType::Unknown, - length: 0, - handshake_data: HandshakeData::Uninitialized, - } - } + pub(self) fn new() -> Self { + HandshakeRepr { + msg_type: HandshakeType::Unknown, + length: 0, + handshake_data: HandshakeData::Uninitialized, + } + } - pub(crate) fn get_length(&self) -> u16 { - let mut length :u16 = 1; // Handshake Type - length += 3; // Length of Handshake data - length += u16::try_from(self.handshake_data.get_length()).unwrap(); - length - } + pub(crate) fn get_length(&self) -> u16 { + let mut length :u16 = 1; // Handshake Type + length += 3; // Length of Handshake data + length += u16::try_from(self.handshake_data.get_length()).unwrap(); + length + } } #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[allow(non_camel_case_types)] #[repr(u16)] pub(crate) enum CipherSuite { - TLS_AES_128_GCM_SHA256 = 0x1301, - TLS_AES_256_GCM_SHA384 = 0x1302, - TLS_CHACHA20_POLY1305_SHA256 = 0x1303, - TLS_AES_128_CCM_SHA256 = 0x1304, - TLS_AES_128_CCM_8_SHA256 = 0x1305, + TLS_AES_128_GCM_SHA256 = 0x1301, + TLS_AES_256_GCM_SHA384 = 0x1302, + TLS_CHACHA20_POLY1305_SHA256 = 0x1303, + TLS_AES_128_CCM_SHA256 = 0x1304, + TLS_AES_128_CCM_8_SHA256 = 0x1305, } #[derive(Debug, Clone)] pub(crate) struct ClientHello<'a> { - pub(crate) version: TlsVersion, // Legacy: Must be Tls12 (0x0303) - pub(crate) random: [u8; 32], - pub(crate) session_id_length: u8, // Legacy: Keep it 32 - pub(crate) session_id: [u8; 32], // Legacy: Fill this with an unpredictable value - pub(crate) cipher_suites_length: u16, - pub(crate) cipher_suites: &'a[CipherSuite], - pub(crate) compression_method_length: u8, // Legacy: Must be 1, to contain a byte - pub(crate) compression_methods: u8, // Legacy: Must be 1 byte of 0 - pub(crate) extension_length: u16, - pub(crate) extensions: Vec, + pub(crate) version: TlsVersion, // Legacy: Must be Tls12 (0x0303) + pub(crate) random: [u8; 32], + pub(crate) session_id_length: u8, // Legacy: Keep it 32 + pub(crate) session_id: [u8; 32], // Legacy: Fill this with an unpredictable value + pub(crate) cipher_suites_length: u16, + pub(crate) cipher_suites: &'a[CipherSuite], + pub(crate) compression_method_length: u8, // Legacy: Must be 1, to contain a byte + pub(crate) compression_methods: u8, // Legacy: Must be 1 byte of 0 + pub(crate) extension_length: u16, + pub(crate) extensions: Vec, } #[derive(Debug, Clone)] pub(crate) enum HandshakeData<'a> { - Uninitialized, - ClientHello(ClientHello<'a>), - ServerHello(ServerHello<'a>), - EncryptedExtensions(EncryptedExtensions), - Certificate(Certificate<'a>), + Uninitialized, + ClientHello(ClientHello<'a>), + ServerHello(ServerHello<'a>), + EncryptedExtensions(EncryptedExtensions), + Certificate(Certificate<'a>), } impl<'a> HandshakeData<'a> { - pub(crate) fn get_length(&self) -> usize { - match self { - HandshakeData::ClientHello(data) => data.get_length(), - HandshakeData::ServerHello(data) => todo!(), - _ => 0, - } - } + pub(crate) fn get_length(&self) -> usize { + match self { + HandshakeData::ClientHello(data) => data.get_length(), + HandshakeData::ServerHello(data) => todo!(), + _ => 0, + } + } } impl<'a> ClientHello<'a> { - pub(self) fn new(secret: &EphemeralSecret, random: [u8; 32], session_id: [u8; 32]) -> Self { - let mut client_hello = ClientHello { - version: TlsVersion::Tls12, - random, - session_id_length: 32, - session_id, - cipher_suites_length: 0, - cipher_suites: &[ - CipherSuite::TLS_AES_128_GCM_SHA256, - CipherSuite::TLS_AES_256_GCM_SHA384, - CipherSuite::TLS_CHACHA20_POLY1305_SHA256, - CipherSuite::TLS_AES_128_CCM_SHA256, - ], - compression_method_length: 1, - compression_methods: 0, - extension_length: 0, - extensions: Vec::new(), - }; - client_hello.cipher_suites_length = u16::try_from(client_hello.cipher_suites.len() * 2).unwrap(); + pub(self) fn new(secret: &EphemeralSecret, random: [u8; 32], session_id: [u8; 32]) -> Self { + let mut client_hello = ClientHello { + version: TlsVersion::Tls12, + random, + session_id_length: 32, + session_id, + cipher_suites_length: 0, + cipher_suites: &[ + CipherSuite::TLS_AES_128_GCM_SHA256, + CipherSuite::TLS_AES_256_GCM_SHA384, + CipherSuite::TLS_CHACHA20_POLY1305_SHA256, + CipherSuite::TLS_AES_128_CCM_SHA256, + ], + compression_method_length: 1, + compression_methods: 0, + extension_length: 0, + extensions: Vec::new(), + }; + client_hello.cipher_suites_length = u16::try_from(client_hello.cipher_suites.len() * 2).unwrap(); - client_hello.add_ch_supported_versions() - .add_sig_algs() - .add_client_groups_with_key_shares(secret) - .finalise() - } + client_hello.add_ch_supported_versions() + .add_sig_algs() + .add_client_groups_with_key_shares(secret) + .finalise() + } - pub(crate) fn add_ch_supported_versions(mut self) -> Self { - let length = 2; - let mut versions = Vec::new(); - versions.push(TlsVersion::Tls13); + pub(crate) fn add_ch_supported_versions(mut self) -> Self { + let length = 2; + let mut versions = Vec::new(); + versions.push(TlsVersion::Tls13); - let mut content = SupportedVersions::ClientHello { - length, - versions, - }; + let mut content = SupportedVersions::ClientHello { + length, + versions, + }; - let extension_data = ExtensionData::SupportedVersions(content); - let length = extension_data.get_length(); - let extension = Extension { - extension_type: ExtensionType::SupportedVersions, - length: length.try_into().unwrap(), - extension_data, - }; - - self.extensions.push(extension); - self - } + let extension_data = ExtensionData::SupportedVersions(content); + let length = extension_data.get_length(); + let extension = Extension { + extension_type: ExtensionType::SupportedVersions, + length: length.try_into().unwrap(), + extension_data, + }; + + self.extensions.push(extension); + self + } - pub(crate) fn add_sh_supported_versions(mut self) -> Self { - let selected_version = TlsVersion::Tls13; + pub(crate) fn add_sh_supported_versions(mut self) -> Self { + let selected_version = TlsVersion::Tls13; - let mut content = SupportedVersions::ServerHello { - selected_version - }; + let mut content = SupportedVersions::ServerHello { + selected_version + }; - let extension_data = ExtensionData::SupportedVersions(content); - let length = extension_data.get_length(); - let extension = Extension { - extension_type: ExtensionType::SupportedVersions, - length: length.try_into().unwrap(), - extension_data, - }; - - self.extensions.push(extension); - self - } + let extension_data = ExtensionData::SupportedVersions(content); + let length = extension_data.get_length(); + let extension = Extension { + extension_type: ExtensionType::SupportedVersions, + length: length.try_into().unwrap(), + extension_data, + }; + + self.extensions.push(extension); + self + } - pub(crate) fn add_sig_algs(mut self) -> Self { - let mut algorithms = Vec::new(); - { - use SignatureScheme::*; - algorithms.push(ecdsa_secp256r1_sha256); - algorithms.push(ed25519); - algorithms.push(rsa_pss_pss_sha256); - algorithms.push(rsa_pkcs1_sha256); - algorithms.push(rsa_pss_rsae_sha256); - algorithms.push(rsa_pss_pss_sha384); - algorithms.push(rsa_pkcs1_sha384); - algorithms.push(rsa_pss_rsae_sha384); - algorithms.push(rsa_pss_pss_sha512); - algorithms.push(rsa_pkcs1_sha512); - algorithms.push(rsa_pss_rsae_sha512); - } - let length = algorithms.len() * 2; + pub(crate) fn add_sig_algs(mut self) -> Self { + let mut algorithms = Vec::new(); + { + use SignatureScheme::*; + algorithms.push(ecdsa_secp256r1_sha256); + algorithms.push(ed25519); + algorithms.push(rsa_pss_pss_sha256); + algorithms.push(rsa_pkcs1_sha256); + algorithms.push(rsa_pss_rsae_sha256); + algorithms.push(rsa_pss_pss_sha384); + algorithms.push(rsa_pkcs1_sha384); + algorithms.push(rsa_pss_rsae_sha384); + algorithms.push(rsa_pss_pss_sha512); + algorithms.push(rsa_pkcs1_sha512); + algorithms.push(rsa_pss_rsae_sha512); + } + let length = algorithms.len() * 2; - let list = SignatureSchemeList { - supported_signature_algorithms: algorithms, - length: length.try_into().unwrap(), - }; + let list = SignatureSchemeList { + supported_signature_algorithms: algorithms, + length: length.try_into().unwrap(), + }; - let extension_data = ExtensionData::SignatureAlgorithms(list); - let length = extension_data.get_length(); - let extension = Extension { - extension_type: ExtensionType::SignatureAlgorithms, - length: length.try_into().unwrap(), - extension_data - }; + let extension_data = ExtensionData::SignatureAlgorithms(list); + let length = extension_data.get_length(); + let extension = Extension { + extension_type: ExtensionType::SignatureAlgorithms, + length: length.try_into().unwrap(), + extension_data + }; - self.extensions.push(extension); - self - } + self.extensions.push(extension); + self + } - pub(crate) fn add_client_groups_with_key_shares(mut self, ecdh_secret: &EphemeralSecret) -> Self { - // List out all supported groups - let mut list = Vec::new(); - list.push(NamedGroup::secp256r1); + pub(crate) fn add_client_groups_with_key_shares(mut self, ecdh_secret: &EphemeralSecret) -> Self { + // List out all supported groups + let mut list = Vec::new(); + list.push(NamedGroup::secp256r1); - let length = list.len()*2; + let length = list.len()*2; - // Use the list to generate all key shares and store in a vec - let mut client_shares = Vec::new(); - let mut client_shares_length = 0; - for named_group in list.iter() { - let mut key_exchange = Vec::new(); - let key_share_entry = match named_group { - NamedGroup::secp256r1 => { - let ecdh_public = EncodedPoint::from(ecdh_secret); - let x_coor = ecdh_public.x(); - let y_coor = ecdh_public.y().unwrap(); + // Use the list to generate all key shares and store in a vec + let mut client_shares = Vec::new(); + let mut client_shares_length = 0; + for named_group in list.iter() { + let mut key_exchange = Vec::new(); + let key_share_entry = match named_group { + NamedGroup::secp256r1 => { + let ecdh_public = EncodedPoint::from(ecdh_secret); + let x_coor = ecdh_public.x(); + let y_coor = ecdh_public.y().unwrap(); - key_exchange.push(0x04); // Legacy value - key_exchange.extend_from_slice(&x_coor); - key_exchange.extend_from_slice(&y_coor); + key_exchange.push(0x04); // Legacy value + key_exchange.extend_from_slice(&x_coor); + key_exchange.extend_from_slice(&y_coor); - let key_exchange_length = key_exchange.len(); + let key_exchange_length = key_exchange.len(); - KeyShareEntry { - group: *named_group, - length: key_exchange_length.try_into().unwrap(), - key_exchange - } - }, - // TODO: Implement keygen for other named groups - _ => todo!(), - }; + KeyShareEntry { + group: *named_group, + length: key_exchange_length.try_into().unwrap(), + key_exchange + } + }, + // TODO: Implement keygen for other named groups + _ => todo!(), + }; - client_shares_length += key_share_entry.get_length(); - client_shares.push(key_share_entry); - } + client_shares_length += key_share_entry.get_length(); + client_shares.push(key_share_entry); + } - // Pack up the client shares into key share - let key_share_content = KeyShareEntryContent::KeyShareClientHello { - length: client_shares_length.try_into().unwrap(), - client_shares, - }; - let extension_data = ExtensionData::KeyShareEntry(key_share_content); - let length = extension_data.get_length(); - let key_share_extension = Extension { - extension_type: ExtensionType::KeyShare, - length: length.try_into().unwrap(), - extension_data, - }; + // Pack up the client shares into key share + let key_share_content = KeyShareEntryContent::KeyShareClientHello { + length: client_shares_length.try_into().unwrap(), + client_shares, + }; + let extension_data = ExtensionData::KeyShareEntry(key_share_content); + let length = extension_data.get_length(); + let key_share_extension = Extension { + extension_type: ExtensionType::KeyShare, + length: length.try_into().unwrap(), + extension_data, + }; - let length = list.len()*2; - let group_list = NamedGroupList { - length: length.try_into().unwrap(), - named_group_list: list, - }; - let extension_data = ExtensionData::NegotiatedGroups(group_list); - let length = extension_data.get_length(); - let group_list_extension = Extension { - extension_type: ExtensionType::SupportedGroups, - length: length.try_into().unwrap(), - extension_data, - }; + let length = list.len()*2; + let group_list = NamedGroupList { + length: length.try_into().unwrap(), + named_group_list: list, + }; + let extension_data = ExtensionData::NegotiatedGroups(group_list); + let length = extension_data.get_length(); + let group_list_extension = Extension { + extension_type: ExtensionType::SupportedGroups, + length: length.try_into().unwrap(), + extension_data, + }; - self.extensions.push(group_list_extension); - self.extensions.push(key_share_extension); - self - } + self.extensions.push(group_list_extension); + self.extensions.push(key_share_extension); + self + } - pub(crate) fn finalise(mut self) -> Self { - let mut sum = 0; - for extension in self.extensions.iter() { - // TODO: Add up the extension length - sum += extension.get_length(); - } - self.extension_length = sum.try_into().unwrap(); - self - } + pub(crate) fn finalise(mut self) -> Self { + let mut sum = 0; + for extension in self.extensions.iter() { + // TODO: Add up the extension length + sum += extension.get_length(); + } + self.extension_length = sum.try_into().unwrap(); + self + } - pub(crate) fn get_length(&self) -> usize { - let mut length: usize = 2; // TlsVersion size - length += 32; // Random size - length += 1; // Legacy session_id length size - length += 32; // Legacy session_id size - length += 2; // Cipher_suites_length size - length += self.cipher_suites.len() * 2; - length += 1; - length += 1; - length += 2; - length += usize::try_from(self.extension_length).unwrap(); - length - } + pub(crate) fn get_length(&self) -> usize { + let mut length: usize = 2; // TlsVersion size + length += 32; // Random size + length += 1; // Legacy session_id length size + length += 32; // Legacy session_id size + length += 2; // Cipher_suites_length size + length += self.cipher_suites.len() * 2; + length += 1; + length += 1; + length += 2; + length += usize::try_from(self.extension_length).unwrap(); + length + } } #[derive(Debug, Clone)] pub(crate) struct ServerHello<'a> { - pub(crate) version: TlsVersion, - pub(crate) random: &'a[u8], - pub(crate) session_id_echo_length: u8, - pub(crate) session_id_echo: &'a[u8], - pub(crate) cipher_suite: CipherSuite, - pub(crate) compression_method: u8, // Always 0 - pub(crate) extension_length: u16, - pub(crate) extensions: Vec, + pub(crate) version: TlsVersion, + pub(crate) random: &'a[u8], + pub(crate) session_id_echo_length: u8, + pub(crate) session_id_echo: &'a[u8], + pub(crate) cipher_suite: CipherSuite, + pub(crate) compression_method: u8, // Always 0 + pub(crate) extension_length: u16, + pub(crate) extensions: Vec, } #[derive(Debug, Clone)] pub(crate) struct EncryptedExtensions { - pub(crate) length: u16, - pub(crate) extensions: Vec, + pub(crate) length: u16, + pub(crate) extensions: Vec, } #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[repr(u16)] pub(crate) enum ExtensionType { - ServerName = 0, - MaxFragmentLength = 1, - StatusRequest = 5, - SupportedGroups = 10, - SignatureAlgorithms = 13, - UseSRTP = 14, - Heartbeat = 15, - ApplicationLayerProtocolNegotiation = 16, - SignedCertificateTimestamp = 18, - ClientCertificateType = 19, - ServerCertificateType = 20, - Padding = 21, - PreSharedKey = 41, - EarlyData = 42, - SupportedVersions = 43, - Cookie = 44, - PSKKeyExchangeModes = 45, - CertificateAuthorities = 47, - OIDFilters = 48, - PostHandshakeAuth = 49, - SignatureAlgorithmsCert = 50, - KeyShare = 51, + ServerName = 0, + MaxFragmentLength = 1, + StatusRequest = 5, + SupportedGroups = 10, + SignatureAlgorithms = 13, + UseSRTP = 14, + Heartbeat = 15, + ApplicationLayerProtocolNegotiation = 16, + SignedCertificateTimestamp = 18, + ClientCertificateType = 19, + ServerCertificateType = 20, + Padding = 21, + PreSharedKey = 41, + EarlyData = 42, + SupportedVersions = 43, + Cookie = 44, + PSKKeyExchangeModes = 45, + CertificateAuthorities = 47, + OIDFilters = 48, + PostHandshakeAuth = 49, + SignatureAlgorithmsCert = 50, + KeyShare = 51, } impl ExtensionType { - pub(crate) fn get_length(&self) -> u16 { - return 2; - } + pub(crate) fn get_length(&self) -> u16 { + return 2; + } } #[derive(Debug, Clone)] pub(crate) struct Extension { - pub(crate) extension_type: ExtensionType, - pub(crate) length: u16, - pub(crate) extension_data: ExtensionData, + pub(crate) extension_type: ExtensionType, + pub(crate) length: u16, + pub(crate) extension_data: ExtensionData, } impl Extension { - pub(crate) fn get_length(&self) -> usize { - 2 + 2 + usize::try_from(self.length).unwrap() - } + pub(crate) fn get_length(&self) -> usize { + 2 + 2 + usize::try_from(self.length).unwrap() + } } #[derive(Debug, Clone)] pub(crate) enum ExtensionData { - SupportedVersions(SupportedVersions), - Cookie(Cookie), - SignatureAlgorithms(SignatureSchemeList), - SignatureAlgorithmsCertificate(SignatureSchemeList), - NegotiatedGroups(NamedGroupList), - KeyShareEntry(KeyShareEntryContent), - ServerName(ServerName), + SupportedVersions(SupportedVersions), + Cookie(Cookie), + SignatureAlgorithms(SignatureSchemeList), + SignatureAlgorithmsCertificate(SignatureSchemeList), + NegotiatedGroups(NamedGroupList), + KeyShareEntry(KeyShareEntryContent), + ServerName(ServerName), } impl ExtensionData { - pub(crate) fn get_length(&self) -> usize { - match self { - Self::SupportedVersions(s) => s.get_length(), - Self::SignatureAlgorithms(list) => list.get_length(), - Self::NegotiatedGroups(list) => list.get_length(), - Self::KeyShareEntry(entry_content) => entry_content.get_length(), + pub(crate) fn get_length(&self) -> usize { + match self { + Self::SupportedVersions(s) => s.get_length(), + Self::SignatureAlgorithms(list) => list.get_length(), + Self::NegotiatedGroups(list) => list.get_length(), + Self::KeyShareEntry(entry_content) => entry_content.get_length(), - // Implement get_length for all textension data - _ => todo!() - } - } + // Implement get_length for all textension data + _ => todo!() + } + } } #[derive(Debug, Clone)] pub(crate) enum SupportedVersions { - ClientHello { - length: u8, - versions: Vec, - }, - ServerHello { - selected_version: TlsVersion, - } + ClientHello { + length: u8, + versions: Vec, + }, + ServerHello { + selected_version: TlsVersion, + } } impl SupportedVersions { - pub(crate) fn get_length(&self) -> usize { - match self { - Self::ClientHello { length, versions } => { - usize::try_from(*length).unwrap() + 1 - } - Self::ServerHello { selected_version } => 2 - } - } + pub(crate) fn get_length(&self) -> usize { + match self { + Self::ClientHello { length, versions } => { + usize::try_from(*length).unwrap() + 1 + } + Self::ServerHello { selected_version } => 2 + } + } } #[derive(Debug, Clone)] pub(crate) struct Cookie { - length: u16, - cookie: Vec, + length: u16, + cookie: Vec, } #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[repr(u16)] pub(crate) enum SignatureScheme { - /* RSASSA-PKCS1-v1_5 algorithms */ - rsa_pkcs1_sha256 = 0x0401, - rsa_pkcs1_sha384 = 0x0501, - rsa_pkcs1_sha512 = 0x0601, + /* RSASSA-PKCS1-v1_5 algorithms */ + rsa_pkcs1_sha256 = 0x0401, + rsa_pkcs1_sha384 = 0x0501, + rsa_pkcs1_sha512 = 0x0601, - /* ECDSA algorithms */ - ecdsa_secp256r1_sha256 = 0x0403, - ecdsa_secp384r1_sha384 = 0x0503, - ecdsa_secp521r1_sha512 = 0x0603, + /* ECDSA algorithms */ + ecdsa_secp256r1_sha256 = 0x0403, + ecdsa_secp384r1_sha384 = 0x0503, + ecdsa_secp521r1_sha512 = 0x0603, - /* RSASSA-PSS algorithms with public key OID rsaEncryption */ - rsa_pss_rsae_sha256 = 0x0804, - rsa_pss_rsae_sha384 = 0x0805, - rsa_pss_rsae_sha512 = 0x0806, + /* RSASSA-PSS algorithms with public key OID rsaEncryption */ + rsa_pss_rsae_sha256 = 0x0804, + rsa_pss_rsae_sha384 = 0x0805, + rsa_pss_rsae_sha512 = 0x0806, - /* EdDSA algorithms */ - ed25519 = 0x0807, - ed488 = 0x0808, + /* EdDSA algorithms */ + ed25519 = 0x0807, + ed488 = 0x0808, - /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ - rsa_pss_pss_sha256 = 0x0809, - rsa_pss_pss_sha384 = 0x080a, - rsa_pss_pss_sha512 = 0x080b, + /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ + rsa_pss_pss_sha256 = 0x0809, + rsa_pss_pss_sha384 = 0x080a, + rsa_pss_pss_sha512 = 0x080b, } #[derive(Debug, Clone)] pub(crate) struct SignatureSchemeList { - pub(crate) length: u16, - pub(crate) supported_signature_algorithms: Vec, + pub(crate) length: u16, + pub(crate) supported_signature_algorithms: Vec, } impl SignatureSchemeList { - pub(crate) fn get_length(&self) -> usize { - 2 + usize::try_from(self.length).unwrap() - } + pub(crate) fn get_length(&self) -> usize { + 2 + usize::try_from(self.length).unwrap() + } } #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[repr(u16)] pub(crate) enum NamedGroup { - #[num_enum(default)] - UNKNOWN = 0x0000, + #[num_enum(default)] + UNKNOWN = 0x0000, - /* Elliptic Curve Groups (ECDHE) */ - secp256r1 = 0x0017, - secp384r1 = 0x0018, - secp521r1 = 0x0019, - x25519 = 0x001D, - x448 = 0x001E, + /* Elliptic Curve Groups (ECDHE) */ + secp256r1 = 0x0017, + secp384r1 = 0x0018, + secp521r1 = 0x0019, + x25519 = 0x001D, + x448 = 0x001E, - /* Finite Field Groups (DHE) */ - ffdhe2048 = 0x0100, - ffdhe3072 = 0x0101, - ffdhe4096 = 0x0102, - ffdhe6144 = 0x0103, - ffdhe8192 = 0x0104, + /* Finite Field Groups (DHE) */ + ffdhe2048 = 0x0100, + ffdhe3072 = 0x0101, + ffdhe4096 = 0x0102, + ffdhe6144 = 0x0103, + ffdhe8192 = 0x0104, } #[derive(Debug, Clone)] pub(crate) struct NamedGroupList { - pub(crate) length: u16, - pub(crate) named_group_list: Vec, + pub(crate) length: u16, + pub(crate) named_group_list: Vec, } impl NamedGroupList { - pub(crate) fn get_length(&self) -> usize { - usize::try_from(self.length).unwrap() + 2 - } + pub(crate) fn get_length(&self) -> usize { + usize::try_from(self.length).unwrap() + 2 + } } #[derive(Debug, Clone)] pub(crate) struct KeyShareEntry { - pub(crate) group: NamedGroup, - pub(crate) length: u16, - pub(crate) key_exchange: Vec, + pub(crate) group: NamedGroup, + pub(crate) length: u16, + pub(crate) key_exchange: Vec, } impl KeyShareEntry { - pub(crate) fn get_length(&self) -> usize { - 2 + 2 + usize::try_from(self.length).unwrap() - } + pub(crate) fn get_length(&self) -> usize { + 2 + 2 + usize::try_from(self.length).unwrap() + } } #[derive(Debug, Clone)] pub(crate) enum KeyShareEntryContent { - KeyShareClientHello { - length: u16, - client_shares: Vec, - }, - KeyShareHelloRetryRequest { - selected_group: NamedGroup, - }, - KeyShareServerHello { - server_share: KeyShareEntry, - } + KeyShareClientHello { + length: u16, + client_shares: Vec, + }, + KeyShareHelloRetryRequest { + selected_group: NamedGroup, + }, + KeyShareServerHello { + server_share: KeyShareEntry, + } } impl KeyShareEntryContent { - pub(crate) fn get_length(&self) -> usize { - match self { - Self::KeyShareClientHello { length, client_shares } => 2 + usize::try_from(*length).unwrap(), - Self::KeyShareHelloRetryRequest { selected_group } => 2, - Self::KeyShareServerHello { server_share } => server_share.get_length(), - } - } + pub(crate) fn get_length(&self) -> usize { + match self { + Self::KeyShareClientHello { length, client_shares } => 2 + usize::try_from(*length).unwrap(), + Self::KeyShareHelloRetryRequest { selected_group } => 2, + Self::KeyShareServerHello { server_share } => server_share.get_length(), + } + } } #[derive(Debug, Clone)] #[repr(u16)] pub(crate) enum NameType { - host_name = 0 + host_name = 0 } #[derive(Debug, Clone)] pub(crate) enum ServerNameContent { - HostName { - length: u16, - host_name: Vec, - } + HostName { + length: u16, + host_name: Vec, + } } #[derive(Debug, Clone)] pub(crate) struct ServerName { - name_type: NameType, - name: ServerNameContent, + name_type: NameType, + name: ServerNameContent, } // Note: X.509 format is always selected unless negotiated // This TLS implementation still yet to support certificate negotiation #[derive(Debug, Clone)] pub(crate) enum CertificateEntryInfo<'a> { - RawPublicKey { - ASN1_subjectPublicKeyInfo_length: u32, // Only 24 bits - ASN1_subjectPublicKeyInfo: &'a [u8], - }, - X509 { - cert_data_length: u32, // Only 24 bits - cert_data: &'a [u8], - } + RawPublicKey { + ASN1_subjectPublicKeyInfo_length: u32, // Only 24 bits + ASN1_subjectPublicKeyInfo: &'a [u8], + }, + X509 { + cert_data_length: u32, // Only 24 bits + cert_data: &'a [u8], + } } #[derive(Debug, Clone)] pub(crate) struct CertificateEntry<'a> { - certificate_entry_into: CertificateEntryInfo<'a>, - extensions_length: u16, - extensions: Vec, + certificate_entry_into: CertificateEntryInfo<'a>, + extensions_length: u16, + extensions: Vec, } #[derive(Debug, Clone)] pub(crate) struct Certificate<'a> { - certificate_request_context_length: u8, // 0 length unless responding to CERT_REQUEST - certificate_request_context: &'a [u8], - certificate_list_length: u32, // Only 24 bits - certificate_list: &'a [CertificateEntry<'a>], + certificate_request_context_length: u8, // 0 length unless responding to CERT_REQUEST + certificate_request_context: &'a [u8], + certificate_list_length: u32, // Only 24 bits + certificate_list: &'a [CertificateEntry<'a>], }