Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F194793
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
21 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/crypto/outbound-group-session-p.hpp b/src/crypto/outbound-group-session-p.hpp
index bc7ff0a..98e0637 100644
--- a/src/crypto/outbound-group-session-p.hpp
+++ b/src/crypto/outbound-group-session-p.hpp
@@ -1,47 +1,43 @@
/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <libkazv-config.hpp>
#include "outbound-group-session.hpp"
-#include <olm/olm.h>
+#include <vodozemac.h>
#include <immer/map.hpp>
namespace Kazv
{
struct OutboundGroupSessionPrivate
{
/// to be deprecated
OutboundGroupSessionPrivate();
OutboundGroupSessionPrivate(RandomTag,
RandomData random,
Timestamp creationTime);
OutboundGroupSessionPrivate(const OutboundGroupSessionPrivate &that);
~OutboundGroupSessionPrivate() = default;
- ByteArray sessionData;
- OlmOutboundGroupSession *session;
+ std::optional<rust::Box<vodozemac::megolm::GroupSession>> session;
bool valid{false};
Timestamp creationTime;
std::string initialSessionKey;
-
- std::size_t checkError(std::size_t code) const;
- std::string error() const;
-
std::string pickle() const;
bool unpickle(std::string pickleData);
+ bool unpickleFromLibolm(std::string pickleData);
std::string sessionKey();
};
}
diff --git a/src/crypto/outbound-group-session.cpp b/src/crypto/outbound-group-session.cpp
index 2965c2b..1e855a0 100644
--- a/src/crypto/outbound-group-session.cpp
+++ b/src/crypto/outbound-group-session.cpp
@@ -1,221 +1,186 @@
/*
* This file is part of libkazv.
- * SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
+ * SPDX-FileCopyrightText: 2021-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include "outbound-group-session-p.hpp"
-
+#include "crypto-util-p.hpp"
#include <debug.hpp>
#include "time-util.hpp"
namespace Kazv
{
- std::size_t OutboundGroupSessionPrivate::checkError(std::size_t code) const
- {
- if (code == olm_error()) {
- kzo.crypto.warn() << "Olm outbound group session error: "
- << olm_outbound_group_session_last_error(session) << std::endl;
- }
- return code;
- }
-
- std::string OutboundGroupSessionPrivate::error() const
- {
- return olm_outbound_group_session_last_error(session);
- }
-
-
OutboundGroupSessionPrivate::OutboundGroupSessionPrivate()
- : sessionData(olm_outbound_group_session_size(), '\0')
- , session(olm_outbound_group_session(sessionData.data()))
+ : session(std::nullopt)
{
- auto randomData = genRandom(olm_init_outbound_group_session_random_length(session));
- auto res = checkError(olm_init_outbound_group_session(session, randomData.data(), randomData.size()));
-
- if (res != olm_error()) {
- valid = true;
- initialSessionKey = sessionKey();
- }
-
- creationTime = currentTimeMs();
}
- OutboundGroupSessionPrivate::OutboundGroupSessionPrivate(RandomTag,
- RandomData random,
- Timestamp creationTime)
- : sessionData(olm_outbound_group_session_size(), '\0')
- , session(olm_outbound_group_session(sessionData.data()))
+ OutboundGroupSessionPrivate::OutboundGroupSessionPrivate(
+ RandomTag,
+ [[maybe_unused]] RandomData random,
+ Timestamp creationTime)
+ : session(std::nullopt)
, creationTime(creationTime)
{
- assert(random.size() >= OutboundGroupSession::constructRandomSize());
- auto res = checkError(olm_init_outbound_group_session(session, reinterpret_cast<std::uint8_t *>(random.data()), random.size()));
+ session = checkVodozemacError([&]() {
+ return vodozemac::megolm::new_group_session();
+ });
- if (res != olm_error()) {
+ if (session.has_value()) {
valid = true;
initialSessionKey = sessionKey();
}
}
OutboundGroupSessionPrivate::OutboundGroupSessionPrivate(const OutboundGroupSessionPrivate &that)
- : sessionData(olm_outbound_group_session_size(), '\0')
- , session(olm_outbound_group_session(sessionData.data()))
+ : session(std::nullopt)
, creationTime(that.creationTime)
, initialSessionKey(that.initialSessionKey)
{
valid = unpickle(that.pickle());
}
std::string OutboundGroupSessionPrivate::pickle() const
{
- auto pickleData = std::string(olm_pickle_outbound_group_session_length(session), '\0');
- auto key = ByteArray(3, 'x');
- checkError(olm_pickle_outbound_group_session(session,
- key.data(), key.size(),
- pickleData.data(), pickleData.size()));
- return pickleData;
+ auto pickleData = session.value()->pickle(VODOZEMAC_PICKLE_KEY);
+ return static_cast<std::string>(pickleData);
}
bool OutboundGroupSessionPrivate::unpickle(std::string pickleData)
{
- auto key = ByteArray(3, 'x');
- auto res = checkError(olm_unpickle_outbound_group_session(
- session,
- key.data(), key.size(),
- pickleData.data(), pickleData.size()));
+ session = checkVodozemacError([&]() {
+ return vodozemac::megolm::group_session_from_pickle(pickleData, VODOZEMAC_PICKLE_KEY);
+ });
+ return session.has_value();
+ }
- return res != olm_error();
+ bool OutboundGroupSessionPrivate::unpickleFromLibolm(std::string pickleData)
+ {
+ session = checkVodozemacError([&]() {
+ return vodozemac::megolm::group_session_from_libolm_pickle(pickleData, rust::Slice<const unsigned char>(OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size()));
+ });
+ return session.has_value();
}
std::size_t OutboundGroupSession::constructRandomSize()
{
- static std::size_t s =
- []() {
- ByteArray sessionData(olm_outbound_group_session_size(), '\0');
- OlmOutboundGroupSession *session(olm_outbound_group_session(sessionData.data()));
- return olm_init_outbound_group_session_random_length(session);
- }();
-
- return s;
+ return 0;
}
OutboundGroupSession::OutboundGroupSession()
: m_d(new OutboundGroupSessionPrivate)
{
}
OutboundGroupSession::OutboundGroupSession(RandomTag, RandomData random, Timestamp creationTime)
: m_d(new OutboundGroupSessionPrivate(RandomTag{}, std::move(random), std::move(creationTime)))
{
}
OutboundGroupSession::~OutboundGroupSession() = default;
OutboundGroupSession::OutboundGroupSession(const OutboundGroupSession &that)
: m_d(new OutboundGroupSessionPrivate(*that.m_d))
{
}
OutboundGroupSession::OutboundGroupSession(OutboundGroupSession &&that)
: m_d(std::move(that.m_d))
{
}
OutboundGroupSession &OutboundGroupSession::operator=(const OutboundGroupSession &that)
{
m_d.reset(new OutboundGroupSessionPrivate(*that.m_d));
return *this;
}
OutboundGroupSession &OutboundGroupSession::operator=(OutboundGroupSession &&that)
{
m_d = std::move(that.m_d);
return *this;
}
bool OutboundGroupSession::valid() const
{
return m_d && m_d->valid;
}
std::string OutboundGroupSession::encrypt(std::string plainText)
{
- auto plain = ByteArray(plainText.begin(), plainText.end());
- auto size = olm_group_encrypt_message_length(m_d->session, plainText.size());
- auto encrypted = ByteArray(size, '\0');
-
+ auto res = checkVodozemacError([&]() {
+ return m_d->session.value()->encrypt(rust::Str(plainText));
+ });
- auto actualSize = m_d->checkError(olm_group_encrypt(
- m_d->session,
- plain.data(), plain.size(),
- encrypted.data(), encrypted.size()));
+ if (!res.has_value()) {
+ return std::string();
+ }
- return std::string(encrypted.begin(), encrypted.begin() + actualSize);
+ return static_cast<std::string>(res.value()->to_base64());
}
std::string OutboundGroupSessionPrivate::sessionKey()
{
- auto size = olm_outbound_group_session_key_length(session);
- auto keyBuf = ByteArray(size, '\0');
- auto actualSize = checkError(
- olm_outbound_group_session_key(session, keyBuf.data(), keyBuf.size()));
+ auto key = session.value()->session_key()->to_base64();
- return std::string(keyBuf.begin(), keyBuf.begin() + actualSize);
+ return static_cast<std::string>(key);
}
std::string OutboundGroupSession::sessionKey()
{
return m_d->sessionKey();
}
std::string OutboundGroupSession::initialSessionKey() const
{
return m_d->initialSessionKey;
}
std::string OutboundGroupSession::sessionId()
{
- auto size = olm_outbound_group_session_id_length(m_d->session);
- auto idBuf = ByteArray(size, '\0');
- auto actualSize = m_d->checkError(
- olm_outbound_group_session_id(m_d->session, idBuf.data(), idBuf.size()));
-
- return std::string(idBuf.begin(), idBuf.begin() + actualSize);
+ auto id = m_d->session.value()->session_id();
+ return static_cast<std::string>(id);
}
int OutboundGroupSession::messageIndex()
{
- return olm_outbound_group_session_message_index(m_d->session);
+ return m_d->session.value()->message_index();
}
Timestamp OutboundGroupSession::creationTimeMs() const
{
return m_d->creationTime;
}
void to_json(nlohmann::json &j, const OutboundGroupSession &s)
{
j = nlohmann::json::object();
+ j["version"] = 1;
j["valid"] = s.m_d->valid;
j["creationTime"] = s.m_d->creationTime;
j["initialSessionKey"] = s.m_d->initialSessionKey;
if (s.m_d->valid) {
j["session"] = s.m_d->pickle();
}
}
void from_json(const nlohmann::json &j, OutboundGroupSession &s)
{
s.m_d->valid = j.at("valid");
s.m_d->creationTime = j.at("creationTime");
s.m_d->initialSessionKey = j.at("initialSessionKey");
if (s.m_d->valid) {
- s.m_d->valid = s.m_d->unpickle(j.at("session"));
+ if (j.contains("version") && j["version"] == 1) {
+ s.m_d->valid = s.m_d->unpickle(j.at("session"));
+ } else {
+ s.m_d->valid = s.m_d->unpickleFromLibolm(j.at("session"));
+ }
}
}
}
diff --git a/src/crypto/outbound-group-session.hpp b/src/crypto/outbound-group-session.hpp
index aeaabb7..6d14019 100644
--- a/src/crypto/outbound-group-session.hpp
+++ b/src/crypto/outbound-group-session.hpp
@@ -1,63 +1,62 @@
/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <libkazv-config.hpp>
#include <memory>
#include <maybe.hpp>
#include <event.hpp>
#include "crypto-util.hpp"
namespace Kazv
{
struct OutboundGroupSessionPrivate;
class OutboundGroupSession
{
public:
/**
* @return The size of random data needed to construct an OutboundGroupSession.
*/
static std::size_t constructRandomSize();
- [[deprecated("Use deterministic variant instead. In the future, this will construct an invalid OutboundGroupSession.")]]
explicit OutboundGroupSession();
/**
* Constructs an OutboundGroupSession from custom random data.
*
* @param random The random data to use. Must be of at least size
* `constructRandomSize()`.
* @param creationTime The creation time of this OutboundGroupSession.
*/
OutboundGroupSession(RandomTag, RandomData random, Timestamp creationTime);
OutboundGroupSession(const OutboundGroupSession &that);
OutboundGroupSession(OutboundGroupSession &&that);
OutboundGroupSession &operator=(const OutboundGroupSession &that);
OutboundGroupSession &operator=(OutboundGroupSession &&that);
~OutboundGroupSession();
std::string encrypt(std::string plainText);
bool valid() const;
std::string sessionKey();
std::string initialSessionKey() const;
std::string sessionId();
int messageIndex();
Timestamp creationTimeMs() const;
private:
friend void to_json(nlohmann::json &j, const OutboundGroupSession &s);
friend void from_json(const nlohmann::json &j, OutboundGroupSession &s);
std::unique_ptr<OutboundGroupSessionPrivate> m_d;
};
}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 4a1b923..f645beb 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -1,119 +1,120 @@
include(CTest)
set(KAZVTEST_RESPATH ${CMAKE_CURRENT_SOURCE_DIR}/resources)
configure_file(kazvtest-respath.hpp.in kazvtest-respath.hpp)
function(libkazv_add_tests)
set(options "")
set(oneValueArgs "")
set(multiValueArgs EXTRA_LINK_LIBRARIES EXTRA_INCLUDE_DIRECTORIES)
cmake_parse_arguments(PARSE_ARGV 0 libkazv_add_tests "${options}" "${oneValueArgs}" "${multiValueArgs}")
foreach(test_source ${libkazv_add_tests_UNPARSED_ARGUMENTS})
string(REGEX REPLACE "\\.cpp$" "" test_executable "${test_source}")
string(REGEX REPLACE "/|\\\\" "--" test_executable "${test_executable}")
message(STATUS "Test ${test_executable} added")
add_executable("${test_executable}" "${test_source}")
target_link_libraries("${test_executable}"
PRIVATE Catch2::Catch2WithMain
Threads::Threads
${libkazv_add_tests_EXTRA_LINK_LIBRARIES}
)
target_include_directories(
"${test_executable}"
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
${libkazv_add_tests_EXTRA_INCLUDE_DIRECTORIES}
)
target_compile_definitions("${test_executable}" PRIVATE CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
add_test(NAME "${test_executable}" COMMAND "${test_executable}" "--allow-running-no-tests" "~[needs-internet]")
endforeach()
endfunction()
libkazv_add_tests(
event-test.cpp
cursorutiltest.cpp
base/serialization-test.cpp
base/types-test.cpp
base/immer-utils-test.cpp
base/json-utils-test.cpp
EXTRA_LINK_LIBRARIES kazvbase
)
add_library(client-test-lib SHARED client/client-test-util.cpp)
target_link_libraries(client-test-lib PUBLIC kazvjob kazvclient)
libkazv_add_tests(
client/discovery-test.cpp
client/sync-test.cpp
client/content-test.cpp
client/paginate-test.cpp
client/util-test.cpp
client/serialization-test.cpp
client/encrypted-file-test.cpp
client/sdk-test.cpp
client/thread-safety-test.cpp
client/room-test.cpp
client/random-generator-test.cpp
client/profile-test.cpp
client/kick-test.cpp
client/ban-test.cpp
client/join-test.cpp
client/keys-test.cpp
client/device-ops-test.cpp
client/send-test.cpp
client/encryption-test.cpp
client/redact-test.cpp
client/tagging-test.cpp
client/account-data-test.cpp
client/room/room-actions-test.cpp
client/room/local-echo-test.cpp
client/room/event-relationships-test.cpp
client/room/member-membership-test.cpp
client/push-rules-desc-test.cpp
client/notification-handler-test.cpp
client/validator-test.cpp
client/power-levels-desc-test.cpp
client/client-test.cpp
client/create-room-test.cpp
client/device-list-tracker-benchmark-test.cpp
client/room/read-receipt-test.cpp
client/room/undecrypted-events-test.cpp
client/encryption-benchmark-test.cpp
client/logout-test.cpp
client/room/pinned-events-test.cpp
EXTRA_LINK_LIBRARIES kazvclient kazveventemitter kazvjob client-test-lib kazvtestfixtures
EXTRA_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/client
)
libkazv_add_tests(
basejobtest.cpp
kazvjobtest.cpp
file-desc-test.cpp
EXTRA_LINK_LIBRARIES kazvbase kazvjob
)
libkazv_add_tests(
promise-test.cpp
EXTRA_LINK_LIBRARIES kazvbase kazvjob kazvstore
)
libkazv_add_tests(
event-emitter-test.cpp
EXTRA_LINK_LIBRARIES kazvbase kazveventemitter
)
libkazv_add_tests(
crypto-test.cpp
crypto/deterministic-test.cpp
crypto/inbound-group-session-test.cpp
+ crypto/outbound-group-session-test.cpp
EXTRA_LINK_LIBRARIES kazvcrypto
)
libkazv_add_tests(
store-test.cpp
EXTRA_LINK_LIBRARIES kazvstore kazvjob
)
diff --git a/src/tests/crypto/deterministic-test.cpp b/src/tests/crypto/deterministic-test.cpp
index cc175c6..14c0946 100644
--- a/src/tests/crypto/deterministic-test.cpp
+++ b/src/tests/crypto/deterministic-test.cpp
@@ -1,49 +1,41 @@
/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <catch2/catch_all.hpp>
#include <crypto.hpp>
#include <outbound-group-session.hpp>
#include <client/random-generator.hpp>
using namespace Kazv;
-TEST_CASE("Deterministic constructors of Crypto and OutboundGroupSession", "[crypto][deterministic]")
+TEST_CASE("Deterministic constructors of Crypto", "[crypto][deterministic]")
{
auto rg = RandomInterface{RandomDeviceGenerator{}};
auto random = rg.generateRange<RandomData>(Crypto::constructRandomSize());
Crypto crypto1(RandomTag{}, random);
Crypto crypto2(RandomTag{}, random);
REQUIRE(crypto1.toJson() == crypto2.toJson());
-
- random = rg.generateRange<RandomData>(OutboundGroupSession::constructRandomSize());
- auto creationTime = currentTimeMs();
-
- OutboundGroupSession ogs1(RandomTag{}, random, creationTime);
- OutboundGroupSession ogs2(RandomTag{}, random, creationTime);
-
- REQUIRE(nlohmann::json(ogs1) == nlohmann::json(ogs2));
}
TEST_CASE("Deterministic generating of one-time keys", "[crypto][deterministic]")
{
auto rg = RandomInterface{RandomDeviceGenerator{}};
auto random = rg.generateRange<RandomData>(Crypto::constructRandomSize());
Crypto crypto1(RandomTag{}, random);
Crypto crypto2(crypto1);
auto numKeysToGen = 2;
random = rg.generateRange<RandomData>(Crypto::genOneTimeKeysRandomSize(numKeysToGen));
crypto1.genOneTimeKeysWithRandom(random, numKeysToGen);
crypto2.genOneTimeKeysWithRandom(random, numKeysToGen);
REQUIRE(crypto1.toJson() == crypto2.toJson());
}
diff --git a/src/tests/crypto/outbound-group-session-test.cpp b/src/tests/crypto/outbound-group-session-test.cpp
new file mode 100644
index 0000000..2408ac7
--- /dev/null
+++ b/src/tests/crypto/outbound-group-session-test.cpp
@@ -0,0 +1,59 @@
+/*
+ * This file is part of libkazv.
+ * SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libkazv-config.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <outbound-group-session.hpp>
+#include <crypto.hpp>
+#include "crypto-test-resource.hpp"
+
+using namespace Kazv;
+
+static const auto resource = cryptoDumpResource();
+
+TEST_CASE("OutboundGroupSession conversion from libolm to vodozemac")
+{
+ auto sessionJson = resource["a"]["outboundGroupSessions"]["!foo:example.com"];
+ auto session = sessionJson.template get<OutboundGroupSession>();
+ REQUIRE(session.valid());
+ REQUIRE(session.initialSessionKey() == sessionJson["initialSessionKey"]);
+}
+
+TEST_CASE("OutboundGroupSession serialization roundtrip")
+{
+ auto session = OutboundGroupSession(RandomTag{}, genRandomData(OutboundGroupSession::constructRandomSize()), 0);
+ json j = session;
+ auto session2 = j.template get<OutboundGroupSession>();
+ REQUIRE(session2.valid());
+ REQUIRE(session.initialSessionKey() == session2.initialSessionKey());
+ REQUIRE(session.sessionId() == session2.sessionId());
+}
+
+TEST_CASE("OutboundGroupSession::from_json error handling")
+{
+ auto sessionJson = resource["a"]["outboundGroupSessions"]["!foo:example.com"];
+ sessionJson["session"] = "AAAAAAAAAA";
+ auto session = sessionJson.template get<OutboundGroupSession>();
+ REQUIRE(!session.valid());
+}
+
+TEST_CASE("OutboundGroupSession ctor")
+{
+ auto session = OutboundGroupSession();
+ REQUIRE(!session.valid());
+}
+
+TEST_CASE("OutboundGroupSession::encrypt error handling")
+{
+ // invalid utf8 will cause rust::Str to throw
+ // https://stackoverflow.com/questions/1301402/example-invalid-utf8-string
+ std::string plainText = "\xc3\x28";
+ auto session = OutboundGroupSession(RandomTag{}, genRandomData(OutboundGroupSession::constructRandomSize()), 0);
+ auto originalIndex = session.messageIndex();
+ auto res = session.encrypt(plainText);
+ REQUIRE(res.empty());
+ REQUIRE(originalIndex == session.messageIndex());
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Apr 5, 2:55 AM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
85213
Default Alt Text
(21 KB)
Attached To
Mode
rL libkazv
Attached
Detach File
Event Timeline
Log In to Comment