session: add client finished processing

This commit is contained in:
occheung 2020-12-01 16:03:57 +08:00
parent 4b644aafe9
commit c50894ad7f
2 changed files with 394 additions and 596 deletions

View File

@ -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::<Sha256>::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<u8, <Sha256 as FixedOutput>::OutputSize>
= Default::default();
let (master_secret, master_secret_hkdf) = Hkdf::<Sha256>::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::<Sha256>::from_prk(
&client_application_traffic_secret
).unwrap();
let server_application_traffic_hkdf = Hkdf::<Sha256>::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::<u8, U64>, Vec::<u8, U12>, Vec::<u8, U64>, Vec::<u8, U12>) =
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::<Sha384>::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::<Sha384>::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<u8, <Sha384 as FixedOutput>::OutputSize>
= Default::default();
let (master_secret, master_secret_hkdf) = Hkdf::<Sha384>::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::<Sha384>::from_prk(
&client_application_traffic_secret
).unwrap();
let server_application_traffic_hkdf = Hkdf::<Sha384>::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::<u8, U64>, Vec::<u8, U12>, Vec::<u8, U64>, Vec::<u8, U12>) =
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::<Sha256>::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::<u8, <Sha256 as Digest>::OutputSize> =
Default::default();
hkdf_expand_label(&hkdf, "finished", "", &mut okm);
// 2. HKDF-extract "Master Secret"
let zero_ikm: GenericArray<u8, <Sha256 as FixedOutput>::OutputSize>
= Default::default();
let (master_secret, master_secret_hkdf) = Hkdf::<Sha256>::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::<Sha256>::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::<Sha256>::from_prk(
&client_application_traffic_secret
).unwrap();
let server_application_traffic_hkdf = Hkdf::<Sha256>::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::<u8, U64>, Vec::<u8, U12>, Vec::<u8, U64>, Vec::<u8, U12>) =
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::<Sha384>::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::<u8, <Sha384 as Digest>::OutputSize> =
Default::default();
hkdf_expand_label(&hkdf, "finished", "", &mut okm);
// 2. HKDF-extract "Master Secret"
let zero_ikm: GenericArray<u8, <Sha384 as FixedOutput>::OutputSize>
= Default::default();
let (master_secret, master_secret_hkdf) = Hkdf::<Sha384>::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::<Sha384>::from_prk(
&client_application_traffic_secret
).unwrap();
let server_application_traffic_hkdf = Hkdf::<Sha384>::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::<u8, U64>, Vec::<u8, U12>, Vec::<u8, U64>, Vec::<u8, U12>) =
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::<Sha384>::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::<Sha256>::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<u8, <Sha256 as FixedOutput>::OutputSize>
= Default::default();
let (master_secret, master_secret_hkdf) = Hkdf::<Sha256>::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::<Sha256>::from_prk(
&client_application_traffic_secret
).unwrap();
let server_application_traffic_hkdf = Hkdf::<Sha256>::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::<u8, U64>, Vec::<u8, U12>, Vec::<u8, U64>, Vec::<u8, U12>) =
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::<Sha384>::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<u8, <Sha384 as FixedOutput>::OutputSize>
= Default::default();
let (master_secret, master_secret_hkdf) = Hkdf::<Sha384>::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::<Sha384>::from_prk(
&client_application_traffic_secret
).unwrap();
let server_application_traffic_hkdf = Hkdf::<Sha384>::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::<u8, U64>, Vec::<u8, U12>, Vec::<u8, U64>, Vec::<u8, U12>) =
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 => {

View File

@ -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::<TcpSocket>(self.tcp_handle);
if !tcp_socket.can_send() {