Rekeying is now tested and works.

This commit is contained in:
Adam Ierymenko 2023-03-01 14:01:30 -05:00
parent 652f7360f0
commit 8b6c9051fb
4 changed files with 158 additions and 107 deletions

View file

@ -31,7 +31,7 @@ pub trait ApplicationLayer: Sized {
/// Attempting to encrypt more than this many messages with a key will cause a hard error /// Attempting to encrypt more than this many messages with a key will cause a hard error
/// and the internal erasure of ephemeral key material. You'll only ever hit this if something /// and the internal erasure of ephemeral key material. You'll only ever hit this if something
/// goes wrong and rekeying fails. /// goes wrong and rekeying fails.
const EXPIRE_AFTER_USES: u64 = 2147483648; const EXPIRE_AFTER_USES: u64 = 2147483647;
/// Start attempting to rekey after a key has been in use for this many milliseconds. /// Start attempting to rekey after a key has been in use for this many milliseconds.
/// ///

View file

@ -14,7 +14,7 @@ struct TestApplication {
} }
impl zssp::ApplicationLayer for TestApplication { impl zssp::ApplicationLayer for TestApplication {
const REKEY_AFTER_USES: u64 = 131072; const REKEY_AFTER_USES: u64 = 100000;
const EXPIRE_AFTER_USES: u64 = 2147483648; const EXPIRE_AFTER_USES: u64 = 2147483648;
const REKEY_AFTER_TIME_MS: i64 = 1000 * 60 * 60 * 2; const REKEY_AFTER_TIME_MS: i64 = 1000 * 60 * 60 * 2;
const REKEY_AFTER_TIME_MS_MAX_JITTER: u32 = 1000 * 60 * 10; const REKEY_AFTER_TIME_MS_MAX_JITTER: u32 = 1000 * 60 * 10;
@ -44,6 +44,9 @@ fn alice_main(
let context = zssp::Context::<TestApplication>::new(16); let context = zssp::Context::<TestApplication>::new(16);
let mut data_buf = [0u8; 65536]; let mut data_buf = [0u8; 65536];
let mut next_service = ms_monotonic() + 500; let mut next_service = ms_monotonic() + 500;
let mut last_ratchet_count = 0;
let test_data = [1u8; 10000];
let mut up = false;
let alice_session = context let alice_session = context
.open( .open(
@ -62,51 +65,57 @@ fn alice_main(
println!("[alice] opening session {}", alice_session.id.to_string()); println!("[alice] opening session {}", alice_session.id.to_string());
let test_data = [1u8; 10000];
let mut up = false;
while run.load(Ordering::Relaxed) { while run.load(Ordering::Relaxed) {
let pkt = alice_in.try_recv();
let current_time = ms_monotonic(); let current_time = ms_monotonic();
loop {
if let Ok(pkt) = pkt { let pkt = alice_in.try_recv();
//println!("bob >> alice {}", pkt.len()); if let Ok(pkt) = pkt {
match context.receive( //println!("bob >> alice {}", pkt.len());
alice_app, match context.receive(
|| true, alice_app,
|s_public, _| Some((P384PublicKey::from_bytes(s_public).unwrap(), Secret::default(), ())), || true,
|_, b| { |s_public, _| Some((P384PublicKey::from_bytes(s_public).unwrap(), Secret::default(), ())),
let _ = alice_out.send(b.to_vec()); |_, b| {
}, let _ = alice_out.send(b.to_vec());
&mut data_buf, },
pkt, &mut data_buf,
TEST_MTU, pkt,
current_time, TEST_MTU,
) { current_time,
Ok(zssp::ReceiveResult::Ok) => { ) {
//println!("[alice] ok"); Ok(zssp::ReceiveResult::Ok) => {
} //println!("[alice] ok");
Ok(zssp::ReceiveResult::OkData(_, _)) => { }
//println!("[alice] received {}", data.len()); Ok(zssp::ReceiveResult::OkData(_, data)) => {
} //println!("[alice] received {}", data.len());
Ok(zssp::ReceiveResult::OkNewSession(s)) => { }
println!("[alice] new session {}", s.id.to_string()); Ok(zssp::ReceiveResult::OkNewSession(s)) => {
} println!("[alice] new session {}", s.id.to_string());
Ok(zssp::ReceiveResult::Rejected) => {} }
Err(e) => { Ok(zssp::ReceiveResult::Rejected) => {}
println!("[alice] ERROR {}", e.to_string()); Err(e) => {
println!("[alice] ERROR {}", e.to_string());
}
} }
} else {
break;
} }
} }
if up { if up {
let ratchet_count = alice_session.key_info().unwrap().0;
if ratchet_count > last_ratchet_count {
last_ratchet_count = ratchet_count;
println!("[alice] new key! ratchet count {}", ratchet_count);
}
assert!(alice_session assert!(alice_session
.send( .send(
|b| { |b| {
let _ = alice_out.send(b.to_vec()); let _ = alice_out.send(b.to_vec());
}, },
&mut data_buf[..TEST_MTU], &mut data_buf[..TEST_MTU],
&test_data[..2048 + ((zerotier_crypto::random::xorshift64_random() as usize) % (test_data.len() - 2048))], &test_data[..1000 + ((zerotier_crypto::random::xorshift64_random() as usize) % (test_data.len() - 1000))],
) )
.is_ok()); .is_ok());
} else { } else {
@ -137,6 +146,8 @@ fn bob_main(
) { ) {
let context = zssp::Context::<TestApplication>::new(16); let context = zssp::Context::<TestApplication>::new(16);
let mut data_buf = [0u8; 65536]; let mut data_buf = [0u8; 65536];
let mut data_buf_2 = [0u8; TEST_MTU];
let mut last_ratchet_count = 0;
let mut last_speed_metric = ms_monotonic(); let mut last_speed_metric = ms_monotonic();
let mut next_service = last_speed_metric + 500; let mut next_service = last_speed_metric + 500;
let mut transferred = 0u64; let mut transferred = 0u64;
@ -144,7 +155,7 @@ fn bob_main(
let mut bob_session = None; let mut bob_session = None;
while run.load(Ordering::Relaxed) { while run.load(Ordering::Relaxed) {
let pkt = bob_in.recv_timeout(Duration::from_millis(10)); let pkt = bob_in.recv_timeout(Duration::from_millis(100));
let current_time = ms_monotonic(); let current_time = ms_monotonic();
if let Ok(pkt) = pkt { if let Ok(pkt) = pkt {
@ -164,9 +175,18 @@ fn bob_main(
Ok(zssp::ReceiveResult::Ok) => { Ok(zssp::ReceiveResult::Ok) => {
//println!("[bob] ok"); //println!("[bob] ok");
} }
Ok(zssp::ReceiveResult::OkData(_, data)) => { Ok(zssp::ReceiveResult::OkData(s, data)) => {
//println!("[bob] received {}", data.len()); //println!("[bob] received {}", data.len());
transferred += data.len() as u64; transferred += data.len() as u64;
assert!(s
.send(
|b| {
let _ = bob_out.send(b.to_vec());
},
&mut data_buf_2,
data.as_mut(),
)
.is_ok());
} }
Ok(zssp::ReceiveResult::OkNewSession(s)) => { Ok(zssp::ReceiveResult::OkNewSession(s)) => {
println!("[bob] new session {}", s.id.to_string()); println!("[bob] new session {}", s.id.to_string());
@ -179,6 +199,14 @@ fn bob_main(
} }
} }
if let Some(bob_session) = bob_session.as_ref() {
let ratchet_count = bob_session.key_info().unwrap().0;
if ratchet_count > last_ratchet_count {
last_ratchet_count = ratchet_count;
println!("[bob] new key! ratchet count {}", ratchet_count);
}
}
let speed_metric_elapsed = current_time - last_speed_metric; let speed_metric_elapsed = current_time - last_speed_metric;
if speed_metric_elapsed >= 1000 { if speed_metric_elapsed >= 1000 {
last_speed_metric = current_time; last_speed_metric = current_time;
@ -208,8 +236,8 @@ fn main() {
let alice_app = TestApplication { identity_key: P384KeyPair::generate() }; let alice_app = TestApplication { identity_key: P384KeyPair::generate() };
let bob_app = TestApplication { identity_key: P384KeyPair::generate() }; let bob_app = TestApplication { identity_key: P384KeyPair::generate() };
let (alice_out, bob_in) = mpsc::sync_channel::<Vec<u8>>(128); let (alice_out, bob_in) = mpsc::sync_channel::<Vec<u8>>(1024);
let (bob_out, alice_in) = mpsc::sync_channel::<Vec<u8>>(128); let (bob_out, alice_in) = mpsc::sync_channel::<Vec<u8>>(1024);
thread::scope(|ts| { thread::scope(|ts| {
let alice_thread = ts.spawn(|| alice_main(&run, &alice_app, &bob_app, alice_out, alice_in)); let alice_thread = ts.spawn(|| alice_main(&run, &alice_app, &bob_app, alice_out, alice_in));

View file

@ -33,8 +33,8 @@ pub(crate) const PACKET_TYPE_DATA: u8 = 0;
pub(crate) const PACKET_TYPE_ALICE_NOISE_XK_INIT: u8 = 1; pub(crate) const PACKET_TYPE_ALICE_NOISE_XK_INIT: u8 = 1;
pub(crate) const PACKET_TYPE_BOB_NOISE_XK_ACK: u8 = 2; pub(crate) const PACKET_TYPE_BOB_NOISE_XK_ACK: u8 = 2;
pub(crate) const PACKET_TYPE_ALICE_NOISE_XK_ACK: u8 = 3; pub(crate) const PACKET_TYPE_ALICE_NOISE_XK_ACK: u8 = 3;
pub(crate) const PACKET_TYPE_ALICE_REKEY_INIT: u8 = 4; pub(crate) const PACKET_TYPE_REKEY_INIT: u8 = 4;
pub(crate) const PACKET_TYPE_BOB_REKEY_ACK: u8 = 5; pub(crate) const PACKET_TYPE_REKEY_ACK: u8 = 5;
pub(crate) const HEADER_SIZE: usize = 16; pub(crate) const HEADER_SIZE: usize = 16;
pub(crate) const HEADER_PROTECT_ENCRYPT_START: usize = 6; pub(crate) const HEADER_PROTECT_ENCRYPT_START: usize = 6;
@ -123,24 +123,26 @@ pub(crate) const ALICE_NOISE_XK_ACK_MIN_SIZE: usize = ALICE_NOISE_XK_ACK_ENC_STA
#[allow(unused)] #[allow(unused)]
#[repr(C, packed)] #[repr(C, packed)]
pub(crate) struct AliceRekeyInit { pub(crate) struct RekeyInit {
pub header: [u8; HEADER_SIZE], pub header: [u8; HEADER_SIZE],
pub session_protocol_version: u8,
// -- start AES-GCM encrypted portion (using current key) // -- start AES-GCM encrypted portion (using current key)
pub alice_e: [u8; P384_PUBLIC_KEY_SIZE], pub alice_e: [u8; P384_PUBLIC_KEY_SIZE],
// -- end AES-GCM encrypted portion // -- end AES-GCM encrypted portion
pub gcm_mac: [u8; AES_GCM_TAG_SIZE], pub gcm_mac: [u8; AES_GCM_TAG_SIZE],
} }
impl AliceRekeyInit { impl RekeyInit {
pub const ENC_START: usize = HEADER_SIZE; pub const ENC_START: usize = HEADER_SIZE + 1;
pub const AUTH_START: usize = Self::ENC_START + P384_PUBLIC_KEY_SIZE; pub const AUTH_START: usize = Self::ENC_START + P384_PUBLIC_KEY_SIZE;
pub const SIZE: usize = Self::AUTH_START + AES_GCM_TAG_SIZE; pub const SIZE: usize = Self::AUTH_START + AES_GCM_TAG_SIZE;
} }
#[allow(unused)] #[allow(unused)]
#[repr(C, packed)] #[repr(C, packed)]
pub(crate) struct BobRekeyAck { pub(crate) struct RekeyAck {
pub header: [u8; HEADER_SIZE], pub header: [u8; HEADER_SIZE],
pub session_protocol_version: u8,
// -- start AES-GCM encrypted portion (using current key) // -- start AES-GCM encrypted portion (using current key)
pub bob_e: [u8; P384_PUBLIC_KEY_SIZE], pub bob_e: [u8; P384_PUBLIC_KEY_SIZE],
pub next_key_fingerprint: [u8; SHA384_HASH_SIZE], pub next_key_fingerprint: [u8; SHA384_HASH_SIZE],
@ -148,8 +150,8 @@ pub(crate) struct BobRekeyAck {
pub gcm_mac: [u8; AES_GCM_TAG_SIZE], pub gcm_mac: [u8; AES_GCM_TAG_SIZE],
} }
impl BobRekeyAck { impl RekeyAck {
pub const ENC_START: usize = HEADER_SIZE; pub const ENC_START: usize = HEADER_SIZE + 1;
pub const AUTH_START: usize = Self::ENC_START + P384_PUBLIC_KEY_SIZE + SHA384_HASH_SIZE; pub const AUTH_START: usize = Self::ENC_START + P384_PUBLIC_KEY_SIZE + SHA384_HASH_SIZE;
pub const SIZE: usize = Self::AUTH_START + AES_GCM_TAG_SIZE; pub const SIZE: usize = Self::AUTH_START + AES_GCM_TAG_SIZE;
} }
@ -161,8 +163,8 @@ pub(crate) trait ProtocolFlatBuffer {}
impl ProtocolFlatBuffer for AliceNoiseXKInit {} impl ProtocolFlatBuffer for AliceNoiseXKInit {}
impl ProtocolFlatBuffer for BobNoiseXKAck {} impl ProtocolFlatBuffer for BobNoiseXKAck {}
//impl ProtocolFlatBuffer for NoiseXKAliceStaticAck {} //impl ProtocolFlatBuffer for NoiseXKAliceStaticAck {}
impl ProtocolFlatBuffer for AliceRekeyInit {} impl ProtocolFlatBuffer for RekeyInit {}
impl ProtocolFlatBuffer for BobRekeyAck {} impl ProtocolFlatBuffer for RekeyAck {}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(C, packed)] #[repr(C, packed)]

View file

@ -119,7 +119,7 @@ struct OutgoingSessionInit {
enum Offer { enum Offer {
None, None,
NoiseXKInit(Box<OutgoingSessionInit>), NoiseXKInit(Box<OutgoingSessionInit>),
RekeyInit(P384KeyPair, [u8; AliceRekeyInit::SIZE], AtomicI64), RekeyInit(P384KeyPair, [u8; RekeyInit::SIZE], AtomicI64),
} }
/// An ephemeral session key with expiration info. /// An ephemeral session key with expiration info.
@ -181,6 +181,7 @@ impl<Application: ApplicationLayer> Context<Application> {
&& (current_time >= key.rekey_at_time && (current_time >= key.rekey_at_time
|| session.send_counter.load(Ordering::Relaxed) >= key.rekey_at_counter) || session.send_counter.load(Ordering::Relaxed) >= key.rekey_at_counter)
{ {
drop(state);
session.initiate_rekey(|b| send(&session, b), current_time); session.initiate_rekey(|b| send(&session, b), current_time);
} }
} }
@ -1106,8 +1107,8 @@ impl<Application: ApplicationLayer> Context<Application> {
} }
} }
PACKET_TYPE_ALICE_REKEY_INIT => { PACKET_TYPE_REKEY_INIT => {
if pkt_assembled.len() != AliceRekeyInit::SIZE { if pkt_assembled.len() != RekeyInit::SIZE {
return Err(Error::InvalidPacket); return Err(Error::InvalidPacket);
} }
if incoming.is_some() { if incoming.is_some() {
@ -1116,58 +1117,74 @@ impl<Application: ApplicationLayer> Context<Application> {
if let Some(session) = session { if let Some(session) = session {
let state = session.state.read().unwrap(); let state = session.state.read().unwrap();
if let Some(key) = state.keys[key_index].as_ref() { if let Some(remote_session_id) = state.remote_session_id {
// Only the current "Alice" accepts rekeys initiated by the current "Bob." These roles if let Some(key) = state.keys[key_index].as_ref() {
// flip with each rekey event. // Only the current "Alice" accepts rekeys initiated by the current "Bob." These roles
if !key.bob { // flip with each rekey event.
let mut c = key.get_receive_cipher(); if !key.bob {
c.reset_init_gcm(&incoming_message_nonce); let mut c = key.get_receive_cipher();
c.crypt_in_place(&mut pkt_assembled[AliceRekeyInit::ENC_START..AliceRekeyInit::AUTH_START]); c.reset_init_gcm(&incoming_message_nonce);
let aead_authentication_ok = c.finish_decrypt(&pkt_assembled[AliceRekeyInit::AUTH_START..]); c.crypt_in_place(&mut pkt_assembled[RekeyInit::ENC_START..RekeyInit::AUTH_START]);
key.return_receive_cipher(c); let aead_authentication_ok = c.finish_decrypt(&pkt_assembled[RekeyInit::AUTH_START..]);
key.return_receive_cipher(c);
if aead_authentication_ok { if aead_authentication_ok {
let pkt: &AliceRekeyInit = 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();
let next_session_key = Secret(hmac_sha512( let next_session_key = Secret(hmac_sha512(
key.ratchet_key.as_bytes(), key.ratchet_key.as_bytes(),
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; BobRekeyAck::SIZE]; let mut reply_buf = [0u8; RekeyAck::SIZE];
let reply: &mut BobRekeyAck = byte_array_as_proto_buffer_mut(&mut reply_buf).unwrap(); let reply: &mut RekeyAck = byte_array_as_proto_buffer_mut(&mut reply_buf).unwrap();
reply.bob_e = *bob_e_secret.public_key_bytes(); reply.session_protocol_version = SESSION_PROTOCOL_VERSION;
reply.next_key_fingerprint = SHA384::hash(next_session_key.as_bytes()); 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)?; let counter = session.get_next_outgoing_counter().ok_or(Error::MaxKeyLifetimeExceeded)?.get();
let mut c = key.get_send_cipher(counter.get())?; set_packet_header(
c.reset_init_gcm(&create_message_nonce(PACKET_TYPE_BOB_REKEY_ACK, counter.get())); &mut reply_buf,
c.crypt_in_place(&mut reply_buf[BobRekeyAck::ENC_START..BobRekeyAck::AUTH_START]); 1,
reply_buf[BobRekeyAck::AUTH_START..].copy_from_slice(&c.finish_encrypt()); 0,
key.return_send_cipher(c); PACKET_TYPE_REKEY_ACK,
u64::from(remote_session_id),
state.current_key,
counter,
);
send(Some(&session), &mut reply_buf); let mut c = key.get_send_cipher(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]);
reply_buf[RekeyAck::AUTH_START..].copy_from_slice(&c.finish_encrypt());
key.return_send_cipher(c);
// The new "Bob" doesn't know yet if Alice has received the new key, so the session.header_protection_cipher.encrypt_block_in_place(
// new key is recorded as the "alt" (key_index ^ 1) but the current key is &mut reply_buf[HEADER_PROTECT_ENCRYPT_START..HEADER_PROTECT_ENCRYPT_END],
// not advanced yet. This happens automatically the first time we receive a );
// valid packet with the new key. send(Some(&session), &mut reply_buf);
let next_ratchet_count = key.ratchet_count + 1;
drop(state);
let mut state = session.state.write().unwrap();
let _ = state.keys[key_index ^ 1].replace(SessionKey::new::<Application>(
next_session_key,
next_ratchet_count,
current_time,
counter.get(),
false,
));
return Ok(ReceiveResult::Ok); // 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
// not advanced yet. This happens automatically the first time we receive a
// valid packet with the new key.
let next_ratchet_count = key.ratchet_count + 1;
drop(state);
let mut state = session.state.write().unwrap();
let _ = state.keys[key_index ^ 1].replace(SessionKey::new::<Application>(
next_session_key,
next_ratchet_count,
current_time,
counter,
false,
));
return Ok(ReceiveResult::Ok);
}
} }
return Err(Error::FailedAuthentication);
} }
return Err(Error::FailedAuthentication);
} }
} }
return Err(Error::OutOfSequence); return Err(Error::OutOfSequence);
@ -1176,8 +1193,8 @@ impl<Application: ApplicationLayer> Context<Application> {
} }
} }
PACKET_TYPE_BOB_REKEY_ACK => { PACKET_TYPE_REKEY_ACK => {
if pkt_assembled.len() != BobRekeyAck::SIZE { if pkt_assembled.len() != RekeyAck::SIZE {
return Err(Error::InvalidPacket); return Err(Error::InvalidPacket);
} }
if incoming.is_some() { if incoming.is_some() {
@ -1192,12 +1209,12 @@ impl<Application: ApplicationLayer> Context<Application> {
if key.bob { if key.bob {
let mut c = key.get_receive_cipher(); let mut c = key.get_receive_cipher();
c.reset_init_gcm(&incoming_message_nonce); c.reset_init_gcm(&incoming_message_nonce);
c.crypt_in_place(&mut pkt_assembled[BobRekeyAck::ENC_START..BobRekeyAck::AUTH_START]); c.crypt_in_place(&mut pkt_assembled[RekeyAck::ENC_START..RekeyAck::AUTH_START]);
let aead_authentication_ok = c.finish_decrypt(&pkt_assembled[BobRekeyAck::AUTH_START..]); let aead_authentication_ok = c.finish_decrypt(&pkt_assembled[RekeyAck::AUTH_START..]);
key.return_receive_cipher(c); key.return_receive_cipher(c);
if aead_authentication_ok { if aead_authentication_ok {
let pkt: &BobRekeyAck = 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) {
let next_session_key = Secret(hmac_sha512( let next_session_key = Secret(hmac_sha512(
key.ratchet_key.as_bytes(), key.ratchet_key.as_bytes(),
@ -1333,8 +1350,9 @@ impl<Application: ApplicationLayer> Session<Application> {
fn initiate_rekey<SendFunction: FnMut(&mut [u8])>(&self, mut send: SendFunction, current_time: i64) { fn initiate_rekey<SendFunction: FnMut(&mut [u8])>(&self, mut send: SendFunction, current_time: i64) {
let rekey_e = P384KeyPair::generate(); let rekey_e = P384KeyPair::generate();
let mut rekey_buf = [0u8; AliceRekeyInit::SIZE]; let mut rekey_buf = [0u8; RekeyInit::SIZE];
let pkt: &mut AliceRekeyInit = byte_array_as_proto_buffer_mut(&mut rekey_buf).unwrap(); let pkt: &mut RekeyInit = byte_array_as_proto_buffer_mut(&mut rekey_buf).unwrap();
pkt.session_protocol_version = SESSION_PROTOCOL_VERSION;
pkt.alice_e = *rekey_e.public_key_bytes(); pkt.alice_e = *rekey_e.public_key_bytes();
let state = self.state.read().unwrap(); let state = self.state.read().unwrap();
@ -1342,9 +1360,9 @@ impl<Application: ApplicationLayer> Session<Application> {
if let Some(key) = state.keys[state.current_key].as_ref() { if let Some(key) = state.keys[state.current_key].as_ref() {
if let Some(counter) = self.get_next_outgoing_counter() { if let Some(counter) = self.get_next_outgoing_counter() {
if let Ok(mut gcm) = key.get_send_cipher(counter.get()) { if let Ok(mut gcm) = key.get_send_cipher(counter.get()) {
gcm.reset_init_gcm(&create_message_nonce(PACKET_TYPE_ALICE_REKEY_INIT, counter.get())); gcm.reset_init_gcm(&create_message_nonce(PACKET_TYPE_REKEY_INIT, counter.get()));
gcm.crypt_in_place(&mut rekey_buf[AliceRekeyInit::ENC_START..AliceRekeyInit::AUTH_START]); gcm.crypt_in_place(&mut rekey_buf[RekeyInit::ENC_START..RekeyInit::AUTH_START]);
rekey_buf[AliceRekeyInit::AUTH_START..].copy_from_slice(&gcm.finish_encrypt()); rekey_buf[RekeyInit::AUTH_START..].copy_from_slice(&gcm.finish_encrypt());
key.return_send_cipher(gcm); key.return_send_cipher(gcm);
debug_assert!(rekey_buf.len() <= MIN_TRANSPORT_MTU); debug_assert!(rekey_buf.len() <= MIN_TRANSPORT_MTU);
@ -1352,15 +1370,18 @@ impl<Application: ApplicationLayer> Session<Application> {
&mut rekey_buf, &mut rekey_buf,
1, 1,
0, 0,
PACKET_TYPE_ALICE_REKEY_INIT, PACKET_TYPE_REKEY_INIT,
u64::from(remote_session_id), u64::from(remote_session_id),
state.current_key, state.current_key,
counter.get(), counter.get(),
); );
drop(state);
self.header_protection_cipher
.encrypt_block_in_place(&mut rekey_buf[HEADER_PROTECT_ENCRYPT_START..HEADER_PROTECT_ENCRYPT_END]);
send(&mut rekey_buf); send(&mut rekey_buf);
drop(state);
self.state.write().unwrap().current_offer = Offer::RekeyInit(rekey_e, rekey_buf, AtomicI64::new(current_time)); self.state.write().unwrap().current_offer = Offer::RekeyInit(rekey_e, rekey_buf, AtomicI64::new(current_time));
} }
} }