Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F114361
D161.1732540594.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
38 KB
Referenced Files
None
Subscribers
None
D161.1732540594.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 25, 5:16 AM (12 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39925
Default Alt Text
D161.1732540594.diff (38 KB)
Attached To
Mode
D161: Port Crypto and Session to vodozemac
Attached
Detach File
Event Timeline
Log In to Comment