libsignal_service/
envelope.rs

1use aes::cipher::block_padding::Pkcs7;
2use aes::cipher::{BlockDecryptMut, KeyIvInit};
3use libsignal_protocol::ServiceId;
4use prost::Message;
5
6use crate::{configuration::SignalingKey, push_service::ServiceError};
7
8pub use crate::proto::Envelope;
9
10impl Envelope {
11    #[expect(clippy::result_large_err)]
12    #[tracing::instrument(skip(input, signaling_key), fields(signaling_key_present = signaling_key.is_some(), input_size = input.len()))]
13    pub fn decrypt(
14        input: &[u8],
15        signaling_key: Option<&SignalingKey>,
16        is_signaling_key_encrypted: bool,
17    ) -> Result<Self, ServiceError> {
18        if !is_signaling_key_encrypted {
19            tracing::trace!("Envelope::decrypt: not encrypted");
20            Ok(Envelope::decode(input)?)
21        } else {
22            let signaling_key = signaling_key
23                .expect("signaling_key required to decrypt envelopes");
24            tracing::trace!("Envelope::decrypt: decrypting");
25            if input.len() < VERSION_LENGTH
26                || input[VERSION_OFFSET] != SUPPORTED_VERSION
27            {
28                return Err(ServiceError::InvalidFrame {
29                    reason: "unsupported signaling cryptogram version",
30                });
31            }
32
33            let aes_key = &signaling_key[..CIPHER_KEY_SIZE];
34            let mac_key = &signaling_key[CIPHER_KEY_SIZE..];
35            let mac = &input[(input.len() - MAC_SIZE)..];
36            let input_for_mac = &input[..(input.len() - MAC_SIZE)];
37            let iv = &input[IV_OFFSET..(IV_OFFSET + IV_LENGTH)];
38            debug_assert_eq!(mac_key.len(), MAC_KEY_SIZE);
39            debug_assert_eq!(aes_key.len(), CIPHER_KEY_SIZE);
40            debug_assert_eq!(iv.len(), IV_LENGTH);
41
42            // Verify MAC
43            use hmac::{Hmac, Mac};
44            use sha2::Sha256;
45            let mut verifier = Hmac::<Sha256>::new_from_slice(mac_key)
46                .expect("Hmac can take any size key");
47            verifier.update(input_for_mac);
48            // XXX: possible timing attack, but we need the bytes for a
49            // truncated view...
50            let our_mac = verifier.finalize().into_bytes();
51            if &our_mac[..MAC_SIZE] != mac {
52                return Err(ServiceError::MacError);
53            }
54
55            // libsignal-service-java uses Pkcs5,
56            // but that should not matter.
57            // https://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding
58            let cipher =
59                cbc::Decryptor::<aes::Aes256>::new(aes_key.into(), iv.into());
60            let input = &input[CIPHERTEXT_OFFSET..(input.len() - MAC_SIZE)];
61            let input = cipher
62                .decrypt_padded_vec_mut::<Pkcs7>(input)
63                .expect("decryption");
64
65            tracing::trace!("Envelope::decrypt: decrypted, decoding");
66
67            Ok(Envelope::decode(&input as &[u8])?)
68        }
69    }
70
71    pub fn is_unidentified_sender(&self) -> bool {
72        self.r#type() == crate::proto::envelope::Type::UnidentifiedSender
73    }
74
75    pub fn is_prekey_signal_message(&self) -> bool {
76        self.r#type() == crate::proto::envelope::Type::PrekeyBundle
77    }
78
79    pub fn is_receipt(&self) -> bool {
80        self.r#type() == crate::proto::envelope::Type::ServerDeliveryReceipt
81    }
82
83    pub fn is_signal_message(&self) -> bool {
84        self.r#type() == crate::proto::envelope::Type::Ciphertext
85    }
86
87    pub fn is_urgent(&self) -> bool {
88        // SignalServiceEnvelopeEntity: return urgent == null || urgent;
89        self.urgent.unwrap_or(true)
90    }
91
92    pub fn is_story(&self) -> bool {
93        self.story.unwrap_or(false)
94    }
95
96    pub fn source_address(&self) -> ServiceId {
97        match self.source_service_id.as_deref() {
98            Some(service_id) => {
99                ServiceId::parse_from_service_id_string(service_id)
100                    .expect("invalid source ProtocolAddress UUID or prefix")
101            },
102            None => panic!("source_service_id is set"),
103        }
104    }
105
106    pub fn destination_address(&self) -> ServiceId {
107        match self.destination_service_id.as_deref() {
108            Some(service_id) => ServiceId::parse_from_service_id_string(
109                service_id,
110            )
111            .expect("invalid destination ProtocolAddress UUID or prefix"),
112            None => panic!("destination_address is set"),
113        }
114    }
115}
116
117pub(crate) const SUPPORTED_VERSION: u8 = 1;
118pub(crate) const CIPHER_KEY_SIZE: usize = 32;
119pub(crate) const MAC_KEY_SIZE: usize = 20;
120pub(crate) const MAC_SIZE: usize = 10;
121
122pub(crate) const VERSION_OFFSET: usize = 0;
123pub(crate) const VERSION_LENGTH: usize = 1;
124pub(crate) const IV_OFFSET: usize = VERSION_OFFSET + VERSION_LENGTH;
125pub(crate) const IV_LENGTH: usize = 16;
126pub(crate) const CIPHERTEXT_OFFSET: usize = IV_OFFSET + IV_LENGTH;
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131
132    #[test]
133    fn decrypt_envelope() {
134        // This is a real message, reencrypted with the zero-key.
135        let body = [
136            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 32, 12, 100,
137            26, 157, 130, 210, 254, 174, 87, 45, 238, 126, 68, 39, 188, 171,
138            156, 16, 10, 138, 233, 73, 202, 52, 125, 102, 121, 182, 71, 148, 8,
139            3, 134, 149, 154, 67, 116, 40, 146, 253, 242, 196, 139, 203, 14,
140            174, 254, 78, 27, 47, 108, 60, 202, 60, 42, 210, 242, 58, 13, 185,
141            67, 147, 166, 191, 71, 164, 128, 81, 177, 199, 147, 252, 162, 229,
142            143, 98, 141, 222, 46, 83, 109, 82, 196, 109, 161, 40, 108, 207,
143            82, 53, 162, 205, 171, 33, 140, 5, 74, 76, 150, 22, 122, 176, 189,
144            228, 176, 234, 176, 13, 118, 181, 134, 35, 133, 164, 160, 205, 176,
145            32, 188, 185, 166, 73, 24, 164, 20, 187, 2, 226, 186, 238, 98, 57,
146            51, 76, 156, 83, 113, 72, 184, 50, 220, 49, 138, 46, 36, 4, 49,
147            215, 66, 173, 58, 139, 187, 6, 252, 97, 191, 69, 246, 82, 48, 177,
148            11, 149, 168, 93, 15, 170, 125, 131, 101, 103, 253, 177, 165, 71,
149            85, 219, 207, 106, 12, 58, 47, 159, 33, 243, 107, 6, 117, 141, 209,
150            115, 207, 19, 236, 137, 195, 230, 167, 225, 172, 99, 204, 113, 125,
151            69, 125, 97, 252, 90, 248, 198, 175, 240, 187, 246, 164, 220, 102,
152            7, 224, 124, 28, 170, 6, 4, 137, 155, 233, 85, 125, 93, 119, 97,
153            183, 114, 193, 10, 184, 191, 202, 109, 97, 116, 194, 152, 40, 46,
154            202, 49, 195, 138, 14, 2, 255, 44, 107, 160, 45, 150, 6, 78, 145,
155            99,
156        ];
157
158        let signaling_key = [0u8; 52];
159        let envelope =
160            Envelope::decrypt(&body, Some(&signaling_key), true).unwrap();
161        assert_eq!(envelope.server_timestamp(), 1594373582421);
162        assert_eq!(envelope.timestamp(), 1594373580977);
163        assert_eq!(
164            envelope.content(),
165            [
166                51, 10, 33, 5, 239, 254, 183, 191, 204, 223, 85, 150, 43, 192,
167                240, 57, 46, 189, 153, 7, 48, 17, 9, 166, 185, 157, 205, 181,
168                66, 235, 99, 221, 114, 58, 187, 117, 16, 76, 24, 0, 34, 160, 1,
169                85, 61, 73, 83, 99, 213, 160, 109, 122, 125, 204, 137, 178,
170                237, 146, 87, 183, 107, 33, 213, 234, 64, 152, 132, 122, 173,
171                25, 33, 4, 65, 20, 134, 117, 62, 116, 80, 151, 18, 132, 187,
172                101, 235, 208, 74, 78, 214, 66, 59, 71, 171, 124, 167, 217,
173                157, 36, 194, 156, 12, 50, 239, 185, 230, 253, 38, 107, 106,
174                149, 194, 39, 214, 35, 245, 58, 216, 250, 225, 150, 170, 26,
175                241, 153, 133, 173, 197, 194, 27, 127, 56, 77, 119, 242, 26,
176                252, 168, 61, 221, 44, 76, 128, 69, 27, 203, 6, 173, 193, 179,
177                69, 27, 243, 36, 185, 181, 157, 41, 23, 72, 113, 40, 209, 46,
178                189, 63, 167, 156, 148, 118, 76, 153, 91, 40, 179, 180, 245,
179                193, 123, 180, 47, 115, 220, 191, 148, 245, 116, 32, 194, 232,
180                55, 13, 0, 217, 52, 116, 21, 48, 244, 17, 222, 26, 240, 31,
181                236, 199, 237, 94, 255, 93, 137, 192,
182            ]
183        );
184    }
185}