use super::*;
impl Connection {
pub fn noxtls_configure_tls12_key_schedule(
&mut self,
suite: CipherSuite,
client_random: &[u8; 32],
server_random: &[u8; 32],
pre_master_secret: &[u8],
) -> Result<()> {
if !matches!(self.version, TlsVersion::Tls12 | TlsVersion::Dtls12) {
return Err(Error::StateError(
"tls12 key schedule requires a TLS 1.2/DTLS 1.2 connection",
));
}
if pre_master_secret.is_empty() {
return Err(Error::InvalidLength(
"tls12 pre-master secret must not be empty",
));
}
if suite.noxtls_tls12_aead_key_len().is_none()
&& suite.noxtls_tls12_cbc_key_len().is_none()
&& suite.noxtls_tls12_chacha20_poly1305_key_len().is_none()
{
return Err(Error::UnsupportedFeature(
"tls12 key schedule currently supports AEAD, CBC, and ChaCha20 ECDHE suites only",
));
}
self.noxtls_selected_cipher_suite = Some(suite);
self.noxtls_rebuild_transcript_hash_from_selected_suite();
self.tls12_client_random = Some(*client_random);
self.tls12_server_random = Some(*server_random);
self.tls12_pre_master_secret = Some(pre_master_secret.to_vec());
self.tls12_master_secret = None;
self.tls12_extended_master_secret_session_hash = None;
self.client_sequence = 0;
self.server_sequence = 0;
Ok(())
}
pub fn noxtls_set_tls12_pre_master_secret(&mut self, pre_master_secret: &[u8]) -> Result<()> {
if !matches!(self.version, TlsVersion::Tls12 | TlsVersion::Dtls12) {
return Err(Error::StateError(
"tls12 pre-master secret requires a TLS 1.2/DTLS 1.2 connection",
));
}
if pre_master_secret.is_empty() {
return Err(Error::InvalidLength(
"tls12 pre-master secret must not be empty",
));
}
self.tls12_pre_master_secret = Some(pre_master_secret.to_vec());
self.tls12_master_secret = None;
self.tls12_extended_master_secret_session_hash = None;
Ok(())
}
pub fn noxtls_set_tls12_rsa_pre_master_secret_from_encrypted(
&mut self,
private_key: &RsaPrivateKey,
encrypted_pre_master_secret: &[u8],
fallback_pre_master_secret: &[u8; 48],
) -> Result<bool> {
if !matches!(self.version, TlsVersion::Tls12 | TlsVersion::Dtls12) {
return Err(Error::StateError(
"tls12 rsa pre-master secret requires a TLS 1.2/DTLS 1.2 connection",
));
}
if let Some(suite) = self.noxtls_selected_cipher_suite {
if noxtls_tls12_key_exchange_kind(suite)? != Tls12KeyExchangeKind::StaticRsa {
return Err(Error::StateError(
"tls12 rsa pre-master secret requires an RSA key-transport cipher suite",
));
}
}
let decrypted = noxtls_rsaes_pkcs1_v15_decrypt(private_key, encrypted_pre_master_secret);
let expected_version = noxtls_legacy_wire_version(TlsVersion::Tls12);
let mut accepted = false;
let pre_master_secret = match decrypted {
Ok(secret)
if secret.len() == 48
&& secret[0] == expected_version[0]
&& secret[1] == expected_version[1] =>
{
accepted = true;
secret
}
_ => fallback_pre_master_secret.to_vec(),
};
self.noxtls_set_tls12_pre_master_secret(&pre_master_secret)?;
Ok(accepted)
}
pub fn noxtls_install_tls12_rsa_pre_master_secret_from_client_key_exchange(
&mut self,
private_key: &RsaPrivateKey,
fallback_pre_master_secret: &[u8; 48],
) -> Result<bool> {
let encrypted =
self.tls12_rsa_encrypted_pre_master_secret
.clone()
.ok_or(Error::StateError(
"tls12 rsa encrypted pre-master secret is not available",
))?;
self.noxtls_set_tls12_rsa_pre_master_secret_from_encrypted(
private_key,
&encrypted,
fallback_pre_master_secret,
)
}
pub fn noxtls_install_tls12_dhe_pre_master_secret_from_server_key_exchange(
&mut self,
local_private_key: &[u8],
) -> Result<()> {
let prime = self
.tls12_dhe_prime
.as_ref()
.ok_or(Error::StateError("tls12 dhe prime is not available"))?;
let server_public = self
.tls12_dhe_server_public_key
.as_ref()
.ok_or(Error::StateError(
"tls12 dhe server public key is not available",
))?;
let pre_master_secret =
noxtls_ffdhe_shared_secret(local_private_key, server_public, prime)?;
self.noxtls_set_tls12_pre_master_secret(&pre_master_secret)
}
pub fn noxtls_install_tls12_dhe_pre_master_secret_from_client_key_exchange(
&mut self,
local_private_key: &[u8],
) -> Result<()> {
let prime = self
.tls12_dhe_prime
.as_ref()
.ok_or(Error::StateError("tls12 dhe prime is not available"))?;
let client_public = self
.tls12_dhe_client_public_key
.as_ref()
.ok_or(Error::StateError(
"tls12 dhe client public key is not available",
))?;
let pre_master_secret =
noxtls_ffdhe_shared_secret(local_private_key, client_public, prime)?;
self.noxtls_set_tls12_pre_master_secret(&pre_master_secret)
}
pub fn noxtls_build_tls12_psk_pre_master_secret(psk: &[u8]) -> Result<Vec<u8>> {
if psk.is_empty() {
return Err(Error::InvalidLength("tls12 psk must not be empty"));
}
let psk_len = u16::try_from(psk.len())
.map_err(|_| Error::InvalidLength("tls12 psk must not exceed u16 length"))?;
let mut pre_master_secret = Vec::with_capacity(4 + (psk.len() * 2));
pre_master_secret.extend_from_slice(&psk_len.to_be_bytes());
pre_master_secret.resize(2 + psk.len(), 0);
pre_master_secret.extend_from_slice(&psk_len.to_be_bytes());
pre_master_secret.extend_from_slice(psk);
Ok(pre_master_secret)
}
pub fn noxtls_set_tls12_psk_pre_master_secret(&mut self, psk: &[u8]) -> Result<()> {
if !matches!(self.version, TlsVersion::Tls12 | TlsVersion::Dtls12) {
return Err(Error::StateError(
"tls12 psk pre-master secret requires a TLS 1.2/DTLS 1.2 connection",
));
}
if let Some(suite) = self.noxtls_selected_cipher_suite {
if suite != CipherSuite::TlsPskWithAes128Ccm8Sha256 {
return Err(Error::StateError(
"tls12 psk pre-master secret requires a PSK cipher suite",
));
}
}
let pre_master_secret = Self::noxtls_build_tls12_psk_pre_master_secret(psk)?;
self.noxtls_set_tls12_pre_master_secret(&pre_master_secret)
}
pub fn noxtls_tls12_master_secret(&self) -> Result<[u8; 48]> {
self.tls12_master_secret
.ok_or(Error::StateError("tls12 master secret is not installed"))
}
pub fn noxtls_enable_tls12_extended_master_secret(
&mut self,
session_hash: &[u8],
) -> Result<()> {
if !matches!(self.version, TlsVersion::Tls12 | TlsVersion::Dtls12) {
return Err(Error::StateError(
"tls12 extended master secret requires a TLS 1.2/DTLS 1.2 connection",
));
}
if session_hash.is_empty() {
return Err(Error::InvalidLength("tls12 session hash must not be empty"));
}
self.tls12_extended_master_secret_session_hash = Some(session_hash.to_vec());
self.tls12_master_secret = None;
Ok(())
}
pub fn noxtls_compute_finished_verify_data(&self) -> Result<Vec<u8>> {
let hash = self.noxtls_transcript_hash();
match self.version {
TlsVersion::Tls13 | TlsVersion::Dtls13 => {
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let traffic_secret = if self.tls_role == TlsRole::Server {
self.tls13_server_handshake_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 server handshake traffic secret must be installed before server finished",
))?
} else {
self.tls13_client_handshake_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 client handshake traffic secret must be installed before client finished",
))?
};
let finished_key = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
traffic_secret,
b"finished",
&[],
hash_len,
)?;
Ok(noxtls_finished_hmac_for_hash(
noxtls_hash_algorithm,
&finished_key,
&hash,
))
}
TlsVersion::Tls12 | TlsVersion::Dtls12 => {
let hash = self.noxtls_transcript_hash();
let secret = if let Some(master_secret) = self.tls12_master_secret.as_ref() {
master_secret.as_slice()
} else {
self.handshake_secret.as_ref().ok_or(Error::StateError(
"handshake secret must be available before finished",
))?
};
let label = if self.tls_role == TlsRole::Server {
b"server finished".as_slice()
} else {
b"client finished".as_slice()
};
noxtls_tls12_prf_for_hash(
self.noxtls_negotiated_hash_algorithm(),
secret,
label,
&hash,
12,
)
}
TlsVersion::Tls10 | TlsVersion::Tls11 => self.noxtls_compute_expected_finished(),
}
}
pub fn noxtls_update_tls13_traffic_keys(&mut self) -> Result<()> {
if !self.version.uses_tls13_handshake_semantics() {
return Err(Error::StateError(
"tls13 traffic key noxtls_update is only valid for TLS 1.3",
));
}
if self.state != HandshakeState::Finished {
return Err(Error::StateError(
"tls13 traffic key noxtls_update requires finished handshake",
));
}
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let client_secret = self
.tls13_client_application_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 application client traffic secret is not installed",
))?;
let server_secret = self
.tls13_server_application_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 application server traffic secret is not installed",
))?;
let next_client_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
client_secret,
b"traffic upd",
&[],
hash_len,
)?;
let next_server_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
server_secret,
b"traffic upd",
&[],
hash_len,
)?;
self.noxtls_install_tls13_record_protection_keys(
noxtls_hash_algorithm,
&next_client_secret,
&next_server_secret,
)?;
self.tls13_client_application_traffic_secret = Some(next_client_secret);
self.tls13_server_application_traffic_secret = Some(next_server_secret);
self.client_sequence = 0;
self.server_sequence = 0;
Ok(())
}
pub fn noxtls_update_tls13_client_application_read_keys(&mut self) -> Result<()> {
if !self.version.uses_tls13_handshake_semantics() {
return Err(Error::StateError(
"tls13 client traffic key update is only valid for TLS 1.3",
));
}
if self.state != HandshakeState::Finished {
return Err(Error::StateError(
"tls13 client traffic key update requires finished handshake",
));
}
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let client_secret = self
.tls13_client_application_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 application client traffic secret is not installed",
))?;
let next_client_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
client_secret,
b"traffic upd",
&[],
hash_len,
)?;
let suite = self.noxtls_selected_cipher_suite.ok_or(Error::StateError(
"cipher suite must be selected before tls13 record protection keys",
))?;
let key_len = suite
.noxtls_tls13_traffic_key_len()
.ok_or(Error::StateError(
"tls 1.3 record protection requires a tls 1.3 AEAD cipher suite",
))?;
let client_key_material = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&next_client_secret,
b"key",
&[],
key_len,
)?;
let mut client_key = [0_u8; 32];
client_key[..key_len].copy_from_slice(&client_key_material);
let client_iv: [u8; 12] = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&next_client_secret,
b"iv",
&[],
12,
)?
.try_into()
.expect("tls13 iv length should be 12");
self.client_write_key = Some(client_key);
self.client_write_iv = Some(client_iv);
self.tls13_client_application_traffic_secret = Some(next_client_secret);
self.client_sequence = 0;
self.noxtls_sync_dtls13_traffic_keys_from_record_protection_state();
Ok(())
}
pub fn noxtls_update_tls13_server_application_write_keys(&mut self) -> Result<()> {
if !self.version.uses_tls13_handshake_semantics() {
return Err(Error::StateError(
"tls13 server traffic key update is only valid for TLS 1.3",
));
}
if self.state != HandshakeState::Finished {
return Err(Error::StateError(
"tls13 server traffic key update requires finished handshake",
));
}
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let server_secret = self
.tls13_server_application_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 application server traffic secret is not installed",
))?;
let next_server_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
server_secret,
b"traffic upd",
&[],
hash_len,
)?;
let suite = self.noxtls_selected_cipher_suite.ok_or(Error::StateError(
"cipher suite must be selected before tls13 record protection keys",
))?;
let key_len = suite
.noxtls_tls13_traffic_key_len()
.ok_or(Error::StateError(
"tls 1.3 record protection requires a tls 1.3 AEAD cipher suite",
))?;
let server_key_material = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&next_server_secret,
b"key",
&[],
key_len,
)?;
let mut server_key = [0_u8; 32];
server_key[..key_len].copy_from_slice(&server_key_material);
let server_iv: [u8; 12] = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&next_server_secret,
b"iv",
&[],
12,
)?
.try_into()
.expect("tls13 iv length should be 12");
self.server_write_key = Some(server_key);
self.server_write_iv = Some(server_iv);
self.tls13_server_application_traffic_secret = Some(next_server_secret);
self.server_sequence = 0;
self.noxtls_sync_dtls13_traffic_keys_from_record_protection_state();
Ok(())
}
pub fn noxtls_tls13_resumption_master_secret(&self) -> Result<Vec<u8>> {
if !self.version.uses_tls13_handshake_semantics() {
return Err(Error::StateError(
"resumption master secret is only defined for TLS 1.3",
));
}
if self.state != HandshakeState::Finished {
return Err(Error::StateError(
"resumption master secret requires finished handshake state",
));
}
self.noxtls_tls13_resumption_master_secret
.clone()
.ok_or(Error::StateError(
"tls13 resumption master secret is not installed",
))
}
pub fn noxtls_derive_tls13_resumption_psk(&self, ticket_nonce: &[u8]) -> Result<Vec<u8>> {
if !self.version.uses_tls13_handshake_semantics() {
return Err(Error::StateError(
"resumption psk derivation is only defined for TLS 1.3",
));
}
if ticket_nonce.is_empty() {
return Err(Error::InvalidLength("ticket nonce must not be empty"));
}
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let resumption_master =
self.noxtls_tls13_resumption_master_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 resumption master secret is not installed",
))?;
noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
resumption_master,
b"resumption",
ticket_nonce,
hash_len,
)
}
pub(super) fn noxtls_derive_tls13_early_data_record_key_iv(
&self,
psk: &[u8],
) -> Result<(Vec<u8>, [u8; 12])> {
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let noxtls_transcript_hash =
noxtls_hash_bytes_for_algorithm(noxtls_hash_algorithm, &self.transcript);
let early_secret = noxtls_hkdf_extract_for_hash(noxtls_hash_algorithm, psk);
let client_early_traffic_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&early_secret,
b"c e traffic",
&noxtls_transcript_hash,
hash_len,
)?;
let key_len = self.noxtls_tls13_early_data_key_len();
let key = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&client_early_traffic_secret,
b"key",
&[],
key_len,
)?;
let iv: [u8; 12] = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&client_early_traffic_secret,
b"iv",
&[],
12,
)?
.try_into()
.expect("tls13 early-data iv should be 12 bytes");
Ok((key, iv))
}
pub(super) fn noxtls_install_traffic_keys(
&mut self,
noxtls_hash_algorithm: HashAlgorithm,
secret: &[u8],
noxtls_transcript_hash: &[u8],
) -> Result<()> {
let (client_key, server_key, client_iv, server_iv) = match self.version {
TlsVersion::Tls13 | TlsVersion::Dtls13 => {
let hash_len = noxtls_hash_algorithm.output_len();
let client_hs_traffic = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
secret,
b"c hs traffic",
noxtls_transcript_hash,
hash_len,
)?;
let server_hs_traffic = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
secret,
b"s hs traffic",
noxtls_transcript_hash,
hash_len,
)?;
self.tls13_client_handshake_traffic_secret = Some(client_hs_traffic.clone());
self.tls13_server_handshake_traffic_secret = Some(server_hs_traffic.clone());
self.noxtls_install_tls13_record_protection_keys(
noxtls_hash_algorithm,
&client_hs_traffic,
&server_hs_traffic,
)?;
return Ok(());
}
TlsVersion::Tls10 | TlsVersion::Tls11 | TlsVersion::Tls12 | TlsVersion::Dtls12 => {
if matches!(self.version, TlsVersion::Tls12 | TlsVersion::Dtls12)
&& self.tls12_master_secret.is_some()
&& self.tls12_client_random.is_some()
&& self.tls12_server_random.is_some()
{
return self.noxtls_install_tls12_record_protection_keys(noxtls_hash_algorithm);
}
let suite = self.noxtls_selected_cipher_suite.ok_or(Error::StateError(
"cipher suite must be selected before tls12 traffic keys",
))?;
let key_len = suite.noxtls_tls12_aead_key_len().unwrap_or(16);
let client_key_material = noxtls_hkdf_expand_for_hash(
noxtls_hash_algorithm,
secret,
b"client_write_key",
key_len,
)?;
let server_key_material = noxtls_hkdf_expand_for_hash(
noxtls_hash_algorithm,
secret,
b"server_write_key",
key_len,
)?;
let mut client_key = [0_u8; 32];
let mut server_key = [0_u8; 32];
client_key[..key_len].copy_from_slice(&client_key_material);
server_key[..key_len].copy_from_slice(&server_key_material);
let client_iv: [u8; 12] = noxtls_hkdf_expand_for_hash(
noxtls_hash_algorithm,
secret,
b"client_write_iv",
12,
)?
.try_into()
.expect("hkdf output length should be 12");
let server_iv: [u8; 12] = noxtls_hkdf_expand_for_hash(
noxtls_hash_algorithm,
secret,
b"server_write_iv",
12,
)?
.try_into()
.expect("hkdf output length should be 12");
(client_key, server_key, client_iv, server_iv)
}
};
self.client_write_key = Some(client_key);
self.server_write_key = Some(server_key);
self.client_write_iv = Some(client_iv);
self.server_write_iv = Some(server_iv);
self.noxtls_sync_dtls13_traffic_keys_from_record_protection_state();
Ok(())
}
pub(super) fn noxtls_install_tls12_record_protection_keys(
&mut self,
noxtls_hash_algorithm: HashAlgorithm,
) -> Result<()> {
let suite = self.noxtls_selected_cipher_suite.ok_or(Error::StateError(
"cipher suite must be selected before tls12 record protection keys",
))?;
if let Some(key_len) = suite.noxtls_tls12_cbc_key_len() {
return self
.noxtls_install_tls12_cbc_record_protection_keys(noxtls_hash_algorithm, key_len);
}
if let Some(key_len) = suite.noxtls_tls12_chacha20_poly1305_key_len() {
return self.noxtls_install_tls12_chacha20_poly1305_record_protection_keys(
noxtls_hash_algorithm,
key_len,
);
}
let key_len = suite.noxtls_tls12_aead_key_len().ok_or(Error::StateError(
"tls 1.2 record protection requires a tls 1.2 AEAD or CBC cipher suite",
))?;
let master_secret = self
.tls12_master_secret
.as_ref()
.ok_or(Error::StateError("tls12 master secret is not installed"))?;
let client_random = self
.tls12_client_random
.ok_or(Error::StateError("tls12 client random is not available"))?;
let server_random = self
.tls12_server_random
.ok_or(Error::StateError("tls12 server random is not available"))?;
let mut seed = Vec::with_capacity(64);
seed.extend_from_slice(&server_random);
seed.extend_from_slice(&client_random);
let key_block_len = (key_len * 2) + 8;
let key_block = noxtls_tls12_prf_for_hash(
noxtls_hash_algorithm,
master_secret,
b"key expansion",
&seed,
key_block_len,
)?;
let mut cursor = 0_usize;
let mut client_key = [0_u8; 32];
client_key[..key_len].copy_from_slice(&key_block[cursor..cursor + key_len]);
cursor += key_len;
let mut server_key = [0_u8; 32];
server_key[..key_len].copy_from_slice(&key_block[cursor..cursor + key_len]);
cursor += key_len;
let mut client_iv = [0_u8; 12];
client_iv[..4].copy_from_slice(&key_block[cursor..cursor + 4]);
cursor += 4;
let mut server_iv = [0_u8; 12];
server_iv[..4].copy_from_slice(&key_block[cursor..cursor + 4]);
self.client_write_key = Some(client_key);
self.server_write_key = Some(server_key);
self.client_write_iv = Some(client_iv);
self.server_write_iv = Some(server_iv);
self.client_sequence = 0;
self.server_sequence = 0;
Ok(())
}
fn noxtls_install_tls12_chacha20_poly1305_record_protection_keys(
&mut self,
noxtls_hash_algorithm: HashAlgorithm,
key_len: usize,
) -> Result<()> {
let master_secret = self
.tls12_master_secret
.as_ref()
.ok_or(Error::StateError("tls12 master secret is not installed"))?;
let client_random = self
.tls12_client_random
.ok_or(Error::StateError("tls12 client random is not available"))?;
let server_random = self
.tls12_server_random
.ok_or(Error::StateError("tls12 server random is not available"))?;
let mut seed = Vec::with_capacity(64);
seed.extend_from_slice(&server_random);
seed.extend_from_slice(&client_random);
let fixed_iv_len = 12_usize;
let key_block_len = (key_len * 2) + (fixed_iv_len * 2);
let key_block = noxtls_tls12_prf_for_hash(
noxtls_hash_algorithm,
master_secret,
b"key expansion",
&seed,
key_block_len,
)?;
let mut cursor = 0_usize;
let mut client_key = [0_u8; 32];
client_key[..key_len].copy_from_slice(&key_block[cursor..cursor + key_len]);
cursor += key_len;
let mut server_key = [0_u8; 32];
server_key[..key_len].copy_from_slice(&key_block[cursor..cursor + key_len]);
cursor += key_len;
let mut client_iv = [0_u8; 12];
client_iv.copy_from_slice(&key_block[cursor..cursor + fixed_iv_len]);
cursor += fixed_iv_len;
let mut server_iv = [0_u8; 12];
server_iv.copy_from_slice(&key_block[cursor..cursor + fixed_iv_len]);
self.client_write_key = Some(client_key);
self.server_write_key = Some(server_key);
self.client_write_iv = Some(client_iv);
self.server_write_iv = Some(server_iv);
self.client_sequence = 0;
self.server_sequence = 0;
Ok(())
}
fn noxtls_install_tls12_cbc_record_protection_keys(
&mut self,
noxtls_hash_algorithm: HashAlgorithm,
key_len: usize,
) -> Result<()> {
let master_secret = self
.tls12_master_secret
.as_ref()
.ok_or(Error::StateError("tls12 master secret is not installed"))?;
let client_random = self
.tls12_client_random
.ok_or(Error::StateError("tls12 client random is not available"))?;
let server_random = self
.tls12_server_random
.ok_or(Error::StateError("tls12 server random is not available"))?;
let mut seed = Vec::with_capacity(64);
seed.extend_from_slice(&server_random);
seed.extend_from_slice(&client_random);
let mac_key_len = 20_usize;
let key_block_len = (mac_key_len * 2) + (key_len * 2);
let key_block = noxtls_tls12_prf_for_hash(
noxtls_hash_algorithm,
master_secret,
b"key expansion",
&seed,
key_block_len,
)?;
let mut cursor = 0_usize;
let mut client_mac_key = [0_u8; 20];
client_mac_key.copy_from_slice(&key_block[cursor..cursor + mac_key_len]);
cursor += mac_key_len;
let mut server_mac_key = [0_u8; 20];
server_mac_key.copy_from_slice(&key_block[cursor..cursor + mac_key_len]);
cursor += mac_key_len;
let mut client_key = [0_u8; 32];
client_key[..key_len].copy_from_slice(&key_block[cursor..cursor + key_len]);
cursor += key_len;
let mut server_key = [0_u8; 32];
server_key[..key_len].copy_from_slice(&key_block[cursor..cursor + key_len]);
self.tls12_client_write_mac_key = Some(client_mac_key);
self.tls12_server_write_mac_key = Some(server_mac_key);
self.client_write_key = Some(client_key);
self.server_write_key = Some(server_key);
self.client_write_iv = Some([0_u8; 12]);
self.server_write_iv = Some([0_u8; 12]);
self.client_sequence = 0;
self.server_sequence = 0;
Ok(())
}
pub(super) fn noxtls_install_tls13_application_traffic_keys(&mut self) -> Result<()> {
if !self.version.uses_tls13_handshake_semantics() {
return Ok(());
}
if self.tls13_client_application_traffic_secret.is_some()
&& self.tls13_server_application_traffic_secret.is_some()
{
return Ok(());
}
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let noxtls_transcript_hash = self
.tls13_application_traffic_transcript_hash
.clone()
.unwrap_or_else(|| self.noxtls_transcript_hash());
let handshake_secret = self.handshake_secret.as_ref().ok_or(Error::StateError(
"handshake secret must be available before tls13 application traffic keys",
))?;
let derived = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
handshake_secret,
b"derived",
&noxtls_hash_bytes_for_algorithm(noxtls_hash_algorithm, &[]),
hash_len,
)?;
let zero_ikm = vec![0_u8; hash_len];
let master_secret =
noxtls_hkdf_extract_with_salt_for_hash(noxtls_hash_algorithm, &derived, &zero_ikm);
let client_app_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&master_secret,
b"c ap traffic",
&noxtls_transcript_hash,
hash_len,
)?;
let server_app_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&master_secret,
b"s ap traffic",
&noxtls_transcript_hash,
hash_len,
)?;
self.noxtls_install_tls13_record_protection_keys(
noxtls_hash_algorithm,
&client_app_secret,
&server_app_secret,
)?;
self.noxtls_install_tls13_exporter_and_resumption_secrets(
noxtls_hash_algorithm,
&master_secret,
&noxtls_transcript_hash,
)?;
self.tls13_master_secret = Some(master_secret);
self.tls13_client_application_traffic_secret = Some(client_app_secret);
self.tls13_server_application_traffic_secret = Some(server_app_secret);
self.client_sequence = 0;
self.server_sequence = 0;
Ok(())
}
pub(super) fn noxtls_install_tls13_server_application_write_keys(&mut self) -> Result<()> {
if !self.version.uses_tls13_handshake_semantics() {
return Ok(());
}
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let noxtls_transcript_hash = self.noxtls_transcript_hash();
self.tls13_application_traffic_transcript_hash = Some(noxtls_transcript_hash.clone());
let handshake_secret = self.handshake_secret.as_ref().ok_or(Error::StateError(
"handshake secret must be available before tls13 application traffic keys",
))?;
let derived = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
handshake_secret,
b"derived",
&noxtls_hash_bytes_for_algorithm(noxtls_hash_algorithm, &[]),
hash_len,
)?;
let zero_ikm = vec![0_u8; hash_len];
let master_secret =
noxtls_hkdf_extract_with_salt_for_hash(noxtls_hash_algorithm, &derived, &zero_ikm);
let server_app_secret = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&master_secret,
b"s ap traffic",
&noxtls_transcript_hash,
hash_len,
)?;
let suite = self.noxtls_selected_cipher_suite.ok_or(Error::StateError(
"cipher suite must be selected before tls13 record protection keys",
))?;
let key_len = suite
.noxtls_tls13_traffic_key_len()
.ok_or(Error::StateError(
"tls 1.3 record protection requires a tls 1.3 AEAD cipher suite",
))?;
let server_key_material = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&server_app_secret,
b"key",
&[],
key_len,
)?;
let mut server_key = [0_u8; 32];
server_key[..key_len].copy_from_slice(&server_key_material);
let server_iv: [u8; 12] = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&server_app_secret,
b"iv",
&[],
12,
)?
.try_into()
.expect("tls13 iv length should be 12");
self.server_write_key = Some(server_key);
self.server_write_iv = Some(server_iv);
self.server_sequence = 0;
self.tls13_master_secret = Some(master_secret);
self.tls13_server_application_traffic_secret = Some(server_app_secret);
Ok(())
}
fn noxtls_install_tls13_exporter_and_resumption_secrets(
&mut self,
noxtls_hash_algorithm: HashAlgorithm,
master_secret: &[u8],
noxtls_transcript_hash: &[u8],
) -> Result<()> {
let hash_len = noxtls_hash_algorithm.output_len();
self.tls13_exporter_master_secret = Some(noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
master_secret,
b"exp master",
noxtls_transcript_hash,
hash_len,
)?);
self.noxtls_tls13_resumption_master_secret = Some(noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
master_secret,
b"res master",
noxtls_transcript_hash,
hash_len,
)?);
Ok(())
}
pub(super) fn noxtls_install_tls13_record_protection_keys(
&mut self,
noxtls_hash_algorithm: HashAlgorithm,
client_traffic_secret: &[u8],
server_traffic_secret: &[u8],
) -> Result<()> {
let suite = self.noxtls_selected_cipher_suite.ok_or(Error::StateError(
"cipher suite must be selected before tls13 record protection keys",
))?;
let key_len = suite
.noxtls_tls13_traffic_key_len()
.ok_or(Error::StateError(
"tls 1.3 record protection requires a tls 1.3 AEAD cipher suite",
))?;
let client_key_material = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
client_traffic_secret,
b"key",
&[],
key_len,
)?;
let server_key_material = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
server_traffic_secret,
b"key",
&[],
key_len,
)?;
let mut client_key = [0_u8; 32];
let mut server_key = [0_u8; 32];
client_key[..key_len].copy_from_slice(&client_key_material);
server_key[..key_len].copy_from_slice(&server_key_material);
let client_iv: [u8; 12] = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
client_traffic_secret,
b"iv",
&[],
12,
)?
.try_into()
.expect("tls13 iv length should be 12");
let server_iv: [u8; 12] = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
server_traffic_secret,
b"iv",
&[],
12,
)?
.try_into()
.expect("tls13 iv length should be 12");
self.client_write_key = Some(client_key);
self.server_write_key = Some(server_key);
self.client_write_iv = Some(client_iv);
self.server_write_iv = Some(server_iv);
self.noxtls_sync_dtls13_traffic_keys_from_record_protection_state();
Ok(())
}
pub(super) fn noxtls_negotiated_hash_algorithm(&self) -> HashAlgorithm {
self.noxtls_selected_cipher_suite
.map(CipherSuite::noxtls_hash_algorithm)
.unwrap_or_else(|| self.noxtls_transcript_hash.noxtls_algorithm())
}
}
pub(super) fn noxtls_derive_tls13_handshake_secret(
noxtls_hash_algorithm: HashAlgorithm,
shared_secret: &[u8],
suite: Option<CipherSuite>,
) -> Result<Vec<u8>> {
let hash_len = noxtls_hash_algorithm.output_len();
let zero_psk = vec![0_u8; hash_len];
let early_secret = noxtls_hkdf_extract_for_hash(noxtls_hash_algorithm, &zero_psk);
noxtls_tls13_debug_log_bytes("tls13.kdf.early_secret", &early_secret);
let empty_hash = noxtls_hash_bytes_for_algorithm(noxtls_hash_algorithm, &[]);
let derived = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
&early_secret,
b"derived",
&empty_hash,
hash_len,
)?;
noxtls_tls13_debug_log_bytes("tls13.kdf.derived_secret", &derived);
let mut handshake_secret =
noxtls_hkdf_extract_with_salt_for_hash(noxtls_hash_algorithm, &derived, shared_secret);
if let Some(selected) = suite {
if selected.noxtls_hash_algorithm() != noxtls_hash_algorithm {
handshake_secret = noxtls_hkdf_extract_with_salt_for_hash(
selected.noxtls_hash_algorithm(),
&derived,
shared_secret,
);
}
}
Ok(handshake_secret)
}
pub(super) fn noxtls_tls12_prf_for_hash(
noxtls_hash_algorithm: HashAlgorithm,
secret: &[u8],
label: &[u8],
seed: &[u8],
len: usize,
) -> Result<Vec<u8>> {
match noxtls_hash_algorithm {
HashAlgorithm::Sha256 => noxtls_tls12_prf_sha256(secret, label, seed, len),
HashAlgorithm::Sha384 => noxtls_tls12_prf_sha384(secret, label, seed, len),
}
}