2020-10-04 22:22:29 +08:00
|
|
|
use smoltcp::socket::TcpSocket;
|
|
|
|
use smoltcp::socket::TcpState;
|
|
|
|
use smoltcp::socket::Socket;
|
|
|
|
use smoltcp::socket::AnySocket;
|
|
|
|
use smoltcp::socket::SocketRef;
|
|
|
|
use smoltcp::socket::SocketHandle;
|
|
|
|
use smoltcp::socket::SocketSet;
|
|
|
|
use smoltcp::socket::TcpSocketBuffer;
|
|
|
|
use smoltcp::wire::Ipv4Address;
|
|
|
|
use smoltcp::wire::IpEndpoint;
|
|
|
|
use smoltcp::Result;
|
|
|
|
use smoltcp::Error;
|
2020-10-11 23:41:02 +08:00
|
|
|
use smoltcp::iface::EthernetInterface;
|
|
|
|
use smoltcp::time::Instant;
|
|
|
|
use smoltcp::phy::Device;
|
2020-10-04 22:22:29 +08:00
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
|
2020-10-14 17:37:45 +08:00
|
|
|
use generic_array::GenericArray;
|
2020-10-04 22:22:29 +08:00
|
|
|
|
|
|
|
use core::convert::TryInto;
|
|
|
|
use core::convert::TryFrom;
|
2020-10-14 23:38:24 +08:00
|
|
|
use core::cell::RefCell;
|
2020-10-04 22:22:29 +08:00
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
use rand_core::{RngCore, CryptoRng};
|
2020-10-14 17:37:45 +08:00
|
|
|
use p256::{EncodedPoint, AffinePoint, ecdh::EphemeralSecret, ecdh::SharedSecret};
|
2020-10-15 17:29:42 +08:00
|
|
|
use aes_gcm::{Aes128Gcm, Aes256Gcm};
|
|
|
|
use chacha20poly1305::{ChaCha20Poly1305, Key};
|
|
|
|
use ccm::{Ccm, consts::*};
|
|
|
|
use aes_gcm::aes::Aes128;
|
|
|
|
use aes_gcm::{AeadInPlace, NewAead};
|
2020-10-16 17:38:29 +08:00
|
|
|
use sha2::{Sha256, Sha384, Sha512, Digest};
|
2020-10-11 13:46:24 +08:00
|
|
|
|
2020-10-11 23:41:02 +08:00
|
|
|
use alloc::vec::{ self, Vec };
|
|
|
|
|
2020-10-15 17:29:42 +08:00
|
|
|
use crate::Error as TlsError;
|
2020-10-04 22:22:29 +08:00
|
|
|
use crate::tls_packet::*;
|
2020-10-11 23:41:02 +08:00
|
|
|
use crate::parse::parse_tls_repr;
|
2020-10-16 17:38:29 +08:00
|
|
|
use crate::cipher_suite::CipherSuite;
|
2020-10-15 22:40:36 +08:00
|
|
|
use crate::buffer::TlsBuffer;
|
2020-10-11 13:46:24 +08:00
|
|
|
|
2020-10-04 22:22:29 +08:00
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
enum TlsState {
|
|
|
|
START,
|
|
|
|
WAIT_SH,
|
|
|
|
WAIT_EE,
|
|
|
|
WAIT_CERT_CR,
|
|
|
|
WAIT_CERT,
|
|
|
|
WAIT_CV,
|
|
|
|
WAIT_FINISHED,
|
|
|
|
CONNECTED,
|
|
|
|
}
|
|
|
|
|
2020-10-15 17:29:42 +08:00
|
|
|
// TODO: Group up all session_specific parameters into a separate structure
|
2020-10-11 13:46:24 +08:00
|
|
|
pub struct TlsSocket<R: 'static + RngCore + CryptoRng>
|
2020-10-04 22:22:29 +08:00
|
|
|
{
|
2020-10-14 23:38:24 +08:00
|
|
|
state: RefCell<TlsState>,
|
2020-10-04 22:22:29 +08:00
|
|
|
tcp_handle: SocketHandle,
|
2020-10-11 13:46:24 +08:00
|
|
|
rng: R,
|
2020-10-14 23:38:24 +08:00
|
|
|
secret: RefCell<Option<EphemeralSecret>>, // Used enum Option to allow later init
|
|
|
|
session_id: RefCell<Option<[u8; 32]>>, // init session specific field later
|
2020-10-15 17:29:42 +08:00
|
|
|
received_change_cipher_spec: RefCell<Option<bool>>,
|
2020-10-16 17:38:29 +08:00
|
|
|
cipher: RefCell<Option<CipherSuite>>,
|
|
|
|
handshake_sha256: RefCell<Sha256>,
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
2020-10-11 13:46:24 +08:00
|
|
|
impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
2020-10-04 22:22:29 +08:00
|
|
|
pub fn new<'a, 'b, 'c>(
|
|
|
|
sockets: &mut SocketSet<'a, 'b, 'c>,
|
|
|
|
rx_buffer: TcpSocketBuffer<'b>,
|
|
|
|
tx_buffer: TcpSocketBuffer<'b>,
|
2020-10-11 13:46:24 +08:00
|
|
|
rng: R,
|
2020-10-04 22:22:29 +08:00
|
|
|
) -> Self
|
|
|
|
where
|
|
|
|
'b: 'c,
|
|
|
|
{
|
|
|
|
let tcp_socket = TcpSocket::new(rx_buffer, tx_buffer);
|
|
|
|
let tcp_handle = sockets.add(tcp_socket);
|
|
|
|
TlsSocket {
|
2020-10-14 23:38:24 +08:00
|
|
|
state: RefCell::new(TlsState::START),
|
2020-10-04 22:22:29 +08:00
|
|
|
tcp_handle,
|
2020-10-11 13:46:24 +08:00
|
|
|
rng,
|
2020-10-14 23:38:24 +08:00
|
|
|
secret: RefCell::new(None),
|
|
|
|
session_id: RefCell::new(None),
|
2020-10-15 17:29:42 +08:00
|
|
|
received_change_cipher_spec: RefCell::new(None),
|
|
|
|
cipher: RefCell::new(None),
|
2020-10-16 17:38:29 +08:00
|
|
|
handshake_sha256: RefCell::new(Sha256::new()),
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2020-10-11 13:46:24 +08:00
|
|
|
if tcp_socket.state() == TcpState::Established {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
tcp_socket.connect(remote_endpoint, local_endpoint)
|
|
|
|
}
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
2020-10-11 23:41:02 +08:00
|
|
|
pub fn tls_connect<DeviceT>(
|
|
|
|
&mut self,
|
2020-10-13 21:08:20 +08:00
|
|
|
iface: &mut EthernetInterface<DeviceT>,
|
2020-10-11 23:41:02 +08:00
|
|
|
sockets: &mut SocketSet,
|
|
|
|
now: Instant
|
|
|
|
) -> Result<bool>
|
|
|
|
where
|
|
|
|
DeviceT: for<'d> Device<'d>
|
|
|
|
{
|
2020-10-04 22:22:29 +08:00
|
|
|
// Check tcp_socket connectivity
|
|
|
|
{
|
2020-10-11 13:46:24 +08:00
|
|
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
|
|
|
tcp_socket.set_keep_alive(Some(smoltcp::time::Duration::from_millis(1000)));
|
2020-10-04 22:22:29 +08:00
|
|
|
if tcp_socket.state() != TcpState::Established {
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-14 17:37:45 +08:00
|
|
|
// Handle TLS handshake through TLS states
|
2020-10-14 23:38:24 +08:00
|
|
|
let state = self.state.clone().into_inner();
|
|
|
|
match state {
|
2020-10-14 17:37:45 +08:00
|
|
|
// 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);
|
2020-10-16 17:38:29 +08:00
|
|
|
|
|
|
|
// Update hash function with client hello handshake
|
|
|
|
let mut array = [0; 2048];
|
|
|
|
let mut buffer = TlsBuffer::new(&mut array);
|
|
|
|
buffer.enqueue_tls_repr(repr)?;
|
|
|
|
let slice: &[u8] = buffer.into();
|
|
|
|
|
|
|
|
// Update hash by handshake
|
|
|
|
// Update with entire packet except the record layer
|
|
|
|
{
|
|
|
|
self.handshake_sha256.borrow_mut().update(&slice[5..]);
|
|
|
|
}
|
|
|
|
self.send_tls_slice(sockets, slice)?;
|
2020-10-14 17:37:45 +08:00
|
|
|
|
|
|
|
// Store session settings, i.e. secret, session_id
|
2020-10-14 23:38:24 +08:00
|
|
|
self.secret.replace(Some(ecdh_secret));
|
|
|
|
self.session_id.replace(Some(session_id));
|
2020-10-15 17:29:42 +08:00
|
|
|
self.received_change_cipher_spec.replace(Some(false));
|
2020-10-14 17:37:45 +08:00
|
|
|
|
|
|
|
// Update the TLS state
|
2020-10-14 23:38:24 +08:00
|
|
|
self.state.replace(TlsState::WAIT_SH);
|
2020-10-14 17:37:45 +08:00
|
|
|
},
|
|
|
|
// 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 normall send SH alongside EE
|
|
|
|
// TLS client should jump from WAIT_SH directly to WAIT_CERT_CR directly.
|
|
|
|
TlsState::WAIT_EE => {},
|
|
|
|
_ => todo!()
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
2020-10-14 17:37:45 +08:00
|
|
|
|
|
|
|
// Poll the network interface
|
|
|
|
iface.poll(sockets, now);
|
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
// Read for TLS packet
|
|
|
|
let mut array: [u8; 2048] = [0; 2048];
|
2020-10-16 17:38:29 +08:00
|
|
|
let mut tls_repr_vec = self.recv_tls_repr(sockets, &mut array)?;
|
2020-10-14 17:37:45 +08:00
|
|
|
|
2020-10-16 17:38:29 +08:00
|
|
|
// 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);
|
2020-10-14 23:38:24 +08:00
|
|
|
self.process(repr)?;
|
|
|
|
}
|
2020-10-14 17:37:45 +08:00
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
Ok(self.state.clone().into_inner() == TlsState::CONNECTED)
|
|
|
|
}
|
2020-10-14 17:37:45 +08:00
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
// Process TLS ingress during handshake
|
2020-10-16 17:38:29 +08:00
|
|
|
fn process(&self, repr: TlsRepr) -> Result<()> {
|
2020-10-14 23:38:24 +08:00
|
|
|
let state = self.state.clone().into_inner();
|
2020-10-15 17:29:42 +08:00
|
|
|
|
|
|
|
// 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`
|
|
|
|
if repr.is_change_cipher_spec() {
|
|
|
|
self.received_change_cipher_spec.replace(Some(true));
|
|
|
|
return Ok(())
|
|
|
|
}
|
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
match 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!()
|
|
|
|
}
|
2020-10-14 17:37:45 +08:00
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
// 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 ^)
|
|
|
|
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 session_id_echo
|
|
|
|
// The socket should have a session_id after moving from START state
|
|
|
|
if self.session_id.clone().into_inner().unwrap() != server_hello.session_id_echo {
|
|
|
|
// Abort communication
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
// Store the cipher suite
|
2020-10-15 17:29:42 +08:00
|
|
|
let selected_cipher = server_hello.cipher_suite;
|
2020-10-14 23:38:24 +08:00
|
|
|
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
|
2020-10-14 17:37:45 +08:00
|
|
|
todo!()
|
|
|
|
}
|
2020-10-14 23:38:24 +08:00
|
|
|
} else {
|
|
|
|
// Abort for illegal extension
|
|
|
|
todo!()
|
2020-10-14 17:37:45 +08:00
|
|
|
}
|
2020-10-14 23:38:24 +08:00
|
|
|
}
|
2020-10-14 17:37:45 +08:00
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
if extension.extension_type == ExtensionType::KeyShare {
|
|
|
|
if let ExtensionData::KeyShareEntry(
|
|
|
|
KeyShareEntryContent::KeyShareServerHello {
|
|
|
|
server_share
|
2020-10-14 17:37:45 +08:00
|
|
|
}
|
2020-10-14 23:38:24 +08:00
|
|
|
) = &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
|
2020-10-15 17:29:42 +08:00
|
|
|
// It is surely from secp256r1, no other groups are permitted
|
2020-10-14 23:38:24 +08:00
|
|
|
// Convert untagged bytes into encoded point on p256 eliptic curve
|
|
|
|
// Slice the first byte out of the bytes
|
|
|
|
let server_public = EncodedPoint::from_untagged_bytes(
|
|
|
|
GenericArray::from_slice(&server_share.key_exchange[1..])
|
|
|
|
);
|
|
|
|
// TODO: Handle improper shared key
|
2020-10-15 17:29:42 +08:00
|
|
|
// Right now is causes a panic, only socket abort is needed
|
|
|
|
let secret = self.secret.replace(None);
|
|
|
|
let shared = secret.unwrap()
|
|
|
|
.diffie_hellman(&server_public)
|
|
|
|
.expect("Unsupported key");
|
2020-10-16 17:38:29 +08:00
|
|
|
// let cipher = match selected_cipher {
|
|
|
|
// CipherSuite::TLS_AES_128_GCM_SHA256 => {
|
|
|
|
// Cipher::TLS_AES_128_GCM_SHA256(
|
|
|
|
// todo!()
|
|
|
|
// )
|
|
|
|
// },
|
|
|
|
// CipherSuite::TLS_AES_256_GCM_SHA384 => {
|
|
|
|
// Cipher::TLS_AES_256_GCM_SHA384(
|
|
|
|
// Aes256Gcm::new(shared.as_bytes())
|
|
|
|
// )
|
|
|
|
// },
|
|
|
|
// CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => {
|
|
|
|
// Cipher::TLS_CHACHA20_POLY1305_SHA256(
|
|
|
|
// ChaCha20Poly1305::new(shared.as_bytes())
|
|
|
|
// )
|
|
|
|
// },
|
|
|
|
// CipherSuite::TLS_AES_128_CCM_SHA256 => {
|
|
|
|
// Cipher::TLS_AES_128_CCM_SHA256(
|
|
|
|
// todo!()
|
|
|
|
// )
|
|
|
|
// },
|
|
|
|
// // CCM_8 is not supported
|
|
|
|
// // TODO: Abort communication
|
|
|
|
// CipherSuite::TLS_AES_128_CCM_8_SHA256 => {
|
|
|
|
// todo!()
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
// self.cipher.replace(Some(cipher));
|
2020-10-14 17:37:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
} else {
|
|
|
|
// Handle invalid TLS packet
|
|
|
|
todo!()
|
2020-10-14 17:37:45 +08:00
|
|
|
}
|
2020-10-14 23:38:24 +08:00
|
|
|
|
2020-10-16 17:38:29 +08:00
|
|
|
// This is indeed a desirable ServerHello TLS repr
|
|
|
|
// Reprocess ServerHello into a slice
|
|
|
|
// Update SHA256 hasher with the slice
|
|
|
|
let mut array = [0; 2048];
|
|
|
|
let mut buffer = TlsBuffer::new(&mut array);
|
|
|
|
buffer.enqueue_tls_repr(repr);
|
|
|
|
let slice: &[u8] = buffer.into();
|
|
|
|
{
|
|
|
|
self.handshake_sha256
|
|
|
|
.borrow_mut()
|
|
|
|
.update(&slice[5..]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update TLS session state
|
|
|
|
self.state.replace(TlsState::WAIT_EE);
|
2020-10-14 17:37:45 +08:00
|
|
|
}
|
2020-10-15 17:29:42 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
// Expect encrypted extensions after receiving SH
|
|
|
|
TlsState::WAIT_EE => {
|
|
|
|
// ExcepytedExtensions are disguised as ApplicationData
|
|
|
|
// Pull out the `payload` from TlsRepr, decrypt as EE
|
|
|
|
},
|
|
|
|
|
2020-10-14 17:37:45 +08:00
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
|
2020-10-14 23:38:24 +08:00
|
|
|
Ok(())
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Generic inner send method, through TCP socket
|
2020-10-14 17:37:45 +08:00
|
|
|
fn send_tls_repr(&self, sockets: &mut SocketSet, tls_repr: TlsRepr) -> Result<()> {
|
2020-10-04 22:22:29 +08:00
|
|
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
2020-10-14 17:37:45 +08:00
|
|
|
if !tcp_socket.can_send() {
|
|
|
|
return Err(Error::Illegal);
|
|
|
|
}
|
2020-10-04 22:22:29 +08:00
|
|
|
let mut array = [0; 2048];
|
|
|
|
let mut buffer = TlsBuffer::new(&mut array);
|
|
|
|
buffer.enqueue_tls_repr(tls_repr)?;
|
2020-10-15 22:40:36 +08:00
|
|
|
let buffer_size = buffer.get_size();
|
2020-10-04 22:22:29 +08:00
|
|
|
tcp_socket.send_slice(buffer.into())
|
|
|
|
.and_then(
|
2020-10-15 22:40:36 +08:00
|
|
|
|size| if size == buffer_size {
|
2020-10-04 22:22:29 +08:00
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(Error::Truncated)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-10-16 17:38:29 +08:00
|
|
|
// Generic inner send method for buffer IO, through TCP socket
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-10-04 22:22:29 +08:00
|
|
|
// Generic inner recv method, through TCP socket
|
2020-10-14 17:37:45 +08:00
|
|
|
// A TCP packet can contain multiple TLS segments
|
|
|
|
fn recv_tls_repr<'a>(&'a self, sockets: &mut SocketSet, byte_array: &'a mut [u8]) -> Result<Vec::<TlsRepr>> {
|
2020-10-04 22:22:29 +08:00
|
|
|
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
|
2020-10-14 17:37:45 +08:00
|
|
|
if !tcp_socket.can_recv() {
|
|
|
|
return Ok((Vec::new()));
|
|
|
|
}
|
|
|
|
|
|
|
|
let array_size = tcp_socket.recv_slice(byte_array)?;
|
2020-10-11 23:41:02 +08:00
|
|
|
let mut vec: Vec<TlsRepr> = Vec::new();
|
|
|
|
|
2020-10-14 17:37:45 +08:00
|
|
|
let mut bytes: &[u8] = &byte_array[..array_size];
|
2020-10-11 23:41:02 +08:00
|
|
|
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),
|
|
|
|
};
|
|
|
|
}
|
2020-10-04 22:22:29 +08:00
|
|
|
}
|
|
|
|
}
|