QXmpp Version: 1.10.0
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
28class QXmppPubSubNodeConfig;
29class QXmppPubSubPublishOptions;
30class QXmppOmemoIq;
31class QXmppOmemoEnvelope;
32class QXmppOmemoElement;
33class QXmppOmemoDeviceListItem;
34class QXmppOmemoDeviceBundleItem;
35
36using namespace QXmpp;
37using namespace std::chrono_literals;
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
84constexpr QStringView PAYLOAD_CIPHER_TYPE = u"aes256";
85constexpr QCA::Cipher::Mode PAYLOAD_CIPHER_MODE = QCA::Cipher::CBC;
86constexpr QCA::Cipher::Padding PAYLOAD_CIPHER_PADDING = QCA::Cipher::PKCS7;
87
88inline constexpr auto HKDF_INFO = "OMEMO Payload";
89constexpr int HKDF_KEY_SIZE = 32;
90constexpr int HKDF_SALT_SIZE = 32;
91constexpr int HKDF_OUTPUT_SIZE = 80;
92
93inline constexpr QStringView PAYLOAD_MESSAGE_AUTHENTICATION_CODE_TYPE = u"hmac(sha256)";
94constexpr uint32_t PAYLOAD_MESSAGE_AUTHENTICATION_CODE_SIZE = 16;
95
96constexpr int PAYLOAD_KEY_SIZE = 32;
97constexpr uint32_t PAYLOAD_INITIALIZATION_VECTOR_SIZE = 16;
98constexpr uint32_t PAYLOAD_AUTHENTICATION_KEY_SIZE = 32;
99
100// boundaries for the count of characters in SCE's <rpad/> element
101constexpr uint32_t SCE_RPAD_SIZE_MIN = 0;
102constexpr uint32_t SCE_RPAD_SIZE_MAX = 200;
103
104struct PayloadEncryptionResult {
105 QCA::SecureArray decryptionData;
106 QByteArray encryptedPayload;
107};
108
109struct DecryptionResult {
110 QDomElement sceContent;
111 QXmppE2eeMetadata e2eeMetadata;
112};
113
114struct IqDecryptionResult {
115 QDomElement iq;
116 QXmppE2eeMetadata e2eeMetadata;
117};
118
119} // namespace QXmpp::Omemo::Private
120
121using namespace QXmpp::Private;
122using namespace QXmpp::Omemo::Private;
123
124class QXmppOmemoManagerPrivate
125{
126public:
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
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
323 QXmppTask<bool> buildSessionForNewDevice(const QString &jid, uint32_t deviceId, QXmppOmemoStorage::Device &device);
324 QXmppTask<bool> buildSessionWithDeviceBundle(const QString &jid, uint32_t deviceId, QXmppOmemoStorage::Device &device);
325 bool buildSession(signal_protocol_address address, const QXmppOmemoDeviceBundle &deviceBundle);
326 bool createSessionBundle(session_pre_key_bundle **sessionBundle,
327 const QByteArray &serializedPublicIdentityKey,
328 const QByteArray &serializedSignedPublicPreKey,
329 uint32_t signedPublicPreKeyId,
330 const QByteArray &serializedSignedPublicPreKeySignature,
331 const QByteArray &serializedPublicPreKey,
332 uint32_t publicPreKeyId);
333
334 bool deserializeIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair) const;
335 bool deserializePrivateIdentityKey(ec_private_key **privateIdentityKey, const QByteArray &serializedPrivateIdentityKey) const;
336 bool deserializePublicIdentityKey(ec_public_key **publicIdentityKey, const QByteArray &serializedPublicIdentityKey) const;
337 bool deserializeSignedPublicPreKey(ec_public_key **signedPublicPreKey, const QByteArray &serializedSignedPublicPreKey) const;
338 bool deserializePublicPreKey(ec_public_key **publicPreKey, const QByteArray &serializedPublicPreKey) const;
339
340 QXmppTask<QXmpp::SendResult> sendEmptyMessage(const QString &recipientJid, uint32_t recipientDeviceId, bool isKeyExchange = false) const;
341 QXmppTask<void> storeOwnKey() const;
342 QXmppTask<TrustLevel> storeKeyDependingOnSecurityPolicy(const QString &keyOwnerJid, const QByteArray &key);
343 QXmppTask<TrustLevel> storeKey(const QString &keyOwnerJid, const QByteArray &key, TrustLevel trustLevel = TrustLevel::AutomaticallyDistrusted) const;
344 QString ownBareJid() const;
345 QString ownFullJid() const;
346 QHash<uint32_t, QXmppOmemoStorage::Device> otherOwnDevices();
347
348 void warning(const QString &msg) const;
349};
350
351#endif // QXMPPOMEMOMANAGER_P_H
The QXmppE2eeMetadata class contains data used for end-to-end encryption purposes.
Definition: QXmppE2eeMetadata.h:16
The QXmppMessage class represents an XMPP message.
Definition: QXmppMessage.h:64
Definition: QXmppOmemoManager.h:69
The QXmppOmemoStorage class stores data used by XEP-0384: OMEMO Encryption.
Definition: QXmppOmemoStorage.h:17
The QXmppPubSubManager aims to provide publish-subscribe functionality as specified in XEP-0060: Publ...
Definition: QXmppPubSubManager.h:21
Definition: QXmppTask.h:62
The QXmppTrustManager manages end-to-end encryption trust decisions.
Definition: QXmppTrustManager.h:18
Definition: Algorithms.h:12
TrustLevel
Definition: QXmppTrustLevel.h:19
@ ManuallyTrusted
The key is manually trusted (e.g., by clicking a button).
Definition: QXmppOmemoStorage.h:70
Definition: QXmppOmemoStorage.h:22