1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
// 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)
};
/** 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)
QVector<EmojiEntry> sasEmojis() const;
State state() const;
Error error() 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<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;
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)
|