1 | #pragma once |
2 | |
3 | /// @file |
4 | /// @brief E2EE related endpoints. |
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/common.hpp" |
13 | #include "mtx/lightweight_error.hpp" |
14 | |
15 | #include <map> |
16 | #include <string> |
17 | |
18 | namespace mtx { |
19 | namespace responses { |
20 | //! Response from the `POST /_matrix/client/r0/keys/upload` endpoint. |
21 | struct UploadKeys |
22 | { |
23 | //! For each key algorithm, the number of unclaimed one-time keys |
24 | //! of that type currently held on the server for this device. |
25 | std::map<std::string, uint32_t> one_time_key_counts; |
26 | |
27 | friend void from_json(const nlohmann::json &obj, UploadKeys &response); |
28 | }; |
29 | |
30 | using DeviceToKeysMap = std::map<std::string, mtx::crypto::DeviceKeys>; |
31 | |
32 | //! Response from the `POST /_matrix/client/r0/keys/query` endpoint. |
33 | struct QueryKeys |
34 | { |
35 | //! If any remote homeservers could not be reached, they are |
36 | //! recorded here. The names of the properties are the names |
37 | //! of the unreachable servers. |
38 | std::map<std::string, nlohmann::json> failures; |
39 | //! Information on the queried devices. |
40 | //! A map from user ID, to a map from device ID to device information. |
41 | //! For each device, the information returned will be the same |
42 | //! as uploaded via /keys/upload, with the addition of an unsigned property |
43 | std::map<std::string, DeviceToKeysMap> device_keys; |
44 | //! A map from user ID, to information about master_keys. |
45 | std::map<std::string, mtx::crypto::CrossSigningKeys> master_keys; |
46 | //! A map from user ID, to information about user_signing_keys. |
47 | std::map<std::string, mtx::crypto::CrossSigningKeys> user_signing_keys; |
48 | //! A map from user ID, to information about self_signing_keys. |
49 | std::map<std::string, mtx::crypto::CrossSigningKeys> self_signing_keys; |
50 | |
51 | friend void to_json(nlohmann::json &obj, const QueryKeys &response); |
52 | friend void from_json(const nlohmann::json &obj, QueryKeys &response); |
53 | }; |
54 | |
55 | //! Request for `POST /_matrix/client/r0/keys/upload`. |
56 | struct KeySignaturesUpload |
57 | { |
58 | //! Errors returned during upload. |
59 | std::map<std::string, std::map<std::string, mtx::errors::LightweightError>> errors; |
60 | |
61 | friend void from_json(const nlohmann::json &obj, KeySignaturesUpload &response); |
62 | }; |
63 | |
64 | //! Response from the `POST /_matrix/client/r0/keys/claim` endpoint. |
65 | struct ClaimKeys |
66 | { |
67 | //! If any remote homeservers could not be reached, they are |
68 | //! recorded here. The names of the properties are the names |
69 | //! of the unreachable servers. |
70 | std::map<std::string, nlohmann::json> failures; |
71 | //! One-time keys for the queried devices. A map from user ID, |
72 | //! to a map from <algorithm>:<key_id> to the key object. |
73 | std::map<std::string, std::map<std::string, nlohmann::json>> one_time_keys; |
74 | |
75 | friend void from_json(const nlohmann::json &obj, ClaimKeys &response); |
76 | }; |
77 | |
78 | //! Response from the `GET /_matrix/client/r0/keys/changes` endpoint. |
79 | struct KeyChanges |
80 | { |
81 | //! The Matrix User IDs of all users who updated their device identity keys. |
82 | std::vector<std::string> changed; |
83 | //! The Matrix User IDs of all users who may have left all the end-to-end |
84 | //! encrypted rooms they previously shared with the user. |
85 | std::vector<std::string> left; |
86 | |
87 | friend void from_json(const nlohmann::json &obj, KeyChanges &response); |
88 | }; |
89 | |
90 | //! KeysBackup related responses. |
91 | namespace backup { |
92 | //! Encrypted session data using the m.megolm_backup.v1.curve25519-aes-sha2 algorithm |
93 | struct EncryptedSessionData |
94 | { |
95 | //! Generate an ephemeral curve25519 key, and perform an ECDH with the ephemeral key and the |
96 | //! backup's public key to generate a shared secret. The public half of the ephemeral key, |
97 | //! encoded using unpadded base64, becomes the ephemeral property |
98 | std::string ephemeral; |
99 | //! Stringify the JSON object, and encrypt it using AES-CBC-256 with PKCS#7 padding. This |
100 | //! encrypted data, encoded using unpadded base64, becomes the ciphertext property of the |
101 | //! session_data. |
102 | std::string ciphertext; |
103 | //! Pass the raw encrypted data (prior to base64 encoding) through HMAC-SHA-256 using the |
104 | //! MAC key generated above. The first 8 bytes of the resulting MAC are base64-encoded, and |
105 | //! become the mac property of the session_data. |
106 | std::string mac; |
107 | |
108 | friend void from_json(const nlohmann::json &obj, EncryptedSessionData &response); |
109 | friend void to_json(nlohmann::json &obj, const EncryptedSessionData &response); |
110 | }; |
111 | |
112 | //! Responses from the `GET /_matrix/client/r0/room_keys/keys/{room_id}/{session_id}` endpoint |
113 | struct SessionBackup |
114 | { |
115 | //! Required. The index of the first message in the session that the key can decrypt. |
116 | int64_t first_message_index; |
117 | //! Required. The number of times this key has been forwarded via key-sharing between |
118 | //! devices. |
119 | int64_t forwarded_count; |
120 | //! Required. Whether the device backing up the key verified the device that the key is |
121 | //! from. |
122 | bool is_verified; |
123 | //! Required. Algorithm-dependent data. See the documentation for the backup algorithms in |
124 | //! Server-side key backups for more information on the expected format of the data. |
125 | EncryptedSessionData session_data; |
126 | |
127 | friend void from_json(const nlohmann::json &obj, SessionBackup &response); |
128 | friend void to_json(nlohmann::json &obj, const SessionBackup &response); |
129 | }; |
130 | |
131 | //! Responses from the `GET /_matrix/client/r0/room_keys/keys/{room_id}` endpoint |
132 | struct RoomKeysBackup |
133 | { |
134 | //! map of session id to the individual sessions |
135 | std::map<std::string, SessionBackup> sessions; |
136 | |
137 | friend void from_json(const nlohmann::json &obj, RoomKeysBackup &response); |
138 | friend void to_json(nlohmann::json &obj, const RoomKeysBackup &response); |
139 | }; |
140 | |
141 | //! Responses from the `GET /_matrix/client/r0/room_keys/keys` endpoint |
142 | struct KeysBackup |
143 | { |
144 | //! map of room id to map of session ids to backups of individual sessions |
145 | std::map<std::string, RoomKeysBackup> rooms; |
146 | |
147 | friend void from_json(const nlohmann::json &obj, KeysBackup &response); |
148 | friend void to_json(nlohmann::json &obj, const KeysBackup &response); |
149 | }; |
150 | |
151 | inline constexpr const char *megolm_backup_v1 = "m.megolm_backup.v1.curve25519-aes-sha2" ; |
152 | |
153 | //! Responses from the `GET /_matrix/client/r0/room_keys/version` endpoint |
154 | struct BackupVersion |
155 | { |
156 | //! Required. The algorithm used for storing backups. Must be |
157 | //! 'm.megolm_backup.v1.curve25519-aes-sha2'. |
158 | std::string algorithm; |
159 | //! Required. Algorithm-dependent data. See the documentation for the backup algorithms in |
160 | //! Server-side key backups for more information on the expected format of the data. |
161 | std::string auth_data; |
162 | //! Required. The number of keys stored in the backup. |
163 | int64_t count; |
164 | //! Required. An opaque string representing stored keys in the backup. Clients can |
165 | //! compare it with the etag value they received in the request of their last key storage |
166 | //! request. If not equal, another client has modified the backup |
167 | std::string etag; |
168 | //! Required. The backup version |
169 | std::string version; |
170 | |
171 | friend void from_json(const nlohmann::json &obj, BackupVersion &response); |
172 | friend void to_json(nlohmann::json &obj, const BackupVersion &response); |
173 | }; |
174 | |
175 | //! The SessionData stored in the KeysBackup. |
176 | struct SessionData |
177 | { |
178 | //! Required. The end-to-end message encryption algorithm that the key is |
179 | // for. Must be m.megolm.v1.aes-sha2. |
180 | std::string algorithm; |
181 | // Required. Chain of Curve25519 keys through which this |
182 | // session was forwarded, via m.forwarded_room_key events. |
183 | std::vector<std::string> forwarding_curve25519_key_chain; |
184 | // Required. Unpadded base64-encoded device curve25519 key. |
185 | std::string sender_key; |
186 | // Required. A map from algorithm name (ed25519) to the identity |
187 | // key for the sending device. |
188 | std::map<std::string, std::string> sender_claimed_keys; |
189 | // Required. Unpadded base64-encoded session key in session-sharing format. |
190 | std::string session_key; |
191 | |
192 | friend void to_json(nlohmann::json &obj, const SessionData &desc); |
193 | friend void from_json(const nlohmann::json &obj, SessionData &desc); |
194 | }; |
195 | } |
196 | } // namespace responses |
197 | } // namespace mtx |
198 | |