From 755cc434d0d8672d3f1c3c5db718f273886d3e6d Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris <sideris.konstantin@gmail.com> Date: Sat, 15 Sep 2018 17:56:03 +0300 Subject: [PATCH] Add methods for importing/exporting inbound megolm sessions --- include/mtxclient/crypto/client.hpp | 10 ++++- lib/crypto/client.cpp | 30 +++++++++++++++ tests/e2ee.cpp | 59 +++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/include/mtxclient/crypto/client.hpp b/include/mtxclient/crypto/client.hpp index ef16c3f5f..7c46b5d2d 100644 --- a/include/mtxclient/crypto/client.hpp +++ b/include/mtxclient/crypto/client.hpp @@ -214,10 +214,18 @@ session_id(OlmSession *s); std::string session_id(OlmOutboundGroupSession *s); -//! Retrieve the session key. +//! Retrieve the session key from an *outbound* megolm session. std::string session_key(OlmOutboundGroupSession *s); +//! Retrieve the session key from an *inbound* megolm session. +std::string +export_session(OlmInboundGroupSession *s); + +//! Create an *inbound* megolm session from an exported session key. +InboundGroupSessionPtr +import_session(const std::string &session_key); + bool matches_inbound_session(OlmSession *session, const std::string &one_time_key_message); diff --git a/lib/crypto/client.cpp b/lib/crypto/client.cpp index 22f95ecd7..0d0f39619 100644 --- a/lib/crypto/client.cpp +++ b/lib/crypto/client.cpp @@ -437,6 +437,36 @@ mtx::crypto::session_key(OlmOutboundGroupSession *s) return std::string(tmp.begin(), tmp.end()); } +std::string +mtx::crypto::export_session(OlmInboundGroupSession *s) +{ + const size_t len = olm_export_inbound_group_session_length(s); + const uint32_t index = olm_inbound_group_session_first_known_index(s); + + auto session_key = create_buffer(len); + const int rc = + olm_export_inbound_group_session(s, session_key.data(), session_key.size(), index); + + if (rc == -1) + throw olm_exception("session_key", s); + + return std::string(session_key.begin(), session_key.end()); +} + +InboundGroupSessionPtr +mtx::crypto::import_session(const std::string &session_key) +{ + auto session = create_olm_object<InboundSessionObject>(); + + const int rc = olm_import_inbound_group_session( + session.get(), reinterpret_cast<const uint8_t *>(session_key.data()), session_key.size()); + + if (rc == -1) + throw olm_exception("import_session", session.get()); + + return session; +} + bool mtx::crypto::matches_inbound_session(OlmSession *session, const std::string &one_time_key_message) { diff --git a/tests/e2ee.cpp b/tests/e2ee.cpp index 1a1f0e05f..dd0aa9ed8 100644 --- a/tests/e2ee.cpp +++ b/tests/e2ee.cpp @@ -1071,6 +1071,65 @@ TEST(ExportSessions, EncryptDecrypt) EXPECT_EQ(json(keys).dump(), json(restored_keys).dump()); } +TEST(ExportSessions, InboundMegolmSessions) +{ + auto alice = std::make_shared<OlmClient>(); + alice->create_new_account(); + alice->generate_one_time_keys(1); + + auto bob = std::make_shared<OlmClient>(); + bob->create_new_account(); + bob->generate_one_time_keys(1); + + // ==================== SESSION SETUP =================== // + + // Alice wants to send an encrypted megolm message to Bob. + const std::string secret_message = "Hey, Bob!"; + + // Alice creates an outbound megolm session that will be used by both parties. + auto outbound_megolm_session = alice->init_outbound_group_session(); + auto msg_index = olm_outbound_group_session_message_index(outbound_megolm_session.get()); + ASSERT_EQ(msg_index, 0); + + // Alice extracts the session id & session key so she can share them with Bob. + const auto session_id = mtx::crypto::session_id(outbound_megolm_session.get()); + const auto session_key = mtx::crypto::session_key(outbound_megolm_session.get()); + + // Encrypt the message using megolm. + auto encrypted_secret_message = + alice->encrypt_group_message(outbound_megolm_session.get(), secret_message); + + msg_index = olm_outbound_group_session_message_index(outbound_megolm_session.get()); + ASSERT_EQ(msg_index, 1); + + // Bob will use the session_key to create an inbound megolm session. + // The session_id will be used to map future messages to this session. + auto inbound_megolm_session = bob->init_inbound_group_session(session_key); + + // Bob can finally decrypt Alice's original message. + auto ciphertext = + std::string((char *)encrypted_secret_message.data(), encrypted_secret_message.size()); + auto bob_plaintext = bob->decrypt_group_message(inbound_megolm_session.get(), ciphertext); + + auto output_str = std::string((char *)bob_plaintext.data.data(), bob_plaintext.data.size()); + ASSERT_EQ(output_str, secret_message); + + // ==================== SESSION IMPORT/EXPORT =================== // + + auto exported_session_key = export_session(inbound_megolm_session.get()); + auto restored_inbound_session = import_session(exported_session_key); + + // Decrypt message again. + auto restored_ciphertext = + std::string((char *)encrypted_secret_message.data(), encrypted_secret_message.size()); + auto restored_plaintext = + bob->decrypt_group_message(restored_inbound_session.get(), restored_ciphertext); + + auto restored_output_str = + std::string((char *)restored_plaintext.data.data(), restored_plaintext.data.size()); + ASSERT_EQ(restored_output_str, secret_message); +} + TEST(Encryption, DISABLED_HandleRoomKeyEvent) {} TEST(Encryption, DISABLED_HandleRoomKeyRequestEvent) {} TEST(Encryption, DISABLED_HandleNewDevices) {} -- GitLab