aboutsummaryrefslogtreecommitdiff
path: root/omemo_db.cpp
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-06-29 14:10:06 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-08-30 02:46:41 +0200
commit6ecc6b6f0272a47d41ce5d619eaa779a29fcf9df (patch)
treeb304ad33ecadcd1209347b67d525506356d149f0 /omemo_db.cpp
parent48cfe26383feb2fcf6638905060c605af8eb2c69 (diff)
WIP OMEMO
Diffstat (limited to 'omemo_db.cpp')
-rw-r--r--omemo_db.cpp374
1 files changed, 374 insertions, 0 deletions
diff --git a/omemo_db.cpp b/omemo_db.cpp
new file mode 100644
index 0000000..bc8751b
--- /dev/null
+++ b/omemo_db.cpp
@@ -0,0 +1,374 @@
+#include "omemo_db.h"
+#include <QXmppConfiguration.h>
+#include <QXmppFutureUtils_p.h>
+#include <QXmppPromise.h>
+#include <qt5keychain/keychain.h>
+#include <QEventLoop>
+#include <QtConcurrent>
+#include <QString>
+#include <iostream>
+#include <optional>
+
+static const QString service_ns = "xxcc/omemo/";
+
+OmemoDb::OmemoDb(const QString &jid) :
+ jid(jid)
+{
+}
+
+QString OmemoDb::service() const
+{
+ return service_ns + jid;
+}
+
+QXmppTask<QXmppOmemoStorage::OmemoData> OmemoDb::allData()
+{
+ return QXmpp::Private::makeReadyTask(QXmppOmemoStorage::OmemoData());
+}
+
+int OmemoDb::storeOwnKeyId(const QString &service, const uint32_t id)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/keyid");
+ job.setTextData(QString::number(id, 16));
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store own key ID: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storePrivateIdentityKey(const QString &service,
+ const QByteArray &privateIdentityKey)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/privateIdentityKey");
+ job.setBinaryData(privateIdentityKey);
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store private identity key: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storePublicIdentityKey(const QString &service,
+ const QByteArray &publicIdentityKey)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/publicIdentityKey");
+ job.setBinaryData(publicIdentityKey);
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store public identity key: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storeLatestSignedPreKeyId(const QString &service,
+ const uint32_t latestSignedPreKeyId)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/latestSignedPreKeyId");
+ job.setTextData(QString::number(latestSignedPreKeyId, 16));
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store latest signed prekey ID: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storeLatestPreKeyId(const QString &service,
+ const uint32_t latestPreKeyId)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/latestPreKeyId");
+ job.setTextData(QString::number(latestPreKeyId, 16));
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store latest prekey ID: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+QXmppTask<void> OmemoDb::setOwnDevice(const std::optional<OwnDevice> &device)
+{
+ if (!device.has_value())
+ return QXmpp::Private::makeReadyTask();
+
+ QXmppPromise<void> promise;
+
+ auto future = QtConcurrent::run(
+ [=] () mutable
+ {
+ const auto &d = device.value();
+ const auto srv = service();
+
+ storeDeviceLabel(srv, d.label)
+ || storeOwnKeyId(srv, d.id)
+ || storePrivateIdentityKey(srv, d.privateIdentityKey)
+ || storePublicIdentityKey(srv, d.publicIdentityKey)
+ || storeLatestSignedPreKeyId(srv, d.latestSignedPreKeyId)
+ || storeLatestPreKeyId(srv, d.latestPreKeyId);
+
+ promise.finish();
+ });
+
+ return promise.task();
+}
+
+QXmppTask<void> OmemoDb::addSignedPreKeyPair(const uint32_t keyId,
+ const SignedPreKeyPair &keyPair)
+{
+ return QXmpp::Private::makeReadyTask();
+}
+
+QXmppTask<void> OmemoDb::removeSignedPreKeyPair(uint32_t keyId)
+{
+ return QXmpp::Private::makeReadyTask();
+}
+
+QXmppTask<void> OmemoDb::addPreKeyPairs(
+ const QHash<uint32_t, QByteArray> &keyPairs)
+{
+ return QXmpp::Private::makeReadyTask();
+}
+
+QXmppTask<void> OmemoDb::removePreKeyPair(const uint32_t keyId)
+{
+ return QXmpp::Private::makeReadyTask();
+}
+
+int OmemoDb::storeDeviceLabel(const QString &service, const QString &label)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/label");
+ job.setTextData(label);
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store device label: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storeKeyId(const QString &service, const QByteArray &keyId)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/key_id");
+ job.setBinaryData(keyId);
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store device keyID: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storeSession(const QString &service, const QByteArray &session)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/session");
+ job.setBinaryData(session);
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store device session: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storeUnrespondedSentStanzasCount(const QString &service,
+ const int count)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/unresponded_sent_stanzas");
+ job.setTextData(QString::number(count));
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store device unresponded sent stanzas: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storeUnrespondedReceivedStanzasCount(const QString &service,
+ const int count)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/unresponded_received_stanzas");
+ job.setTextData(QString::number(count));
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store device unresponded received stanzas: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+int OmemoDb::storeRemovalFromDeviceListDate(const QString &service,
+ const QDateTime &dt)
+{
+ QKeychain::WritePasswordJob job(service);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/unresponded_received_stanzas");
+ job.setTextData(QString::number(dt.currentMSecsSinceEpoch()));
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store device unresponded received stanzas: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+QXmppTask<void> OmemoDb::addDevice(const QString &jid,
+ const uint32_t deviceId, const Device &device)
+{
+ const QString fullservice = service_ns + jid;
+ QXmppPromise<void> promise;
+
+ auto future = QtConcurrent::run(
+ [=] () mutable
+ {
+ storeDeviceLabel(fullservice, device.label)
+ || storeKeyId(fullservice, device.keyId)
+ || storeSession(fullservice, device.session)
+ || storeUnrespondedSentStanzasCount(fullservice,
+ device.unrespondedSentStanzasCount)
+ || storeUnrespondedReceivedStanzasCount(fullservice,
+ device.unrespondedSentStanzasCount)
+ || storeRemovalFromDeviceListDate(fullservice,
+ device.removalFromDeviceListDate);
+
+ promise.finish();
+ });
+
+ return promise.task();
+}
+
+QXmppTask<void> OmemoDb::removeDevice(const QString &jid,
+ const uint32_t deviceId)
+{
+#if 0
+ const QString fullservice = service_ns + jid;
+ QKeychain::DeletePasswordJob job(fullservice);
+ QEventLoop loop;
+
+ loop.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+ job.setKey("device/unresponded_received_stanzas");
+ job.setTextData(QString::number(dt.currentMSecsSinceEpoch()));
+ job.start();
+ loop.exec();
+
+ if (job.error())
+ {
+ std::cerr << "Failed to store device unresponded received stanzas: "
+ << qPrintable(job.errorString()) << std::endl;
+ return -1;
+ }
+
+ return 0;
+#endif
+ return QXmpp::Private::makeReadyTask();
+}
+
+QXmppTask<void> OmemoDb::removeDevices(const QString &jid)
+{
+ return QXmpp::Private::makeReadyTask();
+}
+
+QXmppTask<void> OmemoDb::resetAll()
+{
+ return QXmpp::Private::makeReadyTask();
+}