aboutsummaryrefslogtreecommitdiff
path: root/src/omemo
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2023-03-11 00:29:02 +0100
committerLinus Jahn <lnj@kaidan.im>2023-03-11 00:29:02 +0100
commit463111576fb1476192acd2d8fe415b8482a8a696 (patch)
treee87e3bb8f8724f019954692ac22b0d6386dfa5e7 /src/omemo
parent6ea3edfd83a0bf1558d43e48eac563730276c175 (diff)
parent4897c9b6a36e961fb44d2bce04a698f979a423d5 (diff)
downloadqxmpp-463111576fb1476192acd2d8fe415b8482a8a696.tar.gz
Merge branch '1.5'
Diffstat (limited to 'src/omemo')
-rw-r--r--src/omemo/CMakeLists.txt4
-rw-r--r--src/omemo/QXmppOmemoData.cpp9
-rw-r--r--src/omemo/QXmppOmemoDeviceList_p.h2
-rw-r--r--src/omemo/QXmppOmemoItems_p.h6
-rw-r--r--src/omemo/QXmppOmemoManager.cpp12
-rw-r--r--src/omemo/QXmppOmemoManager_p.cpp166
-rw-r--r--src/omemo/QXmppOmemoManager_p.h20
7 files changed, 88 insertions, 131 deletions
diff --git a/src/omemo/CMakeLists.txt b/src/omemo/CMakeLists.txt
index 0ec3c0f0..89e1f06c 100644
--- a/src/omemo/CMakeLists.txt
+++ b/src/omemo/CMakeLists.txt
@@ -54,8 +54,10 @@ set_target_properties(QXmppOmemo PROPERTIES
install(
TARGETS QXmppOmemo
- DESTINATION ${CMAKE_INSTALL_LIBDIR}
EXPORT QXmppOmemoTargets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(
diff --git a/src/omemo/QXmppOmemoData.cpp b/src/omemo/QXmppOmemoData.cpp
index d1dd2a88..43e00c35 100644
--- a/src/omemo/QXmppOmemoData.cpp
+++ b/src/omemo/QXmppOmemoData.cpp
@@ -3,19 +3,18 @@
//
// SPDX-License-Identifier: LGPL-2.1-or-later
-#include "QXmppConstants_p.h"
#include "QXmppOmemoDeviceBundle_p.h"
#include "QXmppOmemoDeviceElement_p.h"
#include "QXmppOmemoDeviceList_p.h"
#include "QXmppOmemoElement_p.h"
-#include "QXmppOmemoEnvelope_p.h"
#include "QXmppOmemoIq_p.h"
#include "QXmppOmemoItems_p.h"
-#include "QXmppUtils.h"
#include <QDomElement>
#include <QHash>
+const char *ns_omemo_2 = "urn:xmpp:omemo:2";
+
/// \cond
///
/// \class QXmppOmemoDeviceElement
@@ -425,7 +424,7 @@ void QXmppOmemoDeviceBundleItem::setDeviceBundle(const QXmppOmemoDeviceBundle &d
bool QXmppOmemoDeviceBundleItem::isItem(const QDomElement &itemElement)
{
- return QXmppPubSubItem::isItem(itemElement, QXmppOmemoDeviceBundle::isOmemoDeviceBundle);
+ return QXmppPubSubBaseItem::isItem(itemElement, QXmppOmemoDeviceBundle::isOmemoDeviceBundle);
}
void QXmppOmemoDeviceBundleItem::parsePayload(const QDomElement &payloadElement)
@@ -450,7 +449,7 @@ void QXmppOmemoDeviceListItem::setDeviceList(const QXmppOmemoDeviceList &deviceL
bool QXmppOmemoDeviceListItem::isItem(const QDomElement &itemElement)
{
- return QXmppPubSubItem::isItem(itemElement, QXmppOmemoDeviceList::isOmemoDeviceList);
+ return QXmppPubSubBaseItem::isItem(itemElement, QXmppOmemoDeviceList::isOmemoDeviceList);
}
void QXmppOmemoDeviceListItem::parsePayload(const QDomElement &payloadElement)
diff --git a/src/omemo/QXmppOmemoDeviceList_p.h b/src/omemo/QXmppOmemoDeviceList_p.h
index 76bff435..46ac724d 100644
--- a/src/omemo/QXmppOmemoDeviceList_p.h
+++ b/src/omemo/QXmppOmemoDeviceList_p.h
@@ -7,12 +7,12 @@
#define QXMPPOMEMODEVICELIST_H
#include "QXmppGlobal.h"
+#include "QXmppOmemoDeviceElement_p.h"
#include "QList"
class QDomElement;
class QXmlStreamWriter;
-class QXmppOmemoDeviceElement;
class QXMPP_AUTOTEST_EXPORT QXmppOmemoDeviceList : public QList<QXmppOmemoDeviceElement>
{
diff --git a/src/omemo/QXmppOmemoItems_p.h b/src/omemo/QXmppOmemoItems_p.h
index 9b816ed8..abc6a65f 100644
--- a/src/omemo/QXmppOmemoItems_p.h
+++ b/src/omemo/QXmppOmemoItems_p.h
@@ -7,9 +7,9 @@
#include "QXmppOmemoDeviceBundle_p.h"
#include "QXmppOmemoDeviceList_p.h"
-#include "QXmppPubSubItem.h"
+#include "QXmppPubSubBaseItem.h"
-class QXmppOmemoDeviceBundleItem : public QXmppPubSubItem
+class QXmppOmemoDeviceBundleItem : public QXmppPubSubBaseItem
{
public:
QXmppOmemoDeviceBundle deviceBundle() const;
@@ -25,7 +25,7 @@ private:
QXmppOmemoDeviceBundle m_deviceBundle;
};
-class QXmppOmemoDeviceListItem : public QXmppPubSubItem
+class QXmppOmemoDeviceListItem : public QXmppPubSubBaseItem
{
public:
QXmppOmemoDeviceList deviceList() const;
diff --git a/src/omemo/QXmppOmemoManager.cpp b/src/omemo/QXmppOmemoManager.cpp
index 55a21190..0aab152d 100644
--- a/src/omemo/QXmppOmemoManager.cpp
+++ b/src/omemo/QXmppOmemoManager.cpp
@@ -4,11 +4,7 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "QXmppClient.h"
-#include "QXmppConstants_p.h"
-#include "QXmppOmemoDeviceElement_p.h"
-#include "QXmppOmemoDeviceList_p.h"
#include "QXmppOmemoElement_p.h"
-#include "QXmppOmemoEnvelope_p.h"
#include "QXmppOmemoIq_p.h"
#include "QXmppOmemoItems_p.h"
#include "QXmppOmemoManager_p.h"
@@ -18,6 +14,9 @@
#include <QStringBuilder>
+#undef max
+#undef interface
+
using namespace QXmpp;
using namespace QXmpp::Private;
using namespace QXmpp::Omemo::Private;
@@ -669,7 +668,7 @@ QXmppOmemoOwnDevice Manager::ownDevice()
QXmppOmemoOwnDevice device;
device.setLabel(ownDevice.label);
- device.setKeyId(createKeyId(ownDevice.publicIdentityKey));
+ device.setKeyId(ownDevice.publicIdentityKey);
return device;
}
@@ -885,13 +884,16 @@ QXmppTask<void> Manager::buildMissingSessions(const QList<QString> &jids)
auto future = d->buildSessionWithDeviceBundle(jid, deviceId, device);
future.then(this, [=](auto) mutable {
if (++(*processedDevicesCount) == devicesCount) {
+ interface.finish();
}
});
} else if (++(*processedDevicesCount) == devicesCount) {
+ interface.finish();
}
}
}
} else {
+ interface.finish();
}
return interface.task();
diff --git a/src/omemo/QXmppOmemoManager_p.cpp b/src/omemo/QXmppOmemoManager_p.cpp
index 2e08da04..1c86d80b 100644
--- a/src/omemo/QXmppOmemoManager_p.cpp
+++ b/src/omemo/QXmppOmemoManager_p.cpp
@@ -7,13 +7,12 @@
#include "QXmppOmemoManager_p.h"
-#include "QXmppConstants_p.h"
#include "QXmppOmemoDeviceElement_p.h"
#include "QXmppOmemoElement_p.h"
#include "QXmppOmemoEnvelope_p.h"
#include "QXmppOmemoIq_p.h"
#include "QXmppOmemoItems_p.h"
-#include "QXmppPubSubItem.h"
+#include "QXmppPubSubBaseItem.h"
#include "QXmppSceEnvelope_p.h"
#include "QXmppTrustManager.h"
#include "QXmppUtils.h"
@@ -25,6 +24,9 @@
#include <QRandomGenerator>
#include <QStringBuilder>
+#undef max
+#undef interface
+
using namespace QXmpp;
using namespace QXmpp::Private;
using namespace QXmpp::Omemo::Private;
@@ -33,27 +35,19 @@ using Error = QXmppStanza::Error;
using Manager = QXmppOmemoManager;
using ManagerPrivate = QXmppOmemoManagerPrivate;
+const char *ns_client = "jabber:client";
+const char *ns_pubsub_auto_create = "http://jabber.org/protocol/pubsub#auto-create";
+const char *ns_pubsub_config_node = "http://jabber.org/protocol/pubsub#config-node";
+const char *ns_pubsub_config_node_max = "http://jabber.org/protocol/pubsub#config-node-max";
+const char *ns_pubsub_create_and_configure = "http://jabber.org/protocol/pubsub#create-and-configure";
+const char *ns_pubsub_create_nodes = "http://jabber.org/protocol/pubsub#create-nodes";
+const char *ns_pubsub_publish = "http://jabber.org/protocol/pubsub#publish";
+const char *ns_pubsub_publish_options = "http://jabber.org/protocol/pubsub#publish-options";
+
namespace QXmpp::Omemo::Private {
const QString PAYLOAD_MESSAGE_AUTHENTICATION_CODE_TYPE = QStringLiteral("hmac(sha256)");
-//
-// Creates a key ID.
-//
-// The first byte representing a version string used by the OMEMO library but
-// not needed for trust management is removed.
-// It corresponds to the fingerprint shown to users which also does not contain
-// the first byte.
-//
-// \param key key for whom its ID is created
-//
-// \return the key ID
-//
-QByteArray createKeyId(const QByteArray &key)
-{
- return QByteArray(key).remove(0, 1);
-}
-
} // namespace QXmpp::Omemo::Private
//
@@ -710,13 +704,7 @@ bool ManagerPrivate::setUpIdentityKeyPair(ratchet_identity_key_pair **identityKe
const auto privateIdentityKey = privateIdentityKeyBuffer.toByteArray();
ownDevice.privateIdentityKey = privateIdentityKey;
- BufferPtr publicIdentityKeyBuffer;
-
- if (ec_public_key_serialize(publicIdentityKeyBuffer.ptrRef(), ratchet_identity_key_pair_get_public(*identityKeyPair)) < 0) {
- warning("Public identity key could not be serialized");
- return false;
- }
-
+ BufferPtr publicIdentityKeyBuffer(ec_public_key_get_ed(ratchet_identity_key_pair_get_public(*identityKeyPair)));
const auto publicIdentityKey = publicIdentityKeyBuffer.toByteArray();
deviceBundle.setPublicIdentityKey(publicIdentityKey);
ownDevice.publicIdentityKey = publicIdentityKey;
@@ -832,18 +820,12 @@ bool ManagerPrivate::updateSignedPreKeyPair(ratchet_identity_key_pair *identityK
signedPreKeyPairs.insert(latestSignedPreKeyId, signedPreKeyPairForStorage);
omemoStorage->addSignedPreKeyPair(latestSignedPreKeyId, signedPreKeyPairForStorage);
- BufferPtr signedPublicPreKeyBuffer;
-
- if (ec_public_key_serialize(signedPublicPreKeyBuffer.ptrRef(), ec_key_pair_get_public(session_signed_pre_key_get_key_pair(signedPreKeyPair.get()))) < 0) {
- warning("Signed public pre key could not be serialized");
- return false;
- }
-
+ BufferPtr signedPublicPreKeyBuffer(ec_public_key_get_mont(ec_key_pair_get_public(session_signed_pre_key_get_key_pair(signedPreKeyPair.get()))));
const auto signedPublicPreKeyByteArray = signedPublicPreKeyBuffer.toByteArray();
deviceBundle.setSignedPublicPreKeyId(latestSignedPreKeyId);
deviceBundle.setSignedPublicPreKey(signedPublicPreKeyByteArray);
- deviceBundle.setSignedPublicPreKeySignature(QByteArray(reinterpret_cast<const char *>(session_signed_pre_key_get_signature(signedPreKeyPair.get())), session_signed_pre_key_get_signature_len(signedPreKeyPair.get())));
+ deviceBundle.setSignedPublicPreKeySignature(QByteArray(reinterpret_cast<const char *>(session_signed_pre_key_get_signature_omemo(signedPreKeyPair.get())), session_signed_pre_key_get_signature_omemo_len(signedPreKeyPair.get())));
ownDevice.latestSignedPreKeyId = latestSignedPreKeyId;
@@ -921,7 +903,6 @@ bool ManagerPrivate::updatePreKeyPairs(uint32_t count)
node != nullptr;
node = signal_protocol_key_helper_key_list_next(node)) {
BufferSecurePtr preKeyPairBuffer;
- BufferPtr publicPreKeyBuffer;
auto preKeyPair = signal_protocol_key_helper_key_list_element(node);
@@ -934,11 +915,7 @@ bool ManagerPrivate::updatePreKeyPairs(uint32_t count)
serializedPreKeyPairs.insert(preKeyId, preKeyPairBuffer.toByteArray());
- if (ec_public_key_serialize(publicPreKeyBuffer.ptrRef(), ec_key_pair_get_public(session_pre_key_get_key_pair(preKeyPair))) < 0) {
- warning("Public pre key could not be serialized");
- return false;
- }
-
+ BufferPtr publicPreKeyBuffer(ec_public_key_get_mont(ec_key_pair_get_public(session_pre_key_get_key_pair(preKeyPair))));
const auto serializedPublicPreKey = publicPreKeyBuffer.toByteArray();
deviceBundle.addPublicPreKey(preKeyId, serializedPublicPreKey);
}
@@ -1017,7 +994,7 @@ bool ManagerPrivate::generateIdentityKeyPair(ratchet_identity_key_pair **identit
RefCountedPtr<ec_public_key> publicIdentityKey;
- if (curve_decode_point(publicIdentityKey.ptrRef(), signal_buffer_data(publicIdentityKeyBuffer.get()), signal_buffer_len(publicIdentityKeyBuffer.get()), globalContext.get()) < 0) {
+ if (curve_decode_point_ed(publicIdentityKey.ptrRef(), signal_buffer_data(publicIdentityKeyBuffer.get()), signal_buffer_len(publicIdentityKeyBuffer.get()), globalContext.get()) < 0) {
warning("Public identity key could not be deserialized");
return false;
}
@@ -1234,15 +1211,14 @@ QXmppTask<std::optional<QXmppOmemoElement>> ManagerPrivate::encryptStanza(const
if (optionalDeviceBundle && devices.value(jid).contains(deviceId)) {
auto &deviceBeingModified = devices[jid][deviceId];
const auto &deviceBundle = *optionalDeviceBundle;
- const auto key = deviceBundle.publicIdentityKey();
- deviceBeingModified.keyId = createKeyId(key);
+ deviceBeingModified.keyId = deviceBundle.publicIdentityKey();
auto future = q->trustLevel(jid, deviceBeingModified.keyId);
future.then(q, [=](TrustLevel trustLevel) mutable {
// Store the retrieved key's trust level if it is not stored
// yet.
if (trustLevel == TrustLevel::Undecided) {
- auto future = storeKeyDependingOnSecurityPolicy(jid, key);
+ auto future = storeKeyDependingOnSecurityPolicy(jid, deviceBeingModified.keyId);
future.then(q, [=](TrustLevel trustLevel) mutable {
omemoStorage->addDevice(jid, deviceId, deviceBeingModified);
Q_EMIT q->deviceChanged(jid, deviceId);
@@ -1473,8 +1449,6 @@ QXmppTask<std::optional<QXmppMessage>> ManagerPrivate::decryptMessage(QXmppMessa
future.then(q, [=](std::optional<QCA::SecureArray> payloadDecryptionData) mutable {
if (!payloadDecryptionData) {
warning("Empty OMEMO message could not be successfully processed");
- } else if (payloadDecryptionData->isEmpty()) {
- warning("Empty OMEMO message could not be successfully processed");
} else {
q->debug("Successfully processed empty OMEMO message");
}
@@ -1576,48 +1550,38 @@ QXmppTask<std::optional<DecryptionResult>> ManagerPrivate::decryptStanza(T stanz
QXmppSceEnvelopeReader sceEnvelopeReader(document.documentElement());
if (sceEnvelopeReader.from() != senderJid) {
- warning("Sender '" % senderJid % "' of stanza does not match SCE 'from' affix element '" % sceEnvelopeReader.from() % "'");
- interface.finish(std::nullopt);
- } else {
- const auto recipientJid = QXmppUtils::jidToBareJid(stanza.to());
- auto isSceAffixElementValid = true;
+ q->info("Sender '" % senderJid % "' of stanza does not match SCE 'from' affix element '" % sceEnvelopeReader.from() % "'");
+ }
- if (isMessageStanza) {
- if (const auto &message = dynamic_cast<const QXmppMessage &>(stanza); message.type() == QXmppMessage::GroupChat && (sceEnvelopeReader.to() != recipientJid)) {
- warning("Recipient of group chat message does not match SCE affix element '<to/>'");
- isSceAffixElementValid = false;
- }
- } else {
- if (sceEnvelopeReader.to() != recipientJid) {
- warning("Recipient of IQ does not match SCE affix element '<to/>'");
- isSceAffixElementValid = false;
- }
+ if (const auto recipientJid = QXmppUtils::jidToBareJid(stanza.to()); isMessageStanza) {
+ if (const auto &message = dynamic_cast<const QXmppMessage &>(stanza); message.type() == QXmppMessage::GroupChat && (sceEnvelopeReader.to() != recipientJid)) {
+ warning("Recipient of group chat message does not match SCE affix element '<to/>'");
+ interface.finish(std::nullopt);
+ return;
}
+ } else if (sceEnvelopeReader.to() != recipientJid) {
+ q->info("Recipient of IQ does not match SCE affix element '<to/>'");
+ }
- if (!isSceAffixElementValid) {
- interface.finish(std::nullopt);
- } else {
- auto &device = devices[senderJid][senderDeviceId];
- device.unrespondedSentStanzasCount = 0;
+ auto &device = devices[senderJid][senderDeviceId];
+ device.unrespondedSentStanzasCount = 0;
- // Send a heartbeat message to the sender if too many stanzas were
- // received responding to none.
- if (device.unrespondedReceivedStanzasCount == UNRESPONDED_STANZAS_UNTIL_HEARTBEAT_MESSAGE_IS_SENT) {
- sendEmptyMessage(senderJid, senderDeviceId);
- device.unrespondedReceivedStanzasCount = 0;
- } else {
- ++device.unrespondedReceivedStanzasCount;
- }
+ // Send a heartbeat message to the sender if too many stanzas were
+ // received responding to none.
+ if (device.unrespondedReceivedStanzasCount == UNRESPONDED_STANZAS_UNTIL_HEARTBEAT_MESSAGE_IS_SENT) {
+ sendEmptyMessage(senderJid, senderDeviceId);
+ device.unrespondedReceivedStanzasCount = 0;
+ } else {
+ ++device.unrespondedReceivedStanzasCount;
+ }
- QXmppE2eeMetadata e2eeMetadata;
- e2eeMetadata.setSceTimestamp(sceEnvelopeReader.timestamp());
- e2eeMetadata.setEncryption(QXmpp::Omemo2);
- const auto &senderDevice = devices.value(senderJid).value(senderDeviceId);
- e2eeMetadata.setSenderKey(senderDevice.keyId);
+ QXmppE2eeMetadata e2eeMetadata;
+ e2eeMetadata.setSceTimestamp(sceEnvelopeReader.timestamp());
+ e2eeMetadata.setEncryption(QXmpp::Omemo2);
+ const auto &senderDevice = devices.value(senderJid).value(senderDeviceId);
+ e2eeMetadata.setSenderKey(senderDevice.keyId);
- interface.finish(DecryptionResult { sceEnvelopeReader.contentElement(), e2eeMetadata });
- }
- }
+ interface.finish(DecryptionResult { sceEnvelopeReader.contentElement(), e2eeMetadata });
}
});
@@ -1648,9 +1612,6 @@ QXmppTask<QByteArray> ManagerPrivate::extractSceEnvelope(const QString &senderJi
if (!payloadDecryptionData) {
warning("Data for decrypting OMEMO payload could not be extracted");
interface.finish(QByteArray());
- } else if (payloadDecryptionData->isEmpty()) {
- warning("Data for decrypting OMEMO payload could not be extracted");
- interface.finish(QByteArray());
} else {
interface.finish(decryptPayload(*payloadDecryptionData, omemoPayload));
}
@@ -1669,8 +1630,7 @@ QXmppTask<QByteArray> ManagerPrivate::extractSceEnvelope(const QString &senderJi
// \param omemoEnvelope OMEMO envelope containing the payload decryption data
// \param isMessageStanza whether the received stanza is a message stanza
//
-// \return the serialized payload decryption data if it could be extracted, otherwise a
-// default-constructed secure array
+// \return the serialized payload decryption data if it could be extracted, otherwise std::nullopt
//
QXmppTask<std::optional<QCA::SecureArray>> ManagerPrivate::extractPayloadDecryptionData(const QString &senderJid, uint32_t senderDeviceId, const QXmppOmemoEnvelope &omemoEnvelope, bool isMessageStanza)
{
@@ -1728,11 +1688,10 @@ QXmppTask<std::optional<QCA::SecureArray>> ManagerPrivate::extractPayloadDecrypt
const auto key = publicIdentityKeyBuffer.toByteArray();
auto &device = devices[senderJid][senderDeviceId];
auto &storedKeyId = device.keyId;
- const auto createdKeyId = createKeyId(key);
// Store the key if its ID has changed.
- if (storedKeyId != createdKeyId) {
- storedKeyId = createdKeyId;
+ if (storedKeyId != key) {
+ storedKeyId = key;
omemoStorage->addDevice(senderJid, senderDeviceId, device);
Q_EMIT q->deviceChanged(senderJid, senderDeviceId);
}
@@ -1781,12 +1740,7 @@ QXmppTask<std::optional<QCA::SecureArray>> ManagerPrivate::extractPayloadDecrypt
auto future = q->trustLevel(senderJid, storedKeyId);
future.then(q, [=](TrustLevel trustLevel) mutable {
if (trustLevel == TrustLevel::Undecided) {
- auto future = storeKeyDependingOnSecurityPolicy(senderJid, key);
- future.then(q, [=](auto) mutable {
- interface.finish(std::nullopt);
- });
- } else {
- interface.finish(std::nullopt);
+ storeKeyDependingOnSecurityPolicy(senderJid, key);
}
});
}
@@ -3338,8 +3292,7 @@ QXmppTask<bool> ManagerPrivate::buildSessionWithDeviceBundle(const QString &jid,
future.then(q, [=, &device](std::optional<QXmppOmemoDeviceBundle> optionalDeviceBundle) mutable {
if (optionalDeviceBundle) {
const auto &deviceBundle = *optionalDeviceBundle;
- const auto key = deviceBundle.publicIdentityKey();
- device.keyId = createKeyId(key);
+ device.keyId = deviceBundle.publicIdentityKey();
auto future = q->trustLevel(jid, device.keyId);
future.then(q, [=](TrustLevel trustLevel) mutable {
@@ -3372,7 +3325,7 @@ QXmppTask<bool> ManagerPrivate::buildSessionWithDeviceBundle(const QString &jid,
if (trustLevel == TrustLevel::Undecided) {
// Store the key's trust level if it is not stored yet.
- auto future = storeKeyDependingOnSecurityPolicy(jid, key);
+ auto future = storeKeyDependingOnSecurityPolicy(jid, device.keyId);
future.then(q, [=](TrustLevel trustLevel) mutable {
buildSessionDependingOnTrustLevel(trustLevel);
});
@@ -3517,7 +3470,7 @@ bool ManagerPrivate::deserializePublicIdentityKey(ec_public_key **publicIdentity
return false;
}
- if (curve_decode_point(publicIdentityKey, signal_buffer_data(publicIdentityKeyBuffer.get()), signal_buffer_len(publicIdentityKeyBuffer.get()), globalContext.get()) < 0) {
+ if (curve_decode_point_ed(publicIdentityKey, signal_buffer_data(publicIdentityKeyBuffer.get()), signal_buffer_len(publicIdentityKeyBuffer.get()), globalContext.get()) < 0) {
warning("Public identity key could not be deserialized");
return false;
}
@@ -3542,7 +3495,7 @@ bool ManagerPrivate::deserializeSignedPublicPreKey(ec_public_key **signedPublicP
return false;
}
- if (curve_decode_point(signedPublicPreKey, signal_buffer_data(signedPublicPreKeyBuffer.get()), signal_buffer_len(signedPublicPreKeyBuffer.get()), globalContext.get()) < 0) {
+ if (curve_decode_point_mont(signedPublicPreKey, signal_buffer_data(signedPublicPreKeyBuffer.get()), signal_buffer_len(signedPublicPreKeyBuffer.get()), globalContext.get()) < 0) {
warning("Signed public pre key could not be deserialized");
return false;
}
@@ -3567,7 +3520,7 @@ bool ManagerPrivate::deserializePublicPreKey(ec_public_key **publicPreKey, const
return false;
}
- if (curve_decode_point(publicPreKey, signal_buffer_data(publicPreKeyBuffer.get()), signal_buffer_len(publicPreKeyBuffer.get()), globalContext.get()) < 0) {
+ if (curve_decode_point_mont(publicPreKey, signal_buffer_data(publicPreKeyBuffer.get()), signal_buffer_len(publicPreKeyBuffer.get()), globalContext.get()) < 0) {
warning("Public pre key could not be deserialized");
return false;
}
@@ -3633,16 +3586,11 @@ QXmppTask<QXmpp::SendResult> ManagerPrivate::sendEmptyMessage(const QString &rec
//
// Sets the key of this client instance's device.
//
-// The first byte representing a version string used by the OMEMO library but
-// not needed for trust management is removed before storing it.
-// It corresponds to the fingerprint shown to users which also does not contain
-// the first byte.
-//
QXmppTask<void> ManagerPrivate::storeOwnKey() const
{
QXmppPromise<void> interface;
- auto future = trustManager->setOwnKey(ns_omemo_2, createKeyId(ownDevice.publicIdentityKey));
+ auto future = trustManager->setOwnKey(ns_omemo_2, ownDevice.publicIdentityKey);
future.then(q, [=]() mutable {
interface.finish();
});
@@ -3715,7 +3663,7 @@ QXmppTask<TrustLevel> ManagerPrivate::storeKey(const QString &keyOwnerJid, const
{
QXmppPromise<TrustLevel> interface;
- auto future = trustManager->addKeys(ns_omemo_2, keyOwnerJid, { createKeyId(key) }, trustLevel);
+ auto future = trustManager->addKeys(ns_omemo_2, keyOwnerJid, { key }, trustLevel);
future.then(q, [=]() mutable {
Q_EMIT q->trustLevelsChanged({ { keyOwnerJid, key } });
interface.finish(std::move(trustLevel));
diff --git a/src/omemo/QXmppOmemoManager_p.h b/src/omemo/QXmppOmemoManager_p.h
index 6875a571..96f10f94 100644
--- a/src/omemo/QXmppOmemoManager_p.h
+++ b/src/omemo/QXmppOmemoManager_p.h
@@ -18,6 +18,8 @@
#include <QTimer>
#include <QtCrypto>
+#undef max
+
class QXmppTrustManager;
class QXmppOmemoManager;
class QXmppPubSubManager;
@@ -34,6 +36,11 @@ using namespace std::chrono_literals;
namespace QXmpp::Omemo::Private {
+// XMPP namespaces
+constexpr auto ns_omemo_2 = "urn:xmpp:omemo:2";
+constexpr auto ns_omemo_2_bundles = "urn:xmpp:omemo:2:bundles";
+constexpr auto ns_omemo_2_devices = "urn:xmpp:omemo:2:devices";
+
// default possible trust levels a key must have to be used for encryption
// The class documentation must be adapted if the trust levels are modified.
constexpr auto ACCEPTED_TRUST_LEVELS = TrustLevel::AutomaticallyTrusted | TrustLevel::ManuallyTrusted | TrustLevel::Authenticated;
@@ -84,14 +91,14 @@ constexpr QCA::Cipher::Padding PAYLOAD_CIPHER_PADDING = QCA::Cipher::PKCS7;
constexpr auto HKDF_INFO = "OMEMO Payload";
constexpr int HKDF_KEY_SIZE = 32;
constexpr int HKDF_SALT_SIZE = 32;
-constexpr int HKDF_OUTPUT_SIZE = 60;
+constexpr int HKDF_OUTPUT_SIZE = 80;
extern const QString PAYLOAD_MESSAGE_AUTHENTICATION_CODE_TYPE;
constexpr uint32_t PAYLOAD_MESSAGE_AUTHENTICATION_CODE_SIZE = 16;
constexpr int PAYLOAD_KEY_SIZE = 32;
constexpr uint32_t PAYLOAD_INITIALIZATION_VECTOR_SIZE = 16;
-constexpr uint32_t PAYLOAD_AUTHENTICATION_KEY_SIZE = 16;
+constexpr uint32_t PAYLOAD_AUTHENTICATION_KEY_SIZE = 32;
// boundaries for the count of characters in SCE's <rpad/> element
constexpr uint32_t SCE_RPAD_SIZE_MIN = 0;
@@ -115,8 +122,6 @@ struct IqDecryptionResult
QXmppE2eeMetadata e2eeMetadata;
};
-QByteArray createKeyId(const QByteArray &key);
-
} // namespace QXmpp::Omemo::Private
using namespace QXmpp::Private;
@@ -168,9 +173,10 @@ public:
QXmppOmemoManagerPrivate(QXmppOmemoManager *parent, QXmppOmemoStorage *omemoStorage);
void init();
- bool initGlobalContext();
- bool initLocking();
- bool initCryptoProvider();
+ // exports for unit tests
+ QXMPP_EXPORT bool initGlobalContext();
+ QXMPP_EXPORT bool initLocking();
+ QXMPP_EXPORT bool initCryptoProvider();
void initStores();
signal_protocol_identity_key_store createIdentityKeyStore() const;