1use std::result::Result;
7use std::time::{Duration, SystemTime};
8
9use bitflags::bitflags;
10use prost::Message;
11#[cfg(test)]
12use rand::{CryptoRng, Rng};
13use subtle::ConstantTimeEq;
14
15use crate::proto::storage::{RecordStructure, SessionStructure, session_structure};
16use crate::protocol::CIPHERTEXT_MESSAGE_PRE_KYBER_VERSION;
17#[cfg(test)]
18use crate::ratchet::MessageKeyGenerator;
19use crate::ratchet::{ChainKey, RootKey};
20use crate::state::{KyberPreKeyId, PreKeyId, SignedPreKeyId};
21use crate::{
22 IdentityKey, KeyPair, PrivateKey, PublicKey, SessionNotFound, SignalProtocolError, consts, kem,
23};
24
25#[derive(Debug)]
27pub(crate) struct InvalidSessionError(pub(crate) &'static str);
28
29impl std::fmt::Display for InvalidSessionError {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 self.0.fmt(f)
32 }
33}
34
35impl From<InvalidSessionError> for SignalProtocolError {
36 fn from(e: InvalidSessionError) -> Self {
37 Self::InvalidSessionStructure(e.0)
38 }
39}
40
41#[derive(Debug, Clone)]
42pub(crate) struct UnacknowledgedPreKeyMessageItems<'a> {
43 pre_key_id: Option<PreKeyId>,
44 signed_pre_key_id: SignedPreKeyId,
45 base_key: PublicKey,
46 kyber_pre_key_id: Option<KyberPreKeyId>,
50 kyber_ciphertext: Option<&'a [u8]>,
51 timestamp: SystemTime,
52}
53
54impl<'a> UnacknowledgedPreKeyMessageItems<'a> {
55 fn new(
56 pre_key_id: Option<PreKeyId>,
57 signed_pre_key_id: SignedPreKeyId,
58 base_key: PublicKey,
59 pending_kyber_pre_key: Option<&'a session_structure::PendingKyberPreKey>,
60 timestamp: SystemTime,
61 ) -> Self {
62 let (kyber_pre_key_id, kyber_ciphertext) = pending_kyber_pre_key
63 .map(|pending| (pending.pre_key_id.into(), pending.ciphertext.as_slice()))
64 .unzip();
65 Self {
66 pre_key_id,
67 signed_pre_key_id,
68 base_key,
69 kyber_pre_key_id,
70 kyber_ciphertext,
71 timestamp,
72 }
73 }
74
75 pub(crate) fn pre_key_id(&self) -> Option<PreKeyId> {
76 self.pre_key_id
77 }
78
79 pub(crate) fn signed_pre_key_id(&self) -> SignedPreKeyId {
80 self.signed_pre_key_id
81 }
82
83 pub(crate) fn base_key(&self) -> &PublicKey {
84 &self.base_key
85 }
86
87 pub(crate) fn kyber_pre_key_id(&self) -> Option<KyberPreKeyId> {
88 self.kyber_pre_key_id
89 }
90
91 pub(crate) fn kyber_ciphertext(&self) -> Option<&'a [u8]> {
92 self.kyber_ciphertext
93 }
94
95 pub(crate) fn timestamp(&self) -> SystemTime {
96 self.timestamp
97 }
98}
99
100bitflags! {
101 #[repr(transparent)]
111 #[derive(Clone, Copy, PartialEq, Eq)]
112 pub struct SessionUsabilityRequirements : u32 {
113 const NotStale = 1 << 0;
120 const EstablishedWithPqxdh = 1 << 1;
125 const Spqr = 1 << 2;
133 }
134}
135
136#[derive(Clone, Debug)]
137pub(crate) struct SessionState {
138 session: SessionStructure,
139}
140
141impl SessionState {
142 pub(crate) fn from_session_structure(session: SessionStructure) -> Self {
143 Self { session }
144 }
145
146 pub(crate) fn new(
147 version: u8,
148 our_identity: &IdentityKey,
149 their_identity: &IdentityKey,
150 root_key: &RootKey,
151 alice_base_key: &PublicKey,
152 pq_ratchet_state: spqr::SerializedState,
153 ) -> Self {
154 Self {
155 session: SessionStructure {
156 session_version: version as u32,
157 local_identity_public: our_identity.public_key().serialize().into_vec(),
158 remote_identity_public: their_identity.serialize().into_vec(),
159 root_key: root_key.key().to_vec(),
160 previous_counter: 0,
161 sender_chain: None,
162 receiver_chains: vec![],
163 pending_pre_key: None,
164 pending_kyber_pre_key: None,
165 remote_registration_id: 0,
166 local_registration_id: 0,
167 alice_base_key: alice_base_key.serialize().into_vec(),
168 pq_ratchet_state,
169 },
170 }
171 }
172
173 pub(crate) fn alice_base_key(&self) -> &[u8] {
174 &self.session.alice_base_key
176 }
177
178 pub(crate) fn session_version(&self) -> Result<u32, InvalidSessionError> {
179 match self.session.session_version {
180 0 => Ok(2),
181 v => Ok(v),
182 }
183 }
184
185 pub(crate) fn remote_identity_key(&self) -> Result<Option<IdentityKey>, InvalidSessionError> {
186 match self.session.remote_identity_public.len() {
187 0 => Ok(None),
188 _ => Ok(Some(
189 IdentityKey::decode(&self.session.remote_identity_public)
190 .map_err(|_| InvalidSessionError("invalid remote identity key"))?,
191 )),
192 }
193 }
194
195 pub(crate) fn remote_identity_key_bytes(&self) -> Result<Option<Vec<u8>>, InvalidSessionError> {
196 Ok(self.remote_identity_key()?.map(|k| k.serialize().to_vec()))
197 }
198
199 pub(crate) fn local_identity_key(&self) -> Result<IdentityKey, InvalidSessionError> {
200 IdentityKey::decode(&self.session.local_identity_public)
201 .map_err(|_| InvalidSessionError("invalid local identity key"))
202 }
203
204 pub(crate) fn local_identity_key_bytes(&self) -> Result<Vec<u8>, InvalidSessionError> {
205 Ok(self.local_identity_key()?.serialize().to_vec())
206 }
207
208 #[deprecated]
209 #[allow(unused)]
210 pub(crate) fn session_with_self(&self) -> Result<bool, InvalidSessionError> {
211 if let Some(remote_id) = self.remote_identity_key_bytes()? {
212 let local_id = self.local_identity_key_bytes()?;
213 return Ok(remote_id == local_id);
214 }
215
216 Ok(false)
218 }
219
220 pub(crate) fn previous_counter(&self) -> u32 {
221 self.session.previous_counter
222 }
223
224 #[cfg(test)]
225 pub(crate) fn set_previous_counter(&mut self, ctr: u32) {
226 self.session.previous_counter = ctr;
227 }
228
229 #[cfg(test)]
230 pub(crate) fn root_key(&self) -> Result<RootKey, InvalidSessionError> {
231 let root_key_bytes = self.session.root_key[..]
232 .try_into()
233 .map_err(|_| InvalidSessionError("invalid root key"))?;
234 Ok(RootKey::new(root_key_bytes))
235 }
236
237 #[cfg(test)]
238 pub(crate) fn set_root_key(&mut self, root_key: &RootKey) {
239 self.session.root_key = root_key.key().to_vec();
240 }
241
242 pub(crate) fn sender_ratchet_key(&self) -> Result<PublicKey, InvalidSessionError> {
243 match self.session.sender_chain {
244 None => Err(InvalidSessionError("missing sender chain")),
245 Some(ref c) => PublicKey::deserialize(&c.sender_ratchet_key)
246 .map_err(|_| InvalidSessionError("invalid sender chain ratchet key")),
247 }
248 }
249
250 pub(crate) fn sender_ratchet_key_for_logging(&self) -> Result<String, InvalidSessionError> {
251 Ok(hex::encode(self.sender_ratchet_key()?.public_key_bytes()))
252 }
253
254 pub(crate) fn sender_ratchet_private_key(&self) -> Result<PrivateKey, InvalidSessionError> {
255 match self.session.sender_chain {
256 None => Err(InvalidSessionError("missing sender chain")),
257 Some(ref c) => PrivateKey::deserialize(&c.sender_ratchet_key_private)
258 .map_err(|_| InvalidSessionError("invalid sender chain private ratchet key")),
259 }
260 }
261
262 pub fn has_usable_sender_chain(
263 &self,
264 now: SystemTime,
265 requirements: SessionUsabilityRequirements,
266 ) -> Result<bool, InvalidSessionError> {
267 if self.session.sender_chain.is_none() {
268 return Ok(false);
269 }
270 if requirements.contains(SessionUsabilityRequirements::NotStale) {
271 if let Some(pending_pre_key) = &self.session.pending_pre_key {
272 let creation_timestamp =
273 SystemTime::UNIX_EPOCH + Duration::from_secs(pending_pre_key.timestamp);
274 if creation_timestamp + consts::MAX_UNACKNOWLEDGED_SESSION_AGE < now {
275 return Ok(false);
276 }
277 }
278 }
279 #[allow(clippy::collapsible_if)]
280 if requirements.contains(SessionUsabilityRequirements::EstablishedWithPqxdh) {
281 if self.session_version()? <= CIPHERTEXT_MESSAGE_PRE_KYBER_VERSION.into() {
282 return Ok(false);
283 }
284 }
285 #[allow(clippy::collapsible_if)]
286 if requirements.contains(SessionUsabilityRequirements::Spqr) {
287 if self.pq_ratchet_state().is_empty() {
288 return Ok(false);
289 }
290 }
291 Ok(true)
292 }
293
294 pub(crate) fn all_receiver_chain_logging_info(&self) -> Vec<(Vec<u8>, Option<u32>)> {
295 let mut results = vec![];
296 for chain in self.session.receiver_chains.iter() {
297 let sender_ratchet_public = chain.sender_ratchet_key.clone();
298
299 let chain_key_idx = chain.chain_key.as_ref().map(|chain_key| chain_key.index);
300
301 results.push((sender_ratchet_public, chain_key_idx))
302 }
303 results
304 }
305
306 pub(crate) fn get_receiver_chain(
307 &self,
308 sender: &PublicKey,
309 ) -> Result<Option<(session_structure::Chain, usize)>, InvalidSessionError> {
310 for (idx, chain) in self.session.receiver_chains.iter().enumerate() {
311 let chain_ratchet_key = PublicKey::deserialize(&chain.sender_ratchet_key)
314 .map_err(|_| InvalidSessionError("invalid receiver chain ratchet key"))?;
315
316 if &chain_ratchet_key == sender {
317 return Ok(Some((chain.clone(), idx)));
318 }
319 }
320
321 Ok(None)
322 }
323
324 pub(crate) fn get_receiver_chain_key(
325 &self,
326 sender: &PublicKey,
327 ) -> Result<Option<ChainKey>, InvalidSessionError> {
328 match self.get_receiver_chain(sender)? {
329 None => Ok(None),
330 Some((chain, _)) => match chain.chain_key {
331 None => Err(InvalidSessionError("missing receiver chain key")),
332 Some(c) => {
333 let chain_key_bytes = c.key[..]
334 .try_into()
335 .map_err(|_| InvalidSessionError("invalid receiver chain key"))?;
336 Ok(Some(ChainKey::new(chain_key_bytes, c.index)))
337 }
338 },
339 }
340 }
341
342 pub(crate) fn add_receiver_chain(&mut self, sender: &PublicKey, chain_key: &ChainKey) {
343 let chain_key = session_structure::chain::ChainKey {
344 index: chain_key.index(),
345 key: chain_key.key().to_vec(),
346 };
347
348 let chain = session_structure::Chain {
349 sender_ratchet_key: sender.serialize().to_vec(),
350 sender_ratchet_key_private: vec![],
351 chain_key: Some(chain_key),
352 message_keys: vec![],
353 };
354
355 self.session.receiver_chains.push(chain);
356
357 if self.session.receiver_chains.len() > consts::MAX_RECEIVER_CHAINS {
358 log::info!(
359 "Trimming excessive receiver_chain for session with base key {}, chain count: {}",
360 self.sender_ratchet_key_for_logging()
361 .unwrap_or_else(|e| format!("<error: {}>", e.0)),
362 self.session.receiver_chains.len()
363 );
364 self.session.receiver_chains.remove(0);
365 }
366 }
367
368 pub(crate) fn with_receiver_chain(mut self, sender: &PublicKey, chain_key: &ChainKey) -> Self {
369 self.add_receiver_chain(sender, chain_key);
370 self
371 }
372
373 pub(crate) fn set_sender_chain(&mut self, sender: &KeyPair, next_chain_key: &ChainKey) {
374 let chain_key = session_structure::chain::ChainKey {
375 index: next_chain_key.index(),
376 key: next_chain_key.key().to_vec(),
377 };
378
379 let new_chain = session_structure::Chain {
380 sender_ratchet_key: sender.public_key.serialize().to_vec(),
381 sender_ratchet_key_private: sender.private_key.serialize().to_vec(),
382 chain_key: Some(chain_key),
383 message_keys: vec![],
384 };
385
386 self.session.sender_chain = Some(new_chain);
387 }
388
389 pub(crate) fn with_sender_chain(mut self, sender: &KeyPair, next_chain_key: &ChainKey) -> Self {
390 self.set_sender_chain(sender, next_chain_key);
391 self
392 }
393
394 pub(crate) fn get_sender_chain_key(&self) -> Result<ChainKey, InvalidSessionError> {
395 let sender_chain = self
396 .session
397 .sender_chain
398 .as_ref()
399 .ok_or(InvalidSessionError("missing sender chain"))?;
400
401 let chain_key = sender_chain
402 .chain_key
403 .as_ref()
404 .ok_or(InvalidSessionError("missing sender chain key"))?;
405
406 let chain_key_bytes = chain_key.key[..]
407 .try_into()
408 .map_err(|_| InvalidSessionError("invalid sender chain key"))?;
409
410 Ok(ChainKey::new(chain_key_bytes, chain_key.index))
411 }
412
413 pub(crate) fn get_sender_chain_key_bytes(&self) -> Result<Vec<u8>, InvalidSessionError> {
414 Ok(self.get_sender_chain_key()?.key().to_vec())
415 }
416
417 pub(crate) fn set_sender_chain_key(&mut self, next_chain_key: &ChainKey) {
418 let chain_key = session_structure::chain::ChainKey {
419 index: next_chain_key.index(),
420 key: next_chain_key.key().to_vec(),
421 };
422
423 let new_chain = match self.session.sender_chain.take() {
426 None => session_structure::Chain {
427 sender_ratchet_key: vec![],
428 sender_ratchet_key_private: vec![],
429 chain_key: Some(chain_key),
430 message_keys: vec![],
431 },
432 Some(mut c) => {
433 c.chain_key = Some(chain_key);
434 c
435 }
436 };
437
438 self.session.sender_chain = Some(new_chain);
439 }
440
441 #[cfg(test)]
442 pub(crate) fn get_message_keys(
443 &mut self,
444 sender: &PublicKey,
445 counter: u32,
446 ) -> Result<Option<MessageKeyGenerator>, InvalidSessionError> {
447 if let Some(mut chain_and_index) = self.get_receiver_chain(sender)? {
448 let message_key_idx = chain_and_index
449 .0
450 .message_keys
451 .iter()
452 .position(|m| m.index == counter);
453
454 if let Some(position) = message_key_idx {
455 let message_key = chain_and_index.0.message_keys.remove(position);
456 let keys =
457 MessageKeyGenerator::from_pb(message_key).map_err(InvalidSessionError)?;
458
459 self.session.receiver_chains[chain_and_index.1] = chain_and_index.0;
461 return Ok(Some(keys));
462 }
463 }
464
465 Ok(None)
466 }
467
468 #[cfg(test)]
469 pub(crate) fn set_message_keys(
470 &mut self,
471 sender: &PublicKey,
472 message_keys: MessageKeyGenerator,
473 ) -> Result<(), InvalidSessionError> {
474 let chain_and_index = self
475 .get_receiver_chain(sender)?
476 .expect("called set_message_keys for a non-existent chain");
477 let mut updated_chain = chain_and_index.0;
478 updated_chain.message_keys.insert(0, message_keys.into_pb());
479
480 if updated_chain.message_keys.len() > consts::MAX_MESSAGE_KEYS {
481 updated_chain.message_keys.pop();
482 }
483
484 self.session.receiver_chains[chain_and_index.1] = updated_chain;
485
486 Ok(())
487 }
488
489 #[cfg(test)]
490 pub(crate) fn set_receiver_chain_key(
491 &mut self,
492 sender: &PublicKey,
493 chain_key: &ChainKey,
494 ) -> Result<(), InvalidSessionError> {
495 let chain_and_index = self
496 .get_receiver_chain(sender)?
497 .expect("called set_receiver_chain_key for a non-existent chain");
498 let mut updated_chain = chain_and_index.0;
499 updated_chain.chain_key = Some(session_structure::chain::ChainKey {
500 index: chain_key.index(),
501 key: chain_key.key().to_vec(),
502 });
503
504 self.session.receiver_chains[chain_and_index.1] = updated_chain;
505
506 Ok(())
507 }
508
509 pub(crate) fn set_unacknowledged_pre_key_message(
510 &mut self,
511 pre_key_id: Option<PreKeyId>,
512 signed_ec_pre_key_id: SignedPreKeyId,
513 base_key: &PublicKey,
514 now: SystemTime,
515 ) {
516 let signed_ec_pre_key_id: u32 = signed_ec_pre_key_id.into();
517 let pending = session_structure::PendingPreKey {
518 pre_key_id: pre_key_id.map(PreKeyId::into),
519 signed_pre_key_id: signed_ec_pre_key_id as i32,
520 base_key: base_key.serialize().to_vec(),
521 timestamp: now
522 .duration_since(SystemTime::UNIX_EPOCH)
523 .unwrap_or_default()
524 .as_secs(),
525 };
526 self.session.pending_pre_key = Some(pending);
527 }
528
529 pub(crate) fn set_kyber_ciphertext(&mut self, ciphertext: kem::SerializedCiphertext) {
530 let pending = session_structure::PendingKyberPreKey {
531 pre_key_id: u32::MAX, ciphertext: ciphertext.into_vec(),
533 };
534 self.session.pending_kyber_pre_key = Some(pending);
535 }
536
537 pub(crate) fn set_unacknowledged_kyber_pre_key_id(
538 &mut self,
539 signed_kyber_pre_key_id: KyberPreKeyId,
540 ) {
541 let pending = self
542 .session
543 .pending_kyber_pre_key
544 .as_mut()
545 .expect("must have been set if kyber pre key is present");
546 pending.pre_key_id = signed_kyber_pre_key_id.into();
547 }
548
549 pub(crate) fn unacknowledged_pre_key_message_items(
550 &self,
551 ) -> Result<Option<UnacknowledgedPreKeyMessageItems<'_>>, InvalidSessionError> {
552 if let Some(ref pending_pre_key) = self.session.pending_pre_key {
553 Ok(Some(UnacknowledgedPreKeyMessageItems::new(
554 pending_pre_key.pre_key_id.map(Into::into),
555 (pending_pre_key.signed_pre_key_id as u32).into(),
556 PublicKey::deserialize(&pending_pre_key.base_key)
557 .map_err(|_| InvalidSessionError("invalid pending PreKey message base key"))?,
558 self.session.pending_kyber_pre_key.as_ref(),
559 SystemTime::UNIX_EPOCH + Duration::from_secs(pending_pre_key.timestamp),
560 )))
561 } else {
562 Ok(None)
563 }
564 }
565
566 pub(crate) fn clear_unacknowledged_pre_key_message(&mut self) {
567 let SessionStructure {
570 session_version: _session_version,
571 local_identity_public: _local_identity_public,
572 remote_identity_public: _remote_identity_public,
573 root_key: _root_key,
574 previous_counter: _previous_counter,
575 sender_chain: _sender_chain,
576 receiver_chains: _receiver_chains,
577 pending_pre_key: _pending_pre_key,
578 pending_kyber_pre_key: _pending_kyber_pre_key,
579 remote_registration_id: _remote_registration_id,
580 local_registration_id: _local_registration_id,
581 alice_base_key: _alice_base_key,
582 pq_ratchet_state: _pq_ratchet_state,
583 } = &self.session;
584 self.session.pending_pre_key = None;
588 self.session.pending_kyber_pre_key = None;
589 }
590
591 pub(crate) fn set_remote_registration_id(&mut self, registration_id: u32) {
592 self.session.remote_registration_id = registration_id;
593 }
594
595 pub(crate) fn remote_registration_id(&self) -> u32 {
596 self.session.remote_registration_id
597 }
598
599 pub(crate) fn set_local_registration_id(&mut self, registration_id: u32) {
600 self.session.local_registration_id = registration_id;
601 }
602
603 pub(crate) fn local_registration_id(&self) -> u32 {
604 self.session.local_registration_id
605 }
606
607 pub(crate) fn get_kyber_ciphertext(&self) -> Option<&Vec<u8>> {
608 self.session
609 .pending_kyber_pre_key
610 .as_ref()
611 .map(|pending| &pending.ciphertext)
612 }
613
614 pub(crate) fn take_ratchet_state(
626 &mut self,
627 self_session: bool,
628 ) -> crate::error::Result<crate::double_ratchet::RatchetState> {
629 let receiver_chains = std::mem::take(&mut self.session.receiver_chains);
630 Ok(crate::double_ratchet::RatchetState::from_pb(
631 &self.session,
632 self_session,
633 receiver_chains,
634 )?)
635 }
636
637 pub(crate) fn apply_ratchet_state(&mut self, ratchet: crate::double_ratchet::RatchetState) {
643 ratchet.apply_to_pb(&mut self.session);
644 }
645
646 #[cfg(test)]
647 pub(crate) fn pq_ratchet_recv(
648 &mut self,
649 msg: &spqr::SerializedMessage,
650 ) -> Result<spqr::MessageKey, spqr::Error> {
651 let _trace = libsignal_debug::trace_block!("SessionState::pq_ratchet_recv");
652 let spqr::Recv { state, key } = spqr::recv(&self.session.pq_ratchet_state, msg)?;
653 self.session.pq_ratchet_state = state;
654 Ok(key)
655 }
656
657 #[cfg(test)]
658 pub(crate) fn pq_ratchet_send<R: Rng + CryptoRng>(
659 &mut self,
660 csprng: &mut R,
661 ) -> Result<(spqr::SerializedMessage, spqr::MessageKey), spqr::Error> {
662 let _trace = libsignal_debug::trace_block!("SessionState::pq_ratchet_send");
663 let spqr::Send { state, key, msg } = spqr::send(&self.session.pq_ratchet_state, csprng)?;
664 self.session.pq_ratchet_state = state;
665 Ok((msg, key))
666 }
667
668 pub(crate) fn pq_ratchet_state(&self) -> &spqr::SerializedState {
669 &self.session.pq_ratchet_state
670 }
671
672 pub(crate) fn take_pq_ratchet_state(&mut self) -> spqr::SerializedState {
678 std::mem::take(&mut self.session.pq_ratchet_state)
679 }
680
681 pub(crate) fn set_pq_ratchet_state(&mut self, state: spqr::SerializedState) {
682 self.session.pq_ratchet_state = state;
683 }
684}
685
686impl From<SessionStructure> for SessionState {
687 fn from(value: SessionStructure) -> SessionState {
688 SessionState::from_session_structure(value)
689 }
690}
691
692impl From<SessionState> for SessionStructure {
693 fn from(value: SessionState) -> SessionStructure {
694 value.session
695 }
696}
697
698impl From<&SessionState> for SessionStructure {
699 fn from(value: &SessionState) -> SessionStructure {
700 value.session.clone()
701 }
702}
703
704#[derive(Clone)]
705pub struct SessionRecord {
706 current_session: Option<SessionState>,
707 previous_sessions: Vec<Vec<u8>>,
708}
709
710impl SessionRecord {
711 pub fn new_fresh() -> Self {
712 Self {
713 current_session: None,
714 previous_sessions: Vec::new(),
715 }
716 }
717
718 pub(crate) fn new(state: SessionState) -> Self {
719 Self {
720 current_session: Some(state),
721 previous_sessions: Vec::new(),
722 }
723 }
724
725 pub fn deserialize(bytes: &[u8]) -> Result<Self, SignalProtocolError> {
726 let record = RecordStructure::decode(bytes)
727 .map_err(|_| InvalidSessionError("failed to decode session record protobuf"))?;
728
729 Ok(Self {
730 current_session: record.current_session.map(|s| s.into()),
731 previous_sessions: record.previous_sessions,
732 })
733 }
734
735 pub(crate) fn promote_matching_session(
742 &mut self,
743 version: u32,
744 alice_base_key: &[u8],
745 ) -> Result<bool, InvalidSessionError> {
746 if let Some(current_session) = &self.current_session {
747 if current_session.session_version()? == version
748 && alice_base_key
749 .ct_eq(current_session.alice_base_key())
750 .into()
751 {
752 return Ok(true);
753 }
754 }
755
756 let mut session_to_promote = None;
757 for (i, previous) in self.previous_session_states().enumerate() {
758 let previous = previous?;
759 if previous.session_version()? == version
760 && alice_base_key.ct_eq(previous.alice_base_key()).into()
761 {
762 session_to_promote = Some((i, previous));
763 break;
764 }
765 }
766
767 if let Some((i, state)) = session_to_promote {
768 self.promote_old_session(i, state);
769 return Ok(true);
770 }
771
772 Ok(false)
773 }
774
775 pub(crate) fn session_state(&self) -> Option<&SessionState> {
776 self.current_session.as_ref()
777 }
778
779 pub(crate) fn session_state_mut(&mut self) -> Option<&mut SessionState> {
780 self.current_session.as_mut()
781 }
782
783 pub(crate) fn set_session_state(&mut self, session: SessionState) {
784 self.current_session = Some(session);
785 }
786
787 pub(crate) fn previous_session_states(
788 &self,
789 ) -> impl ExactSizeIterator<Item = Result<SessionState, InvalidSessionError>> + '_ {
790 self.previous_sessions.iter().map(|bytes| {
791 Ok(SessionStructure::decode(&bytes[..])
792 .map_err(|_| InvalidSessionError("failed to decode previous session protobuf"))?
793 .into())
794 })
795 }
796
797 pub(crate) fn promote_old_session(
798 &mut self,
799 old_session: usize,
800 updated_session: SessionState,
801 ) {
802 self.previous_sessions.remove(old_session);
803 self.promote_state(updated_session)
804 }
805
806 pub(crate) fn promote_state(&mut self, new_state: SessionState) {
807 self.archive_current_state_inner();
808 self.current_session = Some(new_state);
809 }
810
811 fn archive_current_state_inner(&mut self) -> bool {
815 if let Some(mut current_session) = self.current_session.take() {
816 if self.previous_sessions.len() >= consts::ARCHIVED_STATES_MAX_LENGTH {
817 self.previous_sessions.pop();
818 }
819 current_session.clear_unacknowledged_pre_key_message();
820 self.previous_sessions
821 .insert(0, current_session.session.encode_to_vec());
822 true
823 } else {
824 false
825 }
826 }
827
828 pub fn archive_current_state(&mut self) -> Result<(), SignalProtocolError> {
829 if !self.archive_current_state_inner() {
830 log::info!("Skipping archive, current session state is fresh");
831 }
832 Ok(())
833 }
834
835 pub fn serialize(&self) -> Result<Vec<u8>, SignalProtocolError> {
836 let record = RecordStructure {
837 current_session: self.current_session.as_ref().map(|s| s.into()),
838 previous_sessions: self.previous_sessions.clone(),
839 };
840 Ok(record.encode_to_vec())
841 }
842
843 pub fn current_pq_state(&self) -> Option<&spqr::SerializedState> {
844 self.current_session.as_ref().map(|s| s.pq_ratchet_state())
845 }
846
847 pub fn remote_registration_id(&self) -> Result<u32, SignalProtocolError> {
848 Ok(self
849 .session_state()
850 .ok_or_else(|| {
851 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
852 "remote_registration_id",
853 ))
854 })?
855 .remote_registration_id())
856 }
857
858 pub fn local_registration_id(&self) -> Result<u32, SignalProtocolError> {
859 Ok(self
860 .session_state()
861 .ok_or_else(|| {
862 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
863 "local_registration_id",
864 ))
865 })?
866 .local_registration_id())
867 }
868
869 pub fn session_version(&self) -> Result<u32, SignalProtocolError> {
870 Ok(self
871 .session_state()
872 .ok_or_else(|| {
873 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
874 "session_version",
875 ))
876 })?
877 .session_version()?)
878 }
879
880 pub fn local_identity_key_bytes(&self) -> Result<Vec<u8>, SignalProtocolError> {
881 Ok(self
882 .session_state()
883 .ok_or_else(|| {
884 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
885 "local_identity_key_bytes",
886 ))
887 })?
888 .local_identity_key_bytes()?)
889 }
890
891 pub fn remote_identity_key_bytes(&self) -> Result<Option<Vec<u8>>, SignalProtocolError> {
892 Ok(self
893 .session_state()
894 .ok_or_else(|| {
895 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
896 "remote_identity_key_bytes",
897 ))
898 })?
899 .remote_identity_key_bytes()?)
900 }
901
902 pub fn has_usable_sender_chain(
903 &self,
904 now: SystemTime,
905 requirements: SessionUsabilityRequirements,
906 ) -> Result<bool, SignalProtocolError> {
907 match &self.current_session {
908 Some(session) => Ok(session.has_usable_sender_chain(now, requirements)?),
909 None => Ok(false),
910 }
911 }
912
913 pub fn alice_base_key(&self) -> Result<&[u8], SignalProtocolError> {
914 Ok(self
915 .session_state()
916 .ok_or_else(|| {
917 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
918 "alice_base_key",
919 ))
920 })?
921 .alice_base_key())
922 }
923
924 pub fn get_receiver_chain_key_bytes(
925 &self,
926 sender: &PublicKey,
927 ) -> Result<Option<Box<[u8]>>, SignalProtocolError> {
928 Ok(self
929 .session_state()
930 .ok_or_else(|| {
931 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
932 "get_receiver_chain_key",
933 ))
934 })?
935 .get_receiver_chain_key(sender)?
936 .map(|chain| chain.key()[..].into()))
937 }
938
939 pub fn get_sender_chain_key_bytes(&self) -> Result<Vec<u8>, SignalProtocolError> {
940 Ok(self
941 .session_state()
942 .ok_or_else(|| {
943 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
944 "get_sender_chain_key_bytes",
945 ))
946 })?
947 .get_sender_chain_key_bytes()?)
948 }
949
950 pub fn current_ratchet_key_matches(
951 &self,
952 key: &PublicKey,
953 ) -> Result<bool, SignalProtocolError> {
954 match &self.current_session {
955 Some(session) => Ok(&session.sender_ratchet_key()? == key),
956 None => Ok(false),
957 }
958 }
959
960 pub fn get_kyber_ciphertext(&self) -> Result<Option<&Vec<u8>>, SignalProtocolError> {
961 Ok(self
962 .session_state()
963 .ok_or_else(|| {
964 SignalProtocolError::SessionNotFound(SessionNotFound::without_address(
965 "get_kyber_ciphertext",
966 ))
967 })?
968 .get_kyber_ciphertext())
969 }
970}