Skip to content
Snippets Groups Projects
encrypted.hpp 17.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • /// @file
    /// @brief Various event types used in E2EE.
    
    
    #if __has_include(<nlohmann/json_fwd.hpp>)
    #include <nlohmann/json_fwd.hpp>
    #else
    
    #include <nlohmann/json.hpp>
    
    
    #include "mtx/events.hpp"
    
    #include "mtx/events/common.hpp"
    
    #include "variant"
    
    
    namespace mtx {
    namespace events {
    namespace msg {
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    //! Display methods for Short Authentication Strings
    
    enum class SASMethods
    {
    
        Decimal, //!< Display 3 times 4 digits
        Emoji,   //! Display 7 emoji
        Unsupported
    
    };
    
    void
    from_json(const nlohmann::json &obj, SASMethods &method);
    
    void
    to_json(nlohmann::json &obj, const SASMethods &method);
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    //! The different verification methods
    
    enum class VerificationMethods
    {
    
        SASv1,      //!< Short Authentication Strings
        Unsupported //!< Unsupported method
    
    };
    
    void
    from_json(const nlohmann::json &obj, VerificationMethods &method);
    
    void
    to_json(nlohmann::json &obj, const VerificationMethods &method);
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    //! Content of an individual message encrypted for a certain key.
    
    struct OlmCipherContent
    {
    
        //! Ciphertext of the message.
        std::string body;
        /// @brief Olm message type.
        ///
        /// `0` for initial pre-key messages.
        /// `1` for normal messages after the initial exchange.
        uint8_t type;
    
        friend void from_json(const nlohmann::json &obj, OlmCipherContent &event);
    
        friend void to_json(nlohmann::json &obj, const OlmCipherContent &event);
    };
    
    
    //! Content of the `m.room.encrypted` Olm event.
    struct OlmEncrypted
    {
    
        //! Algorithm used for encrypting this event.
        std::string algorithm;
        //! curve25519 key of the sender.
        std::string sender_key;
    
        using RecipientKey = std::string;
        //! Map of recipient curve25519 key to the encrypted message.
        std::map<RecipientKey, OlmCipherContent> ciphertext;
    
        friend void from_json(const nlohmann::json &obj, OlmEncrypted &event);
    
        friend void to_json(nlohmann::json &obj, const OlmEncrypted &event);
    };
    
    
    //! Content of the `m.room.encrypted` event.
    struct Encrypted
    {
    
        //! Used for one-on-one exchanges.
        std::string algorithm;
        //! The actual encrypted payload.
        std::string ciphertext;
        //! Sender's device id.
        std::string device_id;
        //! The curve25519 device key.
        std::string sender_key;
        //! Outbound group session id.
        std::string session_id;
        //! Relations like rich replies
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, Encrypted &event);
    
        friend void to_json(nlohmann::json &obj, const Encrypted &event);
    };
    
    //! Content of the `m.dummy` event.
    struct Dummy
    
    {
        friend void from_json(const nlohmann::json &obj, Dummy &event);
        friend void to_json(nlohmann::json &obj, const Dummy &event);
    };
    
    //! Content of the `m.room_key` event.
    struct RoomKey
    {
    
        /// @brief *Required.* The encryption algorithm the key in this event is to be used with.
        ///
        /// Must be 'm.megolm.v1.aes-sha2'.
        std::string algorithm;
        std::string room_id;     //!< *Required.* The room where the key is used.
        std::string session_id;  //!< *Required.* The ID of the session that the key is for.
        std::string session_key; //!< *Required.* The key to be exchanged.
    
        friend void from_json(const nlohmann::json &obj, RoomKey &event);
        friend void to_json(nlohmann::json &obj, const RoomKey &event);
    };
    
    //! Content of the `m.forwarded_room_key` event.
    struct ForwardedRoomKey
    {
    
        /// @brief *Required.* The encryption algorithm the key in this event is to be used with.
        std::string algorithm;
        std::string room_id;     //!< *Required.* The room where the key is used.
        std::string session_id;  //!< *Required.* The ID of the session that the key is for.
        std::string session_key; //!< *Required.* The key to be exchanged.
    
        //! *Required.* The Curve25519 key of the device which initiated the session originally.
        std::string sender_key;
        /// @brief *Required.* The Ed25519 key of the device which initiated the session originally.
        ///
        /// It is 'claimed' because the receiving device has no way to tell that the original
        /// room_key actually came from a device which owns the private part of this key unless they
        /// have done device verification.
        std::string sender_claimed_ed25519_key;
        /// @brief *Required.* Chain of Curve25519 keys.
        ///
        /// It starts out empty, but each time the key is forwarded to another device, the previous
        /// sender in the chain is added to the end of the list. For example, if the key is
        /// forwarded from A to B to C, this field is empty between A and B, and contains A's
        /// Curve25519 key between B and C.
        std::vector<std::string> forwarding_curve25519_key_chain;
    
        friend void from_json(const nlohmann::json &obj, ForwardedRoomKey &event);
        friend void to_json(nlohmann::json &obj, const ForwardedRoomKey &event);
    };
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    //! The type of key request.
    
    enum class RequestAction
    {
    
        Request,      //!< request
        Cancellation, //!< request_cancellation
        Unknown,      //!< Unknown request action
    
    void
    from_json(const nlohmann::json &obj, RequestAction &action);
    
    void
    to_json(nlohmann::json &obj, const RequestAction &action);
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    //! A request to share a session key.
    
        //! The type of request.
        RequestAction action;
    
        /// @brief The encryption algorithm of the session we want keys for.
        ///
        /// Always m.megolm.v1.aes-sha2.
        std::string algorithm;
        //! The room in which the session was created.
        std::string room_id;
        //! The curve25519 key of the session creator.
        std::string sender_key;
        //! The session_id of the outbound megolm session.
        std::string session_id;
    
        //! A unique identifier for this request.
        std::string request_id;
        //! The device requesting the keys.
        std::string requesting_device_id;
    
        friend void from_json(const nlohmann::json &obj, KeyRequest &event);
        friend void to_json(nlohmann::json &obj, const KeyRequest &event);
    };
    
    //! Content of the `m.key.verification.request` event
    struct KeyVerificationRequest
    {
    
        std::optional<std::string> body;
        //! The device ID which is initiating the request.
        std::string from_device;
        //! The device ID to which the key verification request is meant,used only for to-device
        //! verification
        std::optional<std::string> to;
        //! An opaque identifier for the verification request. Must be unique with respect to the
        //! devices involved.
        std::optional<std::string> transaction_id;
        //! must be `key.verification.request`, this field will be needed only in room verification
        std::optional<std::string> msgtype;
        //! The verification methods supported by the sender.
        std::vector<VerificationMethods> methods;
        //! The POSIX timestamp in milliseconds for when the request was made. If the request is in
        //! the future by more than 5 minutes or more than 10 minutes in the past, the message
        //! should be ignored by the receiver.
        std::optional<uint64_t> timestamp;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationRequest &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationRequest &event);
    };
    
    //! Content of the `m.key.verification.start` event
    struct KeyVerificationStart
    {
    
        //! The device ID which is initiating the process.
        std::string from_device;
        /// @brief An opaque identifier for the verification process.
        ///
        /// Must be unique with respect to the devices involved. Must be the same as the
        /// transaction_id given in the `m.key.verification.request` if this process is originating
        /// from a request.
        /// @note Used in verification via to_device messaging
        std::optional<std::string> transaction_id;
        //! The verification method to use. Must be 'm.sas.v1'
        VerificationMethods method = VerificationMethods::SASv1;
        /// @brief Optional method to use to verify the other user's key with.
        //
        // Applicable when the method chosen only verifies one user's key. This field will never be
        // present if the method verifies keys both ways.
        /// @note This appears to be unused in SAS verification
        std::optional<std::string> next_method;
        /// @brief The key agreement protocols the sending device understands.
        ///
        /// Must include at least curve25519.
        std::vector<std::string> key_agreement_protocols;
        //! The hash methods the sending device understands. Must include at least sha256.
        std::vector<std::string> hashes;
        /// @brief The message authentication codes that the sending device understands.
        ///
        /// Must include at least hkdf-hmac-sha256.
        std::vector<std::string> message_authentication_codes;
        /// @brief The SAS methods the sending device (and the sending device's user) understands.
        ///
        /// Must include at least decimal. Optionally can include emoji.
        ///
        /// One of:
        /// - `decimal`
        /// - `emoji`
        std::vector<SASMethods> short_authentication_string;
        /// @brief This is used for relating this message with previously sent
        /// `key.verification.request`
        ///
        /// @note Will be used only for room-verification msgs where this is used in place of
        /// transaction_id.
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationStart &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationStart &event);
    };
    
    //! Implements the `m.key.verification.ready` event
    
    struct KeyVerificationReady
    {
    
        //! the deviceId of the device which send the `m.key.verification.request`
        std::string from_device;
        //! transactionId of the current flow
        std::optional<std::string> transaction_id;
        //! Sends the user the supported methods
        std::vector<VerificationMethods> methods;
        //! this is used for relating this message with previously sent
        //! key.verification.request will be used only for room-verification msgs where this
        //! is used in place of txnid
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationReady &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationReady &event);
    };
    
    
    // ! Implements the `m.key.verification.done` event
    struct KeyVerificationDone
    
        //! transactionId of the current flow
        std::optional<std::string> transaction_id;
        //! this is used for relating this message with previously sent key.verification.request
        //! will be used only for room-verification msgs where this is used in place of txnid
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationDone &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationDone &event);
    };
    
    //! Implements the `m.key.verification.accept` event
    struct KeyVerificationAccept
    {
    
        //! when the method chosen only verifies one user's key. This field will never be present
        //! if the method verifies keys both ways.
        std::optional<std::string> transaction_id;
        //! The verification method to use. Must be 'm.sas.v1'
        VerificationMethods method = VerificationMethods::SASv1;
        //! The key agreement protocol the device is choosing to use, out of the options in the
        //! m.key.verification.start message.
        std::string key_agreement_protocol;
        //! The hash method the device is choosing to use, out of the options in the
        //! m.key.verification.start message.
        std::string hash;
        //! The message authentication code the device is choosing to use, out of the options in
        //! the m.key.verification.start message.
        std::string message_authentication_code;
        //! The SAS methods both devices involed in the verification process understand.  Must be
        //! a subset of the options in the m.key.verification.start message.
        //! One of: ["decimal", "emoji"]
        std::vector<SASMethods> short_authentication_string;
        //! The hash (encoded as unpadded base64) of the concatenation of the device's ephemeral
        //! public key (encoded as unpadded base64) and the canonical JSON representation of the
        //! m.key.verification.start message.
        std::string commitment;
        //! this is used for relating this message with previously sent key.verification.request
        //! will be used only for room-verification msgs where this is used in place of txnid
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationAccept &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationAccept &event);
    };
    
    
    //! implementation of the `m.key.verification.cancel` event
    struct KeyVerificationCancel
    {
    
        //! The opaque identifier for the verification process/request.
        std::optional<std::string> transaction_id;
        //! A human readable description of the code. The client should only rely on this string
        //! if it does not understand the code.
        std::string reason;
        //! The error code for why the process/request was cancelled by the user. Error codes
        //! should use the Java package naming convention if not in the following list:
        //! m.user: The user cancelled the verification.
        //! m.timeout: The verification process timed out. Verification processes can define
        //!            their own timeout parameters.
        //! m.unknown_transaction: The device does not know about the given transaction ID.
        //! m.unknown_method: The device does not know how to handle the requested method.
        //!             This should be sent for m.key.verification.start messages and messages
        //!             defined by individual verification processes.
        //! m.unexpected_message: The device received an unexpected message. Typically raised
        //!             when one of the parties is handling the verification out of order.
        //! m.key_mismatch: The key was not verified.
        //! m.user_mismatch: The expected user did not match the user verified.
        //! m.invalid_message: The message received was invalid.
        //! m.accepted: A m.key.verification.request was accepted by a different device.
        //!             The device receiving this error can ignore the verification request.
        //! m.unknown_method: The devices are unable to agree on the key agreement,
        //!             hash, MAC, or SAS method.
        //! m.mismatched_commitment: The hash commitment did not match.
        //! m.mismatched_sas: The SAS did not match.
        //! Clients should be careful to avoid error loops. For example, if a device sends an
        //! incorrect message and the client returns m.invalid_message to which it gets an
        //! unexpected response with m.unexpected_message, the client should not respond
        //! again with m.unexpected_message to avoid the other device potentially sending
        //! another error response.
        std::string code;
        //! this is used for relating this message with previously sent key.verification.request
        //! will be used only for room-verification msgs where this is used in place of txnid
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationCancel &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationCancel &event);
    };
    
    
    struct KeyVerificationKey
    {
    
        //! An opaque identifier for the verification process. Must be the same as the one
        //! used for the m.key.verification.start message.
        std::optional<std::string> transaction_id;
        //! The device's ephemeral public key, encoded as unpadded base64.
        std::string key;
        //! this is used for relating this message with previously sent key.verification.request
        //! will be used only for room-verification msgs where this is used in place of txnid
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationKey &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationKey &event);
    };
    
    
    struct KeyVerificationMac
    {
    
        //! An opaque identifier for the verification process. Must be the same as the one
        //! used for the m.key.verification.start message.
        std::optional<std::string> transaction_id;
        //! A map of the key ID to the MAC of the key, using the algorithm in the
        //! verification process. The MAC is encoded as unpadded base64.
        std::map<std::string, std::string> mac;
        //! The MAC of the comma-separated, sorted, list of key IDs given in the mac
        //! property, encoded as unpadded base64.
        std::string keys;
        //! this is used for relating this message with previously sent key.verification.request
        //! will be used only for room-verification msgs where this is used in place of txnid
        common::Relations relations;
    
        friend void from_json(const nlohmann::json &obj, KeyVerificationMac &event);
        friend void to_json(nlohmann::json &obj, const KeyVerificationMac &event);
    };
    
    struct SecretRequest
    {
    
        //! The type of request.
        RequestAction action;
    
        //! Required if action is request. The name of the secret that is being requested.
        std::string name;
    
        //! A unique identifier for this request.
        std::string request_id;
        //! The device requesting the keys.
        std::string requesting_device_id;
    
        friend void from_json(const nlohmann::json &obj, SecretRequest &event);
        friend void to_json(nlohmann::json &obj, const SecretRequest &event);
    };
    
    
    struct SecretSend
    {
    
        //! Required. The contents of the secret.
        std::string secret;
    
        //! A unique identifier for this request.
        std::string request_id;
    
        friend void from_json(const nlohmann::json &obj, SecretSend &event);
        friend void to_json(nlohmann::json &obj, const SecretSend &event);
    };
    
    } // namespace msg
    } // namespace events
    } // namespace mtx