1#pragma once
2
3/// @file
4/// @brief Various event types used in E2EE.
5
6#if __has_include(<nlohmann/json_fwd.hpp>)
7#include <nlohmann/json_fwd.hpp>
8#else
9#include <nlohmann/json.hpp>
10#endif
11
12#include "mtx/events.hpp"
13#include "mtx/events/common.hpp"
14#include "variant"
15
16namespace mtx {
17namespace events {
18namespace msg {
19
20//! Display methods for Short Authentication Strings
21enum class SASMethods
22{
23 Decimal, //!< Display 3 times 4 digits
24 Emoji, //! Display 7 emoji
25 Unsupported
26};
27
28void
29from_json(const nlohmann::json &obj, SASMethods &method);
30
31void
32to_json(nlohmann::json &obj, const SASMethods &method);
33
34//! The different verification methods
35enum class VerificationMethods
36{
37 SASv1, //!< Short Authentication Strings
38 Unsupported //!< Unsupported method
39};
40
41void
42from_json(const nlohmann::json &obj, VerificationMethods &method);
43
44void
45to_json(nlohmann::json &obj, const VerificationMethods &method);
46
47//! Content of an individual message encrypted for a certain key.
48struct OlmCipherContent
49{
50 //! Ciphertext of the message.
51 std::string body;
52 /// @brief Olm message type.
53 ///
54 /// `0` for initial pre-key messages.
55 /// `1` for normal messages after the initial exchange.
56 uint8_t type;
57
58 friend void from_json(const nlohmann::json &obj, OlmCipherContent &event);
59
60 friend void to_json(nlohmann::json &obj, const OlmCipherContent &event);
61};
62
63//! Content of the `m.room.encrypted` Olm event.
64struct OlmEncrypted
65{
66 //! Algorithm used for encrypting this event.
67 std::string algorithm;
68 //! curve25519 key of the sender.
69 std::string sender_key;
70
71 using RecipientKey = std::string;
72 //! Map of recipient curve25519 key to the encrypted message.
73 std::map<RecipientKey, OlmCipherContent> ciphertext;
74
75 friend void from_json(const nlohmann::json &obj, OlmEncrypted &event);
76
77 friend void to_json(nlohmann::json &obj, const OlmEncrypted &event);
78};
79
80//! Content of the `m.room.encrypted` event.
81struct Encrypted
82{
83 //! Used for one-on-one exchanges.
84 std::string algorithm;
85 //! The actual encrypted payload.
86 std::string ciphertext;
87 //! Sender's device id.
88 std::string device_id;
89 //! The curve25519 device key.
90 std::string sender_key;
91 //! Outbound group session id.
92 std::string session_id;
93 //! Relations like rich replies
94 common::Relations relations;
95
96 friend void from_json(const nlohmann::json &obj, Encrypted &event);
97
98 friend void to_json(nlohmann::json &obj, const Encrypted &event);
99};
100
101//! Content of the `m.dummy` event.
102struct Dummy
103{
104 friend void from_json(const nlohmann::json &obj, Dummy &event);
105 friend void to_json(nlohmann::json &obj, const Dummy &event);
106};
107
108//! Content of the `m.room_key` event.
109struct RoomKey
110{
111 /// @brief *Required.* The encryption algorithm the key in this event is to be used with.
112 ///
113 /// Must be 'm.megolm.v1.aes-sha2'.
114 std::string algorithm;
115 std::string room_id; //!< *Required.* The room where the key is used.
116 std::string session_id; //!< *Required.* The ID of the session that the key is for.
117 std::string session_key; //!< *Required.* The key to be exchanged.
118
119 friend void from_json(const nlohmann::json &obj, RoomKey &event);
120 friend void to_json(nlohmann::json &obj, const RoomKey &event);
121};
122
123//! Content of the `m.forwarded_room_key` event.
124struct ForwardedRoomKey
125{
126 /// @brief *Required.* The encryption algorithm the key in this event is to be used with.
127 std::string algorithm;
128 std::string room_id; //!< *Required.* The room where the key is used.
129 std::string session_id; //!< *Required.* The ID of the session that the key is for.
130 std::string session_key; //!< *Required.* The key to be exchanged.
131
132 //! *Required.* The Curve25519 key of the device which initiated the session originally.
133 std::string sender_key;
134 /// @brief *Required.* The Ed25519 key of the device which initiated the session originally.
135 ///
136 /// It is 'claimed' because the receiving device has no way to tell that the original
137 /// room_key actually came from a device which owns the private part of this key unless they
138 /// have done device verification.
139 std::string sender_claimed_ed25519_key;
140 /// @brief *Required.* Chain of Curve25519 keys.
141 ///
142 /// It starts out empty, but each time the key is forwarded to another device, the previous
143 /// sender in the chain is added to the end of the list. For example, if the key is
144 /// forwarded from A to B to C, this field is empty between A and B, and contains A's
145 /// Curve25519 key between B and C.
146 std::vector<std::string> forwarding_curve25519_key_chain;
147
148 friend void from_json(const nlohmann::json &obj, ForwardedRoomKey &event);
149 friend void to_json(nlohmann::json &obj, const ForwardedRoomKey &event);
150};
151
152//! The type of key request.
153enum class RequestAction
154{
155 Request, //!< request
156 Cancellation, //!< request_cancellation
157 Unknown, //!< Unknown request action
158};
159
160void
161from_json(const nlohmann::json &obj, RequestAction &action);
162
163void
164to_json(nlohmann::json &obj, const RequestAction &action);
165
166//! A request to share a session key.
167struct KeyRequest
168{
169 //! The type of request.
170 RequestAction action;
171
172 /// @brief The encryption algorithm of the session we want keys for.
173 ///
174 /// Always m.megolm.v1.aes-sha2.
175 std::string algorithm;
176 //! The room in which the session was created.
177 std::string room_id;
178 //! The curve25519 key of the session creator.
179 std::string sender_key;
180 //! The session_id of the outbound megolm session.
181 std::string session_id;
182
183 //! A unique identifier for this request.
184 std::string request_id;
185 //! The device requesting the keys.
186 std::string requesting_device_id;
187
188 friend void from_json(const nlohmann::json &obj, KeyRequest &event);
189 friend void to_json(nlohmann::json &obj, const KeyRequest &event);
190};
191
192//! Content of the `m.key.verification.request` event
193struct KeyVerificationRequest
194{
195 std::optional<std::string> body;
196 //! The device ID which is initiating the request.
197 std::string from_device;
198 //! The device ID to which the key verification request is meant,used only for to-device
199 //! verification
200 std::optional<std::string> to;
201 //! An opaque identifier for the verification request. Must be unique with respect to the
202 //! devices involved.
203 std::optional<std::string> transaction_id;
204 //! must be `key.verification.request`, this field will be needed only in room verification
205 std::optional<std::string> msgtype;
206 //! The verification methods supported by the sender.
207 std::vector<VerificationMethods> methods;
208 //! The POSIX timestamp in milliseconds for when the request was made. If the request is in
209 //! the future by more than 5 minutes or more than 10 minutes in the past, the message
210 //! should be ignored by the receiver.
211 std::optional<uint64_t> timestamp;
212
213 friend void from_json(const nlohmann::json &obj, KeyVerificationRequest &event);
214 friend void to_json(nlohmann::json &obj, const KeyVerificationRequest &event);
215};
216
217//! Content of the `m.key.verification.start` event
218struct KeyVerificationStart
219{
220 //! The device ID which is initiating the process.
221 std::string from_device;
222 /// @brief An opaque identifier for the verification process.
223 ///
224 /// Must be unique with respect to the devices involved. Must be the same as the
225 /// transaction_id given in the `m.key.verification.request` if this process is originating
226 /// from a request.
227 /// @note Used in verification via to_device messaging
228 std::optional<std::string> transaction_id;
229 //! The verification method to use. Must be 'm.sas.v1'
230 VerificationMethods method = VerificationMethods::SASv1;
231 /// @brief Optional method to use to verify the other user's key with.
232 //
233 // Applicable when the method chosen only verifies one user's key. This field will never be
234 // present if the method verifies keys both ways.
235 /// @note This appears to be unused in SAS verification
236 std::optional<std::string> next_method;
237 /// @brief The key agreement protocols the sending device understands.
238 ///
239 /// Must include at least curve25519.
240 std::vector<std::string> key_agreement_protocols;
241 //! The hash methods the sending device understands. Must include at least sha256.
242 std::vector<std::string> hashes;
243 /// @brief The message authentication codes that the sending device understands.
244 ///
245 /// Must include at least hkdf-hmac-sha256.
246 std::vector<std::string> message_authentication_codes;
247 /// @brief The SAS methods the sending device (and the sending device's user) understands.
248 ///
249 /// Must include at least decimal. Optionally can include emoji.
250 ///
251 /// One of:
252 /// - `decimal`
253 /// - `emoji`
254 std::vector<SASMethods> short_authentication_string;
255 /// @brief This is used for relating this message with previously sent
256 /// `key.verification.request`
257 ///
258 /// @note Will be used only for room-verification msgs where this is used in place of
259 /// transaction_id.
260 common::Relations relations;
261
262 friend void from_json(const nlohmann::json &obj, KeyVerificationStart &event);
263 friend void to_json(nlohmann::json &obj, const KeyVerificationStart &event);
264};
265
266//! Implements the `m.key.verification.ready` event
267struct KeyVerificationReady
268{
269 //! the deviceId of the device which send the `m.key.verification.request`
270 std::string from_device;
271 //! transactionId of the current flow
272 std::optional<std::string> transaction_id;
273 //! Sends the user the supported methods
274 std::vector<VerificationMethods> methods;
275 //! this is used for relating this message with previously sent
276 //! key.verification.request will be used only for room-verification msgs where this
277 //! is used in place of txnid
278 common::Relations relations;
279
280 friend void from_json(const nlohmann::json &obj, KeyVerificationReady &event);
281 friend void to_json(nlohmann::json &obj, const KeyVerificationReady &event);
282};
283
284// ! Implements the `m.key.verification.done` event
285struct KeyVerificationDone
286{
287 //! transactionId of the current flow
288 std::optional<std::string> transaction_id;
289 //! this is used for relating this message with previously sent key.verification.request
290 //! will be used only for room-verification msgs where this is used in place of txnid
291 common::Relations relations;
292
293 friend void from_json(const nlohmann::json &obj, KeyVerificationDone &event);
294 friend void to_json(nlohmann::json &obj, const KeyVerificationDone &event);
295};
296
297//! Implements the `m.key.verification.accept` event
298struct KeyVerificationAccept
299{
300 //! when the method chosen only verifies one user's key. This field will never be present
301 //! if the method verifies keys both ways.
302 std::optional<std::string> transaction_id;
303 //! The verification method to use. Must be 'm.sas.v1'
304 VerificationMethods method = VerificationMethods::SASv1;
305 //! The key agreement protocol the device is choosing to use, out of the options in the
306 //! m.key.verification.start message.
307 std::string key_agreement_protocol;
308 //! The hash method the device is choosing to use, out of the options in the
309 //! m.key.verification.start message.
310 std::string hash;
311 //! The message authentication code the device is choosing to use, out of the options in
312 //! the m.key.verification.start message.
313 std::string message_authentication_code;
314 //! The SAS methods both devices involed in the verification process understand. Must be
315 //! a subset of the options in the m.key.verification.start message.
316 //! One of: ["decimal", "emoji"]
317 std::vector<SASMethods> short_authentication_string;
318 //! The hash (encoded as unpadded base64) of the concatenation of the device's ephemeral
319 //! public key (encoded as unpadded base64) and the canonical JSON representation of the
320 //! m.key.verification.start message.
321 std::string commitment;
322 //! this is used for relating this message with previously sent key.verification.request
323 //! will be used only for room-verification msgs where this is used in place of txnid
324 common::Relations relations;
325
326 friend void from_json(const nlohmann::json &obj, KeyVerificationAccept &event);
327 friend void to_json(nlohmann::json &obj, const KeyVerificationAccept &event);
328};
329
330//! implementation of the `m.key.verification.cancel` event
331struct KeyVerificationCancel
332{
333 //! The opaque identifier for the verification process/request.
334 std::optional<std::string> transaction_id;
335 //! A human readable description of the code. The client should only rely on this string
336 //! if it does not understand the code.
337 std::string reason;
338 //! The error code for why the process/request was cancelled by the user. Error codes
339 //! should use the Java package naming convention if not in the following list:
340 //! m.user: The user cancelled the verification.
341 //! m.timeout: The verification process timed out. Verification processes can define
342 //! their own timeout parameters.
343 //! m.unknown_transaction: The device does not know about the given transaction ID.
344 //! m.unknown_method: The device does not know how to handle the requested method.
345 //! This should be sent for m.key.verification.start messages and messages
346 //! defined by individual verification processes.
347 //! m.unexpected_message: The device received an unexpected message. Typically raised
348 //! when one of the parties is handling the verification out of order.
349 //! m.key_mismatch: The key was not verified.
350 //! m.user_mismatch: The expected user did not match the user verified.
351 //! m.invalid_message: The message received was invalid.
352 //! m.accepted: A m.key.verification.request was accepted by a different device.
353 //! The device receiving this error can ignore the verification request.
354 //! m.unknown_method: The devices are unable to agree on the key agreement,
355 //! hash, MAC, or SAS method.
356 //! m.mismatched_commitment: The hash commitment did not match.
357 //! m.mismatched_sas: The SAS did not match.
358 //! Clients should be careful to avoid error loops. For example, if a device sends an
359 //! incorrect message and the client returns m.invalid_message to which it gets an
360 //! unexpected response with m.unexpected_message, the client should not respond
361 //! again with m.unexpected_message to avoid the other device potentially sending
362 //! another error response.
363 std::string code;
364 //! this is used for relating this message with previously sent key.verification.request
365 //! will be used only for room-verification msgs where this is used in place of txnid
366 common::Relations relations;
367
368 friend void from_json(const nlohmann::json &obj, KeyVerificationCancel &event);
369 friend void to_json(nlohmann::json &obj, const KeyVerificationCancel &event);
370};
371
372struct KeyVerificationKey
373{
374 //! An opaque identifier for the verification process. Must be the same as the one
375 //! used for the m.key.verification.start message.
376 std::optional<std::string> transaction_id;
377 //! The device's ephemeral public key, encoded as unpadded base64.
378 std::string key;
379 //! this is used for relating this message with previously sent key.verification.request
380 //! will be used only for room-verification msgs where this is used in place of txnid
381 common::Relations relations;
382
383 friend void from_json(const nlohmann::json &obj, KeyVerificationKey &event);
384 friend void to_json(nlohmann::json &obj, const KeyVerificationKey &event);
385};
386
387struct KeyVerificationMac
388{
389 //! An opaque identifier for the verification process. Must be the same as the one
390 //! used for the m.key.verification.start message.
391 std::optional<std::string> transaction_id;
392 //! A map of the key ID to the MAC of the key, using the algorithm in the
393 //! verification process. The MAC is encoded as unpadded base64.
394 std::map<std::string, std::string> mac;
395 //! The MAC of the comma-separated, sorted, list of key IDs given in the mac
396 //! property, encoded as unpadded base64.
397 std::string keys;
398 //! this is used for relating this message with previously sent key.verification.request
399 //! will be used only for room-verification msgs where this is used in place of txnid
400 common::Relations relations;
401
402 friend void from_json(const nlohmann::json &obj, KeyVerificationMac &event);
403 friend void to_json(nlohmann::json &obj, const KeyVerificationMac &event);
404};
405
406struct SecretRequest
407{
408 //! The type of request.
409 RequestAction action;
410
411 //! Required if action is request. The name of the secret that is being requested.
412 std::string name;
413
414 //! A unique identifier for this request.
415 std::string request_id;
416 //! The device requesting the keys.
417 std::string requesting_device_id;
418
419 friend void from_json(const nlohmann::json &obj, SecretRequest &event);
420 friend void to_json(nlohmann::json &obj, const SecretRequest &event);
421};
422
423struct SecretSend
424{
425 //! Required. The contents of the secret.
426 std::string secret;
427
428 //! A unique identifier for this request.
429 std::string request_id;
430
431 friend void from_json(const nlohmann::json &obj, SecretSend &event);
432 friend void to_json(nlohmann::json &obj, const SecretSend &event);
433};
434
435} // namespace msg
436} // namespace events
437} // namespace mtx
438