Upgrade ByteVector to new version.

dependabot/npm_and_yarn/Src/WebController/UI/websocket-extensions-0.1.4
Pawel Kurowski 2020-03-13 14:13:19 +01:00
parent 37e357fc21
commit fc53b803ae
33 changed files with 760 additions and 742 deletions

View File

@ -49,6 +49,11 @@
<ClInclude Include="$(MSBuildThisFileDirectory)CppCodec\base32_default_crockford.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)CppCodec\base32_default_crockford.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)CppCodec\base64_default_rfc4648.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)CppCodec\base64_default_rfc4648.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)CppRestSdk\include\cpprest\http_client.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)CppRestSdk\include\cpprest\http_client.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteArray.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteConverter.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteVector.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteView.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\Utils.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)json\json.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)json\json.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)libSodium\include\sodium.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)libSodium\include\sodium.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\Slack.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\Slack.h" />
@ -63,10 +68,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Peripherals\Mock.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Peripherals\Mock.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\PrecompiledHeader.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\PrecompiledHeader.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Sdk.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Sdk.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteArray.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteVector.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteView.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Compression.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Compression.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Encryption.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Encryption.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Hash.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Hash.h" />

View File

@ -83,14 +83,15 @@
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\WinTools\StructuredExceptionHandling.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\WinTools\StructuredExceptionHandling.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)C3_BUILD_VERSION_HASH_PART.hxx" /> <ClInclude Include="$(MSBuildThisFileDirectory)C3_BUILD_VERSION_HASH_PART.hxx" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\WinTools\InjectionBuffer.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\WinTools\InjectionBuffer.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteArray.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteVector.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteView.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Utils.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Utils.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Peripherals\Grunt.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Peripherals\Grunt.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)zlib\include\zconf.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)zlib\include\zconf.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)zlib\include\zlib.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)zlib\include\zlib.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Compression.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\Compression.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\Utils.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteView.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteVector.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteConverter.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\CppTools\ByteConverter\ByteArray.h" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,6 +1,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Beacon.h" #include "Beacon.h"
using namespace FSecure::Literals;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::C3::Interfaces::Peripherals::Beacon::Beacon(ByteView arguments) FSecure::C3::Interfaces::Peripherals::Beacon::Beacon(ByteView arguments)
{ {

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Common/FSecure/CppTools/ByteView.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
namespace FSecure namespace FSecure
{ {

View File

@ -1,418 +0,0 @@
#pragma once
#include <map>
#include <filesystem>
#include "ByteView.h"
/// Example code of specializing ByteConverter for custom type A.
/// struct A
/// {
/// uint16_t m_a, m_b;
///
/// A(uint16_t a, uint16_t b) : m_a(a), m_b(b) {}
/// };
///
/// namespace FSecure
/// {
/// template <>
/// struct ByteConverter<A>
/// {
/// static ByteVector To(A const& a)
/// {
/// return ByteVector::Create(a.m_a, a.m_b);
/// }
///
/// static size_t Size(A const& a)
/// {
/// return 2 * sizeof(uint16_t);
/// }
///
/// static A From(ByteView& bv)
/// {
/// auto [a, b] = bv.Read<uint16_t, uint16_t>();
/// return A(a, b);
/// }
/// };
/// }
/// specializations for ByteConverter for common types.
namespace FSecure
{
/// ByteConverter specialization for enum.
template <typename T>
struct ByteConverter<T, std::enable_if_t<std::is_enum_v<T>>>
{
/// Serialize enum type to ByteVector.
/// @param enumInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(T enumInstance)
{
return ByteVector::Create(static_cast<std::underlying_type_t<T>>(enumInstance));
}
/// Get size required after serialization.
/// @return size_t. Number of bytes used after serialization.
constexpr static size_t Size()
{
return sizeof(std::underlying_type_t<T>);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return enum.
static T From(ByteView& bv)
{
return static_cast<T>(bv.Read<std::underlying_type_t<T>>());
}
};
/// ByteConverter specialization for std::pair<>.
template <typename T1, typename T2>
struct ByteConverter<std::pair<T1, T2>>
{
/// Serialize pair type to ByteVector.
/// @param pairInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(std::pair<T1, T2> const& pairInstance)
{
return ByteVector::Create(pairInstance.first, pairInstance.second);
}
/// Get size required after serialization.
/// @param pairInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(std::pair<T1, T2> const& pairInstance)
{
return ByteVector::Size(pairInstance.first) + ByteVector::Size(pairInstance.second);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::pair.
static std::pair<T1, T2> From(ByteView& bv)
{
auto [t1, t2] = bv.Read<T1, T2>();
return { std::move(t1), std::move(t2) };
}
};
/// ByteConverter specialization for std::filesystem::path.
template <>
struct ByteConverter<std::filesystem::path>
{
/// Serialize path type to ByteVector.
/// @param pathInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(std::filesystem::path const& pathInstance)
{
return ByteVector::Create(pathInstance.wstring());
}
/// Get size required after serialization.
/// @param pathInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(std::filesystem::path const& pathInstance)
{
return ByteVector::Size(pathInstance.wstring());
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::filesystem::path.
static std::filesystem::path From(ByteView& bv)
{
return { bv.Read<std::wstring>() };
}
};
/// ByteConverter specialization for std::byte.
template <>
struct ByteConverter<std::byte>
{
/// Serialize byte type to ByteVector.
/// @param byteInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(std::byte byteInstance)
{
return ByteVector::Create(static_cast<unsigned char>(byteInstance));
}
/// Get size required after serialization.
/// @return size_t. Number of bytes used after serialization.
constexpr static size_t Size()
{
return sizeof(unsigned char);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::byte.
static std::byte From(ByteView& bv)
{
return static_cast<std::byte>(bv.Read<unsigned char>());
}
};
/// Class allowing reading N bytes without coping data like in ByeView::Read<ByteArray<N>>() or ByteView::Reed(size_t).
/// Using Bytes class in read will return ByteView with requested size using simple syntax:
/// @code someByteViewObject.Read<int, int, Bytes<7>, std::string> @endCode
template<size_t N>
class Bytes
{
/// This class should never be instantiated.
Bytes() = delete;
};
/// ByteConverter specialization for FSecure::Bytes.
template <size_t N>
struct ByteConverter<FSecure::Bytes<N>>
{
/// Retrieve ByteView substring with requested size.
/// @param bv. Buffer with serialized data. Will be moved by N bytes.
/// @return ByteView new view with size equal to N.
static ByteView From(ByteView& bv)
{
if (N > bv.size())
throw std::out_of_range{ OBF(": Cannot read data from ByteView") };
auto retVal = bv.SubString(0, N);
bv.remove_prefix(N);
return retVal;
}
};
/// ByteConverter specialization for vector types.
template <typename T>
struct ByteConverter<std::vector<T>>
{
/// Serialize vector type to ByteVector.
/// @param vectorInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(std::vector<T> const& vectorInstance)
{
ByteVector ret;
ret.reserve(ByteVector::Size(vectorInstance));
ret.Write(static_cast<uint32_t>(vectorInstance.size()));
for (auto const& e : vectorInstance)
ret.Concat(ByteVector::Create(e));
return ret;
}
/// Get size required after serialization.
/// @param vectorInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(std::vector<T> const& vectorInstance)
{
size_t size = sizeof(uint32_t); //four bytes for vector size.
for (auto const& e : vectorInstance)
size += ByteVector::Size(e);
return size;
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::vector.
static std::vector<T> From(ByteView& bv)
{
std::vector<T> ret;
auto size = bv.Read<uint32_t>();
ret.reserve(size);
for (auto i = 0u; i < size; ++i)
ret.push_back(bv.Read<T>());
return ret;
}
};
/// ByteConverter specialization for map types.
template <typename T1, typename T2>
struct ByteConverter<std::map<T1, T2>>
{
/// Serialize map type to ByteVector.
/// @param mapInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(std::map<T1, T2> const& mapInstance)
{
ByteVector ret;
ret.reserve(ByteVector::Size(mapInstance));
ret.Write(static_cast<uint32_t>(mapInstance.size()));
for (auto const& [key, val] : mapInstance)
ret.Concat(ByteVector::Create(key, val));
return ret;
}
/// Get size required after serialization.
/// @param mapInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(std::map<T1, T2> const& mapInstance)
{
size_t size = sizeof(uint32_t); //four bytes for map size.
for (auto const& [key, val] : mapInstance)
size += ByteVector::Size(key) + ByteVector::Size(val);
return size;
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::map.
static std::map<T1, T2> From(ByteView& bv)
{
std::map<T1, T2> ret;
auto size = bv.Read<uint32_t>();
for (auto i = 0u; i < size; ++i)
{
auto [key, val] = bv.Read<T1, T2>();
ret.emplace(std::move(key), std::move(val));
}
return ret;
}
};
/// ByteConverter specialization for std:array.
template <typename T, size_t N>
struct ByteConverter<std::array<T, N>>
{
/// Serialize array type to ByteVector.
/// @param arrayInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(std::array<T, N> const& arrayInstance)
{
ByteVector ret;
ret.reserve(ByteVector::Size(arrayInstance));
for (auto const& e : arrayInstance)
ret.Write(e);
return ret;
}
/// Get size required after serialization.
/// @param arrayInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(std::array<T, N> const& arrayInstance)
{
auto ret = size_t{ 0 };
if constexpr (std::is_arithmetic_v<T>)
{
static_cast<void>(arrayInstance);
ret = sizeof(T) * N; // avoid extra calls when size of array is known.
}
else
{
for (auto const& e : arrayInstance)
ret += ByteVector::Size(e);
}
return ret;
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::array.
static std::array<T, N> From(ByteView& bv)
{
std::vector<T> temp;
temp.reserve(N);
for (auto i = 0u; i < N; ++i)
temp.push_back(bv.Read<T>());
return MakeArray(std::move(temp), std::make_index_sequence<N>());
}
private:
/// Create array with size N from provided vector.
/// This helper function is required because T might not be default constructible, but array must be filled like aggregator.
/// Reading data to vector first will ensure order of elements, independent of calling convention.
/// @param vec. Temporary vector with data.
/// @returns std::array with all elements.
template<size_t...Is>
static std::array<T, N> MakeArray(std::vector<T>&& vec, std::index_sequence<Is...>)
{
return { std::move(vec[Is])... };
}
};
/// ByteConverter specialization for tuple.
template <typename T>
struct ByteConverter<T, std::enable_if_t<Utils::IsTuple<T>>>
{
/// Serialize tuple type to ByteVector.
/// @param tupleInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(T const& tupleInstance)
{
ByteVector ret;
ret.reserve(Size(tupleInstance));
TupleHandler<T>::Write(ret, tupleInstance);
return ret;
}
/// Get size required after serialization.
/// @param tupleInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(T const& tupleInstance)
{
return TupleHandler<T>::Size(tupleInstance);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::tuple.
static auto From(ByteView& bv)
{
return TupleHandler<T>::Read(bv);
}
private:
/// @tparam T. Tuple type to read/write.
/// @tparam N. How many elements of tuple to handle. Functions will use recursion, decrementing N with each call.
template <typename T, size_t N = std::tuple_size_v<T>>
struct TupleHandler
{
/// Function responsible for recursively packing data to ByteVector.
/// @param self. Reference to ByteVector object using TupleHandler.
/// @param t. reference to tuple.
static void Write(ByteVector& self, T const& t)
{
if constexpr (N != 0)
{
self.Write(std::get<std::tuple_size_v<T> - N>(t));
TupleHandler<T, N - 1>::Write(self, t);
}
}
/// Function responsible for recursively calculating buffer size needed for call with tuple argument.
/// @param t. reference to tuple.
/// @return size_t number of bytes needed.
static size_t Size(T const& t)
{
if constexpr (N != 0)
return ByteVector::Size(std::get<std::tuple_size_v<T> - N>(t)) + TupleHandler<T, N - 1>::Size(t);
else
return 0;
}
/// Function responsible for recursively packing data to tuple.
/// @param self. Reference to ByteView object using generate method.
static auto Read(ByteView& self)
{
if constexpr (N != 0)
{
auto current = std::make_tuple(self.Read<std::tuple_element_t<std::tuple_size_v<T> - N, T>>());
auto rest = TupleHandler<T, N - 1>::Read(self);
return std::tuple_cat(current, rest);
}
else
{
return std::tuple<>{};
}
}
};
};
}

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <array>
namespace FSecure namespace FSecure
{ {
/// Owning container with size known at compilation time. /// Owning container with size known at compilation time.

View File

@ -0,0 +1,291 @@
#pragma once
#include <filesystem>
#include "ByteView.h"
/// specializations for ByteConverter for common types.
namespace FSecure
{
/// ByteConverter specialization for arithmetic types.
template <typename T>
struct ByteConverter<T, std::enable_if_t<std::is_arithmetic_v<T>>>
{
/// Serialize arithmetic type to ByteVector.
/// @param obj. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(T obj)
{
auto ret = ByteVector{};
ret.resize(sizeof(T));
*reinterpret_cast<T*>(ret.data()) = obj;
return ret;
}
/// Get size required after serialization.
/// @return size_t. Number of bytes used after serialization.
constexpr static size_t Size()
{
return sizeof(T);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return arithmetic type.
static T From(ByteView& bv)
{
T ret;
memcpy(&ret, bv.data(), sizeof(T));
bv.remove_prefix(sizeof(T));
return ret;
}
};
/// ByteConverter specialization for enum.
template <typename T>
struct ByteConverter<T, std::enable_if_t<std::is_enum_v<T>>>
{
/// Serialize enum type to ByteVector.
/// @param enumInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(T enumInstance)
{
return ByteVector::Create(static_cast<std::underlying_type_t<T>>(enumInstance));
}
/// Get size required after serialization.
/// @return size_t. Number of bytes used after serialization.
constexpr static size_t Size()
{
return sizeof(std::underlying_type_t<T>);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return enum.
static T From(ByteView& bv)
{
return static_cast<T>(bv.Read<std::underlying_type_t<T>>());
}
};
/// ByteConverter specialization for iterable types.
template <typename T>
struct ByteConverter<T, std::enable_if_t<Utils::Container::IsIterable<T>::value>>
{
/// Serialize iterable type to ByteVector.
/// @param obj. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(T const& obj)
{
auto ret = ByteVector{};
ret.reserve(ByteVector::Size(obj));
if (auto numberOfElements = Utils::Container::Size<T>::Calculate(obj); numberOfElements <= std::numeric_limits<uint32_t>::max())
ret.Write(static_cast<uint32_t>(numberOfElements));
else
throw std::out_of_range{ OBF(": Cannot write size to ByteVector ") };
for (auto&& e : obj)
ret.Write(e);
return ret;
}
/// Get size required after serialization.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(T const& obj)
{
using Element = Utils::Container::StoredValue<T>;
auto ret = sizeof(uint32_t);
if constexpr (ByteSizeFunctionType<Element>::value == ByteSizeFunctionType<Element>::compileTime)
ret += ByteConverter<Element>::Size() * obj.size(); // avoid extra calls when size of stored type is known at compile time
else
for (auto const& e : obj)
ret += ByteVector::Size(e);
return ret;
}
/// Deserialize from ByteView.
/// Writing to ByteVector is similar for any iterable type, but container construction can heavily differ.
/// Utils::Container::Generator is used for unification of this process.
/// @param bv. Buffer with serialized data.
/// @return iterable type.
static T From(ByteView& bv)
{
if (sizeof(uint32_t) > bv.size())
throw std::out_of_range{ OBF(": Cannot read size from ByteView ") };
if constexpr (Utils::Container::GeneratorSignature<T>::value == Utils::Container::GeneratorSignature<T>::queuedAccess)
{
return Utils::Container::Generator<T>{}(bv.Read<uint32_t>(), [&bv] { return bv.Read<Utils::Container::StoredValue<T>>(); } );
}
else if constexpr (Utils::Container::GeneratorSignature<T>::value == Utils::Container::GeneratorSignature<T>::directMemoryAccess)
{
auto size = bv.Read<uint32_t>();
auto data = bv.data();
auto ret = Utils::Container::Generator<T>{}(size, reinterpret_cast<const char**>(&data));
bv.remove_prefix(data - bv.data());
return ret;
}
static_assert(Utils::Container::GeneratorSignature<T>::value != Utils::Container::GeneratorSignature<T>::other, "Unable to find container generator for provided type");
}
};
/// ByteConverter specialization for std::filesystem::path.
template <>
struct ByteConverter<std::filesystem::path>
{
/// Serialize path type to ByteVector.
/// @param pathInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(std::filesystem::path const& pathInstance)
{
return ByteVector::Create(pathInstance.wstring());
}
/// Get size required after serialization.
/// @param pathInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(std::filesystem::path const& pathInstance)
{
return ByteVector::Size(pathInstance.wstring());
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::filesystem::path.
static std::filesystem::path From(ByteView& bv)
{
return { bv.Read<std::wstring>() };
}
};
/// Tag allowing reading N bytes from ByteView.
/// Provides simpler way of joining multiple reads than ByteView::Reed(size_t).
/// @code someByteViewObject.Read<int, int, Bytes<7>, std::string> @endCode
/// Size must be known at compile time.
/// Using Bytes class in read will return ByteView, or ByteVector, depending on HardCopy template argument.
template<size_t N, bool HardCopy = false>
class Bytes
{
/// This class should never be instantiated.
Bytes() = delete;
static constexpr bool Copy = HardCopy;
};
/// Tag always coping data.
template<size_t N>
using BytesCopy = Bytes<N, true>;
/// ByteConverter specialization for FSecure::Bytes.
template <size_t N, bool HardCopy>
struct ByteConverter<Bytes<N, HardCopy>>
{
/// Retrieve ByteView substring with requested size.
/// @param bv. Buffer with serialized data. Will be moved by N bytes.
/// @return ByteView new view with size equal to N.
static auto From(ByteView& bv) -> std::conditional_t<HardCopy, ByteVector, ByteView>
{
if (N > bv.size())
throw std::out_of_range{ OBF(": Cannot read data from ByteView") };
auto retVal = bv.SubString(0, N);
bv.remove_prefix(N);
return retVal;
}
};
/// ByteConverter specialization for tuple.
template <typename T>
struct ByteConverter<T, std::enable_if_t<Utils::IsTuple<T>>>
{
/// Serialize tuple type to ByteVector.
/// @param tupleInstance. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(T const& tupleInstance)
{
ByteVector ret;
ret.reserve(Size(tupleInstance));
TupleHandler<T>::Write(ret, tupleInstance);
return ret;
}
/// Get size required after serialization.
/// @param tupleInstance. Instance for which size should be found.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(T const& tupleInstance)
{
return TupleHandler<T>::Size(tupleInstance);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return std::tuple.
static auto From(ByteView& bv)
{
return TupleHandler<T>::ReadExplicit(bv);
}
private:
/// @tparam T. Tuple type to read/write.
/// @tparam N. How many elements of tuple to handle. Functions will use recursion, decrementing N with each call.
template <typename T, size_t N = std::tuple_size_v<T>>
struct TupleHandler
{
/// Function responsible for recursively packing data to ByteVector.
/// @param self. Reference to ByteVector object using TupleHandler.
/// @param t. reference to tuple.
static void Write(ByteVector& self, T const& t)
{
if constexpr (N != 0)
{
self.Write(std::get<std::tuple_size_v<T> - N>(t));
TupleHandler<T, N - 1>::Write(self, t);
}
}
/// Function responsible for recursively calculating buffer size needed for call with tuple argument.
/// @param t. reference to tuple.
/// @return size_t number of bytes needed.
static size_t Size(T const& t)
{
if constexpr (N != 0)
return ByteVector::Size(std::get<std::tuple_size_v<T> - N>(t)) + TupleHandler<T, N - 1>::Size(t);
else
return 0;
}
/// C++ allows cast from pair to tuple of two, but not other way around.
/// This is oversight, because pair is much older concept than tuple, and no proposition was made to expand old type.
/// This function ensures, that TupleHandler always returns requested type, so no cast is necessary.
static T ReadExplicit(ByteView& self)
{
auto tmp = Read(self);
if constexpr (Utils::IsPair<T>)
return { std::get<0>(tmp), std::get<1>(tmp) };
else
return tmp;
}
/// Function responsible for recursively packing data to tuple.
/// @param self. Reference to ByteView object using generate method.
static auto Read(ByteView& self)
{
if constexpr (N != 0)
{
auto current = std::make_tuple(self.Read<std::tuple_element_t<std::tuple_size_v<T> - N, T>>());
auto rest = TupleHandler<T, N - 1>::Read(self);
return std::tuple_cat(current, rest);
}
else
{
return std::tuple<>{};
}
}
};
};
}

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "Utils.h" #include "Utils.h"
#include <limits>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@ -141,8 +143,8 @@ namespace FSecure
friend inline bool operator!=(ByteVector const& lhs, ByteVector const& rhs); friend inline bool operator!=(ByteVector const& lhs, ByteVector const& rhs);
/// Write content of of provided objects. /// Write content of of provided objects.
/// Suports arithmetic types, std::string, std::wstring, std::string_view, std::wstring_view, ByteVector and ByteView. /// Supports arithmetic types, and basic iterable types.
/// Include ByteConverter.h to add support for common types like enum, std::vector, std:map, std::pair, std::tuple and others. /// Include ByteConverter.h to add support for common types like enum, std::tuple and others.
/// Create specialization on ByteConverter for custom types or template types to expand existing serialization functionality. /// Create specialization on ByteConverter for custom types or template types to expand existing serialization functionality.
/// @param arg. Object to be stored. /// @param arg. Object to be stored.
/// @param args. Optional other objects to be stored. /// @param args. Optional other objects to be stored.
@ -173,19 +175,6 @@ namespace FSecure
return *this; return *this;
} }
// Some versions of msvc can handle fold expression in debug mode, but fails with internal compiler error in release.
// For this reason recursive version is used as deafult.
//template <typename ...T, typename = std::enable_if_t<((Utils::IsOneOf<T, ByteView, ByteVector>::value && ...))>>
//ByteVector& Concat(T const& ...args)
//{
// auto oldSize = size();
// auto foldSize = (args.size() + ...);
// resize(oldSize + foldSize);
// auto ptr = data() + oldSize;
// ((memcpy(ptr, args.data(), args.size()), (ptr += args.size())), ...);
// return *this;
//}
/// Create new ByteVector with Variadic list of parameters. /// Create new ByteVector with Variadic list of parameters.
/// This function cannot be constructor, because it would be ambiguous with super class constructors. /// This function cannot be constructor, because it would be ambiguous with super class constructors.
/// @param arg. Object to be stored. /// @param arg. Object to be stored.
@ -197,7 +186,6 @@ namespace FSecure
return ByteVector{}.Write(arg, args...); return ByteVector{}.Write(arg, args...);
} }
/// Calculate the size that the argument will take in memory /// Calculate the size that the argument will take in memory
/// @param arg. Argument to be stored. /// @param arg. Argument to be stored.
/// @param args. Rest of types that will be handled with recursion. /// @param args. Rest of types that will be handled with recursion.
@ -221,7 +209,7 @@ namespace FSecure
/// @param args. Rest of objects that will be handled with recursion. /// @param args. Rest of objects that will be handled with recursion.
/// @return itself to allow chaining. /// @return itself to allow chaining.
template<typename T, typename ...Ts, typename std::enable_if_t<std::is_same_v<decltype(FSecure::ByteConverter<T>::To(std::declval<T>())), FSecure::ByteVector >, int> = 0> template<typename T, typename ...Ts, typename std::enable_if_t<std::is_same_v<decltype(FSecure::ByteConverter<T>::To(std::declval<T>())), FSecure::ByteVector >, int> = 0>
ByteVector& Store(T const& arg, Ts const& ...args) ByteVector & Store(T const& arg, Ts const& ...args)
{ {
Concat(FSecure::ByteConverter<T>::To(arg)); Concat(FSecure::ByteConverter<T>::To(arg));
@ -232,53 +220,6 @@ namespace FSecure
} }
}; };
/// ByteConverter specialization for ByteVector, ByteView, std::string, std::string_view, std::wstring, std::wstring_view.
/// This is a basic functionality that should be available with ByteVector. This specialization will not be moved to ByteConverter.h.
template <typename T>
struct ByteConverter<T, std::enable_if_t<Utils::IsOneOf<T, ByteVector, ByteView, std::string, std::string_view, std::wstring, std::wstring_view>::value>>
{
static ByteVector To(T const& obj)
{
auto ret = ByteVector{};
auto elementSize = static_cast<uint32_t>(obj.size());
ret.resize(Size(obj));
memcpy(ret.data(), &elementSize, sizeof(elementSize));
memcpy(ret.data() + sizeof(elementSize), obj.data(), elementSize * sizeof(typename T::value_type));
return ret;
}
static size_t Size(T const& obj)
{
return sizeof(uint32_t) + (obj.size() * sizeof(typename T::value_type));
}
// Reading functions are part of ByteView implementation. To deserialize data include ByteView.h
static T From(ByteView& bv);
};
/// ByteConverter specialization for arithmetic types.
/// This is a basic functionality that should be available with ByteVector. This specialization will not be moved to ByteConverter.h.
template <typename T>
struct ByteConverter<T, std::enable_if_t<std::is_arithmetic_v<T>>>
{
static ByteVector To(T obj)
{
auto ret = ByteVector{};
ret.resize(sizeof(T));
*reinterpret_cast<T*>(ret.data()) = obj;
return ret;
}
constexpr static size_t Size()
{
return sizeof(T);
}
// Reading functions are part of ByteView implementation. To deserialize data include ByteView.h
static T From(ByteView& bv);
};
namespace Literals namespace Literals
{ {
/// Create ByteVector with syntax ""_bvec /// Create ByteVector with syntax ""_bvec

View File

@ -156,9 +156,9 @@ namespace FSecure
/// Read object and move ByteView to position after parsed data. /// Read object and move ByteView to position after parsed data.
/// @tparam T. Mandatory type to be retrieved from ByteView. /// @tparam T. Mandatory type to be retrieved from ByteView.
/// @tparam Ts. Optional types to be retrieved in one call. /// @tparam Ts. Optional types to be retrieved in one call.
/// @note Suports arithmetic types, std::string, std::wstring, std::string_view, std::wstring_view, ByteVector and ByteView. /// @note Works with types and templates that have specialized ByteConverter.
/// Include ByteConverter.h to add support for common types like enum, std::vector, std:map, std::pair, std::tuple and others. /// Include ByteConverter.h to add support for arithmetic, iterable, tuple and other standard types.
/// Create specialization on ByteConverter for custom types or template types to expand existing functionality. /// Create new specializations for custom types.
/// @returns one type if Ts was empty, std::tuple with all types otherwise. /// @returns one type if Ts was empty, std::tuple with all types otherwise.
/// Simple usage: /// Simple usage:
/// @code auto [a, b, c] = someByteView.Read<int, float, std::string>(); @endcode /// @code auto [a, b, c] = someByteView.Read<int, float, std::string>(); @endcode
@ -174,41 +174,79 @@ namespace FSecure
return std::make_tuple(std::move(current), Read<Ts...>()); return std::make_tuple(std::move(current), Read<Ts...>());
else else
return std::tuple_cat(std::make_tuple(std::move(current)), Read<Ts...>()); return std::tuple_cat(std::make_tuple(std::move(current)), Read<Ts...>());
} }
}; };
/// ByteConverter::From specialization for arithmetic types. /// Helper class for Reading data from ByteView.
/// This is a basic functionality that should be available with ByteView. This specialization will not be moved to ByteConverter.h. class ByteReader
template <typename T>
T ByteConverter<T, std::enable_if_t<Utils::IsOneOf<T, ByteVector, ByteView, std::string, std::string_view, std::wstring, std::wstring_view>::value>>::From(ByteView& bv)
{ {
if (sizeof(uint32_t) > bv.size()) /// Reference to ByteView with data.
throw std::out_of_range{ OBF(": Cannot read size from ByteView ") }; /// ByteReader will modify ByteView used for it construction.
ByteView& m_byteView;
auto elementCount = *reinterpret_cast<const uint32_t*>(bv.data()); /// Declaration of base template used for pointer to member type deduction.
auto byteCount = elementCount * sizeof(typename T::value_type); template<class T>
bv.remove_prefix(sizeof(uint32_t)); struct SplitMemberPointer;
T retVal; /// Specialization that will perform type deduction.
if constexpr (Utils::IsOneOf<T, ByteVector, std::string, std::wstring>::value) template<class C, class T>
retVal.resize(elementCount), std::memcpy(retVal.data(), bv.data(), byteCount); struct SplitMemberPointer<T C::*> {
else using type = T;
retVal = T{ reinterpret_cast<typename T::value_type const*>(bv.data()), elementCount }; using declaringType = C;
};
bv.remove_prefix(byteCount); /// Function used to call constructor of type T with tuple of types matching constructor arguments.
return retVal; template<typename T, typename Tpl, size_t... Is>
static T TupleToConstructor(Tpl&& tpl, std::integer_sequence<size_t, Is...>)
{
return T{ std::get<Is>(std::move(tpl))... };
} }
/// ByteConverter::from specialization for ByteVector, ByteView, std::string, std::string_view, std::wstring, std::wstring_view. public:
/// This is a basic functionality that should be available with ByteView. This specialization will not be moved to ByteConverter.h. /// Create ByteReader.
template <typename T> /// @param bv, ByteView with data to read.
T ByteConverter<T, std::enable_if_t<std::is_arithmetic_v<T>>>::From(ByteView& bv) ByteReader(ByteView& bv)
: m_byteView{bv}
{}
/// Read each of arguments from ByteView.
/// @param ts, arguments to tie, and read.
template <typename ...Ts>
void Read(Ts&... ts)
{ {
T ret; ((ts = m_byteView.Read<decltype(ts)>()), ...);
memcpy(&ret, bv.data(), sizeof(T)); }
bv.remove_prefix(sizeof(T));
return ret; /// Create object by reading provided types, and passing them to object constructor.
/// @tparam T, type to be constructed.
/// @tparam Ts, types to be read from ByteView, and passed as T constructor arguments.
/// @note T is not the same as first template parameter of Create(...).
template <typename T, typename ...Ts>
auto Create() -> decltype(T{ std::declval<Ts>()... })
{
return TupleToConstructor<T>(m_byteView.Read<Ts...>(), std::make_index_sequence<sizeof...(Ts)>{});
}
/// Create object by reading provided types deduced from pointers to members
/// @tparam T, first pointer to member. Ensures that at least one object will be read from ByteView
/// @tparam Ts, rest of pointers to members.
/// @note T is not the same as first template parameter of Create(void).
template <typename T, typename ...Ts>
auto Create(T, Ts...) -> decltype(SplitMemberPointer<T>::declaringType{ std::declval<SplitMemberPointer<T>::type>(), std::declval<SplitMemberPointer<Ts>::type>()... })
{
return TupleToConstructor<SplitMemberPointer<T>::declaringType>(m_byteView.Read<SplitMemberPointer<T>::type, SplitMemberPointer<Ts>::type...>(), std::make_index_sequence<1 + sizeof...(Ts)>{});
}
};
namespace Utils
{
/// ByteView is a view.
template <>
struct IsView<ByteView>
{
constexpr static bool value = true;
};
} }
namespace Literals namespace Literals

View File

@ -0,0 +1,225 @@
#pragma once
#include <string_view>
#include <type_traits>
#include <utility>
#include <functional>
#include <array>
#include <vector>
#ifndef OBF
# define OBF(x) x
#endif // !OBF
namespace FSecure::Utils
{
/// Prevents compiler from optimizing out call.
/// @param ptr pointer to memory to be cleared.
/// @param n number of bytes to overwrite.
inline void* SecureMemzero(void* ptr, size_t n)
{
if (ptr) for (auto p = reinterpret_cast<volatile char*>(ptr); n--; *p++ = 0);
return ptr;
}
/// Template to evaluate if T is one of Ts types.
template <typename T, typename ...Ts>
struct IsOneOf
{
constexpr static bool value = [](bool ret) { return ret; }((std::is_same_v<T, Ts> || ...));
};
/// Template to strip type out of const, volatile and reference.
template <typename T>
using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
/// Idioms for detecting tuple types.
template <typename T>
constexpr bool IsTuple = false;
template<typename ...T>
constexpr bool IsTuple<std::tuple<T...>> = true;
template<typename ...T>
constexpr bool IsTuple<std::pair<T...>> = true;
template<typename T>
constexpr bool IsPair = false;
template<typename ...T>
constexpr bool IsPair<std::pair<T...>> = true;
/// Check if type is designed to view data owned by other container.
template <typename T, typename = void>
struct IsView
{
constexpr static bool value = false;
};
/// Every basic_string_view is a view.
template <typename T>
struct IsView<std::basic_string_view<T>, void>
{
constexpr static bool value = true;
};
/// Namespace full of helpers for containers template programing.
namespace Container
{
/// Get type stored by container that uses iterators.
template <typename T>
using StoredValue = RemoveCVR<decltype(*begin(std::declval<T>()))>;
/// Check if type can be iterated with begin() and end().
template <typename T>
class IsIterable
{
template <typename C> static uint8_t test(std::void_t<decltype(begin(std::declval<C>()), end(std::declval<C>()))>*);
template <typename C> static uint16_t test(...);
public:
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(uint8_t));
};
/// Check if type have own implementation of size method.
template <typename T>
class Size
{
template <typename C> static uint8_t test(std::void_t<decltype(size(std::declval<C>()))>*);
template <typename C> static uint16_t test(...);
public:
static constexpr bool HasDedicatedImplementation = (sizeof(test<T>(0)) == sizeof(uint8_t));
static size_t Calculate(std::enable_if_t<HasDedicatedImplementation || IsIterable<T>::value, T> const& obj)
{
size_t count = 0;
if constexpr (HasDedicatedImplementation) count = size(obj);
else for (auto it = obj.begin(); it != obj.end(); ++it, ++count);
return count;
}
};
/// Check if type have insert(iterator, value) function.
template <typename T>
class HasInsert
{
template <typename C> static uint8_t test(std::void_t<decltype(std::declval<C>().insert(begin(std::declval<C>()), *end(std::declval<C>())))>*);
template <typename C> static uint16_t test(...);
public:
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(uint8_t));
};
/// Check if type can reserve some space to avoid reallocations.
template <typename T>
class HasReserve
{
template <typename C> static uint8_t test(std::void_t<decltype(std::declval<C>().reserve(size_t{}))>*);
template <typename C> static uint16_t test(...);
public:
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(uint8_t));
};
/// Struct to generalize container construction.
/// Defines one of allowed operators that will return requested container.
/// @tparam T. Type to be constructed.
/// @tparam unnamed typename with default value, to allow easy creation of partial specializations.
template <typename T, typename = void>
struct Generator
{
/// Form with queued access to each of container values.
/// @param size. Defines numbers of elements in constructed container.
/// @param next. Functor returning one of container values at a time.
// T operator()(uint32_t size, std::function<StoredValue<T>()> next);
/// Form with direct access to memory.
/// @param size. Defines numbers of elements in constructed container.
/// @param data. Allows access to data used to container generation.
/// Dereferenced pointer should be changed, to represent number of bytes consumed for container generation.
// T operator()(uint32_t size, const char** data)
};
/// Generator for any container that have insert method.
template <typename T>
struct Generator<T, std::enable_if_t<HasInsert<T>::value>>
{
/// Form with queued access to each of container values.
/// @param size. Defines numbers of elements in constructed container.
/// @param next. Functor returning one of container values at a time.
T operator()(uint32_t size, std::function<StoredValue<T>()> next)
{
T ret;
if constexpr (HasReserve<T>::value)
{
ret.reserve(size);
}
for (auto i = 0u; i < size; ++i)
ret.insert(ret.end(), next());
return ret;
}
};
/// Generator for any container that is simmilar to std::basic_string_view.
template <typename T>
struct Generator<T, std::enable_if_t<IsView<T>::value>>
{
/// Form with direct access to memory.
/// @param size. Defines numbers of elements in constructed container.
/// @param data. Allows access to data used to container generation.
/// Dereferenced pointer should be changed, to represent number of bytes consumed for container generation.
T operator()(uint32_t size, const char** data)
{
auto ptr = reinterpret_cast<const T::value_type*>(*data);
*data += size * sizeof(typename T::value_type);
return { ptr, size };
}
};
/// Generator for any array types.
template <typename T, size_t N>
struct Generator<std::array<T, N>>
{
/// Form with queued access to each of container values.
/// @param size. Defines numbers of elements in constructed container.
/// @param next. Functor returning one of container values at a time.
std::array<T, N> operator()(uint32_t size, std::function<T()> next)
{
if (size != N)
throw std::runtime_error{ OBF("Array size does not match declaration") };
std::vector<T> temp;
temp.reserve(N);
for (auto i = 0u; i < N; ++i)
temp.push_back(next());
return MakeArray(std::move(temp), std::make_index_sequence<N>());
}
private:
/// Create array with size N from provided vector.
/// This helper function is required because T might not be default constructible, but array must be filled like aggregator.
/// Reading data to vector first will ensure order of elements, independent of calling convention.
/// @param obj. Temporary vector with data.
/// @returns std::array with all elements.
template<size_t... Is>
std::array<T, N> MakeArray(std::vector<T>&& obj, std::index_sequence<Is...>)
{
return { std::move(obj[Is])... };
}
};
/// Used to detect form of Generator operator() at compile time.
template <typename T>
class GeneratorSignature
{
template <typename C> static uint32_t test(std::void_t<decltype(Generator<C>{}(std::declval<uint32_t>(), std::declval<std::function<StoredValue<C>()>>()))>*);
template <typename C> static uint16_t test(std::void_t<decltype(Generator<C>{}(std::declval<uint32_t>(), std::declval<const char**>()))>*);
template <typename C> static uint8_t test(...);
public:
enum { other = 0, directMemoryAccess = (sizeof(uint16_t) - sizeof(uint8_t)), queuedAccess = (sizeof(uint32_t) - sizeof(uint8_t)) };
enum { value = (sizeof(test<T>(0)) - sizeof(uint8_t)) };
};
}
}

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "ByteView.h" #include "ByteConverter/ByteView.h"
namespace FSecure::Compression namespace FSecure::Compression
{ {

View File

@ -1,9 +1,6 @@
#pragma once #pragma once
#include "ByteView.h" #include "ByteConverter/ByteView.h"
#include "ByteVector.h"
//
namespace FSecure::Encryption namespace FSecure::Encryption
{ {

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "ByteView.h" #include "ByteConverter/ByteConverter.h"
#include "Encryption.h" #include "Encryption.h"
#define FSECURE_PAYLOAD_GUID "15e3eda3-74c8-43d5-a4a1-e2e039542240" #define FSECURE_PAYLOAD_GUID "15e3eda3-74c8-43d5-a4a1-e2e039542240"

View File

@ -15,7 +15,8 @@
#include "Common/ADVobfuscator/MetaString.h" #include "Common/ADVobfuscator/MetaString.h"
#define BYTEVECTOR_ZERO_MEMORY_DESTRUCTION //< Increase OpSec by clearing memory when ByteVector is destructed. #define BYTEVECTOR_ZERO_MEMORY_DESTRUCTION //< Increase OpSec by clearing memory when ByteVector is destructed.
#include "ByteConverter.h" //< For ByteView, ByteVector and ByteConverter specializations for common types. #include "ByteConverter/ByteConverter.h" //< For ByteView, ByteVector and ByteConverter specializations for common types.
#include "Utils.h" //< For common templates and helpers

View File

@ -22,17 +22,6 @@ namespace FSecure::Utils
# endif # endif
} }
/// Template to evaluate if T is one of Ts types.
template <typename T, typename ...Ts>
struct IsOneOf
{
constexpr static bool value = [](bool ret) { return ret; }((std::is_same_v<T, Ts> || ...));
};
/// Template to strip type out of const, volatile and reference.
template <typename T>
using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
/// Changes value to default if it is out of provided range. /// Changes value to default if it is out of provided range.
/// @param value to be clamped. /// @param value to be clamped.
/// @param minValue lowest accepted value. /// @param minValue lowest accepted value.
@ -60,7 +49,7 @@ namespace FSecure::Utils
/// Generate random string. /// Generate random string.
/// @param size of returned string. /// @param size of returned string.
template <typename T = std::string, std::enable_if_t<IsOneOf<T, std::string, std::wstring>::value, int> = 0> template <typename T = std::string, std::enable_if_t<std::is_same_v<T, std::string> || std::is_same_v<T, std::wstring>, int> = 0>
T GenerateRandomString(size_t size) T GenerateRandomString(size_t size)
{ {
constexpr std::string_view charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; constexpr std::string_view charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@ -78,7 +67,7 @@ namespace FSecure::Utils
/// Generate random data. /// Generate random data.
/// @param size of returned string. /// @param size of returned string.
template <typename T = std::vector<uint8_t>, std::enable_if_t<IsOneOf<T, std::vector<uint8_t>, std::string>::value, int> = 0> template <typename T = std::vector<uint8_t>, std::enable_if_t<std::is_same_v<T, std::string> || std::is_same_v<T, std::vector<uint8_t>>, int> = 0>
T GenerateRandomData(size_t size) T GenerateRandomData(size_t size)
{ {
static std::random_device rd; static std::random_device rd;
@ -246,19 +235,4 @@ namespace FSecure::Utils
return retValue; return retValue;
} }
/// Idiom for detecting tuple types.
template <typename T>
constexpr bool IsTuple = false;
template<typename ...T>
constexpr bool IsTuple<std::tuple<T...>> = true;
/// Prevents compiler from optimizing out call.
/// @param ptr pointer to memory to be cleared.
/// @param n number of bytes to overwrite.
inline void* SecureMemzero(void* ptr, size_t n)
{
if (ptr) for (auto p = reinterpret_cast<volatile char*>(ptr); n--; *p++ = 0);
return ptr;
}
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Common/FSecure/CppTools/ByteView.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
namespace FSecure::Crypto namespace FSecure::Crypto
{ {

View File

@ -1,8 +1,7 @@
#pragma once #pragma once
#include "Socket.h" #include "Socket.h"
#include "Common/FSecure/CppTools/ByteVector.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
#include "Common/FSecure/CppTools/ByteView.h"
namespace FSecure namespace FSecure
{ {

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "AddrInfo.h" #include "AddrInfo.h"
#include "Common/FSecure/CppTools/ByteVector.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
namespace FSecure namespace FSecure
{ {

View File

@ -37,7 +37,8 @@ namespace FSecure
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HostInfo::HostInfo() : m_OsVersionInfo{ sizeof m_OsVersionInfo } HostInfo::HostInfo()
: m_OsVersionInfo{ sizeof(m_OsVersionInfo) }
{ {
// Reserve buffers for winapi calls. // Reserve buffers for winapi calls.
DWORD computerNameBufferLength = MAX_COMPUTERNAME_LENGTH + 1, userNameBufferLength = UNLEN + 1; DWORD computerNameBufferLength = MAX_COMPUTERNAME_LENGTH + 1, userNameBufferLength = UNLEN + 1;
@ -75,29 +76,15 @@ namespace FSecure
} }
} }
HostInfo::HostInfo(ByteView bv) HostInfo::HostInfo(std::string computerName, std::string userName, std::string domain, OSVERSIONINFOEXA osVersionInfo, DWORD processId, bool isElevated)
: m_ComputerName(bv.Read<std::string>()) : m_ComputerName{ std::move(computerName) }
, m_UserName(bv.Read<std::string>()) , m_UserName{ std::move(userName) }
, m_Domain(bv.Read<std::string>()) , m_Domain{ std::move(domain) }
, m_OsVersionInfo , m_OsVersionInfo{ std::move(osVersionInfo) }
{ [&] , m_ProcessId(processId)
{ , m_IsElevated(isElevated)
decltype(m_OsVersionInfo) osv{sizeof osv};
std::tie
(
osv.dwMajorVersion,
osv.dwMinorVersion,
osv.dwBuildNumber,
osv.wServicePackMajor,
osv.wServicePackMinor,
osv.wProductType
) = bv.Read<DWORD, DWORD, DWORD, WORD, WORD, BYTE>();
return osv;
}()
}
, m_ProcessId(bv.Read<decltype(m_ProcessId)>())
, m_IsElevated(bv.Read<bool>())
{ {
} }
HostInfo::HostInfo(const json& json) HostInfo::HostInfo(const json& json)
@ -115,25 +102,6 @@ namespace FSecure
json.at("IsElevated").get_to(m_IsElevated); json.at("IsElevated").get_to(m_IsElevated);
} }
ByteVector HostInfo::ToByteVector() const
{
return ByteVector{}
.Write
(
m_ComputerName,
m_UserName,
m_Domain,
m_OsVersionInfo.dwMajorVersion,
m_OsVersionInfo.dwMinorVersion,
m_OsVersionInfo.dwBuildNumber,
m_OsVersionInfo.wServicePackMajor,
m_OsVersionInfo.wServicePackMinor,
m_OsVersionInfo.wProductType,
m_ProcessId,
m_IsElevated
);
}
std::ostream& operator<<(std::ostream& os, HostInfo const& hi) std::ostream& operator<<(std::ostream& os, HostInfo const& hi)
{ {
return os << "Computer name:\t" << hi.m_ComputerName << '\n' return os << "Computer name:\t" << hi.m_ComputerName << '\n'

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Common/json/json.hpp" #include "Common/json/json.hpp"
#include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
namespace FSecure namespace FSecure
@ -17,20 +18,15 @@ namespace FSecure
DWORD m_ProcessId; ///< Process Id DWORD m_ProcessId; ///< Process Id
bool m_IsElevated; ///< Is process run with elevated rights bool m_IsElevated; ///< Is process run with elevated rights
/// Gather host information /// Gather info about host.
HostInfo(); HostInfo();
/// Deserializing constructor from json /// Aggregate constructor.
HostInfo(std::string computerName, std::string userName, std::string domain, OSVERSIONINFOEXA osVersionInfo, DWORD processId, bool isElevated);
/// Constructor from json
/// @param json to read from /// @param json to read from
HostInfo(const json& json); HostInfo(const json& json);
/// Deserializing constructor from ByteView
/// @param byte view n to read from
HostInfo(ByteView bv);
/// Serialize to ByteVector
/// @returns ByteVector representation of host information
ByteVector ToByteVector() const;
}; };
/// Overload ostream operator << for HostInfo /// Overload ostream operator << for HostInfo
@ -42,4 +38,80 @@ namespace FSecure
/// @param json to write to /// @param json to write to
/// @param host info to write /// @param host info to write
void to_json(json& j, const HostInfo& hi); void to_json(json& j, const HostInfo& hi);
/// overload ByteConverter for OSVERSIONINFOEXA
template<>
struct ByteConverter<OSVERSIONINFOEXA>
{
/// Serialize HostInfo type to ByteVector.
/// @param obj. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(OSVERSIONINFOEXA const& obj)
{
auto ret = ByteVector{};
ret.reserve(ByteVector::Size(obj));
ret.Write(obj.dwOSVersionInfoSize, obj.dwMajorVersion, obj.dwMinorVersion, obj.dwBuildNumber, obj.dwPlatformId);
ret.Concat(ByteVector{ obj.szCSDVersion, obj.szCSDVersion + sizeof(obj.szCSDVersion) });
ret.Write(obj.wServicePackMajor, obj.wServicePackMinor, obj.wSuiteMask, obj.wProductType);
return ret;
}
/// Get size required after serialization.
/// @param obj. Object to be serialized.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(OSVERSIONINFOEXA const& obj)
{
auto ret = ByteVector::Size(obj.dwOSVersionInfoSize, obj.dwMajorVersion, obj.dwMinorVersion, obj.dwBuildNumber, obj.dwPlatformId);
ret += sizeof(obj.szCSDVersion);
ret += ByteVector::Size(obj.wServicePackMajor, obj.wServicePackMinor, obj.wSuiteMask, obj.wProductType);
return ret;
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return OSVERSIONINFOEXA.
static OSVERSIONINFOEXA From(ByteView& bv)
{
OSVERSIONINFOEXA obj;
ByteReader br{ bv };
br.Read(obj.dwOSVersionInfoSize, obj.dwMajorVersion, obj.dwMinorVersion, obj.dwBuildNumber, obj.dwPlatformId);
memcpy(obj.szCSDVersion, bv.data(), sizeof(obj.szCSDVersion));
bv.remove_prefix(sizeof(obj.szCSDVersion));
br.Read(obj.wServicePackMajor, obj.wServicePackMinor, obj.wSuiteMask, obj.wProductType);
return obj;
}
};
/// overload ByteConverter for HostInfo
template<>
struct ByteConverter<HostInfo>
{
/// Serialize HostInfo type to ByteVector.
/// @param obj. Object to be serialized.
/// @return ByteVector. Serialized data.
static ByteVector To(HostInfo const& obj)
{
auto ret = ByteVector{};
ret.reserve(ByteVector::Size(obj));
ret.Write(obj.m_ComputerName, obj.m_UserName, obj.m_Domain, obj.m_OsVersionInfo, obj.m_ProcessId, obj.m_IsElevated);
return ret;
}
/// Get size required after serialization.
/// @param obj. Object to be serialized.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(HostInfo const& obj)
{
return ByteVector::Size(obj.m_ComputerName, obj.m_UserName, obj.m_Domain, obj.m_OsVersionInfo, obj.m_ProcessId, obj.m_IsElevated);
}
/// Deserialize from ByteView.
/// @param bv. Buffer with serialized data.
/// @return arithmetic type.
static HostInfo From(ByteView& bv)
{
using T = HostInfo;
return ByteReader{ bv }.Create(&T::m_ComputerName, &T::m_UserName, &T::m_Domain, &T::m_OsVersionInfo, &T::m_ProcessId, &T::m_IsElevated);
}
};
} }

View File

@ -114,7 +114,7 @@ std::shared_ptr<FSecure::C3::Relay> FSecure::C3::Utils::CreateGatewayFromConfigu
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<FSecure::C3::Relay> FSecure::C3::Utils::CreateNodeRelayFromImagePatch(LoggerCallback callbackOnLog, InterfaceFactory& interfaceFactory, ByteView buildId, ByteView gatewaySignature, ByteView broadcastKey, std::vector<ByteVector> const& gatewayInitialPackets) std::shared_ptr<FSecure::C3::Relay> FSecure::C3::Utils::CreateNodeRelayFromImagePatch(LoggerCallback callbackOnLog, InterfaceFactory& interfaceFactory, ByteView buildId, ByteView gatewaySignature, ByteView broadcastKey, std::vector<ByteVector> const& gatewayInitialPackets)
{ {
return Core::NodeRelay::CreateAndRun(callbackOnLog, interfaceFactory, gatewaySignature, broadcastKey, gatewayInitialPackets, buildId); return Core::NodeRelay::CreateAndRun(callbackOnLog, interfaceFactory, gatewaySignature, broadcastKey, gatewayInitialPackets, buildId.Read<BuildId>());
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -33,7 +33,7 @@ void FSecure::C3::Core::ConnectorBridge::TurnOff()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::ConnectorBridge::PostCommandToBinder(ByteView binderId, ByteView command) void FSecure::C3::Core::ConnectorBridge::PostCommandToBinder(ByteView binderId, ByteView command)
{ {
return GetGateRelay()->PostCommandToPeripheral(command, RouteId(binderId)); return GetGateRelay()->PostCommandToPeripheral(command, binderId.Read<RouteId>());
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Distributor.h" #include "Distributor.h"
#include "DeviceBridge.h" #include "DeviceBridge.h"
#include "Common/FSecure/CppTools/ByteView.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::C3::Core::Distributor::Distributor(LoggerCallback callbackOnLog, Crypto::PrivateKey const& decryptionKey, Crypto::SymmetricKey const& broadcastKey) FSecure::C3::Core::Distributor::Distributor(LoggerCallback callbackOnLog, Crypto::PrivateKey const& decryptionKey, Crypto::SymmetricKey const& broadcastKey)
@ -68,17 +68,19 @@ void FSecure::C3::Core::Distributor::OnProtocolN2N(ByteView packet0, std::shared
if (packet0.size() < 1 + RouteId::BinarySize + 1) if (packet0.size() < 1 + RouteId::BinarySize + 1)
throw std::invalid_argument{ OBF("N2N packet too short.") }; throw std::invalid_argument{ OBF("N2N packet too short.") };
packet0.remove_prefix(1);
// Parse neighbor identifier and check whether is banned. // Parse neighbor identifier and check whether is banned.
auto neighborRouteId = RouteId(packet0.SubString(1)); auto neighborRouteId = packet0.Read<RouteId>();
if (IsAgentBanned(neighborRouteId.GetAgentId())) if (IsAgentBanned(neighborRouteId.GetAgentId()))
return Log({ OBF("Received packet from a banned Agent ") + neighborRouteId.ToString() + OBF("."), LogMessage::Severity::Warning }); return Log({ OBF("Received packet from a banned Agent ") + neighborRouteId.ToString() + OBF("."), LogMessage::Severity::Warning });
// Handle Procedure part. // Handle Procedure part.
return ProceduresN2N::RequestHandler::ParseRequestAndHandleIt(sender, neighborRouteId, packet0.SubString(1 + RouteId::BinarySize)); return ProceduresN2N::RequestHandler::ParseRequestAndHandleIt(sender, neighborRouteId, packet0);
} }
catch (std::exception & exception) catch (std::exception & exception)
{ {
throw std::runtime_error{ OBF_STR("Failed to parse N2N packet. ") +exception.what() }; throw std::runtime_error{ OBF_STR("Failed to parse N2N packet. ") + exception.what() };
} }
} }

View File

@ -46,12 +46,13 @@ void FSecure::C3::Core::GateRelay::OnProtocolS2G(ByteView packet0, std::shared_p
{ {
try try
{ {
auto decrypted = FSecure::Crypto::DecryptFromAnonymous(packet0.SubString(1), m_AuthenticationKey, m_DecryptionKey); packet0.remove_prefix(1);
auto decrypted = FSecure::Crypto::DecryptFromAnonymous(packet0, m_AuthenticationKey, m_DecryptionKey);
auto [procedure, rid, timestamp] = ByteView{ decrypted }.Read<ProceduresUnderlyingType, RouteId, int32_t>(); auto [procedure, rid, timestamp] = ByteView{ decrypted }.Read<ProceduresUnderlyingType, RouteId, int32_t>();
if (!m_Profiler->Get().m_Gateway.ConnectionExist(rid.GetAgentId())) if (!m_Profiler->Get().m_Gateway.ConnectionExist(rid.GetAgentId()))
throw std::runtime_error{ "S2G packet received from not connected source." }; throw std::runtime_error{ "S2G packet received from not connected source." };
ProceduresS2G::RequestHandler::ParseRequestAndHandleIt(sender, procedure, rid, timestamp, packet0.SubString(1)); ProceduresS2G::RequestHandler::ParseRequestAndHandleIt(sender, procedure, rid, timestamp, packet0);
} }
catch (std::exception& exception) catch (std::exception& exception)
{ {
@ -79,7 +80,7 @@ void FSecure::C3::Core::GateRelay::PostCommandToConnector(ByteView command, std:
if (!connector) if (!connector)
throw std::runtime_error{ "Connector not found" }; throw std::runtime_error{ "Connector not found" };
connector->OnCommandFromBinder(RouteId{ GetAgentId(), senderPeripheral->GetDid() }.ToByteVector(), command); connector->OnCommandFromBinder(ByteVector::Create(RouteId{ GetAgentId(), senderPeripheral->GetDid() }), command);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -295,7 +296,7 @@ void FSecure::C3::Core::GateRelay::On(ProceduresN2N::InitializeRouteQuery query)
auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteView>() }; auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteView>() };
auto hash = readView.Read<HashT>(); auto hash = readView.Read<HashT>();
auto lastSeen = readView.Read<int32_t>(); auto lastSeen = readView.Read<int32_t>();
HostInfo hostInfo(readView.Read<ByteView>()); auto hostInfo = readView.Read<HostInfo>();
auto receivedFrom = query.GetSenderChannel().lock(); auto receivedFrom = query.GetSenderChannel().lock();
if (!receivedFrom) if (!receivedFrom)
@ -327,7 +328,7 @@ void FSecure::C3::Core::GateRelay::On(ProceduresS2G::InitializeRouteQuery query)
auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteView>() }; auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteView>() };
auto hash = readView.Read<HashT>(); auto hash = readView.Read<HashT>();
auto lastSeen = readView.Read<int32_t>(); auto lastSeen = readView.Read<int32_t>();
HostInfo hostInfo(readView.Read<ByteView>()); auto hostInfo= readView.Read<HostInfo>();
auto receivedFrom = query.GetSenderChannel().lock(); auto receivedFrom = query.GetSenderChannel().lock();
if (!receivedFrom) if (!receivedFrom)
@ -363,7 +364,7 @@ void FSecure::C3::Core::GateRelay::On(ProceduresS2G::DeliverToBinder query)
if (!connector) if (!connector)
throw std::runtime_error{ "Connector not found" }; throw std::runtime_error{ "Connector not found" };
auto binder = RouteId{ senderRid.GetAgentId(), deviceId }.ToByteVector(); auto binder = ByteVector::Create(RouteId{ senderRid.GetAgentId(), deviceId });
connector->OnCommandFromBinder(binder, readView); connector->OnCommandFromBinder(binder, readView);
m_Profiler->Get().m_Gateway.UpdateRouteTimestamps(senderRid.GetAgentId(), timestamp); m_Profiler->Get().m_Gateway.UpdateRouteTimestamps(senderRid.GetAgentId(), timestamp);

View File

@ -30,10 +30,6 @@ namespace FSecure::C3
/// @notes this specialization exist only to satisfy implicit casts requirements. /// @notes this specialization exist only to satisfy implicit casts requirements.
Identifier(std::string const& textId); Identifier(std::string const& textId);
/// Creates an ID object from a ByteView.
/// @param byteId a ByteView containing the identifier.
Identifier(ByteView byteId);
/// Creates an ID object with a random ("unique") value. /// Creates an ID object with a random ("unique") value.
/// @return Identifier object. /// @return Identifier object.
static Identifier GenerateRandom(); static Identifier GenerateRandom();
@ -42,10 +38,6 @@ namespace FSecure::C3
/// @return a string that describes this ID object. /// @return a string that describes this ID object.
std::string ToString() const; std::string ToString() const;
/// Converts this ID to a byte vector.
/// @return a byte vector that describes this ID object.
ByteVector ToByteVector() const;
/// Converts identifier to underlying type. /// Converts identifier to underlying type.
/// @returns UnderlyingIntegerType identifier in arithmetic form. /// @returns UnderlyingIntegerType identifier in arithmetic form.
UnderlyingIntegerType ToUnderlyingType() const; UnderlyingIntegerType ToUnderlyingType() const;
@ -87,31 +79,5 @@ namespace FSecure::C3
using BuildId = Identifier<std::uint32_t>; ///< ID of Relay's configuration. using BuildId = Identifier<std::uint32_t>; ///< ID of Relay's configuration.
} }
namespace FSecure
{
/// Specialize ByteConverter for identifiers.
template <typename T>
struct ByteConverter <C3::Identifier<T>>
{
static ByteVector To(C3::Identifier<T> const& obj)
{
return obj.ToByteVector();
}
static size_t Size(C3::Identifier<T> const& obj)
{
return C3::Identifier<T>::BinarySize;
}
static C3::Identifier<T> From(ByteView& bv)
{
auto ret = C3::Identifier<T>(bv.SubString(0, C3::Identifier<T>::BinarySize));
bv.remove_prefix(C3::Identifier<T>::BinarySize);
return ret;
}
};
}
// Include template's implementation. // Include template's implementation.
#include "Identifiers.hxx" #include "Identifiers.hxx"

View File

@ -41,18 +41,6 @@ FSecure::C3::Identifier<UnderlyingIntegerType>::Identifier(std::string const& te
{ {
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename UnderlyingIntegerType>
FSecure::C3::Identifier<UnderlyingIntegerType>::Identifier(ByteView byteId)
{
// Sanity check.
if (byteId.size() != BinarySize)
throw std::runtime_error{ OBF("Invalid byte Identifier size.") };
// Just make a byte-to-byte copy.
memcpy(&m_Id, byteId.data(), sizeof(m_Id));
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename UnderlyingIntegerType> template<typename UnderlyingIntegerType>
FSecure::C3::Identifier<UnderlyingIntegerType> FSecure::C3::Identifier<UnderlyingIntegerType>::GenerateRandom() FSecure::C3::Identifier<UnderlyingIntegerType> FSecure::C3::Identifier<UnderlyingIntegerType>::GenerateRandom()
@ -77,13 +65,6 @@ std::string FSecure::C3::Identifier<UnderlyingIntegerType>::ToString() const
return ret.substr(0, sizeof(UnderlyingIntegerType) * 2); return ret.substr(0, sizeof(UnderlyingIntegerType) * 2);
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename UnderlyingIntegerType>
FSecure::ByteVector FSecure::C3::Identifier<UnderlyingIntegerType>::ToByteVector() const
{
return { reinterpret_cast<const std::uint8_t*>(&m_Id), reinterpret_cast<const std::uint8_t*>(&m_Id) + sizeof(m_Id) };
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename UnderlyingIntegerType> template<typename UnderlyingIntegerType>
bool FSecure::C3::Identifier<UnderlyingIntegerType>::operator!() const bool FSecure::C3::Identifier<UnderlyingIntegerType>::operator!() const
@ -124,3 +105,26 @@ UnderlyingIntegerType FSecure::C3::Identifier<UnderlyingIntegerType>::ToUnderlyi
{ {
return m_Id; return m_Id;
} }
namespace FSecure
{
/// Specialize ByteConverter for identifiers.
template <typename T>
struct ByteConverter <C3::Identifier<T>>
{
static ByteVector To(C3::Identifier<T> const& obj)
{
return ByteVector::Create(obj.ToUnderlyingType());
}
static size_t Size()
{
return sizeof(C3::Identifier<T>::UnderlyingIntegerType);
}
static C3::Identifier<T> From(ByteView& bv)
{
return bv.Read<C3::Identifier<T>::UnderlyingIntegerType>();
}
};
}

View File

@ -1,7 +1,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "NodeRelay.h" #include "NodeRelay.h"
#include "DeviceBridge.h" #include "DeviceBridge.h"
#include "Common/FSecure/CppTools/ByteView.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<FSecure::C3::Core::NodeRelay> FSecure::C3::Core::NodeRelay::CreateAndRun(LoggerCallback callbackOnLog, InterfaceFactory& interfaceFactory, std::shared_ptr<FSecure::C3::Core::NodeRelay> FSecure::C3::Core::NodeRelay::CreateAndRun(LoggerCallback callbackOnLog, InterfaceFactory& interfaceFactory,

View File

@ -99,7 +99,7 @@ namespace FSecure::C3::Core
/// @return buffer containing composed header. /// @return buffer containing composed header.
ByteVector CompileProtocolHeader() const override ByteVector CompileProtocolHeader() const override
{ {
return ByteVector{}.Write(static_cast<ProtocolsUnderlyingType>(Protocols::N2N), m_SendersRid.ToByteArray()); return ByteVector{}.Write(static_cast<ProtocolsUnderlyingType>(Protocols::N2N), m_SendersRid);
} }
private: private:
@ -135,7 +135,7 @@ namespace FSecure::C3::Core
static std::unique_ptr<InitializeRouteQuery> Create(RouteId sendersRid, BuildId buildId, Crypto::PublicKey gatewayEncryptionKey, Crypto::PublicKey agentsPublicEncryptionKey, HashT grcHash, int32_t timestamp, ResponseType responseType = ResponseType::None) static std::unique_ptr<InitializeRouteQuery> Create(RouteId sendersRid, BuildId buildId, Crypto::PublicKey gatewayEncryptionKey, Crypto::PublicKey agentsPublicEncryptionKey, HashT grcHash, int32_t timestamp, ResponseType responseType = ResponseType::None)
{ {
auto query = std::make_unique<InitializeRouteQuery>(sendersRid, responseType); auto query = std::make_unique<InitializeRouteQuery>(sendersRid, responseType);
query->m_QueryPacketBody = Crypto::EncryptAnonymously(buildId.ToByteVector().Write(agentsPublicEncryptionKey.ToByteVector(), grcHash, timestamp, HostInfo().ToByteVector()), gatewayEncryptionKey); query->m_QueryPacketBody = Crypto::EncryptAnonymously(ByteVector::Create(buildId, agentsPublicEncryptionKey.ToByteVector(), grcHash, timestamp, HostInfo()), gatewayEncryptionKey);
return query; return query;
} }

View File

@ -52,7 +52,7 @@ namespace FSecure::C3::Core::ProceduresG2X
ByteVector ComposeQueryPacket() const override ByteVector ComposeQueryPacket() const override
{ {
assert(m_GatewayPrivateSignature); assert(m_GatewayPrivateSignature);
return CompileProtocolHeader().Concat(Crypto::SignMessage(m_ReceiverRid.ToByteVector().Concat(GetQueryHeader()).Concat(m_QueryPacketBody), *m_GatewayPrivateSignature)); return CompileProtocolHeader().Concat(Crypto::SignMessage(ByteVector::Create(m_ReceiverRid).Concat(GetQueryHeader(), m_QueryPacketBody), *m_GatewayPrivateSignature));
} }
protected: protected:
@ -199,7 +199,7 @@ namespace FSecure::C3::Core::ProceduresG2X
static std::unique_ptr<RunCommandOnDeviceQuery> Create(RouteId receiverRid, Crypto::PrivateSignature const& gatewayPrivateSignature, Crypto::PublicKey const& agentPublicKey, Crypto::PrivateKey const& gatewayPrivateKey, DeviceId deviceToRunOn, ByteView commandWithArguments, ResponseType responseType = ResponseType::None) static std::unique_ptr<RunCommandOnDeviceQuery> Create(RouteId receiverRid, Crypto::PrivateSignature const& gatewayPrivateSignature, Crypto::PublicKey const& agentPublicKey, Crypto::PrivateKey const& gatewayPrivateKey, DeviceId deviceToRunOn, ByteView commandWithArguments, ResponseType responseType = ResponseType::None)
{ {
auto query = std::make_unique<RunCommandOnDeviceQuery>(Propagation::Agent, receiverRid, gatewayPrivateSignature, responseType); auto query = std::make_unique<RunCommandOnDeviceQuery>(Propagation::Agent, receiverRid, gatewayPrivateSignature, responseType);
query->EncrpytQueryWithBody(deviceToRunOn.ToByteVector().Concat(commandWithArguments), agentPublicKey, gatewayPrivateKey); query->EncrpytQueryWithBody(ByteVector::Create(deviceToRunOn).Concat(commandWithArguments), agentPublicKey, gatewayPrivateKey);
return query; return query;
} }
@ -223,7 +223,7 @@ namespace FSecure::C3::Core::ProceduresG2X
static std::unique_ptr<DeliverToBinder> Create(RouteId receiverRid, Crypto::PrivateSignature const& gatewayPrivateSignature, Crypto::PublicKey const& agentPublicKey, Crypto::PrivateKey const& gatewayPrivateKey, DeviceId deliverTo, ByteView commandWithArguments, ResponseType responseType = ResponseType::None) static std::unique_ptr<DeliverToBinder> Create(RouteId receiverRid, Crypto::PrivateSignature const& gatewayPrivateSignature, Crypto::PublicKey const& agentPublicKey, Crypto::PrivateKey const& gatewayPrivateKey, DeviceId deliverTo, ByteView commandWithArguments, ResponseType responseType = ResponseType::None)
{ {
auto query = std::make_unique<DeliverToBinder>(Propagation::Agent, receiverRid, gatewayPrivateSignature, responseType); auto query = std::make_unique<DeliverToBinder>(Propagation::Agent, receiverRid, gatewayPrivateSignature, responseType);
query->EncrpytQueryWithBody(deliverTo.ToByteVector().Concat(commandWithArguments), agentPublicKey, gatewayPrivateKey); query->EncrpytQueryWithBody(ByteVector::Create(deliverTo).Concat(commandWithArguments), agentPublicKey, gatewayPrivateKey);
return query; return query;
} }

View File

@ -327,7 +327,7 @@ void FSecure::C3::Core::Profiler::RestoreFromSnapshot()
auto creationCommand = base64::decode<ByteVector>(peripheral["startupCommand"]["ByteForm"].get<std::string>()); auto creationCommand = base64::decode<ByteVector>(peripheral["startupCommand"]["ByteForm"].get<std::string>());
auto readView = ByteView{ creationCommand }; auto readView = ByteView{ creationCommand };
auto connectionId = RouteId{ route->m_RouteId.GetAgentId(), DeviceId{ peripheral["iId"].get<std::string>() } }.ToByteVector(); auto connectionId = ByteVector::Create(RouteId{ route->m_RouteId.GetAgentId(), DeviceId{ peripheral["iId"].get<std::string>() } });
readView.remove_prefix(sizeof(uint16_t)); // remove command id readView.remove_prefix(sizeof(uint16_t)); // remove command id
connector->PeripheralCreationCommand(connectionId, readView); // throw away the response. connector->PeripheralCreationCommand(connectionId, readView); // throw away the response.
connector->OnCommandFromBinder(connectionId, base64::decode<ByteVector>(peripheral["startupCommand"]["FirstResponse"].get<std::string>())); connector->OnCommandFromBinder(connectionId, base64::decode<ByteVector>(peripheral["startupCommand"]["FirstResponse"].get<std::string>()));
@ -528,7 +528,7 @@ void FSecure::C3::Core::Profiler::Agent::ParseAndRunCommand(json const& jCommand
return; return;
// Remove connection. // Remove connection.
connector->CloseConnection(RouteId{ m_Id, *deviceId }.ToByteVector()); connector->CloseConnection(ByteVector::Create(RouteId{ m_Id, *deviceId }));
} }
}; };
break; break;
@ -610,7 +610,7 @@ void FSecure::C3::Core::Profiler::Agent::RunCommand(ByteView commandWithArgument
break; break;
// Remove connection. // Remove connection.
connector->CloseConnection(RouteId{ m_Id, element.m_Id }.ToByteVector()); connector->CloseConnection(ByteVector::Create(RouteId{ m_Id, element.m_Id }));
} }
m_Peripherals.Clear(); m_Peripherals.Clear();
@ -701,7 +701,7 @@ void FSecure::C3::Core::Profiler::Agent::PerformCreateCommand(json const& jComma
if (!connector) if (!connector)
throw std::runtime_error{ "Connector for requested peripheral is closed" }; throw std::runtime_error{ "Connector for requested peripheral is closed" };
auto updatedArguments = connector->PeripheralCreationCommand(RouteId{ route->m_RouteId.GetAgentId(), newDeviceId}.ToByteVector(), commandReadView, m_IsX64); auto updatedArguments = connector->PeripheralCreationCommand(ByteVector::Create(RouteId{ route->m_RouteId.GetAgentId(), newDeviceId }), commandReadView, m_IsX64);
repacked.Concat(updatedArguments); repacked.Concat(updatedArguments);
} }
else else
@ -812,7 +812,7 @@ void FSecure::C3::Core::Profiler::Gateway::ParseAndRunCommand(json const& jComma
break; break;
// Remove connection. // Remove connection.
connector->CloseConnection(RouteId{ m_Id, device->GetDid() }.ToByteVector()); connector->CloseConnection(ByteVector::Create(RouteId{ m_Id, device->GetDid() }));
break; break;
} }
@ -1068,7 +1068,7 @@ void FSecure::C3::Core::Profiler::Gateway::PerformCreateCommand(json const& jCom
if (!connector) if (!connector)
throw std::runtime_error{ "Connector for requested peripheral is closed" }; throw std::runtime_error{ "Connector for requested peripheral is closed" };
updatedArguments = connector->PeripheralCreationCommand(RouteId{ gate.GetAgentId(), DeviceId(m_LastDeviceId + 1) }.ToByteVector(), arguments, FSecure::Utils::IsProcess64bit()); updatedArguments = connector->PeripheralCreationCommand(ByteVector::Create(RouteId{ gate.GetAgentId(), DeviceId(m_LastDeviceId + 1) }), arguments, FSecure::Utils::IsProcess64bit());
arguments = updatedArguments; arguments = updatedArguments;
} }

View File

@ -1,7 +1,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Relay.h" #include "Relay.h"
#include "DeviceBridge.h" #include "DeviceBridge.h"
#include "Common/FSecure/CppTools/ByteView.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
#include "Common/FSecure/C3/Internals/InterfaceFactory.h" #include "Common/FSecure/C3/Internals/InterfaceFactory.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -10,11 +10,6 @@ FSecure::C3::RouteId::RouteId(std::string_view textId)
{ {
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::C3::RouteId::RouteId(ByteView byteId)
: RouteId(byteId.SubString(0, AgentId::BinarySize), byteId.SubString(AgentId::BinarySize, DeviceId::BinarySize))
{
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::C3::RouteId FSecure::C3::RouteId::GenerateRandom() FSecure::C3::RouteId FSecure::C3::RouteId::GenerateRandom()
@ -28,36 +23,6 @@ std::string FSecure::C3::RouteId::ToString() const
return m_AgentId.ToString() + OBF(":") + m_InterfaceId.ToString(); return m_AgentId.ToString() + OBF(":") + m_InterfaceId.ToString();
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::ByteVector FSecure::C3::RouteId::ToByteVector() const
{
// Allocate return vector.
FSecure::ByteVector retByteVector;
retByteVector.reserve(m_AgentId.BinarySize + m_InterfaceId.BinarySize);
// Fill it with aid and iid.
auto aid = m_AgentId.ToByteVector(), iid = m_InterfaceId.ToByteVector();
retByteVector.insert(retByteVector.end(), aid.begin(), aid.end());
retByteVector.insert(retByteVector.end(), iid.begin(), iid.end());
// That's it.
return retByteVector;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::ByteArray<FSecure::C3::RouteId::BinarySize> FSecure::C3::RouteId::ToByteArray() const
{
FSecure::ByteArray<BinarySize> retArray;
// Fill it with aid and iid.
auto aid = m_AgentId.ToByteVector(), iid = m_InterfaceId.ToByteVector();
memcpy(retArray.data(), aid.data(), m_AgentId.BinarySize);
memcpy(retArray.data() + m_AgentId.BinarySize, iid.data(), m_InterfaceId.BinarySize);
// That's it.
return retArray;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool FSecure::C3::RouteId::operator!() const bool FSecure::C3::RouteId::operator!() const
{ {

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Common/FSecure/CppTools/ByteView.h" #include "Common/FSecure/CppTools/ByteConverter/ByteConverter.h"
#include "Identifiers.h" #include "Identifiers.h"
namespace FSecure::C3 namespace FSecure::C3
@ -26,10 +26,6 @@ namespace FSecure::C3
/// @param textId text containing the identifier. /// @param textId text containing the identifier.
RouteId(std::string_view textId); RouteId(std::string_view textId);
/// Creates a RouteId object from a vector of bytes.
/// @param byteId a ByteView containing the identifier.
RouteId(ByteView byteId);
/// Creates a RouteId object with a random ("unique") value. /// Creates a RouteId object with a random ("unique") value.
/// @return Identifier object. /// @return Identifier object.
static RouteId GenerateRandom(); static RouteId GenerateRandom();
@ -38,14 +34,6 @@ namespace FSecure::C3
/// @return a string that describes this ID object. /// @return a string that describes this ID object.
std::string ToString() const; std::string ToString() const;
/// Converts this ID to a byte vector.
/// @return a byte vector that describes this ID object.
ByteVector ToByteVector() const;
/// Converts this ID to a byte array.
/// @return a byte array that describes this ID object.
ByteArray<BinarySize> ToByteArray() const;
/// Logical negation operator. Can be used to check if ID is set. /// Logical negation operator. Can be used to check if ID is set.
/// @return true if ID is not set. /// @return true if ID is not set.
bool operator !() const; bool operator !() const;
@ -94,7 +82,7 @@ namespace FSecure
{ {
static ByteVector To(C3::RouteId const& obj) static ByteVector To(C3::RouteId const& obj)
{ {
return obj.ToByteVector(); return ByteVector::Create(obj.GetAgentId(), obj.GetInterfaceId());
} }
static size_t Size(C3::RouteId const& obj) static size_t Size(C3::RouteId const& obj)
@ -104,9 +92,7 @@ namespace FSecure
static C3::RouteId From(ByteView& bv) static C3::RouteId From(ByteView& bv)
{ {
auto ret = C3::RouteId(bv.SubString(0, C3::RouteId::BinarySize)); return ByteReader{ bv }.Create<C3::RouteId, decltype(C3::RouteId::m_AgentId), decltype(C3::RouteId::m_InterfaceId)>();
bv.remove_prefix(C3::RouteId::BinarySize);
return ret;
} }
}; };