aboutsummaryrefslogtreecommitdiff
path: root/lib/keyverificationsession.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/keyverificationsession.h')
-rw-r--r--lib/keyverificationsession.h153
1 files changed, 153 insertions, 0 deletions
diff --git a/lib/keyverificationsession.h b/lib/keyverificationsession.h
new file mode 100644
index 00000000..32a91cfc
--- /dev/null
+++ b/lib/keyverificationsession.h
@@ -0,0 +1,153 @@
+// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#pragma once
+
+#include "events/keyverificationevent.h"
+
+#include <QtCore/QObject>
+
+struct OlmSAS;
+
+namespace Quotient {
+class Connection;
+
+struct QUOTIENT_API EmojiEntry {
+ QString emoji;
+ QString description;
+
+ Q_GADGET
+ Q_PROPERTY(QString emoji MEMBER emoji CONSTANT)
+ Q_PROPERTY(QString description MEMBER description CONSTANT)
+
+public:
+ bool operator==(const EmojiEntry& rhs) const = default;
+};
+
+/** A key verification session. Listen for incoming sessions by connecting to Connection::newKeyVerificationSession.
+ Start a new session using Connection::startKeyVerificationSession.
+ The object is delete after finished is emitted.
+*/
+class QUOTIENT_API KeyVerificationSession : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum State {
+ INCOMING, ///< There is a request for verification incoming
+ //! We sent a request for verification and are waiting for ready
+ WAITINGFORREADY,
+ //! Either party sent a ready as a response to a request; the user
+ //! selects a method
+ READY,
+ WAITINGFORACCEPT, ///< We sent a start and are waiting for an accept
+ ACCEPTED, ///< The other party sent an accept and is waiting for a key
+ WAITINGFORKEY, ///< We're waiting for a key
+ //! We're waiting for the *user* to verify the emojis
+ WAITINGFORVERIFICATION,
+ WAITINGFORMAC, ///< We're waiting for the mac
+ CANCELED, ///< The session has been canceled
+ DONE, ///< The verification is done
+ };
+ Q_ENUM(State)
+
+ enum Error {
+ NONE,
+ TIMEOUT,
+ REMOTE_TIMEOUT,
+ USER,
+ REMOTE_USER,
+ UNEXPECTED_MESSAGE,
+ REMOTE_UNEXPECTED_MESSAGE,
+ UNKNOWN_TRANSACTION,
+ REMOTE_UNKNOWN_TRANSACTION,
+ UNKNOWN_METHOD,
+ REMOTE_UNKNOWN_METHOD,
+ KEY_MISMATCH,
+ REMOTE_KEY_MISMATCH,
+ USER_MISMATCH,
+ REMOTE_USER_MISMATCH,
+ INVALID_MESSAGE,
+ REMOTE_INVALID_MESSAGE,
+ SESSION_ACCEPTED,
+ REMOTE_SESSION_ACCEPTED,
+ MISMATCHED_COMMITMENT,
+ REMOTE_MISMATCHED_COMMITMENT,
+ MISMATCHED_SAS,
+ REMOTE_MISMATCHED_SAS,
+ };
+ Q_ENUM(Error)
+
+ Q_PROPERTY(QString remoteDeviceId MEMBER m_remoteDeviceId CONSTANT)
+ Q_PROPERTY(QVector<EmojiEntry> sasEmojis READ sasEmojis NOTIFY sasEmojisChanged)
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(Error error READ error NOTIFY errorChanged)
+
+ KeyVerificationSession(QString remoteUserId,
+ const KeyVerificationRequestEvent& event,
+ Connection* connection, bool encrypted);
+ KeyVerificationSession(QString userId, QString deviceId,
+ Connection* connection);
+ ~KeyVerificationSession() override;
+ Q_DISABLE_COPY_MOVE(KeyVerificationSession)
+
+ void handleEvent(const KeyVerificationEvent& baseEvent);
+
+ QVector<EmojiEntry> sasEmojis() const;
+ State state() const;
+
+ Error error() const;
+
+ QString remoteDeviceId() const;
+
+public Q_SLOTS:
+ void sendRequest();
+ void sendReady();
+ void sendMac();
+ void sendStartSas();
+ void sendKey();
+ void sendDone();
+ void cancelVerification(Error error);
+
+Q_SIGNALS:
+ void keyReceived();
+ void sasEmojisChanged();
+ void stateChanged();
+ void errorChanged();
+ void finished();
+
+private:
+ const QString m_remoteUserId;
+ const QString m_remoteDeviceId;
+ const QString m_transactionId;
+ Connection* m_connection;
+ OlmSAS* m_sas = nullptr;
+ QVector<EmojiEntry> m_sasEmojis;
+ bool startSentByUs = false;
+ State m_state = INCOMING;
+ Error m_error = NONE;
+ QString m_startEvent;
+ QString m_commitment;
+ bool macReceived = false;
+ bool m_encrypted;
+ QStringList m_remoteSupportedMethods;
+ bool m_verified = false;
+ QString m_pendingEdKeyId{};
+
+ void handleReady(const KeyVerificationReadyEvent& event);
+ void handleStart(const KeyVerificationStartEvent& event);
+ void handleKey(const KeyVerificationKeyEvent& event);
+ void handleMac(const KeyVerificationMacEvent& event);
+ void init(std::chrono::milliseconds timeout);
+ void setState(State state);
+ void setError(Error error);
+ static QString errorToString(Error error);
+ static Error stringToError(const QString& error);
+ void trustKeys();
+
+ QByteArray macInfo(bool verifying, const QString& key = "KEY_IDS"_ls);
+ QString calculateMac(const QString& input, bool verifying, const QString& keyId= "KEY_IDS"_ls);
+};
+
+} // namespace Quotient
+Q_DECLARE_METATYPE(Quotient::EmojiEntry)