aboutsummaryrefslogtreecommitdiff
path: root/src/omemo/QXmppOmemoData.cpp
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2022-05-31 12:22:48 +0200
committerLinus Jahn <lnj@kaidan.im>2022-08-13 15:55:03 +0200
commitf0e0e1cd227c08ffd97aa42813a479b8c3ca6d23 (patch)
tree12ca6aefdef9195ee8937406db86e73cf1a5f820 /src/omemo/QXmppOmemoData.cpp
parent87df8a8dda385558d39639ce09e2717974264ab6 (diff)
downloadqxmpp-f0e0e1cd227c08ffd97aa42813a479b8c3ca6d23.tar.gz
Split up OMEMO into extra module
Diffstat (limited to 'src/omemo/QXmppOmemoData.cpp')
-rw-r--r--src/omemo/QXmppOmemoData.cpp465
1 files changed, 465 insertions, 0 deletions
diff --git a/src/omemo/QXmppOmemoData.cpp b/src/omemo/QXmppOmemoData.cpp
new file mode 100644
index 00000000..d1dd2a88
--- /dev/null
+++ b/src/omemo/QXmppOmemoData.cpp
@@ -0,0 +1,465 @@
+// SPDX-FileCopyrightText: 2021 Germán Márquez Mejía <mancho@olomono.de>
+// SPDX-FileCopyrightText: 2021 Melvin Keskin <melvo@olomono.de>
+//
+// 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>
+
+/// \cond
+///
+/// \class QXmppOmemoDeviceElement
+///
+/// \brief The QXmppOmemoDeviceElement class represents an element of the
+/// OMEMO device list as defined by \xep{0384, OMEMO Encryption}.
+///
+
+///
+/// Returns true if the IDs of both elements match.
+///
+bool QXmppOmemoDeviceElement::operator==(const QXmppOmemoDeviceElement &other) const
+{
+ return m_id == other.id();
+}
+
+///
+/// Returns the ID of this device element.
+///
+/// The ID is used to identify a device and fetch its bundle.
+/// The ID is 0 if it is unset.
+///
+/// \see QXmppOmemoDeviceBundle
+///
+/// \return this device element's ID
+///
+uint32_t QXmppOmemoDeviceElement::id() const
+{
+ return m_id;
+}
+
+///
+/// Sets the ID of this device element.
+///
+/// The ID must be at least 1 and at most
+/// \c std::numeric_limits<int32_t>::max().
+///
+/// \param id this device element's ID
+///
+void QXmppOmemoDeviceElement::setId(uint32_t id)
+{
+ m_id = id;
+}
+
+///
+/// Returns the label of this device element.
+///
+/// The label is a human-readable string used to identify the device by users.
+/// If no label is set, a default-constructed QString is returned.
+///
+/// \return this device element's label
+///
+QString QXmppOmemoDeviceElement::label() const
+{
+ return m_label;
+}
+
+///
+/// Sets the optional label of this device element.
+///
+/// The label should not contain more than 53 characters.
+///
+/// \param label this device element's label
+///
+void QXmppOmemoDeviceElement::setLabel(const QString &label)
+{
+ m_label = label;
+}
+
+void QXmppOmemoDeviceElement::parse(const QDomElement &element)
+{
+ m_id = element.attribute(QStringLiteral("id")).toInt();
+ m_label = element.attribute(QStringLiteral("label"));
+}
+
+void QXmppOmemoDeviceElement::toXml(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement(QStringLiteral("device"));
+
+ writer->writeAttribute(QStringLiteral("id"), QString::number(m_id));
+ if (!m_label.isEmpty()) {
+ writer->writeAttribute(QStringLiteral("label"), m_label);
+ }
+
+ writer->writeEndElement(); // device
+}
+
+///
+/// Determines whether the given DOM element is an OMEMO device element.
+///
+/// \param element DOM element being checked
+///
+/// \return true if element is an OMEMO device element, otherwise false
+///
+bool QXmppOmemoDeviceElement::isOmemoDeviceElement(const QDomElement &element)
+{
+ return element.tagName() == QStringLiteral("device") &&
+ element.namespaceURI() == ns_omemo_2;
+}
+
+///
+/// \class QXmppOmemoDeviceList
+///
+/// \brief The QXmppOmemoDeviceList class represents an OMEMO device list
+/// as defined by \xep{0384, OMEMO Encryption}.
+///
+
+void QXmppOmemoDeviceList::parse(const QDomElement &element)
+{
+ for (auto device = element.firstChildElement(QStringLiteral("device"));
+ !device.isNull();
+ device = device.nextSiblingElement(QStringLiteral("device"))) {
+ QXmppOmemoDeviceElement deviceElement;
+ deviceElement.parse(device);
+ append(deviceElement);
+ }
+}
+
+void QXmppOmemoDeviceList::toXml(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement(QStringLiteral("devices"));
+ writer->writeDefaultNamespace(ns_omemo_2);
+
+ for (const auto &device : *this) {
+ device.toXml(writer);
+ }
+
+ writer->writeEndElement();
+}
+
+///
+/// Determines whether the given DOM element is an OMEMO device list.
+///
+/// \param element DOM element being checked
+///
+/// \return true if element is an OMEMO device list, otherwise false
+///
+bool QXmppOmemoDeviceList::isOmemoDeviceList(const QDomElement &element)
+{
+ return element.tagName() == QStringLiteral("devices") &&
+ element.namespaceURI() == ns_omemo_2;
+}
+
+///
+/// \class QXmppOmemoDeviceBundle
+///
+/// \brief The QXmppOmemoDeviceBundle class represents an OMEMO bundle as
+/// defined by \xep{0384, OMEMO Encryption}.
+///
+/// It is a collection of publicly accessible data used by the X3DH key exchange.
+/// The data is used to build an encrypted session with an OMEMO device.
+///
+
+///
+/// Returns the public identity key.
+///
+/// The public identity key is the public long-term key which never changes.
+///
+/// \return the public identity key
+///
+QByteArray QXmppOmemoDeviceBundle::publicIdentityKey() const
+{
+ return m_publicIdentityKey;
+}
+
+///
+/// Sets the public identity key.
+///
+/// \param key public identity key
+///
+void QXmppOmemoDeviceBundle::setPublicIdentityKey(const QByteArray &key)
+{
+ m_publicIdentityKey = key;
+}
+
+///
+/// Returns the public pre key that is signed.
+///
+/// \return the signed public pre key
+///
+QByteArray QXmppOmemoDeviceBundle::signedPublicPreKey() const
+{
+ return m_signedPublicPreKey;
+}
+
+///
+/// Sets the public pre key that is signed.
+///
+/// \param key signed public pre key
+///
+void QXmppOmemoDeviceBundle::setSignedPublicPreKey(const QByteArray &key)
+{
+ m_signedPublicPreKey = key;
+}
+
+///
+/// Returns the ID of the public pre key that is signed.
+///
+/// The ID is 0 if it is unset.
+///
+/// \return the ID of the signed public pre key
+///
+uint32_t QXmppOmemoDeviceBundle::signedPublicPreKeyId() const
+{
+ return m_signedPublicPreKeyId;
+}
+
+///
+/// Sets the ID of the public pre key that is signed.
+///
+/// The ID must be at least 1 and at most
+/// \c std::numeric_limits<int32_t>::max().
+///
+/// \param id ID of the signed public pre key
+///
+void QXmppOmemoDeviceBundle::setSignedPublicPreKeyId(uint32_t id)
+{
+ m_signedPublicPreKeyId = id;
+}
+
+///
+/// Returns the signature of the public pre key that is signed.
+///
+/// \return the signature of the signed public pre key
+///
+QByteArray QXmppOmemoDeviceBundle::signedPublicPreKeySignature() const
+{
+ return m_signedPublicPreKeySignature;
+}
+
+///
+/// Sets the signature of the public pre key that is signed.
+///
+/// \param signature signature of the signed public pre key
+///
+void QXmppOmemoDeviceBundle::setSignedPublicPreKeySignature(const QByteArray &signature)
+{
+ m_signedPublicPreKeySignature = signature;
+}
+
+///
+/// Returns the public pre keys.
+///
+/// The key of a key-value pair represents the ID of the corresponding public
+/// pre key.
+/// The value of a key-value pair represents the public pre key.
+///
+/// \return the public pre keys
+///
+QHash<uint32_t, QByteArray> QXmppOmemoDeviceBundle::publicPreKeys() const
+{
+ return m_publicPreKeys;
+}
+
+///
+/// Adds a public pre key.
+///
+/// The ID must be at least 1 and at most
+/// \c std::numeric_limits<int32_t>::max().
+///
+/// \param id ID of the public pre key
+/// \param key public pre key
+///
+void QXmppOmemoDeviceBundle::addPublicPreKey(uint32_t id, const QByteArray &key)
+{
+ m_publicPreKeys.insert(id, key);
+}
+
+///
+/// Removes a public pre key.
+///
+/// \param id ID of the public pre key
+/// \param key public pre key
+///
+void QXmppOmemoDeviceBundle::removePublicPreKey(uint32_t id)
+{
+ m_publicPreKeys.remove(id);
+}
+
+void QXmppOmemoDeviceBundle::parse(const QDomElement &element)
+{
+ m_publicIdentityKey = QByteArray::fromBase64(element.firstChildElement(QStringLiteral("ik")).text().toLatin1());
+
+ const auto signedPublicPreKeyElement = element.firstChildElement(QStringLiteral("spk"));
+ if (!signedPublicPreKeyElement.isNull()) {
+ m_signedPublicPreKeyId = signedPublicPreKeyElement.attribute(QStringLiteral("id")).toInt();
+ m_signedPublicPreKey = QByteArray::fromBase64(signedPublicPreKeyElement.text().toLatin1());
+ }
+ m_signedPublicPreKeySignature = QByteArray::fromBase64(element.firstChildElement(QStringLiteral("spks")).text().toLatin1());
+
+ const auto publicPreKeysElement = element.firstChildElement(QStringLiteral("prekeys"));
+ if (!publicPreKeysElement.isNull()) {
+ for (QDomElement publicPreKeyElement = publicPreKeysElement.firstChildElement(QStringLiteral("pk"));
+ !publicPreKeyElement.isNull();
+ publicPreKeyElement = publicPreKeyElement.nextSiblingElement(QStringLiteral("pk"))) {
+ m_publicPreKeys.insert(publicPreKeyElement.attribute(QStringLiteral("id")).toInt(), QByteArray::fromBase64(publicPreKeyElement.text().toLatin1()));
+ }
+ }
+}
+
+void QXmppOmemoDeviceBundle::toXml(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement(QStringLiteral("bundle"));
+ writer->writeDefaultNamespace(ns_omemo_2);
+
+ writer->writeStartElement(QStringLiteral("ik"));
+ writer->writeCharacters(publicIdentityKey().toBase64());
+ writer->writeEndElement();
+
+ writer->writeStartElement(QStringLiteral("spk"));
+ writer->writeAttribute(QStringLiteral("id"), QString::number(signedPublicPreKeyId()));
+ writer->writeCharacters(signedPublicPreKey().toBase64());
+ writer->writeEndElement();
+
+ writer->writeStartElement(QStringLiteral("spks"));
+ writer->writeCharacters(signedPublicPreKeySignature().toBase64());
+ writer->writeEndElement();
+
+ writer->writeStartElement(QStringLiteral("prekeys"));
+ for (auto it = m_publicPreKeys.cbegin(); it != m_publicPreKeys.cend(); it++) {
+ writer->writeStartElement(QStringLiteral("pk"));
+ writer->writeAttribute(QStringLiteral("id"), QString::number(it.key()));
+ writer->writeCharacters(it.value().toBase64());
+ writer->writeEndElement();
+ }
+ writer->writeEndElement(); // prekeys
+
+ writer->writeEndElement(); // bundle
+}
+
+///
+/// Determines whether the given DOM element is an OMEMO device bundle.
+///
+/// \param element DOM element being checked
+///
+/// \return true if element is an OMEMO device bundle, otherwise false
+///
+bool QXmppOmemoDeviceBundle::isOmemoDeviceBundle(const QDomElement &element)
+{
+ return element.tagName() == QStringLiteral("bundle") &&
+ element.namespaceURI() == ns_omemo_2;
+}
+
+///
+/// \class QXmppOmemoIq
+///
+/// \brief The QXmppOmemoIq class represents an encrypted IQ stanza as defined
+/// by \xep{0384, OMEMO Encryption} and \xep{0420, Stanza Content Encryption}
+/// (SCE).
+///
+/// \ingroup Stanzas
+///
+
+///
+/// Returns the OMEMO element which contains the data used by OMEMO.
+///
+/// \return the OMEMO element
+///
+QXmppOmemoElement QXmppOmemoIq::omemoElement()
+{
+ return m_omemoElement;
+}
+
+///
+/// Sets the OMEMO element which contains the data used by OMEMO.
+///
+/// \param omemoElement OMEMO element
+///
+void QXmppOmemoIq::setOmemoElement(const QXmppOmemoElement &omemoElement)
+{
+ m_omemoElement = omemoElement;
+}
+
+void QXmppOmemoIq::parseElementFromChild(const QDomElement &element)
+{
+ QDomElement child = element.firstChildElement();
+ m_omemoElement.parse(child);
+}
+
+void QXmppOmemoIq::toXmlElementFromChild(QXmlStreamWriter *writer) const
+{
+ m_omemoElement.toXml(writer);
+}
+
+///
+/// Determines whether the given DOM element is an OMEMO IQ stanza.
+///
+/// \param element DOM element being checked
+///
+/// \return true if element is an OMEMO IQ stanza, otherwise false
+///
+bool QXmppOmemoIq::isOmemoIq(const QDomElement &element)
+{
+ auto child = element.firstChildElement();
+ return !child.isNull() && QXmppOmemoElement::isOmemoElement(child);
+}
+
+QXmppOmemoDeviceBundle QXmppOmemoDeviceBundleItem::deviceBundle() const
+{
+ return m_deviceBundle;
+}
+
+void QXmppOmemoDeviceBundleItem::setDeviceBundle(const QXmppOmemoDeviceBundle &deviceBundle)
+{
+ m_deviceBundle = deviceBundle;
+}
+
+bool QXmppOmemoDeviceBundleItem::isItem(const QDomElement &itemElement)
+{
+ return QXmppPubSubItem::isItem(itemElement, QXmppOmemoDeviceBundle::isOmemoDeviceBundle);
+}
+
+void QXmppOmemoDeviceBundleItem::parsePayload(const QDomElement &payloadElement)
+{
+ m_deviceBundle.parse(payloadElement);
+}
+
+void QXmppOmemoDeviceBundleItem::serializePayload(QXmlStreamWriter *writer) const
+{
+ m_deviceBundle.toXml(writer);
+}
+
+QXmppOmemoDeviceList QXmppOmemoDeviceListItem::deviceList() const
+{
+ return m_deviceList;
+}
+
+void QXmppOmemoDeviceListItem::setDeviceList(const QXmppOmemoDeviceList &deviceList)
+{
+ m_deviceList = deviceList;
+}
+
+bool QXmppOmemoDeviceListItem::isItem(const QDomElement &itemElement)
+{
+ return QXmppPubSubItem::isItem(itemElement, QXmppOmemoDeviceList::isOmemoDeviceList);
+}
+
+void QXmppOmemoDeviceListItem::parsePayload(const QDomElement &payloadElement)
+{
+ m_deviceList.parse(payloadElement);
+}
+
+void QXmppOmemoDeviceListItem::serializePayload(QXmlStreamWriter *writer) const
+{
+ m_deviceList.toXml(writer);
+}
+/// \endcond