1 | #include <cstdint> |
2 | #include <string> |
3 | |
4 | #include <nlohmann/json.hpp> |
5 | |
6 | #include "mtx/events/encrypted.hpp" |
7 | |
8 | static constexpr auto OLM_ALGO = "m.olm.v1.curve25519-aes-sha2" ; |
9 | |
10 | namespace mtx { |
11 | namespace events { |
12 | namespace msg { |
13 | |
14 | void |
15 | to_json(nlohmann::json &obj, const SASMethods &method) |
16 | { |
17 | switch (method) { |
18 | case SASMethods::Decimal: |
19 | obj = "decimal" ; |
20 | break; |
21 | case SASMethods::Emoji: |
22 | obj = "emoji" ; |
23 | break; |
24 | case SASMethods::Unsupported: |
25 | default: |
26 | obj = "unsupported" ; |
27 | break; |
28 | } |
29 | } |
30 | |
31 | void |
32 | from_json(const nlohmann::json &obj, SASMethods &method) |
33 | { |
34 | if (obj.get<std::string>() == "decimal" ) |
35 | method = SASMethods::Decimal; |
36 | else if (obj.get<std::string>() == "emoji" ) |
37 | method = SASMethods::Emoji; |
38 | else |
39 | method = SASMethods::Unsupported; |
40 | } |
41 | |
42 | void |
43 | to_json(nlohmann::json &obj, const VerificationMethods &method) |
44 | { |
45 | switch (method) { |
46 | case VerificationMethods::SASv1: |
47 | obj = "m.sas.v1" ; |
48 | break; |
49 | case VerificationMethods::Unsupported: |
50 | default: |
51 | obj = "unsupported" ; |
52 | break; |
53 | } |
54 | } |
55 | |
56 | void |
57 | from_json(const nlohmann::json &obj, VerificationMethods &method) |
58 | { |
59 | if (obj.get<std::string>() == "m.sas.v1" ) |
60 | method = VerificationMethods::SASv1; |
61 | else |
62 | method = VerificationMethods::Unsupported; |
63 | } |
64 | |
65 | void |
66 | from_json(const nlohmann::json &obj, OlmCipherContent &msg) |
67 | { |
68 | msg.body = obj.at(key: "body" ).get<std::string>(); |
69 | msg.type = obj.at(key: "type" ).get<uint8_t>(); |
70 | } |
71 | |
72 | void |
73 | to_json(nlohmann::json &obj, const OlmCipherContent &msg) |
74 | { |
75 | obj["body" ] = msg.body; |
76 | obj["type" ] = msg.type; |
77 | } |
78 | |
79 | void |
80 | from_json(const nlohmann::json &obj, OlmEncrypted &msg) |
81 | { |
82 | msg.algorithm = OLM_ALGO; |
83 | msg.sender_key = obj.at(key: "sender_key" ).get<std::string>(); |
84 | msg.ciphertext = |
85 | obj.at(key: "ciphertext" ).get<std::map<OlmEncrypted::RecipientKey, OlmCipherContent>>(); |
86 | } |
87 | |
88 | void |
89 | to_json(nlohmann::json &obj, const OlmEncrypted &msg) |
90 | { |
91 | obj["algorithm" ] = msg.algorithm; |
92 | obj["sender_key" ] = msg.sender_key; |
93 | obj["ciphertext" ] = msg.ciphertext; |
94 | } |
95 | |
96 | void |
97 | from_json(const nlohmann::json &obj, Encrypted &content) |
98 | { |
99 | content.algorithm = obj.at(key: "algorithm" ).get<std::string>(); |
100 | content.ciphertext = obj.at(key: "ciphertext" ).get<std::string>(); |
101 | content.session_id = obj.at(key: "session_id" ).get<std::string>(); |
102 | |
103 | // MSC3700 |
104 | content.device_id = obj.value(key: "device_id" , default_value: "" ); |
105 | content.sender_key = obj.value(key: "sender_key" , default_value: "" ); |
106 | |
107 | content.relations = common::parse_relations(obj); |
108 | } |
109 | |
110 | void |
111 | to_json(nlohmann::json &obj, const Encrypted &content) |
112 | { |
113 | obj["algorithm" ] = content.algorithm; |
114 | obj["ciphertext" ] = content.ciphertext; |
115 | |
116 | // MSC3700 |
117 | if (!content.device_id.empty()) |
118 | obj["device_id" ] = content.device_id; |
119 | if (!content.sender_key.empty()) |
120 | obj["sender_key" ] = content.sender_key; |
121 | |
122 | obj["session_id" ] = content.session_id; |
123 | |
124 | // For encrypted events, only add releations, don't generate new_content and friends |
125 | common::add_relations(obj, relations: content.relations); |
126 | } |
127 | |
128 | void |
129 | from_json(const nlohmann::json &, Dummy &) |
130 | { |
131 | } |
132 | |
133 | void |
134 | to_json(nlohmann::json &obj, const Dummy &) |
135 | { |
136 | obj = nlohmann::json::object(); |
137 | } |
138 | |
139 | void |
140 | from_json(const nlohmann::json &obj, RoomKey &event) |
141 | { |
142 | event.algorithm = obj.at(key: "algorithm" ).get<std::string>(); |
143 | event.room_id = obj.at(key: "room_id" ).get<std::string>(); |
144 | event.session_id = obj.at(key: "session_id" ).get<std::string>(); |
145 | event.session_key = obj.at(key: "session_key" ).get<std::string>(); |
146 | } |
147 | |
148 | void |
149 | to_json(nlohmann::json &obj, const RoomKey &event) |
150 | { |
151 | obj["algorithm" ] = event.algorithm; |
152 | obj["room_id" ] = event.room_id; |
153 | obj["session_id" ] = event.session_id; |
154 | obj["session_key" ] = event.session_key; |
155 | } |
156 | |
157 | void |
158 | from_json(const nlohmann::json &obj, ForwardedRoomKey &event) |
159 | { |
160 | event.algorithm = obj.at(key: "algorithm" ).get<std::string>(); |
161 | event.room_id = obj.at(key: "room_id" ).get<std::string>(); |
162 | event.session_id = obj.at(key: "session_id" ).get<std::string>(); |
163 | event.session_key = obj.at(key: "session_key" ).get<std::string>(); |
164 | event.sender_key = obj.at(key: "sender_key" ).get<std::string>(); |
165 | event.sender_claimed_ed25519_key = obj.at(key: "sender_claimed_ed25519_key" ).get<std::string>(); |
166 | event.forwarding_curve25519_key_chain = |
167 | obj.at(key: "forwarding_curve25519_key_chain" ).get<std::vector<std::string>>(); |
168 | } |
169 | |
170 | void |
171 | to_json(nlohmann::json &obj, const ForwardedRoomKey &event) |
172 | { |
173 | obj["algorithm" ] = event.algorithm; |
174 | obj["room_id" ] = event.room_id; |
175 | obj["session_id" ] = event.session_id; |
176 | obj["session_key" ] = event.session_key; |
177 | obj["sender_key" ] = event.sender_key; |
178 | obj["sender_claimed_ed25519_key" ] = event.sender_claimed_ed25519_key; |
179 | obj["forwarding_curve25519_key_chain" ] = event.forwarding_curve25519_key_chain; |
180 | } |
181 | |
182 | void |
183 | from_json(const nlohmann::json &obj, KeyRequest &event) |
184 | { |
185 | event.request_id = obj.at(key: "request_id" ).get<std::string>(); |
186 | event.requesting_device_id = obj.at(key: "requesting_device_id" ).get<std::string>(); |
187 | |
188 | auto action = obj.at(key: "action" ).get<std::string>(); |
189 | if (action == "request" ) { |
190 | event.action = RequestAction::Request; |
191 | event.room_id = obj.at(key: "body" ).at(key: "room_id" ).get<std::string>(); |
192 | event.sender_key = obj.at(key: "body" ).value(key: "sender_key" , default_value: "" ); |
193 | event.session_id = obj.at(key: "body" ).at(key: "session_id" ).get<std::string>(); |
194 | event.algorithm = obj.at(key: "body" ).at(key: "algorithm" ).get<std::string>(); |
195 | } else if (action == "request_cancellation" ) { |
196 | event.action = RequestAction::Cancellation; |
197 | } |
198 | } |
199 | |
200 | void |
201 | to_json(nlohmann::json &obj, const KeyRequest &event) |
202 | { |
203 | obj = nlohmann::json::object(); |
204 | |
205 | obj = nlohmann::json::object(); |
206 | |
207 | obj["request_id" ] = event.request_id; |
208 | obj["requesting_device_id" ] = event.requesting_device_id; |
209 | |
210 | switch (event.action) { |
211 | case RequestAction::Request: { |
212 | obj["body" ] = nlohmann::json::object(); |
213 | |
214 | obj["body" ]["room_id" ] = event.room_id; |
215 | |
216 | // MSC3070 |
217 | if (!event.sender_key.empty()) |
218 | obj["body" ]["sender_key" ] = event.sender_key; |
219 | |
220 | obj["body" ]["session_id" ] = event.session_id; |
221 | obj["body" ]["algorithm" ] = "m.megolm.v1.aes-sha2" ; |
222 | |
223 | obj["action" ] = "request" ; |
224 | break; |
225 | } |
226 | case RequestAction::Cancellation: { |
227 | obj["action" ] = "request_cancellation" ; |
228 | break; |
229 | } |
230 | default: |
231 | break; |
232 | } |
233 | } |
234 | |
235 | void |
236 | from_json(const nlohmann::json &obj, KeyVerificationRequest &event) |
237 | { |
238 | if (obj.count(key: "body" ) != 0) { |
239 | event.body = obj.at(key: "body" ).get<std::string>(); |
240 | } |
241 | event.from_device = obj.at(key: "from_device" ).get<std::string>(); |
242 | event.methods = obj.at(key: "methods" ).get<std::vector<VerificationMethods>>(); |
243 | if (obj.count(key: "timestamp" ) != 0) { |
244 | event.timestamp = obj.at(key: "timestamp" ).get<uint64_t>(); |
245 | } |
246 | if (obj.count(key: "msgtype" ) != 0) { |
247 | event.msgtype = obj.at(key: "msgtype" ).get<std::string>(); |
248 | } |
249 | if (obj.count(key: "to" ) != 0) { |
250 | event.to = obj.at(key: "to" ).get<std::string>(); |
251 | } |
252 | if (obj.count(key: "transaction_id" ) != 0) { |
253 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
254 | } |
255 | } |
256 | |
257 | void |
258 | to_json(nlohmann::json &obj, const KeyVerificationRequest &event) |
259 | { |
260 | if (event.body.has_value()) |
261 | obj["body" ] = event.body.value(); |
262 | obj["from_device" ] = event.from_device; |
263 | obj["methods" ] = event.methods; |
264 | if (event.msgtype.has_value()) |
265 | obj["msgtype" ] = "m.key.verification.request" ; |
266 | if (event.timestamp.has_value()) |
267 | obj["timestamp" ] = event.timestamp.value(); |
268 | if (event.to.has_value()) |
269 | obj["to" ] = event.to.value(); |
270 | if (event.transaction_id.has_value()) |
271 | obj["transaction_id" ] = event.transaction_id.value(); |
272 | } |
273 | |
274 | void |
275 | from_json(const nlohmann::json &obj, KeyVerificationStart &event) |
276 | { |
277 | event.from_device = obj.at(key: "from_device" ).get<std::string>(); |
278 | if (obj.count(key: "transaction_id" ) != 0) { |
279 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
280 | } |
281 | event.method = obj.at(key: "method" ).get<VerificationMethods>(); |
282 | if (obj.count(key: "next_method" ) != 0) { |
283 | event.next_method = obj.at(key: "next_method" ).get<std::string>(); |
284 | } |
285 | event.key_agreement_protocols = |
286 | obj.at(key: "key_agreement_protocols" ).get<std::vector<std::string>>(); |
287 | event.hashes = obj.at(key: "hashes" ).get<std::vector<std::string>>(); |
288 | event.message_authentication_codes = |
289 | obj.at(key: "message_authentication_codes" ).get<std::vector<std::string>>(); |
290 | event.short_authentication_string = |
291 | obj.at(key: "short_authentication_string" ).get<std::vector<SASMethods>>(); |
292 | event.relations = common::parse_relations(obj); |
293 | } |
294 | |
295 | void |
296 | to_json(nlohmann::json &obj, const KeyVerificationStart &event) |
297 | { |
298 | obj["from_device" ] = event.from_device; |
299 | obj["method" ] = event.method; |
300 | if (event.transaction_id.has_value()) |
301 | obj["transaction_id" ] = event.transaction_id.value(); |
302 | if (event.next_method.has_value()) |
303 | obj["next_method" ] = event.next_method.value(); |
304 | obj["key_agreement_protocols" ] = event.key_agreement_protocols; |
305 | obj["hashes" ] = event.hashes; |
306 | obj["message_authentication_codes" ] = event.message_authentication_codes; |
307 | obj["short_authentication_string" ] = event.short_authentication_string; |
308 | common::apply_relations(obj, relations: event.relations); |
309 | } |
310 | |
311 | void |
312 | from_json(const nlohmann::json &obj, KeyVerificationReady &event) |
313 | { |
314 | if (obj.count(key: "transaction_id" ) != 0) { |
315 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
316 | } |
317 | event.methods = obj.at(key: "methods" ).get<std::vector<VerificationMethods>>(); |
318 | event.from_device = obj.at(key: "from_device" ).get<std::string>(); |
319 | event.relations = common::parse_relations(obj); |
320 | } |
321 | |
322 | void |
323 | to_json(nlohmann::json &obj, const KeyVerificationReady &event) |
324 | { |
325 | obj["methods" ] = event.methods; |
326 | if (event.transaction_id.has_value()) |
327 | obj["transaction_id" ] = event.transaction_id.value(); |
328 | obj["from_device" ] = event.from_device; |
329 | common::apply_relations(obj, relations: event.relations); |
330 | } |
331 | |
332 | void |
333 | from_json(const nlohmann::json &obj, KeyVerificationDone &event) |
334 | { |
335 | if (obj.count(key: "transaction_id" ) != 0) { |
336 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
337 | } |
338 | event.relations = common::parse_relations(obj); |
339 | } |
340 | |
341 | void |
342 | to_json(nlohmann::json &obj, const KeyVerificationDone &event) |
343 | { |
344 | if (event.transaction_id.has_value()) |
345 | obj["transaction_id" ] = event.transaction_id.value(); |
346 | common::apply_relations(obj, relations: event.relations); |
347 | } |
348 | |
349 | void |
350 | from_json(const nlohmann::json &obj, KeyVerificationAccept &event) |
351 | { |
352 | if (obj.count(key: "transaction_id" ) != 0) { |
353 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
354 | } |
355 | event.key_agreement_protocol = obj.at(key: "key_agreement_protocol" ).get<std::string>(); |
356 | event.hash = obj.at(key: "hash" ).get<std::string>(); |
357 | event.message_authentication_code = obj.at(key: "message_authentication_code" ).get<std::string>(); |
358 | event.short_authentication_string = |
359 | obj.at(key: "short_authentication_string" ).get<std::vector<SASMethods>>(); |
360 | event.commitment = obj.at(key: "commitment" ).get<std::string>(); |
361 | event.method = obj.value(key: "method" , default_value: VerificationMethods::SASv1); |
362 | event.relations = common::parse_relations(obj); |
363 | } |
364 | |
365 | void |
366 | to_json(nlohmann::json &obj, const KeyVerificationAccept &event) |
367 | { |
368 | if (event.transaction_id.has_value()) |
369 | obj["transaction_id" ] = event.transaction_id.value(); |
370 | obj["key_agreement_protocol" ] = event.key_agreement_protocol; |
371 | obj["hash" ] = event.hash; |
372 | obj["message_authentication_code" ] = event.message_authentication_code; |
373 | obj["short_authentication_string" ] = event.short_authentication_string; |
374 | obj["commitment" ] = event.commitment; |
375 | obj["method" ] = event.method; |
376 | common::apply_relations(obj, relations: event.relations); |
377 | } |
378 | |
379 | void |
380 | from_json(const nlohmann::json &obj, KeyVerificationCancel &event) |
381 | { |
382 | if (obj.count(key: "transaction_id" ) != 0) { |
383 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
384 | } |
385 | event.reason = obj.value(key: "reason" , default_value: "" ); |
386 | event.code = obj.value(key: "code" , default_value: "" ); |
387 | event.relations = common::parse_relations(obj); |
388 | } |
389 | |
390 | void |
391 | to_json(nlohmann::json &obj, const KeyVerificationCancel &event) |
392 | { |
393 | if (event.transaction_id.has_value()) |
394 | obj["transaction_id" ] = event.transaction_id.value(); |
395 | obj["reason" ] = event.reason; |
396 | obj["code" ] = event.code; |
397 | common::apply_relations(obj, relations: event.relations); |
398 | } |
399 | |
400 | void |
401 | from_json(const nlohmann::json &obj, KeyVerificationKey &event) |
402 | { |
403 | if (obj.count(key: "transaction_id" ) != 0) { |
404 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
405 | } |
406 | event.key = obj.at(key: "key" ).get<std::string>(); |
407 | event.relations = common::parse_relations(obj); |
408 | } |
409 | |
410 | void |
411 | to_json(nlohmann::json &obj, const KeyVerificationKey &event) |
412 | { |
413 | if (event.transaction_id.has_value()) |
414 | obj["transaction_id" ] = event.transaction_id.value(); |
415 | obj["key" ] = event.key; |
416 | common::apply_relations(obj, relations: event.relations); |
417 | } |
418 | |
419 | void |
420 | from_json(const nlohmann::json &obj, KeyVerificationMac &event) |
421 | { |
422 | if (obj.count(key: "transaction_id" ) != 0) { |
423 | event.transaction_id = obj.at(key: "transaction_id" ).get<std::string>(); |
424 | } |
425 | event.mac = obj.at(key: "mac" ).get<std::map<std::string, std::string>>(); |
426 | event.keys = obj.at(key: "keys" ).get<std::string>(); |
427 | event.relations = common::parse_relations(obj); |
428 | } |
429 | |
430 | void |
431 | to_json(nlohmann::json &obj, const KeyVerificationMac &event) |
432 | { |
433 | if (event.transaction_id.has_value()) |
434 | obj["transaction_id" ] = event.transaction_id.value(); |
435 | obj["mac" ] = event.mac; |
436 | obj["keys" ] = event.keys; |
437 | common::apply_relations(obj, relations: event.relations); |
438 | } |
439 | |
440 | void |
441 | from_json(const nlohmann::json &obj, SecretRequest &event) |
442 | { |
443 | event.action = RequestAction::Unknown; |
444 | auto action = obj.value(key: "action" , default_value: "" ); |
445 | if (action == "request" ) { |
446 | event.action = RequestAction::Request; |
447 | } else if (action == "request_cancellation" ) { |
448 | event.action = RequestAction::Cancellation; |
449 | } |
450 | |
451 | event.name = obj.value(key: "name" , default_value: "" ); |
452 | |
453 | event.request_id = obj.value(key: "request_id" , default_value: "" ); |
454 | event.requesting_device_id = obj.value(key: "requesting_device_id" , default_value: "" ); |
455 | } |
456 | |
457 | void |
458 | to_json(nlohmann::json &obj, const SecretRequest &event) |
459 | { |
460 | switch (event.action) { |
461 | case RequestAction::Request: |
462 | obj["action" ] = "request" ; |
463 | break; |
464 | case RequestAction::Cancellation: |
465 | obj["action" ] = "request_cancellation" ; |
466 | break; |
467 | default: |
468 | throw std::invalid_argument("Unknown secret request action type" ); |
469 | } |
470 | |
471 | if (!event.name.empty()) |
472 | obj["name" ] = event.name; |
473 | |
474 | obj["request_id" ] = event.request_id; |
475 | obj["requesting_device_id" ] = event.requesting_device_id; |
476 | } |
477 | |
478 | void |
479 | from_json(const nlohmann::json &obj, SecretSend &event) |
480 | { |
481 | event.request_id = obj.value(key: "request_id" , default_value: "" ); |
482 | event.secret = obj.value(key: "secret" , default_value: "" ); |
483 | } |
484 | |
485 | void |
486 | to_json(nlohmann::json &obj, const SecretSend &event) |
487 | { |
488 | obj["request_id" ] = event.request_id; |
489 | obj["secret" ] = event.secret; |
490 | } |
491 | } // namespace msg |
492 | } // namespace events |
493 | } // namespace mtx |
494 | |