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 | 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. |
64 | struct 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. |
81 | struct 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. |
102 | struct 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. |
109 | struct 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. |
124 | struct 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. |
153 | enum class RequestAction |
154 | { |
155 | Request, //!< request |
156 | Cancellation, //!< request_cancellation |
157 | Unknown, //!< Unknown request action |
158 | }; |
159 | |
160 | void |
161 | from_json(const nlohmann::json &obj, RequestAction &action); |
162 | |
163 | void |
164 | to_json(nlohmann::json &obj, const RequestAction &action); |
165 | |
166 | //! A request to share a session key. |
167 | struct 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 |
193 | struct 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 |
218 | struct 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 |
267 | struct 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 |
285 | struct 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 |
298 | struct 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 |
331 | struct 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 | |
372 | struct 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 | |
387 | struct 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 | |
406 | struct 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 | |
423 | struct 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 | |