1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::time::{Duration, SystemTime, UNIX_EPOCH};
6use thiserror::Error;
7use tracing::{debug, error, info};
8use uuid::Uuid;
9
10use qudag_crypto::{
11 Ciphertext as KemCiphertext, KeyPair as KemKeyPair, MlDsaKeyPair, MlDsaPublicKey, MlKem768,
12 PublicKey as KemPublicKey, SecretKey, SharedSecret,
13};
14use rand;
15
16use crate::message::{HandshakeType, Message, MessageError, MessageType, ProtocolVersion};
17use crate::state::{ProtocolStateMachine, StateError};
18
19#[derive(Debug, Error)]
21pub enum HandshakeError {
22 #[error("Cryptographic operation failed: {reason}")]
24 CryptoError { reason: String },
25
26 #[error("Invalid handshake message: {reason}")]
28 InvalidMessage { reason: String },
29
30 #[error("Handshake timed out after {timeout:?}")]
32 Timeout { timeout: Duration },
33
34 #[error("Protocol version mismatch: expected {expected:?}, got {actual:?}")]
36 VersionMismatch {
37 expected: ProtocolVersion,
38 actual: ProtocolVersion,
39 },
40
41 #[error("Unsupported capabilities: {capabilities:?}")]
43 UnsupportedCapabilities { capabilities: Vec<String> },
44
45 #[error("Invalid peer credentials")]
47 InvalidCredentials,
48
49 #[error("State machine error: {0}")]
51 StateMachine(#[from] StateError),
52
53 #[error("Message error: {0}")]
55 Message(#[from] MessageError),
56
57 #[error("Handshake already in progress with session {session_id}")]
59 HandshakeInProgress { session_id: Uuid },
60
61 #[error("Replay attack detected: timestamp {timestamp} is too old")]
63 ReplayAttack { timestamp: u64 },
64}
65
66#[derive(Debug, Clone)]
68pub struct HandshakeConfig {
69 pub timeout: Duration,
71 pub supported_versions: Vec<ProtocolVersion>,
73 pub required_capabilities: Vec<String>,
75 pub optional_capabilities: Vec<String>,
77 pub max_timestamp_skew: Duration,
79 pub mutual_auth: bool,
81}
82
83impl Default for HandshakeConfig {
84 fn default() -> Self {
85 Self {
86 timeout: Duration::from_secs(30),
87 supported_versions: vec![ProtocolVersion::CURRENT],
88 required_capabilities: vec![
89 "dag-consensus".to_string(),
90 "quantum-resistant-crypto".to_string(),
91 ],
92 optional_capabilities: vec![
93 "anonymous-routing".to_string(),
94 "dark-addressing".to_string(),
95 ],
96 max_timestamp_skew: Duration::from_secs(300), mutual_auth: true,
98 }
99 }
100}
101
102#[derive(Debug)]
104pub struct HandshakeSession {
105 pub session_id: Uuid,
107 pub peer_id: Option<Vec<u8>>,
109 pub state: HandshakeSessionState,
111 pub negotiated_version: Option<ProtocolVersion>,
113 pub peer_capabilities: Vec<String>,
115 pub our_keys: HandshakeKeys,
117 pub peer_keys: Option<PeerKeys>,
119 pub shared_secrets: Option<SharedSecrets>,
121 pub started_at: SystemTime,
123 pub last_activity: SystemTime,
125 pub nonce: u64,
127}
128
129#[derive(Debug, Clone, PartialEq, Eq)]
131pub enum HandshakeSessionState {
132 Waiting,
134 InitSent,
136 InitReceived,
138 ResponseSent,
140 ResponseReceived,
142 Completed,
144 Failed,
146}
147
148#[derive(Debug)]
150pub struct HandshakeKeys {
151 pub signature_keypair: MlDsaKeyPair,
153 pub kem_keypair: KemKeyPair,
155}
156
157#[derive(Debug, Clone)]
159pub struct PeerKeys {
160 pub signature_public_key: MlDsaPublicKey,
162 pub kem_public_key: KemPublicKey,
164}
165
166#[derive(Debug, Clone)]
168pub struct SharedSecrets {
169 pub kem_shared_secret: SharedSecret,
171 pub encryption_key: Vec<u8>,
173 pub mac_key: Vec<u8>,
175 pub session_key: Vec<u8>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
181pub enum HandshakeMessagePayload {
182 Init {
184 protocol_version: ProtocolVersion,
185 supported_versions: Vec<ProtocolVersion>,
186 capabilities: Vec<String>,
187 signature_public_key: Vec<u8>,
188 kem_public_key: Vec<u8>,
189 nonce: u64,
190 timestamp: u64,
191 },
192 Response {
194 protocol_version: ProtocolVersion,
195 capabilities: Vec<String>,
196 signature_public_key: Vec<u8>,
197 kem_ciphertext: Vec<u8>, nonce: u64,
199 timestamp: u64,
200 },
201 Complete { session_id: Vec<u8>, timestamp: u64 },
203 VersionNegotiation {
205 supported_versions: Vec<ProtocolVersion>,
206 preferred_version: ProtocolVersion,
207 },
208}
209
210pub struct HandshakeCoordinator {
212 config: HandshakeConfig,
214 sessions: HashMap<Uuid, HandshakeSession>,
216 #[allow(dead_code)]
218 identity_keys: HandshakeKeys,
219 state_machine: ProtocolStateMachine,
221}
222
223impl HandshakeCoordinator {
224 pub fn new(
226 config: HandshakeConfig,
227 identity_keys: HandshakeKeys,
228 state_machine: ProtocolStateMachine,
229 ) -> Self {
230 Self {
231 config,
232 sessions: HashMap::new(),
233 identity_keys,
234 state_machine,
235 }
236 }
237
238 pub fn generate_keys() -> Result<HandshakeKeys, HandshakeError> {
240 let signature_keypair = MlDsaKeyPair::generate(&mut rand::thread_rng()).map_err(|e| {
242 HandshakeError::CryptoError {
243 reason: format!("Failed to generate ML-DSA keypair: {:?}", e),
244 }
245 })?;
246
247 let (kem_public_key, kem_secret_key) =
249 MlKem768::keygen().map_err(|e| HandshakeError::CryptoError {
250 reason: format!("Failed to generate ML-KEM keypair: {:?}", e),
251 })?;
252 let kem_keypair = KemKeyPair {
253 public_key: kem_public_key.as_bytes().to_vec(),
254 secret_key: kem_secret_key.as_bytes().to_vec(),
255 };
256
257 Ok(HandshakeKeys {
258 signature_keypair,
259 kem_keypair,
260 })
261 }
262
263 pub fn initiate_handshake(
265 &mut self,
266 peer_id: Option<Vec<u8>>,
267 ) -> Result<(Uuid, Message), HandshakeError> {
268 let session_keys = Self::generate_keys()?;
270 let session_id = Uuid::new_v4();
271 let nonce = rand::random::<u64>();
272
273 let session = HandshakeSession {
275 session_id,
276 peer_id,
277 state: HandshakeSessionState::Waiting,
278 negotiated_version: None,
279 peer_capabilities: Vec::new(),
280 our_keys: session_keys,
281 peer_keys: None,
282 shared_secrets: None,
283 started_at: SystemTime::now(),
284 last_activity: SystemTime::now(),
285 nonce,
286 };
287
288 let payload = HandshakeMessagePayload::Init {
290 protocol_version: ProtocolVersion::CURRENT,
291 supported_versions: self.config.supported_versions.clone(),
292 capabilities: [
293 self.config.required_capabilities.clone(),
294 self.config.optional_capabilities.clone(),
295 ]
296 .concat(),
297 signature_public_key: session.our_keys.signature_keypair.public_key().to_vec(),
298 kem_public_key: session.our_keys.kem_keypair.public_key().to_vec(),
299 nonce,
300 timestamp: SystemTime::now()
301 .duration_since(UNIX_EPOCH)
302 .unwrap()
303 .as_millis() as u64,
304 };
305
306 let payload_bytes =
307 bincode::serialize(&payload).map_err(|e| HandshakeError::InvalidMessage {
308 reason: format!("Failed to serialize handshake init: {:?}", e),
309 })?;
310
311 let mut message = Message::new(MessageType::Handshake(HandshakeType::Init), payload_bytes);
312
313 message.sign(&session.our_keys.signature_keypair)?;
315
316 let mut session = session;
318 session.state = HandshakeSessionState::InitSent;
319 session.last_activity = SystemTime::now();
320
321 self.sessions.insert(session_id, session);
323
324 info!("Initiated handshake session: {}", session_id);
325 Ok((session_id, message))
326 }
327
328 pub fn process_handshake_message(
330 &mut self,
331 message: &Message,
332 session_id: Option<Uuid>,
333 ) -> Result<Option<Message>, HandshakeError> {
334 self.validate_timestamp(message)?;
336
337 match &message.msg_type {
338 MessageType::Handshake(HandshakeType::Init) => self.process_handshake_init(message),
339 MessageType::Handshake(HandshakeType::Response) => {
340 self.process_handshake_response(message, session_id)
341 }
342 MessageType::Handshake(HandshakeType::Complete) => {
343 self.process_handshake_complete(message, session_id)
344 }
345 MessageType::Handshake(HandshakeType::VersionNegotiation) => {
346 self.process_version_negotiation(message, session_id)
347 }
348 _ => Err(HandshakeError::InvalidMessage {
349 reason: "Not a handshake message".to_string(),
350 }),
351 }
352 }
353
354 fn process_handshake_init(
356 &mut self,
357 message: &Message,
358 ) -> Result<Option<Message>, HandshakeError> {
359 let payload: HandshakeMessagePayload =
360 bincode::deserialize(&message.payload).map_err(|e| HandshakeError::InvalidMessage {
361 reason: format!("Failed to deserialize handshake init: {:?}", e),
362 })?;
363
364 if let HandshakeMessagePayload::Init {
365 protocol_version,
366 supported_versions,
367 capabilities,
368 signature_public_key,
369 kem_public_key,
370 nonce,
371 timestamp: _,
372 } = payload
373 {
374 let negotiated_version =
376 self.negotiate_version(&supported_versions, &protocol_version)?;
377
378 self.verify_capabilities(&capabilities)?;
380
381 let peer_signature_key =
383 MlDsaPublicKey::from_bytes(&signature_public_key).map_err(|e| {
384 HandshakeError::CryptoError {
385 reason: format!("Invalid peer signature key: {:?}", e),
386 }
387 })?;
388
389 let peer_kem_key = KemPublicKey::from_bytes(&kem_public_key).map_err(|e| {
390 HandshakeError::CryptoError {
391 reason: format!("Invalid peer KEM key: {:?}", e),
392 }
393 })?;
394
395 if !message.verify(&peer_signature_key)? {
397 return Err(HandshakeError::InvalidCredentials);
398 }
399
400 let session_keys = Self::generate_keys()?;
402 let session_id = Uuid::new_v4();
403 let our_nonce = rand::random::<u64>();
404
405 let (kem_ciphertext, shared_secret) =
407 MlKem768::encapsulate(&peer_kem_key).map_err(|e| HandshakeError::CryptoError {
408 reason: format!("KEM encapsulation failed: {:?}", e),
409 })?;
410
411 let shared_secrets = self.derive_session_keys(&shared_secret, nonce, our_nonce)?;
413
414 let session = HandshakeSession {
416 session_id,
417 peer_id: None, state: HandshakeSessionState::InitReceived,
419 negotiated_version: Some(negotiated_version.clone()),
420 peer_capabilities: capabilities,
421 our_keys: session_keys,
422 peer_keys: Some(PeerKeys {
423 signature_public_key: peer_signature_key,
424 kem_public_key: peer_kem_key,
425 }),
426 shared_secrets: Some(shared_secrets),
427 started_at: SystemTime::now(),
428 last_activity: SystemTime::now(),
429 nonce: our_nonce,
430 };
431
432 let response_payload = HandshakeMessagePayload::Response {
434 protocol_version: negotiated_version,
435 capabilities: [
436 self.config.required_capabilities.clone(),
437 self.config.optional_capabilities.clone(),
438 ]
439 .concat(),
440 signature_public_key: session.our_keys.signature_keypair.public_key().to_vec(),
441 kem_ciphertext: kem_ciphertext.as_bytes().to_vec(),
442 nonce: our_nonce,
443 timestamp: SystemTime::now()
444 .duration_since(UNIX_EPOCH)
445 .unwrap()
446 .as_millis() as u64,
447 };
448
449 let response_bytes = bincode::serialize(&response_payload).map_err(|e| {
450 HandshakeError::InvalidMessage {
451 reason: format!("Failed to serialize handshake response: {:?}", e),
452 }
453 })?;
454
455 let mut response_message = Message::new(
456 MessageType::Handshake(HandshakeType::Response),
457 response_bytes,
458 );
459
460 response_message.sign(&session.our_keys.signature_keypair)?;
462
463 let mut session = session;
465 session.state = HandshakeSessionState::ResponseSent;
466 session.last_activity = SystemTime::now();
467
468 self.sessions.insert(session_id, session);
470
471 self.state_machine
473 .process_message(message, Some(session_id))?;
474
475 info!(
476 "Processed handshake init, sending response for session: {}",
477 session_id
478 );
479 Ok(Some(response_message))
480 } else {
481 Err(HandshakeError::InvalidMessage {
482 reason: "Expected handshake init payload".to_string(),
483 })
484 }
485 }
486
487 fn process_handshake_response(
489 &mut self,
490 message: &Message,
491 session_id: Option<Uuid>,
492 ) -> Result<Option<Message>, HandshakeError> {
493 let session_id = session_id.ok_or(HandshakeError::InvalidMessage {
494 reason: "Session ID required for handshake response".to_string(),
495 })?;
496
497 let session = self
498 .sessions
499 .get_mut(&session_id)
500 .ok_or(HandshakeError::InvalidMessage {
501 reason: format!("Session not found: {}", session_id),
502 })?;
503
504 if session.state != HandshakeSessionState::InitSent {
505 return Err(HandshakeError::InvalidMessage {
506 reason: format!("Invalid session state for response: {:?}", session.state),
507 });
508 }
509
510 let payload: HandshakeMessagePayload =
511 bincode::deserialize(&message.payload).map_err(|e| HandshakeError::InvalidMessage {
512 reason: format!("Failed to deserialize handshake response: {:?}", e),
513 })?;
514
515 if let HandshakeMessagePayload::Response {
516 protocol_version,
517 capabilities,
518 signature_public_key,
519 kem_ciphertext,
520 nonce,
521 timestamp: _,
522 } = payload
523 {
524 let peer_signature_key =
526 MlDsaPublicKey::from_bytes(&signature_public_key).map_err(|e| {
527 HandshakeError::CryptoError {
528 reason: format!("Invalid peer signature key: {:?}", e),
529 }
530 })?;
531
532 if !message.verify(&peer_signature_key)? {
534 return Err(HandshakeError::InvalidCredentials);
535 }
536
537 if !self.config.supported_versions.contains(&protocol_version) {
539 return Err(HandshakeError::VersionMismatch {
540 expected: ProtocolVersion::CURRENT,
541 actual: protocol_version,
542 });
543 }
544
545 {
547 for required_cap in &self.config.required_capabilities {
549 if !capabilities.contains(required_cap) {
550 return Err(HandshakeError::UnsupportedCapabilities {
551 capabilities: vec![required_cap.clone()],
552 });
553 }
554 }
555 }
556
557 let kem_ciphertext_bytes = KemCiphertext::from_bytes(&kem_ciphertext).map_err(|e| {
559 HandshakeError::CryptoError {
560 reason: format!("Invalid KEM ciphertext: {:?}", e),
561 }
562 })?;
563
564 let secret_key = SecretKey::from_bytes(session.our_keys.kem_keypair.secret_key())
565 .map_err(|e| HandshakeError::CryptoError {
566 reason: format!("Invalid secret key: {:?}", e),
567 })?;
568
569 let shared_secret =
570 MlKem768::decapsulate(&secret_key, &kem_ciphertext_bytes).map_err(|e| {
571 HandshakeError::CryptoError {
572 reason: format!("KEM decapsulation failed: {:?}", e),
573 }
574 })?;
575
576 let session_nonce = session.nonce;
578 let shared_secrets = {
579 let secret_bytes = shared_secret.as_bytes();
580
581 let combined_nonce = session_nonce ^ nonce;
583 let nonce_bytes = combined_nonce.to_be_bytes();
584
585 let mut key_material = Vec::new();
587 key_material.extend_from_slice(secret_bytes);
588 key_material.extend_from_slice(&nonce_bytes);
589
590 let encryption_key = blake3::keyed_hash(
592 blake3::hash(b"QuDAG-Encryption-Key").as_bytes(),
593 &key_material,
594 )
595 .as_bytes()
596 .to_vec();
597
598 let mac_key =
599 blake3::keyed_hash(blake3::hash(b"QuDAG-MAC-Key").as_bytes(), &key_material)
600 .as_bytes()
601 .to_vec();
602
603 let session_key = blake3::keyed_hash(
604 blake3::hash(b"QuDAG-Session-Key").as_bytes(),
605 &key_material,
606 )
607 .as_bytes()
608 .to_vec();
609
610 SharedSecrets {
611 kem_shared_secret: shared_secret.clone(),
612 encryption_key,
613 mac_key,
614 session_key,
615 }
616 };
617
618 session.negotiated_version = Some(protocol_version);
620 session.peer_capabilities = capabilities;
621 session.peer_keys = Some(PeerKeys {
622 signature_public_key: peer_signature_key,
623 kem_public_key: KemPublicKey::from_bytes(session.our_keys.kem_keypair.public_key())
624 .map_err(|e| HandshakeError::CryptoError {
625 reason: format!("Invalid public key: {:?}", e),
626 })?, });
628 session.shared_secrets = Some(shared_secrets);
629 session.state = HandshakeSessionState::ResponseReceived;
630 session.last_activity = SystemTime::now();
631
632 let complete_payload = HandshakeMessagePayload::Complete {
634 session_id: session_id.as_bytes().to_vec(),
635 timestamp: SystemTime::now()
636 .duration_since(UNIX_EPOCH)
637 .unwrap()
638 .as_millis() as u64,
639 };
640
641 let complete_bytes = bincode::serialize(&complete_payload).map_err(|e| {
642 HandshakeError::InvalidMessage {
643 reason: format!("Failed to serialize handshake complete: {:?}", e),
644 }
645 })?;
646
647 let mut complete_message = Message::new(
648 MessageType::Handshake(HandshakeType::Complete),
649 complete_bytes,
650 );
651
652 complete_message.sign(&session.our_keys.signature_keypair)?;
654
655 session.state = HandshakeSessionState::Completed;
657
658 self.state_machine
660 .process_message(message, Some(session_id))?;
661
662 info!(
663 "Processed handshake response, sending completion for session: {}",
664 session_id
665 );
666 Ok(Some(complete_message))
667 } else {
668 Err(HandshakeError::InvalidMessage {
669 reason: "Expected handshake response payload".to_string(),
670 })
671 }
672 }
673
674 fn process_handshake_complete(
676 &mut self,
677 message: &Message,
678 session_id: Option<Uuid>,
679 ) -> Result<Option<Message>, HandshakeError> {
680 let session_id = session_id.ok_or(HandshakeError::InvalidMessage {
681 reason: "Session ID required for handshake complete".to_string(),
682 })?;
683
684 let session = self
685 .sessions
686 .get_mut(&session_id)
687 .ok_or(HandshakeError::InvalidMessage {
688 reason: format!("Session not found: {}", session_id),
689 })?;
690
691 if session.state != HandshakeSessionState::ResponseSent {
692 return Err(HandshakeError::InvalidMessage {
693 reason: format!("Invalid session state for complete: {:?}", session.state),
694 });
695 }
696
697 if let Some(peer_keys) = &session.peer_keys {
699 if !message.verify(&peer_keys.signature_public_key)? {
700 return Err(HandshakeError::InvalidCredentials);
701 }
702 }
703
704 session.state = HandshakeSessionState::Completed;
706 session.last_activity = SystemTime::now();
707
708 self.state_machine
710 .process_message(message, Some(session_id))?;
711
712 info!(
713 "Handshake completed successfully for session: {}",
714 session_id
715 );
716 Ok(None) }
718
719 fn process_version_negotiation(
721 &mut self,
722 message: &Message,
723 _session_id: Option<Uuid>,
724 ) -> Result<Option<Message>, HandshakeError> {
725 let payload: HandshakeMessagePayload =
726 bincode::deserialize(&message.payload).map_err(|e| HandshakeError::InvalidMessage {
727 reason: format!("Failed to deserialize version negotiation: {:?}", e),
728 })?;
729
730 if let HandshakeMessagePayload::VersionNegotiation {
731 supported_versions,
732 preferred_version,
733 } = payload
734 {
735 let compatible_version =
737 self.negotiate_version(&supported_versions, &preferred_version)?;
738
739 debug!("Negotiated protocol version: {:?}", compatible_version);
741
742 Ok(None)
744 } else {
745 Err(HandshakeError::InvalidMessage {
746 reason: "Expected version negotiation payload".to_string(),
747 })
748 }
749 }
750
751 fn negotiate_version(
753 &self,
754 peer_versions: &[ProtocolVersion],
755 peer_preferred: &ProtocolVersion,
756 ) -> Result<ProtocolVersion, HandshakeError> {
757 if self.config.supported_versions.contains(peer_preferred) {
759 return Ok(peer_preferred.clone());
760 }
761
762 for our_version in &self.config.supported_versions {
764 for peer_version in peer_versions {
765 if our_version.is_compatible(peer_version) {
766 return Ok(our_version.clone());
767 }
768 }
769 }
770
771 Err(HandshakeError::VersionMismatch {
772 expected: ProtocolVersion::CURRENT,
773 actual: peer_preferred.clone(),
774 })
775 }
776
777 fn verify_capabilities(&self, peer_capabilities: &[String]) -> Result<(), HandshakeError> {
779 for required_cap in &self.config.required_capabilities {
780 if !peer_capabilities.contains(required_cap) {
781 return Err(HandshakeError::UnsupportedCapabilities {
782 capabilities: vec![required_cap.clone()],
783 });
784 }
785 }
786 Ok(())
787 }
788
789 fn derive_session_keys(
791 &self,
792 shared_secret: &SharedSecret,
793 our_nonce: u64,
794 peer_nonce: u64,
795 ) -> Result<SharedSecrets, HandshakeError> {
796 let secret_bytes = shared_secret.as_bytes();
797
798 let combined_nonce = our_nonce ^ peer_nonce;
800 let nonce_bytes = combined_nonce.to_be_bytes();
801
802 let mut key_material = Vec::new();
804 key_material.extend_from_slice(secret_bytes);
805 key_material.extend_from_slice(&nonce_bytes);
806
807 let encryption_key = blake3::keyed_hash(
809 blake3::hash(b"QuDAG-Encryption-Key").as_bytes(),
810 &key_material,
811 )
812 .as_bytes()
813 .to_vec();
814
815 let mac_key = blake3::keyed_hash(blake3::hash(b"QuDAG-MAC-Key").as_bytes(), &key_material)
816 .as_bytes()
817 .to_vec();
818
819 let session_key =
820 blake3::keyed_hash(blake3::hash(b"QuDAG-Session-Key").as_bytes(), &key_material)
821 .as_bytes()
822 .to_vec();
823
824 Ok(SharedSecrets {
825 kem_shared_secret: shared_secret.clone(),
826 encryption_key,
827 mac_key,
828 session_key,
829 })
830 }
831
832 fn validate_timestamp(&self, message: &Message) -> Result<(), HandshakeError> {
834 let now = SystemTime::now()
835 .duration_since(UNIX_EPOCH)
836 .unwrap()
837 .as_millis() as u64;
838
839 let message_time = message.timestamp;
840 let max_skew = self.config.max_timestamp_skew.as_millis() as u64;
841
842 if now > message_time + max_skew || message_time > now + max_skew {
843 return Err(HandshakeError::ReplayAttack {
844 timestamp: message_time,
845 });
846 }
847
848 Ok(())
849 }
850
851 pub fn get_session(&self, session_id: &Uuid) -> Option<&HandshakeSession> {
853 self.sessions.get(session_id)
854 }
855
856 pub fn cleanup_sessions(&mut self) {
858 let now = SystemTime::now();
859 let timeout = self.config.timeout;
860
861 self.sessions.retain(|_, session| {
862 let elapsed = now
863 .duration_since(session.started_at)
864 .unwrap_or(Duration::ZERO);
865
866 match session.state {
867 HandshakeSessionState::Completed | HandshakeSessionState::Failed => false,
868 _ => elapsed < timeout,
869 }
870 });
871 }
872
873 pub fn get_active_sessions(&self) -> Vec<&HandshakeSession> {
875 self.sessions
876 .values()
877 .filter(|s| {
878 !matches!(
879 s.state,
880 HandshakeSessionState::Completed | HandshakeSessionState::Failed
881 )
882 })
883 .collect()
884 }
885
886 pub fn is_handshake_completed(&self, session_id: &Uuid) -> bool {
888 self.sessions
889 .get(session_id)
890 .map(|s| s.state == HandshakeSessionState::Completed)
891 .unwrap_or(false)
892 }
893
894 pub fn get_shared_secrets(&self, session_id: &Uuid) -> Option<&SharedSecrets> {
896 self.sessions
897 .get(session_id)
898 .and_then(|s| s.shared_secrets.as_ref())
899 }
900}