QXmpp  Version: 1.15.1
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 "Crypto.h"
17 #include "OmemoLibWrappers.h"
18 
19 #include <QDomElement>
20 #include <QTimer>
21 
22 #undef max
23 
24 class QXmppTrustManager;
25 class QXmppOmemoManager;
26 class QXmppPubSubManager;
27 class QXmppPubSubNodeConfig;
28 class QXmppPubSubPublishOptions;
29 class QXmppOmemoIq;
30 class QXmppOmemoEnvelope;
31 class QXmppOmemoElement;
32 class QXmppOmemoDeviceListItem;
33 class QXmppOmemoDeviceBundleItem;
34 
35 using namespace QXmpp;
36 using namespace std::chrono_literals;
37 using SecureByteArray = QXmpp::Private::Crypto::SecureByteArray;
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 inline constexpr auto HKDF_INFO = "OMEMO Payload";
85 constexpr int HKDF_KEY_SIZE = 32;
86 constexpr int HKDF_SALT_SIZE = 32;
87 constexpr int HKDF_OUTPUT_SIZE = 80;
88 
89 constexpr uint32_t PAYLOAD_MESSAGE_AUTHENTICATION_CODE_SIZE = 16;
90 
91 constexpr int PAYLOAD_KEY_SIZE = 32;
92 constexpr uint32_t PAYLOAD_INITIALIZATION_VECTOR_SIZE = 16;
93 constexpr uint32_t PAYLOAD_AUTHENTICATION_KEY_SIZE = 32;
94 
95 // boundaries for the count of characters in SCE's <rpad/> element
96 constexpr uint32_t SCE_RPAD_SIZE_MIN = 0;
97 constexpr uint32_t SCE_RPAD_SIZE_MAX = 200;
98 
99 struct PayloadEncryptionResult {
100  SecureByteArray decryptionData;
101  QByteArray encryptedPayload;
102 };
103 
104 struct DecryptionResult {
105  QDomElement sceContent;
106  QXmppE2eeMetadata e2eeMetadata;
107 };
108 
109 struct IqDecryptionResult {
110  QDomElement iq;
111  QXmppE2eeMetadata e2eeMetadata;
112 };
113 
114 } // namespace QXmpp::Omemo::Private
115 
116 using namespace QXmpp::Private;
117 using namespace QXmpp::Omemo::Private;
118 
119 class QXmppOmemoManagerPrivate
120 {
121 public:
122  using Result = std::variant<QXmpp::Success, QXmppError>;
123 
125 
126  bool initialized = false;
127  bool isNewDeviceAutoSessionBuildingEnabled = false;
128 
129  QXmppOmemoStorage *omemoStorage;
130  QXmppTrustManager *trustManager = nullptr;
131  QXmppPubSubManager *pubSubManager = nullptr;
132 
133  QTimer signedPreKeyPairsRenewalTimer;
134  QTimer deviceRemovalTimer;
135 
136  TrustLevels acceptedSessionBuildingTrustLevels = ACCEPTED_TRUST_LEVELS;
137 
139  QHash<uint32_t, QByteArray> preKeyPairs;
140  QHash<uint32_t, QXmppOmemoStorage::SignedPreKeyPair> signedPreKeyPairs;
141  QXmppOmemoDeviceBundle deviceBundle;
142 
143  int maximumDevicesPerJid = DEVICES_PER_JID_MAX;
144  int maximumDevicesPerStanza = DEVICES_PER_STANZA_MAX;
145 
146  // recipient JID mapped to device ID mapped to device
147  QHash<QString, QHash<uint32_t, QXmppOmemoStorage::Device>> devices;
148 
149  QList<QString> jidsOfManuallySubscribedDevices;
150 
151  OmemoContextPtr globalContext;
152  StoreContextPtr storeContext;
153  QRecursiveMutex mutex;
154  signal_crypto_provider cryptoProvider;
155 
156  signal_protocol_identity_key_store identityKeyStore;
157  signal_protocol_pre_key_store preKeyStore;
158  signal_protocol_signed_pre_key_store signedPreKeyStore;
159  signal_protocol_session_store sessionStore;
160 
161  QXmppOmemoManagerPrivate(QXmppOmemoManager *parent, QXmppOmemoStorage *omemoStorage);
162 
163  void initOmemoLibrary();
164  // exports for unit tests
165  QXMPP_EXPORT bool initGlobalContext();
166  QXMPP_EXPORT bool initLocking();
167  QXMPP_EXPORT bool initCryptoProvider();
168  void initStores();
169 
170  signal_protocol_identity_key_store createIdentityKeyStore() const;
171  signal_protocol_signed_pre_key_store createSignedPreKeyStore() const;
172  signal_protocol_pre_key_store createPreKeyStore() const;
173  signal_protocol_session_store createSessionStore() const;
174 
175  QXmppTask<bool> setUpDeviceId();
176  std::optional<uint32_t> generateDeviceId();
177  std::optional<uint32_t> generateDeviceId(const QVector<QString> &existingIds);
178  bool setUpIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair);
179  void schedulePeriodicTasks();
180  void renewSignedPreKeyPairs();
181  bool updateSignedPreKeyPair(ratchet_identity_key_pair *identityKeyPair);
182  bool renewPreKeyPairs(uint32_t keyPairBeingRenewed);
183  bool updatePreKeyPairs(uint32_t count = 1);
184  void removeDevicesRemovedFromServer();
185 
186  QXmppTask<QXmppE2eeExtension::MessageEncryptResult> encryptMessageForRecipients(QXmppMessage &&message,
187  QVector<QString> recipientJids,
188  TrustLevels acceptedTrustLevels);
189  template<typename T>
190  QXmppTask<std::optional<QXmppOmemoElement>> encryptStanza(const T &stanza, const QVector<QString> &recipientJids, TrustLevels acceptedTrustLevels);
191  std::optional<PayloadEncryptionResult> encryptPayload(const QByteArray &payload) const;
192  template<typename T>
193  QByteArray createSceEnvelope(const T &stanza);
194  QByteArray createOmemoEnvelopeData(const signal_protocol_address &address, const SecureByteArray &payloadDecryptionData) const;
195 
196  QXmppTask<std::optional<QXmppMessage>> decryptMessage(QXmppMessage stanza);
197  QXmppTask<std::optional<IqDecryptionResult>> decryptIq(QDomElement iqElement);
198  template<typename T>
199  QXmppTask<std::optional<DecryptionResult>> decryptStanza(T stanza,
200  QString senderJid,
201  uint32_t senderDeviceId,
202  const QXmppOmemoEnvelope &omemoEnvelope,
203  const QByteArray &omemoPayload,
204  bool isMessageStanza = true);
205  QXmppTask<QByteArray> extractSceEnvelope(const QString &senderJid,
206  uint32_t senderDeviceId,
207  const QXmppOmemoEnvelope &omemoEnvelope,
208  QByteArray omemoPayload,
209  bool isMessageStanza);
210  QXmppTask<std::optional<SecureByteArray>> extractPayloadDecryptionData(const QString &senderJid,
211  uint32_t senderDeviceId,
212  QXmppOmemoEnvelope omemoEnvelope,
213  bool isMessageStanza = true);
214  QByteArray decryptPayload(const SecureByteArray &payloadDecryptionData, const QByteArray &payload) const;
215 
216  QXmppTask<bool> publishOmemoData();
217 
218  QXmppTask<bool> publishDeviceBundle(bool isDeviceBundlesNodeExistent,
219  bool arePublishOptionsSupported,
220  bool isAutomaticCreationSupported,
221  bool isCreationAndConfigurationSupported,
222  bool isCreationSupported,
223  bool isConfigurationSupported,
224  bool isConfigNodeMaxSupported);
225  QXmppTask<bool> publishDeviceBundleWithoutOptions(bool isDeviceBundlesNodeExistent,
226  bool isCreationAndConfigurationSupported,
227  bool isCreationSupported,
228  bool isConfigurationSupported,
229  bool isConfigNodeMaxSupported);
230  QXmppTask<bool> configureNodeAndPublishDeviceBundle(bool isConfigNodeMaxSupported);
231  QXmppTask<bool> createAndConfigureDeviceBundlesNode(bool isConfigNodeMaxSupported);
232  QXmppTask<bool> createDeviceBundlesNode();
233  QXmppTask<bool> configureDeviceBundlesNode(bool isConfigNodeMaxSupported);
234  QXmppTask<bool> publishDeviceBundleItem();
235  QXmppTask<bool> publishDeviceBundleItemWithOptions();
236  QXmppOmemoDeviceBundleItem deviceBundleItem() const;
237  QXmppTask<std::optional<QXmppOmemoDeviceBundle>> requestDeviceBundle(QString deviceOwnerJid, uint32_t deviceId) const;
238  QXmppTask<bool> deleteDeviceBundle();
239 
240  QXmppTask<bool> publishDeviceElement(bool isDeviceListNodeExistent,
241  bool arePublishOptionsSupported,
242  bool isAutomaticCreationSupported,
243  bool isCreationAndConfigurationSupported,
244  bool isCreationSupported,
245  bool isConfigurationSupported);
246  QXmppTask<bool> publishDeviceElementWithoutOptions(bool isDeviceListNodeExistent,
247  bool isCreationAndConfigurationSupported,
248  bool isCreationSupported,
249  bool isConfigurationSupported);
250  QXmppTask<bool> configureNodeAndPublishDeviceElement();
251  QXmppTask<bool> createAndConfigureDeviceListNode();
252  QXmppTask<bool> createDeviceListNode();
253  QXmppTask<bool> configureDeviceListNode();
254  QXmppTask<bool> publishDeviceListItem(bool addOwnDevice);
255  QXmppTask<bool> publishDeviceListItemWithOptions();
256  QXmppOmemoDeviceListItem deviceListItem(bool addOwnDevice = true);
257  QXmppTask<bool> updateOwnDevicesLocally(bool isDeviceListNodeExistent);
258  std::optional<QXmppOmemoDeviceListItem> updateContactDevices(const QString &deviceOwnerJid, const QVector<QXmppOmemoDeviceListItem> &deviceListItems);
259  void updateDevices(const QString &deviceOwnerJid, const QXmppOmemoDeviceListItem &deviceListItem);
260  void handleIrregularDeviceListChanges(const QString &deviceOwnerJid);
261  QXmppTask<bool> deleteDeviceElement();
262 
263  QXmppTask<bool> createNode(const QString &node);
264  QXmppTask<bool> createNode(const QString &node, const QXmppPubSubNodeConfig &config);
265  QXmppTask<bool> configureNode(const QString &node, const QXmppPubSubNodeConfig &config);
266  QXmppTask<bool> retractItem(const QString &node, uint32_t itemId);
267  QXmppTask<bool> deleteNode(QString node);
268 
269  template<typename T>
270  QXmppTask<bool> publishItem(const QString &node, const T &item);
271  template<typename T>
272  QXmppTask<bool> publishItem(const QString &node, const T &item, const QXmppPubSubPublishOptions &publishOptions);
273 
274  template<typename T>
275  QXmppTask<bool> runPubSubQueryWithContinuation(QXmppTask<T> future, QString errorMessage);
276 
277  QXmppTask<bool> changeDeviceLabel(QString deviceLabel);
278 
280  void subscribeToNewDeviceLists(const QString &jid, uint32_t deviceId);
281  QXmppTask<Result> subscribeToDeviceList(QString jid);
282  QXmppTask<QVector<QXmppOmemoManager::DevicesResult>> unsubscribeFromDeviceLists(const QList<QString> &jids);
283  QXmppTask<Result> unsubscribeFromDeviceList(QString jid);
284 
285  QXmppTask<bool> resetOwnDevice();
286  QXmppTask<void> resetOwnDeviceLocally();
287  QXmppTask<bool> resetAll();
288  void resetCachedData();
289 
290  QXmppTask<bool> buildSessionForNewDevice(const QString &jid, uint32_t deviceId, QXmppOmemoStorage::Device &device);
291  QXmppTask<bool> buildSessionWithDeviceBundle(QString jid, uint32_t deviceId, QXmppOmemoStorage::Device &device);
292  bool buildSession(signal_protocol_address address, const QXmppOmemoDeviceBundle &deviceBundle);
293  bool createSessionBundle(session_pre_key_bundle **sessionBundle,
294  const QByteArray &serializedPublicIdentityKey,
295  const QByteArray &serializedSignedPublicPreKey,
296  uint32_t signedPublicPreKeyId,
297  const QByteArray &serializedSignedPublicPreKeySignature,
298  const QByteArray &serializedPublicPreKey,
299  uint32_t publicPreKeyId);
300 
301  bool deserializeIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair) const;
302  bool deserializePrivateIdentityKey(ec_private_key **privateIdentityKey, const QByteArray &serializedPrivateIdentityKey) const;
303  bool deserializePublicIdentityKey(ec_public_key **publicIdentityKey, const QByteArray &serializedPublicIdentityKey) const;
304  bool deserializeSignedPublicPreKey(ec_public_key **signedPublicPreKey, const QByteArray &serializedSignedPublicPreKey) const;
305  bool deserializePublicPreKey(ec_public_key **publicPreKey, const QByteArray &serializedPublicPreKey) const;
306 
307  QXmppTask<QXmpp::SendResult> sendEmptyMessage(const QString &recipientJid, uint32_t recipientDeviceId, bool isKeyExchange = false) const;
308  QXmppTask<void> storeOwnKey() const;
309  QXmppTask<TrustLevel> storeKeyDependingOnSecurityPolicy(QString keyOwnerJid, QByteArray key);
310  QXmppTask<TrustLevel> storeKey(QString keyOwnerJid, QByteArray key, TrustLevel trustLevel = TrustLevel::AutomaticallyDistrusted) const;
311  QString ownBareJid() const;
312  QString ownFullJid() const;
313  QHash<uint32_t, QXmppOmemoStorage::Device> otherOwnDevices();
314 
315  void warning(const QString &msg) const;
316 };
317 
318 #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:67
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:14
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:174
Definition: QXmppOmemoStorage.h:22
std::variant< T, QXmppError > Result
Definition: QXmppGlobal.h:209