handshake.rs
1 //! Handshake state machine for Dead Drop protocol. 2 //! 3 //! This module provides a high-level wrapper around the Noise XX handshake, 4 //! adding application-specific functionality like contact verification and 5 //! state tracking for the BLE communication flow. 6 //! 7 //! # Overview 8 //! 9 //! The handshake establishes a secure channel between two devices: 10 //! 11 //! 1. **Discovery**: Devices detect each other via BLE rotating IDs 12 //! 2. **Connection**: BLE GATT connection is established 13 //! 3. **Handshake**: Noise XX handshake authenticates both parties 14 //! 4. **Verification**: Remote identity is verified against contacts 15 //! 5. **Exchange**: Secure channel is used for message exchange 16 //! 17 //! # Handshake Flow 18 //! 19 //! ```text 20 //! Initiator Responder 21 //! | | 22 //! |──────────── Message 1 ──────────────>| (ephemeral key) 23 //! | | 24 //! |<─────────── Message 2 ───────────────| (ephemeral + static, encrypted) 25 //! | | 26 //! |──────────── Message 3 ──────────────>| (static, encrypted) 27 //! | | 28 //! | [Handshake Complete] | 29 //! | [Secure Channel Established] | 30 //! | | 31 //! ``` 32 //! 33 //! # States 34 //! 35 //! | State | Description | Next Action | 36 //! |-------|-------------|-------------| 37 //! | `AwaitingOutgoing` | Need to send a message | Call `generate()` | 38 //! | `AwaitingSend` | Have message to send | Send via BLE | 39 //! | `AwaitingIncoming` | Waiting for peer message | Wait for BLE data | 40 //! | `Complete` | Handshake finished | Call `finalize()` | 41 //! | `Failed` | Handshake failed | Handle error | 42 //! 43 //! # Example 44 //! 45 //! ``` 46 //! use dead_drop_core::crypto::keys::ExchangeKeyPair; 47 //! use dead_drop_core::protocol::handshake::Handshake; 48 //! 49 //! let my_keys = ExchangeKeyPair::generate(); 50 //! 51 //! // As initiator 52 //! let mut handshake = Handshake::new_initiator(&my_keys).unwrap(); 53 //! 54 //! // Generate first message 55 //! let msg1 = handshake.generate().unwrap(); 56 //! // ... send msg1 over BLE ... 57 //! 58 //! // After receiving response 59 //! // let response = handshake.receive(&msg2_from_peer).unwrap(); 60 //! ``` 61 62 use crate::crypto::keys::ExchangeKeyPair; 63 use crate::crypto::noise::{HandshakeStatus, NoiseHandshake, NoiseTransport, Role}; 64 use crate::error::{DeadDropError, Result}; 65 66 // ============================================================================= 67 // HANDSHAKE STATE 68 // ============================================================================= 69 70 /// State of the handshake protocol. 71 /// 72 /// Tracks the current state of the handshake for the application layer. 73 /// This provides a more granular view than the underlying Noise states. 74 #[derive(Debug, Clone, PartialEq, Eq)] 75 pub enum HandshakeState { 76 /// Initial state, not yet started. 77 Initial, 78 79 /// Initiator: Sent message 1, waiting for message 2. 80 /// Pattern: → e 81 SentEphemeral, 82 83 /// Responder: Received message 1, ready to send message 2. 84 /// Pattern: received e, ready to send e,ee,s,es 85 ReceivedEphemeral, 86 87 /// Responder: Sent message 2, waiting for message 3. 88 /// Pattern: ← e, ee, s, es 89 SentEphemeralAndStatic, 90 91 /// Initiator: Received message 2, ready to send message 3. 92 /// Pattern: received e,ee,s,es, ready to send s,se 93 ReceivedEphemeralAndStatic, 94 95 /// Initiator: Sent message 3, handshake complete. 96 /// Pattern: → s, se 97 SentStatic, 98 99 /// Responder: Received message 3, handshake complete. 100 ReceivedStatic, 101 102 /// Handshake completed successfully. 103 Complete, 104 105 /// Handshake failed. 106 Failed(String), 107 } 108 109 impl HandshakeState { 110 /// Check if the handshake is complete. 111 pub fn is_complete(&self) -> bool { 112 matches!(self, HandshakeState::Complete) 113 } 114 115 /// Check if the handshake has failed. 116 pub fn is_failed(&self) -> bool { 117 matches!(self, HandshakeState::Failed(_)) 118 } 119 120 /// Check if we need to send a message. 121 pub fn needs_to_send(&self) -> bool { 122 matches!( 123 self, 124 HandshakeState::Initial 125 | HandshakeState::ReceivedEphemeral 126 | HandshakeState::ReceivedEphemeralAndStatic 127 ) 128 } 129 130 /// Check if we are waiting to receive a message. 131 pub fn needs_to_receive(&self) -> bool { 132 matches!( 133 self, 134 HandshakeState::SentEphemeral | HandshakeState::SentEphemeralAndStatic 135 ) 136 } 137 } 138 139 // ============================================================================= 140 // HANDSHAKE RESULT 141 // ============================================================================= 142 143 /// Result of processing a handshake operation. 144 /// 145 /// Contains the outcome of a `receive()` or `generate()` call, 146 /// including any data to send and the new state. 147 #[derive(Debug)] 148 pub struct HandshakeResult { 149 /// Data to send to the peer (if any). 150 pub data_to_send: Option<Vec<u8>>, 151 /// Whether the handshake is now complete. 152 pub is_complete: bool, 153 /// The remote peer's static public key (if known). 154 pub remote_static: Option<[u8; 32]>, 155 } 156 157 // ============================================================================= 158 // HANDSHAKE 159 // ============================================================================= 160 161 /// High-level handshake handler for Dead Drop protocol. 162 /// 163 /// Wraps the Noise XX handshake with application-specific state tracking 164 /// and contact verification support. 165 /// 166 /// # Lifecycle 167 /// 168 /// 1. Create with `new_initiator()` or `new_responder()` 169 /// 2. Call `generate()` when `state().needs_to_send()` 170 /// 3. Call `receive()` when data arrives from peer 171 /// 4. Repeat until `state().is_complete()` 172 /// 5. Call `finalize()` to get the secure transport 173 /// 174 /// # Thread Safety 175 /// 176 /// This type is `Send` but not `Sync`. For concurrent access, 177 /// wrap in `Arc<Mutex<Handshake>>`. 178 pub struct Handshake { 179 /// The underlying Noise handshake. 180 noise: NoiseHandshake, 181 /// Application-level state tracking. 182 state: HandshakeState, 183 /// The role in the handshake. 184 role: Role, 185 /// Remote peer's static key (once known). 186 remote_static: Option<[u8; 32]>, 187 /// Count of messages sent. 188 messages_sent: u8, 189 /// Count of messages received. 190 messages_received: u8, 191 } 192 193 impl Handshake { 194 /// Create a new handshake as the initiator. 195 /// 196 /// The initiator is the device that detected the other device's 197 /// rotating ID and is initiating the connection. 198 /// 199 /// # Arguments 200 /// 201 /// * `local_exchange` - Our exchange key pair for the handshake 202 /// 203 /// # Example 204 /// 205 /// ``` 206 /// use dead_drop_core::crypto::keys::ExchangeKeyPair; 207 /// use dead_drop_core::protocol::handshake::Handshake; 208 /// 209 /// let keys = ExchangeKeyPair::generate(); 210 /// let handshake = Handshake::new_initiator(&keys).unwrap(); 211 /// 212 /// assert!(handshake.state().needs_to_send()); 213 /// ``` 214 pub fn new_initiator(local_exchange: &ExchangeKeyPair) -> Result<Self> { 215 let noise = NoiseHandshake::new_initiator(local_exchange)?; 216 217 Ok(Self { 218 noise, 219 state: HandshakeState::Initial, 220 role: Role::Initiator, 221 remote_static: None, 222 messages_sent: 0, 223 messages_received: 0, 224 }) 225 } 226 227 /// Create a new handshake as the responder. 228 /// 229 /// The responder is the device that was discovered and is responding 230 /// to an incoming connection. 231 /// 232 /// # Arguments 233 /// 234 /// * `local_exchange` - Our exchange key pair for the handshake 235 /// 236 /// # Example 237 /// 238 /// ``` 239 /// use dead_drop_core::crypto::keys::ExchangeKeyPair; 240 /// use dead_drop_core::protocol::handshake::Handshake; 241 /// 242 /// let keys = ExchangeKeyPair::generate(); 243 /// let handshake = Handshake::new_responder(&keys).unwrap(); 244 /// 245 /// assert!(handshake.state().needs_to_receive()); 246 /// ``` 247 pub fn new_responder(local_exchange: &ExchangeKeyPair) -> Result<Self> { 248 let noise = NoiseHandshake::new_responder(local_exchange)?; 249 250 Ok(Self { 251 noise, 252 state: HandshakeState::SentEphemeral, // Waiting for first message 253 role: Role::Responder, 254 remote_static: None, 255 messages_sent: 0, 256 messages_received: 0, 257 }) 258 } 259 260 /// Get the current handshake state. 261 pub fn state(&self) -> &HandshakeState { 262 &self.state 263 } 264 265 /// Get the handshake role. 266 pub fn role(&self) -> Role { 267 self.role 268 } 269 270 /// Check if the handshake is complete. 271 pub fn is_complete(&self) -> bool { 272 self.state.is_complete() 273 } 274 275 /// Check if the handshake has failed. 276 pub fn is_failed(&self) -> bool { 277 self.state.is_failed() 278 } 279 280 /// Get the remote peer's static public key. 281 /// 282 /// Only available after the peer has sent their static key 283 /// (message 2 for initiator, message 3 for responder). 284 pub fn remote_static(&self) -> Option<&[u8; 32]> { 285 self.remote_static.as_ref() 286 } 287 288 /// Get the number of messages sent. 289 pub fn messages_sent(&self) -> u8 { 290 self.messages_sent 291 } 292 293 /// Get the number of messages received. 294 pub fn messages_received(&self) -> u8 { 295 self.messages_received 296 } 297 298 /// Generate the next outgoing handshake message. 299 /// 300 /// Call this when `state().needs_to_send()` returns true. 301 /// 302 /// # Returns 303 /// 304 /// The handshake message to send to the peer. 305 /// 306 /// # Errors 307 /// 308 /// - `InvalidHandshakeState` if not in a sending state 309 /// - `Handshake` if message generation fails 310 /// 311 /// # Example 312 /// 313 /// ``` 314 /// use dead_drop_core::crypto::keys::ExchangeKeyPair; 315 /// use dead_drop_core::protocol::handshake::Handshake; 316 /// 317 /// let keys = ExchangeKeyPair::generate(); 318 /// let mut handshake = Handshake::new_initiator(&keys).unwrap(); 319 /// 320 /// let msg = handshake.generate().unwrap(); 321 /// assert!(!msg.is_empty()); 322 /// ``` 323 pub fn generate(&mut self) -> Result<Vec<u8>> { 324 if !self.state.needs_to_send() && self.state != HandshakeState::Initial { 325 // Special case: responder starts in "waiting" state 326 if self.role == Role::Responder && self.noise.status() == HandshakeStatus::NeedToReceive 327 { 328 return Err(DeadDropError::InvalidHandshakeState( 329 "Responder must receive first message before generating".to_string(), 330 )); 331 } 332 } 333 334 // Generate the message 335 let message = self.noise.write_message().map_err(|e| { 336 self.state = HandshakeState::Failed(e.to_string()); 337 e 338 })?; 339 340 self.messages_sent += 1; 341 342 // Update state based on role and message count 343 self.update_state_after_send(); 344 345 // Check for remote static key 346 if let Some(rs) = self.noise.remote_static() { 347 self.remote_static = Some(*rs); 348 } 349 350 Ok(message) 351 } 352 353 /// Process an incoming handshake message from the peer. 354 /// 355 /// Call this when handshake data is received over BLE. 356 /// 357 /// # Arguments 358 /// 359 /// * `data` - The handshake message from the peer 360 /// 361 /// # Returns 362 /// 363 /// A `HandshakeResult` indicating what to do next. 364 /// 365 /// # Errors 366 /// 367 /// - `InvalidHandshakeState` if not expecting incoming data 368 /// - `Handshake` if message processing fails 369 /// 370 /// # Example 371 /// 372 /// ``` 373 /// use dead_drop_core::crypto::keys::ExchangeKeyPair; 374 /// use dead_drop_core::protocol::handshake::Handshake; 375 /// 376 /// let alice_keys = ExchangeKeyPair::generate(); 377 /// let bob_keys = ExchangeKeyPair::generate(); 378 /// 379 /// let mut alice = Handshake::new_initiator(&alice_keys).unwrap(); 380 /// let mut bob = Handshake::new_responder(&bob_keys).unwrap(); 381 /// 382 /// // Alice sends first message 383 /// let msg1 = alice.generate().unwrap(); 384 /// 385 /// // Bob receives and processes 386 /// let result = bob.receive(&msg1).unwrap(); 387 /// assert!(result.data_to_send.is_none()); // Bob needs to call generate() 388 /// ``` 389 pub fn receive(&mut self, data: &[u8]) -> Result<HandshakeResult> { 390 // For responder, the first receive is valid even in "initial" equivalent state 391 let is_responder_first = self.role == Role::Responder && self.messages_received == 0; 392 393 if !self.state.needs_to_receive() && !is_responder_first && !self.state.needs_to_send() { 394 // Special case for responder waiting state 395 if !(self.role == Role::Responder 396 && self.noise.status() == HandshakeStatus::NeedToReceive) 397 { 398 return Err(DeadDropError::InvalidHandshakeState(format!( 399 "Cannot receive in state {:?}", 400 self.state 401 ))); 402 } 403 } 404 405 // Process the message 406 let _payload = self.noise.read_message(data).map_err(|e| { 407 self.state = HandshakeState::Failed(e.to_string()); 408 e 409 })?; 410 411 self.messages_received += 1; 412 413 // Check for remote static key 414 if let Some(rs) = self.noise.remote_static() { 415 self.remote_static = Some(*rs); 416 } 417 418 // Update state based on role and message count 419 self.update_state_after_receive(); 420 421 Ok(HandshakeResult { 422 data_to_send: None, // Caller should call generate() if needed 423 is_complete: self.is_complete(), 424 remote_static: self.remote_static, 425 }) 426 } 427 428 /// Update state after sending a message. 429 fn update_state_after_send(&mut self) { 430 match self.role { 431 Role::Initiator => { 432 match self.messages_sent { 433 1 => self.state = HandshakeState::SentEphemeral, 434 2 => { 435 self.state = HandshakeState::SentStatic; 436 if self.noise.is_complete() { 437 self.state = HandshakeState::Complete; 438 } 439 } 440 _ => {} 441 } 442 } 443 Role::Responder => { 444 if self.messages_sent == 1 { 445 self.state = HandshakeState::SentEphemeralAndStatic; 446 } 447 } 448 } 449 450 // Check if noise thinks we're complete 451 if self.noise.is_complete() { 452 self.state = HandshakeState::Complete; 453 } 454 } 455 456 /// Update state after receiving a message. 457 fn update_state_after_receive(&mut self) { 458 match self.role { 459 Role::Initiator => { 460 if self.messages_received == 1 { 461 self.state = HandshakeState::ReceivedEphemeralAndStatic; 462 } 463 } 464 Role::Responder => { 465 match self.messages_received { 466 1 => self.state = HandshakeState::ReceivedEphemeral, 467 2 => { 468 self.state = HandshakeState::ReceivedStatic; 469 if self.noise.is_complete() { 470 self.state = HandshakeState::Complete; 471 } 472 } 473 _ => {} 474 } 475 } 476 } 477 478 // Check if noise thinks we're complete 479 if self.noise.is_complete() { 480 self.state = HandshakeState::Complete; 481 } 482 } 483 484 /// Finalize the handshake and get the secure transport. 485 /// 486 /// Consumes the handshake and returns a `NoiseTransport` for 487 /// encrypted communication. 488 /// 489 /// # Errors 490 /// 491 /// - `InvalidHandshakeState` if the handshake is not complete 492 /// 493 /// # Example 494 /// 495 /// ``` 496 /// use dead_drop_core::crypto::keys::ExchangeKeyPair; 497 /// use dead_drop_core::crypto::noise::perform_handshake; 498 /// 499 /// let alice = ExchangeKeyPair::generate(); 500 /// let bob = ExchangeKeyPair::generate(); 501 /// 502 /// // Use the helper for complete handshake 503 /// let (alice_transport, bob_transport) = perform_handshake(&alice, &bob).unwrap(); 504 /// 505 /// // Now both can send encrypted messages 506 /// ``` 507 pub fn finalize(self) -> Result<NoiseTransport> { 508 if !self.is_complete() { 509 return Err(DeadDropError::InvalidHandshakeState(format!( 510 "Cannot finalize in state {:?}", 511 self.state 512 ))); 513 } 514 515 self.noise.into_transport() 516 } 517 518 /// Verify that the remote peer is a known contact. 519 /// 520 /// Call this after receiving the peer's static key to verify they 521 /// are in your contact list. 522 /// 523 /// # Arguments 524 /// 525 /// * `known_contacts` - List of known contact exchange public keys 526 /// 527 /// # Returns 528 /// 529 /// `true` if the remote static key matches one of the known contacts. 530 /// 531 /// # Example 532 /// 533 /// ``` 534 /// use dead_drop_core::crypto::keys::ExchangeKeyPair; 535 /// use dead_drop_core::protocol::handshake::Handshake; 536 /// 537 /// let my_keys = ExchangeKeyPair::generate(); 538 /// let contact_keys = ExchangeKeyPair::generate(); 539 /// 540 /// // After handshake completes... 541 /// // let is_known = handshake.verify_contact(&[contact_keys.public_bytes()]); 542 /// ``` 543 pub fn verify_contact(&self, known_contacts: &[[u8; 32]]) -> bool { 544 match &self.remote_static { 545 Some(remote) => known_contacts.iter().any(|contact| contact == remote), 546 None => false, 547 } 548 } 549 } 550 551 impl std::fmt::Debug for Handshake { 552 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 553 f.debug_struct("Handshake") 554 .field("state", &self.state) 555 .field("role", &self.role) 556 .field("messages_sent", &self.messages_sent) 557 .field("messages_received", &self.messages_received) 558 .field("remote_static", &self.remote_static.map(|k| hex::encode(&k[..8]))) 559 .finish() 560 } 561 } 562 563 // ============================================================================= 564 // CONVENIENCE FUNCTIONS 565 // ============================================================================= 566 567 /// Perform a complete handshake between two parties. 568 /// 569 /// This is a convenience function for testing. In production, handshake 570 /// messages are exchanged over BLE. 571 /// 572 /// # Arguments 573 /// 574 /// * `initiator_keys` - Initiator's exchange key pair 575 /// * `responder_keys` - Responder's exchange key pair 576 /// 577 /// # Returns 578 /// 579 /// A tuple of (initiator_transport, responder_transport). 580 pub fn perform_handshake( 581 initiator_keys: &ExchangeKeyPair, 582 responder_keys: &ExchangeKeyPair, 583 ) -> Result<(NoiseTransport, NoiseTransport)> { 584 let mut initiator = Handshake::new_initiator(initiator_keys)?; 585 let mut responder = Handshake::new_responder(responder_keys)?; 586 587 // Message 1: Initiator → Responder 588 let msg1 = initiator.generate()?; 589 responder.receive(&msg1)?; 590 591 // Message 2: Responder → Initiator 592 let msg2 = responder.generate()?; 593 initiator.receive(&msg2)?; 594 595 // Message 3: Initiator → Responder 596 let msg3 = initiator.generate()?; 597 responder.receive(&msg3)?; 598 599 // Both should be complete 600 assert!(initiator.is_complete(), "Initiator not complete"); 601 assert!(responder.is_complete(), "Responder not complete"); 602 603 // Finalize into transports 604 let initiator_transport = initiator.finalize()?; 605 let responder_transport = responder.finalize()?; 606 607 Ok((initiator_transport, responder_transport)) 608 } 609 610 #[cfg(test)] 611 mod tests { 612 use super::*; 613 614 // ==================== Creation Tests ==================== 615 616 #[test] 617 fn test_create_initiator() { 618 let keys = ExchangeKeyPair::generate(); 619 let handshake = Handshake::new_initiator(&keys).unwrap(); 620 621 assert_eq!(handshake.role(), Role::Initiator); 622 assert!(handshake.state().needs_to_send() || *handshake.state() == HandshakeState::Initial); 623 assert!(!handshake.is_complete()); 624 assert!(!handshake.is_failed()); 625 assert_eq!(handshake.messages_sent(), 0); 626 assert_eq!(handshake.messages_received(), 0); 627 } 628 629 #[test] 630 fn test_create_responder() { 631 let keys = ExchangeKeyPair::generate(); 632 let handshake = Handshake::new_responder(&keys).unwrap(); 633 634 assert_eq!(handshake.role(), Role::Responder); 635 // Responder waits for first message 636 assert!(!handshake.is_complete()); 637 assert!(!handshake.is_failed()); 638 } 639 640 // ==================== Complete Handshake Tests ==================== 641 642 #[test] 643 fn test_complete_handshake_flow() { 644 let alice_keys = ExchangeKeyPair::generate(); 645 let bob_keys = ExchangeKeyPair::generate(); 646 647 let mut alice = Handshake::new_initiator(&alice_keys).unwrap(); 648 let mut bob = Handshake::new_responder(&bob_keys).unwrap(); 649 650 // Message 1: Alice → Bob (ephemeral) 651 let msg1 = alice.generate().unwrap(); 652 assert_eq!(alice.messages_sent(), 1); 653 assert_eq!(*alice.state(), HandshakeState::SentEphemeral); 654 655 bob.receive(&msg1).unwrap(); 656 assert_eq!(bob.messages_received(), 1); 657 assert_eq!(*bob.state(), HandshakeState::ReceivedEphemeral); 658 659 // Message 2: Bob → Alice (ephemeral + static) 660 let msg2 = bob.generate().unwrap(); 661 assert_eq!(bob.messages_sent(), 1); 662 assert_eq!(*bob.state(), HandshakeState::SentEphemeralAndStatic); 663 664 alice.receive(&msg2).unwrap(); 665 assert_eq!(alice.messages_received(), 1); 666 assert_eq!(*alice.state(), HandshakeState::ReceivedEphemeralAndStatic); 667 668 // Alice should now have Bob's static key 669 assert!(alice.remote_static().is_some()); 670 assert_eq!(alice.remote_static().unwrap(), &bob_keys.public_bytes()); 671 672 // Message 3: Alice → Bob (static) 673 let msg3 = alice.generate().unwrap(); 674 assert_eq!(alice.messages_sent(), 2); 675 assert!(alice.is_complete()); 676 677 bob.receive(&msg3).unwrap(); 678 assert_eq!(bob.messages_received(), 2); 679 assert!(bob.is_complete()); 680 681 // Bob should now have Alice's static key 682 assert!(bob.remote_static().is_some()); 683 assert_eq!(bob.remote_static().unwrap(), &alice_keys.public_bytes()); 684 } 685 686 #[test] 687 fn test_perform_handshake_helper() { 688 let alice = ExchangeKeyPair::generate(); 689 let bob = ExchangeKeyPair::generate(); 690 691 let result = perform_handshake(&alice, &bob); 692 assert!(result.is_ok()); 693 694 let (alice_transport, bob_transport) = result.unwrap(); 695 696 // Verify they have each other's static keys 697 assert_eq!(alice_transport.remote_static().unwrap(), &bob.public_bytes()); 698 assert_eq!(bob_transport.remote_static().unwrap(), &alice.public_bytes()); 699 } 700 701 // ==================== Transport Tests ==================== 702 703 #[test] 704 fn test_finalize_to_transport() { 705 let alice = ExchangeKeyPair::generate(); 706 let bob = ExchangeKeyPair::generate(); 707 708 let (mut alice_transport, mut bob_transport) = perform_handshake(&alice, &bob).unwrap(); 709 710 // Test encryption/decryption 711 let plaintext = b"Hello from Alice!"; 712 let ciphertext = alice_transport.encrypt(plaintext).unwrap(); 713 let decrypted = bob_transport.decrypt(&ciphertext).unwrap(); 714 715 assert_eq!(plaintext.as_slice(), decrypted.as_slice()); 716 717 // Bidirectional 718 let reply = b"Hello from Bob!"; 719 let ciphertext2 = bob_transport.encrypt(reply).unwrap(); 720 let decrypted2 = alice_transport.decrypt(&ciphertext2).unwrap(); 721 722 assert_eq!(reply.as_slice(), decrypted2.as_slice()); 723 } 724 725 // ==================== Error Cases ==================== 726 727 #[test] 728 fn test_cannot_generate_when_not_ready() { 729 let keys = ExchangeKeyPair::generate(); 730 let mut responder = Handshake::new_responder(&keys).unwrap(); 731 732 // Responder can't generate before receiving 733 let result = responder.generate(); 734 assert!(result.is_err()); 735 } 736 737 #[test] 738 fn test_cannot_finalize_incomplete() { 739 let keys = ExchangeKeyPair::generate(); 740 let handshake = Handshake::new_initiator(&keys).unwrap(); 741 742 let result = handshake.finalize(); 743 assert!(result.is_err()); 744 assert!(matches!( 745 result.unwrap_err(), 746 DeadDropError::InvalidHandshakeState(_) 747 )); 748 } 749 750 #[test] 751 fn test_invalid_handshake_message() { 752 let alice_keys = ExchangeKeyPair::generate(); 753 let bob_keys = ExchangeKeyPair::generate(); 754 755 let mut alice = Handshake::new_initiator(&alice_keys).unwrap(); 756 let mut bob = Handshake::new_responder(&bob_keys).unwrap(); 757 758 // Get a valid first message 759 let msg1 = alice.generate().unwrap(); 760 bob.receive(&msg1).unwrap(); 761 762 // Now Bob generates message 2 763 let msg2 = bob.generate().unwrap(); 764 765 // Tamper with the encrypted portion of message 2 766 let mut garbage = msg2.clone(); 767 for byte in garbage.iter_mut().skip(32) { 768 // Skip the ephemeral key, tamper with encrypted payload 769 *byte ^= 0xFF; 770 } 771 772 // Alice should reject the tampered message 773 let result = alice.receive(&garbage); 774 assert!(result.is_err(), "Should reject tampered handshake message"); 775 assert!(alice.is_failed()); 776 } 777 778 // ==================== Contact Verification ==================== 779 780 #[test] 781 fn test_verify_contact_success() { 782 let alice = ExchangeKeyPair::generate(); 783 let bob = ExchangeKeyPair::generate(); 784 785 let (alice_hs, bob_hs) = { 786 let mut alice_hs = Handshake::new_initiator(&alice).unwrap(); 787 let mut bob_hs = Handshake::new_responder(&bob).unwrap(); 788 789 let msg1 = alice_hs.generate().unwrap(); 790 bob_hs.receive(&msg1).unwrap(); 791 792 let msg2 = bob_hs.generate().unwrap(); 793 alice_hs.receive(&msg2).unwrap(); 794 795 let msg3 = alice_hs.generate().unwrap(); 796 bob_hs.receive(&msg3).unwrap(); 797 798 (alice_hs, bob_hs) 799 }; 800 801 // Alice verifies Bob is a known contact 802 let known_contacts = [bob.public_bytes()]; 803 assert!(alice_hs.verify_contact(&known_contacts)); 804 805 // Bob verifies Alice is a known contact 806 let known_contacts = [alice.public_bytes()]; 807 assert!(bob_hs.verify_contact(&known_contacts)); 808 } 809 810 #[test] 811 fn test_verify_contact_failure() { 812 let alice = ExchangeKeyPair::generate(); 813 let bob = ExchangeKeyPair::generate(); 814 let charlie = ExchangeKeyPair::generate(); 815 816 let (alice_hs, _) = { 817 let mut alice_hs = Handshake::new_initiator(&alice).unwrap(); 818 let mut bob_hs = Handshake::new_responder(&bob).unwrap(); 819 820 let msg1 = alice_hs.generate().unwrap(); 821 bob_hs.receive(&msg1).unwrap(); 822 823 let msg2 = bob_hs.generate().unwrap(); 824 alice_hs.receive(&msg2).unwrap(); 825 826 let msg3 = alice_hs.generate().unwrap(); 827 bob_hs.receive(&msg3).unwrap(); 828 829 (alice_hs, bob_hs) 830 }; 831 832 // Alice's contact list only has Charlie, not Bob 833 let known_contacts = [charlie.public_bytes()]; 834 assert!(!alice_hs.verify_contact(&known_contacts)); 835 836 // Empty contact list 837 assert!(!alice_hs.verify_contact(&[])); 838 } 839 840 #[test] 841 fn test_verify_contact_before_key_exchange() { 842 let keys = ExchangeKeyPair::generate(); 843 let handshake = Handshake::new_initiator(&keys).unwrap(); 844 845 // Remote static not yet known 846 assert!(handshake.remote_static().is_none()); 847 assert!(!handshake.verify_contact(&[keys.public_bytes()])); 848 } 849 850 // ==================== State Tests ==================== 851 852 #[test] 853 fn test_handshake_state_needs_to_send() { 854 assert!(HandshakeState::Initial.needs_to_send()); 855 assert!(HandshakeState::ReceivedEphemeral.needs_to_send()); 856 assert!(HandshakeState::ReceivedEphemeralAndStatic.needs_to_send()); 857 assert!(!HandshakeState::SentEphemeral.needs_to_send()); 858 assert!(!HandshakeState::Complete.needs_to_send()); 859 } 860 861 #[test] 862 fn test_handshake_state_needs_to_receive() { 863 assert!(HandshakeState::SentEphemeral.needs_to_receive()); 864 assert!(HandshakeState::SentEphemeralAndStatic.needs_to_receive()); 865 assert!(!HandshakeState::Initial.needs_to_receive()); 866 assert!(!HandshakeState::Complete.needs_to_receive()); 867 } 868 869 #[test] 870 fn test_handshake_state_is_terminal() { 871 assert!(HandshakeState::Complete.is_complete()); 872 assert!(!HandshakeState::Initial.is_complete()); 873 874 assert!(HandshakeState::Failed("test".to_string()).is_failed()); 875 assert!(!HandshakeState::Complete.is_failed()); 876 } 877 878 // ==================== Debug Tests ==================== 879 880 #[test] 881 fn test_handshake_debug() { 882 let keys = ExchangeKeyPair::generate(); 883 let handshake = Handshake::new_initiator(&keys).unwrap(); 884 885 let debug_str = format!("{:?}", handshake); 886 assert!(debug_str.contains("Handshake")); 887 assert!(debug_str.contains("state")); 888 assert!(debug_str.contains("role")); 889 } 890 }