Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,17 @@ set(version_file "${CMAKE_CURRENT_BINARY_DIR}/Version.cpp")
##############################
# Botan #
##############################
find_package(Botan 2.14.0 REQUIRED)
include_directories(${BOTAN_INCLUDE_DIRS})
find_package(Botan 3.7.0 REQUIRED)
# Check if the static target exists; otherwise fallback to the shared target.
if(TARGET Botan::Botan-static)
set(BOTAN_LIBRARY Botan::Botan-static)
message(STATUS "Using Botan static library")
elseif(TARGET Botan::Botan)
set(BOTAN_LIBRARY Botan::Botan)
message(STATUS "Using Botan shared library")
else()
message(FATAL_ERROR "No valid Botan target found")
endif()

##############################
# MySQL Connector C++ #
Expand Down
14 changes: 9 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ RUN apt-get -y update && apt-get -y upgrade \
&& apt-get -y install cmake \
&& apt-get -y install git \
# Install required library packages
&& apt-get install -y libbotan-2-dev \
&& apt-get install -y libbotan-3-dev \
&& apt-get install -y libmysqlcppconn-dev \
&& apt-get install -y zlib1g-dev \
&& apt-get install -y libpcre3-dev \
Expand All @@ -45,15 +45,19 @@ ARG disable_threads=0
ARG build_type=Rel
ARG install_dir=/usr/local/bin

# Patch the Botan config file for header paths: (THIS IS FIXED IN BOTAN 3.8 - REMOVE WHEN apt-get HAS UPDATED)
RUN sh -c 'arch=$(dpkg-architecture -qDEB_HOST_MULTIARCH) && \
BOTAN_CFG=$(find / -type f -iname "botan-config.cmake" 2>/dev/null | grep "/usr/lib/$arch" | head -n1) && \
[ -n "$BOTAN_CFG" ] && \
sed -i -e "s|\${_Botan_PREFIX}/include|/usr/include|g" -e "s|\${_Botan_PREFIX}/lib|/usr/lib/$arch|g" "$BOTAN_CFG"'

# Generate Makefile & compile
RUN --mount=type=cache,target=build \
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=${build_type} \
-DCMAKE_INSTALL_PREFIX=${install_dir} \
-DBUILD_OPT_TOOLS=${build_optional_tools} \
-DDISABLE_EMBER_THREADS=${disable_threads} \
-DBOTAN_ROOT_DIR=/usr/include/botan-2/ \
-DBOTAN_LIBRARY=/usr/lib/x86_64-linux-gnu/libbotan-2.so \
&& cd build && make -j$(nproc) install \
&& make test

