session: calculate ap key
This commit is contained in:
parent
73f95555eb
commit
4b644aafe9
350
src/session.rs
350
src/session.rs
@ -685,8 +685,6 @@ impl<'a> Session<'a> {
|
||||
// Compute verify_data using HMAC
|
||||
let mut hmac = Hmac::<Sha384>::new_varkey(&okm).unwrap();
|
||||
hmac.update(&transcript_hash);
|
||||
log::info!("HMAC: {:?}", hmac);
|
||||
log::info!("Received data: {:?}", server_verify_data);
|
||||
hmac.verify(server_verify_data).unwrap();
|
||||
|
||||
// Update hash for key computation
|
||||
@ -954,6 +952,312 @@ impl<'a> Session<'a> {
|
||||
self.hash.update(certificate_verify_slice);
|
||||
}
|
||||
|
||||
pub(crate) fn server_update_for_server_finished(
|
||||
&mut self,
|
||||
server_finished_slice: &[u8]
|
||||
) {
|
||||
// Update hash for key computation
|
||||
self.hash.update(server_finished_slice);
|
||||
|
||||
// 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!()
|
||||
};
|
||||
}
|
||||
|
||||
fn find_handshake_keying_info(&mut self, shared_secret_bytes: &[u8], cipher_suite: CipherSuite) {
|
||||
// Ensure that it is 32-bytes long
|
||||
assert!(shared_secret_bytes.len() == 32);
|
||||
@ -1596,6 +1900,48 @@ impl<'a> Session<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_server_finished_verify_data(&self) -> Vec<u8, U64> {
|
||||
if let Ok(sha256) = self.hash.get_sha256_clone() {
|
||||
let hkdf = Hkdf::<Sha256>::from_prk(
|
||||
self.server_handshake_traffic_secret.as_ref().unwrap()
|
||||
).unwrap();
|
||||
|
||||
// Compute finished_key
|
||||
let mut okm: GenericArray::<u8, <Sha256 as Digest>::OutputSize> =
|
||||
Default::default();
|
||||
hkdf_expand_label(&hkdf, "finished", "", &mut okm);
|
||||
|
||||
// Get transcript hash
|
||||
let transcript_hash = sha256.finalize();
|
||||
|
||||
// Compute verify_data, store in heapless vec
|
||||
let mut hmac = Hmac::<Sha256>::new_varkey(&okm).unwrap();
|
||||
hmac.update(&transcript_hash);
|
||||
Vec::from_slice(&hmac.finalize().into_bytes()).unwrap()
|
||||
|
||||
} else if let Ok(sha384) = self.hash.get_sha384_clone() {
|
||||
let hkdf = Hkdf::<Sha384>::from_prk(
|
||||
self.server_handshake_traffic_secret.as_ref().unwrap()
|
||||
).unwrap();
|
||||
|
||||
// Compute finished_key
|
||||
let mut okm: GenericArray::<u8, <Sha384 as Digest>::OutputSize> =
|
||||
Default::default();
|
||||
hkdf_expand_label(&hkdf, "finished", "", &mut okm);
|
||||
|
||||
// Get transcript hash
|
||||
let transcript_hash = sha384.finalize();
|
||||
|
||||
// Compute verify_data, store in heapless vec
|
||||
let mut hmac = Hmac::<Sha384>::new_varkey(&okm).unwrap();
|
||||
hmac.update(&transcript_hash);
|
||||
Vec::from_slice(&hmac.finalize().into_bytes()).unwrap()
|
||||
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_cipher_suite_type(&self) -> Option<CipherSuite> {
|
||||
self.client_handshake_cipher.as_ref().map(|cipher| cipher.get_cipher_suite_type())
|
||||
}
|
||||
|
23
src/tls.rs
23
src/tls.rs
@ -631,6 +631,29 @@ impl<'s> TlsSocket<'s> {
|
||||
&inner_plaintext[..(inner_plaintext_length-1)]
|
||||
);
|
||||
}
|
||||
|
||||
// Construct and send server finished
|
||||
let inner_plaintext: HeaplessVec<u8, U64> = {
|
||||
let verify_data = self.session.borrow()
|
||||
.get_server_finished_verify_data();
|
||||
let mut handshake_header: [u8; 4] = [20, 0, 0, 0];
|
||||
NetworkEndian::write_u24(
|
||||
&mut handshake_header[1..4],
|
||||
u32::try_from(verify_data.len()).unwrap()
|
||||
);
|
||||
let mut buffer = HeaplessVec::from_slice(&handshake_header).unwrap();
|
||||
buffer.extend_from_slice(&verify_data).unwrap();
|
||||
// Inner plaintext: record type
|
||||
buffer.push(22).unwrap();
|
||||
buffer
|
||||
};
|
||||
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)]);
|
||||
// }
|
||||
}
|
||||
|
||||
// Other states regarding server role
|
||||
|
Loading…
Reference in New Issue
Block a user