aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelvin Keskin <melvo@olomono.de>2021-09-02 23:37:24 +0200
committerLinus Jahn <lnj@kaidan.im>2021-09-03 16:16:14 +0200
commit12c63eddded9f02369bd4e569f62acfdd95cc723 (patch)
treede008ca97accd962c5d2ca54ba9302c2f952a0ea
parent11db6293ced5c4665630ad3d728aba5751a3f658 (diff)
downloadqxmpp-12c63eddded9f02369bd4e569f62acfdd95cc723.tar.gz
Add QXmppOmemoEnvelope
Co-authored-by: Germán Márquez Mejía <mancho@olomono.de>
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/base/QXmppOmemoData.cpp153
-rw-r--r--src/base/QXmppOmemoEnvelope.h67
-rw-r--r--tests/qxmppomemodata/tst_qxmppomemodata.cpp75
4 files changed, 296 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7a17b027..e166a8cb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -49,6 +49,7 @@ set(INSTALL_HEADER_FILES
base/QXmppOmemoDeviceBundle.h
base/QXmppOmemoDeviceList.h
base/QXmppOmemoDeviceElement.h
+ base/QXmppOmemoEnvelope.h
base/QXmppPingIq.h
base/QXmppPresence.h
base/QXmppPubSubAffiliation.h
diff --git a/src/base/QXmppOmemoData.cpp b/src/base/QXmppOmemoData.cpp
index 84170c24..6fb2580d 100644
--- a/src/base/QXmppOmemoData.cpp
+++ b/src/base/QXmppOmemoData.cpp
@@ -26,6 +26,7 @@
#include "QXmppOmemoDeviceBundle.h"
#include "QXmppOmemoDeviceElement.h"
#include "QXmppOmemoDeviceList.h"
+#include "QXmppOmemoEnvelope.h"
#include "QXmppUtils.h"
#include <QDomElement>
@@ -465,3 +466,155 @@ bool QXmppOmemoDeviceBundle::isOmemoDeviceBundle(const QDomElement &element)
return element.tagName() == QStringLiteral("bundle") &&
element.namespaceURI() == ns_omemo_1;
}
+
+///
+/// \class QXmppOmemoEnvelope
+///
+/// \brief The QXmppOmemoEnvelope class represents an OMEMO envelope as
+/// defined by \xep{0384, OMEMO Encryption}.
+///
+/// \since QXmpp 1.5
+///
+
+class QXmppOmemoEnvelopePrivate : public QSharedData
+{
+public:
+ uint32_t recipientDeviceId = 0;
+ bool isUsedForKeyExchange = false;
+ QByteArray data;
+};
+
+///
+/// Constructs an OMEMO envelope.
+///
+QXmppOmemoEnvelope::QXmppOmemoEnvelope()
+ : d(new QXmppOmemoEnvelopePrivate)
+{
+}
+
+///
+/// Constructs a copy of \a other.
+///
+/// \param other
+///
+QXmppOmemoEnvelope::QXmppOmemoEnvelope(const QXmppOmemoEnvelope &other) = default;
+
+QXmppOmemoEnvelope::~QXmppOmemoEnvelope() = default;
+
+///
+/// Assigns \a other to this OMEMO envelope.
+///
+/// \param other
+///
+QXmppOmemoEnvelope &QXmppOmemoEnvelope::operator=(const QXmppOmemoEnvelope &other) = default;
+
+///
+/// Returns the ID of the recipient's device.
+///
+/// The ID is 0 if it is unset.
+///
+/// \return the recipient's device ID
+///
+uint32_t QXmppOmemoEnvelope::recipientDeviceId() const
+{
+ return d->recipientDeviceId;
+}
+
+///
+/// Sets the ID of the recipient's device.
+///
+/// A valid ID must be at least 1 and at most 2^32-1.
+///
+/// \param id recipient's device ID
+///
+void QXmppOmemoEnvelope::setRecipientDeviceId(const uint32_t id)
+{
+ d->recipientDeviceId = id;
+}
+
+///
+/// Returns true if a pre-key was used to prepare this envelope.
+///
+/// The default is false.
+///
+/// \return true if a pre-key was used to prepare this envelope, otherwise false
+///
+bool QXmppOmemoEnvelope::isUsedForKeyExchange() const
+{
+ return d->isUsedForKeyExchange;
+}
+
+///
+/// Sets whether a pre-key was used to prepare this envelope.
+///
+/// \param isUsed whether a pre-key was used to prepare this envelope
+///
+void QXmppOmemoEnvelope::setIsUsedForKeyExchange(const bool isUsed)
+{
+ d->isUsedForKeyExchange = isUsed;
+}
+
+///
+/// Returns the BLOB containing the data for the underlying double ratchet library.
+///
+/// It should be treated like an obscure BLOB being passed as is to the ratchet
+/// library for further processing.
+///
+/// \return the binary data for the ratchet library
+///
+QByteArray QXmppOmemoEnvelope::data() const
+{
+ return d->data;
+}
+
+///
+/// Sets the BLOB containing the data from the underlying double ratchet library.
+///
+/// It should be treated like an obscure BLOB produced by the ratchet library.
+///
+/// \param data binary data from the ratchet library
+///
+void QXmppOmemoEnvelope::setData(const QByteArray &data)
+{
+ d->data = data;
+}
+
+/// \cond
+void QXmppOmemoEnvelope::parse(const QDomElement &element)
+{
+ d->recipientDeviceId = element.attribute("rid").toInt();
+
+ const auto isUsedForKeyExchange = element.attribute("kex");
+ if (isUsedForKeyExchange == "true" || isUsedForKeyExchange == "1") {
+ d->isUsedForKeyExchange = true;
+ }
+
+ d->data = QByteArray::fromBase64(element.text().toLatin1());
+}
+
+void QXmppOmemoEnvelope::toXml(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement("key");
+ writer->writeAttribute("rid", QString::number(d->recipientDeviceId));
+
+ if (d->isUsedForKeyExchange) {
+ helperToXmlAddAttribute(writer, "kex", "true");
+ }
+
+ writer->writeCharacters(d->data.toBase64());
+ writer->writeEndElement();
+}
+/// \endcond
+
+///
+/// Determines whether the given DOM element is an OMEMO envelope.
+///
+/// \param element DOM element being checked
+///
+/// \return true if element is an OMEMO envelope, otherwise false
+///
+bool QXmppOmemoEnvelope::isOmemoEnvelope(const QDomElement &element)
+{
+ return element.tagName() == QStringLiteral("key") &&
+ element.namespaceURI() == ns_omemo_1;
+}
diff --git a/src/base/QXmppOmemoEnvelope.h b/src/base/QXmppOmemoEnvelope.h
new file mode 100644
index 00000000..a8f0a0c1
--- /dev/null
+++ b/src/base/QXmppOmemoEnvelope.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008-2021 The QXmpp developers
+ *
+ * Author:
+ * Germán Márquez Mejía
+ * Melvin Keskin
+ *
+ * Source:
+ * https://github.com/qxmpp-project/qxmpp
+ *
+ * This file is a part of QXmpp library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+
+#ifndef QXMPPOMEMOENVELOPE_H
+#define QXMPPOMEMOENVELOPE_H
+
+#include "QXmppGlobal.h"
+
+#include <QSharedDataPointer>
+
+class QDomElement;
+class QXmppOmemoEnvelopePrivate;
+class QXmlStreamWriter;
+
+class QXMPP_EXPORT QXmppOmemoEnvelope
+{
+public:
+ QXmppOmemoEnvelope();
+ QXmppOmemoEnvelope(const QXmppOmemoEnvelope &other);
+ ~QXmppOmemoEnvelope();
+
+ QXmppOmemoEnvelope &operator=(const QXmppOmemoEnvelope &other);
+
+ uint32_t recipientDeviceId() const;
+ void setRecipientDeviceId(uint32_t id);
+
+ bool isUsedForKeyExchange() const;
+ void setIsUsedForKeyExchange(bool isUsed);
+
+ QByteArray data() const;
+ void setData(const QByteArray &data);
+
+ /// \cond
+ void parse(const QDomElement &element);
+ void toXml(QXmlStreamWriter *writer) const;
+ /// \endcond
+
+ static bool isOmemoEnvelope(const QDomElement &element);
+
+private:
+ QSharedDataPointer<QXmppOmemoEnvelopePrivate> d;
+};
+
+Q_DECLARE_TYPEINFO(QXmppOmemoEnvelope, Q_MOVABLE_TYPE);
+
+#endif // QXMPPOMEMOENVELOPE_H
diff --git a/tests/qxmppomemodata/tst_qxmppomemodata.cpp b/tests/qxmppomemodata/tst_qxmppomemodata.cpp
index 46bc2b44..8a583622 100644
--- a/tests/qxmppomemodata/tst_qxmppomemodata.cpp
+++ b/tests/qxmppomemodata/tst_qxmppomemodata.cpp
@@ -25,6 +25,7 @@
#include "QXmppOmemoDeviceBundle.h"
#include "QXmppOmemoDeviceElement.h"
#include "QXmppOmemoDeviceList.h"
+#include "QXmppOmemoEnvelope.h"
#include "util.h"
#include <QObject>
@@ -44,6 +45,10 @@ private slots:
void testIsOmemoDeviceBundle_data();
void testIsOmemoDeviceBundle();
void testOmemoDeviceBundle();
+ void testIsOmemoEnvelope_data();
+ void testIsOmemoEnvelope();
+ void testOmemoEnvelope_data();
+ void testOmemoEnvelope();
};
void tst_QXmppOmemoData::testIsOmemoDeviceElement_data()
@@ -235,5 +240,75 @@ void tst_QXmppOmemoData::testOmemoDeviceBundle()
serializePacket(deviceBundle2, xml);
}
+void tst_QXmppOmemoData::testIsOmemoEnvelope_data()
+{
+ QTest::addColumn<QByteArray>("xml");
+ QTest::addColumn<bool>("isValid");
+
+ QTest::newRow("valid")
+ << QByteArrayLiteral("<key xmlns=\"urn:xmpp:omemo:1\"/>")
+ << true;
+ QTest::newRow("invalidTag")
+ << QByteArrayLiteral("<invalid xmlns=\"urn:xmpp:omemo:1\"/>")
+ << false;
+ QTest::newRow("invalidNamespace")
+ << QByteArrayLiteral("<key xmlns=\"invalid\"/>")
+ << false;
+}
+
+void tst_QXmppOmemoData::testIsOmemoEnvelope()
+{
+ QFETCH(QByteArray, xml);
+ QFETCH(bool, isValid);
+
+ QDomDocument doc;
+ QCOMPARE(doc.setContent(xml, true), true);
+ const QDomElement element = doc.documentElement();
+ QCOMPARE(QXmppOmemoEnvelope::isOmemoEnvelope(element), isValid);
+}
+
+void tst_QXmppOmemoData::testOmemoEnvelope_data()
+{
+ QTest::addColumn<QByteArray>("xml");
+ QTest::addColumn<uint32_t>("recipientDeviceId");
+ QTest::addColumn<bool>("isUsedForKeyExchange");
+ QTest::addColumn<QByteArray>("data");
+
+ QTest::newRow("keyAndHmac")
+ << QByteArrayLiteral("<key rid=\"1337\">PTEoSk91VnRZSXBzcFlPXy4jZ3NKcGVZZ2d3YVJbVj8K</key>")
+ << uint32_t(1337)
+ << false
+ << QByteArrayLiteral("PTEoSk91VnRZSXBzcFlPXy4jZ3NKcGVZZ2d3YVJbVj8K");
+ QTest::newRow("keyExchange")
+ << QByteArrayLiteral("<key rid=\"12321\" kex=\"true\">a012U0R9WixWKUYhYipucnZOWG06akFOR3Q1NGNOOmUK</key>")
+ << uint32_t(12321)
+ << true
+ << QByteArrayLiteral("a012U0R9WixWKUYhYipucnZOWG06akFOR3Q1NGNOOmUK");
+}
+
+void tst_QXmppOmemoData::testOmemoEnvelope()
+{
+ QFETCH(QByteArray, xml);
+ QFETCH(uint32_t, recipientDeviceId);
+ QFETCH(bool, isUsedForKeyExchange);
+ QFETCH(QByteArray, data);
+
+ QXmppOmemoEnvelope omemoEnvelope1;
+ parsePacket(omemoEnvelope1, xml);
+ QCOMPARE(omemoEnvelope1.recipientDeviceId(), recipientDeviceId);
+ QCOMPARE(omemoEnvelope1.isUsedForKeyExchange(), isUsedForKeyExchange);
+ QCOMPARE(omemoEnvelope1.data().toBase64(), data);
+ serializePacket(omemoEnvelope1, xml);
+
+ QXmppOmemoEnvelope omemoEnvelope2;
+ omemoEnvelope2.setRecipientDeviceId(recipientDeviceId);
+ omemoEnvelope2.setIsUsedForKeyExchange(isUsedForKeyExchange);
+ omemoEnvelope2.setData(QByteArray::fromBase64(data));
+ QCOMPARE(omemoEnvelope2.recipientDeviceId(), recipientDeviceId);
+ QCOMPARE(omemoEnvelope2.isUsedForKeyExchange(), isUsedForKeyExchange);
+ QCOMPARE(omemoEnvelope2.data().toBase64(), data);
+ serializePacket(omemoEnvelope2, xml);
+}
+
QTEST_MAIN(tst_QXmppOmemoData)
#include "tst_qxmppomemodata.moc"