// SPDX-FileCopyrightText: 2022 Tobias Fella // SPDX-License-Identifier: LGPL-2.1-or-later #pragma once #include "events/keyverificationevent.h" #include 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 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) QVector 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 startReceived(); 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 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; void handleReady(const KeyVerificationReadyEvent& event); void handleStart(const KeyVerificationStartEvent& event); void handleAccept(const KeyVerificationAcceptEvent& event); void handleKey(const KeyVerificationKeyEvent& event); void handleMac(const KeyVerificationMacEvent& event); void handleDone(const KeyVerificationDoneEvent&); void handleCancel(const KeyVerificationCancelEvent& 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); 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)