socket: handle concatenated handshake
This commit is contained in:
parent
59dc5873c5
commit
c57fc79f6b
|
@ -26,7 +26,7 @@ default-features = true
|
||||||
features = [ "heapless" ]
|
features = [ "heapless" ]
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
version = "0.6.0"
|
git = "https://github.com/smoltcp-rs/smoltcp.git"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp", "alloc"]
|
features = ["ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp", "alloc"]
|
||||||
|
|
||||||
|
@ -61,11 +61,6 @@ version = "5.1.2"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = []
|
features = []
|
||||||
|
|
||||||
[dependencies.arraydeque]
|
|
||||||
version = "0.4.5"
|
|
||||||
default-features = false
|
|
||||||
features = [ "use_generic_array" ]
|
|
||||||
|
|
||||||
[dependencies.simple_logger]
|
[dependencies.simple_logger]
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
27
src/parse.rs
27
src/parse.rs
|
@ -31,7 +31,8 @@ use core::convert::TryInto;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
pub(crate) fn parse_tls_repr(bytes: &[u8]) -> IResult<&[u8], TlsRepr> {
|
// Return handshake/payload slice and TLS Record
|
||||||
|
pub(crate) fn parse_tls_repr(bytes: &[u8]) -> IResult<&[u8], (&[u8], TlsRepr)> {
|
||||||
let content_type = take(1_usize);
|
let content_type = take(1_usize);
|
||||||
let version = take(2_usize);
|
let version = take(2_usize);
|
||||||
let length = take(2_usize);
|
let length = take(2_usize);
|
||||||
|
@ -51,6 +52,9 @@ pub(crate) fn parse_tls_repr(bytes: &[u8]) -> IResult<&[u8], TlsRepr> {
|
||||||
handshake: None,
|
handshake: None,
|
||||||
};
|
};
|
||||||
let (rest, bytes) = take(repr.length)(rest)?;
|
let (rest, bytes) = take(repr.length)(rest)?;
|
||||||
|
|
||||||
|
// Store a copy of the TLS Handshake slice to return
|
||||||
|
let repr_slice_clone = bytes;
|
||||||
{
|
{
|
||||||
use crate::tls_packet::TlsContentType::*;
|
use crate::tls_packet::TlsContentType::*;
|
||||||
match repr.content_type {
|
match repr.content_type {
|
||||||
|
@ -68,7 +72,7 @@ pub(crate) fn parse_tls_repr(bytes: &[u8]) -> IResult<&[u8], TlsRepr> {
|
||||||
_ => todo!()
|
_ => todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((rest, repr))
|
Ok((rest, (repr_slice_clone, repr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert TlsInnerPlainText in RFC 8446 into Handshake
|
// Convert TlsInnerPlainText in RFC 8446 into Handshake
|
||||||
|
@ -76,9 +80,9 @@ pub(crate) fn parse_tls_repr(bytes: &[u8]) -> IResult<&[u8], TlsRepr> {
|
||||||
// 1. Handshake can coalesced into a larger TLS record
|
// 1. Handshake can coalesced into a larger TLS record
|
||||||
// 2. Content type and zero paddings at the end
|
// 2. Content type and zero paddings at the end
|
||||||
// Return handshake slice for hashing
|
// Return handshake slice for hashing
|
||||||
pub(crate) fn parse_inner_plaintext_for_handshake(bytes: &[u8]) -> IResult<&[u8], (&[u8], Vec<HandshakeRepr>)> {
|
pub(crate) fn parse_inner_plaintext_for_handshake(bytes: &[u8]) -> IResult<&[u8], Vec<(&[u8], HandshakeRepr)>> {
|
||||||
let mut remaining_bytes = bytes;
|
let mut remaining_bytes = bytes;
|
||||||
let mut handshake_vec: Vec<HandshakeRepr> = Vec::new();
|
let mut handshake_vec: Vec<(&[u8], HandshakeRepr)> = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Perform check on the number of remaining bytes
|
// Perform check on the number of remaining bytes
|
||||||
|
@ -97,20 +101,19 @@ pub(crate) fn parse_inner_plaintext_for_handshake(bytes: &[u8]) -> IResult<&[u8]
|
||||||
)(remaining_bytes)?;
|
)(remaining_bytes)?;
|
||||||
return Ok((
|
return Ok((
|
||||||
&[],
|
&[],
|
||||||
(
|
// // A concatenation of all handshakes received
|
||||||
// A concatenation of all handshakes received
|
// // The remaining content_type byte and zero paddings are stripped
|
||||||
// The remaining content_type byte and zero paddings are stripped
|
// &bytes[
|
||||||
&bytes[
|
// ..(bytes.len()-remaining_bytes.len())
|
||||||
..(bytes.len()-remaining_bytes.len())
|
// ],
|
||||||
],
|
|
||||||
handshake_vec
|
handshake_vec
|
||||||
)
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (rem, handshake_repr) = parse_handshake(remaining_bytes)?;
|
let (rem, handshake_repr) = parse_handshake(remaining_bytes)?;
|
||||||
|
let handshake_slice = &remaining_bytes[..(remaining_bytes.len()-rem.len())];
|
||||||
remaining_bytes = rem;
|
remaining_bytes = rem;
|
||||||
handshake_vec.push(handshake_repr);
|
handshake_vec.push((handshake_slice, handshake_repr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1121,6 +1121,7 @@ impl Session {
|
||||||
|
|
||||||
// TODO: Merge decryption methods
|
// TODO: Merge decryption methods
|
||||||
// Take control of the entire decryption, manually invoke detached decryption
|
// Take control of the entire decryption, manually invoke detached decryption
|
||||||
|
// TODO: Bad naming, it should say the KEY of application data
|
||||||
pub(crate) fn decrypt_application_data_in_place(
|
pub(crate) fn decrypt_application_data_in_place(
|
||||||
&self,
|
&self,
|
||||||
associated_data: &[u8],
|
associated_data: &[u8],
|
||||||
|
@ -1145,6 +1146,7 @@ impl Session {
|
||||||
let mut processed_nonce: [u8; 12] = [0; 12];
|
let mut processed_nonce: [u8; 12] = [0; 12];
|
||||||
NetworkEndian::write_uint128(&mut processed_nonce, nonce ^ clipped_seq_num, 12);
|
NetworkEndian::write_uint128(&mut processed_nonce, nonce ^ clipped_seq_num, 12);
|
||||||
|
|
||||||
|
// Duplicate authentication tag
|
||||||
let buffer_size = buffer.len();
|
let buffer_size = buffer.len();
|
||||||
let tag = GenericArray::clone_from_slice(&buffer[(buffer_size-16)..]);
|
let tag = GenericArray::clone_from_slice(&buffer[(buffer_size-16)..]);
|
||||||
|
|
||||||
|
@ -1156,6 +1158,7 @@ impl Session {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decryption using handshake keys
|
||||||
pub(crate) fn decrypt_in_place(
|
pub(crate) fn decrypt_in_place(
|
||||||
&self,
|
&self,
|
||||||
associated_data: &[u8],
|
associated_data: &[u8],
|
||||||
|
@ -1187,6 +1190,44 @@ impl Session {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A veriant for handshake decryption in-place and detached
|
||||||
|
// Caller need to manually discard the authentication bytes
|
||||||
|
pub(crate) fn decrypt_in_place_detached(
|
||||||
|
&self,
|
||||||
|
associated_data: &[u8],
|
||||||
|
buffer: &mut [u8]
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let (seq_num, nonce, cipher): (u64, &Vec<u8, U12>, &Cipher) = match self.role {
|
||||||
|
TlsRole::Server => {(
|
||||||
|
self.client_sequence_number,
|
||||||
|
self.client_handshake_nonce.as_ref().unwrap(),
|
||||||
|
self.client_handshake_cipher.as_ref().unwrap()
|
||||||
|
)},
|
||||||
|
TlsRole::Client => {(
|
||||||
|
self.server_sequence_number,
|
||||||
|
self.server_handshake_nonce.as_ref().unwrap(),
|
||||||
|
self.server_handshake_cipher.as_ref().unwrap()
|
||||||
|
)},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate XOR'ed nonce
|
||||||
|
let nonce: u128 = NetworkEndian::read_uint128(nonce, 12);
|
||||||
|
let clipped_seq_num: u128 = seq_num.into();
|
||||||
|
let mut processed_nonce: [u8; 12] = [0; 12];
|
||||||
|
NetworkEndian::write_uint128(&mut processed_nonce, nonce ^ clipped_seq_num, 12);
|
||||||
|
|
||||||
|
// Duplicate authentication tag
|
||||||
|
let buffer_size = buffer.len();
|
||||||
|
let tag = GenericArray::clone_from_slice(&buffer[(buffer_size-16)..]);
|
||||||
|
|
||||||
|
cipher.decrypt_in_place_detached(
|
||||||
|
&GenericArray::from_slice(&processed_nonce),
|
||||||
|
associated_data,
|
||||||
|
&mut buffer[..(buffer_size-16)],
|
||||||
|
&tag
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn increment_client_sequence_number(&mut self) {
|
pub(crate) fn increment_client_sequence_number(&mut self) {
|
||||||
self.client_sequence_number += 1;
|
self.client_sequence_number += 1;
|
||||||
}
|
}
|
||||||
|
|
228
src/tls.rs
228
src/tls.rs
|
@ -23,6 +23,7 @@ use aes_gcm::AeadInPlace;
|
||||||
|
|
||||||
use nom::bytes::complete::take;
|
use nom::bytes::complete::take;
|
||||||
use nom::error::ErrorKind;
|
use nom::error::ErrorKind;
|
||||||
|
use nom::combinator::complete;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use heapless::Vec as HeaplessVec;
|
use heapless::Vec as HeaplessVec;
|
||||||
|
@ -202,6 +203,7 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
|
|
||||||
// Read for TLS packet
|
// Read for TLS packet
|
||||||
// Proposition: Decouple all data from TLS record layer before processing
|
// Proposition: Decouple all data from TLS record layer before processing
|
||||||
|
// Recouple a brand new TLS record wrapper
|
||||||
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)?;
|
||||||
|
|
||||||
|
@ -209,15 +211,84 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
// 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_slice, mut repr) = tls_repr_vec.remove(0);
|
||||||
self.process(repr)?;
|
// TODO:
|
||||||
|
// Check TLS content type
|
||||||
|
// If application data, decrypt before process.
|
||||||
|
// If there are multiple handshakes within a record,
|
||||||
|
// give each of them a unique TLS record wrapper and process
|
||||||
|
// If a pure application data is found, sliently ignore
|
||||||
|
// Otherwise process directly
|
||||||
|
log::info!("Record type: {:?}", repr.content_type);
|
||||||
|
if repr.content_type == TlsContentType::ApplicationData {
|
||||||
|
log::info!("Found application data");
|
||||||
|
// Take the payload out of TLS Record and decrypt
|
||||||
|
let mut app_data = repr.payload.take().unwrap();
|
||||||
|
let mut associated_data = [0; 5];
|
||||||
|
associated_data[0] = repr.content_type.into();
|
||||||
|
NetworkEndian::write_u16(
|
||||||
|
&mut associated_data[1..3],
|
||||||
|
repr.version.into()
|
||||||
|
);
|
||||||
|
NetworkEndian::write_u16(
|
||||||
|
&mut associated_data[3..5],
|
||||||
|
repr.length
|
||||||
|
);
|
||||||
|
{
|
||||||
|
let mut session = self.session.borrow_mut();
|
||||||
|
session.decrypt_in_place_detached(
|
||||||
|
&associated_data,
|
||||||
|
&mut app_data
|
||||||
|
).unwrap();
|
||||||
|
// log::info!("Decypted data: {:?}", app_data);
|
||||||
|
session.increment_server_sequence_number();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard last 16 bytes (auth tag)
|
||||||
|
let inner_plaintext = &app_data[..app_data.len()-16];
|
||||||
|
let (inner_content_type, _) = get_content_type_inner_plaintext(
|
||||||
|
inner_plaintext
|
||||||
|
);
|
||||||
|
if inner_content_type != TlsContentType::Handshake {
|
||||||
|
// Silently ignore non-handshakes
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let (_, mut inner_handshakes) = complete(
|
||||||
|
parse_inner_plaintext_for_handshake
|
||||||
|
)(inner_plaintext).unwrap();
|
||||||
|
|
||||||
|
// Sequentially process all handshakes
|
||||||
|
let num_of_handshakes = inner_handshakes.len();
|
||||||
|
for _ in 0..num_of_handshakes {
|
||||||
|
let (handshake_slice, handshake_repr) = inner_handshakes.remove(0);
|
||||||
|
self.process(
|
||||||
|
handshake_slice,
|
||||||
|
TlsRepr {
|
||||||
|
content_type: TlsContentType::Handshake,
|
||||||
|
version: repr.version,
|
||||||
|
length: u16::try_from(handshake_repr.length).unwrap() + 4,
|
||||||
|
payload: None,
|
||||||
|
handshake: Some(handshake_repr)
|
||||||
|
}
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
else {
|
||||||
|
self.process(repr_slice, repr)?;
|
||||||
|
log::info!("Processed record");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<()> {
|
// The slice should ONLY include handshake overhead
|
||||||
|
// i.e. No 5 bytes of TLS Record
|
||||||
|
// YES 4 bytes of HandshakeRepr, everything within the same handshake
|
||||||
|
fn process(&self, handshake_slice: &[u8], 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
|
||||||
|
@ -226,8 +297,10 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
// 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();
|
log::info!("Change Cipher Spec");
|
||||||
|
let mut session = self.session.try_borrow_mut().expect("Cannot borrow mut");
|
||||||
session.receive_change_cipher_spec();
|
session.receive_change_cipher_spec();
|
||||||
|
log::info!("Changed Cipher Spec");
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,34 +430,9 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
|
|
||||||
// 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
|
|
||||||
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();
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let parse_result = parse_inner_plaintext_for_handshake(&payload);
|
|
||||||
let (_, (handshake_slice, mut handshake_vec)) =
|
|
||||||
parse_result.map_err(|_| Error::Unrecognized)?;
|
|
||||||
|
|
||||||
// Verify that it is indeed an EE
|
// Verify that it is indeed an EE
|
||||||
let might_be_ee = handshake_vec.remove(0);
|
// let might_be_ee = handshake_vec.remove(0);
|
||||||
|
let might_be_ee = repr.handshake.take().unwrap();
|
||||||
if might_be_ee.get_msg_type() != HandshakeType::EncryptedExtensions {
|
if might_be_ee.get_msg_type() != HandshakeType::EncryptedExtensions {
|
||||||
// Process the other handshakes in "handshake_vec"
|
// Process the other handshakes in "handshake_vec"
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -407,47 +455,15 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
&ee_slice
|
&ee_slice
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Handle in WAIT_CERT_CR if there are still unprocessed handshakes
|
log::info!("Received EE");
|
||||||
// Ideas: 1. Split off WAIT_CERT_CR handling into a separate function
|
|
||||||
// so WAIT_EE branch can jsut call WAIT_CERT_CR branch
|
|
||||||
// if there are extra handshake unprocessed
|
|
||||||
// 2. Merge state dependent listeners into 1 branch, execute conditionally
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 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
|
|
||||||
// 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 CERT
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the certificate from TLS payload
|
|
||||||
let parse_result = parse_inner_plaintext_for_handshake(&payload);
|
|
||||||
let (_, (handshake_slice, mut handshake_vec)) = parse_result
|
|
||||||
.map_err(|_| Error::Unrecognized)?;
|
|
||||||
|
|
||||||
// Verify that it is indeed an Certificate
|
// Verify that it is indeed an Certificate
|
||||||
let might_be_cert = handshake_vec.remove(0);
|
// let might_be_cert = handshake_vec.remove(0);
|
||||||
|
let might_be_cert = repr.handshake.take().unwrap();
|
||||||
if might_be_cert.get_msg_type() != HandshakeType::Certificate {
|
if might_be_cert.get_msg_type() != HandshakeType::Certificate {
|
||||||
// Process the other handshakes in "handshake_vec"
|
// Process the other handshakes in "handshake_vec"
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -476,41 +492,15 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
&cert_slice,
|
&cert_slice,
|
||||||
cert.return_rsa_public_key().unwrap()
|
cert.return_rsa_public_key().unwrap()
|
||||||
);
|
);
|
||||||
|
log::info!("Received WAIT_CERT_CR");
|
||||||
},
|
},
|
||||||
|
|
||||||
// In this stage, server will eventually send a CertificateVerify
|
// In this stage, server will eventually send a CertificateVerify
|
||||||
// Verify that the signature is indeed correct
|
// Verify that the signature is indeed correct
|
||||||
TlsState::WAIT_CV => {
|
TlsState::WAIT_CV => {
|
||||||
// CertificateVerify 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 CV
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the certificate from TLS payload
|
|
||||||
let parse_result = parse_inner_plaintext_for_handshake(&payload);
|
|
||||||
let (_, (handshake_slice, mut handshake_vec)) = parse_result
|
|
||||||
.map_err(|_| Error::Unrecognized)?;
|
|
||||||
|
|
||||||
// Ensure that it is CertificateVerify
|
// Ensure that it is CertificateVerify
|
||||||
let might_be_cert_verify = handshake_vec.remove(0);
|
// let might_be_cert_verify = handshake_vec.remove(0);
|
||||||
|
let might_be_cert_verify = repr.handshake.take().unwrap();
|
||||||
if might_be_cert_verify.get_msg_type() != HandshakeType::CertificateVerify {
|
if might_be_cert_verify.get_msg_type() != HandshakeType::CertificateVerify {
|
||||||
// Process the other handshakes in "handshake_vec"
|
// Process the other handshakes in "handshake_vec"
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -532,40 +522,14 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
sig_alg,
|
sig_alg,
|
||||||
signature
|
signature
|
||||||
);
|
);
|
||||||
|
log::info!("Received CV");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Client will receive a Finished handshake from server
|
// Client will receive a Finished handshake from server
|
||||||
TlsState::WAIT_FINISHED => {
|
TlsState::WAIT_FINISHED => {
|
||||||
// Finished 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 Finished
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the TLS inner ciphertext as a Finished handshake
|
|
||||||
let parse_result = parse_inner_plaintext_for_handshake(&payload);
|
|
||||||
let (_, (handshake_slice, mut handshake_vec)) = parse_result
|
|
||||||
.map_err(|_| Error::Unrecognized)?;
|
|
||||||
|
|
||||||
// Ensure that it is Finished
|
// Ensure that it is Finished
|
||||||
let might_be_server_finished = handshake_vec.remove(0);
|
// let might_be_server_finished = handshake_vec.remove(0);
|
||||||
|
let might_be_server_finished = repr.handshake.take().unwrap();
|
||||||
if might_be_server_finished.get_msg_type() != HandshakeType::Finished {
|
if might_be_server_finished.get_msg_type() != HandshakeType::Finished {
|
||||||
// Process the other handshakes in "handshake_vec"
|
// Process the other handshakes in "handshake_vec"
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -586,15 +550,11 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
server_finished_slice,
|
server_finished_slice,
|
||||||
might_be_server_finished.get_verify_data().unwrap()
|
might_be_server_finished.get_verify_data().unwrap()
|
||||||
);
|
);
|
||||||
|
log::info!("Received server FIN");
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// A TLS Record was received and processed and verified
|
|
||||||
// Increment sequence number
|
|
||||||
self.session.borrow_mut().increment_server_sequence_number();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,18 +653,20 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||||
// 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<(&[u8], 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<(&[u8], 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_slice, repr))) => {
|
||||||
vec.push(repr);
|
vec.push(
|
||||||
|
(repr_slice, repr)
|
||||||
|
);
|
||||||
if rest.len() == 0 {
|
if rest.len() == 0 {
|
||||||
return Ok(vec);
|
return Ok(vec);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue