key: init
This commit is contained in:
parent
912feac263
commit
ec53973aec
|
@ -7,11 +7,13 @@ edition = "2018"
|
|||
[dependencies]
|
||||
aes-gcm = "0.7.0"
|
||||
ccm = "0.2.0"
|
||||
hkdf = "0.9.0"
|
||||
sha2 = { version = "0.9.1", default-features = false }
|
||||
byteorder = { version = "1.3.4", default-features = false }
|
||||
num_enum = { version = "0.5.1", default-features = false }
|
||||
log = "0.4.11"
|
||||
generic-array = "0.14.4"
|
||||
heapless = "0.5.6"
|
||||
|
||||
[dependencies.smoltcp]
|
||||
version = "0.6.0"
|
||||
|
|
|
@ -8,8 +8,10 @@ use alloc::vec::Vec;
|
|||
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
|
||||
|
||||
use crate::tls_packet::*;
|
||||
use crate::key::*;
|
||||
|
||||
// Only designed to support read or write the entire buffer
|
||||
// TODO: Stricter visibility
|
||||
pub(crate) struct TlsBuffer<'a> {
|
||||
buffer: &'a mut [u8],
|
||||
index: RefCell<usize>,
|
||||
|
@ -22,7 +24,7 @@ impl<'a> Into<&'a [u8]> for TlsBuffer<'a> {
|
|||
}
|
||||
|
||||
impl<'a> TlsBuffer<'a> {
|
||||
pub(crate) fn new(buffer: &'a mut [u8]) -> Self {
|
||||
pub fn new(buffer: &'a mut [u8]) -> Self {
|
||||
Self {
|
||||
buffer,
|
||||
index: RefCell::new(0),
|
||||
|
@ -199,6 +201,14 @@ impl<'a> TlsBuffer<'a> {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! export_byte_order_fn {
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
use p256::{EncodedPoint, AffinePoint, ecdh::EphemeralSecret, ecdh::SharedSecret};
|
||||
use aes_gcm::{Aes128Gcm, Aes256Gcm};
|
||||
use chacha20poly1305::{ChaCha20Poly1305, Key};
|
||||
use ccm::{Ccm, consts::*};
|
||||
use aes_gcm::aes::Aes128;
|
||||
use aes_gcm::{AeadInPlace, NewAead};
|
||||
use generic_array::GenericArray;
|
||||
use rand_core::{ RngCore, CryptoRng };
|
||||
use alloc::vec::Vec;
|
||||
use crate::Error as TlsError;
|
||||
|
||||
pub(crate) enum Cipher {
|
||||
TLS_AES_128_GCM_SHA256(Aes128Gcm),
|
||||
TLS_AES_256_GCM_SHA384(Aes256Gcm),
|
||||
TLS_CHACHA20_POLY1305_SHA256(ChaCha20Poly1305),
|
||||
TLS_AES_128_CCM_SHA256(Ccm<Aes128, U16, U12>)
|
||||
}
|
||||
|
||||
macro_rules! impl_cipher {
|
||||
($($cipher_name: ident),+) => {
|
||||
impl Cipher {
|
||||
pub(crate) fn encrypt<T>(&self, rng: &mut T, associated_data: &[u8], buffer: &mut Vec<u8>) -> core::result::Result<(), TlsError>
|
||||
where
|
||||
T: RngCore + CryptoRng
|
||||
{
|
||||
// All 4 supported Ciphers use a nonce of 12 bytes
|
||||
let mut nonce_array: [u8; 12] = [0; 12];
|
||||
rng.fill_bytes(&mut nonce_array);
|
||||
use Cipher::*;
|
||||
match self {
|
||||
$(
|
||||
$cipher_name(cipher) => {
|
||||
cipher.encrypt_in_place(
|
||||
&GenericArray::from_slice(&nonce_array),
|
||||
associated_data,
|
||||
buffer
|
||||
).map_err(
|
||||
|_| TlsError::EncryptionError
|
||||
)
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn decrypt<T>(&self, rng: &mut T, associated_data: &[u8], buffer: &mut Vec<u8>) -> core::result::Result<(), TlsError>
|
||||
where
|
||||
T: RngCore + CryptoRng
|
||||
{
|
||||
// All 4 supported Ciphers use a nonce of 12 bytes
|
||||
let mut nonce_array: [u8; 12] = [0; 12];
|
||||
rng.fill_bytes(&mut nonce_array);
|
||||
use Cipher::*;
|
||||
match self {
|
||||
$(
|
||||
$cipher_name(cipher) => {
|
||||
cipher.decrypt_in_place(
|
||||
&GenericArray::from_slice(&nonce_array),
|
||||
associated_data,
|
||||
buffer
|
||||
).map_err(
|
||||
|_| TlsError::EncryptionError
|
||||
)
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_cipher!(
|
||||
TLS_AES_128_GCM_SHA256,
|
||||
TLS_AES_256_GCM_SHA384,
|
||||
TLS_CHACHA20_POLY1305_SHA256,
|
||||
TLS_AES_128_CCM_SHA256
|
||||
);
|
|
@ -0,0 +1,226 @@
|
|||
use p256::{EncodedPoint, AffinePoint, ecdh::EphemeralSecret, ecdh::SharedSecret};
|
||||
use aes_gcm::{Aes128Gcm, Aes256Gcm};
|
||||
use chacha20poly1305::{ChaCha20Poly1305, Key};
|
||||
use ccm::{Ccm, consts::*};
|
||||
use aes_gcm::aes::Aes128;
|
||||
use aes_gcm::{AeadInPlace, NewAead};
|
||||
use generic_array::GenericArray;
|
||||
use rand_core::{ RngCore, CryptoRng };
|
||||
use sha2::{ Digest, Sha256, Sha384, Sha512 };
|
||||
use heapless::Vec;
|
||||
use hkdf::Hkdf;
|
||||
|
||||
use crate::Error as TlsError;
|
||||
use crate::tls_packet::CipherSuite as CipherSuiteField;
|
||||
use crate::key::*;
|
||||
|
||||
// A structure representing the block cipher and the hashes
|
||||
pub(crate) enum CipherSuite {
|
||||
// Handshake is still proceeding, no cipher can be produced yet,
|
||||
// Though hashes still has to be prepared for deriving key later,
|
||||
// This enum offers all possible hashes that could be needed
|
||||
// i.e. SHA256 and SHA384
|
||||
Undetermined {
|
||||
sha_256: Sha256,
|
||||
sha_384: Sha384,
|
||||
},
|
||||
|
||||
// Established cipher suites
|
||||
// Contains a block cipher (GCM/CCM/ChaChaPoly)
|
||||
// Contains a hash function (SHA256/SHA384)
|
||||
TLS_AES_128_GCM_SHA256 {
|
||||
aes_128_gcm: Aes128Gcm,
|
||||
sha_256: Sha256,
|
||||
},
|
||||
TLS_AES_256_GCM_SHA384 {
|
||||
aes_256_gcm: Aes256Gcm,
|
||||
sha_384: Sha384,
|
||||
},
|
||||
TLS_CHACHA20_POLY1305_SHA256 {
|
||||
chacha20_poly1305: ChaCha20Poly1305,
|
||||
sha_256: Sha256,
|
||||
},
|
||||
TLS_AES_128_CCM_SHA256 {
|
||||
ccm: Ccm<Aes128, U16, U12>,
|
||||
sha_256: Sha256,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
impl CipherSuite {
|
||||
pub(crate) fn new() -> Self {
|
||||
CipherSuite::Undetermined {
|
||||
sha_256: Sha256::new(),
|
||||
sha_384: Sha384::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// Assume no PSK, establish ciphersuite along side handshake secret
|
||||
// Need to update hash function before calling
|
||||
pub(crate) fn establish(
|
||||
self,
|
||||
field: CipherSuiteField,
|
||||
ecdhe_shared: SharedSecret
|
||||
) -> Self {
|
||||
use CipherSuiteField::*;
|
||||
|
||||
let (sha_256, sha_384) = {
|
||||
if let CipherSuite::Undetermined {
|
||||
sha_256,
|
||||
sha_384,
|
||||
} = self {
|
||||
(sha_256, sha_384)
|
||||
} else {
|
||||
// TODO: Implement key change
|
||||
return self;
|
||||
}
|
||||
};
|
||||
|
||||
match field {
|
||||
TLS_AES_128_GCM_SHA256 | TLS_CHACHA20_POLY1305_SHA256 |
|
||||
TLS_AES_128_CCM_SHA256 => {
|
||||
// Compute early_secret in HKDF, without PSK
|
||||
let empty_hash = Sha256::new().chain("");
|
||||
let early_secret = Hkdf::<Sha256>::new(None, &[0; 32]);
|
||||
|
||||
// Calculate derived secret
|
||||
let derived_secret = derive_secret(
|
||||
&early_secret,
|
||||
"derived",
|
||||
empty_hash
|
||||
);
|
||||
|
||||
// Calculate handshake secret in HKDF
|
||||
let handshake_secret = Hkdf::<Sha256>::new(
|
||||
Some(&derived_secret),
|
||||
ecdhe_shared.as_bytes()
|
||||
);
|
||||
|
||||
// Calculate client_handshake_traffic_secret
|
||||
let client_handshake_traffic_secret = derive_secret(
|
||||
&handshake_secret,
|
||||
"c hs traffic",
|
||||
sha_256.clone()
|
||||
);
|
||||
|
||||
// Calculate server_handshake_traffic_secret
|
||||
let server_handshake_traffic_secret = derive_secret(
|
||||
&handshake_secret,
|
||||
"c hs traffic",
|
||||
sha_256.clone()
|
||||
);
|
||||
|
||||
// let client_write_key = hkdf_expand_label(
|
||||
//
|
||||
// );
|
||||
}
|
||||
_ => todo!()
|
||||
}
|
||||
|
||||
todo!()
|
||||
|
||||
// // Compute HKDF
|
||||
// let (hash, empty_hash, hkdf) = match field {
|
||||
// TLS_AES_128_GCM_SHA256 |
|
||||
// TLS_CHACHA20_POLY1305_SHA256 |
|
||||
// TLS_AES_128_CCM_SHA256 => {
|
||||
// (
|
||||
// sha_256,
|
||||
// Sha256::new().chain(""),
|
||||
// Hkdf::<Sha256>::new(None, &[0; 32])
|
||||
// )
|
||||
// },
|
||||
// TLS_AES_256_GCM_SHA384 => {
|
||||
// (
|
||||
// sha_384,
|
||||
// Sha384::new().chain(""),
|
||||
// Hkdf::<Sha384>::new(None, &[0; 48])
|
||||
// )
|
||||
// }
|
||||
// };
|
||||
|
||||
// // get_derived_secret, then insert ECDHE shared secret
|
||||
// let derived_secret = derive_secret(hkdf, "derived", empty_hash);
|
||||
|
||||
// let (key, iv) = match field {
|
||||
// TLS_AES_128_GCM_SHA256 |
|
||||
// TLS_CHACHA20_POLY1305_SHA256 |
|
||||
// TLS_AES_128_CCM_SHA256 => {
|
||||
// let hkdf = Hkdf::<Sha256>::new(
|
||||
// Some(&derived_secret),
|
||||
// ecdhe_shared.as_bytes()
|
||||
// );
|
||||
// let client_handshake_traffic_secret = derive_secret(
|
||||
// hkdf,
|
||||
// "c hs traffic",
|
||||
// sha256.clone(),
|
||||
// );
|
||||
// },
|
||||
// TLS_AES_256_GCM_SHA384 => {
|
||||
// Hkdf::<Sha384>::new(
|
||||
// Some(&derived_secret),
|
||||
// ecdhe_shared.as_bytes()
|
||||
// )
|
||||
// }
|
||||
// };
|
||||
}
|
||||
}
|
||||
|
||||
// macro_rules! impl_cipher {
|
||||
// ($($cipher_name: ident),+) => {
|
||||
// impl Cipher {
|
||||
// pub(crate) fn encrypt<T>(&self, rng: &mut T, associated_data: &[u8], buffer: &mut Vec<u8>) -> core::result::Result<(), TlsError>
|
||||
// where
|
||||
// T: RngCore + CryptoRng
|
||||
// {
|
||||
// // All 4 supported Ciphers use a nonce of 12 bytes
|
||||
// let mut nonce_array: [u8; 12] = [0; 12];
|
||||
// rng.fill_bytes(&mut nonce_array);
|
||||
// use Cipher::*;
|
||||
// match self {
|
||||
// $(
|
||||
// $cipher_name(cipher) => {
|
||||
// cipher.encrypt_in_place(
|
||||
// &GenericArray::from_slice(&nonce_array),
|
||||
// associated_data,
|
||||
// buffer
|
||||
// ).map_err(
|
||||
// |_| TlsError::EncryptionError
|
||||
// )
|
||||
// }
|
||||
// )+
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub(crate) fn decrypt<T>(&self, rng: &mut T, associated_data: &[u8], buffer: &mut Vec<u8>) -> core::result::Result<(), TlsError>
|
||||
// where
|
||||
// T: RngCore + CryptoRng
|
||||
// {
|
||||
// // All 4 supported Ciphers use a nonce of 12 bytes
|
||||
// let mut nonce_array: [u8; 12] = [0; 12];
|
||||
// rng.fill_bytes(&mut nonce_array);
|
||||
// use Cipher::*;
|
||||
// match self {
|
||||
// $(
|
||||
// $cipher_name(cipher) => {
|
||||
// cipher.decrypt_in_place(
|
||||
// &GenericArray::from_slice(&nonce_array),
|
||||
// associated_data,
|
||||
// buffer
|
||||
// ).map_err(
|
||||
// |_| TlsError::EncryptionError
|
||||
// )
|
||||
// }
|
||||
// )+
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl_cipher!(
|
||||
// TLS_AES_128_GCM_SHA256,
|
||||
// TLS_AES_256_GCM_SHA384,
|
||||
// TLS_CHACHA20_POLY1305_SHA256,
|
||||
// TLS_AES_128_CCM_SHA256
|
||||
// );
|
|
@ -0,0 +1,111 @@
|
|||
use hkdf::Hkdf;
|
||||
use sha2::{ Digest, Sha256, Sha384, Sha512 };
|
||||
use sha2::digest::{BlockInput, FixedOutput, Reset, Update};
|
||||
use generic_array::{ GenericArray, ArrayLength };
|
||||
use heapless::{ String, Vec, consts::* };
|
||||
|
||||
use crate::buffer::TlsBuffer;
|
||||
|
||||
use core::convert::TryFrom;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct HkdfLabel<'a> {
|
||||
// Length of hash function
|
||||
pub(crate) length: u16,
|
||||
// Label vector: "tls13 " + label
|
||||
pub(crate) label_length: u8,
|
||||
pub(crate) label: &'a [u8],
|
||||
// Context vector: Hashed message
|
||||
pub(crate) context_length: u8,
|
||||
pub(crate) context: &'a [u8],
|
||||
}
|
||||
|
||||
// Implementation of Derive-Secret function in RFC8446
|
||||
pub(crate) fn derive_secret<Hash>(
|
||||
hkdf: &Hkdf<Hash>,
|
||||
label: &str,
|
||||
hash: Hash
|
||||
) -> GenericArray<u8, Hash::OutputSize>
|
||||
where
|
||||
Hash: Update + BlockInput + FixedOutput + Reset + Default + Clone,
|
||||
Hash::OutputSize: ArrayLength<u8>,
|
||||
{
|
||||
// Build a string using heapless
|
||||
// label size:
|
||||
// prefix: "tls13 " => 6 chars
|
||||
// suffix: at most 12 chars as per RFC8446, section 7.1
|
||||
let mut label_string: String<U32> = String::new();
|
||||
label_string.push_str("tls13 ").unwrap();
|
||||
label_string.push_str(label);
|
||||
|
||||
let length = u16::try_from(Hash::output_size()).unwrap();
|
||||
let label_length = u8::try_from(label_string.len()).unwrap();
|
||||
|
||||
let hkdf_label = HkdfLabel {
|
||||
length,
|
||||
label_length,
|
||||
label: label_string.as_ref(),
|
||||
context_length: u8::try_from(length).unwrap(),
|
||||
context: &hash.finalize(),
|
||||
};
|
||||
|
||||
// Build info from HKDF label using Buffer
|
||||
// length: 2 bytes,
|
||||
// label_vec: 18 bytes (label) + 1 byte (len)
|
||||
// context_vec: 48 bytes for SHA384 + 1 byte (len)
|
||||
let mut array = [0; 100];
|
||||
let mut buffer = TlsBuffer::new(&mut array);
|
||||
buffer.enqueue_hkdf_label(hkdf_label);
|
||||
let info: &[u8] = buffer.into();
|
||||
|
||||
// Define output key material (OKM), dynamically sized by hash
|
||||
let mut okm: GenericArray<u8, Hash::OutputSize> = GenericArray::default();
|
||||
hkdf.expand(info, &mut okm).unwrap();
|
||||
okm
|
||||
}
|
||||
|
||||
// Implementation of HKDF-Expand-Label function in RFC8446
|
||||
// Secret is embedded inside hkdf through salt and input key material (IKM)
|
||||
pub(crate) fn hkdf_expand_label<Hash>(
|
||||
hkdf: &Hkdf<Hash>,
|
||||
label: &str,
|
||||
context: &str,
|
||||
okm: &mut [u8],
|
||||
)
|
||||
where
|
||||
Hash: Update + BlockInput + FixedOutput + Reset + Default + Clone,
|
||||
{
|
||||
// Build a string using heapless
|
||||
// label size:
|
||||
// prefix: "tls13 " => 6 chars
|
||||
// suffix: at most 12 chars as per RFC8446, section 7.1
|
||||
let mut label_string: String<U32> = String::new();
|
||||
label_string.push_str("tls13 ").unwrap();
|
||||
label_string.push_str(label);
|
||||
let label_length = u8::try_from(label_string.len()).unwrap();
|
||||
|
||||
let context_slice = context.as_bytes();
|
||||
let context_length = u8::try_from(context_slice.len()).unwrap();
|
||||
|
||||
let length = u16::try_from(okm.len()).unwrap();
|
||||
|
||||
// Build HKDF label
|
||||
let hkdf_label = HkdfLabel {
|
||||
length,
|
||||
label_length,
|
||||
label: label_string.as_ref(),
|
||||
context_length: context_length,
|
||||
context: context_slice,
|
||||
};
|
||||
|
||||
// Build info from HKDF label using Buffer
|
||||
// length: 2 bytes,
|
||||
// label_vec: 18 bytes (label) + 1 byte (len)
|
||||
// context_vec: 48 bytes for SHA384 + 1 byte (len)
|
||||
let mut array = [0; 100];
|
||||
let mut buffer = TlsBuffer::new(&mut array);
|
||||
buffer.enqueue_hkdf_label(hkdf_label);
|
||||
let info: &[u8] = buffer.into();
|
||||
|
||||
hkdf.expand(info, okm).unwrap();
|
||||
}
|
|
@ -6,8 +6,9 @@ extern crate alloc;
|
|||
pub mod tls;
|
||||
pub mod tls_packet;
|
||||
pub mod parse;
|
||||
pub mod cipher;
|
||||
pub mod cipher_suite;
|
||||
pub mod buffer;
|
||||
pub mod key;
|
||||
|
||||
// TODO: Implement errors
|
||||
// Details: Encapsulate smoltcp & nom errors
|
||||
|
|
120
src/tls.rs
120
src/tls.rs
|
@ -28,13 +28,14 @@ use chacha20poly1305::{ChaCha20Poly1305, Key};
|
|||
use ccm::{Ccm, consts::*};
|
||||
use aes_gcm::aes::Aes128;
|
||||
use aes_gcm::{AeadInPlace, NewAead};
|
||||
use sha2::{Sha256, Sha384, Sha512, Digest};
|
||||
|
||||
use alloc::vec::{ self, Vec };
|
||||
|
||||
use crate::Error as TlsError;
|
||||
use crate::tls_packet::*;
|
||||
use crate::parse::parse_tls_repr;
|
||||
use crate::cipher::Cipher;
|
||||
use crate::cipher_suite::CipherSuite;
|
||||
use crate::buffer::TlsBuffer;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
|
@ -59,7 +60,8 @@ pub struct TlsSocket<R: 'static + RngCore + CryptoRng>
|
|||
secret: RefCell<Option<EphemeralSecret>>, // Used enum Option to allow later init
|
||||
session_id: RefCell<Option<[u8; 32]>>, // init session specific field later
|
||||
received_change_cipher_spec: RefCell<Option<bool>>,
|
||||
cipher: RefCell<Option<Cipher>>,
|
||||
cipher: RefCell<Option<CipherSuite>>,
|
||||
handshake_sha256: RefCell<Sha256>,
|
||||
}
|
||||
|
||||
impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
|
@ -82,6 +84,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
|||
session_id: RefCell::new(None),
|
||||
received_change_cipher_spec: RefCell::new(None),
|
||||
cipher: RefCell::new(None),
|
||||
handshake_sha256: RefCell::new(Sha256::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +138,19 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
|||
self.rng.fill_bytes(&mut session_id);
|
||||
let repr = TlsRepr::new()
|
||||
.client_hello(&ecdh_secret, random, session_id);
|
||||
self.send_tls_repr(sockets, repr)?;
|
||||
|
||||
// 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)?;
|
||||
|
||||
// Store session settings, i.e. secret, session_id
|
||||
self.secret.replace(Some(ecdh_secret));
|
||||
|
@ -161,9 +176,13 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
|||
|
||||
// Read for TLS packet
|
||||
let mut array: [u8; 2048] = [0; 2048];
|
||||
let tls_repr_vec = self.recv_tls_repr(sockets, &mut array)?;
|
||||
let mut tls_repr_vec = self.recv_tls_repr(sockets, &mut array)?;
|
||||
|
||||
for repr in tls_repr_vec.iter() {
|
||||
// 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)?;
|
||||
}
|
||||
|
||||
|
@ -171,7 +190,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
|||
}
|
||||
|
||||
// Process TLS ingress during handshake
|
||||
fn process(&self, repr: &TlsRepr) -> Result<()> {
|
||||
fn process(&self, repr: TlsRepr) -> Result<()> {
|
||||
let state = self.state.clone().into_inner();
|
||||
|
||||
// Change_cipher_spec check:
|
||||
|
@ -270,44 +289,58 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
|||
let shared = secret.unwrap()
|
||||
.diffie_hellman(&server_public)
|
||||
.expect("Unsupported key");
|
||||
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));
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
self.state.replace(TlsState::WAIT_EE);
|
||||
|
||||
} else {
|
||||
// Handle invalid TLS packet
|
||||
todo!()
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -343,6 +376,23 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
|||
)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Generic inner recv method, through TCP socket
|
||||
// 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>> {
|
||||
|
|
|
@ -201,7 +201,7 @@ impl<'a> ClientHello<'a> {
|
|||
random,
|
||||
session_id_length: 32,
|
||||
session_id,
|
||||
cipher_suites_length: 6,
|
||||
cipher_suites_length: 0,
|
||||
cipher_suites: &[
|
||||
CipherSuite::TLS_AES_128_GCM_SHA256,
|
||||
CipherSuite::TLS_AES_256_GCM_SHA384,
|
||||
|
@ -213,6 +213,7 @@ impl<'a> ClientHello<'a> {
|
|||
extension_length: 0,
|
||||
extensions: Vec::new(),
|
||||
};
|
||||
client_hello.cipher_suites_length = u16::try_from(client_hello.cipher_suites.len() * 2).unwrap();
|
||||
|
||||
client_hello.add_ch_supported_versions()
|
||||
.add_sig_algs()
|
||||
|
|
Loading…
Reference in New Issue