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