libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
keyverificationsession.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include "events/keyverificationevent.h"
7#include "events/roommessageevent.h"
8
9#include <QtCore/QObject>
10#include <QtCore/QPointer>
11#include <QtQmlIntegration/qqmlintegration.h>
12
13struct OlmSAS;
14
15namespace Quotient {
16class Connection;
17class Room;
18
22
26
27public:
28 friend bool operator==(const EmojiEntry&, const EmojiEntry&) = default;
29};
30
31/** A key verification session. Listen for incoming sessions by connecting to Connection::newKeyVerificationSession.
32 Start a new session using Connection::startKeyVerificationSession.
33 The object is delete after finished is emitted.
34*/
36{
37 Q_OBJECT
38 QML_ELEMENT
39 QML_UNCREATABLE("")
40
41public:
42 enum State {
43 INCOMING, ///< There is a request for verification incoming
44 //! We sent a request for verification and are waiting for ready
45 WAITINGFORREADY,
46 //! Either party sent a ready as a response to a request; the user
47 //! selects a method
48 READY,
49 WAITINGFORACCEPT, ///< We sent a start and are waiting for an accept
50 ACCEPTED, ///< The other party sent an accept and is waiting for a key
51 WAITINGFORKEY, ///< We're waiting for a key
52 //! We're waiting for the *user* to verify the emojis
53 WAITINGFORVERIFICATION,
54 WAITINGFORMAC, ///< We're waiting for the mac
55 CANCELED, ///< The session has been canceled
56 DONE, ///< The verification is done
57 };
58 Q_ENUM(State)
59
60 enum Error {
61 NONE,
62 TIMEOUT,
63 REMOTE_TIMEOUT,
64 USER,
65 REMOTE_USER,
66 UNEXPECTED_MESSAGE,
67 REMOTE_UNEXPECTED_MESSAGE,
68 UNKNOWN_TRANSACTION,
69 REMOTE_UNKNOWN_TRANSACTION,
70 UNKNOWN_METHOD,
71 REMOTE_UNKNOWN_METHOD,
72 KEY_MISMATCH,
73 REMOTE_KEY_MISMATCH,
74 USER_MISMATCH,
75 REMOTE_USER_MISMATCH,
76 INVALID_MESSAGE,
77 REMOTE_INVALID_MESSAGE,
78 SESSION_ACCEPTED,
79 REMOTE_SESSION_ACCEPTED,
80 MISMATCHED_COMMITMENT,
81 REMOTE_MISMATCHED_COMMITMENT,
82 MISMATCHED_SAS,
83 REMOTE_MISMATCHED_SAS,
84 };
85 Q_ENUM(Error)
86
87 Q_PROPERTY(QString remoteDeviceId MEMBER m_remoteDeviceId CONSTANT)
88 Q_PROPERTY(QString remoteUserId MEMBER m_remoteUserId CONSTANT)
89 Q_PROPERTY(QVector<EmojiEntry> sasEmojis READ sasEmojis NOTIFY sasEmojisChanged)
90 Q_PROPERTY(State state READ state NOTIFY stateChanged)
91 Q_PROPERTY(Error error READ error NOTIFY errorChanged)
92 // Whether this is a user verification (in contrast to a device verification)
93 Q_PROPERTY(bool userVerification READ userVerification CONSTANT)
94
95 // Incoming device verification
96 KeyVerificationSession(QString remoteUserId,
97 const KeyVerificationRequestEvent& event,
98 Connection* connection, bool encrypted);
99
100 // Outgoing device verification
101 KeyVerificationSession(QString userId, QString deviceId,
102 Connection* connection);
103
104 // Incoming user verification
105 KeyVerificationSession(const RoomMessageEvent *event, Room *room);
106
107 // Outgoing user verification
108 explicit KeyVerificationSession(Room *room);
109
110 void handleEvent(const KeyVerificationEvent& baseEvent);
111
112 QVector<EmojiEntry> sasEmojis() const;
113 State state() const;
114
115 Error error() const;
116
117 QString remoteDeviceId() const;
118 QString transactionId() const;
119 bool userVerification() const;
120
121 void setRequestEventId(const QString &eventId);
122
123public Q_SLOTS:
124 void sendRequest();
125 void sendReady();
126 void sendMac();
127 void sendStartSas();
128 void sendKey();
129 void sendDone();
130 void cancelVerification(Error error);
131
132Q_SIGNALS:
133 void keyReceived();
134 void sasEmojisChanged();
135 void stateChanged();
136 void errorChanged();
137 void finished();
138
139private:
140 // Internal delegating constructors
141
142 KeyVerificationSession(QString remoteUserId, Connection* connection, QString remoteDeviceId,
143 bool encrypted, QStringList methods, QDateTime startTimestamp,
144 QString transactionId, Room* room = nullptr, QString requestEventId = {});
145 KeyVerificationSession(QString remoteUserId, Connection* connection, Room* room,
146 QString remoteDeviceId = {}, QString transactionId = {});
147
148 Connection* const m_connection;
149 QPointer<Room> m_room;
150 const QString m_remoteUserId;
151 QString m_remoteDeviceId;
152 QString m_transactionId;
153 bool m_encrypted = false;
154 QStringList m_remoteSupportedMethods{};
155 QStringList m_commonMacCodes{};
156
157 CStructPtr<OlmSAS> olmDataHolder = makeOlmData();
158 OlmSAS* olmData = olmDataHolder.get();
159 QVector<EmojiEntry> m_sasEmojis;
160 bool startSentByUs = false;
161 State m_state = INCOMING;
162 Error m_error = NONE;
163 QString m_startEvent{};
164 QByteArray m_commitment{};
165 bool macReceived = false;
166 bool m_verified = false;
167 QString m_pendingEdKeyId{};
168 QString m_pendingMasterKey{};
169 QString m_requestEventId{};
170
171 static CStructPtr<OlmSAS> makeOlmData();
172 void handleReady(const KeyVerificationReadyEvent& event);
173 void handleStart(const KeyVerificationStartEvent& event);
174 void handleKey(const KeyVerificationKeyEvent& event);
175 void handleMac(const KeyVerificationMacEvent& event);
176 void handleCancel(Error error);
177 void setupTimeout(std::chrono::milliseconds timeout);
178 void setState(State state);
179 void setError(Error error);
180 static QString errorToString(Error error);
181 static Error stringToError(const QString& error);
182 void trustKeys();
183 void sendEvent(const QString &userId, const QString &deviceId, const KeyVerificationEvent &event, bool encrypted);
184
185 QByteArray macInfo(bool verifying, const QString& key = "KEY_IDS"_L1);
186 QString calculateMac(const QString& input, bool verifying, const QString& keyId= "KEY_IDS"_L1);
187};
188
189} // namespace Quotient
#define QUOTIENT_API