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 #[cfg(test)]
17 pub(crate) fn set_rekey_jitter_secs_for_test(&mut self, seconds: i64) {
18 self.rekey_jitter_secs = seconds;
19 }
20
21 pub fn rekey_jitter_secs(&self) -> i64 {
23 self.rekey_jitter_secs
24 }
25
26 pub fn current_k_bit(&self) -> bool {
28 self.current_k_bit
29 }
30
31 pub fn rekey_in_progress(&self) -> bool {
33 self.rekey_in_progress
34 }
35
36 pub fn set_rekey_in_progress(&mut self) {
38 self.rekey_in_progress = true;
39 }
40
41 pub fn is_rekey_dampened(&self, dampening_secs: u64) -> bool {
43 match self.last_rekey_dampening_at {
44 Some(t) => t.elapsed().as_secs() < dampening_secs,
45 None => false,
46 }
47 }
48
49 pub fn record_peer_rekey(&mut self) {
51 self.last_rekey_dampening_at = Some(Instant::now());
52 }
53
54 pub fn pending_our_index(&self) -> Option<SessionIndex> {
56 self.pending_our_index
57 }
58
59 pub fn pending_their_index(&self) -> Option<SessionIndex> {
61 self.pending_their_index
62 }
63
64 pub fn previous_our_index(&self) -> Option<SessionIndex> {
66 self.previous_our_index
67 }
68
69 pub fn previous_transport_id(&self) -> Option<TransportId> {
71 self.previous_transport_id
72 }
73
74 pub fn previous_session(&self) -> Option<&NoiseSession> {
76 self.previous_session.as_ref()
77 }
78
79 pub fn previous_session_mut(&mut self) -> Option<&mut NoiseSession> {
81 self.previous_session.as_mut()
82 }
83
84 pub fn pending_new_session(&self) -> Option<&NoiseSession> {
86 self.pending_new_session.as_ref()
87 }
88
89 pub fn pending_rekey_initiator(&self) -> bool {
91 self.pending_rekey_initiator
92 }
93
94 pub fn pending_rekey_cutover_due(&self, delay: Duration) -> bool {
97 self.pending_rekey_initiator
98 && self
99 .pending_rekey_completed_at
100 .is_some_and(|completed| completed.elapsed() >= delay)
101 }
102
103 pub fn set_pending_session(
109 &mut self,
110 session: NoiseSession,
111 our_index: SessionIndex,
112 their_index: SessionIndex,
113 initiated_by_local: bool,
114 ) {
115 self.pending_new_session = Some(session);
116 self.pending_our_index = Some(our_index);
117 self.pending_their_index = Some(their_index);
118 self.pending_rekey_initiator = initiated_by_local;
119 self.pending_rekey_completed_at = Some(Instant::now());
120 self.rekey_in_progress = false;
121 self.rekey_our_index = None;
123 self.rekey_handshake = None;
124 self.rekey_msg1 = None;
125 self.rekey_msg1_next_resend = 0;
126 self.rekey_msg1_resend_count = 0;
127 }
128
129 pub fn cutover_to_new_session(&mut self) -> Option<SessionIndex> {
135 let new_session = self.pending_new_session.take()?;
136 let new_our_index = self.pending_our_index.take();
137 let new_their_index = self.pending_their_index.take();
138
139 self.previous_session = self.noise_session.take();
141 self.previous_our_index = self.our_index;
142 self.previous_transport_id = self.transport_id;
143 self.drain_started = Some(Instant::now());
144
145 self.noise_session = Some(new_session);
147 self.our_index = new_our_index;
148 self.their_index = new_their_index;
149 self.pending_rekey_initiator = false;
150 self.pending_rekey_completed_at = None;
151
152 self.current_k_bit = !self.current_k_bit;
154 self.session_established_at = Instant::now();
155 self.session_start = Instant::now();
156 self.session_generation = self.session_generation.wrapping_add(1).max(1);
157 self.rekey_in_progress = false;
158 self.rekey_msg1_resend_count = 0;
159 self.rekey_jitter_secs = draw_rekey_jitter();
160 self.last_rekey_dampening_at = Some(Instant::now());
161 self.last_heartbeat_sent = None;
162 self.reset_replay_suppressed();
163
164 self.previous_our_index
165 }
166
167 pub fn handle_peer_kbit_flip(&mut self) -> Option<SessionIndex> {
172 let new_session = self.pending_new_session.take()?;
173 let new_our_index = self.pending_our_index.take();
174 let new_their_index = self.pending_their_index.take();
175
176 self.previous_session = self.noise_session.take();
178 self.previous_our_index = self.our_index;
179 self.previous_transport_id = self.transport_id;
180 self.drain_started = Some(Instant::now());
181
182 self.noise_session = Some(new_session);
184 self.our_index = new_our_index;
185 self.their_index = new_their_index;
186 self.pending_rekey_initiator = false;
187 self.pending_rekey_completed_at = None;
188
189 self.current_k_bit = !self.current_k_bit;
191 self.session_established_at = Instant::now();
192 self.session_start = Instant::now();
193 self.session_generation = self.session_generation.wrapping_add(1).max(1);
194 self.rekey_in_progress = false;
195 self.rekey_msg1_resend_count = 0;
196 self.rekey_jitter_secs = draw_rekey_jitter();
197 self.last_rekey_dampening_at = Some(Instant::now());
198 self.last_heartbeat_sent = None;
199 self.reset_replay_suppressed();
200
201 self.previous_our_index
202 }
203
204 pub fn drain_expired(&self, drain_secs: u64) -> bool {
206 match self.drain_started {
207 Some(t) => t.elapsed().as_secs() >= drain_secs,
208 None => false,
209 }
210 }
211
212 pub fn is_draining(&self) -> bool {
214 self.drain_started.is_some()
215 }
216
217 pub fn complete_drain(&mut self) -> Option<SessionIndex> {
222 self.previous_session = None;
223 self.drain_started = None;
224 self.previous_transport_id = None;
225 self.previous_our_index.take()
226 }
227
228 pub fn abandon_rekey(&mut self) -> Option<SessionIndex> {
234 self.rekey_handshake = None;
235 self.rekey_msg1 = None;
236 self.rekey_msg1_next_resend = 0;
237 self.rekey_msg1_resend_count = 0;
238 self.rekey_in_progress = false;
239 self.rekey_our_index.take().or_else(|| {
241 self.pending_new_session = None;
242 self.pending_their_index = None;
243 self.pending_rekey_initiator = false;
244 self.pending_rekey_completed_at = None;
245 self.pending_our_index.take()
246 })
247 }
248
249 pub fn set_rekey_state(
253 &mut self,
254 handshake: NoiseHandshakeState,
255 our_index: SessionIndex,
256 wire_msg1: Vec<u8>,
257 next_resend_ms: u64,
258 ) {
259 self.rekey_handshake = Some(handshake);
260 self.rekey_our_index = Some(our_index);
261 self.rekey_msg1 = Some(wire_msg1);
262 self.rekey_msg1_next_resend = next_resend_ms;
263 self.rekey_msg1_resend_count = 0;
264 self.rekey_in_progress = true;
265 }
266
267 pub fn rekey_our_index(&self) -> Option<SessionIndex> {
269 self.rekey_our_index
270 }
271
272 pub fn complete_rekey_msg2(
278 &mut self,
279 msg2_bytes: &[u8],
280 ) -> Result<(NoiseSession, Option<[u8; 8]>), NoiseError> {
281 let mut hs = self
282 .rekey_handshake
283 .take()
284 .ok_or_else(|| NoiseError::WrongState {
285 expected: "rekey handshake in progress".to_string(),
286 got: "no handshake state".to_string(),
287 })?;
288
289 hs.read_message_2(msg2_bytes)?;
290 let remote_epoch = hs.remote_epoch();
291 let session = hs.into_session()?;
292
293 self.rekey_msg1 = None;
295 self.rekey_msg1_next_resend = 0;
296 self.rekey_msg1_resend_count = 0;
297
298 Ok((session, remote_epoch))
299 }
300
301 pub fn needs_msg1_resend(&self, now_ms: u64) -> bool {
303 self.rekey_in_progress && self.rekey_msg1.is_some() && now_ms >= self.rekey_msg1_next_resend
304 }
305
306 pub fn rekey_msg1(&self) -> Option<&[u8]> {
308 self.rekey_msg1.as_deref()
309 }
310
311 pub fn set_msg1_next_resend(&mut self, next_ms: u64) {
313 self.rekey_msg1_next_resend = next_ms;
314 }
315
316 pub fn rekey_msg1_resend_count(&self) -> u32 {
318 self.rekey_msg1_resend_count
319 }
320
321 pub fn record_rekey_msg1_resend(&mut self, next_ms: u64) {
323 self.rekey_msg1_resend_count = self.rekey_msg1_resend_count.saturating_add(1);
324 self.rekey_msg1_next_resend = next_ms;
325 }
326}