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_peer_rekey {
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_peer_rekey = 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_heartbeat_sent = None;
161 self.reset_replay_suppressed();
162
163 self.previous_our_index
164 }
165
166 pub fn handle_peer_kbit_flip(&mut self) -> Option<SessionIndex> {
171 let new_session = self.pending_new_session.take()?;
172 let new_our_index = self.pending_our_index.take();
173 let new_their_index = self.pending_their_index.take();
174
175 self.previous_session = self.noise_session.take();
177 self.previous_our_index = self.our_index;
178 self.previous_transport_id = self.transport_id;
179 self.drain_started = Some(Instant::now());
180
181 self.noise_session = Some(new_session);
183 self.our_index = new_our_index;
184 self.their_index = new_their_index;
185 self.pending_rekey_initiator = false;
186 self.pending_rekey_completed_at = None;
187
188 self.current_k_bit = !self.current_k_bit;
190 self.session_established_at = Instant::now();
191 self.session_start = Instant::now();
192 self.session_generation = self.session_generation.wrapping_add(1).max(1);
193 self.rekey_in_progress = false;
194 self.rekey_msg1_resend_count = 0;
195 self.rekey_jitter_secs = draw_rekey_jitter();
196 self.last_heartbeat_sent = None;
197 self.reset_replay_suppressed();
198
199 self.previous_our_index
200 }
201
202 pub fn drain_expired(&self, drain_secs: u64) -> bool {
204 match self.drain_started {
205 Some(t) => t.elapsed().as_secs() >= drain_secs,
206 None => false,
207 }
208 }
209
210 pub fn is_draining(&self) -> bool {
212 self.drain_started.is_some()
213 }
214
215 pub fn complete_drain(&mut self) -> Option<SessionIndex> {
220 self.previous_session = None;
221 self.drain_started = None;
222 self.previous_transport_id = None;
223 self.previous_our_index.take()
224 }
225
226 pub fn abandon_rekey(&mut self) -> Option<SessionIndex> {
232 self.rekey_handshake = None;
233 self.rekey_msg1 = None;
234 self.rekey_msg1_next_resend = 0;
235 self.rekey_msg1_resend_count = 0;
236 self.rekey_in_progress = false;
237 self.rekey_our_index.take().or_else(|| {
239 self.pending_new_session = None;
240 self.pending_their_index = None;
241 self.pending_rekey_initiator = false;
242 self.pending_rekey_completed_at = None;
243 self.pending_our_index.take()
244 })
245 }
246
247 pub fn set_rekey_state(
251 &mut self,
252 handshake: NoiseHandshakeState,
253 our_index: SessionIndex,
254 wire_msg1: Vec<u8>,
255 next_resend_ms: u64,
256 ) {
257 self.rekey_handshake = Some(handshake);
258 self.rekey_our_index = Some(our_index);
259 self.rekey_msg1 = Some(wire_msg1);
260 self.rekey_msg1_next_resend = next_resend_ms;
261 self.rekey_msg1_resend_count = 0;
262 self.rekey_in_progress = true;
263 }
264
265 pub fn rekey_our_index(&self) -> Option<SessionIndex> {
267 self.rekey_our_index
268 }
269
270 pub fn complete_rekey_msg2(
276 &mut self,
277 msg2_bytes: &[u8],
278 ) -> Result<(NoiseSession, Option<[u8; 8]>), NoiseError> {
279 let mut hs = self
280 .rekey_handshake
281 .take()
282 .ok_or_else(|| NoiseError::WrongState {
283 expected: "rekey handshake in progress".to_string(),
284 got: "no handshake state".to_string(),
285 })?;
286
287 hs.read_message_2(msg2_bytes)?;
288 let remote_epoch = hs.remote_epoch();
289 let session = hs.into_session()?;
290
291 self.rekey_msg1 = None;
293 self.rekey_msg1_next_resend = 0;
294 self.rekey_msg1_resend_count = 0;
295
296 Ok((session, remote_epoch))
297 }
298
299 pub fn needs_msg1_resend(&self, now_ms: u64) -> bool {
301 self.rekey_in_progress && self.rekey_msg1.is_some() && now_ms >= self.rekey_msg1_next_resend
302 }
303
304 pub fn rekey_msg1(&self) -> Option<&[u8]> {
306 self.rekey_msg1.as_deref()
307 }
308
309 pub fn set_msg1_next_resend(&mut self, next_ms: u64) {
311 self.rekey_msg1_next_resend = next_ms;
312 }
313
314 pub fn rekey_msg1_resend_count(&self) -> u32 {
316 self.rekey_msg1_resend_count
317 }
318
319 pub fn record_rekey_msg1_resend(&mut self, next_ms: u64) {
321 self.rekey_msg1_resend_count = self.rekey_msg1_resend_count.saturating_add(1);
322 self.rekey_msg1_next_resend = next_ms;
323 }
324}