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_transport_id(&self) -> Option<TransportId> {
66 self.previous_transport_id
67 }
68
69 pub fn previous_session(&self) -> Option<&NoiseSession> {
71 self.previous_session.as_ref()
72 }
73
74 pub fn previous_session_mut(&mut self) -> Option<&mut NoiseSession> {
76 self.previous_session.as_mut()
77 }
78
79 pub fn pending_new_session(&self) -> Option<&NoiseSession> {
81 self.pending_new_session.as_ref()
82 }
83
84 pub fn pending_rekey_initiator(&self) -> bool {
86 self.pending_rekey_initiator
87 }
88
89 pub fn pending_rekey_cutover_due(&self, delay: Duration) -> bool {
92 self.pending_rekey_initiator
93 && self
94 .pending_rekey_completed_at
95 .is_some_and(|completed| completed.elapsed() >= delay)
96 }
97
98 pub fn set_pending_session(
104 &mut self,
105 session: NoiseSession,
106 our_index: SessionIndex,
107 their_index: SessionIndex,
108 initiated_by_local: bool,
109 ) {
110 self.pending_new_session = Some(session);
111 self.pending_our_index = Some(our_index);
112 self.pending_their_index = Some(their_index);
113 self.pending_rekey_initiator = initiated_by_local;
114 self.pending_rekey_completed_at = Some(Instant::now());
115 self.rekey_in_progress = false;
116 self.rekey_our_index = None;
118 self.rekey_handshake = None;
119 self.rekey_msg1 = None;
120 self.rekey_msg1_next_resend = 0;
121 self.rekey_msg1_resend_count = 0;
122 }
123
124 pub fn cutover_to_new_session(&mut self) -> Option<SessionIndex> {
130 let new_session = self.pending_new_session.take()?;
131 let new_our_index = self.pending_our_index.take();
132 let new_their_index = self.pending_their_index.take();
133
134 self.previous_session = self.noise_session.take();
136 self.previous_our_index = self.our_index;
137 self.previous_transport_id = self.transport_id;
138 self.drain_started = Some(Instant::now());
139
140 self.noise_session = Some(new_session);
142 self.our_index = new_our_index;
143 self.their_index = new_their_index;
144 self.pending_rekey_initiator = false;
145 self.pending_rekey_completed_at = None;
146
147 self.current_k_bit = !self.current_k_bit;
149 self.session_established_at = Instant::now();
150 self.session_start = Instant::now();
151 self.session_generation = self.session_generation.wrapping_add(1).max(1);
152 self.rekey_in_progress = false;
153 self.rekey_msg1_resend_count = 0;
154 self.rekey_jitter_secs = draw_rekey_jitter();
155 self.last_heartbeat_sent = None;
156 self.reset_replay_suppressed();
157
158 self.previous_our_index
159 }
160
161 pub fn handle_peer_kbit_flip(&mut self) -> Option<SessionIndex> {
166 let new_session = self.pending_new_session.take()?;
167 let new_our_index = self.pending_our_index.take();
168 let new_their_index = self.pending_their_index.take();
169
170 self.previous_session = self.noise_session.take();
172 self.previous_our_index = self.our_index;
173 self.previous_transport_id = self.transport_id;
174 self.drain_started = Some(Instant::now());
175
176 self.noise_session = Some(new_session);
178 self.our_index = new_our_index;
179 self.their_index = new_their_index;
180 self.pending_rekey_initiator = false;
181 self.pending_rekey_completed_at = None;
182
183 self.current_k_bit = !self.current_k_bit;
185 self.session_established_at = Instant::now();
186 self.session_start = Instant::now();
187 self.session_generation = self.session_generation.wrapping_add(1).max(1);
188 self.rekey_in_progress = false;
189 self.rekey_msg1_resend_count = 0;
190 self.rekey_jitter_secs = draw_rekey_jitter();
191 self.last_heartbeat_sent = None;
192 self.reset_replay_suppressed();
193
194 self.previous_our_index
195 }
196
197 pub fn drain_expired(&self, drain_secs: u64) -> bool {
199 match self.drain_started {
200 Some(t) => t.elapsed().as_secs() >= drain_secs,
201 None => false,
202 }
203 }
204
205 pub fn is_draining(&self) -> bool {
207 self.drain_started.is_some()
208 }
209
210 pub fn complete_drain(&mut self) -> Option<SessionIndex> {
215 self.previous_session = None;
216 self.drain_started = None;
217 self.previous_transport_id = None;
218 self.previous_our_index.take()
219 }
220
221 pub fn abandon_rekey(&mut self) -> Option<SessionIndex> {
227 self.rekey_handshake = None;
228 self.rekey_msg1 = None;
229 self.rekey_msg1_next_resend = 0;
230 self.rekey_msg1_resend_count = 0;
231 self.rekey_in_progress = false;
232 self.rekey_our_index.take().or_else(|| {
234 self.pending_new_session = None;
235 self.pending_their_index = None;
236 self.pending_rekey_initiator = false;
237 self.pending_rekey_completed_at = None;
238 self.pending_our_index.take()
239 })
240 }
241
242 pub fn set_rekey_state(
246 &mut self,
247 handshake: NoiseHandshakeState,
248 our_index: SessionIndex,
249 wire_msg1: Vec<u8>,
250 next_resend_ms: u64,
251 ) {
252 self.rekey_handshake = Some(handshake);
253 self.rekey_our_index = Some(our_index);
254 self.rekey_msg1 = Some(wire_msg1);
255 self.rekey_msg1_next_resend = next_resend_ms;
256 self.rekey_msg1_resend_count = 0;
257 self.rekey_in_progress = true;
258 }
259
260 pub fn rekey_our_index(&self) -> Option<SessionIndex> {
262 self.rekey_our_index
263 }
264
265 pub fn complete_rekey_msg2(
271 &mut self,
272 msg2_bytes: &[u8],
273 ) -> Result<(NoiseSession, Option<[u8; 8]>), NoiseError> {
274 let mut hs = self
275 .rekey_handshake
276 .take()
277 .ok_or_else(|| NoiseError::WrongState {
278 expected: "rekey handshake in progress".to_string(),
279 got: "no handshake state".to_string(),
280 })?;
281
282 hs.read_message_2(msg2_bytes)?;
283 let remote_epoch = hs.remote_epoch();
284 let session = hs.into_session()?;
285
286 self.rekey_msg1 = None;
288 self.rekey_msg1_next_resend = 0;
289 self.rekey_msg1_resend_count = 0;
290
291 Ok((session, remote_epoch))
292 }
293
294 pub fn needs_msg1_resend(&self, now_ms: u64) -> bool {
296 self.rekey_in_progress && self.rekey_msg1.is_some() && now_ms >= self.rekey_msg1_next_resend
297 }
298
299 pub fn rekey_msg1(&self) -> Option<&[u8]> {
301 self.rekey_msg1.as_deref()
302 }
303
304 pub fn set_msg1_next_resend(&mut self, next_ms: u64) {
306 self.rekey_msg1_next_resend = next_ms;
307 }
308
309 pub fn rekey_msg1_resend_count(&self) -> u32 {
311 self.rekey_msg1_resend_count
312 }
313
314 pub fn record_rekey_msg1_resend(&mut self, next_ms: u64) {
316 self.rekey_msg1_resend_count = self.rekey_msg1_resend_count.saturating_add(1);
317 self.rekey_msg1_next_resend = next_ms;
318 }
319}