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 message =
898        message_encrypt(ptext, destination, session_store, identity_store, now, rng).await?;
899    let usmc = UnidentifiedSenderMessageContent::new(
900        message.message_type(),
901        sender_cert.clone(),
902        message.serialize().to_vec(),
903        ContentHint::Default,
904        None,
905    )?;
906    sealed_sender_encrypt_from_usmc(destination, &usmc, identity_store, rng).await
907}
908
909/// This method implements the single-key single-recipient [KEM] described in [this Signal blog
910/// post], a.k.a. Sealed Sender v1.
911///
912/// [KEM]: https://en.wikipedia.org/wiki/Key_encapsulation
913/// [this Signal blog post]: https://signal.org/blog/sealed-sender/
914///
915/// [`sealed_sender_decrypt`] is used in the client to decrypt the Sealed Sender message produced by
916/// this method.
917///
918/// # Contrast with Sealed Sender v2
919/// The *single-recipient* KEM scheme implemented by this method partially derives the encryption
920/// key from the recipient's identity key, which would then require re-encrypting the same message
921/// multiple times to send to multiple recipients. In contrast,
922/// [Sealed Sender v2](sealed_sender_multi_recipient_encrypt) uses a *multi-recipient* KEM scheme
923/// which avoids this repeated work, but makes a few additional design tradeoffs.
924///
925/// # High-level algorithmic overview
926/// The KEM scheme implemented by this method is described in [this Signal blog post]. The
927/// high-level steps of this process are listed below:
928/// 1. Generate a random key pair.
929/// 2. Derive a symmetric chain key, cipher key, and MAC key from the recipient's public key and the
930///    sender's public/private key pair.
931/// 3. Symmetrically encrypt the sender's public key using the cipher key and MAC key from (2) with
932///    AES-256 in CTR mode.
933/// 4. Derive a second symmetric cipher key and MAC key from the sender's private key, the
934///    recipient's public key, and the chain key from (2).
935/// 5. Symmetrically encrypt the underlying [`UnidentifiedSenderMessageContent`] using the cipher key
936///    and MAC key from (4) with AES-256 in CTR mode.
937/// 6. Send the ephemeral public key from (1) and the encrypted public key from (3) to the
938///    recipient, along with the encrypted message (5).
939///
940/// ## Pseudocode
941///```text
942/// e_pub, e_priv                  = X25519.generateEphemeral()
943/// e_chain, e_cipherKey, e_macKey = HKDF(salt="UnidentifiedDelivery" || recipientIdentityPublic || e_pub, ikm=ECDH(recipientIdentityPublic, e_priv), info="")
944/// e_ciphertext                   = AES_CTR(key=e_cipherKey, input=senderIdentityPublic)
945/// e_mac                          = Hmac256(key=e_macKey, input=e_ciphertext)
946///
947/// s_cipherKey, s_macKey = HKDF(salt=e_chain || e_ciphertext || e_mac, ikm=ECDH(recipientIdentityPublic, senderIdentityPrivate), info="")
948/// s_ciphertext          = AES_CTR(key=s_cipherKey, input=sender_certificate || message_ciphertext)
949/// s_mac                 = Hmac256(key=s_macKey, input=s_ciphertext)
950///
951/// message_to_send = s_ciphertext || s_mac
952///```
953///
954/// # Wire Format
955/// The output of this method is encoded as an `UnidentifiedSenderMessage.Message` from
956/// `sealed_sender.proto`, prepended with an additional byte to indicate the version of Sealed
957/// Sender in use (see [further documentation on the version
958/// byte](sealed_sender_multi_recipient_encrypt#the-version-byte)).
959pub async fn sealed_sender_encrypt_from_usmc<R: Rng + CryptoRng>(
960    destination: &ProtocolAddress,
961    usmc: &UnidentifiedSenderMessageContent,
962    identity_store: &dyn IdentityKeyStore,
963    rng: &mut R,
964) -> Result<Vec<u8>> {
965    let our_identity = identity_store.get_identity_key_pair().await?;
966    let their_identity = identity_store
967        .get_identity(destination)
968        .await?
969        .ok_or_else(|| SignalProtocolError::SessionNotFound(destination.clone()))?;
970
971    let ephemeral = KeyPair::generate(rng);
972
973    let eph_keys = sealed_sender_v1::EphemeralKeys::calculate(
974        &ephemeral,
975        their_identity.public_key(),
976        Direction::Sending,
977    )?;
978
979    let static_key_ctext = crypto::aes256_ctr_hmacsha256_encrypt(
980        &our_identity.public_key().serialize(),
981        &eph_keys.cipher_key,
982        &eph_keys.mac_key,
983    )
984    .expect("just generated these keys, they should be correct");
985
986    let static_keys = sealed_sender_v1::StaticKeys::calculate(
987        &our_identity,
988        their_identity.public_key(),
989        &eph_keys.chain_key,
990        &static_key_ctext,
991    )?;
992
993    let message_data = crypto::aes256_ctr_hmacsha256_encrypt(
994        usmc.serialized()?,
995        &static_keys.cipher_key,
996        &static_keys.mac_key,
997    )
998    .expect("just generated these keys, they should be correct");
999
1000    let mut serialized = vec![SEALED_SENDER_V1_FULL_VERSION];
1001    let pb = proto::sealed_sender::UnidentifiedSenderMessage {
1002        ephemeral_public: Some(ephemeral.public_key.serialize().to_vec()),
1003        encrypted_static: Some(static_key_ctext),
1004        encrypted_message: Some(message_data),
1005    };
1006    pb.encode(&mut serialized)
1007        .expect("can always append to Vec");
1008
1009    Ok(serialized)
1010}
1011
1012mod sealed_sender_v2 {
1013    use super::*;
1014
1015    // Static byte strings used as part of a MAC in HKDF.
1016    const LABEL_R: &[u8] = b"Sealed Sender v2: r (2023-08)";
1017    const LABEL_K: &[u8] = b"Sealed Sender v2: K";
1018    const LABEL_DH: &[u8] = b"Sealed Sender v2: DH";
1019    const LABEL_DH_S: &[u8] = b"Sealed Sender v2: DH-sender";
1020
1021    pub const MESSAGE_KEY_LEN: usize = 32;
1022    pub const CIPHER_KEY_LEN: usize =
1023        <Aes256GcmSiv as aes_gcm_siv::aead::KeySizeUser>::KeySize::USIZE;
1024    pub const AUTH_TAG_LEN: usize = 16;
1025    /// SSv2 hardcodes that its keys are Curve25519 public keys.
1026    pub const PUBLIC_KEY_LEN: usize = 32;
1027
1028    /// An asymmetric and a symmetric cipher key.
1029    pub(super) struct DerivedKeys {
1030        kdf: hkdf::Hkdf<sha2::Sha256>,
1031    }
1032
1033    impl DerivedKeys {
1034        /// Initialize from a slice of random bytes `m`.
1035        pub(super) fn new(m: &[u8]) -> DerivedKeys {
1036            Self {
1037                kdf: hkdf::Hkdf::<sha2::Sha256>::new(None, m),
1038            }
1039        }
1040
1041        /// Derive the ephemeral asymmetric keys.
1042        pub(super) fn derive_e(&self) -> KeyPair {
1043            let mut r = [0; 32];
1044            self.kdf
1045                .expand(LABEL_R, &mut r)
1046                .expect("valid output length");
1047            let e = PrivateKey::try_from(&r[..]).expect("valid PrivateKey");
1048            KeyPair::try_from(e).expect("can derive public key")
1049        }
1050
1051        /// Derive the symmetric cipher key.
1052        pub(super) fn derive_k(&self) -> [u8; CIPHER_KEY_LEN] {
1053            let mut k = [0; CIPHER_KEY_LEN];
1054            self.kdf
1055                .expand(LABEL_K, &mut k)
1056                .expect("valid output length");
1057            k
1058        }
1059    }
1060
1061    /// Encrypt or decrypt a slice of random bytes `input` using a shared secret derived from
1062    /// `our_keys` and `their_key`.
1063    ///
1064    /// The output of this method when called with [`Direction::Sending`] can be inverted to produce
1065    /// the original `input` bytes if called with [`Direction::Receiving`] with `our_keys` and
1066    /// `their_key` swapped.
1067    pub(super) fn apply_agreement_xor(
1068        our_keys: &KeyPair,
1069        their_key: &PublicKey,
1070        direction: Direction,
1071        input: &[u8; MESSAGE_KEY_LEN],
1072    ) -> Result<[u8; MESSAGE_KEY_LEN]> {
1073        let agreement = our_keys.calculate_agreement(their_key)?;
1074        let agreement_key_input = match direction {
1075            Direction::Sending => [
1076                agreement,
1077                our_keys.public_key.serialize(),
1078                their_key.serialize(),
1079            ],
1080            Direction::Receiving => [
1081                agreement,
1082                their_key.serialize(),
1083                our_keys.public_key.serialize(),
1084            ],
1085        }
1086        .concat();
1087
1088        let mut result = [0; MESSAGE_KEY_LEN];
1089        hkdf::Hkdf::<sha2::Sha256>::new(None, &agreement_key_input)
1090            .expand(LABEL_DH, &mut result)
1091            .expect("valid output length");
1092        result
1093            .iter_mut()
1094            .zip(input)
1095            .for_each(|(result_byte, input_byte)| *result_byte ^= input_byte);
1096        Ok(result)
1097    }
1098
1099    /// Compute an [authentication tag] for the bytes `encrypted_message_key` using a shared secret
1100    /// derived from `our_keys` and `their_key`.
1101    ///
1102    /// [authentication tag]: https://en.wikipedia.org/wiki/Message_authentication_code
1103    ///
1104    /// The output of this method with [`Direction::Sending`] should be the same bytes produced by
1105    /// calling this method with [`Direction::Receiving`] with `our_keys` and `their_key`
1106    /// swapped, if `ephemeral_pub_key` and `encrypted_message_key` are the same.
1107    pub(super) fn compute_authentication_tag(
1108        our_keys: &IdentityKeyPair,
1109        their_key: &IdentityKey,
1110        direction: Direction,
1111        ephemeral_pub_key: &PublicKey,
1112        encrypted_message_key: &[u8; MESSAGE_KEY_LEN],
1113    ) -> Result<[u8; AUTH_TAG_LEN]> {
1114        let agreement = our_keys
1115            .private_key()
1116            .calculate_agreement(their_key.public_key())?;
1117        let mut agreement_key_input = agreement.into_vec();
1118        agreement_key_input.extend_from_slice(&ephemeral_pub_key.serialize());
1119        agreement_key_input.extend_from_slice(encrypted_message_key);
1120        match direction {
1121            Direction::Sending => {
1122                agreement_key_input.extend_from_slice(&our_keys.public_key().serialize());
1123                agreement_key_input.extend_from_slice(&their_key.serialize());
1124            }
1125            Direction::Receiving => {
1126                agreement_key_input.extend_from_slice(&their_key.serialize());
1127                agreement_key_input.extend_from_slice(&our_keys.public_key().serialize());
1128            }
1129        }
1130
1131        let mut result = [0; AUTH_TAG_LEN];
1132        hkdf::Hkdf::<sha2::Sha256>::new(None, &agreement_key_input)
1133            .expand(LABEL_DH_S, &mut result)
1134            .expect("valid output length");
1135        Ok(result)
1136    }
1137
1138    #[test]
1139    fn test_agreement_and_authentication() -> Result<()> {
1140        // The sender and recipient each have a long-term identity key pair.
1141        let sender_identity = IdentityKeyPair::generate(&mut rand::rng());
1142        let recipient_identity = IdentityKeyPair::generate(&mut rand::rng());
1143
1144        // Generate random bytes used for our multi-recipient encoding scheme.
1145        let m: [u8; MESSAGE_KEY_LEN] = rand::rng().random();
1146        // Derive an ephemeral key pair from those random bytes.
1147        let ephemeral_keys = DerivedKeys::new(&m);
1148        let e = ephemeral_keys.derive_e();
1149
1150        // Encrypt the ephemeral key pair.
1151        let sender_c_0: [u8; MESSAGE_KEY_LEN] =
1152            apply_agreement_xor(&e, recipient_identity.public_key(), Direction::Sending, &m)?;
1153        // Compute an authentication tag for the encrypted key pair.
1154        let sender_at_0 = compute_authentication_tag(
1155            &sender_identity,
1156            recipient_identity.identity_key(),
1157            Direction::Sending,
1158            &e.public_key,
1159            &sender_c_0,
1160        )?;
1161
1162        // The message recipient calculates the original random bytes and authenticates the result.
1163        let recv_m = apply_agreement_xor(
1164            &recipient_identity.into(),
1165            &e.public_key,
1166            Direction::Receiving,
1167            &sender_c_0,
1168        )?;
1169        assert_eq!(&recv_m, &m);
1170
1171        let recv_at_0 = compute_authentication_tag(
1172            &recipient_identity,
1173            sender_identity.identity_key(),
1174            Direction::Receiving,
1175            &e.public_key,
1176            &sender_c_0,
1177        )?;
1178        assert_eq!(&recv_at_0, &sender_at_0);
1179
1180        Ok(())
1181    }
1182}
1183
1184/// This method implements a single-key multi-recipient [KEM] as defined in Manuel Barbosa's
1185/// ["Randomness Reuse: Extensions and Improvements"], a.k.a. Sealed Sender v2.
1186///
1187/// [KEM]: https://en.wikipedia.org/wiki/Key_encapsulation
1188/// ["Randomness Reuse: Extensions and Improvements"]: https://haslab.uminho.pt/mbb/files/reuse.pdf
1189///
1190/// # Contrast with Sealed Sender v1
1191/// The KEM scheme implemented by this method uses the "Generic Construction" in `4.1` of [Barbosa's
1192/// paper]["Randomness Reuse: Extensions and Improvements"], instantiated with [ElGamal encryption].
1193/// This technique enables reusing a single sequence of random bytes across multiple messages with
1194/// the same content, which reduces computation time for clients sending the same message to
1195/// multiple recipients (without compromising the message security).
1196///
1197/// There are a few additional design tradeoffs this method makes vs [Sealed Sender v1] which may
1198/// make it comparatively unwieldy for certain scenarios:
1199/// 1. it requires a [`SessionRecord`] to exist already for the recipient, i.e. that a Double
1200///    Ratchet message chain has previously been established in the [`SessionStore`] via
1201///    [`process_prekey_bundle`][crate::process_prekey_bundle] after an initial
1202///    [`PreKeySignalMessage`] is received.
1203/// 2. it ferries a lot of additional information in its encoding which makes the resulting message
1204///    bulkier than the message produced by [Sealed Sender v1]. For sending, this will generally
1205///    still be more compact than sending the same message N times, but on the receiver side the
1206///    message is slightly larger.
1207/// 3. unlike other message types sent over the wire, the encoded message returned by this method
1208///    does not use protobuf, in order to avoid inefficiencies produced by protobuf's packing (see
1209///    **[Wire Format]**).
1210///
1211/// [ElGamal encryption]: https://en.wikipedia.org/wiki/ElGamal_encryption
1212/// [Sealed Sender v1]: sealed_sender_encrypt_from_usmc
1213/// [Wire Format]: #wire-format
1214///
1215/// # High-level algorithmic overview
1216/// The high-level steps of this process are summarized below:
1217/// 1. Generate a series of random bytes.
1218/// 2. Derive an ephemeral key pair from (1).
1219/// 3. *Once per recipient:* Encrypt (1) using a shared secret derived from the private ephemeral
1220///    key (2) and the recipient's public identity key.
1221/// 4. *Once per recipient:* Add an authentication tag for (3) using a secret derived from the
1222///    sender's private identity key and the recipient's public identity key.
1223/// 5. Generate a symmetric key from (1) and use it to symmetrically encrypt the underlying
1224///    [`UnidentifiedSenderMessageContent`] via [AEAD encryption]. *This step is only performed once
1225///    per message, regardless of the number of recipients.*
1226/// 6. Send the public ephemeral key (2) to the server, along with the sequence of encrypted random
1227///    bytes (3) and authentication tags (4), and the single encrypted message (5).
1228///
1229/// [AEAD encryption]:
1230///    https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data_(AEAD)
1231///
1232/// ## Pseudocode
1233///```text
1234/// ENCRYPT(message, R_i):
1235///     M = Random(32)
1236///     r = KDF(label_r, M, len=32)
1237///     K = KDF(label_K, M, len=32)
1238///     E = DeriveKeyPair(r)
1239///     for i in num_recipients:
1240///         C_i = KDF(label_DH, DH(E, R_i) || E.public || R_i.public, len=32) XOR M
1241///         AT_i = KDF(label_DH_s, DH(S, R_i) || E.public || C_i || S.public || R_i.public, len=16)
1242///     ciphertext = AEAD_Encrypt(K, message)
1243///     return E.public, C_i, AT_i, ciphertext
1244///
1245/// DECRYPT(E.public, C, AT, ciphertext):
1246///     M = KDF(label_DH, DH(E, R) || E.public || R.public, len=32) xor C
1247///     r = KDF(label_r, M, len=32)
1248///     K = KDF(label_K, M, len=32)
1249///     E' = DeriveKeyPair(r)
1250///     if E.public != E'.public:
1251///         return DecryptionError
1252///     message = AEAD_Decrypt(K, ciphertext) // includes S.public
1253///     AT' = KDF(label_DH_s, DH(S, R) || E.public || C || S.public || R.public, len=16)
1254///     if AT != AT':
1255///         return DecryptionError
1256///     return message
1257///```
1258///
1259/// # Routing messages to recipients
1260///
1261/// The server will split up the set of messages and securely route each individual [received
1262/// message][receiving] to its intended recipient. [`SealedSenderV2SentMessage`] can perform this
1263/// fan-out operation.
1264///
1265/// # Wire Format
1266/// Multi-recipient sealed-sender does not use protobufs for its payload format. Instead, it uses a
1267/// flat format marked with a [version byte](#the-version-byte). The format is different for
1268/// [sending] and [receiving]. The decrypted content is a protobuf-encoded
1269/// `UnidentifiedSenderMessage.Message` from `sealed_sender.proto`.
1270///
1271/// The public key used in Sealed Sender v2 is always a Curve25519 DJB key.
1272///
1273/// [sending]: #sent-messages
1274/// [receiving]: #received-messages
1275///
1276/// ## The version byte
1277///
1278/// Sealed sender messages (v1 and v2) in serialized form begin with a version [byte][u8]. This byte
1279/// has the form:
1280///
1281/// ```text
1282/// (requiredVersion << 4) | currentVersion
1283/// ```
1284///
1285/// v1 messages thus have a version byte of `0x11`. v2 messages have a version byte of `0x22` or
1286/// `0x23`. A hypothetical version byte `0x34` would indicate a message encoded as Sealed Sender v4,
1287/// but decodable by any client that supports Sealed Sender v3.
1288///
1289/// ## Received messages
1290///
1291/// ```text
1292/// ReceivedMessage {
1293///     version_byte: u8,
1294///     c: [u8; 32],
1295///     at: [u8; 16],
1296///     e_pub: [u8; 32],
1297///     message: [u8] // remaining bytes
1298/// }
1299/// ```
1300///
1301/// Each individual Sealed Sender message received from the server is decoded in the Signal client
1302/// by calling [`sealed_sender_decrypt`].
1303///
1304/// ## Sent messages
1305///
1306/// ```text
1307/// SentMessage {
1308///     version_byte: u8,
1309///     count: varint,
1310///     recipients: [PerRecipientData | ExcludedRecipient; count],
1311///     e_pub: [u8; 32],
1312///     message: [u8] // remaining bytes
1313/// }
1314///
1315/// PerRecipientData {
1316///     recipient: Recipient,
1317///     devices: [DeviceList], // last element's has_more = 0
1318///     c: [u8; 32],
1319///     at: [u8; 16],
1320/// }
1321///
1322/// ExcludedRecipient {
1323///     recipient: Recipient,
1324///     no_devices_marker: u8 = 0, // never a valid device ID
1325/// }
1326///
1327/// DeviceList {
1328///     device_id: u8,
1329///     has_more: u1, // high bit of following field
1330///     unused: u1,   // high bit of following field
1331///     registration_id: u14,
1332/// }
1333///
1334/// Recipient {
1335///     service_id_fixed_width_binary: [u8; 17],
1336/// }
1337/// ```
1338///
1339/// The varint encoding used is the same as [protobuf's][varint]. Values are unsigned.
1340/// Fixed-width-binary encoding is used for the [ServiceId] values.
1341/// Fixed-width integers are unaligned and in network byte order (big-endian).
1342///
1343/// [varint]: https://developers.google.com/protocol-buffers/docs/encoding#varints
1344pub async fn sealed_sender_multi_recipient_encrypt<
1345    R: Rng + CryptoRng,
1346    X: IntoIterator<Item = ServiceId>,
1347>(
1348    destinations: &[&ProtocolAddress],
1349    destination_sessions: &[&SessionRecord],
1350    excluded_recipients: X,
1351    usmc: &UnidentifiedSenderMessageContent,
1352    identity_store: &dyn IdentityKeyStore,
1353    rng: &mut R,
1354) -> Result<Vec<u8>>
1355where
1356    X::IntoIter: ExactSizeIterator,
1357{
1358    sealed_sender_multi_recipient_encrypt_impl(
1359        destinations,
1360        destination_sessions,
1361        excluded_recipients,
1362        usmc,
1363        identity_store,
1364        rng,
1365    )
1366    .await
1367}
1368
1369async fn sealed_sender_multi_recipient_encrypt_impl<
1370    R: Rng + CryptoRng,
1371    X: IntoIterator<Item = ServiceId>,
1372>(
1373    destinations: &[&ProtocolAddress],
1374    destination_sessions: &[&SessionRecord],
1375    excluded_recipients: X,
1376    usmc: &UnidentifiedSenderMessageContent,
1377    identity_store: &dyn IdentityKeyStore,
1378    rng: &mut R,
1379) -> Result<Vec<u8>>
1380where
1381    X::IntoIter: ExactSizeIterator,
1382{
1383    if destinations.len() != destination_sessions.len() {
1384        return Err(SignalProtocolError::InvalidArgument(
1385            "must have the same number of destination sessions as addresses".to_string(),
1386        ));
1387    }
1388
1389    let excluded_recipients = excluded_recipients.into_iter();
1390    let our_identity = identity_store.get_identity_key_pair().await?;
1391
1392    let m: [u8; sealed_sender_v2::MESSAGE_KEY_LEN] = rng.random();
1393    let keys = sealed_sender_v2::DerivedKeys::new(&m);
1394    let e = keys.derive_e();
1395    let e_pub = &e.public_key;
1396
1397    // Encrypt the shared ciphertext using AES-GCM-SIV.
1398    let ciphertext = {
1399        let mut ciphertext = usmc.serialized()?.to_vec();
1400        let symmetric_authentication_tag = Aes256GcmSiv::new(&keys.derive_k().into())
1401            .encrypt_in_place_detached(
1402                // There's no nonce because the key is already one-use.
1403                &aes_gcm_siv::Nonce::default(),
1404                // And there's no associated data.
1405                &[],
1406                &mut ciphertext,
1407            )
1408            .expect("AES-GCM-SIV encryption should not fail with a just-computed key");
1409        // AES-GCM-SIV expects the authentication tag to be at the end of the ciphertext
1410        // when decrypting.
1411        ciphertext.extend_from_slice(&symmetric_authentication_tag);
1412        ciphertext
1413    };
1414
1415    // Group the destinations by name, and fetch identity keys once for each name. This optimizes
1416    // for the common case where all of a recipient's devices are included contiguously in the
1417    // destination list. (If the caller *doesn't* do this, that's on them; the message will still be
1418    // valid but some key material will be redundantly computed and encoded in the output.)
1419    let identity_keys_and_ranges: Vec<(IdentityKey, Range<usize>)> = {
1420        let mut identity_keys_and_ranges = vec![];
1421        for (_, mut next_group) in &destinations
1422            .iter()
1423            .enumerate()
1424            .chunk_by(|(_i, next)| next.name())
1425        {
1426            let (i, &destination) = next_group
1427                .next()
1428                .expect("at least one element in every group");
1429            // We can't put this before the call to `next()` because `count` consumes the rest of
1430            // the iterator.
1431            let count = 1 + next_group.count();
1432            let their_identity =
1433                identity_store
1434                    .get_identity(destination)
1435                    .await?
1436                    .ok_or_else(|| {
1437                        log::error!("missing identity key for {destination}");
1438                        // Returned as a SessionNotFound error because (a) we don't have an identity
1439                        // error that includes the address, and (b) re-establishing the session should
1440                        // re-fetch the identity.
1441                        SignalProtocolError::SessionNotFound(destination.clone())
1442                    })?;
1443            identity_keys_and_ranges.push((their_identity, i..i + count));
1444        }
1445        identity_keys_and_ranges
1446    };
1447
1448    // Next, fan out the work of generating the per-recipient to multiple cores, since we do two key
1449    // agreements per recipient (though not per device) and those are CPU-bound.
1450
1451    // I know this looks complicated enough to pull out into a separate function altogether, but it
1452    // also depends on a bunch of local state: our identity, E and E_pub, and M.
1453    let serialize_recipient_destinations_into = |serialized: &mut Vec<u8>,
1454                                                 destinations: &[&ProtocolAddress],
1455                                                 sessions: &[&SessionRecord],
1456                                                 their_identity: &IdentityKey|
1457     -> Result<()> {
1458        let their_service_id = ServiceId::parse_from_service_id_string(destinations[0].name())
1459            .ok_or_else(|| {
1460                SignalProtocolError::InvalidArgument(format!(
1461                    "multi-recipient sealed sender requires recipients' ServiceId (not {})",
1462                    destinations[0].name()
1463                ))
1464            })?;
1465
1466        serialized.extend_from_slice(&their_service_id.service_id_fixed_width_binary());
1467
1468        debug_assert_eq!(
1469            destinations.len(),
1470            sessions.len(),
1471            "should be sliced with the same range"
1472        );
1473        let mut destinations_and_sessions = destinations.iter().zip(sessions);
1474        while let Some((&destination, session)) = destinations_and_sessions.next() {
1475            let their_registration_id = session.remote_registration_id().map_err(|_| {
1476                SignalProtocolError::InvalidState(
1477                    "sealed_sender_multi_recipient_encrypt",
1478                    format!(
1479                        concat!(
1480                            "cannot get registration ID from session with {} ",
1481                            "(maybe it was recently archived)"
1482                        ),
1483                        destination
1484                    ),
1485                )
1486            })?;
1487            if their_registration_id & u32::from(VALID_REGISTRATION_ID_MASK)
1488                != their_registration_id
1489            {
1490                return Err(SignalProtocolError::InvalidRegistrationId(
1491                    destination.clone(),
1492                    their_registration_id,
1493                ));
1494            }
1495            let mut their_registration_id =
1496                u16::try_from(their_registration_id).expect("just checked range");
1497            if destinations_and_sessions.len() > 0 {
1498                their_registration_id |= 0x8000;
1499            }
1500
1501            let device_id = destination.device_id();
1502            serialized.push(device_id.into());
1503            serialized.extend_from_slice(&their_registration_id.to_be_bytes());
1504        }
1505
1506        let c_i = sealed_sender_v2::apply_agreement_xor(
1507            &e,
1508            their_identity.public_key(),
1509            Direction::Sending,
1510            &m,
1511        )?;
1512        serialized.extend_from_slice(&c_i);
1513
1514        let at_i = sealed_sender_v2::compute_authentication_tag(
1515            &our_identity,
1516            their_identity,
1517            Direction::Sending,
1518            e_pub,
1519            &c_i,
1520        )?;
1521        serialized.extend_from_slice(&at_i);
1522
1523        Ok(())
1524    };
1525
1526    let process_chunk =
1527        |serialized: &mut Vec<u8>, chunk: &[(IdentityKey, Range<usize>)]| -> Result<()> {
1528            for (their_identity, destination_range) in chunk {
1529                let these_destinations = &destinations[destination_range.clone()];
1530                let these_sessions = &destination_sessions[destination_range.clone()];
1531                serialize_recipient_destinations_into(
1532                    serialized,
1533                    these_destinations,
1534                    these_sessions,
1535                    their_identity,
1536                )?;
1537            }
1538            Ok(())
1539        };
1540
1541    let mut serialized: Vec<u8> = vec![SEALED_SENDER_V2_SERVICE_ID_FULL_VERSION];
1542
1543    let count_of_recipients = identity_keys_and_ranges.len() + excluded_recipients.len();
1544    prost::encode_length_delimiter(count_of_recipients, &mut serialized)
1545        .expect("can always resize a Vec");
1546
1547    // Fan out to N threads, like Rayon would. But don't bother for less than 6 items.
1548    let parallelism = std::thread::available_parallelism()
1549        .map(usize::from)
1550        .unwrap_or(1);
1551    let chunk_size = std::cmp::max(6, identity_keys_and_ranges.len().div_ceil(parallelism));
1552
1553    if parallelism == 1 || chunk_size >= identity_keys_and_ranges.len() {
1554        process_chunk(&mut serialized, &identity_keys_and_ranges)?;
1555    } else {
1556        let mut chunks = identity_keys_and_ranges.chunks(chunk_size);
1557        // We'll process the first chunk on the current thread once we've spawned all the others.
1558        let first_chunk = chunks.next().expect("at least one chunk, tested above");
1559
1560        let mut all_outputs = Vec::new();
1561        all_outputs.resize_with(chunks.len(), || Ok(vec![]));
1562
1563        rayon::scope(|scope| -> Result<()> {
1564            let mut outputs = &mut all_outputs[..];
1565            for chunk in chunks {
1566                let (next_output, remaining_outputs) = outputs
1567                    .split_first_mut()
1568                    .expect("as many outputs as remaining chunks");
1569                scope.spawn(|_| {
1570                    let mut serialized = vec![];
1571                    *next_output = process_chunk(&mut serialized, chunk).map(|_| serialized);
1572                });
1573                outputs = remaining_outputs;
1574            }
1575
1576            process_chunk(&mut serialized, first_chunk)
1577        })?;
1578
1579        for output in all_outputs {
1580            serialized.extend(output?);
1581        }
1582    }
1583
1584    for excluded in excluded_recipients {
1585        serialized.extend_from_slice(&excluded.service_id_fixed_width_binary());
1586        serialized.push(0);
1587    }
1588
1589    serialized.extend_from_slice(e_pub.public_key_bytes());
1590    serialized.extend_from_slice(&ciphertext);
1591
1592    Ok(serialized)
1593}
1594
1595/// Represents a single recipient in an SSv2 SentMessage.
1596///
1597/// See [`SealedSenderV2SentMessage`].
1598pub struct SealedSenderV2SentMessageRecipient<'a> {
1599    /// The recipient's devices and their registration IDs. May be empty.
1600    pub devices: Vec<(DeviceId, u16)>,
1601    /// A concatenation of the `C_i` and `AT_i` SSv2 fields for this recipient, or an empty slice if
1602    /// the recipient has no devices.
1603    c_and_at: &'a [u8],
1604}
1605
1606/// A parsed representation of a Sealed Sender v2 SentMessage.
1607///
1608/// This only parses enough to fan out the message as a series of ReceivedMessages.
1609pub struct SealedSenderV2SentMessage<'a> {
1610    /// The full message, for calculating offsets.
1611    full_message: &'a [u8],
1612    /// The version byte at the head of the message.
1613    pub version: u8,
1614    /// The parsed list of recipients, grouped by ServiceId.
1615    ///
1616    /// The map is ordered by when a recipient first appears in the full message, even if they
1617    /// appear again later with more devices. This makes iteration over the full set of recipients
1618    /// deterministic.
1619    pub recipients: IndexMap<ServiceId, SealedSenderV2SentMessageRecipient<'a>>,
1620    /// A concatenation of the `e_pub` and `message` SSv2 fields for this recipient.
1621    shared_bytes: &'a [u8],
1622}
1623
1624impl<'a> SealedSenderV2SentMessage<'a> {
1625    /// Parses the message, or produces an error if the message is invalid.
1626    pub fn parse(data: &'a [u8]) -> Result<Self> {
1627        if data.is_empty() {
1628            return Err(SignalProtocolError::InvalidSealedSenderMessage(
1629                "Message was empty".to_owned(),
1630            ));
1631        }
1632
1633        let version = data[0];
1634        if !matches!(
1635            version,
1636            SEALED_SENDER_V2_UUID_FULL_VERSION | SEALED_SENDER_V2_SERVICE_ID_FULL_VERSION
1637        ) {
1638            return Err(SignalProtocolError::UnknownSealedSenderVersion(version));
1639        }
1640
1641        fn advance<'a, const N: usize>(buf: &mut &'a [u8]) -> Result<&'a [u8; N]> {
1642            let (prefix, remaining) = buf
1643                .split_first_chunk()
1644                .ok_or(SignalProtocolError::InvalidProtobufEncoding)?;
1645            *buf = remaining;
1646            Ok(prefix)
1647        }
1648        fn decode_varint(buf: &mut &[u8]) -> Result<u32> {
1649            let result: usize = prost::decode_length_delimiter(*buf)
1650                .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
1651            *buf = &buf[prost::length_delimiter_len(result)..];
1652            result
1653                .try_into()
1654                .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)
1655        }
1656
1657        let mut remaining = &data[1..];
1658        let recipient_count = decode_varint(&mut remaining)?
1659            .try_into()
1660            .unwrap_or(usize::MAX);
1661
1662        // Cap our preallocated capacity; anything higher than this is *probably* a mistake, but
1663        // could just be a very large message.
1664        // (Callers can of course refuse to process messages with too many recipients.)
1665        let mut recipients: IndexMap<ServiceId, SealedSenderV2SentMessageRecipient<'a>> =
1666            IndexMap::with_capacity(std::cmp::min(recipient_count as usize, 6000));
1667        for _ in 0..recipient_count {
1668            let service_id = if version == SEALED_SENDER_V2_UUID_FULL_VERSION {
1669                // The original version of SSv2 assumed ACIs here, and only encoded the raw UUID.
1670                ServiceId::from(Aci::from_uuid_bytes(*advance::<
1671                    { std::mem::size_of::<uuid::Bytes>() },
1672                >(&mut remaining)?))
1673            } else {
1674                ServiceId::parse_from_service_id_fixed_width_binary(advance::<
1675                    { std::mem::size_of::<ServiceIdFixedWidthBinaryBytes>() },
1676                >(
1677                    &mut remaining
1678                )?)
1679                .ok_or(SignalProtocolError::InvalidProtobufEncoding)?
1680            };
1681            let mut devices = Vec::new();
1682            loop {
1683                let device_id = advance::<1>(&mut remaining)?[0];
1684                if device_id == 0 {
1685                    if !devices.is_empty() {
1686                        return Err(SignalProtocolError::InvalidProtobufEncoding);
1687                    }
1688                    break;
1689                }
1690                let device_id = DeviceId::new(device_id)
1691                    .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
1692                let registration_id_and_has_more =
1693                    u16::from_be_bytes(*advance::<2>(&mut remaining)?);
1694                devices.push((
1695                    device_id,
1696                    registration_id_and_has_more & VALID_REGISTRATION_ID_MASK,
1697                ));
1698                let has_more = (registration_id_and_has_more & 0x8000) != 0;
1699                if !has_more {
1700                    break;
1701                }
1702            }
1703
1704            let c_and_at: &[u8] = if devices.is_empty() {
1705                &[]
1706            } else {
1707                advance::<{ sealed_sender_v2::MESSAGE_KEY_LEN + sealed_sender_v2::AUTH_TAG_LEN }>(
1708                    &mut remaining,
1709                )?
1710            };
1711
1712            match recipients.entry(service_id) {
1713                indexmap::map::Entry::Occupied(mut existing) => {
1714                    if existing.get().devices.is_empty() || devices.is_empty() {
1715                        return Err(SignalProtocolError::InvalidSealedSenderMessage(
1716                            "recipient redundantly encoded as empty".to_owned(),
1717                        ));
1718                    }
1719                    // We don't unique the recipient devices; the server is going to check this
1720                    // against the account's canonical list of devices anyway.
1721                    existing.get_mut().devices.extend(devices);
1722                    // Note that we don't check that c_and_at matches. Any case where it doesn't
1723                    // match would already result in a decryption error for at least one of the
1724                    // recipient's devices, though.
1725                }
1726                indexmap::map::Entry::Vacant(entry) => {
1727                    entry.insert(SealedSenderV2SentMessageRecipient { devices, c_and_at });
1728                }
1729            };
1730        }
1731
1732        if remaining.len() < sealed_sender_v2::PUBLIC_KEY_LEN {
1733            return Err(SignalProtocolError::InvalidProtobufEncoding);
1734        }
1735
1736        Ok(Self {
1737            full_message: data,
1738            version,
1739            recipients,
1740            shared_bytes: remaining,
1741        })
1742    }
1743
1744    /// Returns a slice of slices that, when concatenated, form the ReceivedMessage appropriate for
1745    /// `recipient`.
1746    ///
1747    /// If `recipient` is not one of the recipients in `self`, the resulting message will not be
1748    /// decryptable.
1749    #[inline]
1750    pub fn received_message_parts_for_recipient(
1751        &self,
1752        recipient: &SealedSenderV2SentMessageRecipient<'a>,
1753    ) -> impl AsRef<[&[u8]]> {
1754        // Why not use `IntoIterator<Item = &[u8]>` as the result? Because the `concat` method on
1755        // slices is more efficient when the caller just wants a `Vec<u8>`.
1756        // Why use SEALED_SENDER_V2_UUID_FULL_VERSION as the version? Because the ReceivedMessage
1757        // format hasn't changed since then.
1758        [
1759            &[SEALED_SENDER_V2_UUID_FULL_VERSION],
1760            recipient.c_and_at,
1761            self.shared_bytes,
1762        ]
1763    }
1764
1765    /// Returns the offset of `addr` within `self.full_message`, or `None` if `addr` does not lie
1766    /// within `self.full_message`.
1767    ///
1768    /// A stripped-down version of [a dormant Rust RFC][subslice-offset].
1769    ///
1770    /// [subslice-offset]: https://github.com/rust-lang/rfcs/pull/2796
1771    #[inline]
1772    fn offset_within_full_message(&self, addr: *const u8) -> Option<usize> {
1773        // Arithmetic on addresses is valid for offsets within a byte array.
1774        // If addr < start, we'll wrap around to a very large value, which will be out of range just
1775        // like if addr > end.
1776        let offset = (addr as usize).wrapping_sub(self.full_message.as_ptr() as usize);
1777        // We *do* want to allow the "one-past-the-end" offset here, because the offset might be
1778        // used as part of a range (e.g. 0..end).
1779        if offset <= self.full_message.len() {
1780            debug_assert!(
1781                offset == self.full_message.len() || std::ptr::eq(&self.full_message[offset], addr)
1782            );
1783            Some(offset)
1784        } else {
1785            None
1786        }
1787    }
1788
1789    /// Returns the range within the full message of `recipient`'s user-specific key material.
1790    ///
1791    /// This can be concatenated as `[version, recipient_key_material, shared_bytes]` to produce a
1792    /// valid SSv2 ReceivedMessage, the payload delivered to recipients.
1793    ///
1794    /// **Panics** if `recipient` is not one of the recipients in `self`.
1795    pub fn range_for_recipient_key_material(
1796        &self,
1797        recipient: &SealedSenderV2SentMessageRecipient<'a>,
1798    ) -> Range<usize> {
1799        if recipient.c_and_at.is_empty() {
1800            return 0..0;
1801        }
1802        let offset = self
1803            .offset_within_full_message(recipient.c_and_at.as_ptr())
1804            .expect("'recipient' is not one of the recipients in this SealedSenderV2SentMessage");
1805        let end_offset = offset.saturating_add(recipient.c_and_at.len());
1806        assert!(
1807            end_offset <= self.full_message.len(),
1808            "invalid 'recipient' passed to range_for_recipient_key_material"
1809        );
1810        offset..end_offset
1811    }
1812
1813    /// Returns the offset of the shared bytes within the full message.
1814    ///
1815    /// This can be concatenated as `[version, recipient_key_material, shared_bytes]` to produce a
1816    /// valid SSv2 ReceivedMessage, the payload delivered to recipients.
1817    pub fn offset_of_shared_bytes(&self) -> usize {
1818        debug_assert_eq!(
1819            self.full_message.as_ptr_range().end,
1820            self.shared_bytes.as_ptr_range().end,
1821            "SealedSenderV2SentMessage parsed incorrectly"
1822        );
1823        self.offset_within_full_message(self.shared_bytes.as_ptr())
1824            .expect("constructed correctly")
1825    }
1826}
1827
1828/// Decrypt the payload of a sealed-sender message in either the v1 or v2 format.
1829///
1830/// [`sealed_sender_decrypt`] consumes the output of this method to validate the sender's identity
1831/// before decrypting the underlying message.
1832pub async fn sealed_sender_decrypt_to_usmc(
1833    ciphertext: &[u8],
1834    identity_store: &dyn IdentityKeyStore,
1835) -> Result<UnidentifiedSenderMessageContent> {
1836    let our_identity = identity_store.get_identity_key_pair().await?;
1837
1838    match UnidentifiedSenderMessage::deserialize(ciphertext)? {
1839        UnidentifiedSenderMessage::V1 {
1840            ephemeral_public,
1841            encrypted_static,
1842            encrypted_message,
1843        } => {
1844            let eph_keys = sealed_sender_v1::EphemeralKeys::calculate(
1845                &our_identity.into(),
1846                &ephemeral_public,
1847                Direction::Receiving,
1848            )?;
1849
1850            let message_key_bytes = match crypto::aes256_ctr_hmacsha256_decrypt(
1851                &encrypted_static,
1852                &eph_keys.cipher_key,
1853                &eph_keys.mac_key,
1854            ) {
1855                Ok(plaintext) => plaintext,
1856                Err(crypto::DecryptionError::BadKeyOrIv) => {
1857                    unreachable!("just derived these keys; they should be valid");
1858                }
1859                Err(crypto::DecryptionError::BadCiphertext(msg)) => {
1860                    log::error!("failed to decrypt sealed sender v1 message key: {msg}");
1861                    return Err(SignalProtocolError::InvalidSealedSenderMessage(
1862                        "failed to decrypt sealed sender v1 message key".to_owned(),
1863                    ));
1864                }
1865            };
1866
1867            let static_key = PublicKey::try_from(&message_key_bytes[..])?;
1868
1869            let static_keys = sealed_sender_v1::StaticKeys::calculate(
1870                &our_identity,
1871                &static_key,
1872                &eph_keys.chain_key,
1873                &encrypted_static,
1874            )?;
1875
1876            let message_bytes = match crypto::aes256_ctr_hmacsha256_decrypt(
1877                &encrypted_message,
1878                &static_keys.cipher_key,
1879                &static_keys.mac_key,
1880            ) {
1881                Ok(plaintext) => plaintext,
1882                Err(crypto::DecryptionError::BadKeyOrIv) => {
1883                    unreachable!("just derived these keys; they should be valid");
1884                }
1885                Err(crypto::DecryptionError::BadCiphertext(msg)) => {
1886                    log::error!("failed to decrypt sealed sender v1 message contents: {msg}");
1887                    return Err(SignalProtocolError::InvalidSealedSenderMessage(
1888                        "failed to decrypt sealed sender v1 message contents".to_owned(),
1889                    ));
1890                }
1891            };
1892
1893            let usmc = UnidentifiedSenderMessageContent::deserialize(&message_bytes)?;
1894
1895            if !bool::from(message_key_bytes.ct_eq(&usmc.sender()?.key()?.serialize())) {
1896                return Err(SignalProtocolError::InvalidSealedSenderMessage(
1897                    "sender certificate key does not match message key".to_string(),
1898                ));
1899            }
1900
1901            Ok(usmc)
1902        }
1903        UnidentifiedSenderMessage::V2 {
1904            ephemeral_public,
1905            encrypted_message_key,
1906            authentication_tag,
1907            encrypted_message,
1908        } => {
1909            let m = sealed_sender_v2::apply_agreement_xor(
1910                &our_identity.into(),
1911                &ephemeral_public,
1912                Direction::Receiving,
1913                encrypted_message_key,
1914            )?;
1915
1916            let keys = sealed_sender_v2::DerivedKeys::new(&m);
1917            if !bool::from(keys.derive_e().public_key.ct_eq(&ephemeral_public)) {
1918                return Err(SignalProtocolError::InvalidSealedSenderMessage(
1919                    "derived ephemeral key did not match key provided in message".to_string(),
1920                ));
1921            }
1922
1923            let mut message_bytes = Vec::from(encrypted_message);
1924            Aes256GcmSiv::new(&keys.derive_k().into())
1925                .decrypt_in_place(
1926                    // There's no nonce because the key is already one-use.
1927                    &aes_gcm_siv::Nonce::default(),
1928                    // And there's no associated data.
1929                    &[],
1930                    &mut message_bytes,
1931                )
1932                .map_err(|err| {
1933                    SignalProtocolError::InvalidSealedSenderMessage(format!(
1934                        "failed to decrypt inner message: {err}"
1935                    ))
1936                })?;
1937
1938            let usmc = UnidentifiedSenderMessageContent::deserialize(&message_bytes)?;
1939
1940            let at = sealed_sender_v2::compute_authentication_tag(
1941                &our_identity,
1942                &usmc.sender()?.key()?.into(),
1943                Direction::Receiving,
1944                &ephemeral_public,
1945                encrypted_message_key,
1946            )?;
1947            if !bool::from(authentication_tag.ct_eq(&at)) {
1948                return Err(SignalProtocolError::InvalidSealedSenderMessage(
1949                    "sender certificate key does not match authentication tag".to_string(),
1950                ));
1951            }
1952
1953            Ok(usmc)
1954        }
1955    }
1956}
1957
1958#[derive(Debug)]
1959pub struct SealedSenderDecryptionResult {
1960    pub sender_uuid: String,
1961    pub sender_e164: Option<String>,
1962    pub device_id: DeviceId,
1963    pub message: Vec<u8>,
1964}
1965
1966impl SealedSenderDecryptionResult {
1967    pub fn sender_uuid(&self) -> Result<&str> {
1968        Ok(self.sender_uuid.as_ref())
1969    }
1970
1971    pub fn sender_e164(&self) -> Result<Option<&str>> {
1972        Ok(self.sender_e164.as_deref())
1973    }
1974
1975    pub fn device_id(&self) -> Result<DeviceId> {
1976        Ok(self.device_id)
1977    }
1978
1979    pub fn message(&self) -> Result<&[u8]> {
1980        Ok(self.message.as_ref())
1981    }
1982}
1983
1984/// Decrypt a Sealed Sender message `ciphertext` in either the v1 or v2 format, validate its sender
1985/// certificate, and then decrypt the inner message payload.
1986///
1987/// This method calls [`sealed_sender_decrypt_to_usmc`] to extract the sender information, including
1988/// the embedded [`SenderCertificate`]. The sender certificate (signed by the [`ServerCertificate`])
1989/// is then validated against the `trust_root` baked into the client to ensure that the sender's
1990/// identity was not forged.
1991#[expect(clippy::too_many_arguments)]
1992pub async fn sealed_sender_decrypt(
1993    ciphertext: &[u8],
1994    trust_root: &PublicKey,
1995    timestamp: Timestamp,
1996    local_e164: Option<String>,
1997    local_uuid: String,
1998    local_device_id: DeviceId,
1999    identity_store: &mut dyn IdentityKeyStore,
2000    session_store: &mut dyn SessionStore,
2001    pre_key_store: &mut dyn PreKeyStore,
2002    signed_pre_key_store: &dyn SignedPreKeyStore,
2003    kyber_pre_key_store: &mut dyn KyberPreKeyStore,
2004) -> Result<SealedSenderDecryptionResult> {
2005    let usmc = sealed_sender_decrypt_to_usmc(ciphertext, identity_store).await?;
2006
2007    if !usmc.sender()?.validate(trust_root, timestamp)? {
2008        return Err(SignalProtocolError::InvalidSealedSenderMessage(
2009            "trust root validation failed".to_string(),
2010        ));
2011    }
2012
2013    let is_local_uuid = local_uuid == usmc.sender()?.sender_uuid()?;
2014
2015    let is_local_e164 = match (local_e164, usmc.sender()?.sender_e164()?) {
2016        (Some(l), Some(s)) => l == s,
2017        (_, _) => false,
2018    };
2019
2020    if (is_local_e164 || is_local_uuid) && usmc.sender()?.sender_device_id()? == local_device_id {
2021        return Err(SignalProtocolError::SealedSenderSelfSend);
2022    }
2023
2024    let mut rng = rand::rngs::OsRng.unwrap_err();
2025
2026    let remote_address = ProtocolAddress::new(
2027        usmc.sender()?.sender_uuid()?.to_string(),
2028        usmc.sender()?.sender_device_id()?,
2029    );
2030
2031    let message = match usmc.msg_type()? {
2032        CiphertextMessageType::Whisper => {
2033            let ctext = SignalMessage::try_from(usmc.contents()?)?;
2034            session_cipher::message_decrypt_signal(
2035                &ctext,
2036                &remote_address,
2037                session_store,
2038                identity_store,
2039                &mut rng,
2040            )
2041            .await?
2042        }
2043        CiphertextMessageType::PreKey => {
2044            let ctext = PreKeySignalMessage::try_from(usmc.contents()?)?;
2045            session_cipher::message_decrypt_prekey(
2046                &ctext,
2047                &remote_address,
2048                session_store,
2049                identity_store,
2050                pre_key_store,
2051                signed_pre_key_store,
2052                kyber_pre_key_store,
2053                &mut rng,
2054            )
2055            .await?
2056        }
2057        msg_type => {
2058            return Err(SignalProtocolError::InvalidMessage(
2059                msg_type,
2060                "unexpected message type for sealed_sender_decrypt",
2061            ));
2062        }
2063    };
2064
2065    Ok(SealedSenderDecryptionResult {
2066        sender_uuid: usmc.sender()?.sender_uuid()?.to_string(),
2067        sender_e164: usmc.sender()?.sender_e164()?.map(|s| s.to_string()),
2068        device_id: usmc.sender()?.sender_device_id()?,
2069        message,
2070    })
2071}
2072
2073#[test]
2074fn test_lossless_round_trip() -> Result<()> {
2075    let trust_root = PrivateKey::deserialize(&[0u8; 32])?;
2076
2077    // To test a hypothetical addition of a new field:
2078    //
2079    // Step 1: temporarily add a new field to the .proto.
2080    //
2081    //    --- a/rust/protocol/src/proto/sealed_sender.proto
2082    //    +++ b/rust/protocol/src/proto/sealed_sender.proto
2083    //    @@ -26,3 +26,4 @@ message SenderCertificate {
2084    //             optional bytes             identityKey   = 4;
2085    //             optional ServerCertificate signer        = 5;
2086    //    +        optional string someFakeField = 999;
2087    //     }
2088    //
2089    // Step 2: Add `some_fake_field: None` to the above construction of
2090    // proto::sealed_sender::sender_certificate::Certificate.
2091    //
2092    // Step 3: Serialize and print out the new fixture data (uncomment the following)
2093    //
2094    // let mut rng = rand::rngs::OsRng.unwrap_err();
2095    // let server_key = KeyPair::generate(&mut rng);
2096    // let sender_key = KeyPair::generate(&mut rng);
2097    //
2098    // let server_cert =
2099    //     ServerCertificate::new(1, server_key.public_key, &trust_root, &mut rng)?;
2100    //
2101    // let sender_cert = proto::sealed_sender::sender_certificate::Certificate {
2102    //     sender_uuid: Some(
2103    //         proto::sealed_sender::sender_certificate::certificate::SenderUuid::UuidString(
2104    //             "aaaaaaaa-7000-11eb-b32a-33b8a8a487a6".to_string(),
2105    //         ),
2106    //     ),
2107    //     sender_e164: None,
2108    //     sender_device: Some(1),
2109    //     expires: Some(31337),
2110    //     identity_key: Some(sender_key.public_key.serialize().to_vec()),
2111    //     signer: Some(
2112    //         proto::sealed_sender::sender_certificate::certificate::Signer::Certificate(
2113    //             server_cert.serialized()?.to_vec(),
2114    //         ),
2115    //     ),
2116    //     some_fake_field: Some("crashing right down".to_string()),
2117    // };
2118    //
2119    // eprintln!("<SNIP>");
2120    // let serialized_certificate_data = sender_cert.encode_to_vec();
2121    // let certificate_data_encoded = hex::encode(&serialized_certificate_data);
2122    // eprintln!("let certificate_data = const_str::hex!(\"{}\");", certificate_data_encoded);
2123    //
2124    // let certificate_signature = server_key.calculate_signature(&serialized_certificate_data, &mut rng)?;
2125    // let certificate_signature_encoded = hex::encode(certificate_signature);
2126    // eprintln!("let certificate_signature = const_str::hex!(\"{}\");", certificate_signature_encoded);
2127
2128    // Step 4: update the following fixture data with the new values from above.
2129    let certificate_data = const_str::hex!(
2130        "100119697a0000000000002221056c9d1f8deb82b9a898f9c277a1b74989ec009afb5c0acb5e8e69e3d5ca29d6322a690a2508011221053b03ca070e6f6b2f271d32f27321689cdf4e59b106c10b58fbe15063ed868a5a124024bc92954e52ad1a105b5bda85c9db410dcfeb42a671b45a523b3a46e9594a8bde0efc671d8e8e046b32c67f59b80a46ffdf24071850779bc21325107902af89322461616161616161612d373030302d313165622d623332612d333362386138613438376136ba3e136372617368696e6720726967687420646f776e"
2131    );
2132    let certificate_signature = const_str::hex!(
2133        "a22d8f86f5d00794f319add821e342c6ffffb6b34f741e569f8b321ab0255f2d1757ecf648e53a3602cae8f09b3fc80dcf27534d67efd272b6739afc31f75c8c"
2134    );
2135
2136    let sender_certificate_data = proto::sealed_sender::SenderCertificate {
2137        certificate: Some(certificate_data.to_vec()),
2138        signature: Some(certificate_signature.to_vec()),
2139    };
2140
2141    let sender_certificate =
2142        SenderCertificate::deserialize(&sender_certificate_data.encode_to_vec())?;
2143    assert_eq!(
2144        sender_certificate.sender_uuid().expect("valid"),
2145        "aaaaaaaa-7000-11eb-b32a-33b8a8a487a6",
2146    );
2147    assert_eq!(sender_certificate.sender_e164().expect("valid"), None);
2148    assert_eq!(
2149        sender_certificate.sender_device_id().expect("valid"),
2150        DeviceId::new(1).expect("valid"),
2151    );
2152    assert_eq!(
2153        sender_certificate
2154            .expiration()
2155            .expect("valid")
2156            .epoch_millis(),
2157        31337
2158    );
2159    assert!(sender_certificate.validate(
2160        &trust_root.public_key()?,
2161        Timestamp::from_epoch_millis(31336)
2162    )?);
2163    Ok(())
2164}
2165
2166#[test]
2167fn test_uuid_bytes_representation() -> Result<()> {
2168    let trust_root = PrivateKey::deserialize(&[0u8; 32])?;
2169
2170    // Same structure as above, but using the uuidBytes representation instead of uuidString.
2171    let certificate_data = const_str::hex!(
2172        "100119697a000000000000222105e083a8ce423d1c1955174107a85a6a7f3bcbf566723624077f75eafe8e0a07752a690a25080112210507a24397ae27d06fa76d2f02cfb5546e0b23a7e0c3670c1eb1e73b135a8e1e4d12407d127509ae1f5e9dcaa511793d3e94350dcb269e4ca54500da6e1f4dc13d95940c15badef019edfe8666315500c54e4489d4b83f6ce79c7f65c9772a1a83d88c3a10aaaaaaaa700011ebb32a33b8a8a487a6"
2173    );
2174    let certificate_signature = const_str::hex!(
2175        "755c428e9bf6ba367152f1e545834649b4e8f70df8383a352a953fdb774862af5d42fab573fc52b90ad47c331c36f93b1a4fa7a2504917d895452ffe7f44bd0e"
2176    );
2177
2178    let sender_certificate_data = proto::sealed_sender::SenderCertificate {
2179        certificate: Some(certificate_data.to_vec()),
2180        signature: Some(certificate_signature.to_vec()),
2181    };
2182
2183    let sender_certificate =
2184        SenderCertificate::deserialize(&sender_certificate_data.encode_to_vec())?;
2185    assert_eq!(
2186        sender_certificate.sender_uuid().expect("valid"),
2187        "aaaaaaaa-7000-11eb-b32a-33b8a8a487a6",
2188    );
2189    assert_eq!(sender_certificate.sender_e164().expect("valid"), None);
2190    assert_eq!(
2191        sender_certificate.sender_device_id().expect("valid"),
2192        DeviceId::new(1).expect("valid"),
2193    );
2194    assert_eq!(
2195        sender_certificate
2196            .expiration()
2197            .expect("valid")
2198            .epoch_millis(),
2199        31337
2200    );
2201    assert!(sender_certificate.validate(
2202        &trust_root.public_key()?,
2203        Timestamp::from_epoch_millis(31336)
2204    )?);
2205    Ok(())
2206}
2207
2208#[test]
2209fn test_known_server_cert() -> Result<()> {
2210    // Same structure as test_lossless_round_trip, but using the fixed server key from the 7357c357
2211    // certificate, and a reference to it rather than embedding it.
2212    //
2213    // % pbpaste | xxd -r -p | protoscope
2214    // 2: 1
2215    // 3: 31337i64
2216    // 4: {`05d75b13e15c7700079dd226f51e5a790ba395e819e88a74d0cf5cedfad8b43348`}
2217    // 8: 1935131479
2218    // 6: {"aaaaaaaa-7000-11eb-b32a-33b8a8a487a6"}
2219
2220    let trust_root = PrivateKey::deserialize(&[0u8; 32])?;
2221    // let server_key = PrivateKey::deserialize(&[0xff; 32])?;
2222
2223    let certificate_data = const_str::hex!(
2224        "100119697a000000000000222105d75b13e15c7700079dd226f51e5a790ba395e819e88a74d0cf5cedfad8b4334840d786df9a07322461616161616161612d373030302d313165622d623332612d333362386138613438376136"
2225    );
2226    let certificate_signature = const_str::hex!(
2227        "e62667bce627caed56ca2ab309b6ae7bc890a30a7482c0e1fd77ec9c3b7528abfd45c8c42b240509a71d973ef5e0f1dbd2685fe01410f0fdbaa8fb247a67e08f"
2228    );
2229
2230    let sender_certificate_data = proto::sealed_sender::SenderCertificate {
2231        certificate: Some(certificate_data.to_vec()),
2232        signature: Some(certificate_signature.to_vec()),
2233    };
2234
2235    let sender_certificate =
2236        SenderCertificate::deserialize(&sender_certificate_data.encode_to_vec())?;
2237    assert!(sender_certificate.validate(
2238        &trust_root.public_key()?,
2239        Timestamp::from_epoch_millis(31336)
2240    )?);
2241
2242    Ok(())
2243}
2244
2245#[test]
2246fn verify_known_certificates() {
2247    assert!(
2248        KNOWN_SERVER_CERTIFICATES
2249            .iter()
2250            .map(|(id, _trust_root, _cert)| id)
2251            .all_unique(),
2252        "all known certificate IDs must be unique"
2253    );
2254
2255    for (id, trust_root, cert) in KNOWN_SERVER_CERTIFICATES {
2256        let trust_root = PublicKey::deserialize(trust_root)
2257            .unwrap_or_else(|e| panic!("[{id:x}] has invalid trust root: {e}"));
2258        let cert = ServerCertificate::deserialize(cert)
2259            .unwrap_or_else(|e| panic!("[{id:x}] has invalid certificate data: {e}"));
2260        assert_eq!(*id, cert.key_id, "[{id:x}] mismatched certificate ID");
2261        assert!(
2262            cert.validate(&trust_root).expect("can validate"),
2263            "[{id:x}] has wrong trust root"
2264        );
2265    }
2266}