QXmpp  Version: 1.10.4
QXmppOmemoManager_p.h
1 // SPDX-FileCopyrightText: 2022 Melvin Keskin <melvo@olomono.de>
2 // SPDX-FileCopyrightText: 2022 Linus Jahn <lnj@kaidan.im>
3 //
4 // SPDX-License-Identifier: LGPL-2.1-or-later
5 
6 #ifndef QXMPPOMEMOMANAGER_P_H
7 #define QXMPPOMEMOMANAGER_P_H
8 
9 #include "QXmppConstants_p.h"
10 #include "QXmppE2eeMetadata.h"
11 #include "QXmppOmemoDeviceBundle_p.h"
12 #include "QXmppOmemoManager.h"
13 #include "QXmppOmemoStorage.h"
14 #include "QXmppPubSubManager.h"
15 
16 #include "OmemoLibWrappers.h"
17 #include "QcaInitializer_p.h"
18 
19 #include <QDomElement>
20 #include <QTimer>
21 #include <QtCrypto>
22 
23 #undef max
24 
25 class QXmppTrustManager;
26 class QXmppOmemoManager;
27 class QXmppPubSubManager;
28 class QXmppPubSubNodeConfig;
29 class QXmppPubSubPublishOptions;
30 class QXmppOmemoIq;
31 class QXmppOmemoEnvelope;
32 class QXmppOmemoElement;
33 class QXmppOmemoDeviceListItem;
34 class QXmppOmemoDeviceBundleItem;
35 
36 using namespace QXmpp;
37 using namespace std::chrono_literals;
38 
39 namespace QXmpp::Omemo::Private {
40 
41 // default possible trust levels a key must have to be used for encryption
42 // The class documentation must be adapted if the trust levels are modified.
44 
45 // count of unresponded stanzas sent to a device until QXmpp stops encrypting for it
46 constexpr int UNRESPONDED_STANZAS_UNTIL_ENCRYPTION_IS_STOPPED = 106;
47 
48 // count of unresponded stanzas received from a device until a heartbeat message is sent to it
49 constexpr int UNRESPONDED_STANZAS_UNTIL_HEARTBEAT_MESSAGE_IS_SENT = 53;
50 
51 // size of empty OMEMO message's decryption data
52 constexpr int EMPTY_MESSAGE_DECRYPTION_DATA_SIZE = 32;
53 
54 // workaround for PubSub nodes that are not configurable to store 'max' as the value for
55 // 'pubsub#max_items'
56 constexpr uint64_t PUBSUB_NODE_MAX_ITEMS_1 = 1000;
57 constexpr uint64_t PUBSUB_NODE_MAX_ITEMS_2 = 100;
58 constexpr uint64_t PUBSUB_NODE_MAX_ITEMS_3 = 10;
59 
60 constexpr uint32_t PRE_KEY_ID_MIN = 1;
61 constexpr uint32_t SIGNED_PRE_KEY_ID_MIN = 1;
62 constexpr uint32_t PRE_KEY_ID_MAX = std::numeric_limits<int32_t>::max();
63 constexpr uint32_t SIGNED_PRE_KEY_ID_MAX = std::numeric_limits<int32_t>::max();
64 constexpr uint32_t PRE_KEY_INITIAL_CREATION_COUNT = 100;
65 
66 // maximum count of devices stored per JID
67 constexpr int DEVICES_PER_JID_MAX = 200;
68 
69 // maximum count of devices for whom a stanza is encrypted
70 constexpr int DEVICES_PER_STANZA_MAX = 1000;
71 
72 // interval to remove old signed pre keys and create new ones
73 constexpr auto SIGNED_PRE_KEY_RENEWAL_INTERVAL = 24h * 7 * 4;
74 
75 // interval to check for old signed pre keys
76 constexpr auto SIGNED_PRE_KEY_RENEWAL_CHECK_INTERVAL = 24h;
77 
78 // interval to remove devices locally after removal from their servers
79 constexpr auto DEVICE_REMOVAL_INTERVAL = 24h * 7 * 12;
80 
81 // interval to check for devices removed from their servers
82 constexpr auto DEVICE_REMOVAL_CHECK_INTERVAL = 24h;
83 
84 constexpr QStringView PAYLOAD_CIPHER_TYPE = u"aes256";
85 constexpr QCA::Cipher::Mode PAYLOAD_CIPHER_MODE = QCA::Cipher::CBC;
86 constexpr QCA::Cipher::Padding PAYLOAD_CIPHER_PADDING = QCA::Cipher::PKCS7;
87 
88 inline constexpr auto HKDF_INFO = "OMEMO Payload";
89 constexpr int HKDF_KEY_SIZE = 32;
90 constexpr int HKDF_SALT_SIZE = 32;
91 constexpr int HKDF_OUTPUT_SIZE = 80;
92 
93 inline constexpr QStringView PAYLOAD_MESSAGE_AUTHENTICATION_CODE_TYPE = u"hmac(sha256)";
94 constexpr uint32_t PAYLOAD_MESSAGE_AUTHENTICATION_CODE_SIZE = 16;
95 
96 constexpr int PAYLOAD_KEY_SIZE = 32;
97 constexpr uint32_t PAYLOAD_INITIALIZATION_VECTOR_SIZE = 16;
98 constexpr uint32_t PAYLOAD_AUTHENTICATION_KEY_SIZE = 32;
99 
100 // boundaries for the count of characters in SCE's <rpad/> element
101 constexpr uint32_t SCE_RPAD_SIZE_MIN = 0;
102 constexpr uint32_t SCE_RPAD_SIZE_MAX = 200;
103 
104 struct PayloadEncryptionResult {
105  QCA::SecureArray decryptionData;
106  QByteArray encryptedPayload;
107 };
108 
109 struct DecryptionResult {
110  QDomElement sceContent;
111  QXmppE2eeMetadata e2eeMetadata;
112 };
113 
114 struct IqDecryptionResult {
115  QDomElement iq;
116  QXmppE2eeMetadata e2eeMetadata;
117 };
118 
119 } // namespace QXmpp::Omemo::Private
120 
121 using namespace QXmpp::Private;
122 using namespace QXmpp::Omemo::Private;
123 
124 class QXmppOmemoManagerPrivate
125 {
126 public:
127  using Result = std::variant<QXmpp::Success, QXmppError>;
128 
130 
131  bool isStarted = false;
132  bool isNewDeviceAutoSessionBuildingEnabled = false;
133 
134  QXmppOmemoStorage *omemoStorage;
135  QXmppTrustManager *trustManager = nullptr;
136  QXmppPubSubManager *pubSubManager = nullptr;
137 
138  QcaInitializer cryptoLibInitializer;
139  QTimer signedPreKeyPairsRenewalTimer;
140  QTimer deviceRemovalTimer;
141 
142  TrustLevels acceptedSessionBuildingTrustLevels = ACCEPTED_TRUST_LEVELS;
143 
145  QHash<uint32_t, QByteArray> preKeyPairs;
146  QHash<uint32_t, QXmppOmemoStorage::SignedPreKeyPair> signedPreKeyPairs;
147  QXmppOmemoDeviceBundle deviceBundle;
148 
149  int maximumDevicesPerJid = DEVICES_PER_JID_MAX;
150  int maximumDevicesPerStanza = DEVICES_PER_STANZA_MAX;
151 
152  // recipient JID mapped to device ID mapped to device
153  QHash<QString, QHash<uint32_t, QXmppOmemoStorage::Device>> devices;
154 
155  QList<QString> jidsOfManuallySubscribedDevices;
156 
157  OmemoContextPtr globalContext;
158  StoreContextPtr storeContext;
159  QRecursiveMutex mutex;
160  signal_crypto_provider cryptoProvider;
161 
162  signal_protocol_identity_key_store identityKeyStore;
163  signal_protocol_pre_key_store preKeyStore;
164  signal_protocol_signed_pre_key_store signedPreKeyStore;
165  signal_protocol_session_store sessionStore;
166 
167  QXmppOmemoManagerPrivate(QXmppOmemoManager *parent, QXmppOmemoStorage *omemoStorage);
168 
169  void init();
170  // exports for unit tests
171  QXMPP_EXPORT bool initGlobalContext();
172  QXMPP_EXPORT bool initLocking();
173  QXMPP_EXPORT bool initCryptoProvider();
174  void initStores();
175 
176  signal_protocol_identity_key_store createIdentityKeyStore() const;
177  signal_protocol_signed_pre_key_store createSignedPreKeyStore() const;
178  signal_protocol_pre_key_store createPreKeyStore() const;
179  signal_protocol_session_store createSessionStore() const;
180 
181  QXmppTask<bool> setUpDeviceId();
182  std::optional<uint32_t> generateDeviceId();
183  std::optional<uint32_t> generateDeviceId(const QVector<QString> &existingIds);
184  bool setUpIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair);
185  void schedulePeriodicTasks();
186  void renewSignedPreKeyPairs();
187  bool updateSignedPreKeyPair(ratchet_identity_key_pair *identityKeyPair);
188  bool renewPreKeyPairs(uint32_t keyPairBeingRenewed);
189  bool updatePreKeyPairs(uint32_t count = 1);
190  void removeDevicesRemovedFromServer();
191 
192  QXmppTask<QXmppE2eeExtension::MessageEncryptResult> encryptMessageForRecipients(QXmppMessage &&message,
193  QVector<QString> recipientJids,
194  TrustLevels acceptedTrustLevels);
195  template<typename T>
196  QXmppTask<std::optional<QXmppOmemoElement>> encryptStanza(const T &stanza, const QVector<QString> &recipientJids, TrustLevels acceptedTrustLevels);
197  std::optional<PayloadEncryptionResult> encryptPayload(const QByteArray &payload) const;
198  template<typename T>
199  QByteArray createSceEnvelope(const T &stanza);
200  QByteArray createOmemoEnvelopeData(const signal_protocol_address &address, const QCA::SecureArray &payloadDecryptionData) const;
201 
202  QXmppTask<std::optional<QXmppMessage>> decryptMessage(QXmppMessage stanza);
203  QXmppTask<std::optional<IqDecryptionResult>> decryptIq(const QDomElement &iqElement);
204  template<typename T>
205  QXmppTask<std::optional<DecryptionResult>> decryptStanza(T stanza,
206  const QString &senderJid,
207  uint32_t senderDeviceId,
208  const QXmppOmemoEnvelope &omemoEnvelope,
209  const QByteArray &omemoPayload,
210  bool isMessageStanza = true);
211  QXmppTask<QByteArray> extractSceEnvelope(const QString &senderJid,
212  uint32_t senderDeviceId,
213  const QXmppOmemoEnvelope &omemoEnvelope,
214  const QByteArray &omemoPayload,
215  bool isMessageStanza);
216  QXmppTask<std::optional<QCA::SecureArray>> extractPayloadDecryptionData(const QString &senderJid,
217  uint32_t senderDeviceId,
218  const QXmppOmemoEnvelope &omemoEnvelope,
219  bool isMessageStanza = true);
220  QByteArray decryptPayload(const QCA::SecureArray &payloadDecryptionData, const QByteArray &payload) const;
221 
222  QXmppTask<bool> publishOmemoData();
223 
224  template<typename Function>
225  void publishDeviceBundle(bool isDeviceBundlesNodeExistent,
226  bool arePublishOptionsSupported,
227  bool isAutomaticCreationSupported,
228  bool isCreationAndConfigurationSupported,
229  bool isCreationSupported,
230  bool isConfigurationSupported,
231  bool isConfigNodeMaxSupported,
232  Function continuation);
233  template<typename Function>
234  void publishDeviceBundleWithoutOptions(bool isDeviceBundlesNodeExistent,
235  bool isCreationAndConfigurationSupported,
236  bool isCreationSupported,
237  bool isConfigurationSupported,
238  bool isConfigNodeMaxSupported,
239  Function continuation);
240  template<typename Function>
241  void configureNodeAndPublishDeviceBundle(bool isConfigNodeMaxSupported, Function continuation);
242  template<typename Function>
243  void createAndConfigureDeviceBundlesNode(bool isConfigNodeMaxSupported, Function continuation);
244  template<typename Function>
245  void createDeviceBundlesNode(Function continuation);
246  template<typename Function>
247  void configureDeviceBundlesNode(bool isConfigNodeMaxSupported, Function continuation);
248  template<typename Function>
249  void publishDeviceBundleItem(Function continuation);
250  template<typename Function>
251  void publishDeviceBundleItemWithOptions(Function continuation);
252  QXmppOmemoDeviceBundleItem deviceBundleItem() const;
253  QXmppTask<std::optional<QXmppOmemoDeviceBundle>> requestDeviceBundle(const QString &deviceOwnerJid, uint32_t deviceId) const;
254  template<typename Function>
255  void deleteDeviceBundle(Function continuation);
256 
257  template<typename Function>
258  void publishDeviceElement(bool isDeviceListNodeExistent,
259  bool arePublishOptionsSupported,
260  bool isAutomaticCreationSupported,
261  bool isCreationAndConfigurationSupported,
262  bool isCreationSupported,
263  bool isConfigurationSupported,
264  Function continuation);
265  template<typename Function>
266  void publishDeviceElementWithoutOptions(bool isDeviceListNodeExistent,
267  bool isCreationAndConfigurationSupported,
268  bool isCreationSupported,
269  bool isConfigurationSupported,
270  Function continuation);
271  template<typename Function>
272  void configureNodeAndPublishDeviceElement(Function continuation);
273  template<typename Function>
274  void createAndConfigureDeviceListNode(Function continuation);
275  template<typename Function>
276  void createDeviceListNode(Function continuation);
277  template<typename Function>
278  void configureDeviceListNode(Function continuation);
279  template<typename Function>
280  void publishDeviceListItem(bool addOwnDevice, Function continuation);
281  template<typename Function>
282  void publishDeviceListItemWithOptions(Function continuation);
283  QXmppOmemoDeviceListItem deviceListItem(bool addOwnDevice = true);
284  template<typename Function>
285  void updateOwnDevicesLocally(bool isDeviceListNodeExistent, Function continuation);
286  std::optional<QXmppOmemoDeviceListItem> updateContactDevices(const QString &deviceOwnerJid, const QVector<QXmppOmemoDeviceListItem> &deviceListItems);
287  void updateDevices(const QString &deviceOwnerJid, const QXmppOmemoDeviceListItem &deviceListItem);
288  void handleIrregularDeviceListChanges(const QString &deviceOwnerJid);
289  template<typename Function>
290  void deleteDeviceElement(Function continuation);
291 
292  template<typename Function>
293  void createNode(const QString &node, Function continuation);
294  template<typename Function>
295  void createNode(const QString &node, const QXmppPubSubNodeConfig &config, Function continuation);
296  template<typename Function>
297  void configureNode(const QString &node, const QXmppPubSubNodeConfig &config, Function continuation);
298  template<typename Function>
299  void retractItem(const QString &node, uint32_t itemId, Function continuation);
300  template<typename Function>
301  void deleteNode(const QString &node, Function continuation);
302 
303  template<typename T, typename Function>
304  void publishItem(const QString &node, const T &item, Function continuation);
305  template<typename T, typename Function>
306  void publishItem(const QString &node, const T &item, const QXmppPubSubPublishOptions &publishOptions, Function continuation);
307 
308  template<typename T, typename Function>
309  void runPubSubQueryWithContinuation(QXmppTask<T> future, const QString &errorMessage, Function continuation);
310 
311  QXmppTask<bool> changeDeviceLabel(const QString &deviceLabel);
312 
313  QXmppTask<QXmppPubSubManager::ItemResult<QXmppOmemoDeviceListItem>> requestDeviceList(const QString &jid);
314  void subscribeToNewDeviceLists(const QString &jid, uint32_t deviceId);
315  QXmppTask<Result> subscribeToDeviceList(const QString &jid);
316  QXmppTask<QVector<QXmppOmemoManager::DevicesResult>> unsubscribeFromDeviceLists(const QList<QString> &jids);
317  QXmppTask<Result> unsubscribeFromDeviceList(const QString &jid);
318 
319  QXmppTask<bool> resetOwnDevice();
320  QXmppTask<void> resetOwnDeviceLocally();
321  QXmppTask<bool> resetAll();
322  void resetCachedData();
323 
324  QXmppTask<bool> buildSessionForNewDevice(const QString &jid, uint32_t deviceId, QXmppOmemoStorage::Device &device);
325  QXmppTask<bool> buildSessionWithDeviceBundle(const QString &jid, uint32_t deviceId, QXmppOmemoStorage::Device &device);
326  bool buildSession(signal_protocol_address address, const QXmppOmemoDeviceBundle &deviceBundle);
327  bool createSessionBundle(session_pre_key_bundle **sessionBundle,
328  const QByteArray &serializedPublicIdentityKey,
329  const QByteArray &serializedSignedPublicPreKey,
330  uint32_t signedPublicPreKeyId,
331  const QByteArray &serializedSignedPublicPreKeySignature,
332  const QByteArray &serializedPublicPreKey,
333  uint32_t publicPreKeyId);
334 
335  bool deserializeIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair) const;
336  bool deserializePrivateIdentityKey(ec_private_key **privateIdentityKey, const QByteArray &serializedPrivateIdentityKey) const;
337  bool deserializePublicIdentityKey(ec_public_key **publicIdentityKey, const QByteArray &serializedPublicIdentityKey) const;
338  bool deserializeSignedPublicPreKey(ec_public_key **signedPublicPreKey, const QByteArray &serializedSignedPublicPreKey) const;
339  bool deserializePublicPreKey(ec_public_key **publicPreKey, const QByteArray &serializedPublicPreKey) const;
340 
341  QXmppTask<QXmpp::SendResult> sendEmptyMessage(const QString &recipientJid, uint32_t recipientDeviceId, bool isKeyExchange = false) const;
342  QXmppTask<void> storeOwnKey() const;
343  QXmppTask<TrustLevel> storeKeyDependingOnSecurityPolicy(const QString &keyOwnerJid, const QByteArray &key);
344  QXmppTask<TrustLevel> storeKey(const QString &keyOwnerJid, const QByteArray &key, TrustLevel trustLevel = TrustLevel::AutomaticallyDistrusted) const;
345  QString ownBareJid() const;
346  QString ownFullJid() const;
347  QHash<uint32_t, QXmppOmemoStorage::Device> otherOwnDevices();
348 
349  void warning(const QString &msg) const;
350 };
351 
352 #endif // QXMPPOMEMOMANAGER_P_H
TrustLevel
Definition: QXmppTrustLevel.h:19
The QXmppOmemoStorage class stores data used by XEP-0384: OMEMO Encryption.
Definition: QXmppOmemoStorage.h:16
Definition: QXmppTask.h:61
The key is manually trusted (e.g., by clicking a button).
The QXmppTrustManager manages end-to-end encryption trust decisions.
Definition: QXmppTrustManager.h:17
Definition: QXmppOmemoManager.h:68
Definition: QXmppOmemoStorage.h:70
The QXmppMessage class represents an XMPP message.
Definition: QXmppMessage.h:63
Definition: Algorithms.h:12
The QXmppPubSubManager aims to provide publish-subscribe functionality as specified in XEP-0060: Publ...
Definition: QXmppPubSubManager.h:20
The QXmppE2eeMetadata class contains data used for end-to-end encryption purposes.
Definition: QXmppE2eeMetadata.h:15
Definition: OmemoCryptoProvider.cpp:220
Definition: QXmppOmemoStorage.h:22