diff --git a/src/session.rs b/src/session.rs index 12569af..8e1b483 100644 --- a/src/session.rs +++ b/src/session.rs @@ -495,180 +495,6 @@ impl<'a> Session<'a> { hmac.update(&transcript_hash); hmac.verify(server_verify_data).unwrap(); - // Update hash for key computation - self.hash.update(server_finished_slice); - - // Derive application traffic secret, key, IV on client's side - // 1. Derive secret from "Handshake Secret" - let hkdf = Hkdf::::from_prk( - // TLS requires the removal of secret if such secret is not of any use - // Replace "latest_secret" with None - self.latest_secret.as_ref().unwrap() - ).unwrap(); - - let empty_hash = Sha256::new().chain(""); - let derived_secret = derive_secret(&hkdf, "derived", empty_hash); - - // 2. HKDF-extract "Master Secret" - let zero_ikm: GenericArray::OutputSize> - = Default::default(); - let (master_secret, master_secret_hkdf) = Hkdf::::extract( - Some(&derived_secret), - &zero_ikm - ); - - // Replace latest secret with "master_secret" - self.latest_secret.replace( - Vec::from_slice(&master_secret).unwrap() - ); - - // 3. Get application traffic secret - let client_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "c ap traffic", - self.hash.get_sha256_clone().unwrap() - ); - - let server_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "s ap traffic", - self.hash.get_sha256_clone().unwrap() - ); - - self.client_application_traffic_secret.replace( - Vec::from_slice(&client_application_traffic_secret).unwrap() - ); - self.server_application_traffic_secret.replace( - Vec::from_slice(&server_application_traffic_secret).unwrap() - ); - - // 4. Replace cipher and IV - let client_application_traffic_hkdf = Hkdf::::from_prk( - &client_application_traffic_secret - ).unwrap(); - let server_application_traffic_hkdf = Hkdf::::from_prk( - &server_application_traffic_secret - ).unwrap(); - - // Init key and IV holders - let cipher_suite = self.client_handshake_cipher.as_ref().unwrap().get_cipher_suite_type(); - - let (mut client_key_holder, mut client_iv_holder, - mut server_key_holder, mut server_iv_holder): - (Vec::, Vec::, Vec::, Vec::) = - match cipher_suite { - CipherSuite::TLS_AES_128_GCM_SHA256 => { - ( - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { - ( - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - CipherSuite::TLS_AES_128_CCM_SHA256 => { - ( - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - // TLS_AES_128_CCM_8_SHA256 is not offered - // TLS_AES_256_GCM_SHA384 should not have SHA256 as hash - _ => unreachable!() - }; - - // Derive Key and IV for both server and client - hkdf_expand_label( - &client_application_traffic_hkdf, - "key", - "", - &mut client_key_holder - ); - hkdf_expand_label( - &client_application_traffic_hkdf, - "iv", - "", - &mut client_iv_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "key", - "", - &mut server_key_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "iv", - "", - &mut server_iv_holder - ); - - // Store IV/nonce - self.client_application_nonce.replace(client_iv_holder); - self.server_application_nonce.replace(server_iv_holder); - - // Instantiate new ciphers - match cipher_suite { - CipherSuite::TLS_AES_128_GCM_SHA256 => { - self.client_application_cipher.replace( - Cipher::Aes128Gcm { - aes128gcm: Aes128Gcm::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Aes128Gcm { - aes128gcm: Aes128Gcm::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { - self.client_application_cipher.replace( - Cipher::Chacha20poly1305 { - chacha20poly1305: ChaCha20Poly1305::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Chacha20poly1305 { - chacha20poly1305: ChaCha20Poly1305::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - CipherSuite::TLS_AES_128_CCM_SHA256 => { - self.client_application_cipher.replace( - Cipher::Ccm { - ccm: Aes128Ccm::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Ccm { - ccm: Aes128Ccm::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - _ => unreachable!() - } - } else if let Ok(sha384) = self.hash.get_sha384_clone() { let hkdf = Hkdf::::from_prk( self.server_handshake_traffic_secret.as_ref().unwrap() @@ -687,134 +513,15 @@ impl<'a> Session<'a> { hmac.update(&transcript_hash); hmac.verify(server_verify_data).unwrap(); - // Update hash for key computation - self.hash.update(server_finished_slice); - - // Derive application traffic secret, key, IV on client's side - // 1. Derive secret from "Handshake Secret" - let hkdf = Hkdf::::from_prk( - self.latest_secret.as_ref().unwrap() - ).unwrap(); - - let empty_hash = Sha384::new().chain(""); - let derived_secret = derive_secret(&hkdf, "derived", empty_hash); - - // 2. HKDF-extract "Master Secret" - let zero_ikm: GenericArray::OutputSize> - = Default::default(); - let (master_secret, master_secret_hkdf) = Hkdf::::extract( - Some(&derived_secret), - &zero_ikm - ); - - // Replace latest secret with "master_secret" - self.latest_secret.replace( - Vec::from_slice(&master_secret).unwrap() - ); - - // 3. Get application traffic secret - let client_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "c ap traffic", - self.hash.get_sha384_clone().unwrap() - ); - - let server_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "s ap traffic", - self.hash.get_sha384_clone().unwrap() - ); - - self.client_application_traffic_secret.replace( - Vec::from_slice(&client_application_traffic_secret).unwrap() - ); - self.server_application_traffic_secret.replace( - Vec::from_slice(&server_application_traffic_secret).unwrap() - ); - - // 4. Replace cipher and IV - let client_application_traffic_hkdf = Hkdf::::from_prk( - &client_application_traffic_secret - ).unwrap(); - let server_application_traffic_hkdf = Hkdf::::from_prk( - &server_application_traffic_secret - ).unwrap(); - - // Init key and IV holders - let cipher_suite = self.client_handshake_cipher.as_ref().unwrap().get_cipher_suite_type(); - - let (mut client_key_holder, mut client_iv_holder, - mut server_key_holder, mut server_iv_holder): - (Vec::, Vec::, Vec::, Vec::) = - match cipher_suite { - CipherSuite::TLS_AES_256_GCM_SHA384 => { - ( - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - // TLS_AES_128_CCM_8_SHA256 is not offered - // Only TLS_AES_256_GCM_SHA384 should have SHA384 as hash - _ => unreachable!() - }; - - // Derive Key and IV for both server and client - hkdf_expand_label( - &client_application_traffic_hkdf, - "key", - "", - &mut client_key_holder - ); - hkdf_expand_label( - &client_application_traffic_hkdf, - "iv", - "", - &mut client_iv_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "key", - "", - &mut server_key_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "iv", - "", - &mut server_iv_holder - ); - - // Store IV/nonce - self.client_application_nonce.replace(client_iv_holder); - self.server_application_nonce.replace(server_iv_holder); - - // Instantiate new ciphers - match cipher_suite { - CipherSuite::TLS_AES_256_GCM_SHA384 => { - self.client_application_cipher.replace( - Cipher::Aes256Gcm { - aes256gcm: Aes256Gcm::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Aes256Gcm { - aes256gcm: Aes256Gcm::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - _ => unreachable!() - } - } else { unreachable!() }; - // Hash was updated for key computation + + // Update hash for key computation + self.hash.update(server_finished_slice); + + // Compute application keys + self.find_application_keying_info(); // At last, update client state self.state = TlsState::SERVER_COMPLETED; @@ -960,302 +667,67 @@ impl<'a> Session<'a> { self.hash.update(server_finished_slice); // Key calculation + self.find_application_keying_info(); + + // Change state + self.state = TlsState::SERVER_WAIT_FINISHED; + } + + pub(crate) fn server_update_for_wait_finished( + &mut self, + client_finished_slice: &[u8], + client_verify_data: &[u8], + ) { + // Take hash from session 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::::from_prk( - // TLS requires the removal of secret if such secret is not of any use - // Replace "latest_secret" with None - self.latest_secret.as_ref().unwrap() + self.client_handshake_traffic_secret.as_ref().unwrap() ).unwrap(); - let empty_hash = Sha256::new().chain(""); - let derived_secret = derive_secret(&hkdf, "derived", empty_hash); + // Compute finished_key + let mut okm: GenericArray::::OutputSize> = + Default::default(); + hkdf_expand_label(&hkdf, "finished", "", &mut okm); - // 2. HKDF-extract "Master Secret" - let zero_ikm: GenericArray::OutputSize> - = Default::default(); - let (master_secret, master_secret_hkdf) = Hkdf::::extract( - Some(&derived_secret), - &zero_ikm - ); + // Get transcript hash + let transcript_hash = sha256.finalize(); - // Replace latest secret with "master_secret" - self.latest_secret.replace( - Vec::from_slice(&master_secret).unwrap() - ); + // Compute verify_data + let mut hmac = Hmac::::new_varkey(&okm).unwrap(); + hmac.update(&transcript_hash); + hmac.verify(client_verify_data).unwrap(); - // 3. Get application traffic secret - let client_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "c ap traffic", - self.hash.get_sha256_clone().unwrap() - ); - - let server_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "s ap traffic", - self.hash.get_sha256_clone().unwrap() - ); - - self.client_application_traffic_secret.replace( - Vec::from_slice(&client_application_traffic_secret).unwrap() - ); - self.server_application_traffic_secret.replace( - Vec::from_slice(&server_application_traffic_secret).unwrap() - ); - - // 4. Replace cipher and IV - let client_application_traffic_hkdf = Hkdf::::from_prk( - &client_application_traffic_secret - ).unwrap(); - let server_application_traffic_hkdf = Hkdf::::from_prk( - &server_application_traffic_secret - ).unwrap(); - - // Init key and IV holders - let cipher_suite = self.client_handshake_cipher.as_ref().unwrap().get_cipher_suite_type(); - - let (mut client_key_holder, mut client_iv_holder, - mut server_key_holder, mut server_iv_holder): - (Vec::, Vec::, Vec::, Vec::) = - match cipher_suite { - CipherSuite::TLS_AES_128_GCM_SHA256 => { - ( - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { - ( - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - CipherSuite::TLS_AES_128_CCM_SHA256 => { - ( - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 16]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - // TLS_AES_128_CCM_8_SHA256 is not offered - // TLS_AES_256_GCM_SHA384 should not have SHA256 as hash - _ => unreachable!() - }; - - // Derive Key and IV for both server and client - hkdf_expand_label( - &client_application_traffic_hkdf, - "key", - "", - &mut client_key_holder - ); - hkdf_expand_label( - &client_application_traffic_hkdf, - "iv", - "", - &mut client_iv_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "key", - "", - &mut server_key_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "iv", - "", - &mut server_iv_holder - ); - - // Store IV/nonce - self.client_application_nonce.replace(client_iv_holder); - self.server_application_nonce.replace(server_iv_holder); - - // Instantiate new ciphers - match cipher_suite { - CipherSuite::TLS_AES_128_GCM_SHA256 => { - self.client_application_cipher.replace( - Cipher::Aes128Gcm { - aes128gcm: Aes128Gcm::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Aes128Gcm { - aes128gcm: Aes128Gcm::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { - self.client_application_cipher.replace( - Cipher::Chacha20poly1305 { - chacha20poly1305: ChaCha20Poly1305::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Chacha20poly1305 { - chacha20poly1305: ChaCha20Poly1305::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - CipherSuite::TLS_AES_128_CCM_SHA256 => { - self.client_application_cipher.replace( - Cipher::Ccm { - ccm: Aes128Ccm::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Ccm { - ccm: Aes128Ccm::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - _ => unreachable!() - } } 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::::from_prk( - self.latest_secret.as_ref().unwrap() + self.client_handshake_traffic_secret.as_ref().unwrap() ).unwrap(); - let empty_hash = Sha384::new().chain(""); - let derived_secret = derive_secret(&hkdf, "derived", empty_hash); + // Compute finished_key + let mut okm: GenericArray::::OutputSize> = + Default::default(); + hkdf_expand_label(&hkdf, "finished", "", &mut okm); - // 2. HKDF-extract "Master Secret" - let zero_ikm: GenericArray::OutputSize> - = Default::default(); - let (master_secret, master_secret_hkdf) = Hkdf::::extract( - Some(&derived_secret), - &zero_ikm - ); + // Get transcript hash + let transcript_hash = sha384.finalize(); - // Replace latest secret with "master_secret" - self.latest_secret.replace( - Vec::from_slice(&master_secret).unwrap() - ); - - // 3. Get application traffic secret - let client_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "c ap traffic", - self.hash.get_sha384_clone().unwrap() - ); - - let server_application_traffic_secret = derive_secret( - &master_secret_hkdf, - "s ap traffic", - self.hash.get_sha384_clone().unwrap() - ); - - self.client_application_traffic_secret.replace( - Vec::from_slice(&client_application_traffic_secret).unwrap() - ); - self.server_application_traffic_secret.replace( - Vec::from_slice(&server_application_traffic_secret).unwrap() - ); - - // 4. Replace cipher and IV - let client_application_traffic_hkdf = Hkdf::::from_prk( - &client_application_traffic_secret - ).unwrap(); - let server_application_traffic_hkdf = Hkdf::::from_prk( - &server_application_traffic_secret - ).unwrap(); - - // Init key and IV holders - let cipher_suite = self.client_handshake_cipher.as_ref().unwrap().get_cipher_suite_type(); - - let (mut client_key_holder, mut client_iv_holder, - mut server_key_holder, mut server_iv_holder): - (Vec::, Vec::, Vec::, Vec::) = - match cipher_suite { - CipherSuite::TLS_AES_256_GCM_SHA384 => { - ( - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap(), - Vec::from_slice(&[0; 32]).unwrap(), - Vec::from_slice(&[0; 12]).unwrap() - ) - }, - // TLS_AES_128_CCM_8_SHA256 is not offered - // Only TLS_AES_256_GCM_SHA384 should have SHA384 as hash - _ => unreachable!() - }; - - // Derive Key and IV for both server and client - hkdf_expand_label( - &client_application_traffic_hkdf, - "key", - "", - &mut client_key_holder - ); - hkdf_expand_label( - &client_application_traffic_hkdf, - "iv", - "", - &mut client_iv_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "key", - "", - &mut server_key_holder - ); - hkdf_expand_label( - &server_application_traffic_hkdf, - "iv", - "", - &mut server_iv_holder - ); - - // Store IV/nonce - self.client_application_nonce.replace(client_iv_holder); - self.server_application_nonce.replace(server_iv_holder); - - // Instantiate new ciphers - match cipher_suite { - CipherSuite::TLS_AES_256_GCM_SHA384 => { - self.client_application_cipher.replace( - Cipher::Aes256Gcm { - aes256gcm: Aes256Gcm::new( - &GenericArray::from_slice(&client_key_holder) - ) - } - ); - self.server_application_cipher.replace( - Cipher::Aes256Gcm { - aes256gcm: Aes256Gcm::new( - &GenericArray::from_slice(&server_key_holder) - ) - } - ); - }, - _ => unreachable!() - } + // Compute verify_data using HMAC + let mut hmac = Hmac::::new_varkey(&okm).unwrap(); + hmac.update(&transcript_hash); + hmac.verify(client_verify_data).unwrap(); } else { unreachable!() }; + + // Update hash for key computation + self.hash.update(client_finished_slice); + + // At last, update client state + self.state = TlsState::SERVER_CONNECTED; + + // Reset sequence number at the end of handshakes + self.server_sequence_number = 0; + self.client_sequence_number = 0; } fn find_handshake_keying_info(&mut self, shared_secret_bytes: &[u8], cipher_suite: CipherSuite) { @@ -1579,6 +1051,306 @@ impl<'a> Session<'a> { self.client_sequence_number = 0; } + fn find_application_keying_info(&mut self) { + // Key calculation + 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::::from_prk( + // TLS requires the removal of secret if such secret is not of any use + // Replace "latest_secret" with None + self.latest_secret.as_ref().unwrap() + ).unwrap(); + + let empty_hash = Sha256::new().chain(""); + let derived_secret = derive_secret(&hkdf, "derived", empty_hash); + + // 2. HKDF-extract "Master Secret" + let zero_ikm: GenericArray::OutputSize> + = Default::default(); + let (master_secret, master_secret_hkdf) = Hkdf::::extract( + Some(&derived_secret), + &zero_ikm + ); + + // Replace latest secret with "master_secret" + self.latest_secret.replace( + Vec::from_slice(&master_secret).unwrap() + ); + + // 3. Get application traffic secret + let client_application_traffic_secret = derive_secret( + &master_secret_hkdf, + "c ap traffic", + self.hash.get_sha256_clone().unwrap() + ); + + let server_application_traffic_secret = derive_secret( + &master_secret_hkdf, + "s ap traffic", + self.hash.get_sha256_clone().unwrap() + ); + + self.client_application_traffic_secret.replace( + Vec::from_slice(&client_application_traffic_secret).unwrap() + ); + self.server_application_traffic_secret.replace( + Vec::from_slice(&server_application_traffic_secret).unwrap() + ); + + // 4. Replace cipher and IV + let client_application_traffic_hkdf = Hkdf::::from_prk( + &client_application_traffic_secret + ).unwrap(); + let server_application_traffic_hkdf = Hkdf::::from_prk( + &server_application_traffic_secret + ).unwrap(); + + // Init key and IV holders + let cipher_suite = self.client_handshake_cipher.as_ref().unwrap().get_cipher_suite_type(); + + let (mut client_key_holder, mut client_iv_holder, + mut server_key_holder, mut server_iv_holder): + (Vec::, Vec::, Vec::, Vec::) = + match cipher_suite { + CipherSuite::TLS_AES_128_GCM_SHA256 => { + ( + Vec::from_slice(&[0; 16]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap(), + Vec::from_slice(&[0; 16]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap() + ) + }, + CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { + ( + Vec::from_slice(&[0; 32]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap(), + Vec::from_slice(&[0; 32]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap() + ) + }, + CipherSuite::TLS_AES_128_CCM_SHA256 => { + ( + Vec::from_slice(&[0; 16]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap(), + Vec::from_slice(&[0; 16]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap() + ) + }, + // TLS_AES_128_CCM_8_SHA256 is not offered + // TLS_AES_256_GCM_SHA384 should not have SHA256 as hash + _ => unreachable!() + }; + + // Derive Key and IV for both server and client + hkdf_expand_label( + &client_application_traffic_hkdf, + "key", + "", + &mut client_key_holder + ); + hkdf_expand_label( + &client_application_traffic_hkdf, + "iv", + "", + &mut client_iv_holder + ); + hkdf_expand_label( + &server_application_traffic_hkdf, + "key", + "", + &mut server_key_holder + ); + hkdf_expand_label( + &server_application_traffic_hkdf, + "iv", + "", + &mut server_iv_holder + ); + + // Store IV/nonce + self.client_application_nonce.replace(client_iv_holder); + self.server_application_nonce.replace(server_iv_holder); + + // Instantiate new ciphers + match cipher_suite { + CipherSuite::TLS_AES_128_GCM_SHA256 => { + self.client_application_cipher.replace( + Cipher::Aes128Gcm { + aes128gcm: Aes128Gcm::new( + &GenericArray::from_slice(&client_key_holder) + ) + } + ); + self.server_application_cipher.replace( + Cipher::Aes128Gcm { + aes128gcm: Aes128Gcm::new( + &GenericArray::from_slice(&server_key_holder) + ) + } + ); + }, + CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => { + self.client_application_cipher.replace( + Cipher::Chacha20poly1305 { + chacha20poly1305: ChaCha20Poly1305::new( + &GenericArray::from_slice(&client_key_holder) + ) + } + ); + self.server_application_cipher.replace( + Cipher::Chacha20poly1305 { + chacha20poly1305: ChaCha20Poly1305::new( + &GenericArray::from_slice(&server_key_holder) + ) + } + ); + }, + CipherSuite::TLS_AES_128_CCM_SHA256 => { + self.client_application_cipher.replace( + Cipher::Ccm { + ccm: Aes128Ccm::new( + &GenericArray::from_slice(&client_key_holder) + ) + } + ); + self.server_application_cipher.replace( + Cipher::Ccm { + ccm: Aes128Ccm::new( + &GenericArray::from_slice(&server_key_holder) + ) + } + ); + }, + _ => unreachable!() + } + } 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::::from_prk( + self.latest_secret.as_ref().unwrap() + ).unwrap(); + + let empty_hash = Sha384::new().chain(""); + let derived_secret = derive_secret(&hkdf, "derived", empty_hash); + + // 2. HKDF-extract "Master Secret" + let zero_ikm: GenericArray::OutputSize> + = Default::default(); + let (master_secret, master_secret_hkdf) = Hkdf::::extract( + Some(&derived_secret), + &zero_ikm + ); + + // Replace latest secret with "master_secret" + self.latest_secret.replace( + Vec::from_slice(&master_secret).unwrap() + ); + + // 3. Get application traffic secret + let client_application_traffic_secret = derive_secret( + &master_secret_hkdf, + "c ap traffic", + self.hash.get_sha384_clone().unwrap() + ); + + let server_application_traffic_secret = derive_secret( + &master_secret_hkdf, + "s ap traffic", + self.hash.get_sha384_clone().unwrap() + ); + + self.client_application_traffic_secret.replace( + Vec::from_slice(&client_application_traffic_secret).unwrap() + ); + self.server_application_traffic_secret.replace( + Vec::from_slice(&server_application_traffic_secret).unwrap() + ); + + // 4. Replace cipher and IV + let client_application_traffic_hkdf = Hkdf::::from_prk( + &client_application_traffic_secret + ).unwrap(); + let server_application_traffic_hkdf = Hkdf::::from_prk( + &server_application_traffic_secret + ).unwrap(); + + // Init key and IV holders + let cipher_suite = self.client_handshake_cipher.as_ref().unwrap().get_cipher_suite_type(); + + let (mut client_key_holder, mut client_iv_holder, + mut server_key_holder, mut server_iv_holder): + (Vec::, Vec::, Vec::, Vec::) = + match cipher_suite { + CipherSuite::TLS_AES_256_GCM_SHA384 => { + ( + Vec::from_slice(&[0; 32]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap(), + Vec::from_slice(&[0; 32]).unwrap(), + Vec::from_slice(&[0; 12]).unwrap() + ) + }, + // TLS_AES_128_CCM_8_SHA256 is not offered + // Only TLS_AES_256_GCM_SHA384 should have SHA384 as hash + _ => unreachable!() + }; + + // Derive Key and IV for both server and client + hkdf_expand_label( + &client_application_traffic_hkdf, + "key", + "", + &mut client_key_holder + ); + hkdf_expand_label( + &client_application_traffic_hkdf, + "iv", + "", + &mut client_iv_holder + ); + hkdf_expand_label( + &server_application_traffic_hkdf, + "key", + "", + &mut server_key_holder + ); + hkdf_expand_label( + &server_application_traffic_hkdf, + "iv", + "", + &mut server_iv_holder + ); + + // Store IV/nonce + self.client_application_nonce.replace(client_iv_holder); + self.server_application_nonce.replace(server_iv_holder); + + // Instantiate new ciphers + match cipher_suite { + CipherSuite::TLS_AES_256_GCM_SHA384 => { + self.client_application_cipher.replace( + Cipher::Aes256Gcm { + aes256gcm: Aes256Gcm::new( + &GenericArray::from_slice(&client_key_holder) + ) + } + ); + self.server_application_cipher.replace( + Cipher::Aes256Gcm { + aes256gcm: Aes256Gcm::new( + &GenericArray::from_slice(&server_key_holder) + ) + } + ); + }, + _ => unreachable!() + } + + } else { + unreachable!() + }; + } + pub(crate) fn verify_session_id_echo(&self, session_id_echo: &[u8]) -> bool { if let Some(session_id_inner) = self.session_id { session_id_inner == session_id_echo @@ -2156,14 +1928,6 @@ impl<'a> Session<'a> { ) } - pub(crate) fn increment_client_sequence_number(&mut self) { - self.client_sequence_number += 1; - } - - pub(crate) fn increment_server_sequence_number(&mut self) { - self.server_sequence_number += 1; - } - pub(crate) fn increment_local_sequence_number(&mut self) { match self.role { TlsRole::Client => { diff --git a/src/tls.rs b/src/tls.rs index 4931821..f773539 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -650,13 +650,19 @@ impl<'s> TlsSocket<'s> { self.send_application_slice(sockets, &mut inner_plaintext.clone())?; let inner_plaintext_length = inner_plaintext.len(); - // { - // self.session.borrow_mut() - // .server_update_for_server_finished(&inner_plaintext[..(inner_plaintext_length-1)]); - // } + { + self.session.borrow_mut() + .server_update_for_server_finished(&inner_plaintext[..(inner_plaintext_length-1)]); + } } - // Other states regarding server role + // There is no need to care about handshake if it was completed + // This is to prevent accidental dequeing of application data + TlsState::SERVER_CONNECTED => { + return Ok(true); + } + + // Other states _ => {} } @@ -728,7 +734,7 @@ impl<'s> TlsSocket<'s> { &associated_data, &mut app_data ).unwrap(); - session.increment_server_sequence_number(); + session.increment_remote_sequence_number(); } // Discard last 16 bytes (auth tag) @@ -1387,6 +1393,32 @@ impl<'s> TlsSocket<'s> { log::info!("Processed client hello") } + }, + + TlsState::SERVER_WAIT_FINISHED => { + // Ensure that it is Finished + let might_be_client_finished = repr.handshake.take().unwrap(); + if might_be_client_finished.get_msg_type() != HandshakeType::Finished { + // Process the other handshakes in "handshake_vec" + todo!() + } + + // Take out the portion for server Finished + // Length of handshake header is 4 + let (_handshake_slice, client_finished_slice) = + take::<_, _, (&[u8], ErrorKind)>( + might_be_client_finished.length + 4 + )(handshake_slice) + .map_err(|_| Error::Unrecognized)?; + + // Perform verification, update TLS state if successful + // Update traffic secret, reset sequence number + self.session.borrow_mut() + .server_update_for_wait_finished( + client_finished_slice, + might_be_client_finished.get_verify_data().unwrap() + ); + log::info!("Received client FIN"); } _ => {}, @@ -1450,7 +1482,8 @@ impl<'s> TlsSocket<'s> { // If the handshake is not completed, do not pull bytes out of the buffer // through TlsSocket.recv_slice() // Handshake recv should be through TCPSocket directly. - if session.get_tls_state() != TlsState::CLIENT_CONNECTED { + if session.get_tls_state() != TlsState::CLIENT_CONNECTED && + session.get_tls_state() != TlsState::SERVER_CONNECTED { return Ok(0); } @@ -1498,7 +1531,7 @@ impl<'s> TlsSocket<'s> { &associated_data, &mut data[5..recv_slice_size] ).unwrap(); - session.increment_server_sequence_number(); + session.increment_remote_sequence_number(); // Make sure it is application data let (content_type, padding_start_index) = @@ -1533,7 +1566,8 @@ impl<'s> TlsSocket<'s> { // through TlsSocket.send_slice() // Handshake send should be through TCPSocket directly. let mut session = self.session.borrow_mut(); - if session.get_tls_state() != TlsState::CLIENT_CONNECTED { + if session.get_tls_state() != TlsState::CLIENT_CONNECTED && + session.get_tls_state() != TlsState::SERVER_CONNECTED { return Ok(()); } @@ -1560,7 +1594,7 @@ impl<'s> TlsSocket<'s> { &associated_data, &mut vec ).unwrap(); - session.increment_client_sequence_number(); + session.increment_local_sequence_number(); let mut tcp_socket = sockets.get::(self.tcp_handle); if !tcp_socket.can_send() {