Expand All @@ -62,11 +66,11 @@ ARG install_dir=/usr/local/bin
ARG working_dir=/usr/src/ember
WORKDIR ${install_dir}
RUN apt-get -y update \
&& apt-get install -y libbotan-2-19 \
&& apt-get install -y libbotan-3-7 \
&& apt-get install -y libmysqlcppconn7v5 \
&& apt-get install -y mysql-client
COPY --from=builder ${install_dir} ${install_dir}
RUN cp configs/*.dist .
COPY ./sql ${install_dir}/sql
COPY ./scripts ${install_dir}
COPY ./dbcs ${install_dir}/dbcs
COPY ./dbcs ${install_dir}/dbcs
106 changes: 0 additions & 106 deletions cmake/FindBotan.cmake

This file was deleted.

5 changes: 3 additions & 2 deletions src/account/AccountService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ AccountService::handle_session_fetch(const SessionLookup& msg, const Link& link,
return response;
}

auto key = Botan::BigInt::encode(*session);
std::vector<uint8_t> key((*session).bytes());
(*session).serialize_to(std::span<uint8_t>(key.data(), key.size()));

response.status = Status::OK;
response.account_id = msg.account_id();
Expand Down Expand Up @@ -120,4 +121,4 @@ AccountService::handle_disconnect_by_id(const DisconnectID& msg, const Link& lin
return std::nullopt;
}

} // ember
} // ember
4 changes: 2 additions & 2 deletions src/gateway/AccountClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ void AccountClient::handle_locate_response(std::expected<const SessionResponse*,
return;
}

auto key = Botan::BigInt::decode(msg->key()->data(), msg->key()->size());
auto key = Botan::BigInt::from_bytes(std::span<const std::uint8_t>(msg->key()->data(), msg->key()->size()));
cb(msg->status(), std::move(key));
}

} // gateway, ember
} // gateway, ember
4 changes: 2 additions & 2 deletions src/gateway/PacketCrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class PacketCrypto final {
);

key_.resize(key.bytes(), boost::container::default_init);
key.binary_encode(key_.data(), key_.size());
key.serialize_to(std::span<uint8_t>( key_.data() + (key_.size() - key.bytes()), key.bytes() ));
}

inline void encrypt(auto& data) {
Expand Down Expand Up @@ -77,4 +77,4 @@ class PacketCrypto final {
}
};

} // gateway, ember
} // gateway, ember
2 changes: 1 addition & 1 deletion src/gateway/states/Authentication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ void prove_session(ClientContext& ctx, const Botan::BigInt& key) {
key.bytes(), boost::container::default_init
);

key.binary_encode(k_bytes.data(), k_bytes.size());
key.serialize_to(std::span<uint8_t>(k_bytes.data() + (k_bytes.size() - key.bytes()), key.bytes()));

const std::uint32_t protocol_id = 0; // best guess, this is hardcoded to zero in the client
auto& auth_ctx = std::get<Context>(ctx.state_ctx);
Expand Down
4 changes: 2 additions & 2 deletions src/libs/shared/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,5 @@ source_group("Metrics" FILES ${METRICS_SRC})
include_directories(${CMAKE_SOURCE_DIR}/deps/utf8cpp ${PROJECT_BINARY_DIR}/src)
add_library(${LIBRARY_NAME} ${LIBRARY_SRC})
target_include_directories(${LIBRARY_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/)
target_link_libraries(${LIBRARY_NAME} PUBLIC logger conpool ${PCRE_LIBRARY})
set_target_properties(${LIBRARY_NAME} PROPERTIES FOLDER "Common Libraries")
target_link_libraries(${LIBRARY_NAME} PUBLIC logger conpool ${BOTAN_LIBRARY} ${PCRE_LIBRARY})
set_target_properties(${LIBRARY_NAME} PROPERTIES FOLDER "Common Libraries")
7 changes: 4 additions & 3 deletions src/libs/shared/shared/database/daos/mysql/PatchDAO.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class MySQLPatchDAO final : public PatchDAO {

const auto md5 = res->getString("md5");
Botan::BigInt md5_int(md5.asStdString());
Botan::BigInt::encode_1363(meta.file_meta.md5.data(), meta.file_meta.md5.size(), md5_int);
std::fill(meta.file_meta.md5.begin(), meta.file_meta.md5.end(), 0); // 1363 style padding
md5_int.serialize_to({ meta.file_meta.md5.data() + meta.file_meta.md5.size() - md5_int.bytes(), md5_int.bytes() });
patches.emplace_back(std::move(meta));
}

Expand All @@ -87,8 +88,8 @@ class MySQLPatchDAO final : public PatchDAO {
stmt->setBoolean(3, meta.mpq);
stmt->setString(4, meta.file_meta.name);
stmt->setUInt64(5, meta.file_meta.size);
auto md5 = Botan::BigInt::decode(reinterpret_cast<const std::uint8_t*>(meta.file_meta.md5.data()),
meta.file_meta.md5.size());
auto md5 = Botan::BigInt::from_bytes(std::span<const uint8_t>(reinterpret_cast<const std::uint8_t*>(
meta.file_meta.md5.data()), meta.file_meta.md5.size()));

stmt->setString(6, md5.to_hex_string());
stmt->setUInt(7, meta.locale_id);
Expand Down
2 changes: 1 addition & 1 deletion src/libs/srp6/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ add_library(${LIBRARY_NAME}
include/srp6/detail/Primes.h
)

target_link_libraries(${LIBRARY_NAME} PRIVATE ${Boost_LIBRARIES})
target_link_libraries(${LIBRARY_NAME} PRIVATE ${Boost_LIBRARIES} ${BOTAN_LIBRARY})
target_include_directories(${LIBRARY_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
set_target_properties(${LIBRARY_NAME} PROPERTIES FOLDER "Common Libraries")
6 changes: 3 additions & 3 deletions src/libs/srp6/src/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Client::Client(std::string identifier, std::string password, Generator gen, std:
: Client(std::move(identifier),
std::move(password),
gen,
BigInt::decode((AutoSeeded_RNG()).random_vec(key_size)) % gen.prime(),
BigInt::from_bytes(std::span<const uint8_t>{ (AutoSeeded_RNG().random_vec(key_size)).data(), key_size }) % gen.prime(),
srp6a) { }

Client::Client(std::string identifier, std::string password, Generator gen, BigInt a, bool srp6a)
Expand Down Expand Up @@ -64,7 +64,7 @@ SessionKey Client::session_key(const BigInt& B, std::span<const std::uint8_t> sa
return SessionKey(detail::interleaved_hash(detail::encode_flip_1363(S, N.bytes())));
} else {
KeyType key(S.bytes(), boost::container::default_init);
S.binary_encode(key.data(), key.size());
S.serialize_to(std::span<uint8_t>(key.data(), key.size()));
return SessionKey(key);
}
}
Expand All @@ -74,4 +74,4 @@ BigInt Client::generate_proof(const SessionKey& key, const Botan::BigInt& B,
return generate_client_proof(identifier_, key, gen_.prime(), gen_.generator(), A_, B, salt);
}

} // srp6, ember
} // srp6, ember
6 changes: 3 additions & 3 deletions src/libs/srp6/src/Server.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014 - 2024 Ember
* Copyright (c) 2014 - 2025 Ember
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
Expand Down Expand Up @@ -48,7 +48,7 @@ SessionKey Server::session_key(const BigInt& A, Compliance mode, bool interleave
return SessionKey(detail::interleaved_hash(detail::encode_flip_1363(S, N_.bytes())));
} else {
KeyType key(N_.bytes(), boost::container::default_init);
S.binary_encode(key.data(), key.size());
S.serialize_to(std::span<uint8_t>(key.data(), key.size()));
return SessionKey(key);
}
}
Expand All @@ -58,4 +58,4 @@ BigInt Server::generate_proof(const SessionKey& key, const Botan::BigInt& A,
return generate_server_proof(A, client_proof, key, N_.bytes());
}

} // srp6, ember
} // srp6, ember
29 changes: 17 additions & 12 deletions src/libs/srp6/src/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,20 @@ namespace detail {

Botan::BigInt decode_flip(std::span<std::uint8_t> val) {
std::ranges::reverse(val);
return Botan::BigInt::decode(val.data(), val.size());
return Botan::BigInt::from_bytes(std::span<const uint8_t>(val.data(), val.size()));
}

SmallVec encode_flip(const Botan::BigInt& val) {
SmallVec res(val.bytes(), boost::container::default_init);
val.binary_encode(res.data(), res.size());
val.serialize_to(std::span<uint8_t>(res.data(), res.size()));
std::ranges::reverse(res);
return res;
}

SmallVec encode_flip_1363(const Botan::BigInt& val, std::size_t padding) {
SmallVec res(padding, boost::container::default_init);
Botan::BigInt::encode_1363(res.data(), res.size(), val);
std::fill(res.begin(), res.end(), 0); // 1363 style padding
val.serialize_to({ res.data() + res.size() - val.bytes(), val.bytes() });
std::ranges::reverse(res);
return res;
}
Expand Down Expand Up @@ -69,15 +70,15 @@ Botan::BigInt scrambler(const Botan::BigInt& A, const Botan::BigInt& B, std::siz
auto hasher = Botan::HashFunction::create_or_throw("SHA-1");
BOOST_ASSERT_MSG(SHA1_LEN == hasher->output_length(), "Bad hash length");
std::array<std::uint8_t, SHA1_LEN> hash_out;
SmallVec vec(padding, boost::container::default_init);
SmallVec vec(padding, 0); // 1363 style padding

if(mode == Compliance::RFC5054) {
Botan::BigInt::encode_1363(vec.data(), vec.size(), A);
A.serialize_to(std::span<uint8_t>(vec.data(), vec.size()));
hasher->update(vec.data(), vec.size());
Botan::BigInt::encode_1363(vec.data(), vec.size(), B);
B.serialize_to(std::span<uint8_t>(vec.data(), vec.size()));
hasher->update(vec.data(), vec.size());
hasher->final(hash_out.data());
return Botan::BigInt::decode(hash_out.data(), hash_out.size());
return Botan::BigInt::from_bytes(std::span<const uint8_t>(hash_out.data(), hash_out.size()));
} else {
const auto& a_enc = encode_flip_1363(A, padding);
const auto& b_enc = encode_flip_1363(B, padding);
Expand All @@ -93,10 +94,14 @@ Botan::BigInt compute_k(const Botan::BigInt& g, const Botan::BigInt& N) {
std::array<std::uint8_t, SHA1_LEN> hash;
auto hasher = Botan::HashFunction::create_or_throw("SHA-1");
BOOST_ASSERT_MSG(SHA1_LEN == hasher->output_length(), "Bad hash length");
hasher->update(Botan::BigInt::encode(N));
hasher->update(Botan::BigInt::encode_1363(g, N.bytes()));
std::vector<uint8_t> n_buf(N.bytes(), 0); // 1363 style padding
N.serialize_to({ n_buf.data() + n_buf.size() - N.bytes(), N.bytes() });
std::vector<uint8_t> g_buf(N.bytes(), 0); // 1363 style padding
g.serialize_to({ g_buf.data() + g_buf.size() - g.bytes(), g.bytes() });
hasher->update(n_buf.data(), n_buf.size());
hasher->update(g_buf.data(), g_buf.size());
hasher->final(hash.data());
return Botan::BigInt::decode(hash.data(), hash.size());
return Botan::BigInt::from_bytes(std::span<const uint8_t>(hash.data(), hash.size()));
}

Botan::BigInt compute_x(std::string_view identifier, std::string_view password,
Expand All @@ -123,7 +128,7 @@ Botan::BigInt compute_x(std::string_view identifier, std::string_view password,
hasher->final(hash.data());

if(mode == Compliance::RFC5054) {
return Botan::BigInt::decode(hash.data(), hash.size());
return Botan::BigInt::from_bytes(std::span<const uint8_t>(hash.data(), hash.size()));
} else {
return detail::decode_flip(hash);
}
Expand Down Expand Up @@ -194,4 +199,4 @@ Botan::BigInt generate_verifier(std::string_view identifier, std::string_view pa
return detail::generate(identifier, password, generator, salt, mode);
}

} // srp6, ember
} // srp6, ember
Loading