Compare commits

..

No commits in common. "0c6807f59315e040244b3400c3eae691540eef6b" and "552d21a1b398ce775857f9fd8e060d3a297152d2" have entirely different histories.

9 changed files with 190 additions and 45 deletions

View File

@ -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" ]

View File

@ -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<()> {

View File

@ -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

View File

@ -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"
);
*/

View File

@ -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>,

View File

@ -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;

View File

@ -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(())

View File

@ -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
}

View File

@ -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,