mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 21:13:44 +02:00
switched to use of safer read and write functions
This commit is contained in:
parent
2213548877
commit
a7fdc82c5b
5 changed files with 142 additions and 89 deletions
|
@ -10,6 +10,5 @@ pub mod salsa;
|
|||
pub mod secret;
|
||||
pub mod verified;
|
||||
pub mod x25519;
|
||||
pub mod zssp;
|
||||
|
||||
pub const ZEROES: [u8; 64] = [0_u8; 64];
|
||||
|
|
|
@ -33,6 +33,25 @@ pub fn write<W: Write>(w: &mut W, v: u64) -> std::io::Result<()> {
|
|||
w.write_all(&b[0..i])
|
||||
}
|
||||
|
||||
/// Read a variable length integer, returning the value and the number of bytes written.
|
||||
pub fn decode(b: &[u8]) -> Option<(u64, usize)> {
|
||||
let mut v = 0_u64;
|
||||
let mut pos = 0;
|
||||
let mut i = 0_usize;
|
||||
while i < b.len() {
|
||||
let b = b[i];
|
||||
i += 1;
|
||||
if b <= 0x7f {
|
||||
v |= (b as u64).wrapping_shl(pos);
|
||||
pos += 7;
|
||||
} else {
|
||||
v |= ((b & 0x7f) as u64).wrapping_shl(pos);
|
||||
return Some((v, i));
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Read a variable length integer, returning the value and the number of bytes written.
|
||||
pub fn read<R: Read>(r: &mut R) -> std::io::Result<(u64, usize)> {
|
||||
let mut v = 0_u64;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
zssp has been moved into it's own crate.
|
||||
|
||||
zssp has been cut up into several files, only the new zssp.rs file contains the critical security path..
|
||||
|
||||
zssp was inconsistently using a local/remote vs alice/bob naming convention, all names have been switched to a local/remote convention.
|
||||
zssp has been cut up into several files, only the new zssp.rs file contains the critical security path.
|
||||
|
||||
Standardized the naming conventions for security variables throughout zssp.
|
||||
|
||||
|
|
|
@ -53,12 +53,6 @@ impl SessionId {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_from_reader<R: Read>(r: &mut R) -> std::io::Result<Option<SessionId>> {
|
||||
let mut tmp = 0_u64.to_ne_bytes();
|
||||
r.read_exact(&mut tmp[..SESSION_ID_SIZE])?;
|
||||
Ok(Self::new_from_u64(u64::from_le_bytes(tmp)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_random() -> Self {
|
||||
|
|
201
zssp/src/zssp.rs
201
zssp/src/zssp.rs
|
@ -3,7 +3,7 @@
|
|||
// ZSSP: ZeroTier Secure Session Protocol
|
||||
// FIPS compliant Noise_IK with Jedi powers and built-in attack-resistant large payload (fragmentation) support.
|
||||
|
||||
use std::io::{Read, Write};
|
||||
use std::mem;
|
||||
use std::sync::{Mutex, RwLock};
|
||||
|
||||
use zerotier_crypto::aes::{Aes, AesGcm};
|
||||
|
@ -61,8 +61,8 @@ pub enum Error {
|
|||
/// Data object is too large to send, even with fragmentation
|
||||
DataTooLarge,
|
||||
|
||||
/// An unexpected I/O error such as a buffer overrun occurred (possible bug)
|
||||
UnexpectedIoError(std::io::Error),
|
||||
/// An unexpected buffer overrun occured while attempting to encode or decode a packet, this can only ever happen if exceptionally large keys are being used (which under p384 would imply there is a bug and potentially an attacker has control of a field they shouldn't), or as the result of an internal encoding bug.
|
||||
UnexpectedBufferOverrun,
|
||||
}
|
||||
|
||||
/// Result generated by the packet receive function, with possible payloads.
|
||||
|
@ -139,14 +139,6 @@ struct EphemeralOffer {
|
|||
// functions
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn from(e: std::io::Error) -> Self {
|
||||
Self::UnexpectedIoError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
@ -161,7 +153,7 @@ impl std::fmt::Display for Error {
|
|||
Self::UnknownProtocolVersion => f.write_str("UnknownProtocolVersion"),
|
||||
Self::DataBufferTooSmall => f.write_str("DataBufferTooSmall"),
|
||||
Self::DataTooLarge => f.write_str("DataTooLarge"),
|
||||
Self::UnexpectedIoError(e) => f.write_str(format!("UnexpectedIoError({})", e.to_string()).as_str()),
|
||||
Self::UnexpectedBufferOverrun => f.write_str("UnexpectedBufferOverrun"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,6 +167,50 @@ impl std::fmt::Debug for Error {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Write src into dest. If dest cannot fit src, nothing at all is written and UnexpectedBufferOverrun is returned. No other errors can be returned by this function. The dest slice is incremented so it starts at the end of where src was written.
|
||||
fn safe_write_all(dest: &mut &mut [u8], src: &[u8]) -> Result<(), Error> {
|
||||
let amt = src.len();
|
||||
if dest.len() >= amt {
|
||||
let (a, b) = mem::replace(dest, &mut []).split_at_mut(amt);
|
||||
a.copy_from_slice(src);
|
||||
*dest = b;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::UnexpectedBufferOverrun)
|
||||
}
|
||||
}
|
||||
/// Write a variable length integer, which can consume up to 10 bytes. Uses safe_write_all to do so.
|
||||
#[inline(always)]
|
||||
pub fn varint_safe_write(dest: &mut &mut [u8], v: u64) -> Result<(), Error> {
|
||||
let mut b = [0_u8; varint::VARINT_MAX_SIZE_BYTES];
|
||||
let i = varint::encode(&mut b, v);
|
||||
safe_write_all(dest, &b[0..i])
|
||||
}
|
||||
|
||||
fn safe_read_exact(src: &mut &[u8], dest: &mut [u8]) -> Result<(), Error> {
|
||||
let amt = dest.len();
|
||||
if src.len() >= amt {
|
||||
let (a, b) = src.split_at(amt);
|
||||
dest.copy_from_slice(a);
|
||||
*src = b;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::InvalidPacket)
|
||||
}
|
||||
}
|
||||
/// Write a variable length integer, which can consume up to 10 bytes. Uses safe_write_all to do so.
|
||||
#[inline(always)]
|
||||
pub fn varint_safe_read(src: &mut &[u8]) -> Result<u64, Error> {
|
||||
let (v, amt) = varint::decode(*src).ok_or(Error::InvalidPacket)?;
|
||||
let (_, b) = src.split_at(amt);
|
||||
*src = b;
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<Layer: ApplicationLayer> Session<Layer> {
|
||||
/// Create a new session and send an initial key offer message to the other end.
|
||||
///
|
||||
|
@ -203,7 +239,7 @@ impl<Layer: ApplicationLayer> Session<Layer> {
|
|||
let send_counter = Counter::new();
|
||||
let bob_s_public_hash = SHA384::hash(bob_s_public_raw);
|
||||
let header_check_cipher =
|
||||
Aes::new(kbkdf512(noise_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<HEADER_CHECK_AES_KEY_SIZE>());
|
||||
Aes::new(kbkdf512(noise_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<HEADER_CHECK_AES_KEY_SIZE>());
|
||||
if let Ok(offer) = send_ephemeral_offer(
|
||||
&mut send,
|
||||
send_counter.next(),
|
||||
|
@ -361,15 +397,16 @@ impl<Layer: ApplicationLayer> Session<Layer> {
|
|||
force_rekey: bool,
|
||||
) {
|
||||
let state = self.state.read().unwrap();
|
||||
if (force_rekey
|
||||
if (
|
||||
force_rekey
|
||||
|| state.session_keys[state.cur_session_key_idx]
|
||||
.as_ref()
|
||||
.map_or(true, |key| key.lifetime.should_rekey(self.send_counter.previous(), current_time)))
|
||||
.as_ref()
|
||||
.map_or(true, |key| key.lifetime.should_rekey(self.send_counter.previous(), current_time)))
|
||||
&& state
|
||||
.offer
|
||||
.as_ref()
|
||||
.map_or(true, |o| (current_time - o.creation_time) > Layer::REKEY_RATE_LIMIT_MS)
|
||||
{
|
||||
.offer
|
||||
.as_ref()
|
||||
.map_or(true, |o| (current_time - o.creation_time) > Layer::REKEY_RATE_LIMIT_MS
|
||||
) {
|
||||
if let Some(remote_s_public) = P384PublicKey::from_bytes(&self.remote_s_public_raw) {
|
||||
if let Ok(offer) = send_ephemeral_offer(
|
||||
&mut send,
|
||||
|
@ -608,9 +645,9 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
if aead_authentication_ok {
|
||||
// Select this key as the new default if it's newer than the current key.
|
||||
if p > 0
|
||||
&& state.session_keys[state.cur_session_key_idx]
|
||||
.as_ref()
|
||||
.map_or(true, |old| old.establish_counter < session_key.establish_counter)
|
||||
&& state.session_keys[state.cur_session_key_idx]
|
||||
.as_ref()
|
||||
.map_or(true, |old| old.establish_counter < session_key.establish_counter)
|
||||
{
|
||||
drop(state);
|
||||
let mut state = session.state.write().unwrap();
|
||||
|
@ -705,9 +742,9 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
|
||||
// Key agreement: alice (remote) ephemeral NIST P-384 <> local static NIST P-384
|
||||
let (alice_e_public, noise_es) =
|
||||
P384PublicKey::from_bytes(&kex_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
|
||||
.and_then(|pk| host.get_local_s_keypair().agree(&pk).map(move |s| (pk, s)))
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
P384PublicKey::from_bytes(&kex_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
|
||||
.and_then(|pk| host.get_local_s_keypair().agree(&pk).map(move |s| (pk, s)))
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
|
||||
// Initial key derivation from starting point, mixing in alice's ephemeral public and the es.
|
||||
let es_key = Secret(hmac_sha512(&hmac_sha512(&INITIAL_KEY, alice_e_public.as_bytes()), noise_es.as_bytes()));
|
||||
|
@ -725,7 +762,7 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
|
||||
// Parse payload and get alice's session ID, alice's public blob, metadata, and (if present) Alice's Kyber1024 public.
|
||||
let (offer_id, alice_session_id, alice_s_public_raw, alice_metadata, alice_hk_public_raw, alice_ratchet_key_fingerprint) =
|
||||
parse_key_offer_after_header(&kex_packet[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..kex_packet_len], packet_type)?;
|
||||
parse_key_offer_after_header(&kex_packet[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..kex_packet_len], packet_type)?;
|
||||
|
||||
// We either have a session, in which case they should have supplied a ratchet key fingerprint, or
|
||||
// we don't and they should not have supplied one.
|
||||
|
@ -738,9 +775,9 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
|
||||
// Key agreement: both sides' static P-384 keys.
|
||||
let noise_ss = host
|
||||
.get_local_s_keypair()
|
||||
.agree(&alice_s_public)
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
.get_local_s_keypair()
|
||||
.agree(&alice_s_public)
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
|
||||
// Mix result of 'ss' agreement into master key.
|
||||
let ss_key = Secret(hmac_sha512(es_key.as_bytes(), noise_ss.as_bytes()));
|
||||
|
@ -789,7 +826,7 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
(None, ratchet_key, ratchet_count)
|
||||
} else {
|
||||
if let Some((new_session_id, psk, associated_object)) =
|
||||
host.accept_new_session(self, remote_address, alice_s_public_raw, alice_metadata)
|
||||
host.accept_new_session(self, remote_address, alice_s_public_raw, alice_metadata)
|
||||
{
|
||||
let header_check_cipher = Aes::new(
|
||||
kbkdf512(noise_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<HEADER_CHECK_AES_KEY_SIZE>(),
|
||||
|
@ -868,24 +905,25 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
let mut reply_len = {
|
||||
let mut rp = &mut reply_buf[HEADER_SIZE..];
|
||||
|
||||
rp.write_all(&[SESSION_PROTOCOL_VERSION])?;
|
||||
rp.write_all(bob_e_keypair.public_key_bytes())?;
|
||||
|
||||
rp.write_all(&offer_id)?;
|
||||
rp.write_all(&session.id.0.to_le_bytes()[..SESSION_ID_SIZE])?;
|
||||
varint::write(&mut rp, 0)?; // they don't need our static public; they have it
|
||||
varint::write(&mut rp, 0)?; // no meta-data in counter-offers (could be used in the future)
|
||||
safe_write_all(&mut rp, &[SESSION_PROTOCOL_VERSION])?;
|
||||
safe_write_all(&mut rp, bob_e_keypair.public_key_bytes())?;
|
||||
|
||||
safe_write_all(&mut rp, &offer_id)?;
|
||||
safe_write_all(&mut rp, &session.id.0.to_le_bytes()[..SESSION_ID_SIZE])?;
|
||||
varint_safe_write(&mut rp, 0)?; // they don't need our static public; they have it
|
||||
varint_safe_write(&mut rp, 0)?; // no meta-data in counter-offers (could be used in the future)
|
||||
if let Some(bob_hk_public) = bob_hk_public.as_ref() {
|
||||
rp.write_all(&[E1_TYPE_KYBER1024])?;
|
||||
rp.write_all(bob_hk_public)?;
|
||||
safe_write_all(&mut rp, &[E1_TYPE_KYBER1024])?;
|
||||
safe_write_all(&mut rp, bob_hk_public)?;
|
||||
} else {
|
||||
rp.write_all(&[E1_TYPE_NONE])?;
|
||||
safe_write_all(&mut rp, &[E1_TYPE_NONE])?;
|
||||
}
|
||||
if ratchet_key.is_some() {
|
||||
rp.write_all(&[0x01])?;
|
||||
rp.write_all(alice_ratchet_key_fingerprint.as_ref().unwrap())?;
|
||||
safe_write_all(&mut rp, &[0x01])?;
|
||||
safe_write_all(&mut rp, alice_ratchet_key_fingerprint.as_ref().unwrap())?;
|
||||
} else {
|
||||
rp.write_all(&[0x00])?;
|
||||
safe_write_all(&mut rp, &[0x00])?;
|
||||
}
|
||||
|
||||
KEX_BUF_LEN - rp.len()
|
||||
|
@ -899,7 +937,7 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
reply_counter,
|
||||
)?;
|
||||
let reply_canonical_header =
|
||||
CanonicalHeader::make(alice_session_id.into(), PACKET_TYPE_KEY_COUNTER_OFFER, reply_counter.to_u32());
|
||||
CanonicalHeader::make(alice_session_id.into(), PACKET_TYPE_KEY_COUNTER_OFFER, reply_counter.to_u32());
|
||||
|
||||
// Encrypt reply packet using final Noise_IK key BEFORE mixing hybrid or ratcheting, since the other side
|
||||
// must decrypt before doing these things.
|
||||
|
@ -966,13 +1004,13 @@ impl<Layer: ApplicationLayer> ReceiveContext<Layer> {
|
|||
let state = session.state.read().unwrap();
|
||||
if let Some(offer) = state.offer.as_ref() {
|
||||
let (bob_e_public, noise_ee) =
|
||||
P384PublicKey::from_bytes(&kex_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
|
||||
.and_then(|pk| offer.alice_e_keypair.agree(&pk).map(move |s| (pk, s)))
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
P384PublicKey::from_bytes(&kex_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
|
||||
.and_then(|pk| offer.alice_e_keypair.agree(&pk).map(move |s| (pk, s)))
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
let noise_se = host
|
||||
.get_local_s_keypair()
|
||||
.agree(&bob_e_public)
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
.get_local_s_keypair()
|
||||
.agree(&bob_e_public)
|
||||
.ok_or(Error::FailedAuthentication)?;
|
||||
|
||||
let noise_ik_key = Secret(hmac_sha512(
|
||||
session.psk.as_bytes(),
|
||||
|
@ -1124,26 +1162,26 @@ fn send_ephemeral_offer<SendFunction: FnMut(&mut [u8])>(
|
|||
let mut packet_len = {
|
||||
let mut p = &mut packet_buf[HEADER_SIZE..];
|
||||
|
||||
p.write_all(&[SESSION_PROTOCOL_VERSION])?;
|
||||
p.write_all(alice_e_keypair.public_key_bytes())?;
|
||||
safe_write_all(&mut p, &[SESSION_PROTOCOL_VERSION])?;
|
||||
safe_write_all(&mut p, alice_e_keypair.public_key_bytes())?;
|
||||
|
||||
p.write_all(&id)?;
|
||||
p.write_all(&alice_session_id.0.to_le_bytes()[..SESSION_ID_SIZE])?;
|
||||
varint::write(&mut p, alice_s_public.len() as u64)?;
|
||||
p.write_all(alice_s_public)?;
|
||||
varint::write(&mut p, alice_metadata.len() as u64)?;
|
||||
p.write_all(alice_metadata)?;
|
||||
safe_write_all(&mut p, &id)?;
|
||||
safe_write_all(&mut p, &alice_session_id.0.to_le_bytes()[..SESSION_ID_SIZE])?;
|
||||
varint_safe_write(&mut p, alice_s_public.len() as u64)?;
|
||||
safe_write_all(&mut p, alice_s_public)?;
|
||||
varint_safe_write(&mut p, alice_metadata.len() as u64)?;
|
||||
safe_write_all(&mut p, alice_metadata)?;
|
||||
if let Some(hkkp) = alice_hk_keypair {
|
||||
p.write_all(&[E1_TYPE_KYBER1024])?;
|
||||
p.write_all(&hkkp.public)?;
|
||||
safe_write_all(&mut p, &[E1_TYPE_KYBER1024])?;
|
||||
safe_write_all(&mut p, &hkkp.public)?;
|
||||
} else {
|
||||
p.write_all(&[E1_TYPE_NONE])?;
|
||||
safe_write_all(&mut p, &[E1_TYPE_NONE])?;
|
||||
}
|
||||
if let Some(ratchet_key) = ratchet_key.as_ref() {
|
||||
p.write_all(&[0x01])?;
|
||||
p.write_all(&secret_fingerprint(ratchet_key.as_bytes())[..16])?;
|
||||
safe_write_all(&mut p, &[0x01])?;
|
||||
safe_write_all(&mut p, &secret_fingerprint(ratchet_key.as_bytes())[..16])?;
|
||||
} else {
|
||||
p.write_all(&[0x00])?;
|
||||
safe_write_all(&mut p, &[0x00])?;
|
||||
}
|
||||
|
||||
PACKET_BUF_SIZE - p.len()
|
||||
|
@ -1243,7 +1281,7 @@ fn create_packet_header(
|
|||
memory::store_raw((counter.to_u32() as u64).to_le(), header);
|
||||
memory::store_raw(
|
||||
(u64::from(recipient_session_id) | (packet_type as u64).wrapping_shl(48) | ((fragment_count - 1) as u64).wrapping_shl(52))
|
||||
.to_le(),
|
||||
.to_le(),
|
||||
&mut header[8..],
|
||||
);
|
||||
Ok(())
|
||||
|
@ -1306,19 +1344,22 @@ fn parse_key_offer_after_header(
|
|||
) -> Result<([u8; 16], SessionId, &[u8], &[u8], &[u8], Option<[u8; 16]>), Error> {
|
||||
let mut p = &incoming_packet[..];
|
||||
let mut offer_id = [0_u8; 16];
|
||||
p.read_exact(&mut offer_id)?;
|
||||
let alice_session_id = SessionId::new_from_reader(&mut p)?;
|
||||
safe_read_exact(&mut p, &mut offer_id)?;
|
||||
|
||||
let mut session_id_buf = 0_u64.to_ne_bytes();
|
||||
safe_read_exact(&mut p, &mut session_id_buf[..SESSION_ID_SIZE])?;
|
||||
let alice_session_id = SessionId::new_from_u64(u64::from_le_bytes(session_id_buf));
|
||||
if alice_session_id.is_none() {
|
||||
return Err(Error::InvalidPacket);
|
||||
}
|
||||
let alice_session_id = alice_session_id.unwrap();
|
||||
let alice_s_public_len = varint::read(&mut p)?.0;
|
||||
let alice_s_public_len = varint_safe_read(&mut p)?;
|
||||
if (p.len() as u64) < alice_s_public_len {
|
||||
return Err(Error::InvalidPacket);
|
||||
}
|
||||
let alice_s_public = &p[..(alice_s_public_len as usize)];
|
||||
p = &p[(alice_s_public_len as usize)..];
|
||||
let alice_metadata_len = varint::read(&mut p)?.0;
|
||||
let alice_metadata_len = varint_safe_read(&mut p)?;
|
||||
if (p.len() as u64) < alice_metadata_len {
|
||||
return Err(Error::InvalidPacket);
|
||||
}
|
||||
|
@ -1380,12 +1421,12 @@ impl KeyLifetime {
|
|||
fn new(current_counter: CounterValue, current_time: i64) -> Self {
|
||||
Self {
|
||||
rekey_at_or_after_counter: current_counter.0
|
||||
+ REKEY_AFTER_USES
|
||||
+ (random::next_u32_secure() % REKEY_AFTER_USES_MAX_JITTER) as u64,
|
||||
+ REKEY_AFTER_USES
|
||||
+ (random::next_u32_secure() % REKEY_AFTER_USES_MAX_JITTER) as u64,
|
||||
hard_expire_at_counter: current_counter.0 + EXPIRE_AFTER_USES,
|
||||
rekey_at_or_after_timestamp: current_time
|
||||
+ REKEY_AFTER_TIME_MS
|
||||
+ (random::next_u32_secure() % REKEY_AFTER_TIME_MS_MAX_JITTER) as i64,
|
||||
+ REKEY_AFTER_TIME_MS
|
||||
+ (random::next_u32_secure() % REKEY_AFTER_TIME_MS_MAX_JITTER) as i64,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1442,12 +1483,14 @@ impl SessionKey {
|
|||
#[inline]
|
||||
fn get_send_cipher(&self, counter: CounterValue) -> Result<Box<AesGcm>, Error> {
|
||||
if !self.lifetime.expired(counter) {
|
||||
Ok(self
|
||||
Ok(
|
||||
self
|
||||
.send_cipher_pool
|
||||
.lock()
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap_or_else(|| Box::new(AesGcm::new(self.send_key.as_bytes(), true))))
|
||||
.unwrap_or_else(|| Box::new(AesGcm::new(self.send_key.as_bytes(), true)))
|
||||
)
|
||||
} else {
|
||||
// Not only do we return an error, but we also destroy the key.
|
||||
let mut scp = self.send_cipher_pool.lock().unwrap();
|
||||
|
@ -1466,10 +1509,10 @@ impl SessionKey {
|
|||
#[inline]
|
||||
fn get_receive_cipher(&self) -> Box<AesGcm> {
|
||||
self.receive_cipher_pool
|
||||
.lock()
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap_or_else(|| Box::new(AesGcm::new(self.receive_key.as_bytes(), false)))
|
||||
.lock()
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap_or_else(|| Box::new(AesGcm::new(self.receive_key.as_bytes(), false)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Add table
Reference in a new issue