diagnostics, recconections fix and bufferbloat fixes
This commit is contained in:
@@ -77,14 +77,14 @@ impl AeadPacker for ChaChaStream {
|
||||
}
|
||||
|
||||
fn decrypt(&mut self, data: &mut BytesMut) -> Result<(), chacha20poly1305::aead::Error> {
|
||||
let current_counter = self.state.counter;
|
||||
let saved_counter = self.state.counter;
|
||||
let nonce = self.state.next_nonce();
|
||||
let data_len = data.len();
|
||||
|
||||
match self.cipher.decrypt_in_place(&nonce, &nonce, data) {
|
||||
Ok(_) => {
|
||||
netrunner_logger::trace!(
|
||||
counter = current_counter,
|
||||
counter = saved_counter,
|
||||
nonce = %hex::encode(nonce),
|
||||
len = data_len,
|
||||
"Decryption successful"
|
||||
@@ -92,13 +92,21 @@ impl AeadPacker for ChaChaStream {
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
// Roll back the counter: the plaintext was not produced, so the
|
||||
// peer's TX counter is still at saved_counter. If the caller
|
||||
// decides to retry (e.g., after a corrective re-read) rather
|
||||
// than drop the connection, the next decrypt attempt will use
|
||||
// the same nonce and succeed. In practice we always Drop on
|
||||
// AEAD failure, but correctness requires the rollback.
|
||||
self.state.counter = saved_counter;
|
||||
|
||||
let data_prefix = if data.len() >= 8 {
|
||||
hex::encode(&data[..8])
|
||||
} else {
|
||||
hex::encode(data.as_ref())
|
||||
};
|
||||
netrunner_logger::error!(
|
||||
counter = current_counter,
|
||||
counter = saved_counter,
|
||||
nonce = %hex::encode(nonce),
|
||||
len = data_len,
|
||||
prefix = %data_prefix,
|
||||
|
||||
+34
-12
@@ -233,7 +233,11 @@ impl SessionAuth {
|
||||
pub fn generate_current_tag(&self) -> [u8; 16] {
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
// NTP step-back can make this return Err; saturate to 0 so the
|
||||
// writer task doesn't panic. The peer's verify_tag will accept
|
||||
// tags up to AUTH_WINDOW_SIZE steps away, so a brief clock skew
|
||||
// is tolerated without a reconnect.
|
||||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
|
||||
Self::compute_tag(&self.auth_key, now / AUTH_TIME_STEP)
|
||||
@@ -242,26 +246,44 @@ impl SessionAuth {
|
||||
pub fn verify_tag(&self, received_tag: &[u8; 16]) -> bool {
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.expect("Time went backwards")
|
||||
// NTP step-back can make duration_since return an error. Saturate to 0
|
||||
// rather than panic; the tag comparison will fail and we log AUTH MISMATCH.
|
||||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
|
||||
let current_step = now / AUTH_TIME_STEP;
|
||||
|
||||
// Constant-time path: always evaluate ALL 2*AUTH_WINDOW_SIZE+1 candidates
|
||||
// so the loop duration doesn't leak which step (if any) matched.
|
||||
let mut matched_step: Option<u64> = None;
|
||||
for step in (current_step.saturating_sub(AUTH_WINDOW_SIZE))
|
||||
..=(current_step.saturating_add(AUTH_WINDOW_SIZE))
|
||||
{
|
||||
if &Self::compute_tag(&self.auth_key, step) == received_tag {
|
||||
if step != current_step {
|
||||
netrunner_logger::debug!(expected = %current_step, matched = %step, "Auth tag valid with time offset");
|
||||
}
|
||||
return true;
|
||||
let candidate = Self::compute_tag(&self.auth_key, step);
|
||||
let mut diff = 0u8;
|
||||
for (a, b) in candidate.iter().zip(received_tag.iter()) {
|
||||
diff |= a ^ b;
|
||||
}
|
||||
if diff == 0 && matched_step.is_none() {
|
||||
matched_step = Some(step);
|
||||
// Do NOT break — iterate full window for constant time.
|
||||
}
|
||||
}
|
||||
|
||||
netrunner_logger::warn!(
|
||||
current_step = %current_step,
|
||||
"AUTH MISMATCH: All tags rejected for current window"
|
||||
);
|
||||
false
|
||||
match matched_step {
|
||||
Some(step) => {
|
||||
if step != current_step {
|
||||
netrunner_logger::debug!(expected = %current_step, matched = %step, "Auth tag valid with time offset");
|
||||
}
|
||||
true
|
||||
}
|
||||
None => {
|
||||
netrunner_logger::warn!(
|
||||
current_step = %current_step,
|
||||
"AUTH MISMATCH: All tags rejected for current window"
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user