| 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 | |