1use hmac::{Hmac, KeyInit as _, Mac as _};
7use prost::Message;
8use rand::{CryptoRng, Rng};
9use sha2::Sha256;
10use subtle::ConstantTimeEq;
11use uuid::Uuid;
12
13use crate::state::{KyberPreKeyId, PreKeyId, SignedPreKeyId};
14use crate::{
15 IdentityKey, PrivateKey, ProtocolAddress, PublicKey, Result, ServiceId, SignalProtocolError,
16 Timestamp, kem, proto,
17};
18
19pub(crate) const CIPHERTEXT_MESSAGE_CURRENT_VERSION: u8 = 4;
20pub(crate) const CIPHERTEXT_MESSAGE_PRE_KYBER_VERSION: u8 = 3;
22pub(crate) const SENDERKEY_MESSAGE_CURRENT_VERSION: u8 = 3;
23
24#[derive(Debug, Clone)]
25pub enum CiphertextMessage {
26 SignalMessage(SignalMessage),
27 PreKeySignalMessage(PreKeySignalMessage),
28 SenderKeyMessage(SenderKeyMessage),
29 PlaintextContent(PlaintextContent),
30}
31
32#[derive(Copy, Clone, Eq, PartialEq, Debug, derive_more::TryFrom)]
33#[repr(u8)]
34#[try_from(repr)]
35pub enum CiphertextMessageType {
36 Whisper = 2,
37 PreKey = 3,
38 SenderKey = 7,
39 Plaintext = 8,
40}
41
42impl CiphertextMessage {
43 pub fn message_type(&self) -> CiphertextMessageType {
44 match self {
45 CiphertextMessage::SignalMessage(_) => CiphertextMessageType::Whisper,
46 CiphertextMessage::PreKeySignalMessage(_) => CiphertextMessageType::PreKey,
47 CiphertextMessage::SenderKeyMessage(_) => CiphertextMessageType::SenderKey,
48 CiphertextMessage::PlaintextContent(_) => CiphertextMessageType::Plaintext,
49 }
50 }
51
52 pub fn serialize(&self) -> &[u8] {
53 match self {
54 CiphertextMessage::SignalMessage(x) => x.serialized(),
55 CiphertextMessage::PreKeySignalMessage(x) => x.serialized(),
56 CiphertextMessage::SenderKeyMessage(x) => x.serialized(),
57 CiphertextMessage::PlaintextContent(x) => x.serialized(),
58 }
59 }
60}
61
62#[derive(Debug, Clone)]
63pub struct SignalMessage {
64 message_version: u8,
65 sender_ratchet_key: PublicKey,
66 counter: u32,
67 #[cfg_attr(not(test), expect(dead_code))]
68 previous_counter: u32,
69 ciphertext: Box<[u8]>,
70 pq_ratchet: spqr::SerializedState,
71 addresses: Option<Box<[u8]>>,
72 serialized: Box<[u8]>,
73}
74
75impl SignalMessage {
76 const MAC_LENGTH: usize = 8;
77
78 #[allow(clippy::too_many_arguments)]
79 pub fn new(
80 message_version: u8,
81 mac_key: &[u8],
82 addresses: Option<(&ProtocolAddress, &ProtocolAddress)>,
83 sender_ratchet_key: PublicKey,
84 counter: u32,
85 previous_counter: u32,
86 ciphertext: &[u8],
87 sender_identity_key: &IdentityKey,
88 receiver_identity_key: &IdentityKey,
89 pq_ratchet: &[u8],
90 ) -> Result<Self> {
91 let addresses =
92 addresses.and_then(|(sender, recipient)| Self::serialize_addresses(sender, recipient));
93 let message = proto::wire::SignalMessage {
94 ratchet_key: Some(sender_ratchet_key.serialize().into_vec()),
95 counter: Some(counter),
96 previous_counter: Some(previous_counter),
97 ciphertext: Some(Vec::<u8>::from(ciphertext)),
98 pq_ratchet: if pq_ratchet.is_empty() {
99 None
100 } else {
101 Some(pq_ratchet.to_vec())
102 },
103 addresses,
104 };
105 let mut serialized = Vec::with_capacity(1 + message.encoded_len() + Self::MAC_LENGTH);
106 serialized.push(((message_version & 0xF) << 4) | CIPHERTEXT_MESSAGE_CURRENT_VERSION);
107 message
108 .encode(&mut serialized)
109 .expect("can always append to a buffer");
110 let mac = Self::compute_mac(
111 sender_identity_key,
112 receiver_identity_key,
113 mac_key,
114 &serialized,
115 )?;
116 serialized.extend_from_slice(&mac);
117 let serialized = serialized.into_boxed_slice();
118 Ok(Self {
119 message_version,
120 sender_ratchet_key,
121 counter,
122 previous_counter,
123 ciphertext: ciphertext.into(),
124 pq_ratchet: pq_ratchet.to_vec(),
125 addresses: message.addresses.map(Into::into),
126 serialized,
127 })
128 }
129
130 #[inline]
131 pub fn message_version(&self) -> u8 {
132 self.message_version
133 }
134
135 #[inline]
136 pub fn sender_ratchet_key(&self) -> &PublicKey {
137 &self.sender_ratchet_key
138 }
139
140 #[inline]
141 pub fn counter(&self) -> u32 {
142 self.counter
143 }
144
145 #[inline]
146 pub fn pq_ratchet(&self) -> &spqr::SerializedMessage {
147 &self.pq_ratchet
148 }
149
150 #[inline]
151 pub fn serialized(&self) -> &[u8] {
152 &self.serialized
153 }
154
155 #[inline]
156 pub fn body(&self) -> &[u8] {
157 &self.ciphertext
158 }
159
160 pub(crate) fn verify_mac(
161 &self,
162 sender_identity_key: &IdentityKey,
163 receiver_identity_key: &IdentityKey,
164 mac_key: &[u8],
165 ) -> Result<bool> {
166 let (content, their_mac) = self
167 .serialized
168 .split_last_chunk::<{ Self::MAC_LENGTH }>()
169 .expect("length checked at construction");
170 let our_mac =
171 Self::compute_mac(sender_identity_key, receiver_identity_key, mac_key, content)?;
172 let result: bool = our_mac.ct_eq(their_mac).into();
173 if !result {
174 log::warn!(
176 "Bad Mac! Their Mac: {} Our Mac: {}",
177 hex::encode(their_mac),
178 hex::encode(our_mac)
179 );
180 return Ok(false);
181 }
182
183 Ok(true)
184 }
185
186 pub fn verify_mac_with_addresses(
187 &self,
188 sender_address: &ProtocolAddress,
189 recipient_address: &ProtocolAddress,
190 sender_identity_key: &IdentityKey,
191 receiver_identity_key: &IdentityKey,
192 mac_key: &[u8],
193 ) -> Result<bool> {
194 if !self.verify_mac(sender_identity_key, receiver_identity_key, mac_key)? {
195 return Ok(false);
196 }
197
198 let Some(encoded_addresses) = &self.addresses else {
201 return Ok(true);
202 };
203
204 let Some(expected) = Self::serialize_addresses(sender_address, recipient_address) else {
205 log::warn!(
206 "Locally supplied addresses not valid Service IDs: sender={}, recipient={}",
207 sender_address,
208 recipient_address,
209 );
210 return Ok(false);
211 };
212
213 if bool::from(expected.ct_eq(encoded_addresses.as_ref())) {
214 Ok(true)
215 } else {
216 log::warn!(
217 "Address mismatch: sender={}, recipient={}",
218 sender_address,
219 recipient_address,
220 );
221 Ok(false)
222 }
223 }
224
225 fn compute_mac(
226 sender_identity_key: &IdentityKey,
227 receiver_identity_key: &IdentityKey,
228 mac_key: &[u8],
229 message: &[u8],
230 ) -> Result<[u8; Self::MAC_LENGTH]> {
231 if mac_key.len() != 32 {
232 return Err(SignalProtocolError::InvalidMacKeyLength(mac_key.len()));
233 }
234 let mut mac = Hmac::<Sha256>::new_from_slice(mac_key)
235 .expect("HMAC-SHA256 should accept any size key");
236
237 mac.update(sender_identity_key.public_key().serialize().as_ref());
238 mac.update(receiver_identity_key.public_key().serialize().as_ref());
239 mac.update(message);
240 let result = *mac
241 .finalize()
242 .into_bytes()
243 .first_chunk()
244 .expect("enough bytes");
245 Ok(result)
246 }
247
248 fn serialize_addresses(
251 sender: &ProtocolAddress,
252 recipient: &ProtocolAddress,
253 ) -> Option<Vec<u8>> {
254 let sender_service_id = ServiceId::parse_from_service_id_string(sender.name())?;
255 let recipient_service_id = ServiceId::parse_from_service_id_string(recipient.name())?;
256
257 let mut bytes = Vec::with_capacity(36);
258 bytes.extend_from_slice(&sender_service_id.service_id_fixed_width_binary());
259 bytes.push(sender.device_id().into());
260 bytes.extend_from_slice(&recipient_service_id.service_id_fixed_width_binary());
261 bytes.push(recipient.device_id().into());
262 Some(bytes)
263 }
264}
265
266impl AsRef<[u8]> for SignalMessage {
267 fn as_ref(&self) -> &[u8] {
268 &self.serialized
269 }
270}
271
272impl TryFrom<&[u8]> for SignalMessage {
273 type Error = SignalProtocolError;
274
275 fn try_from(value: &[u8]) -> Result<Self> {
276 if value.len() < SignalMessage::MAC_LENGTH + 1 {
277 return Err(SignalProtocolError::CiphertextMessageTooShort(value.len()));
278 }
279 let message_version = value[0] >> 4;
280 if message_version < CIPHERTEXT_MESSAGE_PRE_KYBER_VERSION {
281 return Err(SignalProtocolError::LegacyCiphertextVersion(
282 message_version,
283 ));
284 }
285 if message_version > CIPHERTEXT_MESSAGE_CURRENT_VERSION {
286 return Err(SignalProtocolError::UnrecognizedCiphertextVersion(
287 message_version,
288 ));
289 }
290
291 let proto_structure =
292 proto::wire::SignalMessage::decode(&value[1..value.len() - SignalMessage::MAC_LENGTH])
293 .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
294
295 let sender_ratchet_key = proto_structure
296 .ratchet_key
297 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
298 let sender_ratchet_key = PublicKey::deserialize(&sender_ratchet_key)?;
299 let counter = proto_structure
300 .counter
301 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
302 let previous_counter = proto_structure.previous_counter.unwrap_or(0);
303 let ciphertext = proto_structure
304 .ciphertext
305 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?
306 .into_boxed_slice();
307
308 Ok(SignalMessage {
309 message_version,
310 sender_ratchet_key,
311 counter,
312 previous_counter,
313 ciphertext,
314 pq_ratchet: proto_structure.pq_ratchet.unwrap_or(vec![]),
315 addresses: proto_structure.addresses.map(Into::into),
316 serialized: Box::from(value),
317 })
318 }
319}
320
321#[derive(Debug, Clone)]
322pub struct KyberPayload {
323 pre_key_id: KyberPreKeyId,
324 ciphertext: kem::SerializedCiphertext,
325}
326
327impl KyberPayload {
328 pub fn new(id: KyberPreKeyId, ciphertext: kem::SerializedCiphertext) -> Self {
329 Self {
330 pre_key_id: id,
331 ciphertext,
332 }
333 }
334}
335
336#[derive(Debug, Clone)]
337pub struct PreKeySignalMessage {
338 message_version: u8,
339 registration_id: u32,
340 pre_key_id: Option<PreKeyId>,
341 signed_pre_key_id: SignedPreKeyId,
342 kyber_payload: Option<KyberPayload>,
345 base_key: PublicKey,
346 identity_key: IdentityKey,
347 message: SignalMessage,
348 serialized: Box<[u8]>,
349}
350
351impl PreKeySignalMessage {
352 pub fn new(
353 message_version: u8,
354 registration_id: u32,
355 pre_key_id: Option<PreKeyId>,
356 signed_pre_key_id: SignedPreKeyId,
357 kyber_payload: Option<KyberPayload>,
358 base_key: PublicKey,
359 identity_key: IdentityKey,
360 message: SignalMessage,
361 ) -> Result<Self> {
362 let proto_message = proto::wire::PreKeySignalMessage {
363 registration_id: Some(registration_id),
364 pre_key_id: pre_key_id.map(|id| id.into()),
365 signed_pre_key_id: Some(signed_pre_key_id.into()),
366 kyber_pre_key_id: kyber_payload.as_ref().map(|kyber| kyber.pre_key_id.into()),
367 kyber_ciphertext: kyber_payload
368 .as_ref()
369 .map(|kyber| kyber.ciphertext.to_vec()),
370 base_key: Some(base_key.serialize().into_vec()),
371 identity_key: Some(identity_key.serialize().into_vec()),
372 message: Some(Vec::from(message.as_ref())),
373 };
374 let mut serialized = Vec::with_capacity(1 + proto_message.encoded_len());
375 serialized.push(((message_version & 0xF) << 4) | CIPHERTEXT_MESSAGE_CURRENT_VERSION);
376 proto_message
377 .encode(&mut serialized)
378 .expect("can always append to a Vec");
379 Ok(Self {
380 message_version,
381 registration_id,
382 pre_key_id,
383 signed_pre_key_id,
384 kyber_payload,
385 base_key,
386 identity_key,
387 message,
388 serialized: serialized.into_boxed_slice(),
389 })
390 }
391
392 #[inline]
393 pub fn message_version(&self) -> u8 {
394 self.message_version
395 }
396
397 #[inline]
398 pub fn registration_id(&self) -> u32 {
399 self.registration_id
400 }
401
402 #[inline]
403 pub fn pre_key_id(&self) -> Option<PreKeyId> {
404 self.pre_key_id
405 }
406
407 #[inline]
408 pub fn signed_pre_key_id(&self) -> SignedPreKeyId {
409 self.signed_pre_key_id
410 }
411
412 #[inline]
413 pub fn kyber_pre_key_id(&self) -> Option<KyberPreKeyId> {
414 self.kyber_payload.as_ref().map(|kyber| kyber.pre_key_id)
415 }
416
417 #[inline]
418 pub fn kyber_ciphertext(&self) -> Option<&kem::SerializedCiphertext> {
419 self.kyber_payload.as_ref().map(|kyber| &kyber.ciphertext)
420 }
421
422 #[inline]
423 pub fn base_key(&self) -> &PublicKey {
424 &self.base_key
425 }
426
427 #[inline]
428 pub fn identity_key(&self) -> &IdentityKey {
429 &self.identity_key
430 }
431
432 #[inline]
433 pub fn message(&self) -> &SignalMessage {
434 &self.message
435 }
436
437 #[inline]
438 pub fn serialized(&self) -> &[u8] {
439 &self.serialized
440 }
441}
442
443impl AsRef<[u8]> for PreKeySignalMessage {
444 fn as_ref(&self) -> &[u8] {
445 &self.serialized
446 }
447}
448
449impl TryFrom<&[u8]> for PreKeySignalMessage {
450 type Error = SignalProtocolError;
451
452 fn try_from(value: &[u8]) -> Result<Self> {
453 if value.is_empty() {
454 return Err(SignalProtocolError::CiphertextMessageTooShort(value.len()));
455 }
456
457 let message_version = value[0] >> 4;
458 if message_version < CIPHERTEXT_MESSAGE_PRE_KYBER_VERSION {
459 return Err(SignalProtocolError::LegacyCiphertextVersion(
460 message_version,
461 ));
462 }
463 if message_version > CIPHERTEXT_MESSAGE_CURRENT_VERSION {
464 return Err(SignalProtocolError::UnrecognizedCiphertextVersion(
465 message_version,
466 ));
467 }
468
469 let proto_structure = proto::wire::PreKeySignalMessage::decode(&value[1..])
470 .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
471
472 let base_key = proto_structure
473 .base_key
474 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
475 let identity_key = proto_structure
476 .identity_key
477 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
478 let message = proto_structure
479 .message
480 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
481 let signed_pre_key_id = proto_structure
482 .signed_pre_key_id
483 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
484
485 let base_key = PublicKey::deserialize(base_key.as_ref())?;
486
487 let kyber_payload = match (
488 proto_structure.kyber_pre_key_id,
489 proto_structure.kyber_ciphertext,
490 ) {
491 (Some(id), Some(ct)) => Some(KyberPayload::new(id.into(), ct.into_boxed_slice())),
492 (None, None) if message_version <= CIPHERTEXT_MESSAGE_PRE_KYBER_VERSION => None,
493 (None, None) => {
494 return Err(SignalProtocolError::InvalidMessage(
495 CiphertextMessageType::PreKey,
496 "Kyber pre key must be present for this session version".to_owned(),
497 ));
498 }
499 _ => {
500 return Err(SignalProtocolError::InvalidMessage(
501 CiphertextMessageType::PreKey,
502 "Both or neither kyber pre_key_id and kyber_ciphertext can be present"
503 .to_owned(),
504 ));
505 }
506 };
507
508 Ok(PreKeySignalMessage {
509 message_version,
510 registration_id: proto_structure.registration_id.unwrap_or(0),
511 pre_key_id: proto_structure.pre_key_id.map(|id| id.into()),
512 signed_pre_key_id: signed_pre_key_id.into(),
513 kyber_payload,
514 base_key,
515 identity_key: IdentityKey::try_from(identity_key.as_ref())?,
516 message: SignalMessage::try_from(message.as_ref())?,
517 serialized: Box::from(value),
518 })
519 }
520}
521
522#[derive(Debug, Clone)]
523pub struct SenderKeyMessage {
524 message_version: u8,
525 distribution_id: Uuid,
526 chain_id: u32,
527 iteration: u32,
528 ciphertext: Box<[u8]>,
529 serialized: Box<[u8]>,
530}
531
532impl SenderKeyMessage {
533 const SIGNATURE_LEN: usize = 64;
534
535 pub fn new<R: CryptoRng + Rng>(
536 message_version: u8,
537 distribution_id: Uuid,
538 chain_id: u32,
539 iteration: u32,
540 ciphertext: Box<[u8]>,
541 csprng: &mut R,
542 signature_key: &PrivateKey,
543 ) -> Result<Self> {
544 let proto_message = proto::wire::SenderKeyMessage {
545 distribution_uuid: Some(distribution_id.as_bytes().to_vec()),
546 chain_id: Some(chain_id),
547 iteration: Some(iteration),
548 ciphertext: Some(ciphertext.to_vec()),
549 };
550 let proto_message_len = proto_message.encoded_len();
551 let mut serialized = Vec::with_capacity(1 + proto_message_len + Self::SIGNATURE_LEN);
552 serialized.push(((message_version & 0xF) << 4) | SENDERKEY_MESSAGE_CURRENT_VERSION);
553 proto_message
554 .encode(&mut serialized)
555 .expect("can always append to a buffer");
556 let signature = signature_key.calculate_signature(&serialized, csprng)?;
557 serialized.extend_from_slice(&signature[..]);
558 Ok(Self {
559 message_version: SENDERKEY_MESSAGE_CURRENT_VERSION,
560 distribution_id,
561 chain_id,
562 iteration,
563 ciphertext,
564 serialized: serialized.into_boxed_slice(),
565 })
566 }
567
568 pub fn verify_signature(&self, signature_key: &PublicKey) -> Result<bool> {
569 let (content, signature) = self
570 .serialized
571 .split_last_chunk::<{ Self::SIGNATURE_LEN }>()
572 .expect("length checked on initialization");
573 let valid = signature_key.verify_signature(content, signature);
574
575 Ok(valid)
576 }
577
578 #[inline]
579 pub fn message_version(&self) -> u8 {
580 self.message_version
581 }
582
583 #[inline]
584 pub fn distribution_id(&self) -> Uuid {
585 self.distribution_id
586 }
587
588 #[inline]
589 pub fn chain_id(&self) -> u32 {
590 self.chain_id
591 }
592
593 #[inline]
594 pub fn iteration(&self) -> u32 {
595 self.iteration
596 }
597
598 #[inline]
599 pub fn ciphertext(&self) -> &[u8] {
600 &self.ciphertext
601 }
602
603 #[inline]
604 pub fn serialized(&self) -> &[u8] {
605 &self.serialized
606 }
607}
608
609impl AsRef<[u8]> for SenderKeyMessage {
610 fn as_ref(&self) -> &[u8] {
611 &self.serialized
612 }
613}
614
615impl TryFrom<&[u8]> for SenderKeyMessage {
616 type Error = SignalProtocolError;
617
618 fn try_from(value: &[u8]) -> Result<Self> {
619 if value.len() < 1 + Self::SIGNATURE_LEN {
620 return Err(SignalProtocolError::CiphertextMessageTooShort(value.len()));
621 }
622 let message_version = value[0] >> 4;
623 if message_version < SENDERKEY_MESSAGE_CURRENT_VERSION {
624 return Err(SignalProtocolError::LegacyCiphertextVersion(
625 message_version,
626 ));
627 }
628 if message_version > SENDERKEY_MESSAGE_CURRENT_VERSION {
629 return Err(SignalProtocolError::UnrecognizedCiphertextVersion(
630 message_version,
631 ));
632 }
633 let proto_structure =
634 proto::wire::SenderKeyMessage::decode(&value[1..value.len() - Self::SIGNATURE_LEN])
635 .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
636
637 let distribution_id = proto_structure
638 .distribution_uuid
639 .and_then(|bytes| Uuid::from_slice(bytes.as_slice()).ok())
640 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
641 let chain_id = proto_structure
642 .chain_id
643 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
644 let iteration = proto_structure
645 .iteration
646 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
647 let ciphertext = proto_structure
648 .ciphertext
649 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?
650 .into_boxed_slice();
651
652 Ok(SenderKeyMessage {
653 message_version,
654 distribution_id,
655 chain_id,
656 iteration,
657 ciphertext,
658 serialized: Box::from(value),
659 })
660 }
661}
662
663#[derive(Debug, Clone)]
664pub struct SenderKeyDistributionMessage {
665 message_version: u8,
666 distribution_id: Uuid,
667 chain_id: u32,
668 iteration: u32,
669 chain_key: Vec<u8>,
670 signing_key: PublicKey,
671 serialized: Box<[u8]>,
672}
673
674impl SenderKeyDistributionMessage {
675 pub fn new(
676 message_version: u8,
677 distribution_id: Uuid,
678 chain_id: u32,
679 iteration: u32,
680 chain_key: Vec<u8>,
681 signing_key: PublicKey,
682 ) -> Result<Self> {
683 let proto_message = proto::wire::SenderKeyDistributionMessage {
684 distribution_uuid: Some(distribution_id.as_bytes().to_vec()),
685 chain_id: Some(chain_id),
686 iteration: Some(iteration),
687 chain_key: Some(chain_key.clone()),
688 signing_key: Some(signing_key.serialize().to_vec()),
689 };
690 let mut serialized = Vec::with_capacity(1 + proto_message.encoded_len());
691 serialized.push(((message_version & 0xF) << 4) | SENDERKEY_MESSAGE_CURRENT_VERSION);
692 proto_message
693 .encode(&mut serialized)
694 .expect("can always append to a buffer");
695
696 Ok(Self {
697 message_version,
698 distribution_id,
699 chain_id,
700 iteration,
701 chain_key,
702 signing_key,
703 serialized: serialized.into_boxed_slice(),
704 })
705 }
706
707 #[inline]
708 pub fn message_version(&self) -> u8 {
709 self.message_version
710 }
711
712 #[inline]
713 pub fn distribution_id(&self) -> Result<Uuid> {
714 Ok(self.distribution_id)
715 }
716
717 #[inline]
718 pub fn chain_id(&self) -> Result<u32> {
719 Ok(self.chain_id)
720 }
721
722 #[inline]
723 pub fn iteration(&self) -> Result<u32> {
724 Ok(self.iteration)
725 }
726
727 #[inline]
728 pub fn chain_key(&self) -> Result<&[u8]> {
729 Ok(&self.chain_key)
730 }
731
732 #[inline]
733 pub fn signing_key(&self) -> Result<&PublicKey> {
734 Ok(&self.signing_key)
735 }
736
737 #[inline]
738 pub fn serialized(&self) -> &[u8] {
739 &self.serialized
740 }
741}
742
743impl AsRef<[u8]> for SenderKeyDistributionMessage {
744 fn as_ref(&self) -> &[u8] {
745 &self.serialized
746 }
747}
748
749impl TryFrom<&[u8]> for SenderKeyDistributionMessage {
750 type Error = SignalProtocolError;
751
752 fn try_from(value: &[u8]) -> Result<Self> {
753 if value.len() < 1 + 32 + 32 {
755 return Err(SignalProtocolError::CiphertextMessageTooShort(value.len()));
756 }
757
758 let message_version = value[0] >> 4;
759
760 if message_version < SENDERKEY_MESSAGE_CURRENT_VERSION {
761 return Err(SignalProtocolError::LegacyCiphertextVersion(
762 message_version,
763 ));
764 }
765 if message_version > SENDERKEY_MESSAGE_CURRENT_VERSION {
766 return Err(SignalProtocolError::UnrecognizedCiphertextVersion(
767 message_version,
768 ));
769 }
770
771 let proto_structure = proto::wire::SenderKeyDistributionMessage::decode(&value[1..])
772 .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
773
774 let distribution_id = proto_structure
775 .distribution_uuid
776 .and_then(|bytes| Uuid::from_slice(bytes.as_slice()).ok())
777 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
778 let chain_id = proto_structure
779 .chain_id
780 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
781 let iteration = proto_structure
782 .iteration
783 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
784 let chain_key = proto_structure
785 .chain_key
786 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
787 let signing_key = proto_structure
788 .signing_key
789 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
790
791 if chain_key.len() != 32 || signing_key.len() != 33 {
792 return Err(SignalProtocolError::InvalidProtobufEncoding);
793 }
794
795 let signing_key = PublicKey::deserialize(&signing_key)?;
796
797 Ok(SenderKeyDistributionMessage {
798 message_version,
799 distribution_id,
800 chain_id,
801 iteration,
802 chain_key,
803 signing_key,
804 serialized: Box::from(value),
805 })
806 }
807}
808
809#[derive(Debug, Clone)]
810pub struct PlaintextContent {
811 serialized: Box<[u8]>,
812}
813
814impl PlaintextContent {
815 const PLAINTEXT_CONTEXT_IDENTIFIER_BYTE: u8 = 0xC0;
820
821 const PADDING_BOUNDARY_BYTE: u8 = 0x80;
826
827 #[inline]
828 pub fn body(&self) -> &[u8] {
829 &self.serialized[1..]
830 }
831
832 #[inline]
833 pub fn serialized(&self) -> &[u8] {
834 &self.serialized
835 }
836}
837
838impl From<DecryptionErrorMessage> for PlaintextContent {
839 fn from(message: DecryptionErrorMessage) -> Self {
840 let proto_structure = proto::service::Content {
841 decryption_error_message: Some(message.serialized().to_vec()),
842 ..Default::default()
843 };
844 let mut serialized = vec![Self::PLAINTEXT_CONTEXT_IDENTIFIER_BYTE];
845 proto_structure
846 .encode(&mut serialized)
847 .expect("can always encode to a Vec");
848 serialized.push(Self::PADDING_BOUNDARY_BYTE);
849 Self {
850 serialized: Box::from(serialized),
851 }
852 }
853}
854
855impl TryFrom<&[u8]> for PlaintextContent {
856 type Error = SignalProtocolError;
857
858 fn try_from(value: &[u8]) -> Result<Self> {
859 if value.is_empty() {
860 return Err(SignalProtocolError::CiphertextMessageTooShort(0));
861 }
862 if value[0] != Self::PLAINTEXT_CONTEXT_IDENTIFIER_BYTE {
863 return Err(SignalProtocolError::UnrecognizedMessageVersion(
864 value[0] as u32,
865 ));
866 }
867 Ok(Self {
868 serialized: Box::from(value),
869 })
870 }
871}
872
873#[derive(Debug, Clone)]
874pub struct DecryptionErrorMessage {
875 ratchet_key: Option<PublicKey>,
876 timestamp: Timestamp,
877 device_id: u32,
878 serialized: Box<[u8]>,
879}
880
881impl DecryptionErrorMessage {
882 pub fn for_original(
883 original_bytes: &[u8],
884 original_type: CiphertextMessageType,
885 original_timestamp: Timestamp,
886 original_sender_device_id: u32,
887 ) -> Result<Self> {
888 let ratchet_key = match original_type {
889 CiphertextMessageType::Whisper => {
890 Some(*SignalMessage::try_from(original_bytes)?.sender_ratchet_key())
891 }
892 CiphertextMessageType::PreKey => Some(
893 *PreKeySignalMessage::try_from(original_bytes)?
894 .message()
895 .sender_ratchet_key(),
896 ),
897 CiphertextMessageType::SenderKey => None,
898 CiphertextMessageType::Plaintext => {
899 return Err(SignalProtocolError::InvalidArgument(
900 "cannot create a DecryptionErrorMessage for plaintext content; it is not encrypted".to_string()
901 ));
902 }
903 };
904
905 let proto_message = proto::service::DecryptionErrorMessage {
906 timestamp: Some(original_timestamp.epoch_millis()),
907 ratchet_key: ratchet_key.map(|k| k.serialize().into()),
908 device_id: Some(original_sender_device_id),
909 };
910 let serialized = proto_message.encode_to_vec();
911
912 Ok(Self {
913 ratchet_key,
914 timestamp: original_timestamp,
915 device_id: original_sender_device_id,
916 serialized: serialized.into_boxed_slice(),
917 })
918 }
919
920 #[inline]
921 pub fn timestamp(&self) -> Timestamp {
922 self.timestamp
923 }
924
925 #[inline]
926 pub fn ratchet_key(&self) -> Option<&PublicKey> {
927 self.ratchet_key.as_ref()
928 }
929
930 #[inline]
931 pub fn device_id(&self) -> u32 {
932 self.device_id
933 }
934
935 #[inline]
936 pub fn serialized(&self) -> &[u8] {
937 &self.serialized
938 }
939}
940
941impl TryFrom<&[u8]> for DecryptionErrorMessage {
942 type Error = SignalProtocolError;
943
944 fn try_from(value: &[u8]) -> Result<Self> {
945 let proto_structure = proto::service::DecryptionErrorMessage::decode(value)
946 .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
947 let timestamp = proto_structure
948 .timestamp
949 .map(Timestamp::from_epoch_millis)
950 .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
951 let ratchet_key = proto_structure
952 .ratchet_key
953 .map(|k| PublicKey::deserialize(&k))
954 .transpose()?;
955 let device_id = proto_structure.device_id.unwrap_or_default();
956 Ok(Self {
957 timestamp,
958 ratchet_key,
959 device_id,
960 serialized: Box::from(value),
961 })
962 }
963}
964
965pub fn extract_decryption_error_message_from_serialized_content(
967 bytes: &[u8],
968) -> Result<DecryptionErrorMessage> {
969 if bytes.last() != Some(&PlaintextContent::PADDING_BOUNDARY_BYTE) {
970 return Err(SignalProtocolError::InvalidProtobufEncoding);
971 }
972 let content = proto::service::Content::decode(bytes.split_last().expect("checked above").1)
973 .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
974 content
975 .decryption_error_message
976 .as_deref()
977 .ok_or_else(|| {
978 SignalProtocolError::InvalidArgument(
979 "Content does not contain DecryptionErrorMessage".to_owned(),
980 )
981 })
982 .and_then(DecryptionErrorMessage::try_from)
983}
984
985pub fn should_use_nonpq_session(require_pq_ratio: f64, session_key: &[u8]) -> bool {
992 assert!(session_key.len() >= 4);
993 if require_pq_ratio >= 1.0 {
994 return false;
995 } else if require_pq_ratio <= 0.0 {
996 return true;
997 }
998 let sess_u32 = u32::from_be_bytes(
1005 (&session_key[..4])
1006 .try_into()
1007 .expect("should have 32 bytes"),
1008 );
1009 #[allow(clippy::cast_possible_truncation)]
1012 let ratio_u32 = ((u32::MAX as f64) * require_pq_ratio) as u32;
1013 ratio_u32 <= sess_u32
1016}
1017
1018#[cfg(test)]
1019mod tests {
1020 use rand::rngs::OsRng;
1021 use rand::{CryptoRng, Rng, RngCore, TryRngCore as _};
1022
1023 use super::*;
1024 use crate::{DeviceId, KeyPair};
1025
1026 fn create_signal_message<T>(csprng: &mut T) -> Result<SignalMessage>
1027 where
1028 T: Rng + CryptoRng,
1029 {
1030 let mut mac_key = [0u8; 32];
1031 csprng.fill_bytes(&mut mac_key);
1032 let mac_key = mac_key;
1033
1034 let mut ciphertext = [0u8; 20];
1035 csprng.fill_bytes(&mut ciphertext);
1036 let ciphertext = ciphertext;
1037
1038 let sender_ratchet_key_pair = KeyPair::generate(csprng);
1039 let sender_identity_key_pair = KeyPair::generate(csprng);
1040 let receiver_identity_key_pair = KeyPair::generate(csprng);
1041 let sender_address = ProtocolAddress::new(
1042 "31415926-5358-9793-2384-626433827950".to_owned(),
1043 DeviceId::new(1).unwrap(),
1044 );
1045 let recipient_address = ProtocolAddress::new(
1046 "27182818-2845-9045-2353-602874713526".to_owned(),
1047 DeviceId::new(1).unwrap(),
1048 );
1049
1050 SignalMessage::new(
1051 4,
1052 &mac_key,
1053 Some((&sender_address, &recipient_address)),
1054 sender_ratchet_key_pair.public_key,
1055 42,
1056 41,
1057 &ciphertext,
1058 &sender_identity_key_pair.public_key.into(),
1059 &receiver_identity_key_pair.public_key.into(),
1060 b"", )
1062 }
1063
1064 fn assert_signal_message_equals(m1: &SignalMessage, m2: &SignalMessage) {
1065 assert_eq!(m1.message_version, m2.message_version);
1066 assert_eq!(m1.sender_ratchet_key, m2.sender_ratchet_key);
1067 assert_eq!(m1.counter, m2.counter);
1068 assert_eq!(m1.previous_counter, m2.previous_counter);
1069 assert_eq!(m1.ciphertext, m2.ciphertext);
1070 assert_eq!(m1.addresses, m2.addresses);
1071 assert_eq!(m1.serialized, m2.serialized);
1072 }
1073
1074 #[test]
1075 fn test_signal_message_serialize_deserialize() -> Result<()> {
1076 let mut csprng = OsRng.unwrap_err();
1077 let message = create_signal_message(&mut csprng)?;
1078 let deser_message =
1079 SignalMessage::try_from(message.as_ref()).expect("should deserialize without error");
1080 assert_signal_message_equals(&message, &deser_message);
1081 Ok(())
1082 }
1083
1084 #[test]
1085 fn test_pre_key_signal_message_serialize_deserialize() -> Result<()> {
1086 let mut csprng = OsRng.unwrap_err();
1087 let identity_key_pair = KeyPair::generate(&mut csprng);
1088 let base_key_pair = KeyPair::generate(&mut csprng);
1089 let message = create_signal_message(&mut csprng)?;
1090 let pre_key_signal_message = PreKeySignalMessage::new(
1091 3,
1092 365,
1093 None,
1094 97.into(),
1095 None, base_key_pair.public_key,
1097 identity_key_pair.public_key.into(),
1098 message,
1099 )?;
1100 let deser_pre_key_signal_message =
1101 PreKeySignalMessage::try_from(pre_key_signal_message.as_ref())
1102 .expect("should deserialize without error");
1103 assert_eq!(
1104 pre_key_signal_message.message_version,
1105 deser_pre_key_signal_message.message_version
1106 );
1107 assert_eq!(
1108 pre_key_signal_message.registration_id,
1109 deser_pre_key_signal_message.registration_id
1110 );
1111 assert_eq!(
1112 pre_key_signal_message.pre_key_id,
1113 deser_pre_key_signal_message.pre_key_id
1114 );
1115 assert_eq!(
1116 pre_key_signal_message.signed_pre_key_id,
1117 deser_pre_key_signal_message.signed_pre_key_id
1118 );
1119 assert_eq!(
1120 pre_key_signal_message.base_key,
1121 deser_pre_key_signal_message.base_key
1122 );
1123 assert_eq!(
1124 pre_key_signal_message.identity_key.public_key(),
1125 deser_pre_key_signal_message.identity_key.public_key()
1126 );
1127 assert_signal_message_equals(
1128 &pre_key_signal_message.message,
1129 &deser_pre_key_signal_message.message,
1130 );
1131 assert_eq!(
1132 pre_key_signal_message.serialized,
1133 deser_pre_key_signal_message.serialized
1134 );
1135 Ok(())
1136 }
1137
1138 #[test]
1139 fn test_signal_message_verify_mac_accepts_legacy_message_without_addresses() -> Result<()> {
1140 let mut csprng = OsRng.unwrap_err();
1141 let mut mac_key = [0u8; 32];
1142 csprng.fill_bytes(&mut mac_key);
1143
1144 let mut ciphertext = [0u8; 20];
1145 csprng.fill_bytes(&mut ciphertext);
1146
1147 let sender_ratchet_key_pair = KeyPair::generate(&mut csprng);
1148 let sender_identity_key_pair = KeyPair::generate(&mut csprng);
1149 let receiver_identity_key_pair = KeyPair::generate(&mut csprng);
1150 let sender_address = ProtocolAddress::new(
1151 "16180339-8874-9894-8482-045868343656".to_owned(),
1152 DeviceId::new(1).unwrap(),
1153 );
1154 let recipient_address = ProtocolAddress::new(
1155 "14142135-6237-3095-0488-016887242096".to_owned(),
1156 DeviceId::new(1).unwrap(),
1157 );
1158
1159 let message = SignalMessage::new(
1160 4,
1161 &mac_key,
1162 Some((&sender_address, &recipient_address)),
1163 sender_ratchet_key_pair.public_key,
1164 42,
1165 41,
1166 &ciphertext,
1167 &sender_identity_key_pair.public_key.into(),
1168 &receiver_identity_key_pair.public_key.into(),
1169 b"",
1170 )?;
1171
1172 let mut proto_structure = proto::wire::SignalMessage::decode(
1173 &message.serialized()[1..message.serialized().len() - SignalMessage::MAC_LENGTH],
1174 )
1175 .expect("valid protobuf");
1176 proto_structure.addresses = None;
1177
1178 let mut serialized =
1179 vec![((message.message_version() & 0xF) << 4) | CIPHERTEXT_MESSAGE_CURRENT_VERSION];
1180 proto_structure.encode(&mut serialized).expect("encodes");
1181 let mac = SignalMessage::compute_mac(
1182 &sender_identity_key_pair.public_key.into(),
1183 &receiver_identity_key_pair.public_key.into(),
1184 &mac_key,
1185 &serialized,
1186 )?;
1187 serialized.extend_from_slice(&mac);
1188
1189 let legacy_message = SignalMessage::try_from(serialized.as_slice())?;
1190 assert!(legacy_message.verify_mac_with_addresses(
1191 &sender_address,
1192 &recipient_address,
1193 &sender_identity_key_pair.public_key.into(),
1194 &receiver_identity_key_pair.public_key.into(),
1195 &mac_key,
1196 )?);
1197
1198 Ok(())
1199 }
1200
1201 #[test]
1202 fn test_signal_message_verify_mac_rejects_wrong_address() -> Result<()> {
1203 let mut csprng = OsRng.unwrap_err();
1204 let mut mac_key = [0u8; 32];
1205 csprng.fill_bytes(&mut mac_key);
1206
1207 let mut ciphertext = [0u8; 20];
1208 csprng.fill_bytes(&mut ciphertext);
1209
1210 let sender_ratchet_key_pair = KeyPair::generate(&mut csprng);
1211 let sender_identity_key_pair = KeyPair::generate(&mut csprng);
1212 let receiver_identity_key_pair = KeyPair::generate(&mut csprng);
1213 let sender_address = ProtocolAddress::new(
1214 "deadbeef-cafe-babe-feed-faceb00c0ffe".to_owned(),
1215 DeviceId::new(1).unwrap(),
1216 );
1217 let recipient_address = ProtocolAddress::new(
1218 "01120358-1321-3455-0891-44233377610a".to_owned(),
1219 DeviceId::new(1).unwrap(),
1220 );
1221 let wrong_address = ProtocolAddress::new(
1222 "02030507-1113-1719-2329-313741434753".to_owned(),
1223 DeviceId::new(1).unwrap(),
1224 );
1225
1226 let message = SignalMessage::new(
1227 4,
1228 &mac_key,
1229 Some((&sender_address, &recipient_address)),
1230 sender_ratchet_key_pair.public_key,
1231 42,
1232 41,
1233 &ciphertext,
1234 &sender_identity_key_pair.public_key.into(),
1235 &receiver_identity_key_pair.public_key.into(),
1236 b"",
1237 )?;
1238
1239 assert!(!message.verify_mac_with_addresses(
1241 &wrong_address,
1242 &recipient_address,
1243 &sender_identity_key_pair.public_key.into(),
1244 &receiver_identity_key_pair.public_key.into(),
1245 &mac_key,
1246 )?);
1247
1248 assert!(!message.verify_mac_with_addresses(
1250 &sender_address,
1251 &wrong_address,
1252 &sender_identity_key_pair.public_key.into(),
1253 &receiver_identity_key_pair.public_key.into(),
1254 &mac_key,
1255 )?);
1256
1257 assert!(message.verify_mac_with_addresses(
1259 &sender_address,
1260 &recipient_address,
1261 &sender_identity_key_pair.public_key.into(),
1262 &receiver_identity_key_pair.public_key.into(),
1263 &mac_key,
1264 )?);
1265
1266 Ok(())
1267 }
1268
1269 #[test]
1270 fn test_sender_key_message_serialize_deserialize() -> Result<()> {
1271 let mut csprng = OsRng.unwrap_err();
1272 let signature_key_pair = KeyPair::generate(&mut csprng);
1273 let sender_key_message = SenderKeyMessage::new(
1274 SENDERKEY_MESSAGE_CURRENT_VERSION,
1275 Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6),
1276 42,
1277 7,
1278 [1u8, 2, 3].into(),
1279 &mut csprng,
1280 &signature_key_pair.private_key,
1281 )?;
1282 let deser_sender_key_message = SenderKeyMessage::try_from(sender_key_message.as_ref())
1283 .expect("should deserialize without error");
1284 assert_eq!(
1285 sender_key_message.message_version,
1286 deser_sender_key_message.message_version
1287 );
1288 assert_eq!(
1289 sender_key_message.chain_id,
1290 deser_sender_key_message.chain_id
1291 );
1292 assert_eq!(
1293 sender_key_message.iteration,
1294 deser_sender_key_message.iteration
1295 );
1296 assert_eq!(
1297 sender_key_message.ciphertext,
1298 deser_sender_key_message.ciphertext
1299 );
1300 assert_eq!(
1301 sender_key_message.serialized,
1302 deser_sender_key_message.serialized
1303 );
1304 Ok(())
1305 }
1306
1307 #[test]
1308 fn test_decryption_error_message() -> Result<()> {
1309 let mut csprng = OsRng.unwrap_err();
1310 let identity_key_pair = KeyPair::generate(&mut csprng);
1311 let base_key_pair = KeyPair::generate(&mut csprng);
1312 let message = create_signal_message(&mut csprng)?;
1313 let timestamp: Timestamp = Timestamp::from_epoch_millis(0x2_0000_0001);
1314 let device_id = 0x8086_2021;
1315
1316 {
1317 let error_message = DecryptionErrorMessage::for_original(
1318 message.serialized(),
1319 CiphertextMessageType::Whisper,
1320 timestamp,
1321 device_id,
1322 )?;
1323 let error_message = DecryptionErrorMessage::try_from(error_message.serialized())?;
1324 assert_eq!(
1325 error_message.ratchet_key(),
1326 Some(message.sender_ratchet_key())
1327 );
1328 assert_eq!(error_message.timestamp(), timestamp);
1329 assert_eq!(error_message.device_id(), device_id);
1330 }
1331
1332 let pre_key_signal_message = PreKeySignalMessage::new(
1333 3,
1334 365,
1335 None,
1336 97.into(),
1337 None, base_key_pair.public_key,
1339 identity_key_pair.public_key.into(),
1340 message,
1341 )?;
1342
1343 {
1344 let error_message = DecryptionErrorMessage::for_original(
1345 pre_key_signal_message.serialized(),
1346 CiphertextMessageType::PreKey,
1347 timestamp,
1348 device_id,
1349 )?;
1350 let error_message = DecryptionErrorMessage::try_from(error_message.serialized())?;
1351 assert_eq!(
1352 error_message.ratchet_key(),
1353 Some(pre_key_signal_message.message().sender_ratchet_key())
1354 );
1355 assert_eq!(error_message.timestamp(), timestamp);
1356 assert_eq!(error_message.device_id(), device_id);
1357 }
1358
1359 let sender_key_message = SenderKeyMessage::new(
1360 3,
1361 Uuid::nil(),
1362 1,
1363 2,
1364 Box::from(b"test".to_owned()),
1365 &mut csprng,
1366 &base_key_pair.private_key,
1367 )?;
1368
1369 {
1370 let error_message = DecryptionErrorMessage::for_original(
1371 sender_key_message.serialized(),
1372 CiphertextMessageType::SenderKey,
1373 timestamp,
1374 device_id,
1375 )?;
1376 let error_message = DecryptionErrorMessage::try_from(error_message.serialized())?;
1377 assert_eq!(error_message.ratchet_key(), None);
1378 assert_eq!(error_message.timestamp(), timestamp);
1379 assert_eq!(error_message.device_id(), device_id);
1380 }
1381
1382 Ok(())
1383 }
1384
1385 #[test]
1386 fn test_decryption_error_message_for_plaintext() {
1387 assert!(matches!(
1388 DecryptionErrorMessage::for_original(
1389 &[],
1390 CiphertextMessageType::Plaintext,
1391 Timestamp::from_epoch_millis(5),
1392 7
1393 ),
1394 Err(SignalProtocolError::InvalidArgument(_))
1395 ));
1396 }
1397
1398 #[test]
1399 fn test_should_use_nonpq_session() {
1400 let max = b"\xff\xff\xff\xff";
1401 let min = b"\x00\x00\x00\x00";
1402 let mid = b"\x7f\xff\xff\xff";
1403 assert!(!should_use_nonpq_session(1.0, max));
1404 assert!(!should_use_nonpq_session(1.0, min));
1405 assert!(should_use_nonpq_session(0.0, max));
1406 assert!(should_use_nonpq_session(0.0, min));
1407
1408 assert!(!should_use_nonpq_session(0.75, min));
1409 assert!(!should_use_nonpq_session(0.75, mid));
1410 assert!(should_use_nonpq_session(0.75, max));
1411
1412 assert!(!should_use_nonpq_session(0.25, min));
1413 assert!(should_use_nonpq_session(0.25, mid));
1414 assert!(should_use_nonpq_session(0.25, max));
1415 }
1416}