From 8f17f050d8c68e230f4cb657796ed6781bebc81c Mon Sep 17 00:00:00 2001 From: Joseph Donofry <joedonofry@gmail.com> Date: Fri, 30 Aug 2019 17:39:17 -0400 Subject: [PATCH] Very early cut at key verification addition to lib --- include/mtx/events.hpp | 30 ++++++++++++++++++++++++++++++ include/mtx/events/collections.hpp | 6 ++++++ include/mtx/events/encrypted.hpp | 26 ++++++++++++++++++++++++++ lib/structs/events.cpp | 26 +++++++++++++++++++++++++- lib/structs/events/encrypted.cpp | 20 ++++++++++++++++++++ lib/structs/responses/common.cpp | 24 ++++++++++++++++++++++++ tests/events.cpp | 25 +++++++++++++++++++++++++ 7 files changed, 156 insertions(+), 1 deletion(-) diff --git a/include/mtx/events.hpp b/include/mtx/events.hpp index c0e2b843f..1c0220dc1 100644 --- a/include/mtx/events.hpp +++ b/include/mtx/events.hpp @@ -14,6 +14,18 @@ namespace events { enum class EventType { + /// m.key.verification.cancel + KeyVerificationCancel, + /// m.key.verification.request + KeyVerificationRequest, + /// m.key.verification.start + KeyVerificationStart, + /// m.key.verification.accept + KeyVerificationAccept, + /// m.key.verification.key + KeyVerificationKey, + /// m.key.verification.mac + KeyVerificationMac, /// m.room_key_request RoomKeyRequest, /// m.room.aliases @@ -87,6 +99,24 @@ to_json(json &obj, const Event<Content> &event) obj["content"] = event.content; switch (event.type) { + case EventType::KeyVerificationStart: + obj["type"] = "m.key.verification.start"; + break; + case EventType::KeyVerificationAccept: + obj["type"] = "m.key.verification.accept"; + break; + case EventType::KeyVerificationMac: + obj["type"] = "m.key.verification.mac"; + break; + case EventType::KeyVerificationKey: + obj["type"] = "m.key.verification.accept"; + break; + case EventType::KeyVerificationCancel: + obj["type"] = "m.key.verification.cancel"; + break; + case EventType::KeyVerificationRequest: + obj["type"] = "m.key.verification.request"; + break; case EventType::RoomKeyRequest: obj["type"] = "m.room_key_request"; break; diff --git a/include/mtx/events/collections.hpp b/include/mtx/events/collections.hpp index 13adb68af..2e5de3d02 100644 --- a/include/mtx/events/collections.hpp +++ b/include/mtx/events/collections.hpp @@ -246,6 +246,12 @@ from_json(const json &obj, TimelineEvent &e) case events::EventType::RoomPinnedEvents: case events::EventType::RoomKeyRequest: // Not part of the timeline case events::EventType::Tag: // Not part of the timeline + case events::EventType::KeyVerificationCancel: + case events::EventType::KeyVerificationRequest: + case events::EventType::KeyVerificationStart: + case events::EventType::KeyVerificationAccept: + case events::EventType::KeyVerificationKey: + case events::EventType::KeyVerificationMac: case events::EventType::Unsupported: return; } diff --git a/include/mtx/events/encrypted.hpp b/include/mtx/events/encrypted.hpp index 2077c1c8e..eb9f18972 100644 --- a/include/mtx/events/encrypted.hpp +++ b/include/mtx/events/encrypted.hpp @@ -116,6 +116,32 @@ from_json(const json &obj, KeyRequest &event); void to_json(json &obj, const KeyRequest &event); +//! Content of the `m.key.verification.request` event +struct KeyVerificationRequest +{ + //! The device ID which is initiating the request. + std::string from_device; + //! An opaque identifier for the verification request. Must be unique with respect to the + //! devices involved. + std::string transaction_id; + //! The verification methods supported by the sender. + std::vector<std::string> 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. + uint32_t timestamp; + //! The type of the event. + mtx::events::EventType type; +}; + +// TODO: KeyVerificationStart, KeyVerificationAccept, and KeyVerificationCancel + +void +from_json(const json &obj, KeyVerificationRequest &event); + +void +to_json(json &obj, const KeyVerificationRequest &event); + } // namespace msg } // namespace events } // namespace mtx diff --git a/lib/structs/events.cpp b/lib/structs/events.cpp index 5d1a89cd1..f737649ca 100644 --- a/lib/structs/events.cpp +++ b/lib/structs/events.cpp @@ -8,7 +8,19 @@ namespace events { EventType getEventType(const std::string &type) { - if (type == "m.room_key_request") + if (type == "m.key.verification.request") + return EventType::KeyVerificationRequest; + else if (type == "m.key.verification.start") + return EventType::KeyVerificationStart; + else if (type == "m.key.verification.accept") + return EventType::KeyVerificationAccept; + else if (type == "m.key.verification.key") + return EventType::KeyVerificationKey; + else if (type == "m.key.verification.key") + return EventType::KeyVerificationKey; + else if (type == "m.key.verification.cancel") + return EventType::KeyVerificationCancel; + else if (type == "m.room_key_request") return EventType::RoomKeyRequest; else if (type == "m.room.aliases") return EventType::RoomAliases; @@ -56,6 +68,18 @@ std::string to_string(EventType type) { switch (type) { + case EventType::KeyVerificationCancel: + return "m.key.verification.cancel"; + case EventType::KeyVerificationRequest: + return "m.key.verification.request"; + case EventType::KeyVerificationStart: + return "m.key.verification.start"; + case EventType::KeyVerificationAccept: + return "m.key.verification.accept"; + case EventType::KeyVerificationKey: + return "m.key.verification.key"; + case EventType::KeyVerificationMac: + return "m.key.verification.mac"; case EventType::RoomKeyRequest: return "m.room_key_request"; case EventType::RoomAliases: diff --git a/lib/structs/events/encrypted.cpp b/lib/structs/events/encrypted.cpp index 6dda4b699..7cc79be16 100644 --- a/lib/structs/events/encrypted.cpp +++ b/lib/structs/events/encrypted.cpp @@ -132,6 +132,26 @@ to_json(json &obj, const KeyRequest &event) } } +void +from_json(const json &obj, KeyVerificationRequest &event) +{ + event.from_device = obj.at("from_device").get<std::string>(); + event.methods = obj.at("methods").get<std::vector<std::string>>(); + event.timestamp = obj.at("timestamp").get<uint32_t>(); + event.transaction_id = obj.at("transaction_id").get<std::string>(); + event.type = mtx::events::getEventType(obj.at("type").get<std::string>()); +} + +void +to_json(json &obj, const KeyVerificationRequest &event) +{ + obj["from_device"] = event.from_device; + obj["methods"] = event.methods; + obj["timestamp"] = event.timestamp; + obj["transaction_id"] = event.transaction_id; + obj["type"] = to_string(event.type); +} + } // namespace msg } // namespace events } // namespace mtx diff --git a/lib/structs/responses/common.cpp b/lib/structs/responses/common.cpp index face18d3c..b1a30b58d 100644 --- a/lib/structs/responses/common.cpp +++ b/lib/structs/responses/common.cpp @@ -79,6 +79,12 @@ parse_room_account_data_events( } break; } + case events::EventType::KeyVerificationCancel: + case events::EventType::KeyVerificationRequest: + case events::EventType::KeyVerificationStart: + case events::EventType::KeyVerificationAccept: + case events::EventType::KeyVerificationKey: + case events::EventType::KeyVerificationMac: case events::EventType::RoomKeyRequest: case events::EventType::RoomAliases: case events::EventType::RoomAvatar: @@ -377,6 +383,12 @@ parse_timeline_events(const json &events, case events::EventType::RoomKeyRequest: // Not part of the timeline case events::EventType::Tag: // Not part of the timeline or state case events::EventType::Unsupported: + case events::EventType::KeyVerificationCancel: + case events::EventType::KeyVerificationRequest: + case events::EventType::KeyVerificationStart: + case events::EventType::KeyVerificationAccept: + case events::EventType::KeyVerificationKey: + case events::EventType::KeyVerificationMac: continue; } } @@ -518,6 +530,12 @@ parse_state_events(const json &events, case events::EventType::RoomRedaction: case events::EventType::Tag: // Not part of the timeline or state case events::EventType::Unsupported: + case events::EventType::KeyVerificationCancel: + case events::EventType::KeyVerificationRequest: + case events::EventType::KeyVerificationStart: + case events::EventType::KeyVerificationAccept: + case events::EventType::KeyVerificationKey: + case events::EventType::KeyVerificationMac: continue; } } @@ -651,6 +669,12 @@ parse_stripped_events(const json &events, case events::EventType::RoomPinnedEvents: case events::EventType::Tag: // Not part of the timeline or state case events::EventType::Unsupported: + case events::EventType::KeyVerificationCancel: + case events::EventType::KeyVerificationRequest: + case events::EventType::KeyVerificationStart: + case events::EventType::KeyVerificationAccept: + case events::EventType::KeyVerificationKey: + case events::EventType::KeyVerificationMac: continue; } } diff --git a/tests/events.cpp b/tests/events.cpp index 234426ea2..9e809dcb1 100644 --- a/tests/events.cpp +++ b/tests/events.cpp @@ -726,6 +726,31 @@ TEST(RoomEvents, Encrypted) "\"session_id\":\"/bHcdWPHsJLFd8dkyvG0n7q/RTDmfBIc+gC4laHJCQQ\"}"); } +TEST(ToDevice, KeyVerificationRequest) +{ + json request_data = R"({ + "content": { + "from_device": "AliceDevice2", + "methods": [ + "m.sas.v1" + ], + "timestamp": 1559598944869, + "transaction_id": "S0meUniqueAndOpaqueString" + }, + "type": "m.key.verification.request" +})"_json; + + ns::msg::KeyVerificationRequest event = request_data; + EXPECT_EQ(event.from_device, "AliceDevice2"); + EXPECT_EQ(event.type, mtx::events::EventType::KeyVerificationRequest); + EXPECT_EQ(event.transaction_id, "S0meUniqueAndOpaqueString"); + EXPECT_EQ(event.methods[0], "m.sas.v1"); + EXPECT_EQ(event.timestamp, 1559598944869); + EXPECT_EQ(request_data.dump(), json(event).dump()); +} + +// TODO: KeyVerificationStart, KeyVerificationAccept, and KeyVerificationCancel + TEST(ToDevice, KeyRequest) { json request_data = R"({ -- GitLab