libsignal_protocol/
sealed_sender.rs

1//
2// Copyright 2020-2022 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6use std::collections::HashMap;
7use std::ops::Range;
8use std::sync::LazyLock;
9use std::time::SystemTime;
10
11use aes_gcm_siv::aead::generic_array::typenum::Unsigned;
12use aes_gcm_siv::{AeadInPlace, Aes256GcmSiv, KeyInit};
13use indexmap::IndexMap;
14use itertools::Itertools;
15use prost::Message;
16use proto::sealed_sender::unidentified_sender_message::message::Type as ProtoMessageType;
17use rand::{CryptoRng, Rng, TryRngCore as _};
18use subtle::{Choice, ConstantTimeEq};
19use zerocopy::{FromBytes, Immutable, KnownLayout};
20
21use crate::{
22    Aci, CiphertextMessageType, DeviceId, Direction, IdentityKey, IdentityKeyPair,
23    IdentityKeyStore, KeyPair, KyberPreKeyStore, PreKeySignalMessage, PreKeyStore, PrivateKey,
24    ProtocolAddress, PublicKey, Result, ServiceId, ServiceIdFixedWidthBinaryBytes, SessionRecord,
25    SessionStore, SignalMessage, SignalProtocolError, SignedPreKeyStore, Timestamp, crypto,
26    message_encrypt, proto, session_cipher,
27};
28
29#[derive(Debug, Clone)]
30pub struct ServerCertificate {
31    serialized: Vec<u8>,
32    key_id: u32,
33    key: PublicKey,
34    certificate: Vec<u8>,
35    signature: Vec<u8>,
36}
37
38/*
390xDEADC357 is a server certificate ID which is used to test the
40revocation logic. As of this writing, no prod server certificates have
41been revoked. If one ever does, add its key ID here.
42
43If a production server certificate is ever generated which collides
44with this test certificate ID, Bad Things will happen.
45*/
46const REVOKED_SERVER_CERTIFICATE_KEY_IDS: &[u32] = &[0xDEADC357];
47
48/// A set of server certificates that can be omitted from sender certificates for space savings,
49/// keyed by ID.
50///
51/// The middle item is the trust root for the signature in the certificate, used to check integrity
52/// and potentially to filter out irrelevant certificates during validation. This is the serialized
53/// bytes of an XEd25519 public key, without the leading "type byte" used by the PublicKey type.
54///
55/// Technically the ID is also stored in the certificate data, but listing it here makes it easier
56/// for maintainers to tell which certificates are present.
57const KNOWN_SERVER_CERTIFICATES: &[(u32, [u8; 33], &[u8])] = &[
58    (
59        2,
60        // A trust root used in Staging (but this crate doesn't care about staging / production)
61        data_encoding_macro::base64!("BYhU6tPjqP46KGZEzRs1OL4U39V5dlPJ/X09ha4rErkm"),
62        &const_str::hex!(
63            "0a25080212210539450d63ebd0752c0fd4038b9d07a916f5e174b756d409b5ca79f4c97400631e124064c5a38b1e927497d3d4786b101a623ab34a7da3954fae126b04dba9d7a3604ed88cdc8550950f0d4a9134ceb7e19b94139151d2c3d6e1c81e9d1128aafca806"
64        ),
65    ),
66    (
67        3,
68        // A trust root used in Production (but this crate doesn't care about staging / production)
69        data_encoding_macro::base64!("BUkY0I+9+oPgDCn4+Ac6Iu813yvqkDr/ga8DzLxFxuk6"),
70        &const_str::hex!(
71            "0a250803122105bc9d1d290be964810dfa7e94856480a3f7060d004c9762c24c575a1522353a5a1240c11ec3c401eb0107ab38f8600e8720a63169e0e2eb8a3fae24f63099f85ea319c3c1c46d3454706ae2a679d1fee690a488adda98a2290b66c906bb60295ed781"
72        ),
73    ),
74    (
75        // "Test cert"
76        0x7357C357,
77        // This is the public key that corresponds to a private key of all zeros, which will never
78        // be used in a real service or trusted by a real app.
79        data_encoding_macro::base64!("BS/lfaNHzWJDFSjarF+7KQcw//aEr8TPwu2QmV9Yyzt0"),
80        // And we use it to sign a server certificate for a private key of all 0xFF bytes, also
81        // never used in a real service.
82        &const_str::hex!(
83            "0a2908d786df9a07122105847c0d2c375234f365e660955187a3735a0f7613d1609d3a6a4d8c53aeaa5a221240e0b9ebacdfc3aa2827f7924b697784d1c25e44ca05dd433e1a38dc6382eb2730d419ca9a250b1be9d5a9463e61efd6781777a91b83c97b844d014206e2829785"
84        ),
85    ),
86];
87
88// Valid registration IDs fit in 14 bits.
89// TODO: move this into a RegistrationId strong type.
90const VALID_REGISTRATION_ID_MASK: u16 = 0x3FFF;
91
92impl ServerCertificate {
93    pub fn deserialize(data: &[u8]) -> Result<Self> {
94        let pb = proto::sealed_sender::ServerCertificate::decode(data)
95            .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
96
97        if pb.certificate.is_none() || pb.signature.is_none() {
98            return Err(SignalProtocolError::InvalidProtobufEncoding);
99        }
100
101        let certificate = pb
102            .certificate
103            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
104        let signature = pb
105            .signature
106            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
107        let certificate_data =
108            proto::sealed_sender::server_certificate::Certificate::decode(certificate.as_ref())
109                .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
110        let key = PublicKey::try_from(
111            &certificate_data
112                .key
113                .ok_or(SignalProtocolError::InvalidProtobufEncoding)?[..],
114        )?;
115        let key_id = certificate_data
116            .id
117            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
118
119        Ok(Self {
120            serialized: data.to_vec(),
121            certificate,
122            signature,
123            key,
124            key_id,
125        })
126    }
127
128    pub fn new<R: Rng + CryptoRng>(
129        key_id: u32,
130        key: PublicKey,
131        trust_root: &PrivateKey,
132        rng: &mut R,
133    ) -> Result<Self> {
134        let certificate_pb = proto::sealed_sender::server_certificate::Certificate {
135            id: Some(key_id),
136            key: Some(key.serialize().to_vec()),
137        };
138
139        let certificate = certificate_pb.encode_to_vec();
140
141        let signature = trust_root.calculate_signature(&certificate, rng)?.to_vec();
142
143        let serialized = proto::sealed_sender::ServerCertificate {
144            certificate: Some(certificate.clone()),
145            signature: Some(signature.clone()),
146        }
147        .encode_to_vec();
148
149        Ok(Self {
150            serialized,
151            certificate,
152            signature,
153            key,
154            key_id,
155        })
156    }
157
158    pub fn validate(&self, trust_root: &PublicKey) -> Result<bool> {
159        if REVOKED_SERVER_CERTIFICATE_KEY_IDS.contains(&self.key_id()?) {
160            log::error!(
161                "received server certificate with revoked ID {:x}",
162                self.key_id()?
163            );
164            return Ok(false);
165        }
166        Ok(trust_root.verify_signature(&self.certificate, &self.signature))
167    }
168
169    pub fn key_id(&self) -> Result<u32> {
170        Ok(self.key_id)
171    }
172
173    pub fn public_key(&self) -> Result<PublicKey> {
174        Ok(self.key)
175    }
176
177    pub fn certificate(&self) -> Result<&[u8]> {
178        Ok(&self.certificate)
179    }
180
181    pub fn signature(&self) -> Result<&[u8]> {
182        Ok(&self.signature)
183    }
184
185    pub fn serialized(&self) -> Result<&[u8]> {
186        Ok(&self.serialized)
187    }
188}
189
190#[derive(Debug, Clone)]
191enum SenderCertificateSigner {
192    Embedded(ServerCertificate),
193    Reference(u32),
194}
195
196#[derive(Debug, Clone)]
197pub struct SenderCertificate {
198    signer: SenderCertificateSigner,
199    key: PublicKey,
200    sender_device_id: DeviceId,
201    sender_uuid: String,
202    sender_e164: Option<String>,
203    expiration: Timestamp,
204    serialized: Vec<u8>,
205    certificate: Vec<u8>,
206    signature: Vec<u8>,
207}
208
209impl SenderCertificate {
210    pub fn deserialize(data: &[u8]) -> Result<Self> {
211        let pb = proto::sealed_sender::SenderCertificate::decode(data)
212            .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
213        let certificate = pb
214            .certificate
215            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
216        let signature = pb
217            .signature
218            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
219        let certificate_data =
220            proto::sealed_sender::sender_certificate::Certificate::decode(certificate.as_ref())
221                .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
222
223        let sender_device_id: DeviceId = certificate_data
224            .sender_device
225            .and_then(|v| DeviceId::try_from(v).ok())
226            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
227        let expiration = certificate_data
228            .expires
229            .map(Timestamp::from_epoch_millis)
230            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
231        let signer = match certificate_data
232            .signer
233            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?
234        {
235            proto::sealed_sender::sender_certificate::certificate::Signer::Certificate(encoded) => {
236                SenderCertificateSigner::Embedded(ServerCertificate::deserialize(&encoded)?)
237            }
238            proto::sealed_sender::sender_certificate::certificate::Signer::Id(id) => {
239                SenderCertificateSigner::Reference(id)
240            }
241        };
242        let sender_uuid = match certificate_data
243            .sender_uuid
244            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?
245        {
246            proto::sealed_sender::sender_certificate::certificate::SenderUuid::UuidString(
247                uuid_str,
248            ) => uuid_str,
249            proto::sealed_sender::sender_certificate::certificate::SenderUuid::UuidBytes(raw) => {
250                // For now, map this back to a string locally.
251                uuid::Uuid::from_slice(&raw)
252                    .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?
253                    .to_string()
254            }
255        };
256        let sender_e164 = certificate_data.sender_e164;
257
258        let key = PublicKey::try_from(
259            &certificate_data
260                .identity_key
261                .ok_or(SignalProtocolError::InvalidProtobufEncoding)?[..],
262        )?;
263
264        Ok(Self {
265            signer,
266            key,
267            sender_device_id,
268            sender_uuid,
269            sender_e164,
270            expiration,
271            serialized: data.to_vec(),
272            certificate,
273            signature,
274        })
275    }
276
277    pub fn new<R: Rng + CryptoRng>(
278        sender_uuid: String,
279        sender_e164: Option<String>,
280        key: PublicKey,
281        sender_device_id: DeviceId,
282        expiration: Timestamp,
283        signer: ServerCertificate,
284        signer_key: &PrivateKey,
285        rng: &mut R,
286    ) -> Result<Self> {
287        let certificate_pb = proto::sealed_sender::sender_certificate::Certificate {
288            sender_uuid: Some(
289                proto::sealed_sender::sender_certificate::certificate::SenderUuid::UuidString(
290                    sender_uuid.clone(),
291                ),
292            ),
293            sender_e164: sender_e164.clone(),
294            sender_device: Some(sender_device_id.into()),
295            expires: Some(expiration.epoch_millis()),
296            identity_key: Some(key.serialize().to_vec()),
297            signer: Some(
298                proto::sealed_sender::sender_certificate::certificate::Signer::Certificate(
299                    signer.serialized()?.to_vec(),
300                ),
301            ),
302        };
303
304        let certificate = certificate_pb.encode_to_vec();
305
306        let signature = signer_key.calculate_signature(&certificate, rng)?.to_vec();
307
308        let serialized = proto::sealed_sender::SenderCertificate {
309            certificate: Some(certificate.clone()),
310            signature: Some(signature.clone()),
311        }
312        .encode_to_vec();
313
314        Ok(Self {
315            signer: SenderCertificateSigner::Embedded(signer),
316            key,
317            sender_device_id,
318            sender_uuid,
319            sender_e164,
320            expiration,
321            serialized,
322            certificate,
323            signature,
324        })
325    }
326
327    pub fn validate(&self, trust_root: &PublicKey, validation_time: Timestamp) -> Result<bool> {
328        self.validate_with_trust_roots(&[trust_root], validation_time)
329    }
330
331    pub fn validate_with_trust_roots(
332        &self,
333        trust_roots: &[impl AsRef<PublicKey>],
334        validation_time: Timestamp,
335    ) -> Result<bool> {
336        let signer = self.signer()?;
337
338        // Check the signer against every trust root to hide which one was the correct one.
339        let mut any_valid = Choice::from(0u8);
340        for root in trust_roots {
341            let ok = signer.validate(root.as_ref())?;
342            any_valid |= Choice::from(u8::from(ok));
343        }
344        if !bool::from(any_valid) {
345            log::error!(
346                "sender certificate contained server certificate that wasn't signed by any trust root"
347            );
348            return Ok(false);
349        }
350
351        if !signer
352            .public_key()?
353            .verify_signature(&self.certificate, &self.signature)
354        {
355            log::error!("sender certificate not signed by server");
356            return Ok(false);
357        }
358
359        if validation_time > self.expiration {
360            log::error!(
361                "sender certificate is expired (expiration: {}, validation_time: {})",
362                self.expiration.epoch_millis(),
363                validation_time.epoch_millis()
364            );
365            return Ok(false);
366        }
367
368        Ok(true)
369    }
370
371    pub fn signer(&self) -> Result<&ServerCertificate> {
372        static CERT_MAP: LazyLock<HashMap<u32, (PublicKey, ServerCertificate)>> =
373            LazyLock::new(|| {
374                HashMap::from_iter(KNOWN_SERVER_CERTIFICATES.iter().map(
375                    |(id, trust_root, cert)| {
376                        (
377                            *id,
378                            (
379                                PublicKey::deserialize(trust_root).expect("valid"),
380                                ServerCertificate::deserialize(cert).expect("valid"),
381                            ),
382                        )
383                    },
384                ))
385            });
386
387        match &self.signer {
388            SenderCertificateSigner::Embedded(cert) => Ok(cert),
389            SenderCertificateSigner::Reference(id) => CERT_MAP
390                .get(id)
391                .map(|(_trust_root, cert)| cert)
392                .ok_or_else(|| SignalProtocolError::UnknownSealedSenderServerCertificateId(*id)),
393        }
394    }
395
396    pub fn key(&self) -> Result<PublicKey> {
397        Ok(self.key)
398    }
399
400    pub fn sender_device_id(&self) -> Result<DeviceId> {
401        Ok(self.sender_device_id)
402    }
403
404    pub fn sender_uuid(&self) -> Result<&str> {
405        Ok(&self.sender_uuid)
406    }
407
408    pub fn sender_e164(&self) -> Result<Option<&str>> {
409        Ok(self.sender_e164.as_deref())
410    }
411
412    pub fn expiration(&self) -> Result<Timestamp> {
413        Ok(self.expiration)
414    }
415
416    pub fn serialized(&self) -> Result<&[u8]> {
417        Ok(&self.serialized)
418    }
419
420    pub fn certificate(&self) -> Result<&[u8]> {
421        Ok(&self.certificate)
422    }
423
424    pub fn signature(&self) -> Result<&[u8]> {
425        Ok(&self.signature)
426    }
427}
428
429impl From<ProtoMessageType> for CiphertextMessageType {
430    fn from(message_type: ProtoMessageType) -> Self {
431        let result = match message_type {
432            ProtoMessageType::Message => Self::Whisper,
433            ProtoMessageType::PrekeyMessage => Self::PreKey,
434            ProtoMessageType::SenderkeyMessage => Self::SenderKey,
435            ProtoMessageType::PlaintextContent => Self::Plaintext,
436        };
437        // Keep raw values in sync from now on, for efficient codegen.
438        assert!(result == Self::PreKey || message_type as i32 == result as i32);
439        result
440    }
441}
442
443impl From<CiphertextMessageType> for ProtoMessageType {
444    fn from(message_type: CiphertextMessageType) -> Self {
445        let result = match message_type {
446            CiphertextMessageType::PreKey => Self::PrekeyMessage,
447            CiphertextMessageType::Whisper => Self::Message,
448            CiphertextMessageType::SenderKey => Self::SenderkeyMessage,
449            CiphertextMessageType::Plaintext => Self::PlaintextContent,
450        };
451        // Keep raw values in sync from now on, for efficient codegen.
452        assert!(result == Self::PrekeyMessage || message_type as i32 == result as i32);
453        result
454    }
455}
456
457#[derive(Clone, Copy, PartialEq, Eq, Debug)]
458pub enum ContentHint {
459    Default,
460    Resendable,
461    Implicit,
462    Unknown(u32),
463}
464
465impl ContentHint {
466    fn to_proto(self) -> Option<i32> {
467        if self == ContentHint::Default {
468            None
469        } else {
470            Some(u32::from(self) as i32)
471        }
472    }
473
474    pub const fn to_u32(self) -> u32 {
475        use proto::sealed_sender::unidentified_sender_message::message::ContentHint as ProtoContentHint;
476        match self {
477            ContentHint::Default => 0,
478            ContentHint::Resendable => ProtoContentHint::Resendable as u32,
479            ContentHint::Implicit => ProtoContentHint::Implicit as u32,
480            ContentHint::Unknown(value) => value,
481        }
482    }
483}
484
485impl From<u32> for ContentHint {
486    fn from(raw_value: u32) -> Self {
487        use proto::sealed_sender::unidentified_sender_message::message::ContentHint as ProtoContentHint;
488        assert!(!ProtoContentHint::is_valid(0));
489        match ProtoContentHint::try_from(raw_value as i32) {
490            Err(_) if raw_value == 0 => ContentHint::Default,
491            Err(_) => ContentHint::Unknown(raw_value),
492            Ok(ProtoContentHint::Resendable) => ContentHint::Resendable,
493            Ok(ProtoContentHint::Implicit) => ContentHint::Implicit,
494        }
495    }
496}
497
498impl From<ContentHint> for u32 {
499    fn from(hint: ContentHint) -> Self {
500        hint.to_u32()
501    }
502}
503
504pub struct UnidentifiedSenderMessageContent {
505    serialized: Vec<u8>,
506    contents: Vec<u8>,
507    sender: SenderCertificate,
508    msg_type: CiphertextMessageType,
509    content_hint: ContentHint,
510    group_id: Option<Vec<u8>>,
511}
512
513impl UnidentifiedSenderMessageContent {
514    pub fn deserialize(data: &[u8]) -> Result<Self> {
515        let pb = proto::sealed_sender::unidentified_sender_message::Message::decode(data)
516            .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
517
518        let msg_type = pb
519            .r#type
520            .and_then(|t| ProtoMessageType::try_from(t).ok())
521            .map(CiphertextMessageType::from)
522            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
523        let sender = pb
524            .sender_certificate
525            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
526        let contents = pb
527            .content
528            .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
529        let content_hint = pb
530            .content_hint
531            .map(|raw| ContentHint::from(raw as u32))
532            .unwrap_or(ContentHint::Default);
533        let group_id = pb.group_id;
534
535        let sender = SenderCertificate::deserialize(&sender)?;
536
537        let serialized = data.to_vec();
538
539        log::info!(
540            "deserialized UnidentifiedSenderMessageContent from {}.{} with type {:?}",
541            sender.sender_uuid()?,
542            sender.sender_device_id()?,
543            msg_type,
544        );
545
546        Ok(Self {
547            serialized,
548            contents,
549            sender,
550            msg_type,
551            content_hint,
552            group_id,
553        })
554    }
555
556    pub fn new(
557        msg_type: CiphertextMessageType,
558        sender: SenderCertificate,
559        contents: Vec<u8>,
560        content_hint: ContentHint,
561        group_id: Option<Vec<u8>>,
562    ) -> Result<Self> {
563        let proto_msg_type = ProtoMessageType::from(msg_type);
564        let msg = proto::sealed_sender::unidentified_sender_message::Message {
565            content: Some(contents.clone()),
566            r#type: Some(proto_msg_type.into()),
567            sender_certificate: Some(sender.serialized()?.to_vec()),
568            content_hint: content_hint.to_proto(),
569            group_id: group_id.as_ref().and_then(|buf| {
570                if buf.is_empty() {
571                    None
572                } else {
573                    Some(buf.clone())
574                }
575            }),
576        };
577
578        let serialized = msg.encode_to_vec();
579
580        Ok(Self {
581            serialized,
582            msg_type,
583            sender,
584            contents,
585            content_hint,
586            group_id,
587        })
588    }
589
590    pub fn msg_type(&self) -> Result<CiphertextMessageType> {
591        Ok(self.msg_type)
592    }
593
594    pub fn sender(&self) -> Result<&SenderCertificate> {
595        Ok(&self.sender)
596    }
597
598    pub fn contents(&self) -> Result<&[u8]> {
599        Ok(&self.contents)
600    }
601
602    pub fn content_hint(&self) -> Result<ContentHint> {
603        Ok(self.content_hint)
604    }
605
606    pub fn group_id(&self) -> Result<Option<&[u8]>> {
607        Ok(self.group_id.as_deref())
608    }
609
610    pub fn serialized(&self) -> Result<&[u8]> {
611        Ok(&self.serialized)
612    }
613}
614
615enum UnidentifiedSenderMessage<'a> {
616    V1 {
617        ephemeral_public: PublicKey,
618        encrypted_static: Vec<u8>,
619        encrypted_message: Vec<u8>,
620    },
621    V2 {
622        ephemeral_public: PublicKey,
623        encrypted_message_key: &'a [u8; sealed_sender_v2::MESSAGE_KEY_LEN],
624        authentication_tag: &'a [u8; sealed_sender_v2::AUTH_TAG_LEN],
625        encrypted_message: &'a [u8],
626    },
627}
628
629const SEALED_SENDER_V1_MAJOR_VERSION: u8 = 1;
630const SEALED_SENDER_V1_FULL_VERSION: u8 = 0x11;
631const SEALED_SENDER_V2_MAJOR_VERSION: u8 = 2;
632const SEALED_SENDER_V2_UUID_FULL_VERSION: u8 = 0x22;
633const SEALED_SENDER_V2_SERVICE_ID_FULL_VERSION: u8 = 0x23;
634
635impl<'a> UnidentifiedSenderMessage<'a> {
636    fn deserialize(data: &'a [u8]) -> Result<Self> {
637        let (version_byte, remaining) = data.split_first().ok_or_else(|| {
638            SignalProtocolError::InvalidSealedSenderMessage("Message was empty".to_owned())
639        })?;
640        let version = version_byte >> 4;
641        log::debug!("deserializing UnidentifiedSenderMessage with version {version}");
642
643        match version {
644            0 | SEALED_SENDER_V1_MAJOR_VERSION => {
645                // XXX should we really be accepted version == 0 here?
646                let pb = proto::sealed_sender::UnidentifiedSenderMessage::decode(remaining)
647                    .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
648
649                let ephemeral_public = pb
650                    .ephemeral_public
651                    .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
652                let encrypted_static = pb
653                    .encrypted_static
654                    .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
655                let encrypted_message = pb
656                    .encrypted_message
657                    .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
658
659                let ephemeral_public = PublicKey::try_from(&ephemeral_public[..])?;
660
661                Ok(Self::V1 {
662                    ephemeral_public,
663                    encrypted_static,
664                    encrypted_message,
665                })
666            }
667            SEALED_SENDER_V2_MAJOR_VERSION => {
668                /// Uses a flat representation: C || AT || E.pub || ciphertext
669                #[derive(FromBytes, Immutable, KnownLayout)]
670                #[repr(C, packed)]
671                struct PrefixRepr {
672                    encrypted_message_key: [u8; sealed_sender_v2::MESSAGE_KEY_LEN],
673                    encrypted_authentication_tag: [u8; sealed_sender_v2::AUTH_TAG_LEN],
674                    ephemeral_public: [u8; sealed_sender_v2::PUBLIC_KEY_LEN],
675                }
676                let (prefix, encrypted_message) =
677                    zerocopy::Ref::<_, PrefixRepr>::from_prefix(remaining)
678                        .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
679
680                let PrefixRepr {
681                    encrypted_message_key,
682                    encrypted_authentication_tag,
683                    ephemeral_public,
684                } = zerocopy::Ref::into_ref(prefix);
685
686                Ok(Self::V2 {
687                    ephemeral_public: PublicKey::from_djb_public_key_bytes(
688                        ephemeral_public.as_slice(),
689                    )?,
690                    encrypted_message_key,
691                    authentication_tag: encrypted_authentication_tag,
692                    encrypted_message,
693                })
694            }
695            _ => Err(SignalProtocolError::UnknownSealedSenderVersion(version)),
696        }
697    }
698}
699
700mod sealed_sender_v1 {
701    #[cfg(test)]
702    use std::fmt;
703
704    use libsignal_core::derive_arrays;
705
706    use super::*;
707
708    /// A symmetric cipher key and a MAC key, along with a "chain key" consumed in
709    /// [`StaticKeys::calculate`].
710    pub(super) struct EphemeralKeys {
711        pub(super) chain_key: [u8; 32],
712        pub(super) cipher_key: [u8; 32],
713        pub(super) mac_key: [u8; 32],
714    }
715
716    const SALT_PREFIX: &[u8] = b"UnidentifiedDelivery";
717
718    impl EphemeralKeys {
719        /// Derive a set of symmetric keys from the key agreement between the sender and
720        /// recipient's identities.
721        pub(super) fn calculate(
722            our_keys: &KeyPair,
723            their_public: &PublicKey,
724            direction: Direction,
725        ) -> Result<Self> {
726            let our_pub_key = our_keys.public_key.serialize();
727            let their_pub_key = their_public.serialize();
728            let ephemeral_salt = match direction {
729                Direction::Sending => [SALT_PREFIX, &their_pub_key, &our_pub_key],
730                Direction::Receiving => [SALT_PREFIX, &our_pub_key, &their_pub_key],
731            }
732            .concat();
733
734            let shared_secret = our_keys.private_key.calculate_agreement(their_public)?;
735            let (chain_key, cipher_key, mac_key) = derive_arrays(|bytes| {
736                hkdf::Hkdf::<sha2::Sha256>::new(Some(&ephemeral_salt), &shared_secret)
737                    .expand(&[], bytes)
738                    .expect("valid output length")
739            });
740
741            Ok(Self {
742                chain_key,
743                cipher_key,
744                mac_key,
745            })
746        }
747    }
748
749    #[cfg(test)]
750    impl PartialEq for EphemeralKeys {
751        fn eq(&self, other: &Self) -> bool {
752            self.chain_key == other.chain_key
753                && self.cipher_key == other.cipher_key
754                && self.mac_key == other.mac_key
755        }
756    }
757
758    #[cfg(test)]
759    impl Eq for EphemeralKeys {}
760
761    #[cfg(test)]
762    impl fmt::Debug for EphemeralKeys {
763        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
764            write!(
765                f,
766                "EphemeralKeys {{ chain_key: {:?}, cipher_key: {:?}, mac_key: {:?} }}",
767                self.chain_key, self.cipher_key, self.mac_key
768            )
769        }
770    }
771
772    /// A symmetric cipher key and a MAC key.
773    pub(super) struct StaticKeys {
774        pub(super) cipher_key: [u8; 32],
775        pub(super) mac_key: [u8; 32],
776    }
777
778    impl StaticKeys {
779        /// Derive a set of symmetric keys from the agreement between the sender and
780        /// recipient's identities, as well as [`EphemeralKeys::chain_key`].
781        pub(super) fn calculate(
782            our_keys: &IdentityKeyPair,
783            their_key: &PublicKey,
784            chain_key: &[u8; 32],
785            ctext: &[u8],
786        ) -> Result<Self> {
787            let salt = [chain_key, ctext].concat();
788
789            let shared_secret = our_keys.private_key().calculate_agreement(their_key)?;
790            // 96 bytes are derived, but the first 32 are discarded/unused. This is intended to
791            // mirror the way the EphemeralKeys are derived, even though StaticKeys does not end up
792            // requiring a third "chain key".
793            let (_, cipher_key, mac_key) = derive_arrays::<32, 32, 32>(|bytes| {
794                hkdf::Hkdf::<sha2::Sha256>::new(Some(&salt), &shared_secret)
795                    .expand(&[], bytes)
796                    .expect("valid output length")
797            });
798
799            Ok(Self {
800                cipher_key,
801                mac_key,
802            })
803        }
804    }
805
806    #[test]
807    fn test_agreement_and_authentication() -> Result<()> {
808        // The sender and recipient each have a long-term identity key pair.
809        let sender_identity = IdentityKeyPair::generate(&mut rand::rng());
810        let recipient_identity = IdentityKeyPair::generate(&mut rand::rng());
811
812        // Generate an ephemeral key pair.
813        let sender_ephemeral = KeyPair::generate(&mut rand::rng());
814        let ephemeral_public = sender_ephemeral.public_key;
815        // Generate ephemeral cipher, chain, and MAC keys.
816        let sender_eph_keys = EphemeralKeys::calculate(
817            &sender_ephemeral,
818            recipient_identity.public_key(),
819            Direction::Sending,
820        )?;
821
822        // Encrypt the sender's public key with AES-256 CTR and a MAC.
823        let sender_static_key_ctext = crypto::aes256_ctr_hmacsha256_encrypt(
824            &sender_identity.public_key().serialize(),
825            &sender_eph_keys.cipher_key,
826            &sender_eph_keys.mac_key,
827        )
828        .expect("just generated these keys, they should be correct");
829
830        // Generate another cipher and MAC key.
831        let sender_static_keys = StaticKeys::calculate(
832            &sender_identity,
833            recipient_identity.public_key(),
834            &sender_eph_keys.chain_key,
835            &sender_static_key_ctext,
836        )?;
837
838        let sender_message_contents = b"this is a binary message";
839        let sender_message_data = crypto::aes256_ctr_hmacsha256_encrypt(
840            sender_message_contents,
841            &sender_static_keys.cipher_key,
842            &sender_static_keys.mac_key,
843        )
844        .expect("just generated these keys, they should be correct");
845
846        // The message recipient calculates the ephemeral key and the sender's public key.
847        let recipient_eph_keys = EphemeralKeys::calculate(
848            &recipient_identity.into(),
849            &ephemeral_public,
850            Direction::Receiving,
851        )?;
852        assert_eq!(sender_eph_keys, recipient_eph_keys);
853
854        let recipient_message_key_bytes = crypto::aes256_ctr_hmacsha256_decrypt(
855            &sender_static_key_ctext,
856            &recipient_eph_keys.cipher_key,
857            &recipient_eph_keys.mac_key,
858        )
859        .expect("should decrypt successfully");
860        let sender_public_key: PublicKey = PublicKey::try_from(&recipient_message_key_bytes[..])?;
861        assert_eq!(sender_identity.public_key(), &sender_public_key);
862
863        let recipient_static_keys = StaticKeys::calculate(
864            &recipient_identity,
865            &sender_public_key,
866            &recipient_eph_keys.chain_key,
867            &sender_static_key_ctext,
868        )?;
869
870        let recipient_message_contents = crypto::aes256_ctr_hmacsha256_decrypt(
871            &sender_message_data,
872            &recipient_static_keys.cipher_key,
873            &recipient_static_keys.mac_key,
874        )
875        .expect("should decrypt successfully");
876        assert_eq!(recipient_message_contents, sender_message_contents);
877
878        Ok(())
879    }
880}
881
882/// Encrypt the plaintext message `ptext`, generate an [`UnidentifiedSenderMessageContent`], then
883/// pass the result to [`sealed_sender_encrypt_from_usmc`].
884///
885/// This is a simple way to encrypt a message in a 1:1 using [Sealed Sender v1].
886///
887/// [Sealed Sender v1]: sealed_sender_encrypt_from_usmc
888pub async fn sealed_sender_encrypt<R: Rng + CryptoRng>(
889    destination: &ProtocolAddress,
890    sender_cert: &SenderCertificate,
891    ptext: &[u8],
892    session_store: &mut dyn SessionStore,
893    identity_store: &mut dyn IdentityKeyStore,
894    now: SystemTime,
895    rng: &mut R,
896) -> Result<Vec<u8>> {
897    let sender_address = ProtocolAddress::new(
898        sender_cert.sender_uuid()?.to_owned(),
899        sender_cert.sender_device_id()?,
900    );
901    let message = message_encrypt(
902        ptext,
903        destination,
904        &sender_address,
905        session_store,
906        identity_store,
907        now,
908        rng,
909    )
910    .await?;
911    let usmc = UnidentifiedSenderMessageContent::new(
912        message.message_type(),
913        sender_cert.clone(),
914        message.serialize().to_vec(),
915        ContentHint::Default,
916        None,
917    )?;
918    sealed_sender_encrypt_from_usmc(destination, &usmc, identity_store, rng).await
919}
920
921/// This method implements the single-key single-recipient [KEM] described in [this Signal blog
922/// post], a.k.a. Sealed Sender v1.
923///
924/// [KEM]: https://en.wikipedia.org/wiki/Key_encapsulation
925/// [this Signal blog post]: https://signal.org/blog/sealed-sender/
926///
927/// [`sealed_sender_decrypt`] is used in the client to decrypt the Sealed Sender message produced by
928/// this method.
929///
930/// # Contrast with Sealed Sender v2
931/// The *single-recipient* KEM scheme implemented by this method partially derives the encryption
932/// key from the recipient's identity key, which would then require re-encrypting the same message
933/// multiple times to send to multiple recipients. In contrast,
934/// [Sealed Sender v2](sealed_sender_multi_recipient_encrypt) uses a *multi-recipient* KEM scheme
935/// which avoids this repeated work, but makes a few additional design tradeoffs.
936///
937/// # High-level algorithmic overview
938/// The KEM scheme implemented by this method is described in [this Signal blog post]. The
939/// high-level steps of this process are listed below:
940/// 1. Generate a random key pair.
941/// 2. Derive a symmetric chain key, cipher key, and MAC key from the recipient's public key and the
942///    sender's public/private key pair.
943/// 3. Symmetrically encrypt the sender's public key using the cipher key and MAC key from (2) with
944///    AES-256 in CTR mode.
945/// 4. Derive a second symmetric cipher key and MAC key from the sender's private key, the
946///    recipient's public key, and the chain key from (2).
947/// 5. Symmetrically encrypt the underlying [`UnidentifiedSenderMessageContent`] using the cipher key
948///    and MAC key from (4) with AES-256 in CTR mode.
949/// 6. Send the ephemeral public key from (1) and the encrypted public key from (3) to the
950///    recipient, along with the encrypted message (5).
951///
952/// ## Pseudocode
953///```text
954/// e_pub, e_priv                  = X25519.generateEphemeral()
955/// e_chain, e_cipherKey, e_macKey = HKDF(salt="UnidentifiedDelivery" || recipientIdentityPublic || e_pub, ikm=ECDH(recipientIdentityPublic, e_priv), info="")
956/// e_ciphertext                   = AES_CTR(key=e_cipherKey, input=senderIdentityPublic)
957/// e_mac                          = Hmac256(key=e_macKey, input=e_ciphertext)
958///
959/// s_cipherKey, s_macKey = HKDF(salt=e_chain || e_ciphertext || e_mac, ikm=ECDH(recipientIdentityPublic, senderIdentityPrivate), info="")
960/// s_ciphertext          = AES_CTR(key=s_cipherKey, input=sender_certificate || message_ciphertext)
961/// s_mac                 = Hmac256(key=s_macKey, input=s_ciphertext)
962///
963/// message_to_send = s_ciphertext || s_mac
964///```
965///
966/// # Wire Format
967/// The output of this method is encoded as an `UnidentifiedSenderMessage.Message` from
968/// `sealed_sender.proto`, prepended with an additional byte to indicate the version of Sealed
969/// Sender in use (see [further documentation on the version
970/// byte](sealed_sender_multi_recipient_encrypt#the-version-byte)).
971pub async fn sealed_sender_encrypt_from_usmc<R: Rng + CryptoRng>(
972    destination: &ProtocolAddress,
973    usmc: &UnidentifiedSenderMessageContent,
974    identity_store: &dyn IdentityKeyStore,
975    rng: &mut R,
976) -> Result<Vec<u8>> {
977    let our_identity = identity_store.get_identity_key_pair().await?;
978    let their_identity = identity_store
979        .get_identity(destination)
980        .await?
981        .ok_or_else(|| SignalProtocolError::SessionNotFound(destination.clone()))?;
982
983    let ephemeral = KeyPair::generate(rng);
984
985    let eph_keys = sealed_sender_v1::EphemeralKeys::calculate(
986        &ephemeral,
987        their_identity.public_key(),
988        Direction::Sending,
989    )?;
990
991    let static_key_ctext = crypto::aes256_ctr_hmacsha256_encrypt(
992        &our_identity.public_key().serialize(),
993        &eph_keys.cipher_key,
994        &eph_keys.mac_key,
995    )
996    .expect("just generated these keys, they should be correct");
997
998    let static_keys = sealed_sender_v1::StaticKeys::calculate(
999        &our_identity,
1000        their_identity.public_key(),
1001        &eph_keys.chain_key,
1002        &static_key_ctext,
1003    )?;
1004
1005    let message_data = crypto::aes256_ctr_hmacsha256_encrypt(
1006        usmc.serialized()?,
1007        &static_keys.cipher_key,
1008        &static_keys.mac_key,
1009    )
1010    .expect("just generated these keys, they should be correct");
1011
1012    let mut serialized = vec![SEALED_SENDER_V1_FULL_VERSION];
1013    let pb = proto::sealed_sender::UnidentifiedSenderMessage {
1014        ephemeral_public: Some(ephemeral.public_key.serialize().to_vec()),
1015        encrypted_static: Some(static_key_ctext),
1016        encrypted_message: Some(message_data),
1017    };
1018    pb.encode(&mut serialized)
1019        .expect("can always append to Vec");
1020
1021    Ok(serialized)
1022}
1023
1024mod sealed_sender_v2 {
1025    use super::*;
1026
1027    // Static byte strings used as part of a MAC in HKDF.
1028    const LABEL_R: &[u8] = b"Sealed Sender v2: r (2023-08)";
1029    const LABEL_K: &[u8] = b"Sealed Sender v2: K";
1030    const LABEL_DH: &[u8] = b"Sealed Sender v2: DH";
1031    const LABEL_DH_S: &[u8] = b"Sealed Sender v2: DH-sender";
1032
1033    pub const MESSAGE_KEY_LEN: usize = 32;
1034    pub const CIPHER_KEY_LEN: usize =
1035        <Aes256GcmSiv as aes_gcm_siv::aead::KeySizeUser>::KeySize::USIZE;
1036    pub const AUTH_TAG_LEN: usize = 16;
1037    /// SSv2 hardcodes that its keys are Curve25519 public keys.
1038    pub const PUBLIC_KEY_LEN: usize = 32;
1039
1040    /// An asymmetric and a symmetric cipher key.
1041    pub(super) struct DerivedKeys {
1042        kdf: hkdf::Hkdf<sha2::Sha256>,
1043    }
1044
1045    impl DerivedKeys {
1046        /// Initialize from a slice of random bytes `m`.
1047        pub(super) fn new(m: &[u8]) -> DerivedKeys {
1048            Self {
1049                kdf: hkdf::Hkdf::<sha2::Sha256>::new(None, m),
1050            }
1051        }
1052
1053        /// Derive the ephemeral asymmetric keys.
1054        pub(super) fn derive_e(&self) -> KeyPair {
1055            let mut r = [0; 32];
1056            self.kdf
1057                .expand(LABEL_R, &mut r)
1058                .expect("valid output length");
1059            let e = PrivateKey::try_from(&r[..]).expect("valid PrivateKey");
1060            KeyPair::try_from(e).expect("can derive public key")
1061        }
1062
1063        /// Derive the symmetric cipher key.
1064        pub(super) fn derive_k(&self) -> [u8; CIPHER_KEY_LEN] {
1065            let mut k = [0; CIPHER_KEY_LEN];
1066            self.kdf
1067                .expand(LABEL_K, &mut k)
1068                .expect("valid output length");
1069            k
1070        }
1071    }
1072
1073    /// Encrypt or decrypt a slice of random bytes `input` using a shared secret derived from
1074    /// `our_keys` and `their_key`.
1075    ///
1076    /// The output of this method when called with [`Direction::Sending`] can be inverted to produce
1077    /// the original `input` bytes if called with [`Direction::Receiving`] with `our_keys` and
1078    /// `their_key` swapped.
1079    pub(super) fn apply_agreement_xor(
1080        our_keys: &KeyPair,
1081        their_key: &PublicKey,
1082        direction: Direction,
1083        input: &[u8; MESSAGE_KEY_LEN],
1084    ) -> Result<[u8; MESSAGE_KEY_LEN]> {
1085        let agreement = our_keys.calculate_agreement(their_key)?;
1086        let agreement_key_input = match direction {
1087            Direction::Sending => [
1088                agreement,
1089                our_keys.public_key.serialize(),
1090                their_key.serialize(),
1091            ],
1092            Direction::Receiving => [
1093                agreement,
1094                their_key.serialize(),
1095                our_keys.public_key.serialize(),
1096            ],
1097        }
1098        .concat();
1099
1100        let mut result = [0; MESSAGE_KEY_LEN];
1101        hkdf::Hkdf::<sha2::Sha256>::new(None, &agreement_key_input)
1102            .expand(LABEL_DH, &mut result)
1103            .expect("valid output length");
1104        result
1105            .iter_mut()
1106            .zip(input)
1107            .for_each(|(result_byte, input_byte)| *result_byte ^= input_byte);
1108        Ok(result)
1109    }
1110
1111    /// Compute an [authentication tag] for the bytes `encrypted_message_key` using a shared secret
1112    /// derived from `our_keys` and `their_key`.
1113    ///
1114    /// [authentication tag]: https://en.wikipedia.org/wiki/Message_authentication_code
1115    ///
1116    /// The output of this method with [`Direction::Sending`] should be the same bytes produced by
1117    /// calling this method with [`Direction::Receiving`] with `our_keys` and `their_key`
1118    /// swapped, if `ephemeral_pub_key` and `encrypted_message_key` are the same.
1119    pub(super) fn compute_authentication_tag(
1120        our_keys: &IdentityKeyPair,
1121        their_key: &IdentityKey,
1122        direction: Direction,
1123        ephemeral_pub_key: &PublicKey,
1124        encrypted_message_key: &[u8; MESSAGE_KEY_LEN],
1125    ) -> Result<[u8; AUTH_TAG_LEN]> {
1126        let agreement = our_keys
1127            .private_key()
1128            .calculate_agreement(their_key.public_key())?;
1129        let mut agreement_key_input = agreement.into_vec();
1130        agreement_key_input.extend_from_slice(&ephemeral_pub_key.serialize());
1131        agreement_key_input.extend_from_slice(encrypted_message_key);
1132        match direction {
1133            Direction::Sending => {
1134                agreement_key_input.extend_from_slice(&our_keys.public_key().serialize());
1135                agreement_key_input.extend_from_slice(&their_key.serialize());
1136            }
1137            Direction::Receiving => {
1138                agreement_key_input.extend_from_slice(&their_key.serialize());
1139                agreement_key_input.extend_from_slice(&our_keys.public_key().serialize());
1140            }
1141        }
1142
1143        let mut result = [0; AUTH_TAG_LEN];
1144        hkdf::Hkdf::<sha2::Sha256>::new(None, &agreement_key_input)
1145            .expand(LABEL_DH_S, &mut result)
1146            .expect("valid output length");
1147        Ok(result)
1148    }
1149
1150    #[test]
1151    fn test_agreement_and_authentication() -> Result<()> {
1152        // The sender and recipient each have a long-term identity key pair.
1153        let sender_identity = IdentityKeyPair::generate(&mut rand::rng());
1154        let recipient_identity = IdentityKeyPair::generate(&mut rand::rng());
1155
1156        // Generate random bytes used for our multi-recipient encoding scheme.
1157        let m: [u8; MESSAGE_KEY_LEN] = rand::rng().random();
1158        // Derive an ephemeral key pair from those random bytes.
1159        let ephemeral_keys = DerivedKeys::new(&m);
1160        let e = ephemeral_keys.derive_e();
1161
1162        // Encrypt the ephemeral key pair.
1163        let sender_c_0: [u8; MESSAGE_KEY_LEN] =
1164            apply_agreement_xor(&e, recipient_identity.public_key(), Direction::Sending, &m)?;
1165        // Compute an authentication tag for the encrypted key pair.
1166        let sender_at_0 = compute_authentication_tag(
1167            &sender_identity,
1168            recipient_identity.identity_key(),
1169            Direction::Sending,
1170            &e.public_key,
1171            &sender_c_0,
1172        )?;
1173
1174        // The message recipient calculates the original random bytes and authenticates the result.
1175        let recv_m = apply_agreement_xor(
1176            &recipient_identity.into(),
1177            &e.public_key,
1178            Direction::Receiving,
1179            &sender_c_0,
1180        )?;
1181        assert_eq!(&recv_m, &m);
1182
1183        let recv_at_0 = compute_authentication_tag(
1184            &recipient_identity,
1185            sender_identity.identity_key(),
1186            Direction::Receiving,
1187            &e.public_key,
1188            &sender_c_0,
1189        )?;
1190        assert_eq!(&recv_at_0, &sender_at_0);
1191
1192        Ok(())
1193    }
1194}
1195
1196/// This method implements a single-key multi-recipient [KEM] as defined in Manuel Barbosa's
1197/// ["Randomness Reuse: Extensions and Improvements"], a.k.a. Sealed Sender v2.
1198///
1199/// [KEM]: https://en.wikipedia.org/wiki/Key_encapsulation
1200/// ["Randomness Reuse: Extensions and Improvements"]: https://haslab.uminho.pt/mbb/files/reuse.pdf
1201///
1202/// # Contrast with Sealed Sender v1
1203/// The KEM scheme implemented by this method uses the "Generic Construction" in `4.1` of [Barbosa's
1204/// paper]["Randomness Reuse: Extensions and Improvements"], instantiated with [ElGamal encryption].
1205/// This technique enables reusing a single sequence of random bytes across multiple messages with
1206/// the same content, which reduces computation time for clients sending the same message to
1207/// multiple recipients (without compromising the message security).
1208///
1209/// There are a few additional design tradeoffs this method makes vs [Sealed Sender v1] which may
1210/// make it comparatively unwieldy for certain scenarios:
1211/// 1. it requires a [`SessionRecord`] to exist already for the recipient, i.e. that a Double
1212///    Ratchet message chain has previously been established in the [`SessionStore`] via
1213///    [`process_prekey_bundle`][crate::process_prekey_bundle] after an initial
1214///    [`PreKeySignalMessage`] is received.
1215/// 2. it ferries a lot of additional information in its encoding which makes the resulting message
1216///    bulkier than the message produced by [Sealed Sender v1]. For sending, this will generally
1217///    still be more compact than sending the same message N times, but on the receiver side the
1218///    message is slightly larger.
1219/// 3. unlike other message types sent over the wire, the encoded message returned by this method
1220///    does not use protobuf, in order to avoid inefficiencies produced by protobuf's packing (see
1221///    **[Wire Format]**).
1222///
1223/// [ElGamal encryption]: https://en.wikipedia.org/wiki/ElGamal_encryption
1224/// [Sealed Sender v1]: sealed_sender_encrypt_from_usmc
1225/// [Wire Format]: #wire-format
1226///
1227/// # High-level algorithmic overview
1228/// The high-level steps of this process are summarized below:
1229/// 1. Generate a series of random bytes.
1230/// 2. Derive an ephemeral key pair from (1).
1231/// 3. *Once per recipient:* Encrypt (1) using a shared secret derived from the private ephemeral
1232///    key (2) and the recipient's public identity key.
1233/// 4. *Once per recipient:* Add an authentication tag for (3) using a secret derived from the
1234///    sender's private identity key and the recipient's public identity key.
1235/// 5. Generate a symmetric key from (1) and use it to symmetrically encrypt the underlying
1236///    [`UnidentifiedSenderMessageContent`] via [AEAD encryption]. *This step is only performed once
1237///    per message, regardless of the number of recipients.*
1238/// 6. Send the public ephemeral key (2) to the server, along with the sequence of encrypted random
1239///    bytes (3) and authentication tags (4), and the single encrypted message (5).
1240///
1241/// [AEAD encryption]:
1242///    https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data_(AEAD)
1243///
1244/// ## Pseudocode
1245///```text
1246/// ENCRYPT(message, R_i):
1247///     M = Random(32)
1248///     r = KDF(label_r, M, len=32)
1249///     K = KDF(label_K, M, len=32)
1250///     E = DeriveKeyPair(r)
1251///     for i in num_recipients:
1252///         C_i = KDF(label_DH, DH(E, R_i) || E.public || R_i.public, len=32) XOR M
1253///         AT_i = KDF(label_DH_s, DH(S, R_i) || E.public || C_i || S.public || R_i.public, len=16)
1254///     ciphertext = AEAD_Encrypt(K, message)
1255///     return E.public, C_i, AT_i, ciphertext
1256///
1257/// DECRYPT(E.public, C, AT, ciphertext):
1258///     M = KDF(label_DH, DH(E, R) || E.public || R.public, len=32) xor C
1259///     r = KDF(label_r, M, len=32)
1260///     K = KDF(label_K, M, len=32)
1261///     E' = DeriveKeyPair(r)
1262///     if E.public != E'.public:
1263///         return DecryptionError
1264///     message = AEAD_Decrypt(K, ciphertext) // includes S.public
1265///     AT' = KDF(label_DH_s, DH(S, R) || E.public || C || S.public || R.public, len=16)
1266///     if AT != AT':
1267///         return DecryptionError
1268///     return message
1269///```
1270///
1271/// # Routing messages to recipients
1272///
1273/// The server will split up the set of messages and securely route each individual [received
1274/// message][receiving] to its intended recipient. [`SealedSenderV2SentMessage`] can perform this
1275/// fan-out operation.
1276///
1277/// # Wire Format
1278/// Multi-recipient sealed-sender does not use protobufs for its payload format. Instead, it uses a
1279/// flat format marked with a [version byte](#the-version-byte). The format is different for
1280/// [sending] and [receiving]. The decrypted content is a protobuf-encoded
1281/// `UnidentifiedSenderMessage.Message` from `sealed_sender.proto`.
1282///
1283/// The public key used in Sealed Sender v2 is always a Curve25519 DJB key.
1284///
1285/// [sending]: #sent-messages
1286/// [receiving]: #received-messages
1287///
1288/// ## The version byte
1289///
1290/// Sealed sender messages (v1 and v2) in serialized form begin with a version [byte][u8]. This byte
1291/// has the form:
1292///
1293/// ```text
1294/// (requiredVersion << 4) | currentVersion
1295/// ```
1296///
1297/// v1 messages thus have a version byte of `0x11`. v2 messages have a version byte of `0x22` or
1298/// `0x23`. A hypothetical version byte `0x34` would indicate a message encoded as Sealed Sender v4,
1299/// but decodable by any client that supports Sealed Sender v3.
1300///
1301/// ## Received messages
1302///
1303/// ```text
1304/// ReceivedMessage {
1305///     version_byte: u8,
1306///     c: [u8; 32],
1307///     at: [u8; 16],
1308///     e_pub: [u8; 32],
1309///     message: [u8] // remaining bytes
1310/// }
1311/// ```
1312///
1313/// Each individual Sealed Sender message received from the server is decoded in the Signal client
1314/// by calling [`sealed_sender_decrypt`].
1315///
1316/// ## Sent messages
1317///
1318/// ```text
1319/// SentMessage {
1320///     version_byte: u8,
1321///     count: varint,
1322///     recipients: [PerRecipientData | ExcludedRecipient; count],
1323///     e_pub: [u8; 32],
1324///     message: [u8] // remaining bytes
1325/// }
1326///
1327/// PerRecipientData {
1328///     recipient: Recipient,
1329///     devices: [DeviceList], // last element's has_more = 0
1330///     c: [u8; 32],
1331///     at: [u8; 16],
1332/// }
1333///
1334/// ExcludedRecipient {
1335///     recipient: Recipient,
1336///     no_devices_marker: u8 = 0, // never a valid device ID
1337/// }
1338///
1339/// DeviceList {
1340///     device_id: u8,
1341///     has_more: u1, // high bit of following field
1342///     unused: u1,   // high bit of following field
1343///     registration_id: u14,
1344/// }
1345///
1346/// Recipient {
1347///     service_id_fixed_width_binary: [u8; 17],
1348/// }
1349/// ```
1350///
1351/// The varint encoding used is the same as [protobuf's][varint]. Values are unsigned.
1352/// Fixed-width-binary encoding is used for the [ServiceId] values.
1353/// Fixed-width integers are unaligned and in network byte order (big-endian).
1354///
1355/// [varint]: https://developers.google.com/protocol-buffers/docs/encoding#varints
1356pub async fn sealed_sender_multi_recipient_encrypt<
1357    R: Rng + CryptoRng,
1358    X: IntoIterator<Item = ServiceId>,
1359>(
1360    destinations: &[&ProtocolAddress],
1361    destination_sessions: &[&SessionRecord],
1362    excluded_recipients: X,
1363    usmc: &UnidentifiedSenderMessageContent,
1364    identity_store: &dyn IdentityKeyStore,
1365    rng: &mut R,
1366) -> Result<Vec<u8>>
1367where
1368    X::IntoIter: ExactSizeIterator,
1369{
1370    sealed_sender_multi_recipient_encrypt_impl(
1371        destinations,
1372        destination_sessions,
1373        excluded_recipients,
1374        usmc,
1375        identity_store,
1376        rng,
1377    )
1378    .await
1379}
1380
1381async fn sealed_sender_multi_recipient_encrypt_impl<
1382    R: Rng + CryptoRng,
1383    X: IntoIterator<Item = ServiceId>,
1384>(
1385    destinations: &[&ProtocolAddress],
1386    destination_sessions: &[&SessionRecord],
1387    excluded_recipients: X,
1388    usmc: &UnidentifiedSenderMessageContent,
1389    identity_store: &dyn IdentityKeyStore,
1390    rng: &mut R,
1391) -> Result<Vec<u8>>
1392where
1393    X::IntoIter: ExactSizeIterator,
1394{
1395    if destinations.len() != destination_sessions.len() {
1396        return Err(SignalProtocolError::InvalidArgument(
1397            "must have the same number of destination sessions as addresses".to_string(),
1398        ));
1399    }
1400
1401    let excluded_recipients = excluded_recipients.into_iter();
1402    let our_identity = identity_store.get_identity_key_pair().await?;
1403
1404    let m: [u8; sealed_sender_v2::MESSAGE_KEY_LEN] = rng.random();
1405    let keys = sealed_sender_v2::DerivedKeys::new(&m);
1406    let e = keys.derive_e();
1407    let e_pub = &e.public_key;
1408
1409    // Encrypt the shared ciphertext using AES-GCM-SIV.
1410    let ciphertext = {
1411        let mut ciphertext = usmc.serialized()?.to_vec();
1412        let symmetric_authentication_tag = Aes256GcmSiv::new(&keys.derive_k().into())
1413            .encrypt_in_place_detached(
1414                // There's no nonce because the key is already one-use.
1415                &aes_gcm_siv::Nonce::default(),
1416                // And there's no associated data.
1417                &[],
1418                &mut ciphertext,
1419            )
1420            .expect("AES-GCM-SIV encryption should not fail with a just-computed key");
1421        // AES-GCM-SIV expects the authentication tag to be at the end of the ciphertext
1422        // when decrypting.
1423        ciphertext.extend_from_slice(&symmetric_authentication_tag);
1424        ciphertext
1425    };
1426
1427    // Group the destinations by name, and fetch identity keys once for each name. This optimizes
1428    // for the common case where all of a recipient's devices are included contiguously in the
1429    // destination list. (If the caller *doesn't* do this, that's on them; the message will still be
1430    // valid but some key material will be redundantly computed and encoded in the output.)
1431    let identity_keys_and_ranges: Vec<(IdentityKey, Range<usize>)> = {
1432        let mut identity_keys_and_ranges = vec![];
1433        for (_, mut next_group) in &destinations
1434            .iter()
1435            .enumerate()
1436            .chunk_by(|(_i, next)| next.name())
1437        {
1438            let (i, &destination) = next_group
1439                .next()
1440                .expect("at least one element in every group");
1441            // We can't put this before the call to `next()` because `count` consumes the rest of
1442            // the iterator.
1443            let count = 1 + next_group.count();
1444            let their_identity =
1445                identity_store
1446                    .get_identity(destination)
1447                    .await?
1448                    .ok_or_else(|| {
1449                        log::error!("missing identity key for {destination}");
1450                        // Returned as a SessionNotFound error because (a) we don't have an identity
1451                        // error that includes the address, and (b) re-establishing the session should
1452                        // re-fetch the identity.
1453                        SignalProtocolError::SessionNotFound(destination.clone())
1454                    })?;
1455            identity_keys_and_ranges.push((their_identity, i..i + count));
1456        }
1457        identity_keys_and_ranges
1458    };
1459
1460    // Next, fan out the work of generating the per-recipient to multiple cores, since we do two key
1461    // agreements per recipient (though not per device) and those are CPU-bound.
1462
1463    // I know this looks complicated enough to pull out into a separate function altogether, but it
1464    // also depends on a bunch of local state: our identity, E and E_pub, and M.
1465    let serialize_recipient_destinations_into = |serialized: &mut Vec<u8>,
1466                                                 destinations: &[&ProtocolAddress],
1467                                                 sessions: &[&SessionRecord],
1468                                                 their_identity: &IdentityKey|
1469     -> Result<()> {
1470        let their_service_id = ServiceId::parse_from_service_id_string(destinations[0].name())
1471            .ok_or_else(|| {
1472                SignalProtocolError::InvalidArgument(format!(
1473                    "multi-recipient sealed sender requires recipients' ServiceId (not {})",
1474                    destinations[0].name()
1475                ))
1476            })?;
1477
1478        serialized.extend_from_slice(&their_service_id.service_id_fixed_width_binary());
1479
1480        debug_assert_eq!(
1481            destinations.len(),
1482            sessions.len(),
1483            "should be sliced with the same range"
1484        );
1485        let mut destinations_and_sessions = destinations.iter().zip(sessions);
1486        while let Some((&destination, session)) = destinations_and_sessions.next() {
1487            let their_registration_id = session.remote_registration_id().map_err(|_| {
1488                SignalProtocolError::InvalidState(
1489                    "sealed_sender_multi_recipient_encrypt",
1490                    format!(
1491                        concat!(
1492                            "cannot get registration ID from session with {} ",
1493                            "(maybe it was recently archived)"
1494                        ),
1495                        destination
1496                    ),
1497                )
1498            })?;
1499            if their_registration_id & u32::from(VALID_REGISTRATION_ID_MASK)
1500                != their_registration_id
1501            {
1502                return Err(SignalProtocolError::InvalidRegistrationId(
1503                    destination.clone(),
1504                    their_registration_id,
1505                ));
1506            }
1507            let mut their_registration_id =
1508                u16::try_from(their_registration_id).expect("just checked range");
1509            if destinations_and_sessions.len() > 0 {
1510                their_registration_id |= 0x8000;
1511            }
1512
1513            let device_id = destination.device_id();
1514            serialized.push(device_id.into());
1515            serialized.extend_from_slice(&their_registration_id.to_be_bytes());
1516        }
1517
1518        let c_i = sealed_sender_v2::apply_agreement_xor(
1519            &e,
1520            their_identity.public_key(),
1521            Direction::Sending,
1522            &m,
1523        )?;
1524        serialized.extend_from_slice(&c_i);
1525
1526        let at_i = sealed_sender_v2::compute_authentication_tag(
1527            &our_identity,
1528            their_identity,
1529            Direction::Sending,
1530            e_pub,
1531            &c_i,
1532        )?;
1533        serialized.extend_from_slice(&at_i);
1534
1535        Ok(())
1536    };
1537
1538    let process_chunk =
1539        |serialized: &mut Vec<u8>, chunk: &[(IdentityKey, Range<usize>)]| -> Result<()> {
1540            for (their_identity, destination_range) in chunk {
1541                let these_destinations = &destinations[destination_range.clone()];
1542                let these_sessions = &destination_sessions[destination_range.clone()];
1543                serialize_recipient_destinations_into(
1544                    serialized,
1545                    these_destinations,
1546                    these_sessions,
1547                    their_identity,
1548                )?;
1549            }
1550            Ok(())
1551        };
1552
1553    let mut serialized: Vec<u8> = vec![SEALED_SENDER_V2_SERVICE_ID_FULL_VERSION];
1554
1555    let count_of_recipients = identity_keys_and_ranges.len() + excluded_recipients.len();
1556    prost::encode_length_delimiter(count_of_recipients, &mut serialized)
1557        .expect("can always resize a Vec");
1558
1559    // Fan out to N threads, like Rayon would. But don't bother for less than 6 items.
1560    let parallelism = std::thread::available_parallelism()
1561        .map(usize::from)
1562        .unwrap_or(1);
1563    let chunk_size = std::cmp::max(6, identity_keys_and_ranges.len().div_ceil(parallelism));
1564
1565    if parallelism == 1 || chunk_size >= identity_keys_and_ranges.len() {
1566        process_chunk(&mut serialized, &identity_keys_and_ranges)?;
1567    } else {
1568        let mut chunks = identity_keys_and_ranges.chunks(chunk_size);
1569        // We'll process the first chunk on the current thread once we've spawned all the others.
1570        let first_chunk = chunks.next().expect("at least one chunk, tested above");
1571
1572        let mut all_outputs = Vec::new();
1573        all_outputs.resize_with(chunks.len(), || Ok(vec![]));
1574
1575        rayon::scope(|scope| -> Result<()> {
1576            let mut outputs = &mut all_outputs[..];
1577            for chunk in chunks {
1578                let (next_output, remaining_outputs) = outputs
1579                    .split_first_mut()
1580                    .expect("as many outputs as remaining chunks");
1581                scope.spawn(|_| {
1582                    let mut serialized = vec![];
1583                    *next_output = process_chunk(&mut serialized, chunk).map(|_| serialized);
1584                });
1585                outputs = remaining_outputs;
1586            }
1587
1588            process_chunk(&mut serialized, first_chunk)
1589        })?;
1590
1591        for output in all_outputs {
1592            serialized.extend(output?);
1593        }
1594    }
1595
1596    for excluded in excluded_recipients {
1597        serialized.extend_from_slice(&excluded.service_id_fixed_width_binary());
1598        serialized.push(0);
1599    }
1600
1601    serialized.extend_from_slice(e_pub.public_key_bytes());
1602    serialized.extend_from_slice(&ciphertext);
1603
1604    Ok(serialized)
1605}
1606
1607/// Represents a single recipient in an SSv2 SentMessage.
1608///
1609/// See [`SealedSenderV2SentMessage`].
1610pub struct SealedSenderV2SentMessageRecipient<'a> {
1611    /// The recipient's devices and their registration IDs. May be empty.
1612    pub devices: Vec<(DeviceId, u16)>,
1613    /// A concatenation of the `C_i` and `AT_i` SSv2 fields for this recipient, or an empty slice if
1614    /// the recipient has no devices.
1615    c_and_at: &'a [u8],
1616}
1617
1618/// A parsed representation of a Sealed Sender v2 SentMessage.
1619///
1620/// This only parses enough to fan out the message as a series of ReceivedMessages.
1621pub struct SealedSenderV2SentMessage<'a> {
1622    /// The full message, for calculating offsets.
1623    full_message: &'a [u8],
1624    /// The version byte at the head of the message.
1625    pub version: u8,
1626    /// The parsed list of recipients, grouped by ServiceId.
1627    ///
1628    /// The map is ordered by when a recipient first appears in the full message, even if they
1629    /// appear again later with more devices. This makes iteration over the full set of recipients
1630    /// deterministic.
1631    pub recipients: IndexMap<ServiceId, SealedSenderV2SentMessageRecipient<'a>>,
1632    /// A concatenation of the `e_pub` and `message` SSv2 fields for this recipient.
1633    shared_bytes: &'a [u8],
1634}
1635
1636impl<'a> SealedSenderV2SentMessage<'a> {
1637    /// Parses the message, or produces an error if the message is invalid.
1638    pub fn parse(data: &'a [u8]) -> Result<Self> {
1639        if data.is_empty() {
1640            return Err(SignalProtocolError::InvalidSealedSenderMessage(
1641                "Message was empty".to_owned(),
1642            ));
1643        }
1644
1645        let version = data[0];
1646        if !matches!(
1647            version,
1648            SEALED_SENDER_V2_UUID_FULL_VERSION | SEALED_SENDER_V2_SERVICE_ID_FULL_VERSION
1649        ) {
1650            return Err(SignalProtocolError::UnknownSealedSenderVersion(version));
1651        }
1652
1653        fn advance<'a, const N: usize>(buf: &mut &'a [u8]) -> Result<&'a [u8; N]> {
1654            let (prefix, remaining) = buf
1655                .split_first_chunk()
1656                .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
1657            *buf = remaining;
1658            Ok(prefix)
1659        }
1660        fn decode_varint(buf: &mut &[u8]) -> Result<u32> {
1661            let result: usize = prost::decode_length_delimiter(*buf)
1662                .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
1663            *buf = &buf[prost::length_delimiter_len(result)..];
1664            result
1665                .try_into()
1666                .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)
1667        }
1668
1669        let mut remaining = &data[1..];
1670        let recipient_count = decode_varint(&mut remaining)?
1671            .try_into()
1672            .unwrap_or(usize::MAX);
1673
1674        // Cap our preallocated capacity; anything higher than this is *probably* a mistake, but
1675        // could just be a very large message.
1676        // (Callers can of course refuse to process messages with too many recipients.)
1677        let mut recipients: IndexMap<ServiceId, SealedSenderV2SentMessageRecipient<'a>> =
1678            IndexMap::with_capacity(std::cmp::min(recipient_count as usize, 6000));
1679        for _ in 0..recipient_count {
1680            let service_id = if version == SEALED_SENDER_V2_UUID_FULL_VERSION {
1681                // The original version of SSv2 assumed ACIs here, and only encoded the raw UUID.
1682                ServiceId::from(Aci::from_uuid_bytes(*advance::<
1683                    { std::mem::size_of::<uuid::Bytes>() },
1684                >(&mut remaining)?))
1685            } else {
1686                ServiceId::parse_from_service_id_fixed_width_binary(advance::<
1687                    { std::mem::size_of::<ServiceIdFixedWidthBinaryBytes>() },
1688                >(
1689                    &mut remaining
1690                )?)
1691                .ok_or(SignalProtocolError::InvalidProtobufEncoding)?
1692            };
1693            let mut devices = Vec::new();
1694            loop {
1695                let device_id = advance::<1>(&mut remaining)?[0];
1696                if device_id == 0 {
1697                    if !devices.is_empty() {
1698                        return Err(SignalProtocolError::InvalidProtobufEncoding);
1699                    }
1700                    break;
1701                }
1702                let device_id = DeviceId::new(device_id)
1703                    .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
1704                let registration_id_and_has_more =
1705                    u16::from_be_bytes(*advance::<2>(&mut remaining)?);
1706                devices.push((
1707                    device_id,
1708                    registration_id_and_has_more & VALID_REGISTRATION_ID_MASK,
1709                ));
1710                let has_more = (registration_id_and_has_more & 0x8000) != 0;
1711                if !has_more {
1712                    break;
1713                }
1714            }
1715
1716            let c_and_at: &[u8] = if devices.is_empty() {
1717                &[]
1718            } else {
1719                advance::<{ sealed_sender_v2::MESSAGE_KEY_LEN + sealed_sender_v2::AUTH_TAG_LEN }>(
1720                    &mut remaining,
1721                )?
1722            };
1723
1724            match recipients.entry(service_id) {
1725                indexmap::map::Entry::Occupied(mut existing) => {
1726                    if existing.get().devices.is_empty() || devices.is_empty() {
1727                        return Err(SignalProtocolError::InvalidSealedSenderMessage(
1728                            "recipient redundantly encoded as empty".to_owned(),
1729                        ));
1730                    }
1731                    // We don't unique the recipient devices; the server is going to check this
1732                    // against the account's canonical list of devices anyway.
1733                    existing.get_mut().devices.extend(devices);
1734                    // Note that we don't check that c_and_at matches. Any case where it doesn't
1735                    // match would already result in a decryption error for at least one of the
1736                    // recipient's devices, though.
1737                }
1738                indexmap::map::Entry::Vacant(entry) => {
1739                    entry.insert(SealedSenderV2SentMessageRecipient { devices, c_and_at });
1740                }
1741            };
1742        }
1743
1744        if remaining.len() < sealed_sender_v2::PUBLIC_KEY_LEN {
1745            return Err(SignalProtocolError::InvalidProtobufEncoding);
1746        }
1747
1748        Ok(Self {
1749            full_message: data,
1750            version,
1751            recipients,
1752            shared_bytes: remaining,
1753        })
1754    }
1755
1756    /// Returns a slice of slices that, when concatenated, form the ReceivedMessage appropriate for
1757    /// `recipient`.
1758    ///
1759    /// If `recipient` is not one of the recipients in `self`, the resulting message will not be
1760    /// decryptable.
1761    #[inline]
1762    pub fn received_message_parts_for_recipient(
1763        &self,
1764        recipient: &SealedSenderV2SentMessageRecipient<'a>,
1765    ) -> impl AsRef<[&[u8]]> {
1766        // Why not use `IntoIterator<Item = &[u8]>` as the result? Because the `concat` method on
1767        // slices is more efficient when the caller just wants a `Vec<u8>`.
1768        // Why use SEALED_SENDER_V2_UUID_FULL_VERSION as the version? Because the ReceivedMessage
1769        // format hasn't changed since then.
1770        [
1771            &[SEALED_SENDER_V2_UUID_FULL_VERSION],
1772            recipient.c_and_at,
1773            self.shared_bytes,
1774        ]
1775    }
1776
1777    /// Returns the offset of `addr` within `self.full_message`, or `None` if `addr` does not lie
1778    /// within `self.full_message`.
1779    ///
1780    /// A stripped-down version of [a dormant Rust RFC][subslice-offset].
1781    ///
1782    /// [subslice-offset]: https://github.com/rust-lang/rfcs/pull/2796
1783    #[inline]
1784    fn offset_within_full_message(&self, addr: *const u8) -> Option<usize> {
1785        // Arithmetic on addresses is valid for offsets within a byte array.
1786        // If addr < start, we'll wrap around to a very large value, which will be out of range just
1787        // like if addr > end.
1788        let offset = (addr as usize).wrapping_sub(self.full_message.as_ptr() as usize);
1789        // We *do* want to allow the "one-past-the-end" offset here, because the offset might be
1790        // used as part of a range (e.g. 0..end).
1791        if offset <= self.full_message.len() {
1792            debug_assert!(
1793                offset == self.full_message.len() || std::ptr::eq(&self.full_message[offset], addr)
1794            );
1795            Some(offset)
1796        } else {
1797            None
1798        }
1799    }
1800
1801    /// Returns the range within the full message of `recipient`'s user-specific key material.
1802    ///
1803    /// This can be concatenated as `[version, recipient_key_material, shared_bytes]` to produce a
1804    /// valid SSv2 ReceivedMessage, the payload delivered to recipients.
1805    ///
1806    /// **Panics** if `recipient` is not one of the recipients in `self`.
1807    pub fn range_for_recipient_key_material(
1808        &self,
1809        recipient: &SealedSenderV2SentMessageRecipient<'a>,
1810    ) -> Range<usize> {
1811        if recipient.c_and_at.is_empty() {
1812            return 0..0;
1813        }
1814        let offset = self
1815            .offset_within_full_message(recipient.c_and_at.as_ptr())
1816            .expect("'recipient' is not one of the recipients in this SealedSenderV2SentMessage");
1817        let end_offset = offset.saturating_add(recipient.c_and_at.len());
1818        assert!(
1819            end_offset <= self.full_message.len(),
1820            "invalid 'recipient' passed to range_for_recipient_key_material"
1821        );
1822        offset..end_offset
1823    }
1824
1825    /// Returns the offset of the shared bytes within the full message.
1826    ///
1827    /// This can be concatenated as `[version, recipient_key_material, shared_bytes]` to produce a
1828    /// valid SSv2 ReceivedMessage, the payload delivered to recipients.
1829    pub fn offset_of_shared_bytes(&self) -> usize {
1830        debug_assert_eq!(
1831            self.full_message.as_ptr_range().end,
1832            self.shared_bytes.as_ptr_range().end,
1833            "SealedSenderV2SentMessage parsed incorrectly"
1834        );
1835        self.offset_within_full_message(self.shared_bytes.as_ptr())
1836            .expect("constructed correctly")
1837    }
1838}
1839
1840/// Decrypt the payload of a sealed-sender message in either the v1 or v2 format.
1841///
1842/// [`sealed_sender_decrypt`] consumes the output of this method to validate the sender's identity
1843/// before decrypting the underlying message.
1844pub async fn sealed_sender_decrypt_to_usmc(
1845    ciphertext: &[u8],
1846    identity_store: &dyn IdentityKeyStore,
1847) -> Result<UnidentifiedSenderMessageContent> {
1848    let our_identity = identity_store.get_identity_key_pair().await?;
1849
1850    match UnidentifiedSenderMessage::deserialize(ciphertext)? {
1851        UnidentifiedSenderMessage::V1 {
1852            ephemeral_public,
1853            encrypted_static,
1854            encrypted_message,
1855        } => {
1856            let eph_keys = sealed_sender_v1::EphemeralKeys::calculate(
1857                &our_identity.into(),
1858                &ephemeral_public,
1859                Direction::Receiving,
1860            )?;
1861
1862            let message_key_bytes = match crypto::aes256_ctr_hmacsha256_decrypt(
1863                &encrypted_static,
1864                &eph_keys.cipher_key,
1865                &eph_keys.mac_key,
1866            ) {
1867                Ok(plaintext) => plaintext,
1868                Err(crypto::DecryptionError::BadKeyOrIv) => {
1869                    unreachable!("just derived these keys; they should be valid");
1870                }
1871                Err(crypto::DecryptionError::BadCiphertext(msg)) => {
1872                    log::error!("failed to decrypt sealed sender v1 message key: {msg}");
1873                    return Err(SignalProtocolError::InvalidSealedSenderMessage(
1874                        "failed to decrypt sealed sender v1 message key".to_owned(),
1875                    ));
1876                }
1877            };
1878
1879            let static_key = PublicKey::try_from(&message_key_bytes[..])?;
1880
1881            let static_keys = sealed_sender_v1::StaticKeys::calculate(
1882                &our_identity,
1883                &static_key,
1884                &eph_keys.chain_key,
1885                &encrypted_static,
1886            )?;
1887
1888            let message_bytes = match crypto::aes256_ctr_hmacsha256_decrypt(
1889                &encrypted_message,
1890                &static_keys.cipher_key,
1891                &static_keys.mac_key,
1892            ) {
1893                Ok(plaintext) => plaintext,
1894                Err(crypto::DecryptionError::BadKeyOrIv) => {
1895                    unreachable!("just derived these keys; they should be valid");
1896                }
1897                Err(crypto::DecryptionError::BadCiphertext(msg)) => {
1898                    log::error!("failed to decrypt sealed sender v1 message contents: {msg}");
1899                    return Err(SignalProtocolError::InvalidSealedSenderMessage(
1900                        "failed to decrypt sealed sender v1 message contents".to_owned(),
1901                    ));
1902                }
1903            };
1904
1905            let usmc = UnidentifiedSenderMessageContent::deserialize(&message_bytes)?;
1906
1907            if !bool::from(message_key_bytes.ct_eq(&usmc.sender()?.key()?.serialize())) {
1908                return Err(SignalProtocolError::InvalidSealedSenderMessage(
1909                    "sender certificate key does not match message key".to_string(),
1910                ));
1911            }
1912
1913            Ok(usmc)
1914        }
1915        UnidentifiedSenderMessage::V2 {
1916            ephemeral_public,
1917            encrypted_message_key,
1918            authentication_tag,
1919            encrypted_message,
1920        } => {
1921            let m = sealed_sender_v2::apply_agreement_xor(
1922                &our_identity.into(),
1923                &ephemeral_public,
1924                Direction::Receiving,
1925                encrypted_message_key,
1926            )?;
1927
1928            let keys = sealed_sender_v2::DerivedKeys::new(&m);
1929            if !bool::from(keys.derive_e().public_key.ct_eq(&ephemeral_public)) {
1930                return Err(SignalProtocolError::InvalidSealedSenderMessage(
1931                    "derived ephemeral key did not match key provided in message".to_string(),
1932                ));
1933            }
1934
1935            let mut message_bytes = Vec::from(encrypted_message);
1936            Aes256GcmSiv::new(&keys.derive_k().into())
1937                .decrypt_in_place(
1938                    // There's no nonce because the key is already one-use.
1939                    &aes_gcm_siv::Nonce::default(),
1940                    // And there's no associated data.
1941                    &[],
1942                    &mut message_bytes,
1943                )
1944                .map_err(|err| {
1945                    SignalProtocolError::InvalidSealedSenderMessage(format!(
1946                        "failed to decrypt inner message: {err}"
1947                    ))
1948                })?;
1949
1950            let usmc = UnidentifiedSenderMessageContent::deserialize(&message_bytes)?;
1951
1952            let at = sealed_sender_v2::compute_authentication_tag(
1953                &our_identity,
1954                &usmc.sender()?.key()?.into(),
1955                Direction::Receiving,
1956                &ephemeral_public,
1957                encrypted_message_key,
1958            )?;
1959            if !bool::from(authentication_tag.ct_eq(&at)) {
1960                return Err(SignalProtocolError::InvalidSealedSenderMessage(
1961                    "sender certificate key does not match authentication tag".to_string(),
1962                ));
1963            }
1964
1965            Ok(usmc)
1966        }
1967    }
1968}
1969
1970#[derive(Debug)]
1971pub struct SealedSenderDecryptionResult {
1972    pub sender_uuid: String,
1973    pub sender_e164: Option<String>,
1974    pub device_id: DeviceId,
1975    pub message: Vec<u8>,
1976}
1977
1978impl SealedSenderDecryptionResult {
1979    pub fn sender_uuid(&self) -> Result<&str> {
1980        Ok(self.sender_uuid.as_ref())
1981    }
1982
1983    pub fn sender_e164(&self) -> Result<Option<&str>> {
1984        Ok(self.sender_e164.as_deref())
1985    }
1986
1987    pub fn device_id(&self) -> Result<DeviceId> {
1988        Ok(self.device_id)
1989    }
1990
1991    pub fn message(&self) -> Result<&[u8]> {
1992        Ok(self.message.as_ref())
1993    }
1994}
1995
1996/// Decrypt a Sealed Sender message `ciphertext` in either the v1 or v2 format, validate its sender
1997/// certificate, and then decrypt the inner message payload.
1998///
1999/// This method calls [`sealed_sender_decrypt_to_usmc`] to extract the sender information, including
2000/// the embedded [`SenderCertificate`]. The sender certificate (signed by the [`ServerCertificate`])
2001/// is then validated against the `trust_root` baked into the client to ensure that the sender's
2002/// identity was not forged.
2003#[expect(clippy::too_many_arguments)]
2004pub async fn sealed_sender_decrypt(
2005    ciphertext: &[u8],
2006    trust_root: &PublicKey,
2007    timestamp: Timestamp,
2008    local_e164: Option<String>,
2009    local_uuid: String,
2010    local_device_id: DeviceId,
2011    identity_store: &mut dyn IdentityKeyStore,
2012    session_store: &mut dyn SessionStore,
2013    pre_key_store: &mut dyn PreKeyStore,
2014    signed_pre_key_store: &dyn SignedPreKeyStore,
2015    kyber_pre_key_store: &mut dyn KyberPreKeyStore,
2016) -> Result<SealedSenderDecryptionResult> {
2017    let usmc = sealed_sender_decrypt_to_usmc(ciphertext, identity_store).await?;
2018
2019    if !usmc.sender()?.validate(trust_root, timestamp)? {
2020        return Err(SignalProtocolError::InvalidSealedSenderMessage(
2021            "trust root validation failed".to_string(),
2022        ));
2023    }
2024
2025    let is_local_uuid = local_uuid == usmc.sender()?.sender_uuid()?;
2026
2027    let is_local_e164 = match (local_e164, usmc.sender()?.sender_e164()?) {
2028        (Some(l), Some(s)) => l == s,
2029        (_, _) => false,
2030    };
2031
2032    if (is_local_e164 || is_local_uuid) && usmc.sender()?.sender_device_id()? == local_device_id {
2033        return Err(SignalProtocolError::SealedSenderSelfSend);
2034    }
2035
2036    let mut rng = rand::rngs::OsRng.unwrap_err();
2037
2038    let remote_address = ProtocolAddress::new(
2039        usmc.sender()?.sender_uuid()?.to_string(),
2040        usmc.sender()?.sender_device_id()?,
2041    );
2042    let local_address = ProtocolAddress::new(local_uuid, local_device_id);
2043
2044    let message = match usmc.msg_type()? {
2045        CiphertextMessageType::Whisper => {
2046            let ctext = SignalMessage::try_from(usmc.contents()?)?;
2047            session_cipher::message_decrypt_signal(
2048                &ctext,
2049                &remote_address,
2050                session_store,
2051                identity_store,
2052                &mut rng,
2053            )
2054            .await?
2055        }
2056        CiphertextMessageType::PreKey => {
2057            let ctext = PreKeySignalMessage::try_from(usmc.contents()?)?;
2058            session_cipher::message_decrypt_prekey(
2059                &ctext,
2060                &remote_address,
2061                &local_address,
2062                session_store,
2063                identity_store,
2064                pre_key_store,
2065                signed_pre_key_store,
2066                kyber_pre_key_store,
2067                &mut rng,
2068            )
2069            .await?
2070        }
2071        msg_type => {
2072            return Err(SignalProtocolError::InvalidMessage(
2073                msg_type,
2074                "unexpected message type for sealed_sender_decrypt",
2075            ));
2076        }
2077    };
2078
2079    Ok(SealedSenderDecryptionResult {
2080        sender_uuid: usmc.sender()?.sender_uuid()?.to_string(),
2081        sender_e164: usmc.sender()?.sender_e164()?.map(|s| s.to_string()),
2082        device_id: usmc.sender()?.sender_device_id()?,
2083        message,
2084    })
2085}
2086
2087#[test]
2088fn test_lossless_round_trip() -> Result<()> {
2089    let trust_root = PrivateKey::deserialize(&[0u8; 32])?;
2090
2091    // To test a hypothetical addition of a new field:
2092    //
2093    // Step 1: temporarily add a new field to the .proto.
2094    //
2095    //    --- a/rust/protocol/src/proto/sealed_sender.proto
2096    //    +++ b/rust/protocol/src/proto/sealed_sender.proto
2097    //    @@ -26,3 +26,4 @@ message SenderCertificate {
2098    //             optional bytes             identityKey   = 4;
2099    //             optional ServerCertificate signer        = 5;
2100    //    +        optional string someFakeField = 999;
2101    //     }
2102    //
2103    // Step 2: Add `some_fake_field: None` to the above construction of
2104    // proto::sealed_sender::sender_certificate::Certificate.
2105    //
2106    // Step 3: Serialize and print out the new fixture data (uncomment the following)
2107    //
2108    // let mut rng = rand::rngs::OsRng.unwrap_err();
2109    // let server_key = KeyPair::generate(&mut rng);
2110    // let sender_key = KeyPair::generate(&mut rng);
2111    //
2112    // let server_cert =
2113    //     ServerCertificate::new(1, server_key.public_key, &trust_root, &mut rng)?;
2114    //
2115    // let sender_cert = proto::sealed_sender::sender_certificate::Certificate {
2116    //     sender_uuid: Some(
2117    //         proto::sealed_sender::sender_certificate::certificate::SenderUuid::UuidString(
2118    //             "aaaaaaaa-7000-11eb-b32a-33b8a8a487a6".to_string(),
2119    //         ),
2120    //     ),
2121    //     sender_e164: None,
2122    //     sender_device: Some(1),
2123    //     expires: Some(31337),
2124    //     identity_key: Some(sender_key.public_key.serialize().to_vec()),
2125    //     signer: Some(
2126    //         proto::sealed_sender::sender_certificate::certificate::Signer::Certificate(
2127    //             server_cert.serialized()?.to_vec(),
2128    //         ),
2129    //     ),
2130    //     some_fake_field: Some("crashing right down".to_string()),
2131    // };
2132    //
2133    // eprintln!("<SNIP>");
2134    // let serialized_certificate_data = sender_cert.encode_to_vec();
2135    // let certificate_data_encoded = hex::encode(&serialized_certificate_data);
2136    // eprintln!("let certificate_data = const_str::hex!(\"{}\");", certificate_data_encoded);
2137    //
2138    // let certificate_signature = server_key.calculate_signature(&serialized_certificate_data, &mut rng)?;
2139    // let certificate_signature_encoded = hex::encode(certificate_signature);
2140    // eprintln!("let certificate_signature = const_str::hex!(\"{}\");", certificate_signature_encoded);
2141
2142    // Step 4: update the following fixture data with the new values from above.
2143    let certificate_data = const_str::hex!(
2144        "100119697a0000000000002221056c9d1f8deb82b9a898f9c277a1b74989ec009afb5c0acb5e8e69e3d5ca29d6322a690a2508011221053b03ca070e6f6b2f271d32f27321689cdf4e59b106c10b58fbe15063ed868a5a124024bc92954e52ad1a105b5bda85c9db410dcfeb42a671b45a523b3a46e9594a8bde0efc671d8e8e046b32c67f59b80a46ffdf24071850779bc21325107902af89322461616161616161612d373030302d313165622d623332612d333362386138613438376136ba3e136372617368696e6720726967687420646f776e"
2145    );
2146    let certificate_signature = const_str::hex!(
2147        "a22d8f86f5d00794f319add821e342c6ffffb6b34f741e569f8b321ab0255f2d1757ecf648e53a3602cae8f09b3fc80dcf27534d67efd272b6739afc31f75c8c"
2148    );
2149
2150    let sender_certificate_data = proto::sealed_sender::SenderCertificate {
2151        certificate: Some(certificate_data.to_vec()),
2152        signature: Some(certificate_signature.to_vec()),
2153    };
2154
2155    let sender_certificate =
2156        SenderCertificate::deserialize(&sender_certificate_data.encode_to_vec())?;
2157    assert_eq!(
2158        sender_certificate.sender_uuid().expect("valid"),
2159        "aaaaaaaa-7000-11eb-b32a-33b8a8a487a6",
2160    );
2161    assert_eq!(sender_certificate.sender_e164().expect("valid"), None);
2162    assert_eq!(
2163        sender_certificate.sender_device_id().expect("valid"),
2164        DeviceId::new(1).expect("valid"),
2165    );
2166    assert_eq!(
2167        sender_certificate
2168            .expiration()
2169            .expect("valid")
2170            .epoch_millis(),
2171        31337
2172    );
2173    assert!(sender_certificate.validate(
2174        &trust_root.public_key()?,
2175        Timestamp::from_epoch_millis(31336)
2176    )?);
2177    Ok(())
2178}
2179
2180#[test]
2181fn test_uuid_bytes_representation() -> Result<()> {
2182    let trust_root = PrivateKey::deserialize(&[0u8; 32])?;
2183
2184    // Same structure as above, but using the uuidBytes representation instead of uuidString.
2185    let certificate_data = const_str::hex!(
2186        "100119697a000000000000222105e083a8ce423d1c1955174107a85a6a7f3bcbf566723624077f75eafe8e0a07752a690a25080112210507a24397ae27d06fa76d2f02cfb5546e0b23a7e0c3670c1eb1e73b135a8e1e4d12407d127509ae1f5e9dcaa511793d3e94350dcb269e4ca54500da6e1f4dc13d95940c15badef019edfe8666315500c54e4489d4b83f6ce79c7f65c9772a1a83d88c3a10aaaaaaaa700011ebb32a33b8a8a487a6"
2187    );
2188    let certificate_signature = const_str::hex!(
2189        "755c428e9bf6ba367152f1e545834649b4e8f70df8383a352a953fdb774862af5d42fab573fc52b90ad47c331c36f93b1a4fa7a2504917d895452ffe7f44bd0e"
2190    );
2191
2192    let sender_certificate_data = proto::sealed_sender::SenderCertificate {
2193        certificate: Some(certificate_data.to_vec()),
2194        signature: Some(certificate_signature.to_vec()),
2195    };
2196
2197    let sender_certificate =
2198        SenderCertificate::deserialize(&sender_certificate_data.encode_to_vec())?;
2199    assert_eq!(
2200        sender_certificate.sender_uuid().expect("valid"),
2201        "aaaaaaaa-7000-11eb-b32a-33b8a8a487a6",
2202    );
2203    assert_eq!(sender_certificate.sender_e164().expect("valid"), None);
2204    assert_eq!(
2205        sender_certificate.sender_device_id().expect("valid"),
2206        DeviceId::new(1).expect("valid"),
2207    );
2208    assert_eq!(
2209        sender_certificate
2210            .expiration()
2211            .expect("valid")
2212            .epoch_millis(),
2213        31337
2214    );
2215    assert!(sender_certificate.validate(
2216        &trust_root.public_key()?,
2217        Timestamp::from_epoch_millis(31336)
2218    )?);
2219    Ok(())
2220}
2221
2222#[test]
2223fn test_known_server_cert() -> Result<()> {
2224    // Same structure as test_lossless_round_trip, but using the fixed server key from the 7357c357
2225    // certificate, and a reference to it rather than embedding it.
2226    //
2227    // % pbpaste | xxd -r -p | protoscope
2228    // 2: 1
2229    // 3: 31337i64
2230    // 4: {`05d75b13e15c7700079dd226f51e5a790ba395e819e88a74d0cf5cedfad8b43348`}
2231    // 8: 1935131479
2232    // 6: {"aaaaaaaa-7000-11eb-b32a-33b8a8a487a6"}
2233
2234    let trust_root = PrivateKey::deserialize(&[0u8; 32])?;
2235    // let server_key = PrivateKey::deserialize(&[0xff; 32])?;
2236
2237    let certificate_data = const_str::hex!(
2238        "100119697a000000000000222105d75b13e15c7700079dd226f51e5a790ba395e819e88a74d0cf5cedfad8b4334840d786df9a07322461616161616161612d373030302d313165622d623332612d333362386138613438376136"
2239    );
2240    let certificate_signature = const_str::hex!(
2241        "e62667bce627caed56ca2ab309b6ae7bc890a30a7482c0e1fd77ec9c3b7528abfd45c8c42b240509a71d973ef5e0f1dbd2685fe01410f0fdbaa8fb247a67e08f"
2242    );
2243
2244    let sender_certificate_data = proto::sealed_sender::SenderCertificate {
2245        certificate: Some(certificate_data.to_vec()),
2246        signature: Some(certificate_signature.to_vec()),
2247    };
2248
2249    let sender_certificate =
2250        SenderCertificate::deserialize(&sender_certificate_data.encode_to_vec())?;
2251    assert!(sender_certificate.validate(
2252        &trust_root.public_key()?,
2253        Timestamp::from_epoch_millis(31336)
2254    )?);
2255
2256    Ok(())
2257}
2258
2259#[test]
2260fn verify_known_certificates() {
2261    assert!(
2262        KNOWN_SERVER_CERTIFICATES
2263            .iter()
2264            .map(|(id, _trust_root, _cert)| id)
2265            .all_unique(),
2266        "all known certificate IDs must be unique"
2267    );
2268
2269    for (id, trust_root, cert) in KNOWN_SERVER_CERTIFICATES {
2270        let trust_root = PublicKey::deserialize(trust_root)
2271            .unwrap_or_else(|e| panic!("[{id:x}] has invalid trust root: {e}"));
2272        let cert = ServerCertificate::deserialize(cert)
2273            .unwrap_or_else(|e| panic!("[{id:x}] has invalid certificate data: {e}"));
2274        assert_eq!(*id, cert.key_id, "[{id:x}] mismatched certificate ID");
2275        assert!(
2276            cert.validate(&trust_root).expect("can validate"),
2277            "[{id:x}] has wrong trust root"
2278        );
2279    }
2280}