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
341
zssp/src/zssp.rs
341
zssp/src/zssp.rs
|
@ -138,7 +138,6 @@ struct SessionKey {
|
||||||
receive_cipher_pool: [Mutex<AesGcm<false>>; AES_POOL_SIZE], // Pool of reusable sending ciphers
|
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
|
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)
|
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
|
rekey_at_counter: u64, // Rekey at or after this counter
|
||||||
expire_at_counter: u64, // Hard error when this counter value is reached or exceeded
|
expire_at_counter: u64, // Hard error when this counter value is reached or exceeded
|
||||||
ratchet_count: u64, // Number of rekey events
|
ratchet_count: u64, // Number of rekey events
|
||||||
|
@ -640,45 +639,35 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
|
|
||||||
if aead_authentication_ok {
|
if aead_authentication_ok {
|
||||||
// Packet fully authenticated
|
// Packet fully authenticated
|
||||||
if !session.update_receive_window(incoming_counter) {
|
if session.update_receive_window(incoming_counter) {
|
||||||
return Err(Error::OutOfSequence);
|
// 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
|
||||||
// Update the current key to point to this key if it's newer, since having received
|
// as well.
|
||||||
// a packet encrypted with it proves that the other side has successfully derived it
|
let confirmed = key.confirmed;
|
||||||
// as well.
|
|
||||||
if state.current_key == key_index && key.confirmed {
|
|
||||||
drop(state);
|
drop(state);
|
||||||
} else {
|
if !confirmed {
|
||||||
let current_key_created_at_counter = key.created_at_counter;
|
let mut state = session.state.write().unwrap();
|
||||||
|
|
||||||
drop(state);
|
state.current_key = key_index;
|
||||||
let mut state = session.state.write().unwrap();
|
state.keys[key_index].as_mut().unwrap().confirmed = true;
|
||||||
|
|
||||||
if state.current_key != key_index {
|
// If we got a valid data packet from Bob, this means we can cancel any offers
|
||||||
if let Some(other_session_key) = state.keys[state.current_key].as_ref() {
|
// that are still oustanding for initialization.
|
||||||
if other_session_key.created_at_counter < current_key_created_at_counter {
|
match &state.current_offer {
|
||||||
state.current_key = key_index;
|
Offer::NoiseXKInit(_) | Offer::NoiseXKAck(_) => {
|
||||||
|
state.current_offer = Offer::None;
|
||||||
}
|
}
|
||||||
} 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
|
if packet_type == PACKET_TYPE_DATA {
|
||||||
// that are still oustanding for initialization.
|
return Ok(ReceiveResult::OkData(session, &mut data_buf[..data_len]));
|
||||||
match &state.current_offer {
|
} else {
|
||||||
Offer::NoiseXKInit(_) | Offer::NoiseXKAck(_) => {
|
return Ok(ReceiveResult::Ok(Some(session)));
|
||||||
state.current_offer = Offer::None;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if packet_type == PACKET_TYPE_DATA {
|
|
||||||
return Ok(ReceiveResult::OkData(session, &mut data_buf[..data_len]));
|
|
||||||
} else {
|
} else {
|
||||||
return Ok(ReceiveResult::Ok(Some(session)));
|
return Err(Error::OutOfSequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,82 +887,82 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
let noise_se = app.get_local_s_keypair().agree(&bob_noise_e).ok_or(Error::FailedAuthentication)?;
|
let noise_se = app.get_local_s_keypair().agree(&bob_noise_e).ok_or(Error::FailedAuthentication)?;
|
||||||
|
|
||||||
// Packet fully authenticated
|
// Packet fully authenticated
|
||||||
if !session.update_receive_window(incoming_counter) {
|
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(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let reply_message_nonce = create_message_nonce(PACKET_TYPE_ALICE_NOISE_XK_ACK, 2);
|
||||||
|
|
||||||
|
// Create reply informing Bob of our static identity now that we've verified Bob and set
|
||||||
|
// up forward secrecy. Also return Bob's opaque note.
|
||||||
|
let mut reply_buffer = [0u8; MAX_NOISE_HANDSHAKE_SIZE];
|
||||||
|
reply_buffer[HEADER_SIZE] = SESSION_PROTOCOL_VERSION;
|
||||||
|
let mut reply_len = HEADER_SIZE + 1;
|
||||||
|
|
||||||
|
let alice_s_public_blob = app.get_local_s_public_blob();
|
||||||
|
assert!(alice_s_public_blob.len() <= (u16::MAX as usize));
|
||||||
|
reply_len = append_to_slice(&mut reply_buffer, reply_len, &(alice_s_public_blob.len() as u16).to_le_bytes())?;
|
||||||
|
let mut enc_start = reply_len;
|
||||||
|
reply_len = append_to_slice(&mut reply_buffer, reply_len, alice_s_public_blob)?;
|
||||||
|
|
||||||
|
let mut gcm = AesGcm::new(&kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_KEX_ES_EE_HK>(
|
||||||
|
hmac_sha512_secret::<BASE_KEY_SIZE>(noise_es_ee.as_bytes(), hk.as_bytes()).as_bytes(),
|
||||||
|
));
|
||||||
|
gcm.reset_init_gcm(&reply_message_nonce);
|
||||||
|
gcm.aad(&noise_h_next);
|
||||||
|
gcm.crypt_in_place(&mut reply_buffer[enc_start..reply_len]);
|
||||||
|
reply_len = append_to_slice(&mut reply_buffer, reply_len, &gcm.finish_encrypt())?;
|
||||||
|
|
||||||
|
let metadata = outgoing_offer.metadata.as_ref().map_or(&[][..0], |md| md.as_slice());
|
||||||
|
|
||||||
|
assert!(metadata.len() <= (u16::MAX as usize));
|
||||||
|
reply_len = append_to_slice(&mut reply_buffer, reply_len, &(metadata.len() as u16).to_le_bytes())?;
|
||||||
|
|
||||||
|
let noise_h_next = mix_hash(&mix_hash(&noise_h_next, &reply_buffer[HEADER_SIZE..reply_len]), session.psk.as_bytes());
|
||||||
|
|
||||||
|
enc_start = reply_len;
|
||||||
|
reply_len = append_to_slice(&mut reply_buffer, reply_len, metadata)?;
|
||||||
|
|
||||||
|
let mut gcm = AesGcm::new(&kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_KEX_ES_EE_SE_HK_PSK>(
|
||||||
|
noise_es_ee_se_hk_psk.as_bytes(),
|
||||||
|
));
|
||||||
|
gcm.reset_init_gcm(&reply_message_nonce);
|
||||||
|
gcm.aad(&noise_h_next);
|
||||||
|
gcm.crypt_in_place(&mut reply_buffer[enc_start..reply_len]);
|
||||||
|
reply_len = append_to_slice(&mut reply_buffer, reply_len, &gcm.finish_encrypt())?;
|
||||||
|
|
||||||
|
drop(state);
|
||||||
|
{
|
||||||
|
let mut state = session.state.write().unwrap();
|
||||||
|
let _ = state.remote_session_id.insert(bob_session_id);
|
||||||
|
let _ =
|
||||||
|
state.keys[0].insert(SessionKey::new::<Application>(noise_es_ee_se_hk_psk, 1, current_time, 2, false, false));
|
||||||
|
debug_assert!(state.keys[1].is_none());
|
||||||
|
state.current_key = 0;
|
||||||
|
state.current_offer = Offer::NoiseXKAck(Box::new(OutgoingSessionAck {
|
||||||
|
last_retry_time: AtomicI64::new(current_time),
|
||||||
|
ack: reply_buffer,
|
||||||
|
ack_size: reply_len,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
send_with_fragmentation(
|
||||||
|
|b| send(Some(&session), b),
|
||||||
|
&mut reply_buffer[..reply_len],
|
||||||
|
mtu,
|
||||||
|
PACKET_TYPE_ALICE_NOISE_XK_ACK,
|
||||||
|
Some(bob_session_id),
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
Some(&session.header_protection_cipher),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
return Ok(ReceiveResult::Ok(Some(session)));
|
||||||
|
} else {
|
||||||
return Err(Error::OutOfSequence);
|
return Err(Error::OutOfSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
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(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let reply_message_nonce = create_message_nonce(PACKET_TYPE_ALICE_NOISE_XK_ACK, 2);
|
|
||||||
|
|
||||||
// Create reply informing Bob of our static identity now that we've verified Bob and set
|
|
||||||
// up forward secrecy. Also return Bob's opaque note.
|
|
||||||
let mut reply_buffer = [0u8; MAX_NOISE_HANDSHAKE_SIZE];
|
|
||||||
reply_buffer[HEADER_SIZE] = SESSION_PROTOCOL_VERSION;
|
|
||||||
let mut reply_len = HEADER_SIZE + 1;
|
|
||||||
|
|
||||||
let alice_s_public_blob = app.get_local_s_public_blob();
|
|
||||||
assert!(alice_s_public_blob.len() <= (u16::MAX as usize));
|
|
||||||
reply_len = append_to_slice(&mut reply_buffer, reply_len, &(alice_s_public_blob.len() as u16).to_le_bytes())?;
|
|
||||||
let mut enc_start = reply_len;
|
|
||||||
reply_len = append_to_slice(&mut reply_buffer, reply_len, alice_s_public_blob)?;
|
|
||||||
|
|
||||||
let mut gcm = AesGcm::new(&kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_KEX_ES_EE_HK>(
|
|
||||||
hmac_sha512_secret::<BASE_KEY_SIZE>(noise_es_ee.as_bytes(), hk.as_bytes()).as_bytes(),
|
|
||||||
));
|
|
||||||
gcm.reset_init_gcm(&reply_message_nonce);
|
|
||||||
gcm.aad(&noise_h_next);
|
|
||||||
gcm.crypt_in_place(&mut reply_buffer[enc_start..reply_len]);
|
|
||||||
reply_len = append_to_slice(&mut reply_buffer, reply_len, &gcm.finish_encrypt())?;
|
|
||||||
|
|
||||||
let metadata = outgoing_offer.metadata.as_ref().map_or(&[][..0], |md| md.as_slice());
|
|
||||||
|
|
||||||
assert!(metadata.len() <= (u16::MAX as usize));
|
|
||||||
reply_len = append_to_slice(&mut reply_buffer, reply_len, &(metadata.len() as u16).to_le_bytes())?;
|
|
||||||
|
|
||||||
let noise_h_next = mix_hash(&mix_hash(&noise_h_next, &reply_buffer[HEADER_SIZE..reply_len]), session.psk.as_bytes());
|
|
||||||
|
|
||||||
enc_start = reply_len;
|
|
||||||
reply_len = append_to_slice(&mut reply_buffer, reply_len, metadata)?;
|
|
||||||
|
|
||||||
let mut gcm = AesGcm::new(&kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_KEX_ES_EE_SE_HK_PSK>(
|
|
||||||
noise_es_ee_se_hk_psk.as_bytes(),
|
|
||||||
));
|
|
||||||
gcm.reset_init_gcm(&reply_message_nonce);
|
|
||||||
gcm.aad(&noise_h_next);
|
|
||||||
gcm.crypt_in_place(&mut reply_buffer[enc_start..reply_len]);
|
|
||||||
reply_len = append_to_slice(&mut reply_buffer, reply_len, &gcm.finish_encrypt())?;
|
|
||||||
|
|
||||||
drop(state);
|
|
||||||
{
|
|
||||||
let mut state = session.state.write().unwrap();
|
|
||||||
let _ = state.remote_session_id.insert(bob_session_id);
|
|
||||||
let _ =
|
|
||||||
state.keys[0].insert(SessionKey::new::<Application>(noise_es_ee_se_hk_psk, 1, current_time, 2, false, false));
|
|
||||||
debug_assert!(state.keys[1].is_none());
|
|
||||||
state.current_key = 0;
|
|
||||||
state.current_offer = Offer::NoiseXKAck(Box::new(OutgoingSessionAck {
|
|
||||||
last_retry_time: AtomicI64::new(current_time),
|
|
||||||
ack: reply_buffer,
|
|
||||||
ack_size: reply_len,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
send_with_fragmentation(
|
|
||||||
|b| send(Some(&session), b),
|
|
||||||
&mut reply_buffer[..reply_len],
|
|
||||||
mtu,
|
|
||||||
PACKET_TYPE_ALICE_NOISE_XK_ACK,
|
|
||||||
Some(bob_session_id),
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
Some(&session.header_protection_cipher),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
return Ok(ReceiveResult::Ok(Some(session)));
|
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::InvalidPacket);
|
return Err(Error::InvalidPacket);
|
||||||
}
|
}
|
||||||
|
@ -1124,11 +1113,6 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
drop(c);
|
drop(c);
|
||||||
|
|
||||||
if aead_authentication_ok {
|
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();
|
let pkt: &RekeyInit = byte_array_as_proto_buffer(&pkt_assembled).unwrap();
|
||||||
if let Some(alice_e) = P384PublicKey::from_bytes(&pkt.alice_e) {
|
if let Some(alice_e) = P384PublicKey::from_bytes(&pkt.alice_e) {
|
||||||
let bob_e_secret = P384KeyPair::generate();
|
let bob_e_secret = P384KeyPair::generate();
|
||||||
|
@ -1137,52 +1121,57 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
bob_e_secret.agree(&alice_e).ok_or(Error::FailedAuthentication)?.as_bytes(),
|
bob_e_secret.agree(&alice_e).ok_or(Error::FailedAuthentication)?.as_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut reply_buf = [0u8; RekeyAck::SIZE];
|
// Packet fully authenticated
|
||||||
let reply: &mut RekeyAck = byte_array_as_proto_buffer_mut(&mut reply_buf).unwrap();
|
if session.update_receive_window(incoming_counter) {
|
||||||
reply.session_protocol_version = SESSION_PROTOCOL_VERSION;
|
let mut reply_buf = [0u8; RekeyAck::SIZE];
|
||||||
reply.bob_e = *bob_e_secret.public_key_bytes();
|
let reply: &mut RekeyAck = byte_array_as_proto_buffer_mut(&mut reply_buf).unwrap();
|
||||||
reply.next_key_fingerprint = SHA384::hash(next_session_key.as_bytes());
|
reply.session_protocol_version = SESSION_PROTOCOL_VERSION;
|
||||||
|
reply.bob_e = *bob_e_secret.public_key_bytes();
|
||||||
|
reply.next_key_fingerprint = SHA384::hash(next_session_key.as_bytes());
|
||||||
|
|
||||||
let counter = session.get_next_outgoing_counter().ok_or(Error::MaxKeyLifetimeExceeded)?.get();
|
let counter = session.get_next_outgoing_counter().ok_or(Error::MaxKeyLifetimeExceeded)?.get();
|
||||||
set_packet_header(
|
set_packet_header(
|
||||||
&mut reply_buf,
|
&mut reply_buf,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
PACKET_TYPE_REKEY_ACK,
|
PACKET_TYPE_REKEY_ACK,
|
||||||
u64::from(remote_session_id),
|
u64::from(remote_session_id),
|
||||||
state.current_key,
|
state.current_key,
|
||||||
counter,
|
counter,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut c = key.get_send_cipher(counter)?;
|
let mut c = key.get_send_cipher(counter)?;
|
||||||
c.reset_init_gcm(&create_message_nonce(PACKET_TYPE_REKEY_ACK, counter));
|
c.reset_init_gcm(&create_message_nonce(PACKET_TYPE_REKEY_ACK, counter));
|
||||||
c.crypt_in_place(&mut reply_buf[RekeyAck::ENC_START..RekeyAck::AUTH_START]);
|
c.crypt_in_place(&mut reply_buf[RekeyAck::ENC_START..RekeyAck::AUTH_START]);
|
||||||
reply_buf[RekeyAck::AUTH_START..].copy_from_slice(&c.finish_encrypt());
|
reply_buf[RekeyAck::AUTH_START..].copy_from_slice(&c.finish_encrypt());
|
||||||
drop(c);
|
drop(c);
|
||||||
|
|
||||||
session
|
session
|
||||||
.header_protection_cipher
|
.header_protection_cipher
|
||||||
.encrypt_block_in_place(&mut reply_buf[HEADER_PROTECT_ENCRYPT_START..HEADER_PROTECT_ENCRYPT_END]);
|
.encrypt_block_in_place(&mut reply_buf[HEADER_PROTECT_ENCRYPT_START..HEADER_PROTECT_ENCRYPT_END]);
|
||||||
send(Some(&session), &mut reply_buf);
|
send(Some(&session), &mut reply_buf);
|
||||||
|
|
||||||
// The new "Bob" doesn't know yet if Alice has received the new key, so the
|
// The new "Bob" doesn't know yet if Alice has received the new key, so the
|
||||||
// new key is recorded as the "alt" (key_index ^ 1) but the current key is
|
// new key is recorded as the "alt" (key_index ^ 1) but the current key is
|
||||||
// not advanced yet. This happens automatically the first time we receive a
|
// not advanced yet. This happens automatically the first time we receive a
|
||||||
// valid packet with the new key.
|
// valid packet with the new key.
|
||||||
let next_ratchet_count = key.ratchet_count + 1;
|
let next_ratchet_count = key.ratchet_count + 1;
|
||||||
drop(state);
|
drop(state);
|
||||||
let mut state = session.state.write().unwrap();
|
let mut state = session.state.write().unwrap();
|
||||||
let _ = state.keys[key_index ^ 1].replace(SessionKey::new::<Application>(
|
let _ = state.keys[key_index ^ 1].replace(SessionKey::new::<Application>(
|
||||||
next_session_key,
|
next_session_key,
|
||||||
next_ratchet_count,
|
next_ratchet_count,
|
||||||
current_time,
|
current_time,
|
||||||
counter,
|
counter,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
drop(state);
|
drop(state);
|
||||||
return Ok(ReceiveResult::Ok(Some(session)));
|
return Ok(ReceiveResult::Ok(Some(session)));
|
||||||
|
} else {
|
||||||
|
return Err(Error::OutOfSequence);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(Error::FailedAuthentication);
|
return Err(Error::FailedAuthentication);
|
||||||
|
@ -1217,9 +1206,6 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
|
|
||||||
if aead_authentication_ok {
|
if aead_authentication_ok {
|
||||||
// Packet fully authenticated
|
// 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();
|
let pkt: &RekeyAck = byte_array_as_proto_buffer(&pkt_assembled).unwrap();
|
||||||
if let Some(bob_e) = P384PublicKey::from_bytes(&pkt.bob_e) {
|
if let Some(bob_e) = P384PublicKey::from_bytes(&pkt.bob_e) {
|
||||||
|
@ -1229,26 +1215,30 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
);
|
);
|
||||||
|
|
||||||
if secure_eq(&pkt.next_key_fingerprint, &SHA384::hash(next_session_key.as_bytes())) {
|
if secure_eq(&pkt.next_key_fingerprint, &SHA384::hash(next_session_key.as_bytes())) {
|
||||||
// The new "Alice" knows Bob has the key since this is an ACK, so she can go
|
if session.update_receive_window(incoming_counter) {
|
||||||
// ahead and set current_key to the new key. Then when she sends something
|
// The new "Alice" knows Bob has the key since this is an ACK, so she can go
|
||||||
// to Bob the other side will automatically advance to the new key as well.
|
// ahead and set current_key to the new key. Then when she sends something
|
||||||
let next_ratchet_count = key.ratchet_count + 1;
|
// to Bob the other side will automatically advance to the new key as well.
|
||||||
drop(state);
|
let next_ratchet_count = key.ratchet_count + 1;
|
||||||
let next_key_index = key_index ^ 1;
|
drop(state);
|
||||||
let mut state = session.state.write().unwrap();
|
let next_key_index = key_index ^ 1;
|
||||||
let _ = state.keys[next_key_index].replace(SessionKey::new::<Application>(
|
let mut state = session.state.write().unwrap();
|
||||||
next_session_key,
|
let _ = state.keys[next_key_index].replace(SessionKey::new::<Application>(
|
||||||
next_ratchet_count,
|
next_session_key,
|
||||||
current_time,
|
next_ratchet_count,
|
||||||
session.send_counter.load(Ordering::Relaxed),
|
current_time,
|
||||||
true,
|
session.send_counter.load(Ordering::Relaxed),
|
||||||
true,
|
true,
|
||||||
));
|
true,
|
||||||
state.current_key = next_key_index; // this is an ACK so it's confirmed
|
));
|
||||||
state.current_offer = Offer::None;
|
state.current_key = next_key_index; // this is an ACK so it's confirmed
|
||||||
|
state.current_offer = Offer::None;
|
||||||
|
|
||||||
drop(state);
|
drop(state);
|
||||||
return Ok(ReceiveResult::Ok(Some(session)));
|
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,
|
Application::REKEY_AFTER_TIME_MS + ((random::xorshift64_random() as u32) % Application::REKEY_AFTER_TIME_MS_MAX_JITTER) as i64,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
created_at_counter: current_counter,
|
|
||||||
rekey_at_counter: current_counter.checked_add(Application::REKEY_AFTER_USES).unwrap(),
|
rekey_at_counter: current_counter.checked_add(Application::REKEY_AFTER_USES).unwrap(),
|
||||||
expire_at_counter: current_counter.checked_add(Application::EXPIRE_AFTER_USES).unwrap(),
|
expire_at_counter: current_counter.checked_add(Application::EXPIRE_AFTER_USES).unwrap(),
|
||||||
ratchet_count,
|
ratchet_count,
|
||||||
|
@ -1586,7 +1575,7 @@ impl SessionKey {
|
||||||
|
|
||||||
fn get_send_cipher<'a>(&'a self, counter: u64) -> Result<MutexGuard<'a, AesGcm<true>>, Error> {
|
fn get_send_cipher<'a>(&'a self, counter: u64) -> Result<MutexGuard<'a, AesGcm<true>>, Error> {
|
||||||
if counter < self.expire_at_counter {
|
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() {
|
if let Ok(p) = self.send_cipher_pool[(counter as usize).wrapping_add(i) % AES_POOL_SIZE].try_lock() {
|
||||||
return Ok(p);
|
return Ok(p);
|
||||||
}
|
}
|
||||||
|
@ -1598,7 +1587,7 @@ impl SessionKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_receive_cipher<'a>(&'a self, counter: u64) -> MutexGuard<'a, AesGcm<false>> {
|
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() {
|
if let Ok(p) = self.receive_cipher_pool[(counter as usize).wrapping_add(i) % AES_POOL_SIZE].try_lock() {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue