diff options
| author | Linus Jahn <lnj@kaidan.im> | 2022-05-31 12:22:48 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2022-08-13 15:55:03 +0200 |
| commit | f0e0e1cd227c08ffd97aa42813a479b8c3ca6d23 (patch) | |
| tree | 12ca6aefdef9195ee8937406db86e73cf1a5f820 /src/omemo/QXmppOmemoData.cpp | |
| parent | 87df8a8dda385558d39639ce09e2717974264ab6 (diff) | |
| download | qxmpp-f0e0e1cd227c08ffd97aa42813a479b8c3ca6d23.tar.gz | |
Split up OMEMO into extra module
Diffstat (limited to 'src/omemo/QXmppOmemoData.cpp')
| -rw-r--r-- | src/omemo/QXmppOmemoData.cpp | 465 |
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 |
