legacy_omemo.rs

  1// Copyright (c) 2022 Yureka Lilian <yuka@yuka.dev>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use crate::message::MessagePayload;
  8use crate::pubsub::PubSubPayload;
  9use crate::util::helpers::Base64;
 10
 11generate_element!(
 12    /// Element of the device list
 13    Device, "device", LEGACY_OMEMO,
 14    attributes: [
 15        /// Device id
 16        id: Required<u32> = "id"
 17    ]
 18);
 19
 20generate_element!(
 21    /// A user's device list contains the OMEMO device ids of all the user's
 22    /// devicse. These can be used to look up bundles and build a session.
 23    DeviceList, "list", LEGACY_OMEMO,
 24    children: [
 25        /// List of devices
 26        devices: Vec<Device> = ("device", LEGACY_OMEMO) => Device
 27    ]
 28);
 29
 30impl PubSubPayload for DeviceList {}
 31
 32generate_element!(
 33    /// SignedPreKey public key
 34    /// Part of a device's bundle
 35    SignedPreKeyPublic, "signedPreKeyPublic", LEGACY_OMEMO,
 36    attributes: [
 37        /// SignedPreKey id
 38        signed_pre_key_id: Option<u32> = "signedPreKeyId"
 39    ],
 40    text: (
 41        /// Serialized PublicKey
 42        data: Base64<Vec<u8>>
 43    )
 44);
 45
 46generate_element!(
 47    /// SignedPreKey signature
 48    /// Part of a device's bundle
 49    SignedPreKeySignature, "signedPreKeySignature", LEGACY_OMEMO,
 50    text: (
 51        /// Signature bytes
 52        data: Base64<Vec<u8>>
 53    )
 54);
 55
 56generate_element!(
 57    /// Part of a device's bundle
 58    IdentityKey, "identityKey", LEGACY_OMEMO,
 59    text: (
 60        /// Serialized PublicKey
 61        data: Base64<Vec<u8>>
 62    )
 63);
 64
 65generate_element!(
 66    /// List of (single use) PreKeys
 67    /// Part of a device's bundle
 68    Prekeys, "prekeys", LEGACY_OMEMO,
 69    children: [
 70        /// List of (single use) PreKeys
 71        keys: Vec<PreKeyPublic> = ("preKeyPublic", LEGACY_OMEMO) => PreKeyPublic,
 72    ]
 73);
 74
 75generate_element!(
 76    /// PreKey public key
 77    /// Part of a device's bundle
 78    PreKeyPublic, "preKeyPublic", LEGACY_OMEMO,
 79    attributes: [
 80        /// PreKey id
 81        pre_key_id: Required<u32> = "preKeyId",
 82    ],
 83    text: (
 84        /// Serialized PublicKey
 85        data: Base64<Vec<u8>>
 86    )
 87);
 88
 89generate_element!(
 90    /// A collection of publicly accessible data that can be used to build a session with a device, namely its public IdentityKey, a signed PreKey with corresponding signature, and a list of (single use) PreKeys.
 91    Bundle, "bundle", LEGACY_OMEMO,
 92    children: [
 93        /// SignedPreKey public key
 94        signed_pre_key_public: Option<SignedPreKeyPublic> = ("signedPreKeyPublic", LEGACY_OMEMO) => SignedPreKeyPublic,
 95        /// SignedPreKey signature
 96        signed_pre_key_signature: Option<SignedPreKeySignature> = ("signedPreKeySignature", LEGACY_OMEMO) => SignedPreKeySignature,
 97        /// IdentityKey public key
 98        identity_key: Option<IdentityKey> = ("identityKey", LEGACY_OMEMO) => IdentityKey,
 99        /// List of (single use) PreKeys
100        prekeys: Option<Prekeys> = ("prekeys", LEGACY_OMEMO) => Prekeys,
101    ]
102);
103
104impl PubSubPayload for Bundle {}
105
106generate_element!(
107    /// The header contains encrypted keys for a message
108    Header, "header", LEGACY_OMEMO,
109    attributes: [
110        /// The device id of the sender
111        sid: Required<u32> = "sid",
112    ],
113    children: [
114        /// The key that the payload message is encrypted with, separately
115        /// encrypted for each recipient device.
116        keys: Vec<Key> = ("key", LEGACY_OMEMO) => Key,
117
118        /// IV used for payload encryption
119        iv: Required<IV> = ("iv", LEGACY_OMEMO) => IV
120    ]
121);
122
123generate_element!(
124    /// IV used for payload encryption
125    IV, "iv", LEGACY_OMEMO,
126    text: (
127        /// IV bytes
128        data: Base64<Vec<u8>>
129    )
130);
131
132generate_attribute!(
133    /// prekey attribute for the key element.
134    IsPreKey,
135    "prekey",
136    bool
137);
138
139generate_element!(
140    /// Part of the OMEMO element header
141    Key, "key", LEGACY_OMEMO,
142    attributes: [
143        /// The device id this key is encrypted for.
144        rid: Required<u32> = "rid",
145
146        /// The key element MUST be tagged with a prekey attribute set to true
147        /// if a PreKeySignalMessage is being used.
148        prekey: Default<IsPreKey> = "prekey",
149    ],
150    text: (
151        /// The 16 bytes key and the GCM authentication tag concatenated together
152        /// and encrypted using the corresponding long-standing SignalProtocol
153        /// session
154        data: Base64<Vec<u8>>
155    )
156);
157
158generate_element!(
159    /// The encrypted message body
160    Payload, "payload", LEGACY_OMEMO,
161    text: (
162        /// Encrypted with AES-128 in Galois/Counter Mode (GCM)
163        data: Base64<Vec<u8>>
164    )
165);
166
167generate_element!(
168    /// An OMEMO element, which can be either a MessageElement (with payload),
169    /// or a KeyTransportElement (without payload).
170    Encrypted, "encrypted", LEGACY_OMEMO,
171    children: [
172        /// The header contains encrypted keys for a message
173        header: Required<Header> = ("header", LEGACY_OMEMO) => Header,
174        /// Payload for MessageElement
175        payload: Option<Payload> = ("payload", LEGACY_OMEMO) => Payload
176    ]
177);
178
179impl MessagePayload for Encrypted {}
180
181#[cfg(test)]
182mod tests {
183    use super::*;
184    use crate::Element;
185    use std::convert::TryInto;
186
187    #[test]
188    fn parse_bundle() {
189        let elem: Element = r#"<bundle xmlns="eu.siacs.conversations.axolotl">
190  <signedPreKeyPublic signedPreKeyId="1">BYAbACA15bPn95p7RGC2XbgQyly8aRKS4BaJ+hD8Ybhe</signedPreKeyPublic>
191  <signedPreKeySignature>sIJVNDZi/NgFsry4OBdM+adyGttLEXbUh/h/5dVOZveMgyVoIdgwBUzq8Wgd2xYTQMioNzwYebTX+9p0h9eujA==</signedPreKeySignature>
192  <identityKey>BQFd2p/Oq97vAAdLKA09DlcSg0x1xWn260p1jaeyIhAZ</identityKey>
193  <prekeys>
194    <preKeyPublic preKeyId="1">BbjHsF5ndtNV8ToRcJTYSNGePgAWsFGkSL6OG7B7LXRe</preKeyPublic>
195    <preKeyPublic preKeyId="2">BeWHsbBNx1uer1ia/nW/6tn/OlqHll9itjjUTIvV39x7</preKeyPublic>
196    <preKeyPublic preKeyId="3">BeVr5xPmNErkwK3ocPmv0Nohy3C4PKQBnxMuOqiXotJY</preKeyPublic>
197  </prekeys>
198</bundle>
199        "#.parse().unwrap();
200        let bundle: Bundle = elem.try_into().unwrap();
201        let bundle2 = Bundle {
202            signed_pre_key_public: Some(SignedPreKeyPublic {
203                signed_pre_key_id: Some(1),
204                data: vec![
205                    5, 128, 27, 0, 32, 53, 229, 179, 231, 247, 154, 123, 68, 96, 182, 93, 184, 16,
206                    202, 92, 188, 105, 18, 146, 224, 22, 137, 250, 16, 252, 97, 184, 94,
207                ],
208            }),
209            signed_pre_key_signature: Some(SignedPreKeySignature {
210                data: vec![
211                    176, 130, 85, 52, 54, 98, 252, 216, 5, 178, 188, 184, 56, 23, 76, 249, 167,
212                    114, 26, 219, 75, 17, 118, 212, 135, 248, 127, 229, 213, 78, 102, 247, 140,
213                    131, 37, 104, 33, 216, 48, 5, 76, 234, 241, 104, 29, 219, 22, 19, 64, 200, 168,
214                    55, 60, 24, 121, 180, 215, 251, 218, 116, 135, 215, 174, 140,
215                ],
216            }),
217            identity_key: Some(IdentityKey {
218                data: vec![
219                    5, 1, 93, 218, 159, 206, 171, 222, 239, 0, 7, 75, 40, 13, 61, 14, 87, 18, 131,
220                    76, 117, 197, 105, 246, 235, 74, 117, 141, 167, 178, 34, 16, 25,
221                ],
222            }),
223            prekeys: Some(Prekeys {
224                keys: vec![
225                    PreKeyPublic {
226                        pre_key_id: 1,
227                        data: vec![
228                            5, 184, 199, 176, 94, 103, 118, 211, 85, 241, 58, 17, 112, 148, 216,
229                            72, 209, 158, 62, 0, 22, 176, 81, 164, 72, 190, 142, 27, 176, 123, 45,
230                            116, 94,
231                        ],
232                    },
233                    PreKeyPublic {
234                        pre_key_id: 2,
235                        data: vec![
236                            5, 229, 135, 177, 176, 77, 199, 91, 158, 175, 88, 154, 254, 117, 191,
237                            234, 217, 255, 58, 90, 135, 150, 95, 98, 182, 56, 212, 76, 139, 213,
238                            223, 220, 123,
239                        ],
240                    },
241                    PreKeyPublic {
242                        pre_key_id: 3,
243                        data: vec![
244                            5, 229, 107, 231, 19, 230, 52, 74, 228, 192, 173, 232, 112, 249, 175,
245                            208, 218, 33, 203, 112, 184, 60, 164, 1, 159, 19, 46, 58, 168, 151,
246                            162, 210, 88,
247                        ],
248                    },
249                ],
250            }),
251        };
252        assert_eq!(bundle, bundle2);
253    }
254    #[test]
255    fn parse_device_list() {
256        let elem: Element = r#"<list xmlns="eu.siacs.conversations.axolotl">
257  <device id="1164059891" />
258  <device id="26052318" />
259  <device id="564866972" />
260</list>
261        "#
262        .parse()
263        .unwrap();
264        let list: DeviceList = elem.try_into().unwrap();
265        let list2 = DeviceList {
266            devices: vec![
267                Device { id: 1164059891 },
268                Device { id: 26052318 },
269                Device { id: 564866972 },
270            ],
271        };
272        assert_eq!(list, list2);
273    }
274    #[test]
275    fn parse_encrypted() {
276        let elem: Element = r#"<encrypted xmlns="eu.siacs.conversations.axolotl">
277  <header sid="564866972">
278    <key prekey="true" rid="1236">Mwjp9AESIQVylscLPpj/HlowaTiIsaBj73HCVEllXpVTtMG9EYwRexohBQFd2p/Oq97vAAdLKA09DlcSg0x1xWn260p1jaeyIhAZImIzCiEFhaQ4I+DuQgo6vCLCjHu4uewDZmWHuBl8uJw1IkyZxhUQABgAIjCoEVgVThWlaIlnN3V5Bg1hQX7OD1cvstLD5lH3zZMadL3KeONELESlBbeKmNgcYC/e3HZnbgWzBiic36yNAjAW</key>
279    <key rid="26052318">MwohBTV6dpumL1OxA9MdIFmu2E19+cIWDHWYfhdubvo0hmh6EAAYHCIwNc9/59eeYi8pVZQhMJJMVkKUkFP/yrTfG3o1lfpHGseCqb/JTgtDytQPiYrTpHl2V/mdsM6IPig=</key>
280    <key rid="1164059891">MwohBVnhz9pvEj1s1waEHuk5qpQqhUrpavycFz0hq/KYwI8oEAAYCSIwedEGN6MidxyvaPI8zorLcpG0Y7e7ecGkkd5vdDrL7Qt1tXaHb0iDyE/rZZHpFiNN38Izfp5vHv4=</key>
281    <iv>SY/SCGPt0CnA2odB</iv>
282  </header>
283  <payload>Vas=</payload>
284</encrypted>
285        "#.parse().unwrap();
286        let encrypted: Encrypted = elem.try_into().unwrap();
287        let encrypted2 = Encrypted {
288            header: Header {
289                sid: 564866972,
290                keys: vec![
291                    Key {
292                        rid: 1236,
293                        prekey: IsPreKey::True,
294                        data: vec![
295                            51, 8, 233, 244, 1, 18, 33, 5, 114, 150, 199, 11, 62, 152, 255, 30, 90,
296                            48, 105, 56, 136, 177, 160, 99, 239, 113, 194, 84, 73, 101, 94, 149,
297                            83, 180, 193, 189, 17, 140, 17, 123, 26, 33, 5, 1, 93, 218, 159, 206,
298                            171, 222, 239, 0, 7, 75, 40, 13, 61, 14, 87, 18, 131, 76, 117, 197,
299                            105, 246, 235, 74, 117, 141, 167, 178, 34, 16, 25, 34, 98, 51, 10, 33,
300                            5, 133, 164, 56, 35, 224, 238, 66, 10, 58, 188, 34, 194, 140, 123, 184,
301                            185, 236, 3, 102, 101, 135, 184, 25, 124, 184, 156, 53, 34, 76, 153,
302                            198, 21, 16, 0, 24, 0, 34, 48, 168, 17, 88, 21, 78, 21, 165, 104, 137,
303                            103, 55, 117, 121, 6, 13, 97, 65, 126, 206, 15, 87, 47, 178, 210, 195,
304                            230, 81, 247, 205, 147, 26, 116, 189, 202, 120, 227, 68, 44, 68, 165,
305                            5, 183, 138, 152, 216, 28, 96, 47, 222, 220, 118, 103, 110, 5, 179, 6,
306                            40, 156, 223, 172, 141, 2, 48, 22,
307                        ],
308                    },
309                    Key {
310                        rid: 26052318,
311                        prekey: IsPreKey::False,
312                        data: vec![
313                            51, 10, 33, 5, 53, 122, 118, 155, 166, 47, 83, 177, 3, 211, 29, 32, 89,
314                            174, 216, 77, 125, 249, 194, 22, 12, 117, 152, 126, 23, 110, 110, 250,
315                            52, 134, 104, 122, 16, 0, 24, 28, 34, 48, 53, 207, 127, 231, 215, 158,
316                            98, 47, 41, 85, 148, 33, 48, 146, 76, 86, 66, 148, 144, 83, 255, 202,
317                            180, 223, 27, 122, 53, 149, 250, 71, 26, 199, 130, 169, 191, 201, 78,
318                            11, 67, 202, 212, 15, 137, 138, 211, 164, 121, 118, 87, 249, 157, 176,
319                            206, 136, 62, 40,
320                        ],
321                    },
322                    Key {
323                        rid: 1164059891,
324                        prekey: IsPreKey::False,
325                        data: vec![
326                            51, 10, 33, 5, 89, 225, 207, 218, 111, 18, 61, 108, 215, 6, 132, 30,
327                            233, 57, 170, 148, 42, 133, 74, 233, 106, 252, 156, 23, 61, 33, 171,
328                            242, 152, 192, 143, 40, 16, 0, 24, 9, 34, 48, 121, 209, 6, 55, 163, 34,
329                            119, 28, 175, 104, 242, 60, 206, 138, 203, 114, 145, 180, 99, 183, 187,
330                            121, 193, 164, 145, 222, 111, 116, 58, 203, 237, 11, 117, 181, 118,
331                            135, 111, 72, 131, 200, 79, 235, 101, 145, 233, 22, 35, 77, 223, 194,
332                            51, 126, 158, 111, 30, 254,
333                        ],
334                    },
335                ],
336                iv: IV {
337                    data: vec![73, 143, 210, 8, 99, 237, 208, 41, 192, 218, 135, 65],
338                },
339            },
340            payload: Some(Payload {
341                data: vec![85, 171],
342            }),
343        };
344        assert_eq!(encrypted, encrypted2);
345    }
346}