Skip to main content

libsignal_protocol/
protocol.rs

1//
2// Copyright 2020-2021 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6use 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;
20// Backward compatible, lacking Kyber keys, version
21pub(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            // A warning instead of an error because we try multiple sessions.
175            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        // If the sender didn't include addresses, accept the message for
199        // backward compatibility with older clients.
200        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    /// Serializes sender and recipient addresses into a single byte vector.
249    /// Returns `None` if either address name is not a valid ServiceId.
250    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    // While we reject messages without Kyber payloads, we still for now allow constructing the
343    // struct without one so that we can provide a better error message when we try to process it.
344    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        // The message contains at least a X25519 key and a chain key
754        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    /// Identifies a serialized PlaintextContent.
816    ///
817    /// This ensures someone doesn't try to serialize an arbitrary Content message as
818    /// PlaintextContent; only messages that are okay to send as plaintext should be allowed.
819    const PLAINTEXT_CONTEXT_IDENTIFIER_BYTE: u8 = 0xC0;
820
821    /// Marks the end of a message and the start of any padding.
822    ///
823    /// Usually messages are padded to avoid exposing patterns,
824    /// but PlaintextContent messages are all fixed-length anyway, so there won't be any padding.
825    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
965/// For testing
966pub 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
985/// A consistent way to determine, given a session that is not PQ
986/// and a ratio of sessions which if not PQ should be archived,
987/// which sessions to use (returning true) and which to archive
988/// (returning false).  The session key's first 4 bytes are used as
989/// a uniformly random big-endian integer as part of this calculation,
990/// which works well for a session's `alice_base_key()`.
991pub 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    // We have a chain, but it's not a PQ chain.
999    // We want to deterministically decide whether a session should be used
1000    // based on a ratio between 0 and 1.  We also want the decision as to
1001    // whether to use the session to be the same for Alice and Bob.
1002    // The session key is a x25519 key, from which we pull out 4 bytes
1003    // we expect to be relatively uniform.
1004    let sess_u32 = u32::from_be_bytes(
1005        (&session_key[..4])
1006            .try_into()
1007            .expect("should have 32 bytes"),
1008    );
1009    // We then convert the require_pq_ratio to a u32 that is 0xFF... for 1,
1010    // 0x00... for 0, and uniform in between for other values.
1011    #[allow(clippy::cast_possible_truncation)]
1012    let ratio_u32 = ((u32::MAX as f64) * require_pq_ratio) as u32;
1013    // Finally, we compare the two, and we only expire the existing session if
1014    // its key is smaller than the ratio key.
1015    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"", // pq_ratchet
1061        )
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, // TODO: add kyber prekeys
1096            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        // Wrong sender address should be rejected.
1240        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        // Wrong recipient address should be rejected.
1249        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        // Correct addresses should be accepted.
1258        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, // TODO: add kyber prekeys
1338            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}