Compare commits
No commits in common. "0c6807f59315e040244b3400c3eae691540eef6b" and "552d21a1b398ce775857f9fd8e060d3a297152d2" have entirely different histories.
0c6807f593
...
552d21a1b3
|
@ -58,7 +58,6 @@ features = [ "u64_backend" ]
|
|||
# Fetch from master, for "no_std" + "alloc" combination
|
||||
[dependencies.rsa]
|
||||
git = "https://github.com/RustCrypto/RSA.git"
|
||||
rev = "c879eb2"
|
||||
default-features = false
|
||||
features = [ "alloc" ]
|
||||
|
||||
|
@ -94,14 +93,13 @@ optional = true
|
|||
version = "0.3.1"
|
||||
optional = true
|
||||
|
||||
# Support `TcpStack` from old version of embedded_nal interface
|
||||
# Support old version of embedded_nal interface only
|
||||
# It is to operate with crates such as MiniMQ, which still depends on version 0.1.0
|
||||
[dependencies.embedded-nal-tcp-stack]
|
||||
package = "embedded-nal"
|
||||
[dependencies.embedded-nal]
|
||||
version = "0.1.0"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
std = [ "rand", "hex-literal", "simple_logger", "rsa/default" ]
|
||||
nal_tcp_stack = [ "embedded-nal-tcp-stack" ]
|
||||
nal_stack = [ "embedded-nal" ]
|
||||
|
|
|
@ -193,7 +193,6 @@ impl<'a> TlsBuffer<'a> {
|
|||
|
||||
macro_rules! export_byte_order_fn {
|
||||
($($write_fn_name: ident, $read_fn_name: ident, $data_type: ty, $data_size: literal),+) => {
|
||||
#[allow(dead_code)]
|
||||
impl<'a> TlsBuffer<'a> {
|
||||
$(
|
||||
pub(crate) fn $write_fn_name(&mut self, data: $data_type) -> Result<()> {
|
||||
|
|
|
@ -13,7 +13,7 @@ pub mod fake_rng;
|
|||
pub mod oid;
|
||||
pub mod set;
|
||||
|
||||
#[cfg(feature = "nal_tcp_stack")]
|
||||
#[cfg(feature = "nal_stack")]
|
||||
pub mod tcp_stack;
|
||||
|
||||
// TODO: Implement errors
|
||||
|
|
44
src/main.rs
44
src/main.rs
|
@ -19,7 +19,7 @@ use sha2::{ Digest, Sha256, Sha384, Sha512 };
|
|||
use std::vec::Vec;
|
||||
use hkdf::Hkdf;
|
||||
|
||||
// use rand::rngs::OsRng;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use chrono::prelude::*;
|
||||
|
||||
|
@ -57,30 +57,29 @@ impl TlsRng 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[..]);
|
||||
// let tcp_socket = smoltcp::socket::TcpSocket::new(rx_buffer, tx_buffer);
|
||||
// TlsSocket::new(
|
||||
// tcp_socket,
|
||||
// &mut RNG,
|
||||
// None
|
||||
// )
|
||||
// };
|
||||
let mut tls_socket = unsafe {
|
||||
let tx_buffer = TcpSocketBuffer::new(&mut tx_storage[..]);
|
||||
let rx_buffer = TcpSocketBuffer::new(&mut rx_storage[..]);
|
||||
let tcp_socket = smoltcp::socket::TcpSocket::new(rx_buffer, tx_buffer);
|
||||
TlsSocket::new(
|
||||
tcp_socket,
|
||||
&mut RNG,
|
||||
None
|
||||
)
|
||||
};
|
||||
|
||||
tls_socket.connect(
|
||||
// &mut sockets,
|
||||
(Ipv4Address::new(192, 168, 1, 125), 1883),
|
||||
49600
|
||||
).unwrap();
|
||||
|
||||
// tls_socket.connect(
|
||||
// // &mut sockets,
|
||||
// (Ipv4Address::new(192, 168, 1, 125), 1883),
|
||||
// 49600
|
||||
// ).unwrap();
|
||||
}
|
||||
/*
|
||||
// tls_socket.tls_connect(&mut sockets).unwrap();
|
||||
simple_logger::SimpleLogger::new().init().unwrap();
|
||||
|
||||
|
@ -361,4 +360,3 @@ const ED25519_SIGNATURE: [u8; 64] =
|
|||
hex_literal::hex!(
|
||||
"e9988fcc188fbe85a66929634badb47c5b765c3c6087a7e44b41efda1fdcd0baf67ded6159a5af6d396ca59439de8907160fc729a42ed50e69a3f54abe6dad0c"
|
||||
);
|
||||
*/
|
123
src/session.rs
123
src/session.rs
|
@ -2,7 +2,7 @@ use p256::{ EncodedPoint, ecdh::EphemeralSecret, ecdsa::signature::DigestVerifie
|
|||
use heapless::{ Vec, consts::* };
|
||||
use sha2::{ Digest, Sha256, Sha384, Sha512, digest::FixedOutput };
|
||||
use aes_gcm::{ Aes128Gcm, Aes256Gcm, aes::Aes128 };
|
||||
use aes_gcm::{ AeadInPlace, NewAead };
|
||||
use aes_gcm::{ AeadInPlace, NewAead, aead::Buffer };
|
||||
use chacha20poly1305::ChaCha20Poly1305;
|
||||
use ccm::Ccm;
|
||||
use hkdf::Hkdf;
|
||||
|
@ -1072,7 +1072,7 @@ impl<'a> Session<'a> {
|
|||
|
||||
fn find_application_keying_info(&mut self) {
|
||||
// Key calculation
|
||||
if let Ok(_sha256) = self.hash.get_sha256_clone() {
|
||||
if let Ok(sha256) = self.hash.get_sha256_clone() {
|
||||
// Derive application traffic secret, key, IV on client's side
|
||||
// 1. Derive secret from "Handshake Secret"
|
||||
let hkdf = Hkdf::<Sha256>::from_prk(
|
||||
|
@ -1243,7 +1243,7 @@ impl<'a> Session<'a> {
|
|||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
} else if let Ok(_sha384) = self.hash.get_sha384_clone() {
|
||||
} else if let Ok(sha384) = self.hash.get_sha384_clone() {
|
||||
// Derive application traffic secret, key, IV on client's side
|
||||
// 1. Derive secret from "Handshake Secret"
|
||||
let hkdf = Hkdf::<Sha384>::from_prk(
|
||||
|
@ -1418,6 +1418,10 @@ impl<'a> Session<'a> {
|
|||
self.need_send_alert
|
||||
}
|
||||
|
||||
pub(crate) fn has_completed_handshake(&self) -> bool {
|
||||
self.state == TlsState::CLIENT_CONNECTED
|
||||
}
|
||||
|
||||
pub(crate) fn receive_change_cipher_spec(&mut self) {
|
||||
self.changed_cipher_spec = true;
|
||||
}
|
||||
|
@ -1770,6 +1774,38 @@ impl<'a> Session<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn encrypt_in_place(
|
||||
&self,
|
||||
associated_data: &[u8],
|
||||
buffer: &mut dyn Buffer
|
||||
) -> Result<(), Error> {
|
||||
let (seq_num, nonce, cipher): (u64, &Vec<u8, U12>, &Cipher) = match self.role {
|
||||
TlsRole::Client => {(
|
||||
self.client_sequence_number,
|
||||
self.client_handshake_nonce.as_ref().unwrap(),
|
||||
self.client_handshake_cipher.as_ref().unwrap()
|
||||
)},
|
||||
TlsRole::Server => {(
|
||||
self.server_sequence_number,
|
||||
self.server_handshake_nonce.as_ref().unwrap(),
|
||||
self.server_handshake_cipher.as_ref().unwrap()
|
||||
)},
|
||||
TlsRole::Unknown => unreachable!()
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
cipher.encrypt_in_place(
|
||||
&GenericArray::from_slice(&processed_nonce),
|
||||
associated_data,
|
||||
buffer
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn encrypt_in_place_detached(
|
||||
&self,
|
||||
associated_data: &[u8],
|
||||
|
@ -1842,6 +1878,39 @@ impl<'a> Session<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
// Decryption using handshake keys
|
||||
pub(crate) fn decrypt_in_place(
|
||||
&self,
|
||||
associated_data: &[u8],
|
||||
buffer: &mut dyn Buffer
|
||||
) -> 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()
|
||||
)},
|
||||
TlsRole::Unknown => unreachable!()
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
cipher.decrypt_in_place(
|
||||
&GenericArray::from_slice(&processed_nonce),
|
||||
associated_data,
|
||||
buffer
|
||||
)
|
||||
}
|
||||
|
||||
// A veriant for handshake decryption in-place and detached
|
||||
// Caller need to manually discard the authentication bytes
|
||||
pub(crate) fn decrypt_in_place_detached(
|
||||
|
@ -1905,6 +1974,10 @@ impl<'a> Session<'a> {
|
|||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_session_role(&self) -> TlsRole {
|
||||
self.role
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
|
@ -1999,6 +2072,28 @@ pub(crate) enum Cipher {
|
|||
}
|
||||
|
||||
impl Cipher {
|
||||
pub(crate) fn encrypt_in_place(
|
||||
&self,
|
||||
nonce: &GenericArray<u8, U12>,
|
||||
associated_data: &[u8],
|
||||
buffer: &mut dyn Buffer
|
||||
) -> Result<(), Error> {
|
||||
match self {
|
||||
Cipher::Aes128Gcm { aes128gcm } => {
|
||||
aes128gcm.encrypt_in_place(nonce, associated_data, buffer)
|
||||
},
|
||||
Cipher::Aes256Gcm { aes256gcm } => {
|
||||
aes256gcm.encrypt_in_place(nonce, associated_data, buffer)
|
||||
},
|
||||
Cipher::Chacha20poly1305 { chacha20poly1305 } => {
|
||||
chacha20poly1305.encrypt_in_place(nonce, associated_data, buffer)
|
||||
},
|
||||
Cipher::Ccm { ccm } => {
|
||||
ccm.encrypt_in_place(nonce, associated_data, buffer)
|
||||
}
|
||||
}.map_err(|_| Error::EncryptionError)
|
||||
}
|
||||
|
||||
pub(crate) fn encrypt_in_place_detached(
|
||||
&self,
|
||||
nonce: &GenericArray<u8, U12>,
|
||||
|
@ -2021,6 +2116,28 @@ impl Cipher {
|
|||
}.map_err(|_| Error::EncryptionError)
|
||||
}
|
||||
|
||||
pub(crate) fn decrypt_in_place(
|
||||
&self,
|
||||
nonce: &GenericArray<u8, U12>,
|
||||
associated_data: &[u8],
|
||||
buffer: &mut dyn Buffer
|
||||
) -> Result<(), Error> {
|
||||
match self {
|
||||
Cipher::Aes128Gcm { aes128gcm } => {
|
||||
aes128gcm.decrypt_in_place(nonce, associated_data, buffer)
|
||||
},
|
||||
Cipher::Aes256Gcm { aes256gcm } => {
|
||||
aes256gcm.decrypt_in_place(nonce, associated_data, buffer)
|
||||
},
|
||||
Cipher::Chacha20poly1305 { chacha20poly1305 } => {
|
||||
chacha20poly1305.decrypt_in_place(nonce, associated_data, buffer)
|
||||
},
|
||||
Cipher::Ccm { ccm } => {
|
||||
ccm.decrypt_in_place(nonce, associated_data, buffer)
|
||||
}
|
||||
}.map_err(|_| Error::DecryptionError)
|
||||
}
|
||||
|
||||
pub(crate) fn decrypt_in_place_detached(
|
||||
&self,
|
||||
nonce: &GenericArray<u8, U12>,
|
||||
|
|
|
@ -2,6 +2,7 @@ use smoltcp as net;
|
|||
|
||||
use managed::ManagedSlice;
|
||||
use crate::tls::TlsSocket;
|
||||
use net::socket::SocketSet;
|
||||
use net::phy::Device;
|
||||
use net::iface::EthernetInterface;
|
||||
use net::time::Instant;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use embedded_nal_tcp_stack as nal;
|
||||
use embedded_nal as nal;
|
||||
use smoltcp as net;
|
||||
|
||||
use crate::set::TlsSocketHandle as SocketHandle;
|
||||
use crate::set::TlsSocketSet as SocketSet;
|
||||
use crate::tls::TlsSocket;
|
||||
|
||||
use nal::{TcpStack, Mode, SocketAddr, nb};
|
||||
use net::Error;
|
||||
use net::iface::EthernetInterface;
|
||||
use net::time::Instant;
|
||||
use net::phy::Device;
|
||||
|
@ -75,13 +77,15 @@ impl<'a, 'b, 'c> TcpStack for NetworkStack<'a, 'b, 'c> {
|
|||
match self.unused_handles.borrow_mut().pop() {
|
||||
Some(handle) => {
|
||||
// Abort any active connections on the handle.
|
||||
log::info!("Have handle");
|
||||
let mut sockets = self.sockets.borrow_mut();
|
||||
let internal_socket = sockets.get(handle);
|
||||
internal_socket.close().unwrap();
|
||||
let mut internal_socket = sockets.get(handle);
|
||||
internal_socket.close();
|
||||
|
||||
Ok(handle)
|
||||
}
|
||||
None => {
|
||||
log::info!("Insufficient handles");
|
||||
Err(NetworkError::NoSocket)
|
||||
},
|
||||
}
|
||||
|
@ -96,7 +100,7 @@ impl<'a, 'b, 'c> TcpStack for NetworkStack<'a, 'b, 'c> {
|
|||
let internal_socket = sockets.get(socket);
|
||||
|
||||
match remote.ip() {
|
||||
nal::IpAddr::V4(addr) => {
|
||||
embedded_nal::IpAddr::V4(addr) => {
|
||||
let address = {
|
||||
let octets = addr.octets();
|
||||
net::wire::Ipv4Address::new(octets[0], octets[1], octets[2], octets[3])
|
||||
|
@ -105,7 +109,7 @@ impl<'a, 'b, 'c> TcpStack for NetworkStack<'a, 'b, 'c> {
|
|||
.connect((address, remote.port()), self.get_ephemeral_port())
|
||||
.map_err(|_| NetworkError::ConnectionFailure)?;
|
||||
}
|
||||
nal::IpAddr::V6(addr) => {
|
||||
embedded_nal::IpAddr::V6(addr) => {
|
||||
let address = {
|
||||
let octets = addr.segments();
|
||||
net::wire::Ipv6Address::new(
|
||||
|
@ -159,7 +163,7 @@ impl<'a, 'b, 'c> TcpStack for NetworkStack<'a, 'b, 'c> {
|
|||
) -> Result<(), Self::Error> {
|
||||
let mut sockets = self.sockets.borrow_mut();
|
||||
let internal_socket = sockets.get(socket);
|
||||
internal_socket.close().unwrap();
|
||||
internal_socket.close();
|
||||
|
||||
self.unused_handles.borrow_mut().push(socket).unwrap();
|
||||
Ok(())
|
||||
|
|
15
src/tls.rs
15
src/tls.rs
|
@ -2,6 +2,7 @@ use smoltcp::socket::TcpSocket;
|
|||
use smoltcp::socket::TcpState;
|
||||
use smoltcp::socket::SocketHandle;
|
||||
use smoltcp::socket::SocketSet;
|
||||
use smoltcp::socket::TcpSocketBuffer;
|
||||
use smoltcp::wire::IpEndpoint;
|
||||
use smoltcp::Result;
|
||||
use smoltcp::Error;
|
||||
|
@ -584,7 +585,7 @@ impl<'a, 'b, 'c> TlsSocket<'a, 'b, 'c> {
|
|||
let mut random: [u8; 32] = [0; 32];
|
||||
self.rng.fill_bytes(&mut random);
|
||||
let (session_id, cipher_suite, server_ecdhe_public_key) = {
|
||||
let session = self.session.borrow();
|
||||
let mut session = self.session.borrow();
|
||||
(
|
||||
session.get_session_id(),
|
||||
session.get_cipher_suite(),
|
||||
|
@ -664,7 +665,7 @@ impl<'a, 'b, 'c> TlsSocket<'a, 'b, 'c> {
|
|||
// TODO: Option to allow a certificate request
|
||||
|
||||
// Construct and send server certificate handshake content
|
||||
let inner_plaintext = {
|
||||
let mut inner_plaintext = {
|
||||
let mut inner_plaintext: Vec<u8> = Vec::new();
|
||||
let session = self.session.borrow();
|
||||
let certificates = session.get_private_certificate_slices().clone();
|
||||
|
@ -734,7 +735,7 @@ impl<'a, 'b, 'c> TlsSocket<'a, 'b, 'c> {
|
|||
log::info!("sent certificate");
|
||||
|
||||
// Construct and send certificate verify
|
||||
let inner_plaintext = {
|
||||
let mut inner_plaintext = {
|
||||
let mut inner_plaintext = Vec::new();
|
||||
inner_plaintext.extend_from_slice(&[
|
||||
15,
|
||||
|
@ -1430,10 +1431,11 @@ impl<'a, 'b, 'c> TlsSocket<'a, 'b, 'c> {
|
|||
// `key_share` extension: find the corresponding ECDHE shared key
|
||||
// `signature_algorithm`: pick a signature algorithm
|
||||
// Will not handle PSK, no 0-RTT
|
||||
let mut version_check = false;
|
||||
let mut offered_p256 = false;
|
||||
let mut offered_x25519 = false;
|
||||
let mut ecdhe_public_key: Option<DiffieHellmanPublicKey> = None;
|
||||
let signature_algorithm: Option<SignatureScheme>;
|
||||
let mut signature_algorithm: Option<SignatureScheme> = None;
|
||||
|
||||
// Verify that TLS 1.3 is offered by the client
|
||||
if let Some(supported_version_extension) = client_hello.extensions.iter().find(
|
||||
|
@ -1445,6 +1447,7 @@ impl<'a, 'b, 'c> TlsSocket<'a, 'b, 'c> {
|
|||
if let SupportedVersions::ClientHello { versions, .. }
|
||||
= supported_version
|
||||
{
|
||||
version_check = true;
|
||||
if versions.iter().find(
|
||||
|&&version| version == TlsVersion::Tls13
|
||||
).is_none()
|
||||
|
@ -1491,7 +1494,7 @@ impl<'a, 'b, 'c> TlsSocket<'a, 'b, 'c> {
|
|||
= &supported_groups.extension_data
|
||||
{
|
||||
// Mark down the offered and acceptable group
|
||||
if let Some(_group) = named_group_list.iter().find(
|
||||
if let Some(group) = named_group_list.iter().find(
|
||||
|&&named_group| {
|
||||
named_group == NamedGroup::secp256r1
|
||||
}
|
||||
|
@ -1499,7 +1502,7 @@ impl<'a, 'b, 'c> TlsSocket<'a, 'b, 'c> {
|
|||
offered_p256 = true;
|
||||
}
|
||||
|
||||
if let Some(_group) = named_group_list.iter().find(
|
||||
if let Some(group) = named_group_list.iter().find(
|
||||
|&&named_group| {
|
||||
named_group == NamedGroup::x25519
|
||||
}
|
||||
|
|
|
@ -406,6 +406,25 @@ impl ClientHello {
|
|||
self
|
||||
}
|
||||
|
||||
pub(crate) fn add_sh_supported_versions(mut self) -> Self {
|
||||
let selected_version = TlsVersion::Tls13;
|
||||
|
||||
let content = SupportedVersions::ServerHello {
|
||||
selected_version
|
||||
};
|
||||
|
||||
let extension_data = ExtensionData::SupportedVersions(content);
|
||||
let length = extension_data.get_length();
|
||||
let extension = Extension {
|
||||
extension_type: ExtensionType::SupportedVersions,
|
||||
length: length.try_into().unwrap(),
|
||||
extension_data,
|
||||
};
|
||||
|
||||
self.extensions.push(extension);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn add_sig_algs(mut self) -> Self {
|
||||
let mut algorithms = Vec::new();
|
||||
{
|
||||
|
@ -710,6 +729,12 @@ pub(crate) enum ExtensionType {
|
|||
Unknown = 0xFFFF,
|
||||
}
|
||||
|
||||
impl ExtensionType {
|
||||
pub(crate) fn get_length(&self) -> u16 {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Extension {
|
||||
pub(crate) extension_type: ExtensionType,
|
||||
|
|
Loading…
Reference in New Issue