Compare commits
3 Commits
2e8ccdf910
...
eadf776da3
Author | SHA1 | Date |
---|---|---|
occheung | eadf776da3 | |
occheung | 5986777770 | |
occheung | 2b107881d8 |
|
@ -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"
|
||||
|
|
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
|
||||
// TODO: Stricter visibility
|
||||
pub struct TlsBuffer<'a> {
|
||||
buffer: &'a mut [u8],
|
||||
index: RefCell<usize>,
|
||||
buffer: &'a mut [u8],
|
||||
index: RefCell<usize>,
|
||||
}
|
||||
|
||||
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<u8> {
|
||||
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<u8> {
|
||||
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<Extension>) -> 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<Extension>) -> 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
|
||||
);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
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)]
|
||||
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],
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
91
src/main.rs
91
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
|
||||
];
|
||||
|
|
124
src/parse.rs
124
src/parse.rs
|
@ -5,6 +5,7 @@ use nom::bytes::complete::take_till;
|
|||
use nom::combinator::complete;
|
||||
use nom::sequence::preceded;
|
||||
use nom::sequence::tuple;
|
||||
use nom::error::make_error;
|
||||
use nom::error::ErrorKind;
|
||||
use smoltcp::Error;
|
||||
use smoltcp::Result;
|
||||
|
@ -12,7 +13,18 @@ use smoltcp::Result;
|
|||
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
|
||||
|
||||
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::TryInto;
|
||||
|
||||
use asn1_der::{
|
||||
DerObject,
|
||||
typed::{ DerEncodable, DerDecodable },
|
||||
Asn1DerError,
|
||||
};
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
|
@ -327,3 +339,115 @@ 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)]
|
||||
#[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<R: 'static + RngCore + CryptoRng>
|
||||
{
|
||||
tcp_handle: SocketHandle,
|
||||
rng: R,
|
||||
session: RefCell<Session>,
|
||||
tcp_handle: SocketHandle,
|
||||
rng: R,
|
||||
session: RefCell<Session>,
|
||||
}
|
||||
|
||||
impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
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<T, U>(
|
||||
&mut self,
|
||||
sockets: &mut SocketSet,
|
||||
remote_endpoint: T,
|
||||
local_endpoint: U,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: Into<IpEndpoint>,
|
||||
U: Into<IpEndpoint>,
|
||||
{
|
||||
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
||||
if tcp_socket.state() == TcpState::Established {
|
||||
Ok(())
|
||||
} else {
|
||||
tcp_socket.connect(remote_endpoint, local_endpoint)
|
||||
}
|
||||
}
|
||||
pub fn tcp_connect<T, U>(
|
||||
&mut self,
|
||||
sockets: &mut SocketSet,
|
||||
remote_endpoint: T,
|
||||
local_endpoint: U,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: Into<IpEndpoint>,
|
||||
U: Into<IpEndpoint>,
|
||||
{
|
||||
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
||||
if tcp_socket.state() == TcpState::Established {
|
||||
Ok(())
|
||||
} else {
|
||||
tcp_socket.connect(remote_endpoint, local_endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tls_connect<DeviceT>(
|
||||
&mut self,
|
||||
iface: &mut EthernetInterface<DeviceT>,
|
||||
sockets: &mut SocketSet,
|
||||
now: Instant
|
||||
) -> Result<bool>
|
||||
where
|
||||
DeviceT: for<'d> Device<'d>
|
||||
{
|
||||
// Check tcp_socket connectivity
|
||||
{
|
||||
let mut tcp_socket = sockets.get::<TcpSocket>(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<DeviceT>(
|
||||
&mut self,
|
||||
iface: &mut EthernetInterface<DeviceT>,
|
||||
sockets: &mut SocketSet,
|
||||
now: Instant
|
||||
) -> Result<bool>
|
||||
where
|
||||
DeviceT: for<'d> Device<'d>
|
||||
{
|
||||
// Check tcp_socket connectivity
|
||||
{
|
||||
let mut tcp_socket = sockets.get::<TcpSocket>(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<EncodedPoint> = None;
|
||||
let mut selected_cipher: Option<CipherSuite> = None;
|
||||
// "Cache" for ECDHE server public info
|
||||
let mut server_public: Option<EncodedPoint> = None;
|
||||
let mut selected_cipher: Option<CipherSuite> = 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::<TcpSocket>(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::<TcpSocket>(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::<TcpSocket>(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::<TcpSocket>(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<Vec::<TlsRepr>> {
|
||||
let mut tcp_socket = sockets.get::<TcpSocket>(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<TlsRepr> = 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<Vec::<TlsRepr>> {
|
||||
let mut tcp_socket = sockets.get::<TcpSocket>(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<TlsRepr> = 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),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue