1use std::result::Result;
7use std::time::{Duration, SystemTime};
8
9use prost::Message;
10use subtle::ConstantTimeEq;
11
12use crate::proto::storage::{session_structure, RecordStructure, SessionStructure};
13use crate::ratchet::{ChainKey, MessageKeys, RootKey};
14use crate::state::{KyberPreKeyId, PreKeyId, SignedPreKeyId};
15use crate::{consts, kem, IdentityKey, KeyPair, PrivateKey, PublicKey, SignalProtocolError};
16
17#[derive(Debug)]
19pub(crate) struct InvalidSessionError(&'static str);
20
21impl std::fmt::Display for InvalidSessionError {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 self.0.fmt(f)
24 }
25}
26
27impl From<InvalidSessionError> for SignalProtocolError {
28 fn from(e: InvalidSessionError) -> Self {
29 Self::InvalidSessionStructure(e.0)
30 }
31}
32
33#[derive(Debug, Clone)]
34pub(crate) struct UnacknowledgedPreKeyMessageItems<'a> {
35 pre_key_id: Option<PreKeyId>,
36 signed_pre_key_id: SignedPreKeyId,
37 base_key: PublicKey,
38 kyber_pre_key_id: Option<KyberPreKeyId>,
39 kyber_ciphertext: Option<&'a [u8]>,
40 timestamp: SystemTime,
41}
42
43impl<'a> UnacknowledgedPreKeyMessageItems<'a> {
44 fn new(
45 pre_key_id: Option<PreKeyId>,
46 signed_pre_key_id: SignedPreKeyId,
47 base_key: PublicKey,
48 pending_kyber_pre_key: Option<&'a session_structure::PendingKyberPreKey>,
49 timestamp: SystemTime,
50 ) -> Self {
51 let (kyber_pre_key_id, kyber_ciphertext) = pending_kyber_pre_key
52 .map(|pending| (pending.pre_key_id.into(), pending.ciphertext.as_slice()))
53 .unzip();
54 Self {
55 pre_key_id,
56 signed_pre_key_id,
57 base_key,
58 kyber_pre_key_id,
59 kyber_ciphertext,
60 timestamp,
61 }
62 }
63
64 pub(crate) fn pre_key_id(&self) -> Option<PreKeyId> {
65 self.pre_key_id
66 }
67
68 pub(crate) fn signed_pre_key_id(&self) -> SignedPreKeyId {
69 self.signed_pre_key_id
70 }
71
72 pub(crate) fn base_key(&self) -> &PublicKey {
73 &self.base_key
74 }
75
76 pub(crate) fn kyber_pre_key_id(&self) -> Option<KyberPreKeyId> {
77 self.kyber_pre_key_id
78 }
79
80 pub(crate) fn kyber_ciphertext(&self) -> Option<&'a [u8]> {
81 self.kyber_ciphertext
82 }
83
84 pub(crate) fn timestamp(&self) -> SystemTime {
85 self.timestamp
86 }
87}
88
89#[derive(Clone, Debug)]
90pub(crate) struct SessionState {
91 session: SessionStructure,
92}
93
94impl SessionState {
95 pub(crate) fn from_session_structure(session: SessionStructure) -> Self {
96 Self { session }
97 }
98
99 pub(crate) fn new(
100 version: u8,
101 our_identity: &IdentityKey,
102 their_identity: &IdentityKey,
103 root_key: &RootKey,
104 alice_base_key: &PublicKey,
105 ) -> Self {
106 Self {
107 session: SessionStructure {
108 session_version: version as u32,
109 local_identity_public: our_identity.public_key().serialize().into_vec(),
110 remote_identity_public: their_identity.serialize().into_vec(),
111 root_key: root_key.key().to_vec(),
112 previous_counter: 0,
113 sender_chain: None,
114 receiver_chains: vec![],
115 pending_pre_key: None,
116 pending_kyber_pre_key: None,
117 remote_registration_id: 0,
118 local_registration_id: 0,
119 alice_base_key: alice_base_key.serialize().into_vec(),
120 },
121 }
122 }
123
124 pub(crate) fn alice_base_key(&self) -> &[u8] {
125 &self.session.alice_base_key
127 }
128
129 pub(crate) fn session_version(&self) -> Result<u32, InvalidSessionError> {
130 match self.session.session_version {
131 0 => Ok(2),
132 v => Ok(v),
133 }
134 }
135
136 pub(crate) fn remote_identity_key(&self) -> Result<Option<IdentityKey>, InvalidSessionError> {
137 match self.session.remote_identity_public.len() {
138 0 => Ok(None),
139 _ => Ok(Some(
140 IdentityKey::decode(&self.session.remote_identity_public)
141 .map_err(|_| InvalidSessionError("invalid remote identity key"))?,
142 )),
143 }
144 }
145
146 pub(crate) fn remote_identity_key_bytes(&self) -> Result<Option<Vec<u8>>, InvalidSessionError> {
147 Ok(self.remote_identity_key()?.map(|k| k.serialize().to_vec()))
148 }
149
150 pub(crate) fn local_identity_key(&self) -> Result<IdentityKey, InvalidSessionError> {
151 IdentityKey::decode(&self.session.local_identity_public)
152 .map_err(|_| InvalidSessionError("invalid local identity key"))
153 }
154
155 pub(crate) fn local_identity_key_bytes(&self) -> Result<Vec<u8>, InvalidSessionError> {
156 Ok(self.local_identity_key()?.serialize().to_vec())
157 }
158
159 pub(crate) fn session_with_self(&self) -> Result<bool, InvalidSessionError> {
160 if let Some(remote_id) = self.remote_identity_key_bytes()? {
161 let local_id = self.local_identity_key_bytes()?;
162 return Ok(remote_id == local_id);
163 }
164
165 Ok(false)
167 }
168
169 pub(crate) fn previous_counter(&self) -> u32 {
170 self.session.previous_counter
171 }
172
173 pub(crate) fn set_previous_counter(&mut self, ctr: u32) {
174 self.session.previous_counter = ctr;
175 }
176
177 pub(crate) fn root_key(&self) -> Result<RootKey, InvalidSessionError> {
178 let root_key_bytes = self.session.root_key[..]
179 .try_into()
180 .map_err(|_| InvalidSessionError("invalid root key"))?;
181 Ok(RootKey::new(root_key_bytes))
182 }
183
184 pub(crate) fn set_root_key(&mut self, root_key: &RootKey) {
185 self.session.root_key = root_key.key().to_vec();
186 }
187
188 pub(crate) fn sender_ratchet_key(&self) -> Result<PublicKey, InvalidSessionError> {
189 match self.session.sender_chain {
190 None => Err(InvalidSessionError("missing sender chain")),
191 Some(ref c) => PublicKey::deserialize(&c.sender_ratchet_key)
192 .map_err(|_| InvalidSessionError("invalid sender chain ratchet key")),
193 }
194 }
195
196 pub(crate) fn sender_ratchet_key_for_logging(&self) -> Result<String, InvalidSessionError> {
197 Ok(hex::encode(
198 self.sender_ratchet_key()?
199 .public_key_bytes()
200 .expect("no invalid public keys"),
201 ))
202 }
203
204 pub(crate) fn sender_ratchet_private_key(&self) -> Result<PrivateKey, InvalidSessionError> {
205 match self.session.sender_chain {
206 None => Err(InvalidSessionError("missing sender chain")),
207 Some(ref c) => PrivateKey::deserialize(&c.sender_ratchet_key_private)
208 .map_err(|_| InvalidSessionError("invalid sender chain private ratchet key")),
209 }
210 }
211
212 pub fn has_usable_sender_chain(&self, now: SystemTime) -> Result<bool, InvalidSessionError> {
213 if self.session.sender_chain.is_none() {
214 return Ok(false);
215 }
216 if let Some(pending_pre_key) = &self.session.pending_pre_key {
217 let creation_timestamp =
218 SystemTime::UNIX_EPOCH + Duration::from_secs(pending_pre_key.timestamp);
219 if creation_timestamp + consts::MAX_UNACKNOWLEDGED_SESSION_AGE < now {
220 return Ok(false);
221 }
222 }
223 Ok(true)
224 }
225
226 pub(crate) fn all_receiver_chain_logging_info(&self) -> Vec<(Vec<u8>, Option<u32>)> {
227 let mut results = vec![];
228 for chain in self.session.receiver_chains.iter() {
229 let sender_ratchet_public = chain.sender_ratchet_key.clone();
230
231 let chain_key_idx = chain.chain_key.as_ref().map(|chain_key| chain_key.index);
232
233 results.push((sender_ratchet_public, chain_key_idx))
234 }
235 results
236 }
237
238 pub(crate) fn get_receiver_chain(
239 &self,
240 sender: &PublicKey,
241 ) -> Result<Option<(session_structure::Chain, usize)>, InvalidSessionError> {
242 for (idx, chain) in self.session.receiver_chains.iter().enumerate() {
243 let chain_ratchet_key = PublicKey::deserialize(&chain.sender_ratchet_key)
246 .map_err(|_| InvalidSessionError("invalid receiver chain ratchet key"))?;
247
248 if &chain_ratchet_key == sender {
249 return Ok(Some((chain.clone(), idx)));
250 }
251 }
252
253 Ok(None)
254 }
255
256 pub(crate) fn get_receiver_chain_key(
257 &self,
258 sender: &PublicKey,
259 ) -> Result<Option<ChainKey>, InvalidSessionError> {
260 match self.get_receiver_chain(sender)? {
261 None => Ok(None),
262 Some((chain, _)) => match chain.chain_key {
263 None => Err(InvalidSessionError("missing receiver chain key")),
264 Some(c) => {
265 let chain_key_bytes = c.key[..]
266 .try_into()
267 .map_err(|_| InvalidSessionError("invalid receiver chain key"))?;
268 Ok(Some(ChainKey::new(chain_key_bytes, c.index)))
269 }
270 },
271 }
272 }
273
274 pub(crate) fn add_receiver_chain(&mut self, sender: &PublicKey, chain_key: &ChainKey) {
275 let chain_key = session_structure::chain::ChainKey {
276 index: chain_key.index(),
277 key: chain_key.key().to_vec(),
278 };
279
280 let chain = session_structure::Chain {
281 sender_ratchet_key: sender.serialize().to_vec(),
282 sender_ratchet_key_private: vec![],
283 chain_key: Some(chain_key),
284 message_keys: vec![],
285 };
286
287 self.session.receiver_chains.push(chain);
288
289 if self.session.receiver_chains.len() > consts::MAX_RECEIVER_CHAINS {
290 log::info!(
291 "Trimming excessive receiver_chain for session with base key {}, chain count: {}",
292 self.sender_ratchet_key_for_logging()
293 .unwrap_or_else(|e| format!("<error: {}>", e.0)),
294 self.session.receiver_chains.len()
295 );
296 self.session.receiver_chains.remove(0);
297 }
298 }
299
300 pub(crate) fn with_receiver_chain(mut self, sender: &PublicKey, chain_key: &ChainKey) -> Self {
301 self.add_receiver_chain(sender, chain_key);
302 self
303 }
304
305 pub(crate) fn set_sender_chain(&mut self, sender: &KeyPair, next_chain_key: &ChainKey) {
306 let chain_key = session_structure::chain::ChainKey {
307 index: next_chain_key.index(),
308 key: next_chain_key.key().to_vec(),
309 };
310
311 let new_chain = session_structure::Chain {
312 sender_ratchet_key: sender.public_key.serialize().to_vec(),
313 sender_ratchet_key_private: sender.private_key.serialize().to_vec(),
314 chain_key: Some(chain_key),
315 message_keys: vec![],
316 };
317
318 self.session.sender_chain = Some(new_chain);
319 }
320
321 pub(crate) fn with_sender_chain(mut self, sender: &KeyPair, next_chain_key: &ChainKey) -> Self {
322 self.set_sender_chain(sender, next_chain_key);
323 self
324 }
325
326 pub(crate) fn get_sender_chain_key(&self) -> Result<ChainKey, InvalidSessionError> {
327 let sender_chain = self
328 .session
329 .sender_chain
330 .as_ref()
331 .ok_or(InvalidSessionError("missing sender chain"))?;
332
333 let chain_key = sender_chain
334 .chain_key
335 .as_ref()
336 .ok_or(InvalidSessionError("missing sender chain key"))?;
337
338 let chain_key_bytes = chain_key.key[..]
339 .try_into()
340 .map_err(|_| InvalidSessionError("invalid sender chain key"))?;
341
342 Ok(ChainKey::new(chain_key_bytes, chain_key.index))
343 }
344
345 pub(crate) fn get_sender_chain_key_bytes(&self) -> Result<Vec<u8>, InvalidSessionError> {
346 Ok(self.get_sender_chain_key()?.key().to_vec())
347 }
348
349 pub(crate) fn set_sender_chain_key(&mut self, next_chain_key: &ChainKey) {
350 let chain_key = session_structure::chain::ChainKey {
351 index: next_chain_key.index(),
352 key: next_chain_key.key().to_vec(),
353 };
354
355 let new_chain = match self.session.sender_chain.take() {
358 None => session_structure::Chain {
359 sender_ratchet_key: vec![],
360 sender_ratchet_key_private: vec![],
361 chain_key: Some(chain_key),
362 message_keys: vec![],
363 },
364 Some(mut c) => {
365 c.chain_key = Some(chain_key);
366 c
367 }
368 };
369
370 self.session.sender_chain = Some(new_chain);
371 }
372
373 pub(crate) fn get_message_keys(
374 &mut self,
375 sender: &PublicKey,
376 counter: u32,
377 ) -> Result<Option<MessageKeys>, InvalidSessionError> {
378 if let Some(mut chain_and_index) = self.get_receiver_chain(sender)? {
379 let message_key_idx = chain_and_index
380 .0
381 .message_keys
382 .iter()
383 .position(|m| m.index == counter);
384
385 if let Some(position) = message_key_idx {
386 let message_key = chain_and_index.0.message_keys.remove(position);
387
388 let cipher_key_bytes = message_key
389 .cipher_key
390 .try_into()
391 .map_err(|_| InvalidSessionError("invalid message cipher key"))?;
392 let mac_key_bytes = message_key
393 .mac_key
394 .try_into()
395 .map_err(|_| InvalidSessionError("invalid message MAC key"))?;
396 let iv_bytes = message_key
397 .iv
398 .try_into()
399 .map_err(|_| InvalidSessionError("invalid message IV"))?;
400
401 let keys = MessageKeys::new(cipher_key_bytes, mac_key_bytes, iv_bytes, counter);
402
403 self.session.receiver_chains[chain_and_index.1] = chain_and_index.0;
405 return Ok(Some(keys));
406 }
407 }
408
409 Ok(None)
410 }
411
412 pub(crate) fn set_message_keys(
413 &mut self,
414 sender: &PublicKey,
415 message_keys: &MessageKeys,
416 ) -> Result<(), InvalidSessionError> {
417 let new_keys = session_structure::chain::MessageKey {
418 cipher_key: message_keys.cipher_key().to_vec(),
419 mac_key: message_keys.mac_key().to_vec(),
420 iv: message_keys.iv().to_vec(),
421 index: message_keys.counter(),
422 };
423
424 let chain_and_index = self
425 .get_receiver_chain(sender)?
426 .expect("called set_message_keys for a non-existent chain");
427 let mut updated_chain = chain_and_index.0;
428 updated_chain.message_keys.insert(0, new_keys);
429
430 if updated_chain.message_keys.len() > consts::MAX_MESSAGE_KEYS {
431 updated_chain.message_keys.pop();
432 }
433
434 self.session.receiver_chains[chain_and_index.1] = updated_chain;
435
436 Ok(())
437 }
438
439 pub(crate) fn set_receiver_chain_key(
440 &mut self,
441 sender: &PublicKey,
442 chain_key: &ChainKey,
443 ) -> Result<(), InvalidSessionError> {
444 let chain_and_index = self
445 .get_receiver_chain(sender)?
446 .expect("called set_receiver_chain_key for a non-existent chain");
447 let mut updated_chain = chain_and_index.0;
448 updated_chain.chain_key = Some(session_structure::chain::ChainKey {
449 index: chain_key.index(),
450 key: chain_key.key().to_vec(),
451 });
452
453 self.session.receiver_chains[chain_and_index.1] = updated_chain;
454
455 Ok(())
456 }
457
458 pub(crate) fn set_unacknowledged_pre_key_message(
459 &mut self,
460 pre_key_id: Option<PreKeyId>,
461 signed_ec_pre_key_id: SignedPreKeyId,
462 base_key: &PublicKey,
463 now: SystemTime,
464 ) {
465 let signed_ec_pre_key_id: u32 = signed_ec_pre_key_id.into();
466 let pending = session_structure::PendingPreKey {
467 pre_key_id: pre_key_id.map(PreKeyId::into),
468 signed_pre_key_id: signed_ec_pre_key_id as i32,
469 base_key: base_key.serialize().to_vec(),
470 timestamp: now
471 .duration_since(SystemTime::UNIX_EPOCH)
472 .unwrap_or_default()
473 .as_secs(),
474 };
475 self.session.pending_pre_key = Some(pending);
476 }
477
478 #[allow(clippy::boxed_local)]
479 pub(crate) fn set_kyber_ciphertext(&mut self, ciphertext: kem::SerializedCiphertext) {
480 let pending = session_structure::PendingKyberPreKey {
481 pre_key_id: u32::MAX, ciphertext: ciphertext.to_vec(),
483 };
484 self.session.pending_kyber_pre_key = Some(pending);
485 }
486
487 pub(crate) fn set_unacknowledged_kyber_pre_key_id(
488 &mut self,
489 signed_kyber_pre_key_id: KyberPreKeyId,
490 ) {
491 let pending = self
492 .session
493 .pending_kyber_pre_key
494 .as_mut()
495 .expect("must have been set if kyber pre key is present");
496 pending.pre_key_id = signed_kyber_pre_key_id.into();
497 }
498
499 pub(crate) fn unacknowledged_pre_key_message_items(
500 &self,
501 ) -> Result<Option<UnacknowledgedPreKeyMessageItems>, InvalidSessionError> {
502 if let Some(ref pending_pre_key) = self.session.pending_pre_key {
503 Ok(Some(UnacknowledgedPreKeyMessageItems::new(
504 pending_pre_key.pre_key_id.map(Into::into),
505 (pending_pre_key.signed_pre_key_id as u32).into(),
506 PublicKey::deserialize(&pending_pre_key.base_key)
507 .map_err(|_| InvalidSessionError("invalid pending PreKey message base key"))?,
508 self.session.pending_kyber_pre_key.as_ref(),
509 SystemTime::UNIX_EPOCH + Duration::from_secs(pending_pre_key.timestamp),
510 )))
511 } else {
512 Ok(None)
513 }
514 }
515
516 pub(crate) fn clear_unacknowledged_pre_key_message(&mut self) {
517 let SessionStructure {
520 session_version: _session_version,
521 local_identity_public: _local_identity_public,
522 remote_identity_public: _remote_identity_public,
523 root_key: _root_key,
524 previous_counter: _previous_counter,
525 sender_chain: _sender_chain,
526 receiver_chains: _receiver_chains,
527 pending_pre_key: _pending_pre_key,
528 pending_kyber_pre_key: _pending_kyber_pre_key,
529 remote_registration_id: _remote_registration_id,
530 local_registration_id: _local_registration_id,
531 alice_base_key: _alice_base_key,
532 } = &self.session;
533 self.session.pending_pre_key = None;
537 self.session.pending_kyber_pre_key = None;
538 }
539
540 pub(crate) fn set_remote_registration_id(&mut self, registration_id: u32) {
541 self.session.remote_registration_id = registration_id;
542 }
543
544 pub(crate) fn remote_registration_id(&self) -> u32 {
545 self.session.remote_registration_id
546 }
547
548 pub(crate) fn set_local_registration_id(&mut self, registration_id: u32) {
549 self.session.local_registration_id = registration_id;
550 }
551
552 pub(crate) fn local_registration_id(&self) -> u32 {
553 self.session.local_registration_id
554 }
555
556 pub(crate) fn get_kyber_ciphertext(&self) -> Option<&Vec<u8>> {
557 self.session
558 .pending_kyber_pre_key
559 .as_ref()
560 .map(|pending| &pending.ciphertext)
561 }
562}
563
564impl From<SessionStructure> for SessionState {
565 fn from(value: SessionStructure) -> SessionState {
566 SessionState::from_session_structure(value)
567 }
568}
569
570impl From<SessionState> for SessionStructure {
571 fn from(value: SessionState) -> SessionStructure {
572 value.session
573 }
574}
575
576impl From<&SessionState> for SessionStructure {
577 fn from(value: &SessionState) -> SessionStructure {
578 value.session.clone()
579 }
580}
581
582#[derive(Clone)]
583pub struct SessionRecord {
584 current_session: Option<SessionState>,
585 previous_sessions: Vec<Vec<u8>>,
586}
587
588impl SessionRecord {
589 pub fn new_fresh() -> Self {
590 Self {
591 current_session: None,
592 previous_sessions: Vec::new(),
593 }
594 }
595
596 pub(crate) fn new(state: SessionState) -> Self {
597 Self {
598 current_session: Some(state),
599 previous_sessions: Vec::new(),
600 }
601 }
602
603 pub fn deserialize(bytes: &[u8]) -> Result<Self, SignalProtocolError> {
604 let record = RecordStructure::decode(bytes)
605 .map_err(|_| InvalidSessionError("failed to decode session record protobuf"))?;
606
607 Ok(Self {
608 current_session: record.current_session.map(|s| s.into()),
609 previous_sessions: record.previous_sessions,
610 })
611 }
612
613 pub(crate) fn has_session_state(
614 &self,
615 version: u32,
616 alice_base_key: &[u8],
617 ) -> Result<bool, InvalidSessionError> {
618 if let Some(current_session) = &self.current_session {
619 if current_session.session_version()? == version
620 && alice_base_key
621 .ct_eq(current_session.alice_base_key())
622 .into()
623 {
624 return Ok(true);
625 }
626 }
627
628 for previous in self.previous_session_states() {
629 let previous = previous?;
630 if previous.session_version()? == version
631 && alice_base_key.ct_eq(previous.alice_base_key()).into()
632 {
633 return Ok(true);
634 }
635 }
636
637 Ok(false)
638 }
639
640 pub(crate) fn session_state(&self) -> Option<&SessionState> {
641 self.current_session.as_ref()
642 }
643
644 pub(crate) fn session_state_mut(&mut self) -> Option<&mut SessionState> {
645 self.current_session.as_mut()
646 }
647
648 pub(crate) fn set_session_state(&mut self, session: SessionState) {
649 self.current_session = Some(session);
650 }
651
652 pub(crate) fn previous_session_states(
653 &self,
654 ) -> impl ExactSizeIterator<Item = Result<SessionState, InvalidSessionError>> + '_ {
655 self.previous_sessions.iter().map(|bytes| {
656 Ok(SessionStructure::decode(&bytes[..])
657 .map_err(|_| InvalidSessionError("failed to decode previous session protobuf"))?
658 .into())
659 })
660 }
661
662 pub(crate) fn promote_old_session(
663 &mut self,
664 old_session: usize,
665 updated_session: SessionState,
666 ) {
667 self.previous_sessions.remove(old_session);
668 self.promote_state(updated_session)
669 }
670
671 pub(crate) fn promote_state(&mut self, new_state: SessionState) {
672 self.archive_current_state_inner();
673 self.current_session = Some(new_state);
674 }
675
676 fn archive_current_state_inner(&mut self) -> bool {
680 if let Some(mut current_session) = self.current_session.take() {
681 if self.previous_sessions.len() >= consts::ARCHIVED_STATES_MAX_LENGTH {
682 self.previous_sessions.pop();
683 }
684 current_session.clear_unacknowledged_pre_key_message();
685 self.previous_sessions
686 .insert(0, current_session.session.encode_to_vec());
687 true
688 } else {
689 false
690 }
691 }
692
693 pub fn archive_current_state(&mut self) -> Result<(), SignalProtocolError> {
694 if !self.archive_current_state_inner() {
695 log::info!("Skipping archive, current session state is fresh");
696 }
697 Ok(())
698 }
699
700 pub fn serialize(&self) -> Result<Vec<u8>, SignalProtocolError> {
701 let record = RecordStructure {
702 current_session: self.current_session.as_ref().map(|s| s.into()),
703 previous_sessions: self.previous_sessions.clone(),
704 };
705 Ok(record.encode_to_vec())
706 }
707
708 pub fn remote_registration_id(&self) -> Result<u32, SignalProtocolError> {
709 Ok(self
710 .session_state()
711 .ok_or_else(|| {
712 SignalProtocolError::InvalidState(
713 "remote_registration_id",
714 "No current session".into(),
715 )
716 })?
717 .remote_registration_id())
718 }
719
720 pub fn local_registration_id(&self) -> Result<u32, SignalProtocolError> {
721 Ok(self
722 .session_state()
723 .ok_or_else(|| {
724 SignalProtocolError::InvalidState(
725 "local_registration_id",
726 "No current session".into(),
727 )
728 })?
729 .local_registration_id())
730 }
731
732 pub fn session_version(&self) -> Result<u32, SignalProtocolError> {
733 Ok(self
734 .session_state()
735 .ok_or_else(|| {
736 SignalProtocolError::InvalidState("session_version", "No current session".into())
737 })?
738 .session_version()?)
739 }
740
741 pub fn local_identity_key_bytes(&self) -> Result<Vec<u8>, SignalProtocolError> {
742 Ok(self
743 .session_state()
744 .ok_or_else(|| {
745 SignalProtocolError::InvalidState(
746 "local_identity_key_bytes",
747 "No current session".into(),
748 )
749 })?
750 .local_identity_key_bytes()?)
751 }
752
753 pub fn remote_identity_key_bytes(&self) -> Result<Option<Vec<u8>>, SignalProtocolError> {
754 Ok(self
755 .session_state()
756 .ok_or_else(|| {
757 SignalProtocolError::InvalidState(
758 "remote_identity_key_bytes",
759 "No current session".into(),
760 )
761 })?
762 .remote_identity_key_bytes()?)
763 }
764
765 pub fn has_usable_sender_chain(&self, now: SystemTime) -> Result<bool, SignalProtocolError> {
766 match &self.current_session {
767 Some(session) => Ok(session.has_usable_sender_chain(now)?),
768 None => Ok(false),
769 }
770 }
771
772 pub fn alice_base_key(&self) -> Result<&[u8], SignalProtocolError> {
773 Ok(self
774 .session_state()
775 .ok_or_else(|| {
776 SignalProtocolError::InvalidState("alice_base_key", "No current session".into())
777 })?
778 .alice_base_key())
779 }
780
781 pub fn get_receiver_chain_key_bytes(
782 &self,
783 sender: &PublicKey,
784 ) -> Result<Option<Box<[u8]>>, SignalProtocolError> {
785 Ok(self
786 .session_state()
787 .ok_or_else(|| {
788 SignalProtocolError::InvalidState(
789 "get_receiver_chain_key",
790 "No current session".into(),
791 )
792 })?
793 .get_receiver_chain_key(sender)?
794 .map(|chain| chain.key()[..].into()))
795 }
796
797 pub fn get_sender_chain_key_bytes(&self) -> Result<Vec<u8>, SignalProtocolError> {
798 Ok(self
799 .session_state()
800 .ok_or_else(|| {
801 SignalProtocolError::InvalidState(
802 "get_sender_chain_key_bytes",
803 "No current session".into(),
804 )
805 })?
806 .get_sender_chain_key_bytes()?)
807 }
808
809 pub fn current_ratchet_key_matches(
810 &self,
811 key: &PublicKey,
812 ) -> Result<bool, SignalProtocolError> {
813 match &self.current_session {
814 Some(session) => Ok(&session.sender_ratchet_key()? == key),
815 None => Ok(false),
816 }
817 }
818
819 pub fn get_kyber_ciphertext(&self) -> Result<Option<&Vec<u8>>, SignalProtocolError> {
820 Ok(self
821 .session_state()
822 .ok_or_else(|| {
823 SignalProtocolError::InvalidState(
824 "get_kyber_ciphertext",
825 "No current session".into(),
826 )
827 })?
828 .get_kyber_ciphertext())
829 }
830}