session: add client finished processing
This commit is contained in:
parent
4b644aafe9
commit
c50894ad7f
936
src/session.rs
936
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::<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 => {
|
||||
|
|
54
src/tls.rs
54
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::<TcpSocket>(self.tcp_handle);
|
||||
if !tcp_socket.can_send() {
|
||||
|
|
Loading…
Reference in New Issue