mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 04:53:44 +02:00
tetanus-fixes (#1903)
This commit is contained in:
parent
d3baf083f1
commit
f2e2944658
1 changed files with 165 additions and 176 deletions
|
@ -138,7 +138,6 @@ struct SessionKey {
|
|||
receive_cipher_pool: [Mutex<AesGcm<false>>; AES_POOL_SIZE], // Pool of reusable sending ciphers
|
||||
send_cipher_pool: [Mutex<AesGcm<true>>; AES_POOL_SIZE], // Pool of reusable receiving ciphers
|
||||
rekey_at_time: i64, // Rekey at or after this time (ticks)
|
||||
created_at_counter: u64, // Counter at which session was created
|
||||
rekey_at_counter: u64, // Rekey at or after this counter
|
||||
expire_at_counter: u64, // Hard error when this counter value is reached or exceeded
|
||||
ratchet_count: u64, // Number of rekey events
|
||||
|
@ -640,29 +639,16 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
|
||||
if aead_authentication_ok {
|
||||
// Packet fully authenticated
|
||||
if !session.update_receive_window(incoming_counter) {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
if session.update_receive_window(incoming_counter) {
|
||||
// Update the current key to point to this key if it's newer, since having received
|
||||
// a packet encrypted with it proves that the other side has successfully derived it
|
||||
// as well.
|
||||
if state.current_key == key_index && key.confirmed {
|
||||
drop(state);
|
||||
} else {
|
||||
let current_key_created_at_counter = key.created_at_counter;
|
||||
|
||||
let confirmed = key.confirmed;
|
||||
drop(state);
|
||||
if !confirmed {
|
||||
let mut state = session.state.write().unwrap();
|
||||
|
||||
if state.current_key != key_index {
|
||||
if let Some(other_session_key) = state.keys[state.current_key].as_ref() {
|
||||
if other_session_key.created_at_counter < current_key_created_at_counter {
|
||||
state.current_key = key_index;
|
||||
}
|
||||
} else {
|
||||
state.current_key = key_index;
|
||||
}
|
||||
}
|
||||
state.keys[key_index].as_mut().unwrap().confirmed = true;
|
||||
|
||||
// If we got a valid data packet from Bob, this means we can cancel any offers
|
||||
|
@ -680,6 +666,9 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
} else {
|
||||
return Ok(ReceiveResult::Ok(Some(session)));
|
||||
}
|
||||
} else {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -898,10 +887,7 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
let noise_se = app.get_local_s_keypair().agree(&bob_noise_e).ok_or(Error::FailedAuthentication)?;
|
||||
|
||||
// Packet fully authenticated
|
||||
if !session.update_receive_window(incoming_counter) {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
|
||||
if session.update_receive_window(incoming_counter) {
|
||||
let noise_es_ee_se_hk_psk = hmac_sha512_secret::<BASE_KEY_SIZE>(
|
||||
hmac_sha512_secret::<BASE_KEY_SIZE>(noise_es_ee.as_bytes(), noise_se.as_bytes()).as_bytes(),
|
||||
hmac_sha512_secret::<BASE_KEY_SIZE>(session.psk.as_bytes(), hk.as_bytes()).as_bytes(),
|
||||
|
@ -974,6 +960,9 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
)?;
|
||||
|
||||
return Ok(ReceiveResult::Ok(Some(session)));
|
||||
} else {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
} else {
|
||||
return Err(Error::InvalidPacket);
|
||||
}
|
||||
|
@ -1124,11 +1113,6 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
drop(c);
|
||||
|
||||
if aead_authentication_ok {
|
||||
// Packet fully authenticated
|
||||
if !session.update_receive_window(incoming_counter) {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
|
||||
let pkt: &RekeyInit = byte_array_as_proto_buffer(&pkt_assembled).unwrap();
|
||||
if let Some(alice_e) = P384PublicKey::from_bytes(&pkt.alice_e) {
|
||||
let bob_e_secret = P384KeyPair::generate();
|
||||
|
@ -1137,6 +1121,8 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
bob_e_secret.agree(&alice_e).ok_or(Error::FailedAuthentication)?.as_bytes(),
|
||||
);
|
||||
|
||||
// Packet fully authenticated
|
||||
if session.update_receive_window(incoming_counter) {
|
||||
let mut reply_buf = [0u8; RekeyAck::SIZE];
|
||||
let reply: &mut RekeyAck = byte_array_as_proto_buffer_mut(&mut reply_buf).unwrap();
|
||||
reply.session_protocol_version = SESSION_PROTOCOL_VERSION;
|
||||
|
@ -1183,6 +1169,9 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
|
||||
drop(state);
|
||||
return Ok(ReceiveResult::Ok(Some(session)));
|
||||
} else {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Err(Error::FailedAuthentication);
|
||||
|
@ -1217,9 +1206,6 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
|
||||
if aead_authentication_ok {
|
||||
// Packet fully authenticated
|
||||
if !session.update_receive_window(incoming_counter) {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
|
||||
let pkt: &RekeyAck = byte_array_as_proto_buffer(&pkt_assembled).unwrap();
|
||||
if let Some(bob_e) = P384PublicKey::from_bytes(&pkt.bob_e) {
|
||||
|
@ -1229,6 +1215,7 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
);
|
||||
|
||||
if secure_eq(&pkt.next_key_fingerprint, &SHA384::hash(next_session_key.as_bytes())) {
|
||||
if session.update_receive_window(incoming_counter) {
|
||||
// The new "Alice" knows Bob has the key since this is an ACK, so she can go
|
||||
// ahead and set current_key to the new key. Then when she sends something
|
||||
// to Bob the other side will automatically advance to the new key as well.
|
||||
|
@ -1249,6 +1236,9 @@ impl<Application: ApplicationLayer> Context<Application> {
|
|||
|
||||
drop(state);
|
||||
return Ok(ReceiveResult::Ok(Some(session)));
|
||||
} else {
|
||||
return Err(Error::OutOfSequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1575,7 +1565,6 @@ impl SessionKey {
|
|||
Application::REKEY_AFTER_TIME_MS + ((random::xorshift64_random() as u32) % Application::REKEY_AFTER_TIME_MS_MAX_JITTER) as i64,
|
||||
)
|
||||
.unwrap(),
|
||||
created_at_counter: current_counter,
|
||||
rekey_at_counter: current_counter.checked_add(Application::REKEY_AFTER_USES).unwrap(),
|
||||
expire_at_counter: current_counter.checked_add(Application::EXPIRE_AFTER_USES).unwrap(),
|
||||
ratchet_count,
|
||||
|
@ -1586,7 +1575,7 @@ impl SessionKey {
|
|||
|
||||
fn get_send_cipher<'a>(&'a self, counter: u64) -> Result<MutexGuard<'a, AesGcm<true>>, Error> {
|
||||
if counter < self.expire_at_counter {
|
||||
for i in 0..(AES_POOL_SIZE - 1) {
|
||||
for i in 0..AES_POOL_SIZE {
|
||||
if let Ok(p) = self.send_cipher_pool[(counter as usize).wrapping_add(i) % AES_POOL_SIZE].try_lock() {
|
||||
return Ok(p);
|
||||
}
|
||||
|
@ -1598,7 +1587,7 @@ impl SessionKey {
|
|||
}
|
||||
|
||||
fn get_receive_cipher<'a>(&'a self, counter: u64) -> MutexGuard<'a, AesGcm<false>> {
|
||||
for i in 0..(AES_POOL_SIZE - 1) {
|
||||
for i in 0..AES_POOL_SIZE {
|
||||
if let Ok(p) = self.receive_cipher_pool[(counter as usize).wrapping_add(i) % AES_POOL_SIZE].try_lock() {
|
||||
return p;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue