server ee: init

This commit is contained in:
occheung 2020-11-27 11:53:45 +08:00
parent 3ba03819d4
commit 81d52e9ec4
2 changed files with 459 additions and 18 deletions

View File

@ -1203,7 +1203,362 @@ impl<'a> Session<'a> {
server_ecdhe_secret: DiffieHellmanPrivateKey,
server_hello_slice: &[u8]
) {
todo!()
// Hash update
self.hash.update(server_hello_slice);
let mut shared_secret_bytes: [u8; 32] = [0; 32];
match (self.ecdhe_public.unwrap(), server_ecdhe_secret) {
(
DiffieHellmanPublicKey::SECP256R1 { encoded_point },
DiffieHellmanPrivateKey::SECP256R1 { ephemeral_secret }
) => {
shared_secret_bytes.clone_from_slice(
ephemeral_secret.diffie_hellman(
&encoded_point
).unwrap().as_bytes()
)
},
(
DiffieHellmanPublicKey::X25519 { public_key },
DiffieHellmanPrivateKey::X25519 { ephemeral_secret }
) => {
shared_secret_bytes.clone_from_slice(
ephemeral_secret.diffie_hellman(
&public_key
).as_bytes()
)
},
_ => unreachable!()
}
let server_selected_cipher = self.server_selected_cipher.take().unwrap();
// Find handshake keys and IV
match server_selected_cipher {
CipherSuite::TLS_AES_128_CCM_SHA256 |
CipherSuite::TLS_CHACHA20_POLY1305_SHA256 |
CipherSuite::TLS_AES_128_GCM_SHA256 => {
// Find early secret wrapped in HKDF
let empty_psk: GenericArray<u8, <Sha256 as FixedOutput>::OutputSize> = Default::default();
let early_secret_hkdf = Hkdf::<Sha256>::new(None, &empty_psk);
// Find handshake secret
let empty_hash = Sha256::new().chain("");
let derived_secret = derive_secret(
&early_secret_hkdf,
"derived",
empty_hash
);
let (handshake_secret, handshake_secret_hkdf) =
Hkdf::<Sha256>::extract(
Some(&derived_secret),
&shared_secret_bytes
);
// Store the handshake secret
self.latest_secret.replace(
Vec::from_slice(&handshake_secret)
.unwrap()
);
let client_handshake_traffic_secret = derive_secret(
&handshake_secret_hkdf,
"c hs traffic",
self.hash.get_sha256_clone().unwrap()
);
let server_handshake_traffic_secret = derive_secret(
&handshake_secret_hkdf,
"s hs traffic",
self.hash.get_sha256_clone().unwrap()
);
// Store client_handshake_traffic_secret and
// server_handshake_traffic_secret
// Initial values of both secrets don't matter
self.client_handshake_traffic_secret.replace(
Vec::from_slice(&client_handshake_traffic_secret).unwrap()
);
self.server_handshake_traffic_secret.replace(
Vec::from_slice(&server_handshake_traffic_secret).unwrap()
);
let client_handshake_traffic_secret_hkdf = Hkdf::<Sha256>::from_prk(&client_handshake_traffic_secret).unwrap();
let server_handshake_traffic_secret_hkdf = Hkdf::<Sha256>::from_prk(&server_handshake_traffic_secret).unwrap();
// Prepare holder for key and IV
let client_handshake_key: Vec<u8, U64> = {
let mut client_handshake_key_holder: Vec<u8, U64> = match server_selected_cipher {
// 16 bytes key size
CipherSuite::TLS_AES_128_GCM_SHA256 |
CipherSuite::TLS_AES_128_CCM_SHA256 => {
Vec::from_slice(&[0; 16]).unwrap()
},
// 32 bytes key size
CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => {
Vec::from_slice(&[0; 32]).unwrap()
},
// Not using Sha256 (AES_GCM_256) / not supported (CCM_8)
_ => unreachable!()
};
hkdf_expand_label(
&client_handshake_traffic_secret_hkdf,
"key",
"",
&mut client_handshake_key_holder
);
client_handshake_key_holder
};
let client_handshake_iv: Vec<u8, U12> = {
let mut client_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap();
hkdf_expand_label(
&client_handshake_traffic_secret_hkdf,
"iv",
"",
&mut client_handshake_iv_holder
);
client_handshake_iv_holder
};
let server_handshake_key: Vec<u8, U64> = {
let mut server_handshake_key_holder: Vec<u8, U64> = match server_selected_cipher {
// 16 bytes key size
CipherSuite::TLS_AES_128_GCM_SHA256 |
CipherSuite::TLS_AES_128_CCM_SHA256 => {
Vec::from_slice(&[0; 16]).unwrap()
},
// 32 bytes key size
CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => {
Vec::from_slice(&[0; 32]).unwrap()
},
// Not using Sha256 (AES_GCM_256) / not supported (CCM_8)
_ => unreachable!()
};
hkdf_expand_label(
&server_handshake_traffic_secret_hkdf,
"key",
"",
&mut server_handshake_key_holder
);
server_handshake_key_holder
};
let server_handshake_iv: Vec<u8, U12> = {
let mut server_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap();
hkdf_expand_label(
&server_handshake_traffic_secret_hkdf,
"iv",
"",
&mut server_handshake_iv_holder
);
server_handshake_iv_holder
};
// Store nonce
self.client_handshake_nonce = Some(client_handshake_iv);
self.server_handshake_nonce = Some(server_handshake_iv);
// Construct cipher from key & IV for client & server
// Store the ciphers
match server_selected_cipher {
CipherSuite::TLS_AES_128_GCM_SHA256 => {
let client_handshake_cipher = Aes128Gcm::new(
GenericArray::from_slice(&client_handshake_key)
);
let server_handshake_cipher = Aes128Gcm::new(
GenericArray::from_slice(&server_handshake_key)
);
self.client_handshake_cipher = Some(
Cipher::Aes128Gcm {
aes128gcm: client_handshake_cipher
}
);
self.server_handshake_cipher = Some(
Cipher::Aes128Gcm {
aes128gcm: server_handshake_cipher
}
);
},
CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => {
let client_handshake_cipher = ChaCha20Poly1305::new(
GenericArray::from_slice(&client_handshake_key)
);
let server_handshake_cipher = ChaCha20Poly1305::new(
GenericArray::from_slice(&server_handshake_key)
);
self.client_handshake_cipher = Some(
Cipher::Chacha20poly1305 {
chacha20poly1305: client_handshake_cipher
}
);
self.server_handshake_cipher = Some(
Cipher::Chacha20poly1305 {
chacha20poly1305: server_handshake_cipher
}
);
},
CipherSuite::TLS_AES_128_CCM_SHA256 => {
let client_handshake_cipher = Aes128Ccm::new(
GenericArray::from_slice(&client_handshake_key)
);
let server_handshake_cipher = Aes128Ccm::new(
GenericArray::from_slice(&server_handshake_key)
);
self.client_handshake_cipher = Some(
Cipher::Ccm {
ccm: client_handshake_cipher
}
);
self.server_handshake_cipher = Some(
Cipher::Ccm {
ccm: server_handshake_cipher
}
);
},
_ => unreachable!()
}
},
CipherSuite::TLS_AES_256_GCM_SHA384 => {
// Find early secret in terms wrapped in HKDF
let empty_psk: GenericArray<u8, <Sha384 as FixedOutput>::OutputSize> = Default::default();
let early_secret_hkdf =
Hkdf::<Sha384>::new(None, &empty_psk);
// Find handshake secret
let empty_hash = Sha384::new().chain("");
let derived_secret = derive_secret(
&early_secret_hkdf,
"derived",
empty_hash
);
let (handshake_secret, handshake_secret_hkdf) =
Hkdf::<Sha384>::extract(
Some(&derived_secret),
&shared_secret_bytes
);
// Store the handshake secret
self.latest_secret.replace(
Vec::from_slice(&handshake_secret)
.unwrap()
);
let client_handshake_traffic_secret = derive_secret(
&handshake_secret_hkdf,
"c hs traffic",
self.hash.get_sha384_clone().unwrap()
);
let server_handshake_traffic_secret = derive_secret(
&handshake_secret_hkdf,
"s hs traffic",
self.hash.get_sha384_clone().unwrap()
);
// Store client_handshake_traffic_secret and
// server_handshake_traffic_secret
// Initial values of both secrets don't matter
self.client_handshake_traffic_secret.replace(
Vec::from_slice(&client_handshake_traffic_secret).unwrap()
);
self.server_handshake_traffic_secret.replace(
Vec::from_slice(&server_handshake_traffic_secret).unwrap()
);
let client_handshake_traffic_secret_hkdf = Hkdf::<Sha384>::from_prk(&client_handshake_traffic_secret).unwrap();
let server_handshake_traffic_secret_hkdf = Hkdf::<Sha384>::from_prk(&server_handshake_traffic_secret).unwrap();
// Prepare holder for key and IV
let client_handshake_key: Vec<u8, U64> = {
// 32 bytes key size
let mut client_handshake_key_holder: Vec<u8, U64> =
Vec::from_slice(&[0; 32]).unwrap();
hkdf_expand_label(
&client_handshake_traffic_secret_hkdf,
"key",
"",
&mut client_handshake_key_holder
);
client_handshake_key_holder
};
let client_handshake_iv: Vec<u8, U12> = {
let mut client_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap();
hkdf_expand_label(
&client_handshake_traffic_secret_hkdf,
"iv",
"",
&mut client_handshake_iv_holder
);
client_handshake_iv_holder
};
let server_handshake_key: Vec<u8, U64> = {
// 32 bytes key size
let mut server_handshake_key_holder: Vec<u8, U64> =
Vec::from_slice(&[0; 32]).unwrap();
hkdf_expand_label(
&server_handshake_traffic_secret_hkdf,
"key",
"",
&mut server_handshake_key_holder
);
server_handshake_key_holder
};
let server_handshake_iv: Vec<u8, U12> = {
let mut server_handshake_iv_holder = Vec::from_slice(&[0; 12]).unwrap();
hkdf_expand_label(
&server_handshake_traffic_secret_hkdf,
"iv",
"",
&mut server_handshake_iv_holder
);
server_handshake_iv_holder
};
// Store nonce
self.client_handshake_nonce = Some(client_handshake_iv);
self.server_handshake_nonce = Some(server_handshake_iv);
let client_handshake_cipher = Aes256Gcm::new(
GenericArray::from_slice(&client_handshake_key)
);
let server_handshake_cipher = Aes256Gcm::new(
GenericArray::from_slice(&server_handshake_key)
);
self.client_handshake_cipher = Some(
Cipher::Aes256Gcm {
aes256gcm: client_handshake_cipher
}
);
self.server_handshake_cipher = Some(
Cipher::Aes256Gcm {
aes256gcm: server_handshake_cipher
}
);
},
CipherSuite::TLS_AES_128_CCM_8_SHA256 => unreachable!()
}
// Will send EE, {CR}, Cert, CV FIN in the same state
// No need to mutate FSM
// Ensure that the sequence numbers start from 0
self.client_sequence_number = 0;
self.server_sequence_number = 0;
}
pub(crate) fn server_update_for_encrypted_extension(
&mut self,
encryption_extension_slice: &[u8],
) {
self.hash.update(encryption_extension_slice);
}
pub(crate) fn verify_session_id_echo(&self, session_id_echo: &[u8]) -> bool {
@ -1214,9 +1569,9 @@ impl<'a> Session<'a> {
}
}
pub(crate) fn get_session_id(&self) -> &[u8] {
pub(crate) fn get_session_id(&self) -> [u8; 32] {
if let Some(session_id) = &self.session_id {
session_id
*session_id
} else {
unreachable!()
}
@ -1730,6 +2085,30 @@ impl<'a> Session<'a> {
self.server_sequence_number += 1;
}
pub(crate) fn increment_local_sequence_number(&mut self) {
match self.role {
TlsRole::Client => {
self.client_sequence_number += 1;
},
TlsRole::Server => {
self.server_sequence_number += 1;
},
_ => unreachable!()
}
}
pub(crate) fn increment_remote_sequence_number(&mut self) {
match self.role {
TlsRole::Client => {
self.server_sequence_number += 1;
},
TlsRole::Server => {
self.client_sequence_number += 1;
},
_ => unreachable!()
}
}
pub(crate) fn get_session_role(&self) -> TlsRole {
self.role
}
@ -2013,3 +2392,20 @@ pub enum DiffieHellmanPrivateKey {
ephemeral_secret: x25519_dalek::EphemeralSecret
}
}
impl DiffieHellmanPrivateKey {
pub fn to_public_key(&self) -> DiffieHellmanPublicKey {
match self {
Self::SECP256R1 { ephemeral_secret } => {
DiffieHellmanPublicKey::SECP256R1 {
encoded_point: p256::EncodedPoint::from(ephemeral_secret)
}
},
Self::X25519 { ephemeral_secret } => {
DiffieHellmanPublicKey::X25519 {
public_key: x25519_dalek::PublicKey::from(ephemeral_secret)
}
}
}
}
}

View File

@ -31,7 +31,7 @@ use crate::parse::{
get_content_type_inner_plaintext
};
use crate::buffer::TlsBuffer;
use crate::session::{Session, TlsRole, DiffieHellmanPublicKey};
use crate::session::{Session, TlsRole, DiffieHellmanPublicKey, DiffieHellmanPrivateKey};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(non_camel_case_types)]
@ -437,23 +437,44 @@ impl<'s> TlsSocket<'s> {
// - CertificateVerify
// - Finished
TlsState::NEGOTIATED => {
let mut session = self.session.borrow_mut();
let mut random: [u8; 32] = [0; 32];
self.rng.fill_bytes(&mut random);
// Relay session id
let session_id = session.get_session_id();
let cipher_suite = session.get_cipher_suite();
let ecdhe_key = session.get_server_ecdhe_public_key();
let (session_id, cipher_suite, server_ecdhe_public_key) = {
let mut session = self.session.borrow();
(
session.get_session_id(),
session.get_cipher_suite(),
session.get_server_ecdhe_public_key()
)
};
let ecdhe_private_key = match server_ecdhe_public_key {
DiffieHellmanPublicKey::SECP256R1 { .. } => {
DiffieHellmanPrivateKey::SECP256R1 {
ephemeral_secret: {
p256::ecdh::EphemeralSecret::random(&mut self.rng)
}
}
},
DiffieHellmanPublicKey::X25519 { .. } => {
DiffieHellmanPrivateKey::X25519 {
ephemeral_secret: {
x25519_dalek::EphemeralSecret::new(&mut self.rng)
}
}
}
};
let ecdhe_public_key = ecdhe_private_key.to_public_key();
// Construct and send SH
let repr = TlsRepr::new().server_hello(
&random,
session_id,
&session_id,
cipher_suite,
ecdhe_key
ecdhe_public_key
);
{
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
let mut session = self.session.borrow_mut();
tcp_socket.send(
|data| {
// Enqueue the TLS representation
@ -463,14 +484,35 @@ impl<'s> TlsSocket<'s> {
}
let slice: &[u8] = buffer.into();
// Update session
// todo!();
// Update session after sending only SH
session.server_update_for_server_hello(
ecdhe_private_key,
&slice[5..]
);
// Send the data
(slice.len(), ())
}
)?;
}
// Construct and send minimalistic EE
let inner_plaintext: [u8; 7] = [
0x08, // EE type
0x00, 0x00, 0x02, // Length: 2
0x00, 0x00, // Length of extensions: 0
22 // Content type of InnerPlainText
];
self.send_application_slice(sockets, &mut inner_plaintext.clone())?;
let inner_plaintext_length = inner_plaintext.len();
{
let mut session = self.session.borrow_mut();
session.server_update_for_encrypted_extension(
&inner_plaintext
);
}
}
// Other states regarding server role
@ -1222,16 +1264,19 @@ impl<'s> TlsSocket<'s> {
// TODO: Rename this function. It is only good for client finished
fn send_application_slice(&self, sockets: &mut SocketSet, slice: &mut [u8]) -> Result<()> {
let mut tcp_socket = sockets.get::<TcpSocket>(self.tcp_handle);
log::info!("Got socket");
if !tcp_socket.can_send() {
return Err(Error::Illegal);
}
log::info!("Socket usable");
// Borrow session in advance
let mut client_session = self.session.borrow_mut();
let mut session = self.session.borrow_mut();
log::info!("Got session");
// Pre-compute TLS record layer as associated_data
let mut associated_data: [u8; 5] = [0x17, 0x03, 0x03, 0x00, 0x00];
let auth_tag_length: u16 = match client_session.get_cipher_suite_type() {
let auth_tag_length: u16 = match session.get_cipher_suite_type() {
Some(CipherSuite::TLS_AES_128_GCM_SHA256) |
Some(CipherSuite::TLS_AES_256_GCM_SHA384) |
Some(CipherSuite::TLS_AES_128_CCM_SHA256) |
@ -1246,7 +1291,7 @@ impl<'s> TlsSocket<'s> {
auth_tag_length + u16::try_from(slice.len()).unwrap()
);
let auth_tag = client_session.encrypt_in_place_detached(
let auth_tag = session.encrypt_in_place_detached(
&associated_data,
slice
).map_err(|_| Error::Illegal)?;
@ -1255,7 +1300,7 @@ impl<'s> TlsSocket<'s> {
tcp_socket.send_slice(&slice)?;
tcp_socket.send_slice(&auth_tag)?;
client_session.increment_client_sequence_number();
session.increment_local_sequence_number();
Ok(())
}