Compare commits
No commits in common. "eadf776da34ef1f07ca45168766adca729cc858e" and "2e8ccdf910bfe99e3fde20b0aaad5dbf8c1ed122" have entirely different histories.
eadf776da3
...
2e8ccdf910
|
@ -12,7 +12,6 @@ num_enum = { version = "0.5.1", default-features = false }
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
generic-array = "0.14.4"
|
generic-array = "0.14.4"
|
||||||
heapless = "0.5.6"
|
heapless = "0.5.6"
|
||||||
asn1_der = { version = "0.7.1", features = [ "native_types", "no_std" ] }
|
|
||||||
|
|
||||||
[dependencies.aes-gcm]
|
[dependencies.aes-gcm]
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
436
src/buffer.rs
436
src/buffer.rs
|
@ -13,252 +13,252 @@ use crate::key::*;
|
||||||
// Only designed to support read or write the entire buffer
|
// Only designed to support read or write the entire buffer
|
||||||
// TODO: Stricter visibility
|
// TODO: Stricter visibility
|
||||||
pub struct TlsBuffer<'a> {
|
pub struct TlsBuffer<'a> {
|
||||||
buffer: &'a mut [u8],
|
buffer: &'a mut [u8],
|
||||||
index: RefCell<usize>,
|
index: RefCell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Into<&'a [u8]> for TlsBuffer<'a> {
|
impl<'a> Into<&'a [u8]> for TlsBuffer<'a> {
|
||||||
fn into(self) -> &'a [u8] {
|
fn into(self) -> &'a [u8] {
|
||||||
&self.buffer[0..self.index.into_inner()]
|
&self.buffer[0..self.index.into_inner()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TlsBuffer<'a> {
|
impl<'a> TlsBuffer<'a> {
|
||||||
pub fn new(buffer: &'a mut [u8]) -> Self {
|
pub fn new(buffer: &'a mut [u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
buffer,
|
buffer,
|
||||||
index: RefCell::new(0),
|
index: RefCell::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_size(&self) -> usize {
|
pub(crate) fn get_size(&self) -> usize {
|
||||||
self.index.clone().into_inner()
|
self.index.clone().into_inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write(&mut self, data: &[u8]) -> Result<()> {
|
pub(crate) fn write(&mut self, data: &[u8]) -> Result<()> {
|
||||||
let mut index = self.index.borrow_mut();
|
let mut index = self.index.borrow_mut();
|
||||||
if (self.buffer.len() - *index) < data.len() {
|
if (self.buffer.len() - *index) < data.len() {
|
||||||
return Err(Error::Exhausted);
|
return Err(Error::Exhausted);
|
||||||
}
|
}
|
||||||
let next_index = *index + data.len();
|
let next_index = *index + data.len();
|
||||||
self.buffer[*index..next_index].copy_from_slice(data);
|
self.buffer[*index..next_index].copy_from_slice(data);
|
||||||
*index = next_index;
|
*index = next_index;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write_u8(&mut self, data: u8) -> Result<()> {
|
pub(crate) fn write_u8(&mut self, data: u8) -> Result<()> {
|
||||||
let mut index = self.index.borrow_mut();
|
let mut index = self.index.borrow_mut();
|
||||||
if (self.buffer.len() - *index) < 1 {
|
if (self.buffer.len() - *index) < 1 {
|
||||||
return Err(Error::Exhausted);
|
return Err(Error::Exhausted);
|
||||||
}
|
}
|
||||||
self.buffer[*index] = data;
|
self.buffer[*index] = data;
|
||||||
*index += 1;
|
*index += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_u8(&mut self) -> Result<u8> {
|
pub(crate) fn read_u8(&mut self) -> Result<u8> {
|
||||||
let mut index = self.index.borrow_mut();
|
let mut index = self.index.borrow_mut();
|
||||||
if (self.buffer.len() - *index) < 1 {
|
if (self.buffer.len() - *index) < 1 {
|
||||||
return Err(Error::Exhausted);
|
return Err(Error::Exhausted);
|
||||||
}
|
}
|
||||||
let data = self.buffer[*index];
|
let data = self.buffer[*index];
|
||||||
*index += 1;
|
*index += 1;
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_all(self) -> &'a [u8] {
|
pub(crate) fn read_all(self) -> &'a [u8] {
|
||||||
&self.buffer[self.index.into_inner()..]
|
&self.buffer[self.index.into_inner()..]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_slice(&self, length: usize) -> Result<&[u8]> {
|
pub(crate) fn read_slice(&self, length: usize) -> Result<&[u8]> {
|
||||||
let mut index = self.index.borrow_mut();
|
let mut index = self.index.borrow_mut();
|
||||||
if (self.buffer.len() - *index) < length {
|
if (self.buffer.len() - *index) < length {
|
||||||
return Err(Error::Exhausted);
|
return Err(Error::Exhausted);
|
||||||
}
|
}
|
||||||
let next_index = *index + length;
|
let next_index = *index + length;
|
||||||
let slice = &self.buffer[*index..next_index];
|
let slice = &self.buffer[*index..next_index];
|
||||||
*index = next_index;
|
*index = next_index;
|
||||||
Ok(slice)
|
Ok(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn enqueue_tls_repr(&mut self, tls_repr: TlsRepr<'a>) -> Result<()> {
|
pub(crate) fn enqueue_tls_repr(&mut self, tls_repr: TlsRepr<'a>) -> Result<()> {
|
||||||
self.write_u8(tls_repr.content_type.into())?;
|
self.write_u8(tls_repr.content_type.into())?;
|
||||||
self.write_u16(tls_repr.version.into())?;
|
self.write_u16(tls_repr.version.into())?;
|
||||||
self.write_u16(tls_repr.length)?;
|
self.write_u16(tls_repr.length)?;
|
||||||
if let Some(app_data) = tls_repr.payload {
|
if let Some(app_data) = tls_repr.payload {
|
||||||
self.write(app_data.as_slice())?;
|
self.write(app_data.as_slice())?;
|
||||||
} else if let Some(handshake_repr) = tls_repr.handshake {
|
} else if let Some(handshake_repr) = tls_repr.handshake {
|
||||||
// Queue handshake_repr into buffer
|
// Queue handshake_repr into buffer
|
||||||
self.enqueue_handshake_repr(handshake_repr)?;
|
self.enqueue_handshake_repr(handshake_repr)?;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Malformed);
|
return Err(Error::Malformed);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_handshake_repr(&mut self, handshake_repr: HandshakeRepr<'a>) -> Result<()> {
|
fn enqueue_handshake_repr(&mut self, handshake_repr: HandshakeRepr<'a>) -> Result<()> {
|
||||||
self.write_u8(handshake_repr.msg_type.into())?;
|
self.write_u8(handshake_repr.msg_type.into())?;
|
||||||
self.write_u24(handshake_repr.length)?;
|
self.write_u24(handshake_repr.length)?;
|
||||||
self.enqueue_handshake_data(handshake_repr.handshake_data)
|
self.enqueue_handshake_data(handshake_repr.handshake_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_handshake_data(&mut self, handshake_data: HandshakeData<'a>) -> Result<()> {
|
fn enqueue_handshake_data(&mut self, handshake_data: HandshakeData<'a>) -> Result<()> {
|
||||||
match handshake_data {
|
match handshake_data {
|
||||||
HandshakeData::ClientHello(client_hello) => {
|
HandshakeData::ClientHello(client_hello) => {
|
||||||
self.enqueue_client_hello(client_hello)
|
self.enqueue_client_hello(client_hello)
|
||||||
}
|
}
|
||||||
HandshakeData::ServerHello(server_hello) => {
|
HandshakeData::ServerHello(server_hello) => {
|
||||||
self.euqueue_server_hello(server_hello)
|
self.euqueue_server_hello(server_hello)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
Err(Error::Unrecognized)
|
Err(Error::Unrecognized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_client_hello(&mut self, client_hello: ClientHello<'a>) -> Result<()> {
|
fn enqueue_client_hello(&mut self, client_hello: ClientHello<'a>) -> Result<()> {
|
||||||
self.write_u16(client_hello.version.into())?;
|
self.write_u16(client_hello.version.into())?;
|
||||||
self.write(&client_hello.random)?;
|
self.write(&client_hello.random)?;
|
||||||
self.write_u8(client_hello.session_id_length)?;
|
self.write_u8(client_hello.session_id_length)?;
|
||||||
self.write(&client_hello.session_id)?;
|
self.write(&client_hello.session_id)?;
|
||||||
self.write_u16(client_hello.cipher_suites_length)?;
|
self.write_u16(client_hello.cipher_suites_length)?;
|
||||||
for suite in client_hello.cipher_suites.iter() {
|
for suite in client_hello.cipher_suites.iter() {
|
||||||
self.write_u16((*suite).into())?;
|
self.write_u16((*suite).into())?;
|
||||||
}
|
}
|
||||||
self.write_u8(client_hello.compression_method_length)?;
|
self.write_u8(client_hello.compression_method_length)?;
|
||||||
self.write_u8(client_hello.compression_methods)?;
|
self.write_u8(client_hello.compression_methods)?;
|
||||||
self.write_u16(client_hello.extension_length)?;
|
self.write_u16(client_hello.extension_length)?;
|
||||||
self.enqueue_extensions(client_hello.extensions)
|
self.enqueue_extensions(client_hello.extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn euqueue_server_hello(&mut self, server_hello: ServerHello<'a>) -> Result<()> {
|
fn euqueue_server_hello(&mut self, server_hello: ServerHello<'a>) -> Result<()> {
|
||||||
self.write_u16(server_hello.version.into())?;
|
self.write_u16(server_hello.version.into())?;
|
||||||
self.write(&server_hello.random)?;
|
self.write(&server_hello.random)?;
|
||||||
self.write_u8(server_hello.session_id_echo_length)?;
|
self.write_u8(server_hello.session_id_echo_length)?;
|
||||||
self.write(&server_hello.session_id_echo)?;
|
self.write(&server_hello.session_id_echo)?;
|
||||||
self.write_u16(server_hello.cipher_suite.into())?;
|
self.write_u16(server_hello.cipher_suite.into())?;
|
||||||
self.write_u8(server_hello.compression_method)?;
|
self.write_u8(server_hello.compression_method)?;
|
||||||
self.write_u16(server_hello.extension_length)?;
|
self.write_u16(server_hello.extension_length)?;
|
||||||
self.enqueue_extensions(server_hello.extensions)
|
self.enqueue_extensions(server_hello.extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_extensions(&mut self, extensions: Vec<Extension>) -> Result<()> {
|
fn enqueue_extensions(&mut self, extensions: Vec<Extension>) -> Result<()> {
|
||||||
for extension in extensions {
|
for extension in extensions {
|
||||||
self.write_u16(extension.extension_type.into())?;
|
self.write_u16(extension.extension_type.into())?;
|
||||||
self.write_u16(extension.length)?;
|
self.write_u16(extension.length)?;
|
||||||
self.enqueue_extension_data(extension.extension_data)?;
|
self.enqueue_extension_data(extension.extension_data)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_extension_data(&mut self, extension_data: ExtensionData) -> Result<()> {
|
fn enqueue_extension_data(&mut self, extension_data: ExtensionData) -> Result<()> {
|
||||||
use crate::tls_packet::ExtensionData::*;
|
use crate::tls_packet::ExtensionData::*;
|
||||||
match extension_data {
|
match extension_data {
|
||||||
SupportedVersions(s) => {
|
SupportedVersions(s) => {
|
||||||
use crate::tls_packet::SupportedVersions::*;
|
use crate::tls_packet::SupportedVersions::*;
|
||||||
match s {
|
match s {
|
||||||
ClientHello { length, versions } => {
|
ClientHello { length, versions } => {
|
||||||
self.write_u8(length)?;
|
self.write_u8(length)?;
|
||||||
for version in versions.iter() {
|
for version in versions.iter() {
|
||||||
self.write_u16((*version).into())?;
|
self.write_u16((*version).into())?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ServerHello { selected_version } => {
|
ServerHello { selected_version } => {
|
||||||
self.write_u16(selected_version.into())?;
|
self.write_u16(selected_version.into())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SignatureAlgorithms(s) => {
|
SignatureAlgorithms(s) => {
|
||||||
self.write_u16(s.length)?;
|
self.write_u16(s.length)?;
|
||||||
for sig_alg in s.supported_signature_algorithms.iter() {
|
for sig_alg in s.supported_signature_algorithms.iter() {
|
||||||
self.write_u16((*sig_alg).into())?;
|
self.write_u16((*sig_alg).into())?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NegotiatedGroups(n) => {
|
NegotiatedGroups(n) => {
|
||||||
self.write_u16(n.length)?;
|
self.write_u16(n.length)?;
|
||||||
for group in n.named_group_list.iter() {
|
for group in n.named_group_list.iter() {
|
||||||
self.write_u16((*group).into())?;
|
self.write_u16((*group).into())?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
KeyShareEntry(k) => {
|
KeyShareEntry(k) => {
|
||||||
let mut key_share_entry_into = |buffer: &mut TlsBuffer, entry: crate::tls_packet::KeyShareEntry| {
|
let mut key_share_entry_into = |buffer: &mut TlsBuffer, entry: crate::tls_packet::KeyShareEntry| {
|
||||||
buffer.write_u16(entry.group.into())?;
|
buffer.write_u16(entry.group.into())?;
|
||||||
buffer.write_u16(entry.length)?;
|
buffer.write_u16(entry.length)?;
|
||||||
buffer.write(entry.key_exchange.as_slice())
|
buffer.write(entry.key_exchange.as_slice())
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tls_packet::KeyShareEntryContent::*;
|
use crate::tls_packet::KeyShareEntryContent::*;
|
||||||
match k {
|
match k {
|
||||||
KeyShareClientHello { length, client_shares } => {
|
KeyShareClientHello { length, client_shares } => {
|
||||||
self.write_u16(length)?;
|
self.write_u16(length)?;
|
||||||
for share in client_shares.iter() {
|
for share in client_shares.iter() {
|
||||||
self.enqueue_key_share_entry(share)?;
|
self.enqueue_key_share_entry(share)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyShareHelloRetryRequest { selected_group } => {
|
KeyShareHelloRetryRequest { selected_group } => {
|
||||||
self.write_u16(selected_group.into())?;
|
self.write_u16(selected_group.into())?;
|
||||||
}
|
}
|
||||||
KeyShareServerHello { server_share } => {
|
KeyShareServerHello { server_share } => {
|
||||||
self.enqueue_key_share_entry(&server_share)?;
|
self.enqueue_key_share_entry(&server_share)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: Implement buffer formatting for other extensions
|
// TODO: Implement buffer formatting for other extensions
|
||||||
_ => todo!()
|
_ => todo!()
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_key_share_entry(&mut self, entry: &crate::tls_packet::KeyShareEntry) -> Result<()> {
|
fn enqueue_key_share_entry(&mut self, entry: &crate::tls_packet::KeyShareEntry) -> Result<()> {
|
||||||
self.write_u16(entry.group.into())?;
|
self.write_u16(entry.group.into())?;
|
||||||
self.write_u16(entry.length)?;
|
self.write_u16(entry.length)?;
|
||||||
self.write(entry.key_exchange.as_slice())
|
self.write(entry.key_exchange.as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enqueue_hkdf_label(&mut self, hkdf_label: HkdfLabel) -> Result<()> {
|
pub fn enqueue_hkdf_label(&mut self, hkdf_label: HkdfLabel) -> Result<()> {
|
||||||
self.write_u16(hkdf_label.length)?;
|
self.write_u16(hkdf_label.length)?;
|
||||||
self.write_u8(hkdf_label.label_length)?;
|
self.write_u8(hkdf_label.label_length)?;
|
||||||
self.write(hkdf_label.label)?;
|
self.write(hkdf_label.label)?;
|
||||||
self.write_u8(hkdf_label.context_length)?;
|
self.write_u8(hkdf_label.context_length)?;
|
||||||
self.write(hkdf_label.context)
|
self.write(hkdf_label.context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! export_byte_order_fn {
|
macro_rules! export_byte_order_fn {
|
||||||
($($write_fn_name: ident, $read_fn_name: ident, $data_type: ty, $data_size: literal),+) => {
|
($($write_fn_name: ident, $read_fn_name: ident, $data_type: ty, $data_size: literal),+) => {
|
||||||
impl<'a> TlsBuffer<'a> {
|
impl<'a> TlsBuffer<'a> {
|
||||||
$(
|
$(
|
||||||
pub(crate) fn $write_fn_name(&mut self, data: $data_type) -> Result<()> {
|
pub(crate) fn $write_fn_name(&mut self, data: $data_type) -> Result<()> {
|
||||||
let mut index = self.index.borrow_mut();
|
let mut index = self.index.borrow_mut();
|
||||||
if (self.buffer.len() - *index) < $data_size {
|
if (self.buffer.len() - *index) < $data_size {
|
||||||
return Err(Error::Exhausted);
|
return Err(Error::Exhausted);
|
||||||
}
|
}
|
||||||
let next_index = *index + $data_size;
|
let next_index = *index + $data_size;
|
||||||
NetworkEndian::$write_fn_name(&mut self.buffer[*index..next_index], data);
|
NetworkEndian::$write_fn_name(&mut self.buffer[*index..next_index], data);
|
||||||
*index = next_index;
|
*index = next_index;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn $read_fn_name(&self) -> Result<$data_type> {
|
pub(crate) fn $read_fn_name(&self) -> Result<$data_type> {
|
||||||
let mut index = self.index.borrow_mut();
|
let mut index = self.index.borrow_mut();
|
||||||
if (self.buffer.len() - *index) < $data_size {
|
if (self.buffer.len() - *index) < $data_size {
|
||||||
return Err(Error::Exhausted);
|
return Err(Error::Exhausted);
|
||||||
}
|
}
|
||||||
let next_index = *index + $data_size;
|
let next_index = *index + $data_size;
|
||||||
let data = NetworkEndian::$read_fn_name(&self.buffer[*index..next_index]);
|
let data = NetworkEndian::$read_fn_name(&self.buffer[*index..next_index]);
|
||||||
*index = next_index;
|
*index = next_index;
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export_byte_order_fn!(
|
export_byte_order_fn!(
|
||||||
write_u16, read_u16, u16, 2,
|
write_u16, read_u16, u16, 2,
|
||||||
write_u24, read_u24, u32, 3,
|
write_u24, read_u24, u32, 3,
|
||||||
write_u32, read_u32, u32, 4,
|
write_u32, read_u32, u32, 4,
|
||||||
write_u48, read_u48, u64, 6,
|
write_u48, read_u48, u64, 6,
|
||||||
write_u64, read_u64, u64, 8
|
write_u64, read_u64, u64, 8
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
use num_enum::IntoPrimitive;
|
|
||||||
use num_enum::TryFromPrimitive;
|
|
||||||
|
|
||||||
pub struct Certificate<'a> {
|
|
||||||
tbs_certificate: TBSCertificate<'a>,
|
|
||||||
signature_algorithm: AlgorithmIdentifier<'a>,
|
|
||||||
signature_value: &'a [u8]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TBSCertificate<'a> {
|
|
||||||
version: Version,
|
|
||||||
serial_number: &'a [u8],
|
|
||||||
signature: AlgorithmIdentifier<'a>,
|
|
||||||
issuer: &'a [u8],
|
|
||||||
validity: Validity<'a>,
|
|
||||||
subject: &'a [u8],
|
|
||||||
subject_public_key_info: SubjectPublicKeyInfo<'a>,
|
|
||||||
issuer_unique_id: Option<&'a [u8]>,
|
|
||||||
subject_unique_id: Option<&'a [u8]>,
|
|
||||||
extensions: Extensions,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum Version {
|
|
||||||
#[num_enum(default)]
|
|
||||||
v1 = 0,
|
|
||||||
v2 = 1,
|
|
||||||
v3 = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Validity<'a> {
|
|
||||||
not_before: Time<'a>,
|
|
||||||
not_after: Time<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Time<'a> {
|
|
||||||
UTCTime(&'a [u8]),
|
|
||||||
GeneralizedTime(&'a [u8]),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SubjectPublicKeyInfo<'a> {
|
|
||||||
algorithm: AlgorithmIdentifier<'a>,
|
|
||||||
subject_public_key: &'a [u8],
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Extensions {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AlgorithmIdentifier<'a> {
|
|
||||||
pub algorithm: &'a [u8],
|
|
||||||
pub parameters: &'a [u8],
|
|
||||||
}
|
|
10
src/key.rs
10
src/key.rs
|
@ -10,12 +10,12 @@ use core::convert::TryFrom;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct HkdfLabel<'a> {
|
pub struct HkdfLabel<'a> {
|
||||||
// Length of hash function
|
// Length of hash function
|
||||||
pub length: u16,
|
pub length: u16,
|
||||||
// Label vector: "tls13 " + label
|
// Label vector: "tls13 " + label
|
||||||
pub label_length: u8,
|
pub label_length: u8,
|
||||||
pub label: &'a [u8],
|
pub label: &'a [u8],
|
||||||
// Context vector: Hashed message
|
// Context vector: Hashed message
|
||||||
pub context_length: u8,
|
pub context_length: u8,
|
||||||
pub context: &'a [u8],
|
pub context: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,12 @@ pub mod parse;
|
||||||
pub mod buffer;
|
pub mod buffer;
|
||||||
pub mod key;
|
pub mod key;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod certificate;
|
|
||||||
|
|
||||||
use nom::error::ParseError;
|
|
||||||
|
|
||||||
// TODO: Implement errors
|
// TODO: Implement errors
|
||||||
// Details: Encapsulate smoltcp & nom errors
|
// Details: Encapsulate smoltcp & nom errors
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
PropagatedError(smoltcp::Error),
|
PropagatedError(smoltcp::Error),
|
||||||
ParsingError(nom::error::ErrorKind),
|
ParsingError,
|
||||||
EncryptionError,
|
EncryptionError,
|
||||||
DecryptionError,
|
DecryptionError,
|
||||||
CapacityError,
|
CapacityError,
|
||||||
|
|
91
src/main.rs
91
src/main.rs
|
@ -22,30 +22,31 @@ use hkdf::Hkdf;
|
||||||
use smoltcp_tls::key::*;
|
use smoltcp_tls::key::*;
|
||||||
use smoltcp_tls::buffer::TlsBuffer;
|
use smoltcp_tls::buffer::TlsBuffer;
|
||||||
|
|
||||||
use smoltcp_tls::certificate::*;
|
use asn1_der::{
|
||||||
|
DerObject,
|
||||||
|
typed::{ DerEncodable, DerDecodable }
|
||||||
|
};
|
||||||
|
|
||||||
use asn1_der::DerObject;
|
|
||||||
use smoltcp_tls::parse::*;
|
|
||||||
|
|
||||||
struct CountingRng(u64);
|
struct CountingRng(u64);
|
||||||
|
|
||||||
impl RngCore for CountingRng {
|
impl RngCore for CountingRng {
|
||||||
fn next_u32(&mut self) -> u32 {
|
fn next_u32(&mut self) -> u32 {
|
||||||
self.next_u64() as u32
|
self.next_u64() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_u64(&mut self) -> u64 {
|
fn next_u64(&mut self) -> u64 {
|
||||||
self.0 += 1;
|
self.0 += 1;
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||||
impls::fill_bytes_via_next(self, dest)
|
impls::fill_bytes_via_next(self, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
||||||
Ok(self.fill_bytes(dest))
|
Ok(self.fill_bytes(dest))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CryptoRng for CountingRng {}
|
impl CryptoRng for CountingRng {}
|
||||||
|
@ -53,40 +54,40 @@ impl CryptoRng for CountingRng {}
|
||||||
static mut RNG: CountingRng = CountingRng(0);
|
static mut RNG: CountingRng = CountingRng(0);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut socket_set_entries: [_; 8] = Default::default();
|
let mut socket_set_entries: [_; 8] = Default::default();
|
||||||
let mut sockets = SocketSet::new(&mut socket_set_entries[..]);
|
let mut sockets = SocketSet::new(&mut socket_set_entries[..]);
|
||||||
|
|
||||||
let mut tx_storage = [0; 4096];
|
let mut tx_storage = [0; 4096];
|
||||||
let mut rx_storage = [0; 4096];
|
let mut rx_storage = [0; 4096];
|
||||||
|
|
||||||
let mut tls_socket = unsafe {
|
let mut tls_socket = unsafe {
|
||||||
let tx_buffer = TcpSocketBuffer::new(&mut tx_storage[..]);
|
let tx_buffer = TcpSocketBuffer::new(&mut tx_storage[..]);
|
||||||
let rx_buffer = TcpSocketBuffer::new(&mut rx_storage[..]);
|
let rx_buffer = TcpSocketBuffer::new(&mut rx_storage[..]);
|
||||||
TlsSocket::new(
|
TlsSocket::new(
|
||||||
&mut sockets,
|
&mut sockets,
|
||||||
rx_buffer,
|
rx_buffer,
|
||||||
tx_buffer,
|
tx_buffer,
|
||||||
&mut RNG,
|
&mut RNG,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
tls_socket.tcp_connect(
|
tls_socket.tcp_connect(
|
||||||
&mut sockets,
|
&mut sockets,
|
||||||
(Ipv4Address::new(192, 168, 1, 125), 1883),
|
(Ipv4Address::new(192, 168, 1, 125), 1883),
|
||||||
49600
|
49600
|
||||||
).unwrap();
|
).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.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] = [
|
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
|
||||||
];
|
];
|
||||||
|
|
124
src/parse.rs
124
src/parse.rs
|
@ -5,7 +5,6 @@ use nom::bytes::complete::take_till;
|
||||||
use nom::combinator::complete;
|
use nom::combinator::complete;
|
||||||
use nom::sequence::preceded;
|
use nom::sequence::preceded;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
use nom::error::make_error;
|
|
||||||
use nom::error::ErrorKind;
|
use nom::error::ErrorKind;
|
||||||
use smoltcp::Error;
|
use smoltcp::Error;
|
||||||
use smoltcp::Result;
|
use smoltcp::Result;
|
||||||
|
@ -13,18 +12,7 @@ use smoltcp::Result;
|
||||||
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
|
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
|
||||||
|
|
||||||
use crate::tls_packet::*;
|
use crate::tls_packet::*;
|
||||||
use crate::certificate::Certificate as Asn1DerCertificate;
|
|
||||||
use crate::certificate::Version as Asn1DerVersion;
|
|
||||||
use crate::certificate::AlgorithmIdentifier as Asn1DerAlgId;
|
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use core::convert::TryInto;
|
|
||||||
|
|
||||||
use asn1_der::{
|
|
||||||
DerObject,
|
|
||||||
typed::{ DerEncodable, DerDecodable },
|
|
||||||
Asn1DerError,
|
|
||||||
};
|
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
@ -339,115 +327,3 @@ fn parse_extension(bytes: &[u8], handshake_type: HandshakeType) -> IResult<&[u8]
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_asn1_der_header(bytes: &[u8]) -> IResult<&[u8], (u8, usize)> {
|
|
||||||
// Parse tag
|
|
||||||
let (rest, tag) = take(1_usize)(bytes)?;
|
|
||||||
// Parse length
|
|
||||||
let (rest, length_byte) = take(1_usize)(rest)?;
|
|
||||||
if length_byte[0] <= 0x7F {
|
|
||||||
Ok((rest, (tag[0], length_byte[0].into())))
|
|
||||||
} else {
|
|
||||||
if length_byte[0] & 0x7F > core::mem::size_of::<usize>().try_into().unwrap() {
|
|
||||||
return Err(nom::Err::Failure((length_byte, ErrorKind::TooLarge)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let length_size = length_byte[0] & 0x7F;
|
|
||||||
let (rem, length_slice) = take(length_size)(rest)?;
|
|
||||||
let mut length_array: [u8; 8] = [0; 8];
|
|
||||||
for array_index in 0..length_slice.len() {
|
|
||||||
length_array[array_index + 8 - length_slice.len()] = length_slice[array_index];
|
|
||||||
}
|
|
||||||
Ok((rem, (tag[0], usize::from_be_bytes(length_array))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_asn1_der_object(bytes: &[u8]) -> IResult<&[u8], (u8, usize, &[u8])> {
|
|
||||||
let (rest, (tag, length)) = parse_asn1_der_header(bytes)?;
|
|
||||||
let (rest, value) = take(length)(rest)?;
|
|
||||||
Ok((rest, (tag, length, value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_asn1_der_certificate(bytes: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> {
|
|
||||||
let (_, (_, _, rest)) = parse_asn1_der_object(bytes)?;
|
|
||||||
let (rest, (_, _, tbscertificate_slice)) = parse_asn1_der_object(rest)?;
|
|
||||||
let (rest, (_, _, signature_alg)) = parse_asn1_der_object(rest)?;
|
|
||||||
let (rest, (_, _, sig_val)) = parse_asn1_der_object(rest)?;
|
|
||||||
Ok((rest, (tbscertificate_slice, signature_alg, sig_val)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_asn1_der_tbs_certificate(bytes: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// version: [0] EXPLICIT Version DEFAULT V1
|
|
||||||
// Version encapsulates an Integer
|
|
||||||
// i.e. context-specific, constructed, type [0] -> tag: A0
|
|
||||||
pub fn parse_asn1_der_version(bytes: &[u8]) -> IResult<&[u8], Asn1DerVersion> {
|
|
||||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
|
||||||
// Verify the tag is indeed 0xA0
|
|
||||||
if tag_val != 0xA0 {
|
|
||||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
|
||||||
}
|
|
||||||
// Parse the encapsulated INTEGER, force completeness
|
|
||||||
let (_, integer) = complete(parse_asn1_der_integer)(value)?;
|
|
||||||
// Either 0, 1, or 2, take the last byte and assert all former bytes to be 0
|
|
||||||
let (zeroes, version_byte) = take(integer.len()-1)(integer)?;
|
|
||||||
complete(take_till(|byte| byte != 0))(zeroes)?;
|
|
||||||
Ok((rest, Asn1DerVersion::try_from(version_byte[0]).unwrap()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTEGER: tag: 0x02
|
|
||||||
pub fn parse_asn1_der_integer(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
|
||||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
|
||||||
// Verify the tag is indeed 0x02
|
|
||||||
if tag_val != 0x02 {
|
|
||||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
|
||||||
}
|
|
||||||
Ok((rest, value))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CertificateSerialNumber: alias of INTEGER
|
|
||||||
pub fn parse_asn1_der_serial_number(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
|
||||||
parse_asn1_der_integer(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Algorithm Identifier: Sequence -> universal, constructed, 0 (0x30)
|
|
||||||
// Encapsulates OID (alg) and optional params (params)
|
|
||||||
pub fn parse_asn1_der_algorithm_identifier(bytes: &[u8]) -> IResult<&[u8], Asn1DerAlgId> {
|
|
||||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
|
||||||
// Verify the tag_val is indeed 0x30
|
|
||||||
if tag_val != 0x30 {
|
|
||||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
|
||||||
}
|
|
||||||
// Parse OID and then optionl parameters
|
|
||||||
let (_, (oid, (_, _, optional_param))) = complete(
|
|
||||||
tuple((
|
|
||||||
parse_asn1_der_oid,
|
|
||||||
parse_asn1_der_object
|
|
||||||
))
|
|
||||||
)(value)?;
|
|
||||||
Ok((
|
|
||||||
rest,
|
|
||||||
Asn1DerAlgId {
|
|
||||||
algorithm: oid,
|
|
||||||
parameters: optional_param,
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parser for Universal OID type (0x06)
|
|
||||||
pub fn parse_asn1_der_oid(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
|
||||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
|
||||||
// Verify the tag_val is indeed 0x06
|
|
||||||
if tag_val != 0x06 {
|
|
||||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
|
||||||
}
|
|
||||||
Ok((rest, value))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parser for Time Validity Structure
|
|
||||||
pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
|
||||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
1112
src/session.rs
1112
src/session.rs
File diff suppressed because it is too large
Load Diff
780
src/tls.rs
780
src/tls.rs
|
@ -41,443 +41,443 @@ use crate::session::{Session, TlsRole};
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub(crate) enum TlsState {
|
pub(crate) enum TlsState {
|
||||||
START,
|
START,
|
||||||
WAIT_SH,
|
WAIT_SH,
|
||||||
WAIT_EE,
|
WAIT_EE,
|
||||||
WAIT_CERT_CR,
|
WAIT_CERT_CR,
|
||||||
WAIT_CERT,
|
WAIT_CERT,
|
||||||
WAIT_CV,
|
WAIT_CV,
|
||||||
WAIT_FINISHED,
|
WAIT_FINISHED,
|
||||||
CONNECTED,
|
CONNECTED,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Group up all session_specific parameters into a separate structure
|
// TODO: Group up all session_specific parameters into a separate structure
|
||||||
pub struct TlsSocket<R: 'static + RngCore + CryptoRng>
|
pub struct TlsSocket<R: 'static + RngCore + CryptoRng>
|
||||||
{
|
{
|
||||||
tcp_handle: SocketHandle,
|
tcp_handle: SocketHandle,
|
||||||
rng: R,
|
rng: R,
|
||||||
session: RefCell<Session>,
|
session: RefCell<Session>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||||
pub fn new<'a, 'b, 'c>(
|
pub fn new<'a, 'b, 'c>(
|
||||||
sockets: &mut SocketSet<'a, 'b, 'c>,
|
sockets: &mut SocketSet<'a, 'b, 'c>,
|
||||||
rx_buffer: TcpSocketBuffer<'b>,
|
rx_buffer: TcpSocketBuffer<'b>,
|
||||||
tx_buffer: TcpSocketBuffer<'b>,
|
tx_buffer: TcpSocketBuffer<'b>,
|
||||||
rng: R,
|
rng: R,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
'b: 'c,
|
'b: 'c,
|
||||||
{
|
{
|
||||||
let tcp_socket = TcpSocket::new(rx_buffer, tx_buffer);
|
let tcp_socket = TcpSocket::new(rx_buffer, tx_buffer);
|
||||||
let tcp_handle = sockets.add(tcp_socket);
|
let tcp_handle = sockets.add(tcp_socket);
|
||||||
TlsSocket {
|
TlsSocket {
|
||||||
tcp_handle,
|
tcp_handle,
|
||||||
rng,
|
rng,
|
||||||
session: RefCell::new(
|
session: RefCell::new(
|
||||||
Session::new(TlsRole::Client)
|
Session::new(TlsRole::Client)
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tcp_connect<T, U>(
|
pub fn tcp_connect<T, U>(
|
||||||
&mut self,
|
&mut self,
|
||||||
sockets: &mut SocketSet,
|
sockets: &mut SocketSet,
|
||||||
remote_endpoint: T,
|
remote_endpoint: T,
|
||||||
local_endpoint: U,
|
local_endpoint: U,
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
T: Into<IpEndpoint>,
|
T: Into<IpEndpoint>,
|
||||||
U: Into<IpEndpoint>,
|
U: Into<IpEndpoint>,
|
||||||
{
|
{
|
||||||
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
||||||
if tcp_socket.state() == TcpState::Established {
|
if tcp_socket.state() == TcpState::Established {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
tcp_socket.connect(remote_endpoint, local_endpoint)
|
tcp_socket.connect(remote_endpoint, local_endpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tls_connect<DeviceT>(
|
pub fn tls_connect<DeviceT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
iface: &mut EthernetInterface<DeviceT>,
|
iface: &mut EthernetInterface<DeviceT>,
|
||||||
sockets: &mut SocketSet,
|
sockets: &mut SocketSet,
|
||||||
now: Instant
|
now: Instant
|
||||||
) -> Result<bool>
|
) -> Result<bool>
|
||||||
where
|
where
|
||||||
DeviceT: for<'d> Device<'d>
|
DeviceT: for<'d> Device<'d>
|
||||||
{
|
{
|
||||||
// Check tcp_socket connectivity
|
// Check tcp_socket connectivity
|
||||||
{
|
{
|
||||||
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
||||||
tcp_socket.set_keep_alive(Some(smoltcp::time::Duration::from_millis(1000)));
|
tcp_socket.set_keep_alive(Some(smoltcp::time::Duration::from_millis(1000)));
|
||||||
if tcp_socket.state() != TcpState::Established {
|
if tcp_socket.state() != TcpState::Established {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle TLS handshake through TLS states
|
// Handle TLS handshake through TLS states
|
||||||
let tls_state = {
|
let tls_state = {
|
||||||
self.session.borrow().get_tls_state()
|
self.session.borrow().get_tls_state()
|
||||||
};
|
};
|
||||||
match tls_state {
|
match tls_state {
|
||||||
// Initiate TLS handshake
|
// Initiate TLS handshake
|
||||||
TlsState::START => {
|
TlsState::START => {
|
||||||
// Prepare field that is randomised,
|
// Prepare field that is randomised,
|
||||||
// Supply it to the TLS repr builder.
|
// Supply it to the TLS repr builder.
|
||||||
let ecdh_secret = EphemeralSecret::random(&mut self.rng);
|
let ecdh_secret = EphemeralSecret::random(&mut self.rng);
|
||||||
let mut random: [u8; 32] = [0; 32];
|
let mut random: [u8; 32] = [0; 32];
|
||||||
let mut session_id: [u8; 32] = [0; 32];
|
let mut session_id: [u8; 32] = [0; 32];
|
||||||
self.rng.fill_bytes(&mut random);
|
self.rng.fill_bytes(&mut random);
|
||||||
self.rng.fill_bytes(&mut session_id);
|
self.rng.fill_bytes(&mut session_id);
|
||||||
let repr = TlsRepr::new()
|
let repr = TlsRepr::new()
|
||||||
.client_hello(&ecdh_secret, random, session_id.clone());
|
.client_hello(&ecdh_secret, random, session_id.clone());
|
||||||
|
|
||||||
// Update hash function with client hello handshake
|
// Update hash function with client hello handshake
|
||||||
let mut array = [0; 512];
|
let mut array = [0; 512];
|
||||||
let mut buffer = TlsBuffer::new(&mut array);
|
let mut buffer = TlsBuffer::new(&mut array);
|
||||||
buffer.enqueue_tls_repr(repr)?;
|
buffer.enqueue_tls_repr(repr)?;
|
||||||
let slice: &[u8] = buffer.into();
|
let slice: &[u8] = buffer.into();
|
||||||
|
|
||||||
// Send the packet
|
// Send the packet
|
||||||
self.send_tls_slice(sockets, slice)?;
|
self.send_tls_slice(sockets, slice)?;
|
||||||
|
|
||||||
// Update TLS session
|
// Update TLS session
|
||||||
self.session.borrow_mut().client_update_for_ch(
|
self.session.borrow_mut().client_update_for_ch(
|
||||||
ecdh_secret,
|
ecdh_secret,
|
||||||
session_id,
|
session_id,
|
||||||
&slice[5..]
|
&slice[5..]
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
// TLS Client wait for Server Hello
|
// TLS Client wait for Server Hello
|
||||||
// No need to send anything
|
// No need to send anything
|
||||||
TlsState::WAIT_SH => {},
|
TlsState::WAIT_SH => {},
|
||||||
|
|
||||||
// TLS Client wait for certificate from TLS server
|
// TLS Client wait for certificate from TLS server
|
||||||
// No need to send anything
|
// No need to send anything
|
||||||
// Note: TLS server should normally send SH alongside EE
|
// Note: TLS server should normally send SH alongside EE
|
||||||
// TLS client should jump from WAIT_SH directly to WAIT_CERT_CR directly.
|
// TLS client should jump from WAIT_SH directly to WAIT_CERT_CR directly.
|
||||||
TlsState::WAIT_EE => {},
|
TlsState::WAIT_EE => {},
|
||||||
|
|
||||||
// TLS Client wait for server's certificate
|
// TLS Client wait for server's certificate
|
||||||
// No need to send anything
|
// No need to send anything
|
||||||
TlsState::WAIT_CERT_CR => {},
|
TlsState::WAIT_CERT_CR => {},
|
||||||
|
|
||||||
_ => todo!()
|
_ => todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll the network interface
|
// Poll the network interface
|
||||||
iface.poll(sockets, now);
|
iface.poll(sockets, now);
|
||||||
|
|
||||||
// Read for TLS packet
|
// Read for TLS packet
|
||||||
let mut array: [u8; 2048] = [0; 2048];
|
let mut array: [u8; 2048] = [0; 2048];
|
||||||
let mut tls_repr_vec = self.recv_tls_repr(sockets, &mut array)?;
|
let mut tls_repr_vec = self.recv_tls_repr(sockets, &mut array)?;
|
||||||
|
|
||||||
// Take the TLS representation out of the vector,
|
// Take the TLS representation out of the vector,
|
||||||
// Process as a queue
|
// Process as a queue
|
||||||
let tls_repr_vec_size = tls_repr_vec.len();
|
let tls_repr_vec_size = tls_repr_vec.len();
|
||||||
for index in 0..tls_repr_vec_size {
|
for index in 0..tls_repr_vec_size {
|
||||||
let repr = tls_repr_vec.remove(0);
|
let repr = tls_repr_vec.remove(0);
|
||||||
self.process(repr)?;
|
self.process(repr)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.session.borrow().has_completed_handshake())
|
Ok(self.session.borrow().has_completed_handshake())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process TLS ingress during handshake
|
// Process TLS ingress during handshake
|
||||||
fn process(&self, mut repr: TlsRepr) -> Result<()> {
|
fn process(&self, mut repr: TlsRepr) -> Result<()> {
|
||||||
// Change_cipher_spec check:
|
// Change_cipher_spec check:
|
||||||
// Must receive CCS before recv peer's FINISH message
|
// Must receive CCS before recv peer's FINISH message
|
||||||
// i.e. Must happen after START and before CONNECTED
|
// i.e. Must happen after START and before CONNECTED
|
||||||
//
|
//
|
||||||
// CCS message only exist for compatibility reason,
|
// CCS message only exist for compatibility reason,
|
||||||
// Drop the message and update `received_change_cipher_spec`
|
// Drop the message and update `received_change_cipher_spec`
|
||||||
// Note: CSS doesn't count as a proper record, no need to increment sequence number
|
// Note: CSS doesn't count as a proper record, no need to increment sequence number
|
||||||
if repr.is_change_cipher_spec() {
|
if repr.is_change_cipher_spec() {
|
||||||
let mut session = self.session.borrow_mut();
|
let mut session = self.session.borrow_mut();
|
||||||
session.receive_change_cipher_spec();
|
session.receive_change_cipher_spec();
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
let tls_state = {
|
let tls_state = {
|
||||||
self.session.borrow().get_tls_state()
|
self.session.borrow().get_tls_state()
|
||||||
};
|
};
|
||||||
match tls_state {
|
match tls_state {
|
||||||
// During WAIT_SH for a TLS client, client should wait for ServerHello
|
// During WAIT_SH for a TLS client, client should wait for ServerHello
|
||||||
TlsState::WAIT_SH => {
|
TlsState::WAIT_SH => {
|
||||||
// Legacy_protocol must be TLS 1.2
|
// Legacy_protocol must be TLS 1.2
|
||||||
if repr.version != TlsVersion::Tls12 {
|
if repr.version != TlsVersion::Tls12 {
|
||||||
// Abort communication
|
// Abort communication
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Validate SH
|
// TODO: Validate SH
|
||||||
if repr.is_server_hello() {
|
if repr.is_server_hello() {
|
||||||
// Check SH content:
|
// Check SH content:
|
||||||
// random: Cannot represent HelloRequestRetry
|
// random: Cannot represent HelloRequestRetry
|
||||||
// (TODO: Support other key shares, e.g. X25519)
|
// (TODO: Support other key shares, e.g. X25519)
|
||||||
// session_id_echo: should be same as the one sent by client
|
// session_id_echo: should be same as the one sent by client
|
||||||
// cipher_suite: Store
|
// cipher_suite: Store
|
||||||
// (TODO: Check if such suite was offered)
|
// (TODO: Check if such suite was offered)
|
||||||
// compression_method: Must be null, not supported in TLS 1.3
|
// compression_method: Must be null, not supported in TLS 1.3
|
||||||
//
|
//
|
||||||
// Check extensions:
|
// Check extensions:
|
||||||
// supported_version: Must be TLS 1.3
|
// supported_version: Must be TLS 1.3
|
||||||
// key_share: Store key, must be in secp256r1
|
// key_share: Store key, must be in secp256r1
|
||||||
// (TODO: Support other key shares ^)
|
// (TODO: Support other key shares ^)
|
||||||
|
|
||||||
// "Cache" for ECDHE server public info
|
// "Cache" for ECDHE server public info
|
||||||
let mut server_public: Option<EncodedPoint> = None;
|
let mut server_public: Option<EncodedPoint> = None;
|
||||||
let mut selected_cipher: Option<CipherSuite> = None;
|
let mut selected_cipher: Option<CipherSuite> = None;
|
||||||
|
|
||||||
// Process the handshake data within ServerHello
|
// Process the handshake data within ServerHello
|
||||||
let handshake_data = &repr.handshake.as_ref().unwrap().handshake_data;
|
let handshake_data = &repr.handshake.as_ref().unwrap().handshake_data;
|
||||||
if let HandshakeData::ServerHello(server_hello) = handshake_data {
|
if let HandshakeData::ServerHello(server_hello) = handshake_data {
|
||||||
|
|
||||||
// Check random: Cannot be SHA-256 of "HelloRetryRequest"
|
// Check random: Cannot be SHA-256 of "HelloRetryRequest"
|
||||||
if server_hello.random == HRR_RANDOM {
|
if server_hello.random == HRR_RANDOM {
|
||||||
// Abort communication
|
// Abort communication
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check session_id_echo
|
// Check session_id_echo
|
||||||
// The socket should have a session_id after moving from START state
|
// 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) {
|
if !self.session.borrow().verify_session_id_echo(server_hello.session_id_echo) {
|
||||||
// Abort communication
|
// Abort communication
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note the selected cipher suite
|
// Note the selected cipher suite
|
||||||
selected_cipher.replace(server_hello.cipher_suite);
|
selected_cipher.replace(server_hello.cipher_suite);
|
||||||
|
|
||||||
// TLSv13 forbidden key compression
|
// TLSv13 forbidden key compression
|
||||||
if server_hello.compression_method != 0 {
|
if server_hello.compression_method != 0 {
|
||||||
// Abort communciation
|
// Abort communciation
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
for extension in server_hello.extensions.iter() {
|
for extension in server_hello.extensions.iter() {
|
||||||
if extension.extension_type == ExtensionType::SupportedVersions {
|
if extension.extension_type == ExtensionType::SupportedVersions {
|
||||||
if let ExtensionData::SupportedVersions(
|
if let ExtensionData::SupportedVersions(
|
||||||
SupportedVersions::ServerHello {
|
SupportedVersions::ServerHello {
|
||||||
selected_version
|
selected_version
|
||||||
}
|
}
|
||||||
) = extension.extension_data {
|
) = extension.extension_data {
|
||||||
if selected_version != TlsVersion::Tls13 {
|
if selected_version != TlsVersion::Tls13 {
|
||||||
// Abort for choosing not offered TLS version
|
// Abort for choosing not offered TLS version
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Abort for illegal extension
|
// Abort for illegal extension
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if extension.extension_type == ExtensionType::KeyShare {
|
if extension.extension_type == ExtensionType::KeyShare {
|
||||||
if let ExtensionData::KeyShareEntry(
|
if let ExtensionData::KeyShareEntry(
|
||||||
KeyShareEntryContent::KeyShareServerHello {
|
KeyShareEntryContent::KeyShareServerHello {
|
||||||
server_share
|
server_share
|
||||||
}
|
}
|
||||||
) = &extension.extension_data {
|
) = &extension.extension_data {
|
||||||
// TODO: Use legitimate checking to ensure the chosen
|
// TODO: Use legitimate checking to ensure the chosen
|
||||||
// group is indeed acceptable, when allowing more (EC)DHE
|
// group is indeed acceptable, when allowing more (EC)DHE
|
||||||
// key sharing
|
// key sharing
|
||||||
if server_share.group != NamedGroup::secp256r1 {
|
if server_share.group != NamedGroup::secp256r1 {
|
||||||
// Abort for wrong key sharing
|
// Abort for wrong key sharing
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
// Store key
|
// Store key
|
||||||
// It is surely from secp256r1, no other groups are permitted
|
// It is surely from secp256r1, no other groups are permitted
|
||||||
// Convert untagged bytes into encoded point on p256 eliptic curve
|
// Convert untagged bytes into encoded point on p256 eliptic curve
|
||||||
// Slice the first byte out of the bytes
|
// Slice the first byte out of the bytes
|
||||||
server_public.replace(
|
server_public.replace(
|
||||||
EncodedPoint::from_untagged_bytes(
|
EncodedPoint::from_untagged_bytes(
|
||||||
GenericArray::from_slice(&server_share.key_exchange[1..])
|
GenericArray::from_slice(&server_share.key_exchange[1..])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Handle invalid TLS packet
|
// Handle invalid TLS packet
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that both selected_cipher and server_public were received
|
// Check that both selected_cipher and server_public were received
|
||||||
if selected_cipher.is_none() || server_public.is_none() {
|
if selected_cipher.is_none() || server_public.is_none() {
|
||||||
// Abort communication
|
// Abort communication
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is indeed a desirable ServerHello TLS repr
|
// This is indeed a desirable ServerHello TLS repr
|
||||||
// Reprocess ServerHello into a slice
|
// Reprocess ServerHello into a slice
|
||||||
// Update session with required parameter
|
// Update session with required parameter
|
||||||
let mut array = [0; 512];
|
let mut array = [0; 512];
|
||||||
let mut buffer = TlsBuffer::new(&mut array);
|
let mut buffer = TlsBuffer::new(&mut array);
|
||||||
buffer.enqueue_tls_repr(repr)?;
|
buffer.enqueue_tls_repr(repr)?;
|
||||||
let slice: &[u8] = buffer.into();
|
let slice: &[u8] = buffer.into();
|
||||||
let mut session = self.session.borrow_mut();
|
let mut session = self.session.borrow_mut();
|
||||||
session.client_update_for_sh(
|
session.client_update_for_sh(
|
||||||
selected_cipher.unwrap(),
|
selected_cipher.unwrap(),
|
||||||
server_public.unwrap(),
|
server_public.unwrap(),
|
||||||
&slice[5..]
|
&slice[5..]
|
||||||
);
|
);
|
||||||
// Key exchange occurred, seq_num is set to 0
|
// Key exchange occurred, seq_num is set to 0
|
||||||
// Do NOT update seq_num again. Early return.
|
// Do NOT update seq_num again. Early return.
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Expect encrypted extensions after receiving SH
|
// Expect encrypted extensions after receiving SH
|
||||||
TlsState::WAIT_EE => {
|
TlsState::WAIT_EE => {
|
||||||
// Check that the packet is classified as application data
|
// Check that the packet is classified as application data
|
||||||
if !repr.is_application_data() {
|
if !repr.is_application_data() {
|
||||||
// Abort communication, this affect IV calculation
|
// Abort communication, this affect IV calculation
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExcepytedExtensions are disguised as ApplicationData
|
// ExcepytedExtensions are disguised as ApplicationData
|
||||||
// Pull out the `payload` from TlsRepr, decrypt as EE
|
// Pull out the `payload` from TlsRepr, decrypt as EE
|
||||||
let mut payload = repr.payload.take().unwrap();
|
let mut payload = repr.payload.take().unwrap();
|
||||||
log::info!("Encrypted payload: {:?}", payload);
|
log::info!("Encrypted payload: {:?}", payload);
|
||||||
let mut array: [u8; 5] = [0; 5];
|
let mut array: [u8; 5] = [0; 5];
|
||||||
let mut buffer = TlsBuffer::new(&mut array);
|
let mut buffer = TlsBuffer::new(&mut array);
|
||||||
buffer.write_u8(repr.content_type.into())?;
|
buffer.write_u8(repr.content_type.into())?;
|
||||||
buffer.write_u16(repr.version.into())?;
|
buffer.write_u16(repr.version.into())?;
|
||||||
buffer.write_u16(repr.length)?;
|
buffer.write_u16(repr.length)?;
|
||||||
let associated_data: &[u8] = buffer.into();
|
let associated_data: &[u8] = buffer.into();
|
||||||
log::info!("Associated Data: {:?}", associated_data);
|
log::info!("Associated Data: {:?}", associated_data);
|
||||||
{
|
{
|
||||||
self.session.borrow_mut().decrypt_in_place(
|
self.session.borrow_mut().decrypt_in_place(
|
||||||
associated_data,
|
associated_data,
|
||||||
&mut payload
|
&mut payload
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
log::info!("decrypted EE");
|
log::info!("decrypted EE");
|
||||||
log::info!("{:?}", payload);
|
log::info!("{:?}", payload);
|
||||||
|
|
||||||
// TODO: Parse payload of EE
|
// TODO: Parse payload of EE
|
||||||
let parse_result = parse_handshake(&payload);
|
let parse_result = parse_handshake(&payload);
|
||||||
let (_, encrypted_extensions_handshake) = parse_result
|
let (_, encrypted_extensions_handshake) = parse_result
|
||||||
.map_err(|_| Error::Unrecognized)?;
|
.map_err(|_| Error::Unrecognized)?;
|
||||||
// TODO: Process payload
|
// TODO: Process payload
|
||||||
// Practically, nothing will be done about cookies/server name
|
// Practically, nothing will be done about cookies/server name
|
||||||
// Extension processing is therefore skipped
|
// Extension processing is therefore skipped
|
||||||
log::info!("Parsed EE");
|
log::info!("Parsed EE");
|
||||||
self.session.borrow_mut().client_update_for_ee();
|
self.session.borrow_mut().client_update_for_ee();
|
||||||
},
|
},
|
||||||
|
|
||||||
// In this stage, wait for a certificate from server
|
// In this stage, wait for a certificate from server
|
||||||
// Parse the certificate and check its content
|
// Parse the certificate and check its content
|
||||||
TlsState::WAIT_CERT_CR => {
|
TlsState::WAIT_CERT_CR => {
|
||||||
// Check that the packet is classified as application data
|
// Check that the packet is classified as application data
|
||||||
// Certificates transfer is disguised as application data
|
// Certificates transfer is disguised as application data
|
||||||
if !repr.is_application_data() {
|
if !repr.is_application_data() {
|
||||||
// Abort communication, this affect IV calculation
|
// Abort communication, this affect IV calculation
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull out the `payload` from TlsRepr, decrypt as EE
|
// Pull out the `payload` from TlsRepr, decrypt as EE
|
||||||
let mut payload = repr.payload.take().unwrap();
|
let mut payload = repr.payload.take().unwrap();
|
||||||
|
|
||||||
// Instantiate associated data and decrypt
|
// Instantiate associated data and decrypt
|
||||||
let mut array: [u8; 5] = [0; 5];
|
let mut array: [u8; 5] = [0; 5];
|
||||||
let mut buffer = TlsBuffer::new(&mut array);
|
let mut buffer = TlsBuffer::new(&mut array);
|
||||||
buffer.write_u8(repr.content_type.into())?;
|
buffer.write_u8(repr.content_type.into())?;
|
||||||
buffer.write_u16(repr.version.into())?;
|
buffer.write_u16(repr.version.into())?;
|
||||||
buffer.write_u16(repr.length)?;
|
buffer.write_u16(repr.length)?;
|
||||||
let associated_data: &[u8] = buffer.into();
|
let associated_data: &[u8] = buffer.into();
|
||||||
{
|
{
|
||||||
self.session.borrow_mut().decrypt_in_place(
|
self.session.borrow_mut().decrypt_in_place(
|
||||||
associated_data,
|
associated_data,
|
||||||
&mut payload
|
&mut payload
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
log::info!("Decrypted payload {:?}", payload);
|
log::info!("Decrypted payload {:?}", payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// A TLS Record was received and processed and verified
|
// A TLS Record was received and processed and verified
|
||||||
// Increment sequence number
|
// Increment sequence number
|
||||||
self.session.borrow_mut().increment_sequence_number();
|
self.session.borrow_mut().increment_sequence_number();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic inner send method, through TCP socket
|
// Generic inner send method, through TCP socket
|
||||||
fn send_tls_repr(&self, sockets: &mut SocketSet, tls_repr: TlsRepr) -> Result<()> {
|
fn send_tls_repr(&self, sockets: &mut SocketSet, tls_repr: TlsRepr) -> Result<()> {
|
||||||
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
||||||
if !tcp_socket.can_send() {
|
if !tcp_socket.can_send() {
|
||||||
return Err(Error::Illegal);
|
return Err(Error::Illegal);
|
||||||
}
|
}
|
||||||
let mut array = [0; 2048];
|
let mut array = [0; 2048];
|
||||||
let mut buffer = TlsBuffer::new(&mut array);
|
let mut buffer = TlsBuffer::new(&mut array);
|
||||||
buffer.enqueue_tls_repr(tls_repr)?;
|
buffer.enqueue_tls_repr(tls_repr)?;
|
||||||
let buffer_size = buffer.get_size();
|
let buffer_size = buffer.get_size();
|
||||||
|
|
||||||
// Force send to return if send is unsuccessful
|
// Force send to return if send is unsuccessful
|
||||||
// Only update sequence number if the send is successful
|
// Only update sequence number if the send is successful
|
||||||
tcp_socket.send_slice(buffer.into())
|
tcp_socket.send_slice(buffer.into())
|
||||||
.and_then(
|
.and_then(
|
||||||
|size| if size == buffer_size {
|
|size| if size == buffer_size {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Truncated)
|
Err(Error::Truncated)
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
self.session.borrow_mut().increment_sequence_number();
|
self.session.borrow_mut().increment_sequence_number();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic inner send method for buffer IO, through TCP socket
|
// Generic inner send method for buffer IO, through TCP socket
|
||||||
// Usage: Push a slice representation of ONE TLS packet
|
// Usage: Push a slice representation of ONE TLS packet
|
||||||
// This function will only increment sequence number by 1
|
// This function will only increment sequence number by 1
|
||||||
// Repeatedly call this function if sending multiple TLS packets is needed
|
// Repeatedly call this function if sending multiple TLS packets is needed
|
||||||
fn send_tls_slice(&self, sockets: &mut SocketSet, slice: &[u8]) -> Result<()> {
|
fn send_tls_slice(&self, sockets: &mut SocketSet, slice: &[u8]) -> Result<()> {
|
||||||
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
||||||
if !tcp_socket.can_send() {
|
if !tcp_socket.can_send() {
|
||||||
return Err(Error::Illegal);
|
return Err(Error::Illegal);
|
||||||
}
|
}
|
||||||
let buffer_size = slice.len();
|
let buffer_size = slice.len();
|
||||||
tcp_socket.send_slice(slice)
|
tcp_socket.send_slice(slice)
|
||||||
.and_then(
|
.and_then(
|
||||||
|size| if size == buffer_size {
|
|size| if size == buffer_size {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Truncated)
|
Err(Error::Truncated)
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
self.session.borrow_mut().increment_sequence_number();
|
self.session.borrow_mut().increment_sequence_number();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic inner recv method, through TCP socket
|
// Generic inner recv method, through TCP socket
|
||||||
// A TCP packet can contain multiple TLS records (including 0)
|
// A TCP packet can contain multiple TLS records (including 0)
|
||||||
// Therefore, sequence nubmer incrementation is not completed here
|
// Therefore, sequence nubmer incrementation is not completed here
|
||||||
fn recv_tls_repr<'a>(&'a self, sockets: &mut SocketSet, byte_array: &'a mut [u8]) -> Result<Vec::<TlsRepr>> {
|
fn recv_tls_repr<'a>(&'a self, sockets: &mut SocketSet, byte_array: &'a mut [u8]) -> Result<Vec::<TlsRepr>> {
|
||||||
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
||||||
if !tcp_socket.can_recv() {
|
if !tcp_socket.can_recv() {
|
||||||
return Ok((Vec::new()));
|
return Ok((Vec::new()));
|
||||||
}
|
}
|
||||||
let array_size = tcp_socket.recv_slice(byte_array)?;
|
let array_size = tcp_socket.recv_slice(byte_array)?;
|
||||||
let mut vec: Vec<TlsRepr> = Vec::new();
|
let mut vec: Vec<TlsRepr> = Vec::new();
|
||||||
let mut bytes: &[u8] = &byte_array[..array_size];
|
let mut bytes: &[u8] = &byte_array[..array_size];
|
||||||
loop {
|
loop {
|
||||||
match parse_tls_repr(bytes) {
|
match parse_tls_repr(bytes) {
|
||||||
Ok((rest, repr)) => {
|
Ok((rest, repr)) => {
|
||||||
vec.push(repr);
|
vec.push(repr);
|
||||||
if rest.len() == 0 {
|
if rest.len() == 0 {
|
||||||
return Ok(vec);
|
return Ok(vec);
|
||||||
} else {
|
} else {
|
||||||
bytes = rest;
|
bytes = rest;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => return Err(Error::Unrecognized),
|
_ => return Err(Error::Unrecognized),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue