use super::*;
impl Connection {
pub fn noxtls_set_max_record_plaintext_len(&mut self, max_len: usize) -> Result<()> {
if max_len == 0 || max_len > TLS_MAX_RECORD_PLAINTEXT_LEN {
return Err(Error::InvalidLength(
"record plaintext limit must be between 1 and 16384 bytes",
));
}
self.max_record_plaintext_len = max_len;
Ok(())
}
#[must_use]
pub fn noxtls_transcript_hash(&self) -> Vec<u8> {
self.noxtls_transcript_hash.noxtls_snapshot_hash()
}
#[must_use]
pub fn noxtls_selected_cipher_suite(&self) -> Option<CipherSuite> {
self.noxtls_selected_cipher_suite
}
pub fn noxtls_compute_expected_finished(&self) -> Result<Vec<u8>> {
let hash = self.noxtls_transcript_hash();
match self.version {
TlsVersion::Tls12 | TlsVersion::Dtls12 => {
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"client finished".as_slice()
} else {
b"server finished".as_slice()
};
noxtls_tls12_prf_for_hash(
self.noxtls_negotiated_hash_algorithm(),
secret,
label,
&hash,
12,
)
}
TlsVersion::Tls13 | TlsVersion::Dtls13 => {
let noxtls_hash_algorithm = self.noxtls_negotiated_hash_algorithm();
let hash_len = noxtls_hash_algorithm.output_len();
let peer_hs = if self.tls_role == TlsRole::Server {
self.tls13_client_handshake_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 client handshake traffic secret must be installed before finished verify",
))?
} else {
self.tls13_server_handshake_traffic_secret
.as_ref()
.ok_or(Error::StateError(
"tls13 server handshake traffic secret must be installed before finished verify",
))?
};
let finished_key = noxtls_tls13_expand_label_for_hash(
noxtls_hash_algorithm,
peer_hs,
b"finished",
&[],
hash_len,
)?;
Ok(noxtls_finished_hmac_for_hash(
noxtls_hash_algorithm,
&finished_key,
&hash,
))
}
TlsVersion::Tls10 | TlsVersion::Tls11 => Ok(noxtls_finished_hmac_for_hash(
self.noxtls_negotiated_hash_algorithm(),
b"finished",
&hash,
)),
}
}
pub fn noxtls_compute_expected_client_finished(&self) -> Result<Vec<u8>> {
self.noxtls_compute_expected_finished()
}
pub(super) fn noxtls_append_transcript(&mut self, message: &[u8]) {
self.transcript.extend_from_slice(message);
self.noxtls_transcript_hash.noxtls_update(message);
}
pub(super) fn noxtls_reset_transcript_for_new_handshake(&mut self) {
self.transcript.clear();
self.noxtls_transcript_hash = TranscriptHashState::noxtls_for_version(self.version);
}
pub(super) fn noxtls_rebuild_transcript_hash_from_selected_suite(&mut self) {
let Some(suite) = self.noxtls_selected_cipher_suite else {
return;
};
self.noxtls_transcript_hash = suite.noxtls_transcript_hash_state();
self.noxtls_transcript_hash.noxtls_update(&self.transcript);
}
pub(super) fn noxtls_reset_transcript_for_hrr(&mut self) {
let prior_hash = self.noxtls_transcript_hash();
self.transcript.clear();
if let Some(suite) = self.noxtls_selected_cipher_suite {
self.noxtls_transcript_hash = suite.noxtls_transcript_hash_state();
} else {
self.noxtls_transcript_hash = TranscriptHashState::noxtls_for_version(self.version);
}
let message_hash = noxtls_encode_handshake_message(0xFE, &prior_hash);
self.noxtls_append_transcript(&message_hash);
}
}
pub(super) fn noxtls_constant_time_eq(left: &[u8], right: &[u8]) -> bool {
let max_len = left.len().max(right.len());
let mut diff = left.len() ^ right.len();
for idx in 0..max_len {
let l = left.get(idx).copied().unwrap_or(0);
let r = right.get(idx).copied().unwrap_or(0);
diff |= usize::from(l ^ r);
}
diff == 0
}