Page MenuHomePhorge

D161.1726791628.diff
No OneTemporary

D161.1726791628.diff

diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -90,7 +90,6 @@
set(CRYPTOPP_TARGET_NAME cryptopp)
endif()
-find_package(Olm REQUIRED)
find_package(vodozemac REQUIRED)
if(libkazv_BUILD_EXAMPLES)
diff --git a/cmake/libkazvConfig.cmake b/cmake/libkazvConfig.cmake
--- a/cmake/libkazvConfig.cmake
+++ b/cmake/libkazvConfig.cmake
@@ -4,7 +4,6 @@
find_dependency(Immer)
find_dependency(Zug)
find_dependency(Lager)
-find_dependency(Olm)
set(_oldCmakeModulePath ${CMAKE_MODULE_PATH})
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}" ${CMAKE_MODULE_PATH})
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -13,7 +13,7 @@
add_library(libkazv::kazvcrypto ALIAS kazvcrypto)
set_target_properties(kazvcrypto PROPERTIES VERSION ${libkazv_VERSION_STRING} SOVERSION ${libkazv_SOVERSION})
-target_link_libraries(kazvcrypto PUBLIC kazvbase Olm::Olm ${CRYPTOPP_TARGET_NAME})
+target_link_libraries(kazvcrypto PUBLIC kazvbase ${CRYPTOPP_TARGET_NAME})
target_link_libraries(kazvcrypto PRIVATE vodozemac::vodozemac)
target_include_directories(kazvcrypto PRIVATE .)
diff --git a/src/crypto/crypto-p.hpp b/src/crypto/crypto-p.hpp
--- a/src/crypto/crypto-p.hpp
+++ b/src/crypto/crypto-p.hpp
@@ -7,12 +7,13 @@
#pragma once
#include <libkazv-config.hpp>
-#include <olm/olm.h>
+#include <vodozemac.h>
#include <unordered_map>
#include "crypto.hpp"
#include "crypto-util.hpp"
+#include "crypto-util-p.hpp"
#include "session.hpp"
#include "inbound-group-session.hpp"
#include "outbound-group-session.hpp"
@@ -28,8 +29,7 @@
CryptoPrivate(const CryptoPrivate &that);
~CryptoPrivate();
- ByteArray accountData;
- OlmAccount *account;
+ std::optional<rust::Box<vodozemac::olm::Account>> account;
immer::map<std::string /* algorithm */, int> uploadedOneTimeKeysCount;
int numUnpublishedKeys{0};
std::unordered_map<std::string /* theirCurve25519IdentityKey */, Session> knownSessions;
@@ -37,21 +37,15 @@
std::unordered_map<std::string /* roomId */, OutboundGroupSession> outboundGroupSessions;
- ByteArray utilityData;
- OlmUtility *utility;
bool valid{true};
- std::size_t checkUtilError(std::size_t code) const;
-
std::string pickle() const;
- void unpickle(std::string data);
+ bool unpickle(std::string data);
+ bool unpickleFromLibolm(std::string data);
- ByteArray identityKeys() const;
std::string ed25519IdentityKey() const;
std::string curve25519IdentityKey() const;
- std::size_t checkError(std::size_t code) const;
-
MaybeString decryptOlm(nlohmann::json content);
// Here we need the full event for eventId and originServerTs
MaybeString decryptMegOlm(nlohmann::json eventJson);
diff --git a/src/crypto/crypto.hpp b/src/crypto/crypto.hpp
--- a/src/crypto/crypto.hpp
+++ b/src/crypto/crypto.hpp
@@ -254,7 +254,7 @@
private:
friend class Session;
- friend class SessionPrivate;
+ friend struct SessionPrivate;
std::unique_ptr<CryptoPrivate> m_d;
};
}
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp
--- a/src/crypto/crypto.cpp
+++ b/src/crypto/crypto.cpp
@@ -10,7 +10,7 @@
#include <zug/transducer/filter.hpp>
-#include <olm/olm.h>
+#include <vodozemac.h>
#include <nlohmann/json.hpp>
@@ -21,7 +21,7 @@
#include "crypto-p.hpp"
#include "session-p.hpp"
-
+#include "crypto-util-p.hpp"
#include "crypto-util.hpp"
#include "time-util.hpp"
@@ -30,77 +30,64 @@
using namespace CryptoConstants;
CryptoPrivate::CryptoPrivate()
- : accountData(olm_account_size(), 0)
- , account(olm_account(accountData.data()))
- , utilityData(olm_utility_size(), '\0')
- , utility(olm_utility(utilityData.data()))
+ : account(std::nullopt)
, valid(false)
{
}
- CryptoPrivate::CryptoPrivate(RandomTag, RandomData data)
- : accountData(olm_account_size(), 0)
- , account(olm_account(accountData.data()))
- , utilityData(olm_utility_size(), '\0')
- , utility(olm_utility(utilityData.data()))
+ CryptoPrivate::CryptoPrivate(RandomTag, [[maybe_unused]] RandomData data)
+ : account(std::nullopt)
+ , valid(true)
{
- auto randLenNeeded = Crypto::constructRandomSize();
- checkError(olm_create_account(account, data.data(), randLenNeeded));
+ account = vodozemac::olm::new_account();
}
CryptoPrivate::~CryptoPrivate()
{
- olm_clear_account(account);
}
CryptoPrivate::CryptoPrivate(const CryptoPrivate &that)
- : accountData(olm_account_size(), 0)
- , account(olm_account(accountData.data()))
+ : account(std::nullopt)
, uploadedOneTimeKeysCount(that.uploadedOneTimeKeysCount)
, numUnpublishedKeys(that.numUnpublishedKeys)
, knownSessions(that.knownSessions)
, inboundGroupSessions(that.inboundGroupSessions)
, outboundGroupSessions(that.outboundGroupSessions)
- , utilityData(olm_utility_size(), '\0')
- , utility(olm_utility(utilityData.data()))
{
- unpickle(that.pickle());
+ if (that.valid) {
+ valid = unpickle(that.pickle());
+ }
}
std::string CryptoPrivate::pickle() const
{
- auto key = ByteArray(3, 'x');
- auto pickleData = std::string(olm_pickle_account_length(account), '\0');
- checkError(olm_pickle_account(account, key.data(), key.size(),
- pickleData.data(), pickleData.size()));
- return pickleData;
+ auto pickleData = account.value()->pickle(VODOZEMAC_PICKLE_KEY);
+ return static_cast<std::string>(pickleData);
}
- void CryptoPrivate::unpickle(std::string pickleData)
+ bool CryptoPrivate::unpickle(std::string pickleData)
{
- auto key = ByteArray(3, 'x');
- checkError(olm_unpickle_account(account, key.data(), key.size(),
- pickleData.data(), pickleData.size()));
+ account = checkVodozemacError([&]() {
+ return vodozemac::olm::account_from_pickle(
+ rust::Str(pickleData),
+ VODOZEMAC_PICKLE_KEY
+ );
+ });
+ return account.has_value();
}
- std::size_t CryptoPrivate::checkError(std::size_t code) const
+ bool CryptoPrivate::unpickleFromLibolm(std::string pickleData)
{
- if (code == olm_error()) {
- kzo.crypto.warn() << "Olm error: " << olm_account_last_error(account) << std::endl;
- }
- return code;
- }
-
- std::size_t CryptoPrivate::checkUtilError(std::size_t code) const
- {
- if (code == olm_error()) {
- kzo.crypto.warn() << "Olm utility error: " << olm_utility_last_error(utility) << std::endl;
- }
- return code;
+ account = checkVodozemacError([&]() {
+ return vodozemac::olm::account_from_libolm_pickle(
+ rust::Str(pickleData),
+ rust::Slice<const unsigned char>(OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size())
+ );
+ });
+ return account.has_value();
}
-
MaybeString CryptoPrivate::decryptOlm(nlohmann::json content)
{
auto theirCurve25519IdentityKey = content.at("sender_key").get<std::string>();
@@ -125,9 +112,13 @@
if (shouldCreateNewSession) {
auto created = createInboundSession(theirCurve25519IdentityKey, body);
+
if (! created) { // cannot create session, thus cannot decrypt
return NotBut("Cannot create session");
}
+
+ auto &session = knownSessions.at(theirCurve25519IdentityKey);
+ return session.m_d->takeFirstDecrypted();
}
auto &session = knownSessions.at(theirCurve25519IdentityKey);
@@ -167,11 +158,10 @@
bool CryptoPrivate::createInboundSession(std::string theirCurve25519IdentityKey,
std::string message)
{
- auto s = Session(InboundSessionTag{}, account,
+ auto s = Session(InboundSessionTag{}, *this,
theirCurve25519IdentityKey, message);
if (s.valid()) {
- checkError(olm_remove_one_time_keys(account, s.m_d->session));
knownSessions.insert_or_assign(theirCurve25519IdentityKey, std::move(s));
return true;
}
@@ -218,13 +208,7 @@
std::size_t Crypto::constructRandomSize()
{
- static std::size_t s =
- [] {
- std::vector<char> acc(olm_account_size(), 0);
- OlmAccount *account = olm_account(acc.data());
- return olm_create_account_random_length(account);
- }();
- return s;
+ return 0;
}
Crypto::Crypto()
@@ -271,27 +255,16 @@
return m_d->valid;
}
- ByteArray CryptoPrivate::identityKeys() const
- {
- auto ret = ByteArray(olm_account_identity_keys_length(account), '\0');
- checkError(olm_account_identity_keys(account, ret.data(), ret.size()));
- return ret;
- }
-
std::string CryptoPrivate::ed25519IdentityKey() const
{
- auto keys = identityKeys();
- auto keyStr = std::string(keys.begin(), keys.end());
- auto keyJson = nlohmann::json::parse(keyStr);
- return keyJson.at(ed25519);
+ auto key = account.value()->ed25519_key()->to_base64();
+ return static_cast<std::string>(key);
}
std::string CryptoPrivate::curve25519IdentityKey() const
{
- auto keys = identityKeys();
- auto keyStr = std::string(keys.begin(), keys.end());
- auto keyJson = nlohmann::json::parse(keyStr);
- return keyJson.at(curve25519);
+ auto key = account.value()->curve25519_key()->to_base64();
+ return static_cast<std::string>(key);
}
std::string Crypto::ed25519IdentityKey() const
@@ -311,15 +284,15 @@
auto str = j.dump();
- auto ret = ByteArray(olm_account_signature_length(m_d->account), '\0');
+ auto signature = checkVodozemacError([&]() {
+ return m_d->account.value()->sign(str);
+ });
- kzo.crypto.dbg() << "We are about to sign: " << str << std::endl;
-
- m_d->checkError(olm_account_sign(m_d->account,
- str.data(), str.size(),
- ret.data(), ret.size()));
+ if (!signature.has_value()) {
+ return "";
+ }
- return std::string{ret.begin(), ret.end()};
+ return static_cast<std::string>(signature.value()->to_base64());
}
void Crypto::setUploadedOneTimeKeysCount(immer::map<std::string /* algorithm */, int> uploadedOneTimeKeysCount)
@@ -329,51 +302,43 @@
std::size_t Crypto::maxNumberOfOneTimeKeys() const
{
- return olm_account_max_number_of_one_time_keys(m_d->account);
+ return m_d->account.value()->max_number_of_one_time_keys();
}
std::size_t Crypto::genOneTimeKeysRandomSize(int num)
{
- static std::size_t oneKeyRandomSize =
- [] {
- std::vector<char> acc(olm_account_size(), 0);
- OlmAccount *account = olm_account(acc.data());
- return olm_account_generate_one_time_keys_random_length(account, 1);
- }();
-
- return oneKeyRandomSize * num;
+ return 0;
}
void Crypto::genOneTimeKeysWithRandom(RandomData random, int num)
{
assert(random.size() >= genOneTimeKeysRandomSize(num));
- auto res = m_d->checkError(
- olm_account_generate_one_time_keys(
- m_d->account,
- num,
- random.data(), random.size()));
-
- if (res != olm_error()) {
- m_d->numUnpublishedKeys += num;
- }
+ m_d->account.value()->generate_one_time_keys(num);
+ m_d->numUnpublishedKeys += num;
}
nlohmann::json Crypto::unpublishedOneTimeKeys() const
{
- auto keys = ByteArray(olm_account_one_time_keys_length(m_d->account), '\0');
- m_d->checkError(olm_account_one_time_keys(m_d->account, keys.data(), keys.size()));
+ auto keys = m_d->account.value()->one_time_keys();
+ auto ret = nlohmann::json{
+ {curve25519, nlohmann::json::object()},
+ };
+
+ for (const auto &k : keys) {
+ auto keyId = static_cast<std::string>(k.key_id);
+ auto key = static_cast<std::string>(k.key->to_base64());
+ ret[curve25519][keyId] = key;
+ }
- return nlohmann::json::parse(std::string(keys.begin(), keys.end()));
+ return ret;
}
void Crypto::markOneTimeKeysAsPublished()
{
- auto ret = m_d->checkError(olm_account_mark_keys_as_published(m_d->account));
- if (ret != olm_error()) {
- m_d->numUnpublishedKeys = 0;
- }
+ m_d->account.value()->mark_keys_as_published();
+ m_d->numUnpublishedKeys = 0;
}
int Crypto::numUnpublishedOneTimeKeys() const
@@ -434,13 +399,15 @@
auto message = object.dump();
- auto res = m_d->checkUtilError(
- olm_ed25519_verify(m_d->utility,
- ed25519Key.c_str(), ed25519Key.size(),
- message.c_str(), message.size(),
- signature.data(), signature.size()));
+ auto res = checkVodozemacError([&]() {
+ auto key = vodozemac::types::ed25519_key_from_base64(ed25519Key);
+ auto sig = vodozemac::types::ed25519_signature_from_base64(signature);
+ key->verify(message, *sig);
+ // It throws if the signature cannot be verified
+ return true;
+ });
- return res != olm_error();
+ return res.has_value() && res.value();
}
MaybeString Crypto::getInboundGroupSessionEd25519KeyFromEvent(const nlohmann::json &eventJson) const
@@ -484,8 +451,7 @@
std::size_t Crypto::encryptOlmMaxRandomSize()
{
- static std::size_t maxRandomSizeNeeded = 32;
- return maxRandomSizeNeeded;
+ return 0;
}
nlohmann::json Crypto::encryptOlmWithRandom(
@@ -608,7 +574,7 @@
auto session = Session(OutboundSessionTag{},
RandomTag{},
random,
- m_d->account,
+ *m_d,
theirIdentityKey,
theirOneTimeKey);
@@ -623,6 +589,7 @@
std::string pickledData = m_d->valid ? m_d->pickle() : std::string();
auto j = nlohmann::json::object({
{"valid", m_d->valid},
+ {"version", 1},
{"account", std::move(pickledData)},
{"uploadedOneTimeKeysCount", m_d->uploadedOneTimeKeysCount},
{"numUnpublishedKeys", m_d->numUnpublishedKeys},
@@ -638,7 +605,13 @@
{
m_d->valid = j.contains("valid") ? j["valid"].template get<bool>() : true;
const auto &pickledData = j.at("account").template get<std::string>();
- if (m_d->valid) { m_d->unpickle(pickledData); }
+ if (m_d->valid) {
+ if (j.contains("version") && j["version"] == 1) {
+ m_d->valid = m_d->unpickle(pickledData);
+ } else {
+ m_d->valid = m_d->unpickleFromLibolm(pickledData);
+ }
+ }
m_d->uploadedOneTimeKeysCount = j.at("uploadedOneTimeKeysCount");
m_d->numUnpublishedKeys = j.at("numUnpublishedKeys");
diff --git a/src/crypto/session-p.hpp b/src/crypto/session-p.hpp
--- a/src/crypto/session-p.hpp
+++ b/src/crypto/session-p.hpp
@@ -1,6 +1,6 @@
/*
* 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
*/
@@ -8,42 +8,38 @@
#include <libkazv-config.hpp>
#include "session.hpp"
+#include <vodozemac.h>
namespace Kazv
{
struct SessionPrivate
{
SessionPrivate();
- SessionPrivate(OutboundSessionTag,
- OlmAccount *acc,
- std::string theirIdentityKey,
- std::string theirOneTimeKey);
SessionPrivate(OutboundSessionTag,
RandomTag,
RandomData data,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string theirOneTimeKey);
SessionPrivate(InboundSessionTag,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string message);
SessionPrivate(const SessionPrivate &that);
~SessionPrivate() = default;
- ByteArray sessionData;
- OlmSession *session{0};
+ std::optional<rust::Box<vodozemac::olm::Session>> session;
bool valid{false};
+ std::optional<std::string> firstDecrypted;
std::string pickle() const;
bool unpickle(std::string data);
+ bool unpickleFromLibolm(std::string data);
- std::size_t checkError(std::size_t code) const;
-
- std::string error() const { return olm_session_last_error(session); }
+ MaybeString takeFirstDecrypted();
};
}
diff --git a/src/crypto/session.hpp b/src/crypto/session.hpp
--- a/src/crypto/session.hpp
+++ b/src/crypto/session.hpp
@@ -10,8 +10,6 @@
#include <memory>
#include <tuple>
-#include <olm/olm.h>
-
#include <maybe.hpp>
#include "crypto-util.hpp"
@@ -24,6 +22,7 @@
struct OutboundSessionTag {};
struct SessionPrivate;
+ struct CryptoPrivate;
class Session
{
/**
@@ -31,13 +30,6 @@
*/
static std::size_t constructOutboundRandomSize();
- // Creates an outbound session
- [[deprecated("Use deterministic variant instead. In the future, this will be removed.")]]
- explicit Session(OutboundSessionTag,
- OlmAccount *acc,
- std::string theirIdentityKey,
- std::string theirOneTimeKey);
-
/**
* Construct an outbound session with custom random data.
*
@@ -47,13 +39,13 @@
explicit Session(OutboundSessionTag,
RandomTag,
RandomData data,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string theirOneTimeKey);
// Creates an inbound session
explicit Session(InboundSessionTag,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string message);
@@ -77,9 +69,6 @@
*/
std::size_t encryptRandomSize() const;
- [[deprecated("Use deterministic variant instead. In the future, this will be removed.")]]
- std::pair<int /* type */, std::string /* message */> encrypt(std::string plainText);
-
/**
* Encrypt plainText.
*
@@ -94,8 +83,8 @@
private:
friend class Crypto;
- friend class CryptoPrivate;
- friend class SessionPrivate;
+ friend struct CryptoPrivate;
+ friend struct SessionPrivate;
friend void to_json(nlohmann::json &j, const Session &s);
friend void from_json(const nlohmann::json &j, Session &s);
diff --git a/src/crypto/session.cpp b/src/crypto/session.cpp
--- a/src/crypto/session.cpp
+++ b/src/crypto/session.cpp
@@ -6,8 +6,6 @@
#include <libkazv-config.hpp>
-#include <olm/olm.h>
-
#include <debug.hpp>
#include "crypto-p.hpp"
@@ -16,158 +14,137 @@
namespace Kazv
{
- std::size_t SessionPrivate::checkError(std::size_t code) const
- {
- if (code == olm_error()) {
- kzo.crypto.warn() << "Olm session error: " << olm_session_last_error(session) << std::endl;
- }
- return code;
- }
-
SessionPrivate::SessionPrivate()
- : sessionData(olm_session_size(), '\0')
- , session(olm_session(sessionData.data()))
- {
- }
-
- SessionPrivate::SessionPrivate(OutboundSessionTag,
- OlmAccount *acc,
- std::string theirIdentityKey,
- std::string theirOneTimeKey)
- : SessionPrivate()
+ : session(std::nullopt)
{
- auto random = genRandom(Session::constructOutboundRandomSize());
-
- auto res = checkError(olm_create_outbound_session(
- session,
- acc,
- theirIdentityKey.c_str(), theirIdentityKey.size(),
- theirOneTimeKey.c_str(), theirOneTimeKey.size(),
- random.data(), random.size()));
-
- if (res != olm_error()) {
- valid = true;
- }
}
SessionPrivate::SessionPrivate(OutboundSessionTag,
RandomTag,
RandomData random,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string theirOneTimeKey)
: SessionPrivate()
{
assert(random.size() >= Session::constructOutboundRandomSize());
- auto res = checkError(olm_create_outbound_session(
- session,
- acc,
- theirIdentityKey.c_str(), theirIdentityKey.size(),
- theirOneTimeKey.c_str(), theirOneTimeKey.size(),
- random.data(), random.size()));
+ session = checkVodozemacError([&]() {
+ auto identityKey = vodozemac::types::curve_key_from_base64(rust::Str(theirIdentityKey));
+ auto oneTimeKey = vodozemac::types::curve_key_from_base64(rust::Str(theirOneTimeKey));
+ return cryptoD.account.value()->create_outbound_session(
+ *identityKey,
+ *oneTimeKey
+ );
+ });
- if (res != olm_error()) {
- valid = true;
- }
+ valid = session.has_value();
}
SessionPrivate::SessionPrivate(InboundSessionTag,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string message)
: SessionPrivate()
{
- auto res = checkError(olm_create_inbound_session_from(
- session,
- acc,
- theirIdentityKey.c_str(), theirIdentityKey.size(),
- message.data(), message.size()));
-
- if (res != olm_error()) {
- valid = true;
+ auto res = checkVodozemacError([&]() {
+ auto identityKey = vodozemac::types::curve_key_from_base64(rust::Str(theirIdentityKey));
+ auto msg = vodozemac::olm::olm_message_from_parts(vodozemac::olm::OlmMessageParts{
+ 0, // pre-key message
+ message,
+ });
+ return cryptoD.account.value()->create_inbound_session(
+ *identityKey,
+ *msg
+ );
+ });
+
+ valid = res.has_value();
+
+ if (valid) {
+ session = std::move(res->session);
+ firstDecrypted = std::string(res->plaintext.begin(), res->plaintext.end());
}
}
SessionPrivate::SessionPrivate(const SessionPrivate &that)
: SessionPrivate()
{
- valid = unpickle(that.pickle());
+ if (that.valid) {
+ valid = unpickle(that.pickle());
+ }
}
std::string SessionPrivate::pickle() const
{
- auto pickleData = std::string(olm_pickle_session_length(session), '\0');
- auto key = ByteArray(3, 'x');
- checkError(olm_pickle_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 SessionPrivate::unpickle(std::string pickleData)
{
- auto key = ByteArray(3, 'x');
- auto res = checkError(olm_unpickle_session(
- session,
- key.data(), key.size(),
- pickleData.data(), pickleData.size()));
+ session = checkVodozemacError([&]() {
+ return vodozemac::olm::session_from_pickle(pickleData, VODOZEMAC_PICKLE_KEY);
+ });
- return res != olm_error();
+ return session.has_value();
}
+ bool SessionPrivate::unpickleFromLibolm(std::string pickleData)
+ {
+ session = checkVodozemacError([&]() {
+ return vodozemac::olm::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 Session::constructOutboundRandomSize()
+ MaybeString SessionPrivate::takeFirstDecrypted()
{
- static size_t s =
- [] {
- ByteArray sessionData(olm_session_size(), '\0');
- OlmSession *session(olm_session(sessionData.data()));
- return olm_create_outbound_session_random_length(session);
- }();
- return s;
+ auto res = std::move(firstDecrypted);
+ firstDecrypted = std::nullopt;
+ if (res.has_value()) {
+ return res.value();
+ } else {
+ return NotBut("No first decrypted available");
+ }
}
- Session::Session()
- : m_d(new SessionPrivate)
+ std::size_t Session::constructOutboundRandomSize()
{
+ return 0;
}
- Session::Session(OutboundSessionTag,
- OlmAccount *acc,
- std::string theirIdentityKey,
- std::string theirOneTimeKey)
- : m_d(new SessionPrivate{
- OutboundSessionTag{},
- acc,
- theirIdentityKey,
- theirOneTimeKey})
+ Session::Session()
+ : m_d(new SessionPrivate)
{
}
Session::Session(OutboundSessionTag,
RandomTag,
RandomData data,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string theirOneTimeKey)
: m_d(new SessionPrivate{
OutboundSessionTag{},
RandomTag{},
std::move(data),
- acc,
+ cryptoD,
theirIdentityKey,
theirOneTimeKey})
{
}
Session::Session(InboundSessionTag,
- OlmAccount *acc,
+ CryptoPrivate &cryptoD,
std::string theirIdentityKey,
std::string theirOneTimeKey)
: m_d(new SessionPrivate{
InboundSessionTag{},
- acc,
+ cryptoD,
theirIdentityKey,
theirOneTimeKey})
{
@@ -200,11 +177,15 @@
bool Session::matches(std::string message)
{
- auto res = m_d->checkError(
- olm_matches_inbound_session(m_d->session, message.data(), message.size()));
-
- // if match, returns 1
- return res == 1;
+ auto res = checkVodozemacError([&]() {
+ auto msg = vodozemac::olm::olm_message_from_parts(vodozemac::olm::OlmMessageParts{
+ 0, // pre-key
+ message,
+ });
+ return m_d->session.value()->session_matches(*msg);
+ });
+
+ return res.has_value() && res.value();
}
bool Session::valid() const
@@ -215,65 +196,48 @@
MaybeString Session::decrypt(int type, std::string message)
{
- auto msgBuffer = ByteArray(message.begin(), message.end());
-
- auto size = m_d->checkError(olm_decrypt_max_plaintext_length(
- m_d->session, type, msgBuffer.data(), msgBuffer.size()));
-
- if (size == olm_error()) {
- return NotBut(m_d->error());
- }
-
- auto plainTextBuffer = ByteArray(size, '\0');
-
- auto actualSize = m_d->checkError(
- olm_decrypt(m_d->session, type,
- message.data(), message.size(),
- plainTextBuffer.data(), plainTextBuffer.size()));
-
- if (actualSize == olm_error()) {
- return NotBut(m_d->error());
+ auto res = checkVodozemacError([&]() {
+ auto msg = vodozemac::olm::olm_message_from_parts(vodozemac::olm::OlmMessageParts{
+ static_cast<std::size_t>(type),
+ message,
+ });
+ return m_d->session.value()->decrypt(*msg);
+ });
+
+ if (!res.has_value()) {
+ return NotBut(res.reason());
}
- return std::string(plainTextBuffer.begin(), plainTextBuffer.begin() + actualSize);
+ return std::string(res.value().begin(), res.value().end());
}
std::size_t Session::encryptRandomSize() const
{
- return olm_encrypt_random_length(m_d->session);
- }
-
- std::pair<int, std::string> Session::encrypt(std::string plainText)
- {
- return encryptWithRandom(genRandomData(encryptRandomSize()), std::move(plainText));
+ return 0;
}
std::pair<int, std::string> Session::encryptWithRandom(RandomData random, std::string plainText)
{
assert(random.size() >= encryptRandomSize());
- auto type = m_d->checkError(olm_encrypt_message_type(m_d->session));
-
- auto size = m_d->checkError(olm_encrypt_message_length(m_d->session, plainText.size()));
+ auto res = checkVodozemacError([&]() {
+ return m_d->session.value()->encrypt(plainText);
+ });
- auto buf = ByteArray(size, '\0');
-
- auto actualSize = m_d->checkError(
- olm_encrypt(m_d->session, plainText.c_str(), plainText.size(),
- random.data(), random.size(),
- buf.data(), buf.size()));
-
- if (actualSize != olm_error()) {
- return { type, std::string(buf.begin(), buf.begin() + actualSize) };
+ if (!res.has_value()) {
+ return { -1, "" };
}
- return { -1, "" };
+ auto [type, msg] = res.value()->to_parts();
+
+ return { type, static_cast<std::string>(msg) };
}
void to_json(nlohmann::json &j, const Session &s)
{
j = nlohmann::json::object({
{"valid", s.m_d->valid},
+ {"version", 1},
{"data", s.m_d->valid ? s.m_d->pickle() : std::string()}
});
}
@@ -281,7 +245,11 @@
void from_json(const nlohmann::json &j, Session &s)
{
if (j.at("valid").template get<bool>()) {
- s.m_d->valid = s.m_d->unpickle(j.at("data"));
+ if (j.contains("version") && j["version"] == 1) {
+ s.m_d->valid = s.m_d->unpickle(j.at("data"));
+ } else {
+ s.m_d->valid = s.m_d->unpickleFromLibolm(j.at("data"));
+ }
}
}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -108,9 +108,9 @@
libkazv_add_tests(
crypto-test.cpp
- crypto/deterministic-test.cpp
crypto/inbound-group-session-test.cpp
crypto/outbound-group-session-test.cpp
+ crypto/session-test.cpp
EXTRA_LINK_LIBRARIES kazvcrypto
)
diff --git a/src/tests/crypto-test.cpp b/src/tests/crypto-test.cpp
--- a/src/tests/crypto-test.cpp
+++ b/src/tests/crypto-test.cpp
@@ -19,6 +19,7 @@
#include <aes-256-ctr.hpp>
#include <base64.hpp>
#include <sha256.hpp>
+#include "crypto/crypto-test-resource.hpp"
using namespace Kazv;
using namespace Kazv::CryptoConstants;
@@ -26,6 +27,17 @@
using IAr = boost::archive::text_iarchive;
using OAr = boost::archive::text_oarchive;
+static const auto resource = cryptoDumpResource();
+
+json makeEncryptedJson(json ciphertext, std::string senderKey)
+{
+ return json{{"content", {
+ {"algorithm", olmAlgo},
+ {"ciphertext", std::move(ciphertext)},
+ {"sender_key", std::move(senderKey)},
+ }}};
+}
+
template<class T>
static void serializeDup(const T &in, T &out)
{
@@ -51,6 +63,46 @@
REQUIRE(crypto2.valid());
}
+TEST_CASE("Crypto conversion from libolm to vodozemac", "[crypto]")
+{
+ Crypto a;
+ a.loadJson(resource["a"]);
+
+ Crypto b;
+ b.loadJson(resource["b"]);
+
+ // encrypt with existing sessions
+ auto aIdKey = a.curve25519IdentityKey();
+ auto origJson = json{{"test", "mew"}};
+ {
+ auto encryptedMsg = b.encryptOlmWithRandom(genRandomData(Crypto::encryptOlmMaxRandomSize()), origJson, aIdKey);
+
+ auto decryptedOpt = a.decrypt(makeEncryptedJson(encryptedMsg, b.curve25519IdentityKey()));
+
+ REQUIRE(decryptedOpt);
+ }
+
+ // encrypt/decrypt with new sessions
+ auto k = a.unpublishedOneTimeKeys();
+ a.markOneTimeKeysAsPublished();
+
+ auto oneTimeKey = std::string{};
+
+ for (auto [id, key] : k[curve25519].items()) {
+ oneTimeKey = key;
+ }
+
+ {
+ Crypto c(RandomTag{}, genRandomData(Crypto::constructRandomSize()));
+ c.createOutboundSessionWithRandom(genRandomData(Crypto::createOutboundSessionRandomSize()), aIdKey, oneTimeKey);
+ auto encryptedMsg = c.encryptOlmWithRandom(genRandomData(Crypto::encryptOlmMaxRandomSize()), origJson, aIdKey);
+ auto decryptedOpt = a.decrypt(makeEncryptedJson(encryptedMsg, c.curve25519IdentityKey()));
+ REQUIRE(decryptedOpt.reason() == "");
+ REQUIRE(decryptedOpt);
+ REQUIRE(decryptedOpt.value() == origJson.dump());
+ }
+}
+
TEST_CASE("Crypto should be copyable", "[crypto]")
{
Crypto crypto(RandomTag{}, genRandomData(Crypto::constructRandomSize()));
diff --git a/src/tests/crypto/deterministic-test.cpp b/src/tests/crypto/deterministic-test.cpp
deleted file mode 100644
--- a/src/tests/crypto/deterministic-test.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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", "[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());
-}
-
-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/session-test.cpp b/src/tests/crypto/session-test.cpp
new file mode 100644
--- /dev/null
+++ b/src/tests/crypto/session-test.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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 <session.hpp>
+#include <crypto.hpp>
+#include "crypto-test-resource.hpp"
+
+using namespace Kazv;
+
+static const auto resource = cryptoDumpResource();
+static const auto sessionAJson = resource["a"]["knownSessions"]["wklSkg9T1gz0pnYDZUmKrVqQXEDGW8HnQV0JDWqzYVs"];
+static const auto sessionBJson = resource["b"]["knownSessions"]["L75F3cTDIM/bw/n11zm73o0+LpNZ5ll+FCbCH8+OETQ"];
+
+TEST_CASE("Session conversion from libolm to vodozemac")
+{
+ auto sessionA = sessionAJson.template get<Session>();
+
+ auto sessionB = sessionBJson.template get<Session>();
+
+ REQUIRE(sessionA.valid());
+ REQUIRE(sessionB.valid());
+
+ {
+ auto [type, message] = sessionA.encryptWithRandom(genRandomData(sessionA.encryptRandomSize()), "mew 1");
+ auto res = sessionB.decrypt(type, message);
+ REQUIRE(res.has_value());
+ REQUIRE(res.value() == "mew 1");
+ }
+
+ {
+ auto [type, message] = sessionB.encryptWithRandom(genRandomData(sessionA.encryptRandomSize()), "mew 2");
+ auto res = sessionA.decrypt(type, message);
+ REQUIRE(res.has_value());
+ REQUIRE(res.value() == "mew 2");
+ }
+}
+
+TEST_CASE("Session::from_json error handling")
+{
+ auto j = sessionAJson;
+ j["data"] = "AAAAAAAAAA";
+ auto sessionA = j.template get<Session>();
+
+ REQUIRE(!sessionA.valid());
+}
+
+TEST_CASE("Session::decrypt error handling")
+{
+ auto sessionA = sessionAJson.template get<Session>();
+
+ auto res = sessionA.decrypt(1, "xxx");
+ REQUIRE(!res.has_value());
+}
+
+TEST_CASE("Session serialization roundtrip")
+{
+ auto sessionA = sessionAJson.template get<Session>();
+ auto j = json(sessionA);
+ sessionA = j.template get<Session>();
+
+ auto sessionB = sessionBJson.template get<Session>();
+ j = json(sessionB);
+ sessionB = j.template get<Session>();
+
+ REQUIRE(sessionA.valid());
+ REQUIRE(sessionB.valid());
+
+ {
+ auto [type, message] = sessionA.encryptWithRandom(genRandomData(sessionA.encryptRandomSize()), "mew 1");
+ auto res = sessionB.decrypt(type, message);
+ REQUIRE(res.has_value());
+ REQUIRE(res.value() == "mew 1");
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 19, 5:20 PM (8 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15963
Default Alt Text
D161.1726791628.diff (38 KB)

Event Timeline