QXmpp Version: 1.15.0
Loading...
Searching...
No Matches
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
27class QXmppPubSubNodeConfig;
28class QXmppPubSubPublishOptions;
29class QXmppOmemoIq;
30class QXmppOmemoEnvelope;
31class QXmppOmemoElement;
32class QXmppOmemoDeviceListItem;
33class QXmppOmemoDeviceBundleItem;
34
35using namespace QXmpp;
36using namespace std::chrono_literals;
37using SecureByteArray = QXmpp::Private::Crypto::SecureByteArray;
38
39namespace 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
46constexpr 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
49constexpr int UNRESPONDED_STANZAS_UNTIL_HEARTBEAT_MESSAGE_IS_SENT = 53;
50
51// size of empty OMEMO message's decryption data
52constexpr 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'
56constexpr uint64_t PUBSUB_NODE_MAX_ITEMS_1 = 1000;
57constexpr uint64_t PUBSUB_NODE_MAX_ITEMS_2 = 100;
58constexpr uint64_t PUBSUB_NODE_MAX_ITEMS_3 = 10;
59
60constexpr uint32_t PRE_KEY_ID_MIN = 1;
61constexpr uint32_t SIGNED_PRE_KEY_ID_MIN = 1;
62constexpr uint32_t PRE_KEY_ID_MAX = std::numeric_limits<int32_t>::max();
63constexpr uint32_t SIGNED_PRE_KEY_ID_MAX = std::numeric_limits<int32_t>::max();
64constexpr uint32_t PRE_KEY_INITIAL_CREATION_COUNT = 100;
65
66// maximum count of devices stored per JID
67constexpr int DEVICES_PER_JID_MAX = 200;
68
69// maximum count of devices for whom a stanza is encrypted
70constexpr int DEVICES_PER_STANZA_MAX = 1000;
71
72// interval to remove old signed pre keys and create new ones
73constexpr auto SIGNED_PRE_KEY_RENEWAL_INTERVAL = 24h * 7 * 4;
74
75// interval to check for old signed pre keys
76constexpr auto SIGNED_PRE_KEY_RENEWAL_CHECK_INTERVAL = 24h;
77
78// interval to remove devices locally after removal from their servers
79constexpr auto DEVICE_REMOVAL_INTERVAL = 24h * 7 * 12;
80
81// interval to check for devices removed from their servers
82constexpr auto DEVICE_REMOVAL_CHECK_INTERVAL = 24h;
83
84inline constexpr auto HKDF_INFO = "OMEMO Payload";
85constexpr int HKDF_KEY_SIZE = 32;
86constexpr int HKDF_SALT_SIZE = 32;
87constexpr int HKDF_OUTPUT_SIZE = 80;
88
89constexpr uint32_t PAYLOAD_MESSAGE_AUTHENTICATION_CODE_SIZE = 16;
90
91constexpr int PAYLOAD_KEY_SIZE = 32;
92constexpr uint32_t PAYLOAD_INITIALIZATION_VECTOR_SIZE = 16;
93constexpr uint32_t PAYLOAD_AUTHENTICATION_KEY_SIZE = 32;
94
95// boundaries for the count of characters in SCE's <rpad/> element
96constexpr uint32_t SCE_RPAD_SIZE_MIN = 0;
97constexpr uint32_t SCE_RPAD_SIZE_MAX = 200;
98
99struct PayloadEncryptionResult {
100 SecureByteArray decryptionData;
101 QByteArray encryptedPayload;
102};
103
104struct DecryptionResult {
105 QDomElement sceContent;
106 QXmppE2eeMetadata e2eeMetadata;
107};
108
109struct IqDecryptionResult {
110 QDomElement iq;
111 QXmppE2eeMetadata e2eeMetadata;
112};
113
114} // namespace QXmpp::Omemo::Private
115
116using namespace QXmpp::Private;
117using namespace QXmpp::Omemo::Private;
118
119class QXmppOmemoManagerPrivate
120{
121public:
122 using Result = std::variant<QXmpp::Success, QXmppError>;
123
124 QXmppOmemoManager *q;
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
138 QXmppOmemoStorage::OwnDevice ownDevice;
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
279 QXmppTask<QXmppPubSubManager::ItemResult<QXmppOmemoDeviceListItem>> requestDeviceList(QString jid);
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
Definition QXmppOmemoManager.h:69
The QXmppPubSubManager aims to provide publish-subscribe functionality as specified in XEP-0060: Publ...
Definition QXmppPubSubManager.h:21
The QXmppTrustManager manages end-to-end encryption trust decisions.
Definition QXmppTrustManager.h:18
Definition Algorithms.h:14
TrustLevel
Definition QXmppTrustLevel.h:19
@ ManuallyTrusted
The key is manually trusted (e.g., by clicking a button).
Definition QXmppTrustLevel.h:32
@ Authenticated
Definition QXmppTrustLevel.h:35
@ AutomaticallyTrusted
Definition QXmppTrustLevel.h:30