fips_core/peer/active/
rekey.rs1use super::*;
2
3impl ActivePeer {
4 pub fn session_established_at(&self) -> Instant {
8 self.session_established_at
9 }
10
11 #[cfg(test)]
12 pub(crate) fn set_session_established_at_for_test(&mut self, instant: Instant) {
13 self.session_established_at = instant;
14 }
15
16 pub fn rekey_jitter_secs(&self) -> i64 {
18 self.rekey_jitter_secs
19 }
20
21 pub fn current_k_bit(&self) -> bool {
23 self.current_k_bit
24 }
25
26 pub fn rekey_in_progress(&self) -> bool {
28 self.rekey_in_progress
29 }
30
31 pub fn set_rekey_in_progress(&mut self) {
33 self.rekey_in_progress = true;
34 }
35
36 pub fn is_rekey_dampened(&self, dampening_secs: u64) -> bool {
38 match self.last_peer_rekey {
39 Some(t) => t.elapsed().as_secs() < dampening_secs,
40 None => false,
41 }
42 }
43
44 pub fn record_peer_rekey(&mut self) {
46 self.last_peer_rekey = Some(Instant::now());
47 }
48
49 pub fn pending_our_index(&self) -> Option<SessionIndex> {
51 self.pending_our_index
52 }
53
54 pub fn pending_their_index(&self) -> Option<SessionIndex> {
56 self.pending_their_index
57 }
58
59 pub fn previous_our_index(&self) -> Option<SessionIndex> {
61 self.previous_our_index
62 }
63
64 pub fn previous_session(&self) -> Option<&NoiseSession> {
66 self.previous_session.as_ref()
67 }
68
69 pub fn previous_session_mut(&mut self) -> Option<&mut NoiseSession> {
71 self.previous_session.as_mut()
72 }
73
74 pub fn pending_new_session(&self) -> Option<&NoiseSession> {
76 self.pending_new_session.as_ref()
77 }
78
79 pub(crate) fn trial_decrypt_pending_new_session(
85 &mut self,
86 ciphertext: &[u8],
87 counter: u64,
88 aad: &[u8],
89 ) -> Option<Vec<u8>> {
90 self.pending_new_session.as_mut().and_then(|session| {
91 session
92 .decrypt_with_replay_check_and_aad(ciphertext, counter, aad)
93 .ok()
94 })
95 }
96
97 pub fn pending_rekey_initiator(&self) -> bool {
99 self.pending_rekey_initiator
100 }
101
102 pub fn pending_rekey_cutover_due(&self, delay: Duration) -> bool {
105 self.pending_rekey_initiator
106 && self
107 .pending_rekey_completed_at
108 .is_some_and(|completed| completed.elapsed() >= delay)
109 }
110
111 pub fn set_pending_session(
117 &mut self,
118 session: NoiseSession,
119 our_index: SessionIndex,
120 their_index: SessionIndex,
121 initiated_by_local: bool,
122 ) {
123 self.pending_new_session = Some(session);
124 self.pending_our_index = Some(our_index);
125 self.pending_their_index = Some(their_index);
126 self.pending_rekey_initiator = initiated_by_local;
127 self.pending_rekey_completed_at = Some(Instant::now());
128 self.rekey_in_progress = false;
129 self.rekey_our_index = None;
131 self.rekey_handshake = None;
132 self.rekey_msg1 = None;
133 self.rekey_msg1_next_resend = 0;
134 self.rekey_msg1_resend_count = 0;
135 }
136
137 pub fn cutover_to_new_session(&mut self) -> Option<SessionIndex> {
143 let new_session = self.pending_new_session.take()?;
144 let new_our_index = self.pending_our_index.take();
145 let new_their_index = self.pending_their_index.take();
146
147 self.previous_session = self.noise_session.take();
149 self.previous_our_index = self.our_index;
150 self.drain_started = Some(Instant::now());
151
152 self.noise_session = Some(new_session);
154 self.our_index = new_our_index;
155 self.their_index = new_their_index;
156 self.pending_rekey_initiator = false;
157 self.pending_rekey_completed_at = None;
158
159 self.current_k_bit = !self.current_k_bit;
161 self.session_established_at = Instant::now();
162 self.session_start = Instant::now();
163 self.rekey_in_progress = false;
164 self.rekey_msg1_resend_count = 0;
165 self.rekey_jitter_secs = draw_rekey_jitter();
166 self.last_heartbeat_sent = None;
167 self.reset_replay_suppressed();
168
169 let now = Instant::now();
171 if let Some(mmp) = &mut self.mmp {
172 mmp.reset_for_rekey(now);
173 }
174
175 self.previous_our_index
176 }
177
178 pub fn handle_peer_kbit_flip(&mut self) -> Option<SessionIndex> {
183 let new_session = self.pending_new_session.take()?;
184 let new_our_index = self.pending_our_index.take();
185 let new_their_index = self.pending_their_index.take();
186
187 self.previous_session = self.noise_session.take();
189 self.previous_our_index = self.our_index;
190 self.drain_started = Some(Instant::now());
191
192 self.noise_session = Some(new_session);
194 self.our_index = new_our_index;
195 self.their_index = new_their_index;
196 self.pending_rekey_initiator = false;
197 self.pending_rekey_completed_at = None;
198
199 self.current_k_bit = !self.current_k_bit;
201 self.session_established_at = Instant::now();
202 self.session_start = Instant::now();
203 self.rekey_in_progress = false;
204 self.rekey_msg1_resend_count = 0;
205 self.rekey_jitter_secs = draw_rekey_jitter();
206 self.last_heartbeat_sent = None;
207 self.reset_replay_suppressed();
208
209 let now = Instant::now();
211 if let Some(mmp) = &mut self.mmp {
212 mmp.reset_for_rekey(now);
213 }
214
215 self.previous_our_index
216 }
217
218 pub fn drain_expired(&self, drain_secs: u64) -> bool {
220 match self.drain_started {
221 Some(t) => t.elapsed().as_secs() >= drain_secs,
222 None => false,
223 }
224 }
225
226 pub fn is_draining(&self) -> bool {
228 self.drain_started.is_some()
229 }
230
231 pub fn complete_drain(&mut self) -> Option<SessionIndex> {
236 self.previous_session = None;
237 self.drain_started = None;
238 self.previous_our_index.take()
239 }
240
241 pub fn abandon_rekey(&mut self) -> Option<SessionIndex> {
247 self.rekey_handshake = None;
248 self.rekey_msg1 = None;
249 self.rekey_msg1_next_resend = 0;
250 self.rekey_msg1_resend_count = 0;
251 self.rekey_in_progress = false;
252 self.rekey_our_index.take().or_else(|| {
254 self.pending_new_session = None;
255 self.pending_their_index = None;
256 self.pending_rekey_initiator = false;
257 self.pending_rekey_completed_at = None;
258 self.pending_our_index.take()
259 })
260 }
261
262 pub fn set_rekey_state(
266 &mut self,
267 handshake: NoiseHandshakeState,
268 our_index: SessionIndex,
269 wire_msg1: Vec<u8>,
270 next_resend_ms: u64,
271 ) {
272 self.rekey_handshake = Some(handshake);
273 self.rekey_our_index = Some(our_index);
274 self.rekey_msg1 = Some(wire_msg1);
275 self.rekey_msg1_next_resend = next_resend_ms;
276 self.rekey_msg1_resend_count = 0;
277 self.rekey_in_progress = true;
278 }
279
280 pub fn rekey_our_index(&self) -> Option<SessionIndex> {
282 self.rekey_our_index
283 }
284
285 pub fn complete_rekey_msg2(
291 &mut self,
292 msg2_bytes: &[u8],
293 ) -> Result<(NoiseSession, Option<[u8; 8]>), NoiseError> {
294 let mut hs = self
295 .rekey_handshake
296 .take()
297 .ok_or_else(|| NoiseError::WrongState {
298 expected: "rekey handshake in progress".to_string(),
299 got: "no handshake state".to_string(),
300 })?;
301
302 hs.read_message_2(msg2_bytes)?;
303 let remote_epoch = hs.remote_epoch();
304 let session = hs.into_session()?;
305
306 self.rekey_msg1 = None;
308 self.rekey_msg1_next_resend = 0;
309 self.rekey_msg1_resend_count = 0;
310
311 Ok((session, remote_epoch))
312 }
313
314 pub fn needs_msg1_resend(&self, now_ms: u64) -> bool {
316 self.rekey_in_progress && self.rekey_msg1.is_some() && now_ms >= self.rekey_msg1_next_resend
317 }
318
319 pub fn rekey_msg1(&self) -> Option<&[u8]> {
321 self.rekey_msg1.as_deref()
322 }
323
324 pub fn set_msg1_next_resend(&mut self, next_ms: u64) {
326 self.rekey_msg1_next_resend = next_ms;
327 }
328
329 pub fn rekey_msg1_resend_count(&self) -> u32 {
331 self.rekey_msg1_resend_count
332 }
333
334 pub fn record_rekey_msg1_resend(&mut self, next_ms: u64) {
336 self.rekey_msg1_resend_count = self.rekey_msg1_resend_count.saturating_add(1);
337 self.rekey_msg1_next_resend = next_ms;
338 }
339}