From 74c0cdd7b73de31aaac8543d42a289fecc0a50a6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 11:00:46 -0400 Subject: [PATCH 01/76] Add basic jamfiles --- build.jam | 19 +++++++++++++++++++ test/Jamfile | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 build.jam create mode 100644 test/Jamfile diff --git a/build.jam b/build.jam new file mode 100644 index 00000000..2095c983 --- /dev/null +++ b/build.jam @@ -0,0 +1,19 @@ +# Copyright Matt Borland 2024 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +require-b2 5.2 ; + +project /boost/crypt + : common-requirements + include + ; + +explicit + [ alias boost_core ] + [ alias all : boost_crypt test ] + ; + +call-if : boost-library crypt + ; diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 00000000..d0306e49 --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,44 @@ +# Copyright 2023 - 2024 Matt Borland +# Copyright 2023 - 2024 Christopher Kormanyos +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +require-b2 5.0.1 ; +import-search /boost/config/checks ; +import config : requires ; +import modules ; +import testing ; + +project : requirements + + gcc:-Wall + gcc:-Wextra + + # Clang-Cl gives errors that are incorrect or irrelevant (e.g. C++98 compat) + #clang:-Wall + #clang:-Wextra + + msvc:all + + # Additional flags by request + gcc:-Wsign-conversion + gcc:-Wconversion + gcc:-Wundef + gcc:-Wold-style-cast + #gcc:-Wduplicated-branches + gcc:-Wfloat-equal + + clang:-Wsign-conversion + clang:-Wconversion + clang:-Wundef + clang:-Wold-style-cast + clang:-Wfloat-equal + + msvc:on + clang:on + gcc:on + + [ requires cxx14_decltype_auto cxx14_generic_lambdas cxx14_return_type_deduction cxx14_variable_templates cxx14_constexpr ] + ; + +run test_md5.cpp ; From b6469b03ad8ed39db9d8910098581a83e1f4e5e9 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 11:00:54 -0400 Subject: [PATCH 02/76] Add cmake support --- CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ test/CMakeLists.txt | 12 ++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..f9ef54f3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +# Generated by `boostdep --cmake crypt` +# Copyright 2020, 2021 Peter Dimov +# Copyright 2023 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.8...3.20) + +project(boost_crypt VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_crypt INTERFACE) + +add_library(Boost::crypt ALIAS boost_crypt) + +target_include_directories(boost_crypt INTERFACE include) + +target_compile_features(boost_crypt INTERFACE cxx_std_14) + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + + include(GNUInstallDirs) + install(DIRECTORY "include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + +endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..eb310951 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright 2018, 2019 Peter Dimov +# Copyright 2023 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) + +if(HAVE_BOOST_TEST) + + boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::crypt Boost::core) + +endif() From b992e40c111d674f53edcf004068daeeba470fa6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 12:20:00 -0400 Subject: [PATCH 03/76] Add table macro definitions --- include/boost/crypt/utility/config.hpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/boost/crypt/utility/config.hpp diff --git a/include/boost/crypt/utility/config.hpp b/include/boost/crypt/utility/config.hpp new file mode 100644 index 00000000..0aec83a3 --- /dev/null +++ b/include/boost/crypt/utility/config.hpp @@ -0,0 +1,25 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CRYPT_DETAIL_CONFIG_HPP +#define BOOST_CRYPT_DETAIL_CONFIG_HPP + +#ifdef __CUDACC__ +# ifndef BOOST_CRYPT_ENABLE_CUDA +# define BOOST_CRYPT_ENABLE_CUDA +# endif +#endif + +#if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L +# define BOOST_CRYPT_CONSTEXPR_ARRAY inline constexpr +# define BOOST_CRYPT_DEVICE_ARRAY inline constexpr +#elif defined(BOOST_CRYPT_ENABLE_CUDA) +# define BOOST_CYPRT_CONSTEXPR_ARRAY static constexpr +# define BOOST_CRYPT_DEVICE_ARRAY __constant__ +#else +# define BOOST_CRYPT_CONSTEXPR_ARRAY static constexpr +# define BOOST_CRYPT_DEVICE_ARRAY static constexpr +#endif + +#endif //BOOST_CRYPT_DETAIL_CONFIG_HPP From 8e426f9b2ecf42f4e318605ea6ff973a7a265c63 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 13:11:36 -0400 Subject: [PATCH 04/76] Add rotr and rotl impls --- include/boost/crypt/utility/bit.hpp | 96 +++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 include/boost/crypt/utility/bit.hpp diff --git a/include/boost/crypt/utility/bit.hpp b/include/boost/crypt/utility/bit.hpp new file mode 100644 index 00000000..d69f86d8 --- /dev/null +++ b/include/boost/crypt/utility/bit.hpp @@ -0,0 +1,96 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_BIT_HPP +#define BOOST_BIT_HPP + +#include +#include +#include + +namespace boost { +namespace crypt { +namespace detail { + +// Forward decls +template ::value, bool> = true> +constexpr T rotl(T x, U s) noexcept; +template ::value, bool> = true> +constexpr T rotl(T x, U s) noexcept; + +template ::value, bool> = true> +constexpr T rotr(T x, U s) noexcept; +template ::value, bool> = true> +constexpr T rotr(T x, U s) noexcept; + +// Only works for unsigned s so we can optimize away the call to rotr +template ::value, bool>> +constexpr T rotl(T x, U s) noexcept +{ + constexpr auto N {std::numeric_limits::digits}; + const auto r {s % N}; + + if (r == 0) + { + return x; + } + + return (x << r) | (x >> (N - r)); +} + +template ::value, bool>> +constexpr T rotl(T x, U s) noexcept +{ + constexpr auto N {std::numeric_limits::digits}; + const auto r {s % N}; + + if (r == 0) + { + return x; + } + else if (r < 0) + { + return rotr(x, -r); + } + + return (x << r) | (x >> (N - r)); +} + +template ::value, bool>> +constexpr T rotr(T x, U s) noexcept +{ + constexpr auto N {std::numeric_limits::digits}; + const auto r {s % N}; + + if (r == 0) + { + return x; + } + + return (x >> r) | (x << (N - r)); +} + +template ::value, bool>> +constexpr T rotr(T x, U s) noexcept +{ + constexpr auto N {std::numeric_limits::digits}; + const auto r {s % N}; + + if (r == 0) + { + return x; + } + else if (r < 0) + { + return rotl(x, -r); + } + + return (x >> r) | (x << (N - r)); +} + +} // namespace detail +} // namespace crypt +} // namespace boost + +#endif //BOOST_BIT_HPP From c40d30cd44567513536f3b143f894fd3e6b0da88 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:16:21 -0400 Subject: [PATCH 05/76] Add 32 bit swap endian function --- include/boost/crypt/utility/bit.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/crypt/utility/bit.hpp b/include/boost/crypt/utility/bit.hpp index d69f86d8..36e93de3 100644 --- a/include/boost/crypt/utility/bit.hpp +++ b/include/boost/crypt/utility/bit.hpp @@ -89,6 +89,14 @@ constexpr T rotr(T x, U s) noexcept return (x >> r) | (x << (N - r)); } +constexpr auto swap_endian(const std::uint32_t val) -> std::uint32_t +{ + return ((val & 0xFF000000) >> 24U) | + ((val & 0x00FF0000) >> 8U) | + ((val & 0x0000FF00) << 8U) | + ((val & 0x000000FF) << 24U); +} + } // namespace detail } // namespace crypt } // namespace boost From 8e9e823479f02643d2cd7adda95ab7a2c443988f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:21:12 -0400 Subject: [PATCH 06/76] Add assertion macros --- include/boost/crypt/utility/config.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/crypt/utility/config.hpp b/include/boost/crypt/utility/config.hpp index 0aec83a3..58fac475 100644 --- a/include/boost/crypt/utility/config.hpp +++ b/include/boost/crypt/utility/config.hpp @@ -11,6 +11,7 @@ # endif #endif +// ---- Constexpr arrays ----- #if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L # define BOOST_CRYPT_CONSTEXPR_ARRAY inline constexpr # define BOOST_CRYPT_DEVICE_ARRAY inline constexpr @@ -21,5 +22,12 @@ # define BOOST_CRYPT_CONSTEXPR_ARRAY static constexpr # define BOOST_CRYPT_DEVICE_ARRAY static constexpr #endif +// ---- Constexpr arrays ----- + +// ----- Assertions ----- +#include +#define BOOST_CRYPT_ASSERT(x) assert(x) +#define BOOST_CRYPT_ASSERT_MSG(expr, msg) assert((expr)&&(msg)) +// ----- Assertions ----- #endif //BOOST_CRYPT_DETAIL_CONFIG_HPP From 14ca1e2cc9d60b24013f8ed4e87145c8974aa84f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:21:28 -0400 Subject: [PATCH 07/76] Add super basic md5 impl --- include/boost/crypt/hash/md5.hpp | 194 +++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 include/boost/crypt/hash/md5.hpp diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp new file mode 100644 index 00000000..f5707460 --- /dev/null +++ b/include/boost/crypt/hash/md5.hpp @@ -0,0 +1,194 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CRYPT_HASH_MD5_HPP +#define BOOST_CRYPT_HASH_MD5_HPP + +#include +#include + +#include +#include +#include + +namespace boost { +namespace crypt { + +namespace detail { + +static constexpr std::array S { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 +}; + +static constexpr std::array K { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + +template +auto md5_preprocess(T begin, T end) -> std::vector +{ + std::vector vec; + vec.reserve(end - begin); + std::copy(begin, end, std::back_inserter(vec)); + return vec; +} + +template +auto md5_preprocess(T begin, std::size_t len) -> std::vector +{ + std::vector vec; + vec.reserve(len); + std::copy(begin, begin + len, std::back_inserter(vec)); + return vec; +} + +auto md5_pad(const std::vector& message) noexcept -> std::vector +{ + std::vector padded_message {message}; + const std::uint64_t original_length {message.size() * 8U}; + padded_message.emplace_back(0x80); + + while ((padded_message.size() * 8U) % 512U != 448U) + { + padded_message.push_back(static_cast(0x00)); + } + + // Add the original length as a 64-bit number + for (std::size_t i = 0; i < 8; ++i) + { + padded_message.push_back(static_cast((original_length >> (8 * i)) & 0xFF)); + } + + return padded_message; +} + +template +auto md5_impl(const std::vector& padded_message) -> ResultType +{ + std::uint32_t a0 {0x67452301}; + std::uint32_t b0 {0xefcdab89}; + std::uint32_t c0 {0x98badcfe}; + std::uint32_t d0 {0x10325476}; + + std::array blocks {}; + + std::size_t message_chunk {}; + while (message_chunk < padded_message.size()) + { + for (auto& block : blocks) + { + block = static_cast( + (static_cast(padded_message[message_chunk])) + + (static_cast(padded_message[message_chunk + 1U]) << 8U) + + (static_cast(padded_message[message_chunk + 2U]) << 16U) + + (static_cast(padded_message[message_chunk + 3U]) << 24U) + ); + + message_chunk += 4U; + } + + std::uint32_t A {a0}; + std::uint32_t B {b0}; + std::uint32_t C {c0}; + std::uint32_t D {d0}; + + for (std::uint32_t i {}; i < 64U; ++i) + { + std::uint32_t F {}; + std::uint32_t g {}; + + if (i <= 15U) + { + F = (B & C) | ((~B) & D); + g = i; + } + else if (i <= 31U) + { + F = (D & B) | ((~D) & C); + g = (5U * i + 1U) % 16U; + } + else if (i <= 47U) + { + F = B ^ C ^ D; + g = (3U * i + 5U) % 16U; + } + else + { + F = C ^ (B | (~D)); + g = (7U * i) % 16U; + } + + BOOST_CRYPT_ASSERT(i <= 63U); + + F = F + A + K[i] + blocks[g]; + A = D; + D = C; + C = B; + B = B + rotl(F, S[i]); + } + + a0 += A; + b0 += B; + c0 += C; + d0 += D; + } + + return ResultType {swap_endian(a0), + swap_endian(b0), + swap_endian(c0), + swap_endian(d0)}; +} + +} // namespace detail + +template +ResultType md5(T begin, T end) +{ + if (end <= begin) + { + return ResultType {0, 0, 0, 0}; + } + + + const auto message {detail::md5_preprocess(begin, end)}; + const auto padded_message {detail::md5_pad(message)}; + return detail::md5_impl(padded_message); +} + +template > +ResultType md5(const char* str) +{ + if (str == nullptr) + { + return ResultType {0, 0, 0, 0}; + } + + const auto message_len {std::strlen(str)}; + const auto message {detail::md5_preprocess(str, message_len)}; + const auto padded_message {detail::md5_pad(message)}; + return detail::md5_impl(padded_message); +} + +} // namespace crypt +} // namespace boost + +#endif // BOOST_CRYPT_HASH_MD5_HPP From 0f52a735962e6c6d51015d090517882f15944799 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:29:29 -0400 Subject: [PATCH 08/76] Add basic test set --- test/test_md5.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 test/test_md5.cpp diff --git a/test/test_md5.cpp b/test/test_md5.cpp new file mode 100644 index 00000000..2c26932d --- /dev/null +++ b/test/test_md5.cpp @@ -0,0 +1,36 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Start with the sample hashes from wiki + +#include +#include + +void basic_tests() +{ + const auto message_1_result {boost::crypt::md5("The quick brown fox jumps over the lazy dog")}; + BOOST_TEST_EQ(message_1_result[0], 0x9e107d9d); + BOOST_TEST_EQ(message_1_result[1], 0x372bb682); + BOOST_TEST_EQ(message_1_result[2], 0x6bd81d35); + BOOST_TEST_EQ(message_1_result[3], 0x42a419d6); + + const auto message_2_result {boost::crypt::md5("The quick brown fox jumps over the lazy dog.")}; + BOOST_TEST_EQ(message_2_result[0], 0xe4d909c2); + BOOST_TEST_EQ(message_2_result[1], 0x90d0fb1c); + BOOST_TEST_EQ(message_2_result[2], 0xa068ffad); + BOOST_TEST_EQ(message_2_result[3], 0xdf22cbd0); + + const auto message_3_result {boost::crypt::md5("")}; + BOOST_TEST_EQ(message_3_result[0], 0xd41d8cd9); + BOOST_TEST_EQ(message_3_result[1], 0x8f00b204); + BOOST_TEST_EQ(message_3_result[2], 0xe9800998); + BOOST_TEST_EQ(message_3_result[3], 0xecf8427e); +} + +int main() +{ + basic_tests(); + + return boost::report_errors(); +} From b5173b386f66b0aa33f38bcd16a2164a0dca00c9 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:49:14 -0400 Subject: [PATCH 09/76] Fix conversion error --- include/boost/crypt/hash/md5.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index f5707460..02157cd3 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -47,7 +47,7 @@ template auto md5_preprocess(T begin, T end) -> std::vector { std::vector vec; - vec.reserve(end - begin); + vec.reserve(static_cast(end - begin)); std::copy(begin, end, std::back_inserter(vec)); return vec; } From 53ab95180e4565316c465f1eae921cfb3303f131 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:49:33 -0400 Subject: [PATCH 10/76] Add detection for string view --- include/boost/crypt/utility/config.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/boost/crypt/utility/config.hpp b/include/boost/crypt/utility/config.hpp index 58fac475..4770b948 100644 --- a/include/boost/crypt/utility/config.hpp +++ b/include/boost/crypt/utility/config.hpp @@ -30,4 +30,16 @@ #define BOOST_CRYPT_ASSERT_MSG(expr, msg) assert((expr)&&(msg)) // ----- Assertions ----- +// ----- Has CXX something ----- +// C++17 +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# if __has_include() +# include +# if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L +# define BOOST_CRYPT_HAS_STRING_VIEW +# endif +# endif +#endif +// ----- Has CXX something ----- + #endif //BOOST_CRYPT_DETAIL_CONFIG_HPP From 35416f703f50188568a406f32fb343e207ba1980 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:49:43 -0400 Subject: [PATCH 11/76] Add additional overloads --- include/boost/crypt/hash/md5.hpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 02157cd3..33bf8396 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -160,7 +160,7 @@ auto md5_impl(const std::vector& padded_message) -> ResultType } // namespace detail -template +template , typename T> ResultType md5(T begin, T end) { if (end <= begin) @@ -168,7 +168,6 @@ ResultType md5(T begin, T end) return ResultType {0, 0, 0, 0}; } - const auto message {detail::md5_preprocess(begin, end)}; const auto padded_message {detail::md5_pad(message)}; return detail::md5_impl(padded_message); @@ -188,6 +187,20 @@ ResultType md5(const char* str) return detail::md5_impl(padded_message); } +template > +ResultType md5(const std::string& str) +{ + return md5(str.begin(), str.end()); +} + +#ifdef BOOST_CRYPT_HAS_STRING_VIEW +template > +ResultType md5(const std::string_view& str) +{ + return md5(str.begin(), str.end()); +} +#endif + } // namespace crypt } // namespace boost From 235dd609c97f85d6beb76902d930616edf199db3 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 15:50:00 -0400 Subject: [PATCH 12/76] Add additional tests for new overloads --- test/test_md5.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 2c26932d..83ee3f51 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -6,6 +6,7 @@ #include #include +#include void basic_tests() { @@ -28,9 +29,52 @@ void basic_tests() BOOST_TEST_EQ(message_3_result[3], 0xecf8427e); } +void string_test() +{ + std::string message_1 {"The quick brown fox jumps over the lazy dog"}; + const auto message_1_result {boost::crypt::md5(message_1)}; + BOOST_TEST_EQ(message_1_result[0], 0x9e107d9d); + BOOST_TEST_EQ(message_1_result[1], 0x372bb682); + BOOST_TEST_EQ(message_1_result[2], 0x6bd81d35); + BOOST_TEST_EQ(message_1_result[3], 0x42a419d6); + + #ifdef BOOST_CRYPT_HAS_STRING_VIEW + std::string_view view_1 {message_1}; + const auto view_1_result {boost::crypt::md5(view_1)}; + BOOST_TEST_EQ(view_1_result[0], 0x9e107d9d); + BOOST_TEST_EQ(view_1_result[1], 0x372bb682); + BOOST_TEST_EQ(view_1_result[2], 0x6bd81d35); + BOOST_TEST_EQ(view_1_result[3], 0x42a419d6); + #endif + + std::string message_2 {"The quick brown fox jumps over the lazy dog."}; + const auto message_2_result {boost::crypt::md5(message_2.begin(), message_2.end())}; + BOOST_TEST_EQ(message_2_result[0], 0xe4d909c2); + BOOST_TEST_EQ(message_2_result[1], 0x90d0fb1c); + BOOST_TEST_EQ(message_2_result[2], 0xa068ffad); + BOOST_TEST_EQ(message_2_result[3], 0xdf22cbd0); +} + +void bad_input() +{ + const auto null_message {boost::crypt::md5(nullptr)}; + BOOST_TEST_EQ(null_message[0], 0x0); + BOOST_TEST_EQ(null_message[1], 0x0); + BOOST_TEST_EQ(null_message[2], 0x0); + BOOST_TEST_EQ(null_message[3], 0x0); + + std::string message_1 {"The quick brown fox jumps over the lazy dog"}; + const auto message_1_result {boost::crypt::md5(message_1.begin(), message_1.begin())}; + BOOST_TEST_EQ(message_1_result[0], 0x0); + BOOST_TEST_EQ(message_1_result[1], 0x0); + BOOST_TEST_EQ(message_1_result[2], 0x0); + BOOST_TEST_EQ(message_1_result[3], 0x0); +} + int main() { basic_tests(); + bad_input(); return boost::report_errors(); } From da230bd062621acc6cff422af3cc67e685824cd4 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:05:23 -0400 Subject: [PATCH 13/76] Add drone CI --- .drone.jsonnet | 420 +++++++++++++++++++++++++++++++++++++++++++++++ .drone/drone.bat | 25 +++ .drone/drone.sh | 32 ++++ 3 files changed, 477 insertions(+) create mode 100644 .drone.jsonnet create mode 100644 .drone/drone.bat create mode 100755 .drone/drone.sh diff --git a/.drone.jsonnet b/.drone.jsonnet new file mode 100644 index 00000000..a2c30dcd --- /dev/null +++ b/.drone.jsonnet @@ -0,0 +1,420 @@ +# Copyright 2022, 2023 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +local library = "crypt"; + +local triggers = +{ + branch: [ "master", "develop", "feature/*" ] +}; + +local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' }; +local asan = { ASAN: '1' }; + +local linux_pipeline(name, image, environment, packages = "", sources = [], arch = "amd64") = +{ + name: name, + kind: "pipeline", + type: "docker", + trigger: triggers, + platform: + { + os: "linux", + arch: arch + }, + steps: + [ + { + name: "everything", + image: image, + privileged: true, + environment: environment, + commands: + [ + 'set -e', + 'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -', + ] + + (if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) + + (if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) + + [ + 'export LIBRARY=' + library, + './.drone/drone.sh', + ] + } + ] +}; + +local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "catalina", arch = "amd64") = +{ + name: name, + kind: "pipeline", + type: "exec", + trigger: triggers, + platform: { + "os": "darwin", + "arch": arch + }, + node: { + "os": osx_version + }, + steps: [ + { + name: "everything", + environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" }, + commands: + [ + 'export LIBRARY=' + library, + './.drone/drone.sh', + ] + } + ] +}; + +local windows_pipeline(name, image, environment, arch = "amd64") = +{ + name: name, + kind: "pipeline", + type: "docker", + trigger: triggers, + platform: + { + os: "windows", + arch: arch + }, + "steps": + [ + { + name: "everything", + image: image, + environment: environment, + commands: + [ + 'cmd /C .drone\\\\drone.bat ' + library, + ] + } + ] +}; + +[ + + linux_pipeline( + "Linux 18.04 GCC 8 32/64", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '03,11,14,17', ADDRMD: '32,64' }, + "g++-8-multilib", + ), + + linux_pipeline( + "Linux 20.04 GCC 9* 32/64", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '32,64' }, + ), + + linux_pipeline( + "Linux 20.04 GCC 9* ARM64", + "cppalliance/droneubuntu2004:multiarch", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' }, + arch="arm64", + ), + + linux_pipeline( + "Linux 20.04 GCC 9* ARM64 - ASAN", + "cppalliance/droneubuntu2004:multiarch", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' } + asan, + arch="arm64", + ), + + linux_pipeline( + "Linux 20.04 GCC 9* S390x", + "cppalliance/droneubuntu2004:multiarch", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a' }, + arch="s390x", + ), + + linux_pipeline( + "Linux 20.04 GCC 10 32/64", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '03,11,14,17,20', ADDRMD: '32,64' }, + "g++-10-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 11* 32/64", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '32,64' }, + ), + + linux_pipeline( + "Linux 22.04 GCC 12 32 ASAN 03", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03', ADDRMD: '32' } + asan, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 12 32 ASAN 11", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11', ADDRMD: '32' } + asan, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 12 32 ASAN 14", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '14', ADDRMD: '32' } + asan, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 12 32 ASAN 17", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '17', ADDRMD: '32' } + asan, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 12 32 ASAN 20", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '20', ADDRMD: '32' } + asan, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 12 32 ASAN 2b", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '2b', ADDRMD: '32' } + asan, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 22.04 GCC 12 64 ASAN", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '03,11,14,17,20,2b', ADDRMD: '64' } + asan, + "g++-12-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 13 32/64", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '03,11,14,17,20,23', ADDRMD: '32,64', CXXFLAGS: "-fexcess-precision=fast" }, + "g++-13-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 13 GNU 32/64", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '03,11,14,17,20,23', ADDRMD: '32,64', CXXFLAGS: "-fexcess-precision=fast", CXXSTDDIALECT: "gnu" }, + "g++-13-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 14 32", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '03,11,14,17,20,23', ADDRMD: '32', CXXFLAGS: "-fexcess-precision=fast" }, + "g++-14-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 14 64", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '03,11,14,17,20,23', ADDRMD: '64', CXXFLAGS: "-fexcess-precision=fast" }, + "g++-14-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 14 GNU 32", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '03,11,14,17,20,23', ADDRMD: '32', CXXFLAGS: "-fexcess-precision=fast", CXXSTDDIALECT: "gnu" }, + "g++-14-multilib", + ), + + linux_pipeline( + "Linux 24.04 GCC 14 GNU 64", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '03,11,14,17,20,23', ADDRMD: '64', CXXFLAGS: "-fexcess-precision=fast", CXXSTDDIALECT: "gnu" }, + "g++-14-multilib", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 32 03", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03', ADDRMD: '32' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 32 11", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '32' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 32 14", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '14', ADDRMD: '32' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 32 17", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '17', ADDRMD: '32' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 64 03", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03', ADDRMD: '64' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 64 11", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '64' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 64 14", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '14', ADDRMD: '64' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 GCC 7* 64 17", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '17', ADDRMD: '64' }, + "nload", + ), + + linux_pipeline( + "Linux 18.04 Clang 6.0", + "cppalliance/droneubuntu1804:1", + { TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '03,11,14,17' }, + "clang-6.0", + ), + + linux_pipeline( + "Linux 20.04 Clang 7", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '03,11,14,17' }, + "clang-7", + ), + + linux_pipeline( + "Linux 20.04 Clang 8", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '03,11,14,17' }, + "clang-8", + ), + + linux_pipeline( + "Linux 20.04 Clang 9", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '03,11,14,17,2a' }, + "clang-9", + ), + + linux_pipeline( + "Linux 20.04 Clang 10", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '03,11,14,17,2a' }, + "clang-10", + ), + + linux_pipeline( + "Linux 20.04 Clang 11", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '03,11,14,17,2a' }, + "clang-11", + ), + + linux_pipeline( + "Linux 20.04 Clang 12", + "cppalliance/droneubuntu2004:1", + { TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '03,11,14,17,2a' }, + "clang-12", + ), + + linux_pipeline( + "Linux 22.04 Clang 13", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '03,11,14,17,20' }, + "clang-13", + ), + + linux_pipeline( + "Linux 22.04 Clang 14 UBSAN", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14,17,20,2b' } + ubsan, + "clang-14", + ), + + linux_pipeline( + "Linux 22.04 Clang 14 ASAN", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '03,11,14,17,20,2b' } + asan, + "clang-14", + ), + + linux_pipeline( + "Linux 22.04 Clang 15", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '03,11,14,17,20,2b' }, + "clang-15", + ["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"], + ), + + linux_pipeline( + "Linux 22.04 Clang 16", + "cppalliance/droneubuntu2204:1", + { TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '03,11,14,17,20,2b' }, + "clang-16", + ["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main"], + ), + + linux_pipeline( + "Linux 24.04 Clang 17", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '03,11,14,17,20,2b' }, + "clang-17", + ["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main"], + ), + + linux_pipeline( + "Linux 24.04 Clang 18", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '03,11,14,17,20,2b' }, + "clang-18", + ["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main"], + ), + + macos_pipeline( + "MacOS 12.4 Xcode 13.4.1 UBSAN", + { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + ubsan, + xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64", + ), + + macos_pipeline( + "MacOS 12.4 Xcode 13.4.1 ASAN", + { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,17,20,2b' } + asan, + xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64", + ), + + windows_pipeline( + "Windows VS2019 msvc-14.2", + "cppalliance/dronevs2019", + { TOOLSET: 'msvc-14.2', CXXSTD: '14,17,20,latest' }, + ), + + windows_pipeline( + "Windows VS2022 msvc-14.3", + "cppalliance/dronevs2022:1", + { TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest' }, + ), +] diff --git a/.drone/drone.bat b/.drone/drone.bat new file mode 100644 index 00000000..2b56e63c --- /dev/null +++ b/.drone/drone.bat @@ -0,0 +1,25 @@ +@REM Copyright 2022 Peter Dimov +@REM Distributed under the Boost Software License, Version 1.0. +@REM https://www.boost.org/LICENSE_1_0.txt + +@ECHO ON + +set LIBRARY=%1 +set DRONE_BUILD_DIR=%CD% + +echo $env:DRONE_STAGE_MACHINE + +set BOOST_BRANCH=develop +if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master +cd .. +git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root +cd boost-root +git submodule update --init tools/boostdep +xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\ +python tools/boostdep/depinst/depinst.py -I example %LIBRARY% +cmd /c bootstrap +b2 -d0 headers + +if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% +if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% +b2 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker diff --git a/.drone/drone.sh b/.drone/drone.sh new file mode 100755 index 00000000..5a546959 --- /dev/null +++ b/.drone/drone.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Copyright 2022 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +set -ex +export PATH=~/.local/bin:/usr/local/bin:$PATH +uname -a +echo $DRONE_STAGE_MACHINE + +DRONE_BUILD_DIR=$(pwd) + +BOOST_BRANCH=develop +if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi + +cd .. +git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root +cd boost-root +git submodule update --init tools/boostdep +mkdir -p libs/$LIBRARY +cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY +python tools/boostdep/depinst/depinst.py -I example $LIBRARY +./bootstrap.sh +./b2 -d0 headers + +if [[ $(uname) == "Linux" ]]; then + echo 0 | sudo tee /proc/sys/kernel/randomize_va_space +fi + +echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam +./b2 -j3 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${CXXFLAGS:+cxxflags=$CXXFLAGS} ${CXXSTDDIALECT:+cxxstd-dialect=$CXXSTDDIALECT} ${LINKFLAGS:+linkflags=$LINKFLAGS} From 23e5c23d5f1e23d738a2be494e36810efac03951 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:07:15 -0400 Subject: [PATCH 14/76] Add codecov to CI --- .github/workflows/codecov.yml | 73 ++++++++++++++++++++ test/cover/make_gcov_01_generic.gmk | 103 ++++++++++++++++++++++++++++ test/cover/make_gcov_02_files.gmk | 21 ++++++ test/cover/make_gcov_03_flags.gmk | 73 ++++++++++++++++++++ test/cover/make_gcov_04_rules.gmk | 22 ++++++ 5 files changed, 292 insertions(+) create mode 100644 .github/workflows/codecov.yml create mode 100644 test/cover/make_gcov_01_generic.gmk create mode 100644 test/cover/make_gcov_02_files.gmk create mode 100644 test/cover/make_gcov_03_flags.gmk create mode 100644 test/cover/make_gcov_04_rules.gmk diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml new file mode 100644 index 00000000..e37414c7 --- /dev/null +++ b/.github/workflows/codecov.yml @@ -0,0 +1,73 @@ +# ------------------------------------------------------------------------------ +# Copyright Matt Borland 2023 - 2024. +# Copyright Christopher Kormanyos 2023 - 2024. +# Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) +# ------------------------------------------------------------------------------ + +name: codecov +on: + push: + branches: + - master + - develop + - feature/** + pull_request: + types: [opened, synchronize, reopened] +jobs: + gcc-gcov-native: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + standard: [ c++20 ] + compiler: [ g++ ] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: '0' + - name: update-tools + run: | + sudo apt install lcov locales + sudo locale-gen de_DE.UTF-8 + sudo update-locale + + - name: clone-submods-bootstrap-headers-boost-develop + run: | + git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root + cd ../boost-root + git submodule update --init tools + git submodule update --init libs/assert + git submodule update --init libs/config + git submodule update --init libs/core + git submodule update --init libs/math + git submodule update --init libs/multiprecision + git submodule update --init libs/predef + git submodule update --init libs/static_assert + git submodule update --init libs/test + ./bootstrap.sh + ./b2 headers + - name: gcc-gcov-native + run: | + cd test/cover + echo "build and run gcov/lcov/genhtml" + echo "make prepare -f make_gcov_01_generic.gmk MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }}" + echo + make prepare -f make_gcov_01_generic.gmk MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }} + echo + echo "make gcov -f make_gcov_01_generic.gmk --jobs=8 MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }}" + echo + make gcov -f make_gcov_01_generic.gmk --jobs=8 MY_ALL_COV=0 MY_BOOST_ROOT=../../../boost-root MY_CC=${{ matrix.compiler }} MY_STD=${{ matrix.standard }} + echo + - name: upload-codecov + uses: codecov/codecov-action@v4 + with: + plugin: gcov + file: ${{ runner.workspace }}/crypt/test/cover/coverage.info + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + verbose: false diff --git a/test/cover/make_gcov_01_generic.gmk b/test/cover/make_gcov_01_generic.gmk new file mode 100644 index 00000000..14a4b8ce --- /dev/null +++ b/test/cover/make_gcov_01_generic.gmk @@ -0,0 +1,103 @@ +# ----------------------------------------------------------------------------- +# Copyright Matt Borland 2023 - 2024. +# Copyright Christopher Kormanyos 2023 - 2024. +# Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) +# ----------------------------------------------------------------------------- + +# cd /mnt/c/ChrisGitRepos/cppalliance/crypt/test/cover +# make prepare -f make_gcov_01_generic.gmk MY_ALL_COV=0 MY_BOOST_ROOT=/mnt/c/boost/boost_1_85_0 MY_CC=g++ +# make gcov -f make_gcov_01_generic.gmk --jobs=8 MY_ALL_COV=0 MY_BOOST_ROOT=/mnt/c/boost/boost_1_85_0 MY_CC=g++ + +all: gcov + +PATH_MAKE = $(CURDIR) +PATH_SRC = $(PATH_MAKE)/../../test +PATH_BIN = $(PATH_MAKE)/bin +PATH_OBJ = $(PATH_MAKE)/obj + +CAT = cat +GNUECHO = echo +LS = ls +MKDIR = mkdir +GCOV = gcov +LCOV = lcov +GENHTML = genhtml +RM = rm + +include make_gcov_02_files.gmk +include make_gcov_03_flags.gmk + +FILES_ALL = $(FILES_PRJ) +FILES_EXE = $(addprefix $(PATH_BIN)/, $(notdir $(addsuffix .exe, $(FILES_ALL)))) + +# ----------------------------------------------------------------------------- +# VPATH definition: VPATH is required for make to find the source files. +# ----------------------------------------------------------------------------- +VPATH := $(sort $(dir $(FILES_ALL))) + + +# ----------------------------------------------------------------------------- +# Executable file: +# ----------------------------------------------------------------------------- + +.PHONY: objects +objects: $(FILES_EXE) + @$(GNUECHO) + @$(GNUECHO) +++ compile source to object then link and execute + + +# ----------------------------------------------------------------------------- +# Main dependency: +# Compile all files and link them. +# Run gcov and get results. +# (See also https://github.com/codecov/example-cpp11-cmake) +# ----------------------------------------------------------------------------- + +.PHONY: gcov +gcov: objects + @$(GNUECHO) + @$(GNUECHO) +++ running gcov + @$(GCOV) $(GCOV_FLAGS) $(addsuffix .cpp,$(FILES_PRJ)) + @$(GNUECHO) + @$(GNUECHO) +++ running lcov + @$(LCOV) $(LCOV_BRANCH) -c --directory obj --output-file coverage_unfiltered.info + @$(LCOV) $(LCOV_BRANCH) --remove coverage_unfiltered.info $(LCOV_REMOVES) --output-file coverage.info + @$(GNUECHO) + @$(GNUECHO) +++ running genhtml + @$(GENHTML) coverage.info $(LCOV_BRANCH) --demangle-cpp --output-directory $(PATH_BIN)/report + +# ----------------------------------------------------------------------------- +# Clean temporary files. +# ----------------------------------------------------------------------------- + +.PHONY: clean +clean: + @$(GNUECHO) + @$(GNUECHO) +++ cleaning output directories + @-$(RM) -rf $(PATH_BIN)* || uname -r + @-$(RM) -rf $(PATH_OBJ)* || uname -r + @-$(RM) -f *.gcov || uname -r + @-$(RM) -f coverage* || uname -r + @$(GNUECHO) + + +# ----------------------------------------------------------------------------- +# Prepare the gcov build. +# ----------------------------------------------------------------------------- + +.PHONY: prepare +prepare: clean + @$(GNUECHO) + @$(GNUECHO) +++ creating output directories + @-$(MKDIR) -p $(PATH_BIN) + @-$(MKDIR) -p $(PATH_OBJ) + @$(GNUECHO) + @$(GNUECHO) +++ print gcov version + @$(GCOV) --version + @$(GNUECHO) + @$(GNUECHO) +++ print include paths + @$(GNUECHO) $(C_INCLUDES) + +include make_gcov_04_rules.gmk diff --git a/test/cover/make_gcov_02_files.gmk b/test/cover/make_gcov_02_files.gmk new file mode 100644 index 00000000..36213b9b --- /dev/null +++ b/test/cover/make_gcov_02_files.gmk @@ -0,0 +1,21 @@ +# ----------------------------------------------------------------------------- +# Copyright Matt Borland 2023 - 2024. +# Copyright Christopher Kormanyos 2023 - 2024. +# Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) +# ----------------------------------------------------------------------------- + +FILES_PRJ := $(basename $(wildcard $(PATH_SRC)/*.cpp)) + +FILES_EXCLUDE := $(PATH_SRC)/concepts_test.cpp \ + $(PATH_SRC)/link_1.cpp \ + $(PATH_SRC)/link_2.cpp \ + $(PATH_SRC)/link_3.cpp \ + $(PATH_SRC)/test_bad_evaluation_method.cpp \ + $(PATH_SRC)/test_explicit_floats.cpp \ + $(PATH_SRC)/test_from_chars.cpp + +FILES_EXCLUDE := $(basename $(FILES_EXCLUDE)) + +FILES_PRJ := $(filter-out $(FILES_EXCLUDE),$(FILES_PRJ)) diff --git a/test/cover/make_gcov_03_flags.gmk b/test/cover/make_gcov_03_flags.gmk new file mode 100644 index 00000000..7605ad96 --- /dev/null +++ b/test/cover/make_gcov_03_flags.gmk @@ -0,0 +1,73 @@ +# ----------------------------------------------------------------------------- +# Copyright Matt Borland 2023. +# Copyright Christopher Kormanyos 2023. +# Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) +# ----------------------------------------------------------------------------- + +CC = g++ +STD = c++20 +ALL_COV = 0 + +ifneq ($(MY_BOOST_ROOT),) +BOOST_ROOT_FOR_GCOV := $(MY_BOOST_ROOT) +endif + +ifneq ($(MY_CC),) +CC := $(MY_CC) +endif + +ifneq ($(MY_STD),) +STD := $(MY_STD) +endif + +ifneq ($(MY_ALL_COV),) +ALL_COV := $(MY_ALL_COV) +endif + +CXXFLAGS = -march=native \ + -mtune=native \ + -O1 \ + -Wextra \ + -Wall \ + -fno-inline-functions \ + -fprofile-arcs \ + -ftest-coverage + +C_DEFINES = + +C_INCLUDES = $(PATH_SRC) \ + $(PATH_SRC)/../include \ + $(BOOST_ROOT_FOR_GCOV) + +C_DEFINES :=$(addprefix -D,$(C_DEFINES)) +C_INCLUDES :=$(addprefix -I,$(C_INCLUDES)) + +GCOV_FLAGS = --object-directory obj \ + --demangled-names + + +# ----------------------------------------------------------------------------- +# All gcov flags: The GCOV_FLAGS below are equivalent to -abcfu +# ----------------------------------------------------------------------------- + +ifneq ($(ALL_COV),0) +GCOV_FLAGS := $(GCOV_FLAGS) \ + --all-blocks \ + --branch-counts \ + --branch-probabilities \ + --function-summaries \ + --unconditional-branches +endif + +LCOV_BRANCH = + +ifneq ($(ALL_COV),0) +LCOV_BRANCH := --rc lcov_branch_coverage=1 +endif + +LCOV_REMOVES = '*/test/mini_to_chars.hpp' \ + '*$(MY_BOOST_ROOT)*' \ + '*/boost-root/*' \ + '/usr/*' diff --git a/test/cover/make_gcov_04_rules.gmk b/test/cover/make_gcov_04_rules.gmk new file mode 100644 index 00000000..05dc73a1 --- /dev/null +++ b/test/cover/make_gcov_04_rules.gmk @@ -0,0 +1,22 @@ +# ----------------------------------------------------------------------------- +# Copyright Matt Borland 2023. +# Copyright Christopher Kormanyos 2023. +# Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://www.boost.org/LICENSE_1_0.txt) +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# special flags (on pattern rule) for compilation of files needing threads +# Note: Each file with threads must be specifically, manually listed here. +# Note: TBD: We can/will use a similar method for libquadmath needs. +# ----------------------------------------------------------------------------- +$(PATH_BIN)/test_frexp_ldexp.exe : $(CXXFLAGS) += -pthread -lpthread + + +# ----------------------------------------------------------------------------- +# pattern rule for compilation of cpp-files +# ----------------------------------------------------------------------------- +$(PATH_BIN)/%.exe : %.cpp + @-$(GNUECHO) +++ compile and link and execute: $(notdir $<) to $(notdir $(PATH_BIN)/$(basename $(@F)).exe) + @-$(CC) $(CXXFLAGS) -x c++ -c $(C_INCLUDES) $(C_DEFINES) $< -o $(PATH_OBJ)/$(basename $(@F)).o && $(CC) $(CXXFLAGS) $(PATH_OBJ)/$(basename $(@F)).o -o $(PATH_BIN)/$(basename $(@F)).exe && $(PATH_BIN)/$(basename $(@F)).exe From fdae13a22c86b65ab939e1fbe254d295de5681da Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:09:07 -0400 Subject: [PATCH 15/76] Add github actions CI --- .github/workflows/ci.yml | 798 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 798 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..ca1434ee --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,798 @@ +# Copyright 2021-2022 Andrey Semashev +# Copyright 2023 Matt Borland +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +name: CI + +on: + pull_request: + push: + branches: + - master + - develop + - feature/** + +concurrency: + group: ${{format('{0}:{1}', github.repository, github.ref)}} + cancel-in-progress: true + +env: + GIT_FETCH_JOBS: 8 + NET_RETRY_COUNT: 5 + DEFAULT_BUILD_VARIANT: debug,release + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true + +jobs: + posix: + defaults: + run: + shell: bash + + strategy: + fail-fast: false + matrix: + include: + - toolset: gcc-7 + cxxstd: "03,11,14,17" + address_model: 32,64 + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-7-multilib + - toolset: gcc-8 + cxxstd: "03,11,14,17,2a" + address_model: 32,64 + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-8-multilib + - toolset: gcc-9 + cxxstd: "03,11,14,17,2a" + address_model: 32,64 + os: ubuntu-20.04 + install: + - g++-9-multilib + - toolset: gcc-9 + cxxstd: "03-gnu,11-gnu,14-gnu,17-gnu,2a-gnu" + address_model: 32,64 + os: ubuntu-20.04 + install: + - g++-9-multilib + - toolset: gcc-10 + cxxstd: "03,11,14,17,20" + address_model: 32,64 + os: ubuntu-20.04 + install: + - g++-10-multilib + - toolset: gcc-11 + cxxstd: "03,11,14,17,20,23" + address_model: 32,64 + os: ubuntu-22.04 + install: + - g++-11-multilib + - toolset: gcc-12 + cxxstd: "03,11,14,17,20,23" + address_model: 32,64 + os: ubuntu-22.04 + install: + - g++-12-multilib + # Disabled for now. 22.04 dropped support and 24.04 has internal errors + #- toolset: gcc-13 + # cxxstd: "03,11,14,17,20,23" + # address_model: 32,64 + # os: ubuntu-24.04 + # install: + # - g++-13-multilib + # cxxflags: -Wno-uninitialized + - toolset: gcc-12 + cxxstd: "03-gnu,11-gnu,14-gnu,17-gnu,20-gnu,23-gnu" + address_model: "32" + os: ubuntu-22.04 + install: + - g++-12-multilib + - toolset: gcc-12 + cxxstd: "03-gnu,11-gnu,14-gnu,17-gnu,20-gnu,23-gnu" + address_model: "64" + os: ubuntu-22.04 + install: + - g++-12-multilib + - name: 32-bit UBSAN + toolset: gcc-12 + cxxstd: "03,11,14,17,20,23" + address_model: "32" + ubsan: 1 + os: ubuntu-22.04 + install: + - g++-12-multilib + - name: 64-bit UBSAN + toolset: gcc-12 + cxxstd: "03,11,14,17,20,23" + address_model: "64" + ubsan: 1 + os: ubuntu-22.04 + install: + - g++-12-multilib + + # Linux, clang + - toolset: clang + compiler: clang++-6.0 + cxxstd: "03,11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-6.0 + - toolset: clang + compiler: clang++-7 + cxxstd: "03,11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-7 + # Note: clang-8 does not fully support C++20, so it is not compatible with libstdc++-8 in this mode + - toolset: clang + compiler: clang++-8 + cxxstd: "03,11,14,17,2a" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-8 + - g++-7 + gcc_toolchain: 7 + - toolset: clang + compiler: clang++-9 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + install: + - clang-9 + - toolset: clang + compiler: clang++-10 + cxxstd: "03,11,14,17,20" + os: ubuntu-20.04 + install: + - clang-10 + - toolset: clang + compiler: clang++-11 + cxxstd: "03,11,14,17" + os: ubuntu-22.04 + install: + - clang-11 + - toolset: clang + compiler: clang++-12 + cxxstd: "03,11,14,17" + os: ubuntu-22.04 + install: + - clang-12 + - toolset: clang + compiler: clang++-13 + cxxstd: "03,11,14,17" + os: ubuntu-22.04 + install: + - clang-13 + - toolset: clang + compiler: clang++-14 + cxxstd: "03,11,14,17" + os: ubuntu-22.04 + install: + - clang-14 + - toolset: clang + compiler: clang++-14 + cxxstd: "03-gnu,11-gnu,14-gnu,17-gnu" + os: ubuntu-22.04 + install: + - clang-14 + - toolset: clang + compiler: clang++-15 + cxxstd: "03,11,14,17,20" + os: ubuntu-22.04 + install: + - clang-15 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-15 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-15 + - libc++-15-dev + - libc++abi-15-dev + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ + - toolset: clang + compiler: clang++-16 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-16 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-17 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-17 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - name: UBSAN + toolset: clang + compiler: clang++-14 + cxxstd: "03,11,14,17,20,2b" + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ + ubsan: 1 + os: ubuntu-22.04 + install: + - clang-14 + - libc++-14-dev + - libc++abi-14-dev + + - toolset: clang + cxxstd: "03,11,14,17,20,2b" + os: macos-12 + - toolset: clang + cxxstd: "03,11,14,17,20,2b" + os: macos-13 + - toolset: clang + cxxstd: "03,11,14,17,20,2b" + os: macos-14 + + timeout-minutes: 180 + runs-on: ${{matrix.os}} + container: ${{matrix.container}} + + steps: + - name: Setup environment + run: | + if [ -f "/etc/debian_version" ] + then + echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV + export DEBIAN_FRONTEND=noninteractive + fi + if [ -n "${{matrix.container}}" ] + then + echo "GHA_CONTAINER=${{matrix.container}}" >> $GITHUB_ENV + if [ -f "/etc/debian_version" ] + then + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + if [ "$(apt-cache search "^python-is-python3$" | wc -l)" -ne 0 ] + then + PYTHON_PACKAGE="python-is-python3" + else + PYTHON_PACKAGE="python" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ $PYTHON_PACKAGE python3 perl git cmake + fi + fi + git config --global pack.threads 0 + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: | + declare -a SOURCE_KEYS SOURCES + if [ -n "${{join(matrix.source_keys, ' ')}}" ] + then + SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}") + fi + if [ -n "${{join(matrix.sources, ' ')}}" ] + then + SOURCES=("${{join(matrix.sources, '" "')}}") + fi + for key in "${SOURCE_KEYS[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + echo "Adding key: $key" + wget -O - "$key" | sudo apt-key add - && break || sleep 2 + done + done + if [ ${#SOURCES[@]} -gt 0 ] + then + APT_ADD_REPO_COMMON_ARGS=("-y") + APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')" + if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ] + then + APT_ADD_REPO_COMMON_ARGS+=("-n") + fi + APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)" + for source in "${SOURCES[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + APT_ADD_REPO_ARGS=("${APT_ADD_REPO_COMMON_ARGS[@]}") + if [ $APT_ADD_REPO_HAS_SOURCE_ARGS -ne 0 ] + then + case "$source" in + "ppa:"*) + APT_ADD_REPO_ARGS+=("-P") + ;; + "deb "*) + APT_ADD_REPO_ARGS+=("-S") + ;; + *) + APT_ADD_REPO_ARGS+=("-U") + ;; + esac + fi + APT_ADD_REPO_ARGS+=("$source") + echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}" + sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2 + done + done + fi + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y ${{join(matrix.install, ' ')}} locales + sudo locale-gen de_DE.UTF-8 + sudo update-locale + - name: Setup GCC Toolchain + if: matrix.gcc_toolchain + run: | + GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain" + echo "GCC_TOOLCHAIN_ROOT=\"$GCC_TOOLCHAIN_ROOT\"" >> $GITHUB_ENV + MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" + mkdir -p "$GCC_TOOLCHAIN_ROOT" + ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include" + ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin" + mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET" + ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) + echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV + echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV + DEPINST_ARGS=() + GIT_VERSION="$(git --version | sed -e 's/git version //')" + GIT_HAS_JOBS=1 + if [ -f "/etc/debian_version" ] + then + if $(dpkg --compare-versions "$GIT_VERSION" lt 2.8.0) + then + GIT_HAS_JOBS=0 + fi + else + declare -a GIT_VER=(${GIT_VERSION//./ }) + declare -a GIT_MIN_VER=(2 8 0) + for ((i=0; i<${#GIT_VER[@]}; i++)) + do + if [ -z "${GIT_MIN_VER[i]}" ] + then + GIT_MIN_VER[i]=0 + fi + if [ "${GIT_VER[i]}" -lt "${GIT_MIN_VER[i]}" ] + then + GIT_HAS_JOBS=0 + break + fi + done + fi + if [ "$GIT_HAS_JOBS" -ne 0 ] + then + DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS") + fi + cd .. + git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root" + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + DEPINST_ARGS+=("$LIBRARY") + python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}" + if [ -z "${{matrix.cmake_tests}}" ] + then + ./bootstrap.sh + ./b2 headers + if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam + if [ -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam + fi + echo " ;" >> ~/user-config.jam + fi + fi + - name: Run tests + if: matrix.cmake_tests == '' + run: | + cd ../boost-root + B2_ARGS=("-j" "$BUILD_JOBS" "toolset=${{matrix.toolset}}" "cxxstd=${{matrix.cxxstd}}" "link=static,shared") + if [ -n "${{matrix.build_variant}}" ] + then + B2_ARGS+=("variant=${{matrix.build_variant}}") + else + B2_ARGS+=("variant=$DEFAULT_BUILD_VARIANT") + fi + if [ -n "${{matrix.threading}}" ] + then + B2_ARGS+=("threading=${{matrix.threading}}") + fi + if [ -n "${{matrix.ubsan}}" ] + then + export UBSAN_OPTIONS="print_stacktrace=1" + B2_ARGS+=("cxxflags=-fsanitize=undefined -fno-sanitize-recover=undefined" "linkflags=-fsanitize=undefined -fuse-ld=gold" "define=UBSAN=1" "debug-symbols=on" "visibility=global") + fi + if [ -n "${{matrix.cxxflags}}" ] + then + B2_ARGS+=("cxxflags=${{matrix.cxxflags}}") + fi + if [ -n "${{matrix.linkflags}}" ] + then + B2_ARGS+=("linkflags=${{matrix.linkflags}}") + fi + if [ -n "${{matrix.address_model}}" ] + then + B2_ARGS+=("address-model=${{matrix.address_model}}") + fi + B2_ARGS+=("libs/$LIBRARY/test") + ./b2 "${B2_ARGS[@]}" cxxflags="-Wall -Wextra -Werror" + + windows: + strategy: + fail-fast: false + matrix: + include: + - toolset: msvc-14.2 + cxxstd: "14,17,20,latest" + addrmd: "32" + os: windows-2019 + # B2 does not work with MSVC 17.10. Once it's updated we can re-enable these tests + # Still covered in drone + #- toolset: msvc-14.3 + # cxxstd: "14,17,20,latest" + # addrmd: "32" + # os: windows-2022 + - toolset: msvc-14.2 + cxxstd: "14,17,20,latest" + addrmd: "64" + os: windows-2019 + #- toolset: msvc-14.3 + # cxxstd: "14,17,20,latest" + # addrmd: "64" + # os: windows-2022 + #- toolset: clang-win + # cxxstd: "14,17,latest" + # addrmd: "32" + # os: windows-2022 + #- toolset: clang-win + # cxxstd: "14,17,latest" + # addrmd: "64" + # os: windows-2022 + - toolset: gcc + cxxstd: "03,11,14,17,2a" + addrmd: "64" + os: windows-2019 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + cmd /c bootstrap + b2 -d0 headers + + - name: Run tests + shell: cmd + run: | + cd ../boost-root + b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release link=static,shared embed-manifest-via=linker + + posix-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-12 + - os: macos-13 + - os: macos-14 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Use library with add_subdirectory + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-12 + - os: macos-13 + - os: macos-14 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. + + - name: Install + run: | + cd ../boost-root/__build__ + cmake --build . --target install + + - name: Use the installed library + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=~/.local .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-12 + - os: macos-13 + - os: macos-14 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. + + - name: Build tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + + - name: Run tests + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error + + MSYS2: + defaults: + run: + shell: msys2 {0} + strategy: + fail-fast: false + matrix: + include: + - { sys: MINGW32, compiler: gcc, cxxstd: '03,11,17,20' } + - { sys: MINGW64, compiler: gcc, cxxstd: '03,11,17,20' } + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Setup MSYS2 environment + uses: msys2/setup-msys2@v2 + with: + msystem: ${{matrix.sys}} + update: true + install: git python + pacboy: gcc:p cmake:p ninja:p + + - name: Fetch Boost.CI + uses: actions/checkout@v3 + with: + repository: boostorg/boost-ci + ref: master + path: boost-ci-cloned + - name: Get CI scripts folder + run: | + # Copy ci folder if not testing Boost.CI + [[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci . + rm -rf boost-ci-cloned + + - name: Setup Boost + env: + B2_COMPILER: ${{matrix.compiler}} + B2_CXXSTD: ${{matrix.cxxstd}} + B2_SANITIZE: ${{matrix.sanitize}} + B2_STDLIB: ${{matrix.stdlib}} + run: ci/github/install.sh + + - name: Run tests + run: ci/build.sh + + intel: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + compiler: [ intel ] + standard: [ c++20 ] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: '0' + + - name: Intel Apt repository + timeout-minutes: 1 + run: | + wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB + sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB + rm GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB + echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list + sudo apt-get update + - name: Install Intel oneAPI compilers + timeout-minutes: 5 + run: sudo apt-get install -y intel-oneapi-compiler-fortran intel-oneapi-compiler-dpcpp-cpp + + - name: Setup Intel oneAPI environment + run: | + source /opt/intel/oneapi/setvars.sh + printenv >> $GITHUB_ENV + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. + + - name: Build tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + + - name: Run tests + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error From 2c57a4a8ccfaae1da19ae85af1eeefea0fc7942d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:14:16 -0400 Subject: [PATCH 16/76] Add fuzzing --- .github/workflows/fuzz.yml | 289 +++++++++++++++++++++++++++++++++++++ fuzzing/.gitignore | 7 + fuzzing/Jamfile | 66 +++++++++ fuzzing/fuzz_md5.cpp | 26 ++++ 4 files changed, 388 insertions(+) create mode 100644 .github/workflows/fuzz.yml create mode 100644 fuzzing/.gitignore create mode 100644 fuzzing/Jamfile create mode 100644 fuzzing/fuzz_md5.cpp diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml new file mode 100644 index 00000000..4487018f --- /dev/null +++ b/.github/workflows/fuzz.yml @@ -0,0 +1,289 @@ +# Copyright 2021-2022 Andrey Semashev +# Copyright 2024 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +name: Fuzz + +on: + pull_request: + push: + branches: + - master + - develop + - feature/** + +env: + GIT_FETCH_JOBS: 8 + NET_RETRY_COUNT: 5 + DEFAULT_BUILD_VARIANT: debug,release + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true + +jobs: + posix: + defaults: + run: + shell: bash + + strategy: + fail-fast: false + matrix: + include: + + # Linux, clang + # https://llvm.org/docs/LibFuzzer.html#fuzzer-usage + - toolset: clang + compiler: clang++-12 + cxxstd: "14,17,20" + os: ubuntu-22.04 + install: + - clang-12 + - toolset: clang + compiler: clang++-13 + cxxstd: "14,17,20" + os: ubuntu-22.04 + install: + - clang-13 + - toolset: clang + compiler: clang++-14 + cxxstd: "14,17,20" + os: ubuntu-22.04 + install: + - clang-14 + - toolset: clang + compiler: clang++-14 + cxxstd: "14-gnu,17-gnu,20-gnu" + os: ubuntu-22.04 + install: + - clang-14 + - toolset: clang + compiler: clang++-15 + cxxstd: "14,17,20" + os: ubuntu-22.04 + install: + - clang-15 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-16 + cxxstd: "14,17,20" + os: ubuntu-22.04 + install: + - clang-16 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-17 + cxxstd: "14,17,20" + os: ubuntu-22.04 + install: + - clang-17 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + + + timeout-minutes: 60 + runs-on: ${{matrix.os}} + container: ${{matrix.container}} + + steps: + - name: Setup environment + run: | + if [ -f "/etc/debian_version" ] + then + echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV + export DEBIAN_FRONTEND=noninteractive + fi + if [ -n "${{matrix.container}}" ] + then + echo "GHA_CONTAINER=${{matrix.container}}" >> $GITHUB_ENV + if [ -f "/etc/debian_version" ] + then + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + if [ "$(apt-cache search "^python-is-python3$" | wc -l)" -ne 0 ] + then + PYTHON_PACKAGE="python-is-python3" + else + PYTHON_PACKAGE="python" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ $PYTHON_PACKAGE python3 perl git cmake + fi + fi + git config --global pack.threads 0 + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: | + declare -a SOURCE_KEYS SOURCES + if [ -n "${{join(matrix.source_keys, ' ')}}" ] + then + SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}") + fi + if [ -n "${{join(matrix.sources, ' ')}}" ] + then + SOURCES=("${{join(matrix.sources, '" "')}}") + fi + for key in "${SOURCE_KEYS[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + echo "Adding key: $key" + wget -O - "$key" | sudo apt-key add - && break || sleep 2 + done + done + if [ ${#SOURCES[@]} -gt 0 ] + then + APT_ADD_REPO_COMMON_ARGS=("-y") + APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')" + if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ] + then + APT_ADD_REPO_COMMON_ARGS+=("-n") + fi + APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)" + for source in "${SOURCES[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + APT_ADD_REPO_ARGS=("${APT_ADD_REPO_COMMON_ARGS[@]}") + if [ $APT_ADD_REPO_HAS_SOURCE_ARGS -ne 0 ] + then + case "$source" in + "ppa:"*) + APT_ADD_REPO_ARGS+=("-P") + ;; + "deb "*) + APT_ADD_REPO_ARGS+=("-S") + ;; + *) + APT_ADD_REPO_ARGS+=("-U") + ;; + esac + fi + APT_ADD_REPO_ARGS+=("$source") + echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}" + sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2 + done + done + fi + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y ${{join(matrix.install, ' ')}} locales + sudo locale-gen de_DE.UTF-8 + sudo update-locale + - name: Setup GCC Toolchain + if: matrix.gcc_toolchain + run: | + GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain" + echo "GCC_TOOLCHAIN_ROOT=\"$GCC_TOOLCHAIN_ROOT\"" >> $GITHUB_ENV + MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" + mkdir -p "$GCC_TOOLCHAIN_ROOT" + ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include" + ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin" + mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET" + ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) + echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV + echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV + DEPINST_ARGS=() + GIT_VERSION="$(git --version | sed -e 's/git version //')" + GIT_HAS_JOBS=1 + if [ -f "/etc/debian_version" ] + then + if $(dpkg --compare-versions "$GIT_VERSION" lt 2.8.0) + then + GIT_HAS_JOBS=0 + fi + else + declare -a GIT_VER=(${GIT_VERSION//./ }) + declare -a GIT_MIN_VER=(2 8 0) + for ((i=0; i<${#GIT_VER[@]}; i++)) + do + if [ -z "${GIT_MIN_VER[i]}" ] + then + GIT_MIN_VER[i]=0 + fi + if [ "${GIT_VER[i]}" -lt "${GIT_MIN_VER[i]}" ] + then + GIT_HAS_JOBS=0 + break + fi + done + fi + if [ "$GIT_HAS_JOBS" -ne 0 ] + then + DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS") + fi + cd .. + git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root" + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + DEPINST_ARGS+=("$LIBRARY") + python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}" + if [ -z "${{matrix.cmake_tests}}" ] + then + ./bootstrap.sh + ./b2 headers + if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam + if [ -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam + fi + echo " ;" >> ~/user-config.jam + fi + fi + - name: Run tests + if: matrix.cmake_tests == '' + run: | + cd ../boost-root/libs/$LIBRARY/fuzzing + B2_ARGS=("-j" "$BUILD_JOBS" "toolset=${{matrix.toolset}}" "cxxstd=${{matrix.cxxstd}}" "link=static,shared") + if [ -n "${{matrix.build_variant}}" ] + then + B2_ARGS+=("variant=${{matrix.build_variant}}") + else + B2_ARGS+=("variant=$DEFAULT_BUILD_VARIANT") + fi + if [ -n "${{matrix.threading}}" ] + then + B2_ARGS+=("threading=${{matrix.threading}}") + fi + if [ -n "${{matrix.ubsan}}" ] + then + export UBSAN_OPTIONS="print_stacktrace=1" + B2_ARGS+=("cxxflags=-fsanitize=undefined -fno-sanitize-recover=undefined" "linkflags=-fsanitize=undefined -fuse-ld=gold" "define=UBSAN=1" "debug-symbols=on" "visibility=global") + fi + if [ -n "${{matrix.cxxflags}}" ] + then + B2_ARGS+=("cxxflags=${{matrix.cxxflags}}") + fi + if [ -n "${{matrix.linkflags}}" ] + then + B2_ARGS+=("linkflags=${{matrix.linkflags}}") + fi + if [ -n "${{matrix.address_model}}" ] + then + B2_ARGS+=("address-model=${{matrix.address_model}}") + fi + ../../../b2 "${B2_ARGS[@]}" diff --git a/fuzzing/.gitignore b/fuzzing/.gitignore new file mode 100644 index 00000000..38846572 --- /dev/null +++ b/fuzzing/.gitignore @@ -0,0 +1,7 @@ +cmin/ +out/ +oldcorpus/ +seedcorpus/ +corpus.tar +out*/ +fuzz-*.log diff --git a/fuzzing/Jamfile b/fuzzing/Jamfile new file mode 100644 index 00000000..4739898a --- /dev/null +++ b/fuzzing/Jamfile @@ -0,0 +1,66 @@ +# +# Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) +# Copyright (c) 2024 Matt Borland +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +import common ; +import regex ; + +local all_fuzzers = [ regex.replace-list + [ glob "fuzz_*.cpp" ] : ".cpp" : "" +] ; + +for local fuzzer in $(all_fuzzers) +{ + # These two fuzzers are the most complex ones. The rest are really + # simple, so less time is enough + local fuzz_time = 30 ; + + # Create the output corpus directories + make /tmp/corpus/$(fuzzer) : : common.MkDir ; + make /tmp/mincorpus/$(fuzzer) : : common.MkDir ; + + # Build the fuzzer + exe $(fuzzer) + : + $(fuzzer).cpp + : requirements + on + speed + on + norecover + -fsanitize=fuzzer + -fsanitize=fuzzer + ; + + # Make sure that any old crashes are run without problems + local old_crashes = [ glob-tree-ex old_crashes/$(fuzzer) : * ] ; + if $(old_crashes) + { + run $(fuzzer) + : target-name $(fuzzer)-old-crashes + : input-files [ SORT $(old_crashes) ] + ; + } + + # Run the fuzzer for a short while + run $(fuzzer) + : "seedcorpus/$(fuzzer) -max_total_time=$(fuzz_time)" + : target-name $(fuzzer)-fuzzing + : requirements + /tmp/corpus/$(fuzzer) + ; + + # Minimize the corpus + run $(fuzzer) + : "/tmp/mincorpus/$(fuzzer) /tmp/corpus/$(fuzzer) -merge=1" + : target-name $(fuzzer)-minimize-corpus + : requirements + $(fuzzer)-fuzzing + /tmp/corpus/$(fuzzer) + /tmp/mincorpus/$(fuzzer) + ; +} diff --git a/fuzzing/fuzz_md5.cpp b/fuzzing/fuzz_md5.cpp new file mode 100644 index 00000000..ee708888 --- /dev/null +++ b/fuzzing/fuzz_md5.cpp @@ -0,0 +1,26 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size) +{ + try + { + auto c_data = reinterpret_cast(data); + std::string c_data_str {c_data, size}; // Guarantee null termination since we can't pass the size argument + + boost::crypt::md5(c_data_str); + } + catch(...) + { + std::cerr << "Error with: " << data << std::endl; + std::terminate(); + } + + return 0; +} From 9634af0e2f63ff47132edd999f53a78088d6d580 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:17:46 -0400 Subject: [PATCH 17/76] Add CMake install and subdir testing --- test/Jamfile | 1 + test/cmake_install_test/CMakeLists.txt | 17 ++++++++++++ test/cmake_subdir_test/CMakeLists.txt | 37 ++++++++++++++++++++++++++ test/quick.cpp | 10 +++++++ 4 files changed, 65 insertions(+) create mode 100644 test/cmake_install_test/CMakeLists.txt create mode 100644 test/cmake_subdir_test/CMakeLists.txt create mode 100644 test/quick.cpp diff --git a/test/Jamfile b/test/Jamfile index d0306e49..201cf17f 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -41,4 +41,5 @@ project : requirements [ requires cxx14_decltype_auto cxx14_generic_lambdas cxx14_return_type_deduction cxx14_variable_templates cxx14_constexpr ] ; +run quick.cpp ; run test_md5.cpp ; diff --git a/test/cmake_install_test/CMakeLists.txt b/test/cmake_install_test/CMakeLists.txt new file mode 100644 index 00000000..83a2bf0b --- /dev/null +++ b/test/cmake_install_test/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.16) + +project(cmake_install_test LANGUAGES CXX) + +find_package(boost_quick REQUIRED) + +add_executable(quick ../quick.cpp) +target_link_libraries(quick Boost::quick) + +enable_testing() +add_test(quick quick) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt new file mode 100644 index 00000000..0ac83cf8 --- /dev/null +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.20) + +project(cmake_subdir_test LANGUAGES CXX) + +add_subdirectory(../.. boostorg/crypt) + +set(deps + +# Primary dependencies + +assert +config +core + +# Secondary dependencies + +static_assert +throw_exception +) + +foreach(dep IN LISTS deps) + + add_subdirectory(../../../${dep} boostorg/${dep}) + +endforeach() + +add_executable(quick ../quick.cpp) +target_link_libraries(quick Boost::crypt) + +enable_testing() +add_test(quick quick) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/quick.cpp b/test/quick.cpp new file mode 100644 index 00000000..ca796b7b --- /dev/null +++ b/test/quick.cpp @@ -0,0 +1,10 @@ +// Copyright 2023 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +auto main() -> int +{ + return 0; +} From b82683749f9da54c668513b7d94f75c27ac7939c Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:18:20 -0400 Subject: [PATCH 18/76] Add the seed corpus --- fuzzing/seedcorpus/fuzz_md5/md5.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 fuzzing/seedcorpus/fuzz_md5/md5.txt diff --git a/fuzzing/seedcorpus/fuzz_md5/md5.txt b/fuzzing/seedcorpus/fuzz_md5/md5.txt new file mode 100644 index 00000000..48e3b98c --- /dev/null +++ b/fuzzing/seedcorpus/fuzz_md5/md5.txt @@ -0,0 +1,18 @@ +"The quick brown fox jumps over the lazy dog" +"The quick brown fox jumps over the lazy dog." +"" +"aB3$x9Yz" +"12345" +"!@#$%^&*()" +"FuzzTest123" +" " +"Lorem ipsum dolor sit amet" +"a" +"9876543210" +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"ñÑáéíóúÁÉÍÓÚ" +"\n\r\t" +"0" +"ThisIsAVeryLongStringWithNoSpacesOrPunctuationToTestEdgeCases" +"" +"SELECT * FROM users;" From 392aebcb1eefedbaeeeadb4634e9404b7c997383 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:26:03 -0400 Subject: [PATCH 19/76] Fix typo --- test/cmake_install_test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmake_install_test/CMakeLists.txt b/test/cmake_install_test/CMakeLists.txt index 83a2bf0b..5cbfe3db 100644 --- a/test/cmake_install_test/CMakeLists.txt +++ b/test/cmake_install_test/CMakeLists.txt @@ -9,7 +9,7 @@ project(cmake_install_test LANGUAGES CXX) find_package(boost_quick REQUIRED) add_executable(quick ../quick.cpp) -target_link_libraries(quick Boost::quick) +target_link_libraries(quick Boost::crypt) enable_testing() add_test(quick quick) From 04e7d07ecc3f39c73e30d4672ad69cb7d668692c Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:26:44 -0400 Subject: [PATCH 20/76] Add missing headers --- include/boost/crypt/hash/md5.hpp | 2 ++ include/boost/crypt/utility/bit.hpp | 1 + 2 files changed, 3 insertions(+) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 33bf8396..0bdad19c 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -10,7 +10,9 @@ #include #include +#include #include +#include namespace boost { namespace crypt { diff --git a/include/boost/crypt/utility/bit.hpp b/include/boost/crypt/utility/bit.hpp index 36e93de3..55fe9dc7 100644 --- a/include/boost/crypt/utility/bit.hpp +++ b/include/boost/crypt/utility/bit.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace boost { namespace crypt { From d42854f36ec8a26c4aac98a441f9d0991baf4c29 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:40:44 -0400 Subject: [PATCH 21/76] Fix testing --- test/cmake_install_test/CMakeLists.txt | 2 +- test/test_md5.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/cmake_install_test/CMakeLists.txt b/test/cmake_install_test/CMakeLists.txt index 5cbfe3db..d8597268 100644 --- a/test/cmake_install_test/CMakeLists.txt +++ b/test/cmake_install_test/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.5...3.16) project(cmake_install_test LANGUAGES CXX) -find_package(boost_quick REQUIRED) +find_package(boost_crypt REQUIRED) add_executable(quick ../quick.cpp) target_link_libraries(quick Boost::crypt) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 83ee3f51..04470d42 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -74,6 +74,7 @@ void bad_input() int main() { basic_tests(); + string_test(); bad_input(); return boost::report_errors(); From efbe3cea0a0c7d11dba0d71710fa9b003472d685 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:44:58 -0400 Subject: [PATCH 22/76] Use std::transform instead of std::copy --- include/boost/crypt/hash/md5.hpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 0bdad19c..0295dcb0 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -50,7 +51,13 @@ auto md5_preprocess(T begin, T end) -> std::vector { std::vector vec; vec.reserve(static_cast(end - begin)); - std::copy(begin, end, std::back_inserter(vec)); + + // Like std::copy but gives us the correct cast + std::transform(begin, end, std::back_inserter(vec), + [](const auto& element) { + return static_cast(element); + }); + return vec; } @@ -59,7 +66,12 @@ auto md5_preprocess(T begin, std::size_t len) -> std::vector { std::vector vec; vec.reserve(len); - std::copy(begin, begin + len, std::back_inserter(vec)); + + std::transform(begin, begin + len, std::back_inserter(vec), + [](const auto& element) { + return static_cast(element); + }); + return vec; } From 15db237102e936cfe8c06a154bec6d20b2544d13 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:45:04 -0400 Subject: [PATCH 23/76] CI fixes --- .github/workflows/ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca1434ee..66ba35dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -241,7 +241,7 @@ jobs: - toolset: clang cxxstd: "03,11,14,17,20,2b" - os: macos-12 + os: macos-15 - toolset: clang cxxstd: "03,11,14,17,20,2b" os: macos-13 @@ -461,18 +461,18 @@ jobs: os: windows-2019 # B2 does not work with MSVC 17.10. Once it's updated we can re-enable these tests # Still covered in drone - #- toolset: msvc-14.3 - # cxxstd: "14,17,20,latest" - # addrmd: "32" - # os: windows-2022 + - toolset: msvc-14.3 + cxxstd: "14,17,20,latest" + addrmd: "32" + os: windows-2022 - toolset: msvc-14.2 cxxstd: "14,17,20,latest" addrmd: "64" os: windows-2019 - #- toolset: msvc-14.3 - # cxxstd: "14,17,20,latest" - # addrmd: "64" - # os: windows-2022 + - toolset: msvc-14.3 + cxxstd: "14,17,20,latest" + addrmd: "64" + os: windows-2022 #- toolset: clang-win # cxxstd: "14,17,latest" # addrmd: "32" @@ -526,7 +526,7 @@ jobs: include: - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: macos-12 + - os: macos-15 - os: macos-13 - os: macos-14 @@ -575,7 +575,7 @@ jobs: include: - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: macos-12 + - os: macos-15 - os: macos-13 - os: macos-14 @@ -634,7 +634,7 @@ jobs: include: - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: macos-12 + - os: macos-15 - os: macos-13 - os: macos-14 From 3b05377b8e4a5ddd730e7cbb91b045a6c6240e49 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:49:34 -0400 Subject: [PATCH 24/76] Add meta file --- meta/libraries.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 meta/libraries.json diff --git a/meta/libraries.json b/meta/libraries.json new file mode 100644 index 00000000..b01c225e --- /dev/null +++ b/meta/libraries.json @@ -0,0 +1,17 @@ +{ + "key": "crypt", + "name": "Crypt", + "authors": [ + "Matt Borland", + "Christopher Kormanyos" + ], + "maintainers": [ + "Matt Borland ", + "Christopher Kormanyos " + ], + "description": "A module of cryptographic utilities.", + "category": [ + "Math and numerics" + ], + "cxxstd": "14" +} From 6844616bcba9a5114af90928255ada9ff48545f8 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:50:03 -0400 Subject: [PATCH 25/76] Add PPC64LE QEMU run --- .github/workflows/qemu.yml | 206 +++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 .github/workflows/qemu.yml diff --git a/.github/workflows/qemu.yml b/.github/workflows/qemu.yml new file mode 100644 index 00000000..08bbfdc7 --- /dev/null +++ b/.github/workflows/qemu.yml @@ -0,0 +1,206 @@ +# Copyright 2020-2021 Peter Dimov +# Copyright 2021 Andrey Semashev +# Copyright 2021 Alexander Grund +# Copyright 2022 James E. King III +# Copyright 2024 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) +--- +name: qemu + +on: + pull_request: + push: + branches: + - master + - develop + - bugfix/** + - feature/** + - fix/** + - pr/** + +env: + GIT_FETCH_JOBS: 8 + NET_RETRY_COUNT: 5 + B2_CI_VERSION: 1 + B2_VARIANT: release + B2_LINK: static + LCOV_BRANCH_COVERAGE: 0 + CODECOV_NAME: Github Actions + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true + +jobs: + posix: + defaults: + run: + shell: bash + + strategy: + fail-fast: false + matrix: + include: + # multiarch testing + - { name: PPC64LE-GCC, multiarch: yes, + compiler: gcc, cxxstd: '14', os: ubuntu-22.04, ccache: no, distro: alpine, edition: edge, arch: ppc64le } + - { name: PPC64LE-Clang, multiarch: yes, + compiler: clang, cxxstd: '14', os: ubuntu-22.04, ccache: no, distro: alpine, edition: edge, arch: ppc64le } + + + timeout-minutes: 360 + runs-on: ${{matrix.os}} + container: ${{matrix.container}} + env: {B2_USE_CCACHE: 1} + + steps: + - name: Setup environment + run: | + if [ -f "/etc/debian_version" ]; then + echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV + export DEBIAN_FRONTEND=noninteractive + fi + if [ -n "${{matrix.container}}" ] && [ -f "/etc/debian_version" ]; then + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common curl + # Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80 + curl -sSL --retry ${NET_RETRY_COUNT:-5} 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24' | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg + for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + osver=$(lsb_release -sr | cut -f1 -d.) + pkgs="g++ git" + # Ubuntu 22+ has only Python 3 in the repos + if [ -n "$osver" ] && [ "$osver" -ge "22" ]; then + pkgs+=" python-is-python3 libpython3-dev" + else + pkgs+=" python libpython-dev" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs locales + sudo locale-gen de_DE.UTF-8 + sudo update-locale + fi + # For jobs not compatible with ccache, use "ccache: no" in the matrix + if [[ "${{ matrix.ccache }}" == "no" ]]; then + echo "B2_USE_CCACHE=0" >> $GITHUB_ENV + fi + git config --global pack.threads 0 + if [[ "${{matrix.container}}" == "ubuntu:16.04" ]] || [[ "${{matrix.container}}" == "ubuntu:18.04" ]]; then + # Ubuntu 16/18 can't run Node 20, so stick to older actions: https://github.com/actions/checkout/issues/1590 + echo "GHA_USE_NODE_20=false" >> $GITHUB_ENV + echo "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true" >> $GITHUB_ENV + else + echo "GHA_USE_NODE_20=true" >> $GITHUB_ENV + fi + + - uses: actions/checkout@v3 + if: env.GHA_USE_NODE_20 == 'false' + with: + # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' + fetch-depth: ${{ matrix.coverage && '0' || '1' }} + - uses: actions/checkout@v4 + if: env.GHA_USE_NODE_20 == 'true' + with: + # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' + fetch-depth: ${{ matrix.coverage && '0' || '1' }} + + - name: Cache ccache + uses: actions/cache@v3 + if: env.B2_USE_CCACHE && env.GHA_USE_NODE_20 == 'false' + with: + path: ~/.ccache + key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} + restore-keys: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- + + - name: Cache ccache + uses: actions/cache@v4 + if: env.B2_USE_CCACHE && env.GHA_USE_NODE_20 == 'true' + with: + path: ~/.ccache + key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} + restore-keys: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- + + - name: Fetch Boost.CI + uses: actions/checkout@v3 + if: env.GHA_USE_NODE_20 == 'false' + with: + repository: boostorg/boost-ci + ref: master + path: boost-ci-cloned + + - name: Fetch Boost.CI + uses: actions/checkout@v4 + if: env.GHA_USE_NODE_20 == 'true' + with: + repository: boostorg/boost-ci + ref: master + path: boost-ci-cloned + + - name: Get CI scripts folder + run: | + # Copy ci folder if not testing Boost.CI + [[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci . + rm -rf boost-ci-cloned + + - name: Install packages + if: startsWith(matrix.os, 'ubuntu') + run: | + SOURCE_KEYS=(${{join(matrix.source_keys, ' ')}}) + SOURCES=(${{join(matrix.sources, ' ')}}) + # Add this by default + SOURCE_KEYS+=('http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x1E9377A2BA9EF27F') + SOURCES+=(ppa:ubuntu-toolchain-r/test) + + ci/add-apt-keys.sh "${SOURCE_KEYS[@]}" + # Initial update before adding sources required to get e.g. keys + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + ci/add-apt-repositories.sh "${SOURCES[@]}" + + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + if [[ -z "${{matrix.install}}" ]]; then + pkgs="${{matrix.compiler}}" + pkgs="${pkgs/gcc-/g++-}" + else + pkgs="${{matrix.install}}" + fi + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs + + - name: Setup GCC Toolchain + if: matrix.gcc_toolchain + run: | + GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain" + echo "GCC_TOOLCHAIN_ROOT=$GCC_TOOLCHAIN_ROOT" >> $GITHUB_ENV + if ! command -v dpkg-architecture; then + apt-get install -y dpkg-dev + fi + MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" + mkdir -p "$GCC_TOOLCHAIN_ROOT" + ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include" + ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin" + mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET" + ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" + + - name: Setup multiarch + if: matrix.multiarch + env: + BDDE_DISTRO: ${{matrix.distro}} + BDDE_EDITION: ${{matrix.edition}} + BDDE_ARCH: ${{matrix.arch}} + run: ci/github/setup_bdde.sh + + - name: Setup Boost + env: + B2_ADDRESS_MODEL: ${{matrix.address-model}} + B2_COMPILER: ${{matrix.compiler}} + B2_CXXSTD: ${{matrix.cxxstd}} + B2_SANITIZE: ${{matrix.sanitize}} + B2_STDLIB: ${{matrix.stdlib}} + # More entries can be added in the same way, see the B2_ARGS assignment in ci/enforce.sh for the possible keys. + # B2_DEFINES: 'BOOST_DECIMAL_QEMU_TEST' + # Variables set here (to non-empty) will override the top-level environment variables, e.g. + # B2_VARIANT: ${{matrix.variant}} + # Set the (B2) target(s) to build, defaults to the test folder of the current library + # Can alternatively be done like this in the build step or in the build command of the build step, e.g. `run: B2_TARGETS=libs/$SELF/doc ci/build.sh` + # B2_TARGETS: libs/foo/test//bar + run: source ci/github/install.sh + + - name: Run tests + if: '!matrix.coverity' + run: ci/build.sh From 0e7ca0e2a88974c8e6b465c0d8bf3fe7bc5dedb7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:51:47 -0400 Subject: [PATCH 26/76] Add additional header --- include/boost/crypt/hash/md5.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 0295dcb0..007e8c3d 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include From 32ea9d0647bd82f078f700d99132eb856c1eb0f6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 8 Oct 2024 16:59:00 -0400 Subject: [PATCH 27/76] Additional casts --- include/boost/crypt/hash/md5.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 007e8c3d..1cdde53a 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -80,17 +80,17 @@ auto md5_pad(const std::vector& message) noexcept -> std::vector padded_message {message}; const std::uint64_t original_length {message.size() * 8U}; - padded_message.emplace_back(0x80); + padded_message.emplace_back(static_cast(0x80)); while ((padded_message.size() * 8U) % 512U != 448U) { - padded_message.push_back(static_cast(0x00)); + padded_message.emplace_back(static_cast(0x00)); } // Add the original length as a 64-bit number for (std::size_t i = 0; i < 8; ++i) { - padded_message.push_back(static_cast((original_length >> (8 * i)) & 0xFF)); + padded_message.emplace_back(static_cast((original_length >> (8 * i)) & 0xFF)); } return padded_message; From 0990f0eb95d9350acfc7abbaad0f83a336aecac6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 09:31:50 -0400 Subject: [PATCH 28/76] Add outline of byte class --- include/boost/crypt/utility/byte.hpp | 104 +++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 include/boost/crypt/utility/byte.hpp diff --git a/include/boost/crypt/utility/byte.hpp b/include/boost/crypt/utility/byte.hpp new file mode 100644 index 00000000..669a152c --- /dev/null +++ b/include/boost/crypt/utility/byte.hpp @@ -0,0 +1,104 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CRYPT_UTILITY_BYTE_HPP +#define BOOST_CRYPT_UTILITY_BYTE_HPP + +#include +#include +#include + +namespace boost { +namespace crypt { + +class byte +{ +private: + std::uint8_t bits_; + +public: + constexpr byte() noexcept : bits_ {} {} + explicit constexpr byte(std::uint8_t bits) noexcept : bits_ {bits} {} + + template + constexpr auto to_integer() noexcept -> IntegerType + { + return static_cast(bits_); + } + + template + constexpr auto operator<<(IntegerType shift) noexcept -> byte + { + return byte{bits_ << shift}; + } + + template + constexpr auto operator>>(IntegerType shift) noexcept -> byte + { + return byte{bits_ >> shift}; + } + + constexpr auto operator|(byte rhs) const noexcept -> byte + { + return byte{static_cast(bits_ | rhs.bits_)}; + } + + constexpr auto operator&(byte rhs) const noexcept -> byte + { + return byte{static_cast(bits_ & rhs.bits_)}; + } + + constexpr auto operator^(byte rhs) const noexcept -> byte + { + return byte{static_cast(bits_ ^ rhs.bits_)}; + } + + constexpr auto operator~() const noexcept -> byte + { + return byte{static_cast(~bits_)}; + } + + template + constexpr auto operator<<=(IntegerType shift) noexcept -> byte& + { + bits_ <<= shift; + return *this; + } + + template + constexpr auto operator >>=(IntegerType shift) noexcept -> byte& + { + bits_ >>= shift; + return *this; + } + + constexpr auto operator|(byte rhs) noexcept -> byte& + { + bits_ = static_cast(bits_ | rhs.bits_); + return *this; + } + + constexpr auto operator&(byte rhs) noexcept -> byte& + { + bits_ = static_cast(bits_ & rhs.bits_); + return *this; + } + + constexpr auto operator^(byte rhs) noexcept -> byte& + { + bits_ = static_cast(bits_ ^ rhs.bits_); + return *this; + } + + constexpr auto operator~() noexcept -> byte& + { + bits_ = ~bits_; + return *this; + } +}; + +} // namespace crypt +} // namespace boost + +#endif //BOOST_CRYPT_UTILITY_BYTE_HPP From d0fc1c5cc79429d7071f2b8e1f70d541cf11ef0e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 09:58:50 -0400 Subject: [PATCH 29/76] Add inline constexpr --- include/boost/crypt/utility/config.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/crypt/utility/config.hpp b/include/boost/crypt/utility/config.hpp index 4770b948..fd71b689 100644 --- a/include/boost/crypt/utility/config.hpp +++ b/include/boost/crypt/utility/config.hpp @@ -15,12 +15,15 @@ #if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L # define BOOST_CRYPT_CONSTEXPR_ARRAY inline constexpr # define BOOST_CRYPT_DEVICE_ARRAY inline constexpr +# define BOOST_CRYPT_INLINE_CONSTEXPR inline constexpr #elif defined(BOOST_CRYPT_ENABLE_CUDA) # define BOOST_CYPRT_CONSTEXPR_ARRAY static constexpr # define BOOST_CRYPT_DEVICE_ARRAY __constant__ +# define BOOST_CRYPT_INLINE_CONSTEXPR static constexpr #else # define BOOST_CRYPT_CONSTEXPR_ARRAY static constexpr # define BOOST_CRYPT_DEVICE_ARRAY static constexpr +# define BOOST_CRYPT_INLINE_CONSTEXPR static constexpr #endif // ---- Constexpr arrays ----- From 7c7947c285bb5503eff13925d2f05798a93c8a5f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 09:59:01 -0400 Subject: [PATCH 30/76] Add CUDA capable type_traits --- include/boost/crypt/utility/type_traits.hpp | 494 ++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 include/boost/crypt/utility/type_traits.hpp diff --git a/include/boost/crypt/utility/type_traits.hpp b/include/boost/crypt/utility/type_traits.hpp new file mode 100644 index 00000000..5e78db73 --- /dev/null +++ b/include/boost/crypt/utility/type_traits.hpp @@ -0,0 +1,494 @@ +// Copyright (c) 2024 Matt Borland +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Regular use of is not compatible with CUDA +// Adds aliases to unify the support +// Also adds convience overloads like is_same_v so we don't have to wait for C++17 + +#ifndef BOOST_CRYPT_UTILITY_TYPE_TRAITS +#define BOOST_CRYPT_UTILITY_TYPE_TRAITS + +#include + +#ifdef BOOST_CRYPT_ENABLE_CUDA + +#include + +namespace boost { +namespace crypt { + +// Helper classes +using cuda::std::integral_constant; +using cuda::std::true_type; +using cuda::std::false_type; + +// Primary type categories +using cuda::std::is_void; +using cuda::std::is_null_pointer; +using cuda::std::is_integral; +using cuda::std::is_floating_point; +using cuda::std::is_array; +using cuda::std::is_enum; +using cuda::std::is_union; +using cuda::std::is_class; +using cuda::std::is_function; +using cuda::std::is_pointer; +using cuda::std::is_lvalue_reference; +using cuda::std::is_rvalue_reference; +using cuda::std::is_member_object_pointer; +using cuda::std::is_member_function_pointer; + +// Composite Type Categories +using cuda::std::is_fundamental; +using cuda::std::is_arithmetic; +using cuda::std::is_scalar; +using cuda::std::is_object; +using cuda::std::is_compound; +using cuda::std::is_reference; +using cuda::std::is_member_pointer; + +// Type properties +using cuda::std::is_const; +using cuda::std::is_volatile; +using cuda::std::is_trivial; +using cuda::std::is_trivially_copyable; +using cuda::std::is_standard_layout; +using cuda::std::is_empty; +using cuda::std::is_polymorphic; +using cuda::std::is_abstract; +using cuda::std::is_final; +using cuda::std::is_signed; +using cuda::std::is_unsigned; + +// Supported Operations +using cuda::std::is_constructible; +using cuda::std::is_trivially_constructible; +using cuda::std::is_nothrow_constructible; + +using cuda::std::is_default_constructible; +using cuda::std::is_trivially_default_constructible; +using cuda::std::is_nothrow_default_constructible; + +using cuda::std::is_copy_constructible; +using cuda::std::is_trivially_copy_constructible; +using cuda::std::is_nothrow_copy_constructible; + +using cuda::std::is_move_constructible; +using cuda::std::is_trivially_move_constructible; +using cuda::std::is_nothrow_move_constructible; + +using cuda::std::is_assignable; +using cuda::std::is_trivially_assignable; +using cuda::std::is_nothrow_assignable; + +using cuda::std::is_copy_assignable; +using cuda::std::is_trivially_copy_assignable; +using cuda::std::is_nothrow_copy_assignable; + +using cuda::std::is_move_assignable; +using cuda::std::is_trivially_move_assignable; +using cuda::std::is_nothrow_move_assignable; + +using cuda::std::is_destructible; +using cuda::std::is_trivially_destructible; +using cuda::std::is_nothrow_destructible; + +using cuda::std::has_virtual_destructor; + +// Property Queries +using cuda::std::alignment_of; +using cuda::std::rank; +using cuda::std::extent; + +// Type Relationships +using cuda::std::is_same; +using cuda::std::is_base_of; +using cuda::std::is_convertible; + +// Const-volatility specifiers +using cuda::std::remove_cv; +using cuda::std::remove_cv_t; +using cuda::std::remove_const; +using cuda::std::remove_const_t; +using cuda::std::remove_volatile; +using cuda::std::remove_volatile_t; +using cuda::std::add_cv; +using cuda::std::add_cv_t; +using cuda::std::add_const; +using cuda::std::add_const_t; +using cuda::std::add_volatile; +using cuda::std::add_volatile_t; + +// References +using cuda::std::remove_reference; +using cuda::std::remove_reference_t; +using cuda::std::add_lvalue_reference; +using cuda::std::add_lvalue_reference_t; +using cuda::std::add_rvalue_reference; +using cuda::std::add_rvalue_reference_t; + +// Pointers +using cuda::std::remove_pointer; +using cuda::std::remove_pointer_t; +using cuda::std::add_pointer; +using cuda::std::add_pointer_t; + +// Sign Modifiers +using cuda::std::make_signed; +using cuda::std::make_signed_t; +using cuda::std::make_unsigned; +using cuda::std::make_unsigned_t; + +// Arrays +using cuda::std::remove_extent; +using cuda::std::remove_extent_t; +using cuda::std::remove_all_extents; +using cuda::std::remove_all_extents_t; + +// Misc transformations +using cuda::std::decay; +using cuda::std::decay_t; +using cuda::std::enable_if; +using cuda::std::enable_if_t; +using cuda::std::conditional; +using cuda::std::conditional_t; +using cuda::std::common_type; +using cuda::std::common_type_t; +using cuda::std::underlying_type; +using cuda::std::underlying_type_t; + +#else // STD versions + +#include + +namespace boost { +namespace crypt { + +// Helper classes +using std::integral_constant; +using std::true_type; +using std::false_type; + +// Primary type categories +using std::is_void; +using std::is_null_pointer; +using std::is_integral; +using std::is_floating_point; +using std::is_array; +using std::is_enum; +using std::is_union; +using std::is_class; +using std::is_function; +using std::is_pointer; +using std::is_lvalue_reference; +using std::is_rvalue_reference; +using std::is_member_object_pointer; +using std::is_member_function_pointer; + +// Composite Type Categories +using std::is_fundamental; +using std::is_arithmetic; +using std::is_scalar; +using std::is_object; +using std::is_compound; +using std::is_reference; +using std::is_member_pointer; + +// Type properties +using std::is_const; +using std::is_volatile; +using std::is_trivial; +using std::is_trivially_copyable; +using std::is_standard_layout; +using std::is_empty; +using std::is_polymorphic; +using std::is_abstract; +using std::is_final; +using std::is_signed; +using std::is_unsigned; + +// Supported Operations +using std::is_constructible; +using std::is_trivially_constructible; +using std::is_nothrow_constructible; + +using std::is_default_constructible; +using std::is_trivially_default_constructible; +using std::is_nothrow_default_constructible; + +using std::is_copy_constructible; +using std::is_trivially_copy_constructible; +using std::is_nothrow_copy_constructible; + +using std::is_move_constructible; +using std::is_trivially_move_constructible; +using std::is_nothrow_move_constructible; + +using std::is_assignable; +using std::is_trivially_assignable; +using std::is_nothrow_assignable; + +using std::is_copy_assignable; +using std::is_trivially_copy_assignable; +using std::is_nothrow_copy_assignable; + +using std::is_move_assignable; +using std::is_trivially_move_assignable; +using std::is_nothrow_move_assignable; + +using std::is_destructible; +using std::is_trivially_destructible; +using std::is_nothrow_destructible; + +using std::has_virtual_destructor; + +// Property Queries +using std::alignment_of; +using std::rank; +using std::extent; + +// Type Relationships +using std::is_same; +using std::is_base_of; +using std::is_convertible; + +// Const-volatility specifiers +using std::remove_cv; +using std::remove_cv_t; +using std::remove_const; +using std::remove_const_t; +using std::remove_volatile; +using std::remove_volatile_t; +using std::add_cv; +using std::add_cv_t; +using std::add_const; +using std::add_const_t; +using std::add_volatile; +using std::add_volatile_t; + +// References +using std::remove_reference; +using std::remove_reference_t; +using std::add_lvalue_reference; +using std::add_lvalue_reference_t; +using std::add_rvalue_reference; +using std::add_rvalue_reference_t; + +// Pointers +using std::remove_pointer; +using std::remove_pointer_t; +using std::add_pointer; +using std::add_pointer_t; + +// Sign Modifiers +using std::make_signed; +using std::make_signed_t; +using std::make_unsigned; +using std::make_unsigned_t; + +// Arrays +using std::remove_extent; +using std::remove_extent_t; +using std::remove_all_extents; +using std::remove_all_extents_t; + +// Misc transformations +using std::decay; +using std::decay_t; +using std::enable_if; +using std::enable_if_t; +using std::conditional; +using std::conditional_t; +using std::common_type; +using std::common_type_t; +using std::underlying_type; +using std::underlying_type_t; + +#endif + +template +using bool_constant = boost::crypt::integral_constant; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_void_v = boost::crypt::is_void::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_null_pointer_v = boost::crypt::is_null_pointer::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_integral_v = boost::crypt::is_integral::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_floating_point_v = boost::crypt::is_floating_point::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_array_v = boost::crypt::is_array::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_enum_v = boost::crypt::is_enum::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_union_v = boost::crypt::is_union::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_class_v = boost::crypt::is_class::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_function_v = boost::crypt::is_function::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_pointer_v = boost::crypt::is_pointer::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_lvalue_reference_v = boost::crypt::is_lvalue_reference::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_rvalue_reference_v = boost::crypt::is_rvalue_reference::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_member_object_pointer_v = boost::crypt::is_member_object_pointer::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_member_function_pointer_v = boost::crypt::is_member_function_pointer::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_fundamental_v = boost::crypt::is_fundamental::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_arithmetic_v = boost::crypt::is_arithmetic::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_scalar_v = boost::crypt::is_scalar::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_object_v = boost::crypt::is_object::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_compound_v = boost::crypt::is_compound::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_reference_v = boost::crypt::is_reference::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_member_pointer_v = boost::crypt::is_member_pointer::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_const_v = boost::crypt::is_const::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_volatile_v = boost::crypt::is_volatile::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivial_v = boost::crypt::is_trivial::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_copyable_v = boost::crypt::is_trivially_copyable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_standard_layout_v = boost::crypt::is_standard_layout::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_empty_v = boost::crypt::is_empty::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_polymorphic_v = boost::crypt::is_polymorphic::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_abstract_v = boost::crypt::is_abstract::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_final_v = boost::crypt::is_final::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_signed_v = boost::crypt::is_signed::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_unsigned_v = boost::crypt::is_unsigned::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_constructible_v = boost::crypt::is_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_constructible_v = boost::crypt::is_trivially_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_constructible_v = boost::crypt::is_nothrow_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_default_constructible_v = boost::crypt::is_default_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_default_constructible_v = boost::crypt::is_trivially_default_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_default_constructible_v = boost::crypt::is_nothrow_default_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_copy_constructible_v = boost::crypt::is_copy_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_copy_constructible_v = boost::crypt::is_trivially_copy_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_copy_constructible_v = boost::crypt::is_nothrow_copy_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_move_constructible_v = boost::crypt::is_move_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_move_constructible_v = boost::crypt::is_trivially_move_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_move_constructible_v = boost::crypt::is_nothrow_move_constructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_assignable_v = boost::crypt::is_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_assignable_v = boost::crypt::is_trivially_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_assignable_v = boost::crypt::is_nothrow_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_copy_assignable_v = boost::crypt::is_copy_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_copy_assignable_v = boost::crypt::is_trivially_copy_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_copy_assignable_v = boost::crypt::is_nothrow_copy_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_move_assignable_v = boost::crypt::is_move_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_move_assignable_v = boost::crypt::is_trivially_move_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_move_assignable_v = boost::crypt::is_nothrow_move_assignable::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_destructible_v = boost::crypt::is_destructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_trivially_destructible_v = boost::crypt::is_trivially_destructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_nothrow_destructible_v = boost::crypt::is_nothrow_destructible::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool has_virtual_destructor_v = boost::crypt::has_virtual_destructor::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_same_v = boost::crypt::is_same::value; + +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_base_of_v = boost::crypt::is_base_of::value; + +} // namespace crypt +} // namespace boost + +#endif // BOOST_CRYPT_UTILITY_TYPE_TRAITS From 3be97dc1a914af1fd691b47f1aec8653eee2f353 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:23:38 -0400 Subject: [PATCH 31/76] Add starting concepts definitions --- include/boost/crypt/utility/concepts.hpp | 124 +++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 include/boost/crypt/utility/concepts.hpp diff --git a/include/boost/crypt/utility/concepts.hpp b/include/boost/crypt/utility/concepts.hpp new file mode 100644 index 00000000..889f724f --- /dev/null +++ b/include/boost/crypt/utility/concepts.hpp @@ -0,0 +1,124 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CRYPT_UTILITY_CONCEPTS_HPP +#define BOOST_CRYPT_UTILITY_CONCEPTS_HPP + +#include + +#ifndef BOOST_CRYPT_BUILD_MODULE +#include +#endif + +// GCC-11 yields internal compiler errors when using the concepts + +/* +./boost/decimal/detail/concepts.hpp:239:80: note: in definition of macro 'BOOST_CRYPT_REQUIRES_RETURN' + 239 | #define BOOST_CRYPT_REQUIRES_RETURN(X, T, ReturnType) -> ReturnType requires X + | ^ +0xe3223b internal_error(char const*, ...) + ???:0 +0xf56ed4 duplicate_decls(tree_node*, tree_node*, bool, bool) + ???:0 +0xf60a2b pushdecl_namespace_level(tree_node*, bool) + ???:0 +0x10801ca push_template_decl(tree_node*, bool) + ???:0 +0x1527ec1 do_friend(tree_node*, tree_node*, tree_node*, tree_node*, overload_flags, bool) + ???:0 +0xfc4e1e grokdeclarator(cp_declarator const*, cp_decl_specifier_seq*, decl_context, int, tree_node**) + ???:0 +0x100dcf4 grokfield(cp_declarator const*, cp_decl_specifier_seq*, tree_node*, bool, tree_node*, tree_node*) + ???:0 +0x149dce3 c_parse_file() + ???:0 +0x148d4de c_common_parse_file() + ???:0 +*/ +#if (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) && !defined(BOOST_MATH_DISABLE_CONCEPTS) &&\ + (!defined(__GNUC__) || __GNUC__ != 11) + +#if __has_include() + +#ifndef BOOST_CRYPT_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#endif + +namespace boost::crypt::concepts { + +template +concept integral = boost::crypt::detail::is_integral_v; + +template +concept signed_integral = integral && boost::crypt::is_signed_v; + +template +concept unsigned_integral = integral && boost::crypt::is_unsigned_v; + +template +concept real = boost::crypt::detail::is_floating_point_v; + +} // boost::crypt::concepts + +#define BOOST_CRYPT_HAS_CONCEPTS 1 + +#define BOOST_CRYPT_INTEGRAL boost::crypt::concepts::integral +#define BOOST_CRYPT_SIGNED_INTEGRAL boost::crypt::concepts::signed_integral +#define BOOST_CRYPT_UNSIGNED_INTEGRAL boost::crypt::concepts::unsigned_integral +#define BOOST_CRYPT_REAL boost::crypt::concepts::real + +#define BOOST_CRYPT_REQUIRES(X, T) -> T requires X +#define BOOST_CRYPT_REQUIRES_TWO(X1, T1, X2, T2) -> detail::promote_args_t requires X1 && X2 +#define BOOST_CRYPT_REQUIRES_TWO_RETURN(X1, T1, X2, T2, ReturnType) -> ReturnType requires X1 && X2 +#define BOOST_CRYPT_REQUIRES_THREE(X1, T1, X2, T2, X3, T3) -> detail::promote_args_t requires X1 && X2 && X3 +#define BOOST_CRYPT_REQUIRES_RETURN(X, T, ReturnType) -> ReturnType requires X + + +#endif // Has +#endif // C++20 + +// If concepts are unavailable replace them with typename for compatibility + +#ifndef BOOST_CRYPT_INTEGRAL +# define BOOST_CRYPT_INTEGRAL typename +#endif + +#ifndef BOOST_CRYPT_SIGNED_INTEGRAL +# define BOOST_CRYPT_SIGNED_INTEGRAL typename +#endif + +#ifndef BOOST_CRYPT_UNSIGNED_INTEGRAL +# define BOOST_CRYPT_UNSIGNED_INTEGRAL typename +#endif + +#ifndef BOOST_CRYPT_REAL +# define BOOST_CRYPT_REAL typename +#endif +#ifndef BOOST_CRYPT_REQUIRES +# define BOOST_CRYPT_REQUIRES(X, T) -> boost::crypt::enable_if_t, T> +#endif + +#ifndef BOOST_CRYPT_REQUIRES_TWO +# define BOOST_CRYPT_REQUIRES_TWO(X1, T1, X2, T2) -> boost::crypt::enable_if_t && X2, detail::promote_args_t> +#endif + +#ifndef BOOST_CRYPT_REQUIRES_TWO_RETURN +# define BOOST_CRYPT_REQUIRES_TWO_RETURN(X1, T1, X2, T2, ReturnType) -> boost::crypt::enable_if_t && X2, ReturnType> +#endif + +#ifndef BOOST_CRYPT_REQUIRES_THREE +# define BOOST_CRYPT_REQUIRES_THREE(X1, T1, X2, T2, X3, T3) -> boost::crypt::enable_if_t && X2 && X3, detail::promote_args_t> +#endif + +#ifndef BOOST_CRYPT_REQUIRES_RETURN +# define BOOST_CRYPT_REQUIRES_RETURN(X, T, ReturnType) -> boost::crypt::enable_if_t, ReturnType> +#endif + +#endif //BOOST_CRYPT_UTILITY_CONCEPTS_HPP From 82a69ebe080d27f9ce54ff9b7bda6f321910d798 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:26:28 -0400 Subject: [PATCH 32/76] Add concepts to byte --- include/boost/crypt/utility/byte.hpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/include/boost/crypt/utility/byte.hpp b/include/boost/crypt/utility/byte.hpp index 669a152c..43a8453b 100644 --- a/include/boost/crypt/utility/byte.hpp +++ b/include/boost/crypt/utility/byte.hpp @@ -6,8 +6,11 @@ #define BOOST_CRYPT_UTILITY_BYTE_HPP #include -#include +#include + +#ifndef BOOST_CRYPT_BUILD_MODULE #include +#endif namespace boost { namespace crypt { @@ -22,19 +25,22 @@ class byte explicit constexpr byte(std::uint8_t bits) noexcept : bits_ {bits} {} template - constexpr auto to_integer() noexcept -> IntegerType + constexpr auto to_integer() noexcept + BOOST_CRYPT_REQUIRES(boost::crypt::is_integral_v, IntegerType) { return static_cast(bits_); } template - constexpr auto operator<<(IntegerType shift) noexcept -> byte + constexpr auto operator<<(IntegerType shift) noexcept + BOOST_CRYPT_REQUIRES_RETURN(boost::crypt::is_integral_v, IntegerType, byte) { return byte{bits_ << shift}; } template - constexpr auto operator>>(IntegerType shift) noexcept -> byte + constexpr auto operator>>(IntegerType shift) noexcept + BOOST_CRYPT_REQUIRES_RETURN(boost::crypt::is_integral_v, IntegerType, byte) { return byte{bits_ >> shift}; } @@ -60,14 +66,16 @@ class byte } template - constexpr auto operator<<=(IntegerType shift) noexcept -> byte& + constexpr auto operator<<=(IntegerType shift) noexcept + BOOST_CRYPT_REQUIRES_RETURN(boost::crypt::is_integral_v, IntegerType, byte&) { bits_ <<= shift; return *this; } template - constexpr auto operator >>=(IntegerType shift) noexcept -> byte& + constexpr auto operator >>=(IntegerType shift) noexcept + BOOST_CRYPT_REQUIRES_RETURN(boost::crypt::is_integral_v, IntegerType, byte&) { bits_ >>= shift; return *this; From 385ce9492a2b338b99b66526a06b6cff494ef5f5 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:37:34 -0400 Subject: [PATCH 33/76] Add CUDA array --- include/boost/crypt/utility/array.hpp | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 include/boost/crypt/utility/array.hpp diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp new file mode 100644 index 00000000..f2ab2afd --- /dev/null +++ b/include/boost/crypt/utility/array.hpp @@ -0,0 +1,39 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + + +#ifndef BOOST_CRYPT_UTILITIES_ARRAY_HPP +#define BOOST_CRYPT_UTILITIES_ARRAY_HPP + +#include + +#ifdef BOOST_CRYPT_ENABLE_CUDA + +#include + +namespace boost { +namespace crypt { + +using cuda::std::array; + +} // namespace crypt +} // namespace boost + +#else // Use the STL + +#ifndef BOOST_CRYPT_BUILD_MODULE +#include +#endif + +namespace boost { +namespace crypt { + +using std::array; + +} // namespace crypt +} // namespace boost + +#endif // CUDA + +#endif // BOOST_CRYPT_UTILITIES_ARRAY_HPP From 1574e1910a30fd8a6fbd996656e09f41d2e01ec1 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:40:28 -0400 Subject: [PATCH 34/76] Add CUDA cstdint --- include/boost/crypt/utility/cstdint.hpp | 109 ++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 include/boost/crypt/utility/cstdint.hpp diff --git a/include/boost/crypt/utility/cstdint.hpp b/include/boost/crypt/utility/cstdint.hpp new file mode 100644 index 00000000..5863fc46 --- /dev/null +++ b/include/boost/crypt/utility/cstdint.hpp @@ -0,0 +1,109 @@ +// Copyright (c) 2024 Matt Borland +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CRYPT_TOOLS_CSTDINT +#define BOOST_CRYPT_TOOLS_CSTDINT + +#include + +#ifdef BOOST_CRYPT_ENABLE_CUDA + +#include + +namespace boost { +namespace crypt { + +using cuda::std::int8_t; +using cuda::std::int16_t; +using cuda::std::int32_t; +using cuda::std::int64_t; + +using cuda::std::int_fast8_t; +using cuda::std::int_fast16_t; +using cuda::std::int_fast32_t; +using cuda::std::int_fast64_t; + +using cuda::std::int_least8_t; +using cuda::std::int_least16_t; +using cuda::std::int_least32_t; +using cuda::std::int_least64_t; + +using cuda::std::intmax_t; +using cuda::std::intptr_t; + +using cuda::std::uint8_t; +using cuda::std::uint16_t; +using cuda::std::uint32_t; +using cuda::std::uint64_t; + +using cuda::std::uint_fast8_t; +using cuda::std::uint_fast16_t; +using cuda::std::uint_fast32_t; +using cuda::std::uint_fast64_t; + +using cuda::std::uint_least8_t; +using cuda::std::uint_least16_t; +using cuda::std::uint_least32_t; +using cuda::std::uint_least64_t; + +using cuda::std::uintmax_t; +using cuda::std::uintptr_t; + +using size_t = unsigned long; + +#else + +#ifndef BOOST_CRYPT_BUILD_MODULE +#include +#include +#endif + +namespace boost { +namespace crypt { + +using std::int8_t; +using std::int16_t; +using std::int32_t; +using std::int64_t; + +using std::int_fast8_t; +using std::int_fast16_t; +using std::int_fast32_t; +using std::int_fast64_t; + +using std::int_least8_t; +using std::int_least16_t; +using std::int_least32_t; +using std::int_least64_t; + +using std::intmax_t; +using std::intptr_t; + +using std::uint8_t; +using std::uint16_t; +using std::uint32_t; +using std::uint64_t; + +using std::uint_fast8_t; +using std::uint_fast16_t; +using std::uint_fast32_t; +using std::uint_fast64_t; + +using std::uint_least8_t; +using std::uint_least16_t; +using std::uint_least32_t; +using std::uint_least64_t; + +using std::uintmax_t; +using std::uintptr_t; + +using std::size_t; + +#endif + +} // namespace crypt +} // namespace boost + +#endif // BOOST_CRYPT_TOOLS_CSTDINT From 265ea28101b4e5e73dba475dab5819a9d9d37320 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:55:33 -0400 Subject: [PATCH 35/76] Add more GPU macros --- include/boost/crypt/utility/config.hpp | 29 ++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt/utility/config.hpp b/include/boost/crypt/utility/config.hpp index fd71b689..bec8d29d 100644 --- a/include/boost/crypt/utility/config.hpp +++ b/include/boost/crypt/utility/config.hpp @@ -6,9 +6,34 @@ #define BOOST_CRYPT_DETAIL_CONFIG_HPP #ifdef __CUDACC__ -# ifndef BOOST_CRYPT_ENABLE_CUDA -# define BOOST_CRYPT_ENABLE_CUDA +# ifndef BOOST_CRYPT_HAS_CUDA +# define BOOST_CRYPT_HAS_CUDA # endif +# define BOOST_CRYPT_GPU_ENABLED __host__ __device__ +# define BOOST_CRYPT_GPU_HOST_ENABLED __host__ +# define BOOST_CRYPT_GPU_DEVICE_ENABLED __device__ +#endif + +#ifdef __CUDACC_RTC__ +# ifndef BOOST_CRYPT_HAS_CUDA +# define BOOST_CRYPT_HAS_CUDA +# endif +# define BOOST_CRYPT_HAS_NVRTC +# define BOOST_CRYPT_GPU_ENABLED __host__ __device__ +# define BOOST_CRYPT_GPU_HOST_ENABLED __host__ +# define BOOST_CRYPT_GPU_DEVICE_ENABLED __device__ +#endif + +#ifndef BOOST_CRYPT_GPU_ENABLED +# define BOOST_CRYPT_GPU_ENABLED +#endif + +#ifndef BOOST_CRYPT_GPU_HOST_ENABLED +# define BOOST_CRYPT_GPU_HOST_ENABLED +#endif + +#ifndef BOOST_CRYPT_GPU_DEVICE_ENABLED +# define BOOST_CRYPT_GPU_DEVICE_ENABLED #endif // ---- Constexpr arrays ----- From bd9adb9e7bca79233a206b0109965e60212a71fe Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:55:41 -0400 Subject: [PATCH 36/76] Add limits support --- include/boost/crypt/utility/limits.hpp | 888 +++++++++++++++++++++++++ 1 file changed, 888 insertions(+) create mode 100644 include/boost/crypt/utility/limits.hpp diff --git a/include/boost/crypt/utility/limits.hpp b/include/boost/crypt/utility/limits.hpp new file mode 100644 index 00000000..a09a8bce --- /dev/null +++ b/include/boost/crypt/utility/limits.hpp @@ -0,0 +1,888 @@ +// Copyright (c) 2024 Matt Borland +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Regular use of std::numeric_limits functions can not be used on +// GPU platforms like CUDA since they are missing the __device__ marker +// and libcu++ does not provide something analogous. +// Rather than using giant if else blocks make our own version of numeric limits +// +// On the CUDA NVRTC platform we use a best attempt at emulating the functions +// and values since we do not have any macros to go off of. +// Use the values as found on GCC 11.4 RHEL 9.4 x64 + +#ifndef BOOST_CRYPT_UTILITY_LIMITS_HPP +#define BOOST_CRYPT_UTILITY_LIMITS_HPP + +#include + +#if !defined(BOOST_CRYPT_HAS_NVRTC) && !defined(BOOST_CRYPT_BUILD_MODULE) + +#include +#include +#include +#include + +#endif + +namespace boost { +namespace crypt { + +template +struct numeric_limits +#ifndef BOOST_CRYPT_HAS_NVRTC + : public std::numeric_limits {}; +#else +{}; +#endif + +#if defined(BOOST_CRYPT_HAS_CUDA) && !defined(BOOST_CRYPT_HAS_NVRTC) + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr float (min) () { return FLT_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr float (max) () { return FLT_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr float lowest () { return -FLT_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr float epsilon () { return FLT_EPSILON; } + BOOST_CRYPT_GPU_ENABLED static constexpr float round_error () { return 0.5F; } + BOOST_CRYPT_GPU_ENABLED static constexpr float infinity () { return static_cast(INFINITY); } + BOOST_CRYPT_GPU_ENABLED static constexpr float quiet_NaN () { return static_cast(NAN); } + BOOST_CRYPT_GPU_ENABLED static constexpr float signaling_NaN () + { + #ifdef FLT_SNAN + return FLT_SNAN; + #else + return static_cast(NAN); + #endif + } + BOOST_CRYPT_GPU_ENABLED static constexpr float denorm_min () { return FLT_TRUE_MIN; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr double (min) () { return DBL_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr double (max) () { return DBL_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr double lowest () { return -DBL_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr double epsilon () { return DBL_EPSILON; } + BOOST_CRYPT_GPU_ENABLED static constexpr double round_error () { return 0.5; } + BOOST_CRYPT_GPU_ENABLED static constexpr double infinity () { return static_cast(INFINITY); } + BOOST_CRYPT_GPU_ENABLED static constexpr double quiet_NaN () { return static_cast(NAN); } + BOOST_CRYPT_GPU_ENABLED static constexpr double signaling_NaN () + { + #ifdef DBL_SNAN + return DBL_SNAN; + #else + return static_cast(NAN); + #endif + } + BOOST_CRYPT_GPU_ENABLED static constexpr double denorm_min () { return DBL_TRUE_MIN; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr short (min) () { return SHRT_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr short (max) () { return SHRT_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr short lowest () { return SHRT_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr short epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short (max) () { return USHRT_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr int (min) () { return INT_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr int (max) () { return INT_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr int lowest () { return INT_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr int epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int (max) () { return UINT_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr long (min) () { return LONG_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr long (max) () { return LONG_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr long lowest () { return LONG_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long (max) () { return ULONG_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr long long (min) () { return LLONG_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long (max) () { return LLONG_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long lowest () { return LLONG_MIN; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long (max) () { return ULLONG_MAX; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = std::numeric_limits::is_specialized; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool has_infinity = std::numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN = std::numeric_limits::has_signaling_NaN; + + static constexpr std::float_round_style round_style = std::numeric_limits::round_style; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int max_digits10 = std::numeric_limits::max_digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr int min_exponent = std::numeric_limits::min_exponent; + static constexpr int min_exponent10 = std::numeric_limits::min_exponent10; + static constexpr int max_exponent = std::numeric_limits::max_exponent; + static constexpr int max_exponent10 = std::numeric_limits::max_exponent10; + static constexpr bool traps = std::numeric_limits::traps; + static constexpr bool tinyness_before = std::numeric_limits::tinyness_before; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr bool (min) () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool (max) () { return true; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool lowest () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool epsilon () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool round_error () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool infinity () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool quiet_NaN () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool signaling_NaN () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool denorm_min () { return false; } +}; + +#elif defined(BOOST_CRYPT_HAS_NVRTC) // Pure NVRTC support - Removes rounding style and approximates the traits + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; + + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 24; + static constexpr int digits10 = 6; + static constexpr int max_digits10 = 9; + static constexpr int radix = 2; + static constexpr int min_exponent = -125; + static constexpr int min_exponent10 = -37; + static constexpr int max_exponent = 128; + static constexpr int max_exponent10 = 38; + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr float (min) () { return 1.17549435e-38F; } + BOOST_CRYPT_GPU_ENABLED static constexpr float (max) () { return 3.40282347e+38F; } + BOOST_CRYPT_GPU_ENABLED static constexpr float lowest () { return -3.40282347e+38F; } + BOOST_CRYPT_GPU_ENABLED static constexpr float epsilon () { return 1.1920929e-07; } + BOOST_CRYPT_GPU_ENABLED static constexpr float round_error () { return 0.5F; } + BOOST_CRYPT_GPU_ENABLED static constexpr float infinity () { return __int_as_float(0x7f800000); } + BOOST_CRYPT_GPU_ENABLED static constexpr float quiet_NaN () { return __int_as_float(0x7fc00000); } + BOOST_CRYPT_GPU_ENABLED static constexpr float signaling_NaN () { return __int_as_float(0x7fa00000); } + BOOST_CRYPT_GPU_ENABLED static constexpr float denorm_min () { return 1.4013e-45F; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; + + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 53; + static constexpr int digits10 = 15; + static constexpr int max_digits10 = 21; + static constexpr int radix = 2; + static constexpr int min_exponent = -1021; + static constexpr int min_exponent10 = -307; + static constexpr int max_exponent = 1024; + static constexpr int max_exponent10 = 308; + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr double (min) () { return 2.2250738585072014e-308; } + BOOST_CRYPT_GPU_ENABLED static constexpr double (max) () { return 1.7976931348623157e+308; } + BOOST_CRYPT_GPU_ENABLED static constexpr double lowest () { return -1.7976931348623157e+308; } + BOOST_CRYPT_GPU_ENABLED static constexpr double epsilon () { return 2.2204460492503131e-16; } + BOOST_CRYPT_GPU_ENABLED static constexpr double round_error () { return 0.5; } + BOOST_CRYPT_GPU_ENABLED static constexpr double infinity () { return __longlong_as_double(0x7ff0000000000000ULL); } + BOOST_CRYPT_GPU_ENABLED static constexpr double quiet_NaN () { return __longlong_as_double(0x7ff8000000000000ULL); } + BOOST_CRYPT_GPU_ENABLED static constexpr double signaling_NaN () { return __longlong_as_double(0x7ff4000000000000ULL); } + BOOST_CRYPT_GPU_ENABLED static constexpr double denorm_min () { return 4.9406564584124654e-324; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 15; + static constexpr int digits10 = 4; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr short (min) () { return -32768; } + BOOST_CRYPT_GPU_ENABLED static constexpr short (max) () { return 32767; } + BOOST_CRYPT_GPU_ENABLED static constexpr short lowest () { return -32768; } + BOOST_CRYPT_GPU_ENABLED static constexpr short epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr short denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = 16; + static constexpr int digits10 = 4; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short (max) () { return 65535U; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned short denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 31; + static constexpr int digits10 = 9; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr int (min) () { return -2147483648; } + BOOST_CRYPT_GPU_ENABLED static constexpr int (max) () { return 2147483647; } + BOOST_CRYPT_GPU_ENABLED static constexpr int lowest () { return -2147483648; } + BOOST_CRYPT_GPU_ENABLED static constexpr int epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr int denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = 32; + static constexpr int digits10 = 9; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int (max) () { return 4294967295U; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned int denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 63; + static constexpr int digits10 = 18; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr long (min) () { return -9223372036854775808L; } + BOOST_CRYPT_GPU_ENABLED static constexpr long (max) () { return 9223372036854775807L; } + BOOST_CRYPT_GPU_ENABLED static constexpr long lowest () { return -9223372036854775808L; } + BOOST_CRYPT_GPU_ENABLED static constexpr long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = 64; + static constexpr int digits10 = 19; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long (max) () { return 18446744073709551615UL; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 63; + static constexpr int digits10 = 18; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr long long (min) () { return -9223372036854775808LL; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long (max) () { return 9223372036854775807LL; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long lowest () { return -9223372036854775808LL; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr long long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = 64; + static constexpr int digits10 = 19; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long (min) () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long (max) () { return 18446744073709551615UL; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long lowest () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long epsilon () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long round_error () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long infinity () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long quiet_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long signaling_NaN () { return 0; } + BOOST_CRYPT_GPU_ENABLED static constexpr unsigned long long denorm_min () { return 0; } +}; + +template <> +struct numeric_limits +{ + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 1; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + + // Member Functions + BOOST_CRYPT_GPU_ENABLED static constexpr bool (min) () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool (max) () { return true; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool lowest () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool epsilon () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool round_error () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool infinity () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool quiet_NaN () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool signaling_NaN () { return false; } + BOOST_CRYPT_GPU_ENABLED static constexpr bool denorm_min () { return false; } +}; + +#endif // BOOST_CRYPT_HAS_CUDA + +} // namespace crypt +} // namespace boost + +#endif // BOOST_CRYPT_UTILITY_LIMITS_HPP From 01c12c0802b9de080e605e0976961069e4827e14 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:55:52 -0400 Subject: [PATCH 37/76] Refactor naming --- include/boost/crypt/utility/array.hpp | 2 +- include/boost/crypt/utility/concepts.hpp | 4 ---- include/boost/crypt/utility/cstdint.hpp | 2 +- include/boost/crypt/utility/type_traits.hpp | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp index f2ab2afd..fdeeee74 100644 --- a/include/boost/crypt/utility/array.hpp +++ b/include/boost/crypt/utility/array.hpp @@ -8,7 +8,7 @@ #include -#ifdef BOOST_CRYPT_ENABLE_CUDA +#ifdef BOOST_CRYPT_HAS_CUDA #include diff --git a/include/boost/crypt/utility/concepts.hpp b/include/boost/crypt/utility/concepts.hpp index 889f724f..069598cd 100644 --- a/include/boost/crypt/utility/concepts.hpp +++ b/include/boost/crypt/utility/concepts.hpp @@ -7,10 +7,6 @@ #include -#ifndef BOOST_CRYPT_BUILD_MODULE -#include -#endif - // GCC-11 yields internal compiler errors when using the concepts /* diff --git a/include/boost/crypt/utility/cstdint.hpp b/include/boost/crypt/utility/cstdint.hpp index 5863fc46..975230a1 100644 --- a/include/boost/crypt/utility/cstdint.hpp +++ b/include/boost/crypt/utility/cstdint.hpp @@ -8,7 +8,7 @@ #include -#ifdef BOOST_CRYPT_ENABLE_CUDA +#ifdef BOOST_CRYPT_HAS_CUDA #include diff --git a/include/boost/crypt/utility/type_traits.hpp b/include/boost/crypt/utility/type_traits.hpp index 5e78db73..94635498 100644 --- a/include/boost/crypt/utility/type_traits.hpp +++ b/include/boost/crypt/utility/type_traits.hpp @@ -12,7 +12,7 @@ #include -#ifdef BOOST_CRYPT_ENABLE_CUDA +#ifdef BOOST_CRYPT_HAS_CUDA #include From ea8af67565ef0ef088a07aba4c063ae199945a50 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:59:02 -0400 Subject: [PATCH 38/76] Add cuda to bit utils --- include/boost/crypt/utility/bit.hpp | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/boost/crypt/utility/bit.hpp b/include/boost/crypt/utility/bit.hpp index 55fe9dc7..55b2ec4c 100644 --- a/include/boost/crypt/utility/bit.hpp +++ b/include/boost/crypt/utility/bit.hpp @@ -2,34 +2,34 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#ifndef BOOST_BIT_HPP -#define BOOST_BIT_HPP +#ifndef BOOST_CRYPT_UTILITY_BIT_HPP +#define BOOST_CRYPT_UTILITY_BIT_HPP #include -#include -#include -#include +#include +#include +#include namespace boost { namespace crypt { namespace detail { // Forward decls -template ::value, bool> = true> +template ::value, bool> = true> constexpr T rotl(T x, U s) noexcept; -template ::value, bool> = true> +template ::value, bool> = true> constexpr T rotl(T x, U s) noexcept; -template ::value, bool> = true> +template ::value, bool> = true> constexpr T rotr(T x, U s) noexcept; -template ::value, bool> = true> +template ::value, bool> = true> constexpr T rotr(T x, U s) noexcept; // Only works for unsigned s so we can optimize away the call to rotr -template ::value, bool>> +template ::value, bool>> constexpr T rotl(T x, U s) noexcept { - constexpr auto N {std::numeric_limits::digits}; + constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; if (r == 0) @@ -40,10 +40,10 @@ constexpr T rotl(T x, U s) noexcept return (x << r) | (x >> (N - r)); } -template ::value, bool>> +template ::value, bool>> constexpr T rotl(T x, U s) noexcept { - constexpr auto N {std::numeric_limits::digits}; + constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; if (r == 0) @@ -58,10 +58,10 @@ constexpr T rotl(T x, U s) noexcept return (x << r) | (x >> (N - r)); } -template ::value, bool>> +template ::value, bool>> constexpr T rotr(T x, U s) noexcept { - constexpr auto N {std::numeric_limits::digits}; + constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; if (r == 0) @@ -72,10 +72,10 @@ constexpr T rotr(T x, U s) noexcept return (x >> r) | (x << (N - r)); } -template ::value, bool>> +template ::value, bool>> constexpr T rotr(T x, U s) noexcept { - constexpr auto N {std::numeric_limits::digits}; + constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; if (r == 0) @@ -90,7 +90,7 @@ constexpr T rotr(T x, U s) noexcept return (x >> r) | (x << (N - r)); } -constexpr auto swap_endian(const std::uint32_t val) -> std::uint32_t +constexpr auto swap_endian(const boost::crypt::uint32_t val) -> boost::crypt::uint32_t { return ((val & 0xFF000000) >> 24U) | ((val & 0x00FF0000) >> 8U) | @@ -102,4 +102,4 @@ constexpr auto swap_endian(const std::uint32_t val) -> std::uint32_t } // namespace crypt } // namespace boost -#endif //BOOST_BIT_HPP +#endif //BOOST_CRYPT_UTILITY_BIT_HPP From 5744e7656c66e538f20996885ec6f28178d9b5db Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 11:59:44 -0400 Subject: [PATCH 39/76] Make a byte CUDA capable --- include/boost/crypt/utility/byte.hpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/include/boost/crypt/utility/byte.hpp b/include/boost/crypt/utility/byte.hpp index 43a8453b..1856801e 100644 --- a/include/boost/crypt/utility/byte.hpp +++ b/include/boost/crypt/utility/byte.hpp @@ -7,10 +7,7 @@ #include #include - -#ifndef BOOST_CRYPT_BUILD_MODULE -#include -#endif +#include namespace boost { namespace crypt { @@ -18,11 +15,11 @@ namespace crypt { class byte { private: - std::uint8_t bits_; + boost::crypt::uint8_t bits_; public: constexpr byte() noexcept : bits_ {} {} - explicit constexpr byte(std::uint8_t bits) noexcept : bits_ {bits} {} + explicit constexpr byte(boost::crypt::uint8_t bits) noexcept : bits_ {bits} {} template constexpr auto to_integer() noexcept @@ -47,22 +44,22 @@ class byte constexpr auto operator|(byte rhs) const noexcept -> byte { - return byte{static_cast(bits_ | rhs.bits_)}; + return byte{static_cast(bits_ | rhs.bits_)}; } constexpr auto operator&(byte rhs) const noexcept -> byte { - return byte{static_cast(bits_ & rhs.bits_)}; + return byte{static_cast(bits_ & rhs.bits_)}; } constexpr auto operator^(byte rhs) const noexcept -> byte { - return byte{static_cast(bits_ ^ rhs.bits_)}; + return byte{static_cast(bits_ ^ rhs.bits_)}; } constexpr auto operator~() const noexcept -> byte { - return byte{static_cast(~bits_)}; + return byte{static_cast(~bits_)}; } template @@ -83,19 +80,19 @@ class byte constexpr auto operator|(byte rhs) noexcept -> byte& { - bits_ = static_cast(bits_ | rhs.bits_); + bits_ = static_cast(bits_ | rhs.bits_); return *this; } constexpr auto operator&(byte rhs) noexcept -> byte& { - bits_ = static_cast(bits_ & rhs.bits_); + bits_ = static_cast(bits_ & rhs.bits_); return *this; } constexpr auto operator^(byte rhs) noexcept -> byte& { - bits_ = static_cast(bits_ ^ rhs.bits_); + bits_ = static_cast(bits_ ^ rhs.bits_); return *this; } From e3a137bd0c87e44ac89a91d99ea528a66b89e772 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 12:08:18 -0400 Subject: [PATCH 40/76] Simplify body function --- include/boost/crypt/hash/md5.hpp | 162 ++++++++++++++++--------------- 1 file changed, 86 insertions(+), 76 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 1cdde53a..c29179f0 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -7,6 +7,9 @@ #include #include +#include +#include +#include #include #include @@ -21,14 +24,14 @@ namespace crypt { namespace detail { -static constexpr std::array S { +static constexpr boost::crypt::array S { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; -static constexpr std::array K { +static constexpr boost::crypt::array K { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, @@ -48,123 +51,130 @@ static constexpr std::array K { }; template -auto md5_preprocess(T begin, T end) -> std::vector +auto md5_preprocess(T begin, T end) -> std::vector { - std::vector vec; - vec.reserve(static_cast(end - begin)); + std::vector vec; + vec.reserve(static_cast(end - begin)); // Like std::copy but gives us the correct cast std::transform(begin, end, std::back_inserter(vec), [](const auto& element) { - return static_cast(element); + return static_cast(element); }); return vec; } template -auto md5_preprocess(T begin, std::size_t len) -> std::vector +auto md5_preprocess(T begin, boost::crypt::size_t len) -> std::vector { - std::vector vec; + std::vector vec; vec.reserve(len); std::transform(begin, begin + len, std::back_inserter(vec), [](const auto& element) { - return static_cast(element); + return static_cast(element); }); return vec; } -auto md5_pad(const std::vector& message) noexcept -> std::vector +auto md5_pad(const std::vector& message) noexcept -> std::vector { - std::vector padded_message {message}; - const std::uint64_t original_length {message.size() * 8U}; - padded_message.emplace_back(static_cast(0x80)); + std::vector padded_message {message}; + const boost::crypt::uint64_t original_length {message.size() * 8U}; + padded_message.emplace_back(static_cast(0x80)); while ((padded_message.size() * 8U) % 512U != 448U) { - padded_message.emplace_back(static_cast(0x00)); + padded_message.emplace_back(static_cast(0x00)); } // Add the original length as a 64-bit number - for (std::size_t i = 0; i < 8; ++i) + for (boost::crypt::size_t i = 0; i < 8; ++i) { - padded_message.emplace_back(static_cast((original_length >> (8 * i)) & 0xFF)); + padded_message.emplace_back(static_cast((original_length >> (8 * i)) & 0xFF)); } return padded_message; } +auto md5_body(const boost::crypt::array& blocks, + boost::crypt::uint32_t& a, boost::crypt::uint32_t& b, + boost::crypt::uint32_t& c, boost::crypt::uint32_t& d) noexcept +{ + boost::crypt::uint32_t A {a}; + boost::crypt::uint32_t B {b}; + boost::crypt::uint32_t C {c}; + boost::crypt::uint32_t D {d}; + + for (boost::crypt::uint32_t i {}; i < 64U; ++i) + { + boost::crypt::uint32_t F {}; + boost::crypt::uint32_t g {}; + + if (i <= 15U) + { + F = (B & C) | ((~B) & D); + g = i; + } + else if (i <= 31U) + { + F = (D & B) | ((~D) & C); + g = (5U * i + 1U) % 16U; + } + else if (i <= 47U) + { + F = B ^ C ^ D; + g = (3U * i + 5U) % 16U; + } + else + { + F = C ^ (B | (~D)); + g = (7U * i) % 16U; + } + + BOOST_CRYPT_ASSERT(i <= 63U); + + F = F + A + K[i] + blocks[g]; + A = D; + D = C; + C = B; + B = B + rotl(F, S[i]); + } + + a += A; + b += B; + c += C; + d += D; +} + template -auto md5_impl(const std::vector& padded_message) -> ResultType +auto md5_impl(const std::vector& padded_message) -> ResultType { - std::uint32_t a0 {0x67452301}; - std::uint32_t b0 {0xefcdab89}; - std::uint32_t c0 {0x98badcfe}; - std::uint32_t d0 {0x10325476}; + boost::crypt::uint32_t a0 {0x67452301}; + boost::crypt::uint32_t b0 {0xefcdab89}; + boost::crypt::uint32_t c0 {0x98badcfe}; + boost::crypt::uint32_t d0 {0x10325476}; - std::array blocks {}; + boost::crypt::array blocks {}; - std::size_t message_chunk {}; + boost::crypt::size_t message_chunk {}; while (message_chunk < padded_message.size()) { for (auto& block : blocks) { - block = static_cast( - (static_cast(padded_message[message_chunk])) + - (static_cast(padded_message[message_chunk + 1U]) << 8U) + - (static_cast(padded_message[message_chunk + 2U]) << 16U) + - (static_cast(padded_message[message_chunk + 3U]) << 24U) + block = static_cast( + (static_cast(padded_message[message_chunk])) + + (static_cast(padded_message[message_chunk + 1U]) << 8U) + + (static_cast(padded_message[message_chunk + 2U]) << 16U) + + (static_cast(padded_message[message_chunk + 3U]) << 24U) ); message_chunk += 4U; } - std::uint32_t A {a0}; - std::uint32_t B {b0}; - std::uint32_t C {c0}; - std::uint32_t D {d0}; - - for (std::uint32_t i {}; i < 64U; ++i) - { - std::uint32_t F {}; - std::uint32_t g {}; - - if (i <= 15U) - { - F = (B & C) | ((~B) & D); - g = i; - } - else if (i <= 31U) - { - F = (D & B) | ((~D) & C); - g = (5U * i + 1U) % 16U; - } - else if (i <= 47U) - { - F = B ^ C ^ D; - g = (3U * i + 5U) % 16U; - } - else - { - F = C ^ (B | (~D)); - g = (7U * i) % 16U; - } - - BOOST_CRYPT_ASSERT(i <= 63U); - - F = F + A + K[i] + blocks[g]; - A = D; - D = C; - C = B; - B = B + rotl(F, S[i]); - } - - a0 += A; - b0 += B; - c0 += C; - d0 += D; + md5_body(blocks, a0, b0, c0, d0); } return ResultType {swap_endian(a0), @@ -175,7 +185,7 @@ auto md5_impl(const std::vector& padded_message) -> ResultType } // namespace detail -template , typename T> +template , typename T> ResultType md5(T begin, T end) { if (end <= begin) @@ -188,7 +198,7 @@ ResultType md5(T begin, T end) return detail::md5_impl(padded_message); } -template > +template > ResultType md5(const char* str) { if (str == nullptr) @@ -202,14 +212,14 @@ ResultType md5(const char* str) return detail::md5_impl(padded_message); } -template > +template > ResultType md5(const std::string& str) { return md5(str.begin(), str.end()); } #ifdef BOOST_CRYPT_HAS_STRING_VIEW -template > +template > ResultType md5(const std::string_view& str) { return md5(str.begin(), str.end()); From 12e6fd04831f520ee528e3811f83da322787cfd1 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 18:41:42 -0400 Subject: [PATCH 41/76] Add unreachable macro --- include/boost/crypt/utility/config.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/boost/crypt/utility/config.hpp b/include/boost/crypt/utility/config.hpp index bec8d29d..07e0f940 100644 --- a/include/boost/crypt/utility/config.hpp +++ b/include/boost/crypt/utility/config.hpp @@ -70,4 +70,14 @@ #endif // ----- Has CXX something ----- +// ----- Unreachable ----- +#if defined(__GNUC__) || defined(__clang__) +# define BOOST_CRYPT_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +# define BOOST_CRYPT_UNREACHABLE __assume(0) +#else +# define BOOST_CRYPT_UNREACHABLE std::abort() +#endif +// ----- Unreachable ----- + #endif //BOOST_CRYPT_DETAIL_CONFIG_HPP From b9b0092383eb7a60dd86febf3b9655b9f08624fd Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 18:42:26 -0400 Subject: [PATCH 42/76] Add iter pair md5 impl --- include/boost/crypt/hash/md5.hpp | 134 ++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 3 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index c29179f0..345902c8 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -99,6 +99,7 @@ auto md5_pad(const std::vector& message) noexcept -> std: return padded_message; } +// TODO(mborland): Replace the loop with the known statements auto md5_body(const boost::crypt::array& blocks, boost::crypt::uint32_t& a, boost::crypt::uint32_t& b, boost::crypt::uint32_t& c, boost::crypt::uint32_t& d) noexcept @@ -183,6 +184,135 @@ auto md5_impl(const std::vector& padded_message) -> Resul swap_endian(d0)}; } +template +auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType +{ + boost::crypt::uint32_t a0 {0x67452301}; + boost::crypt::uint32_t b0 {0xefcdab89}; + boost::crypt::uint32_t c0 {0x98badcfe}; + boost::crypt::uint32_t d0 {0x10325476}; + + boost::crypt::array blocks {}; + + do + { + if (first + 64U <= last) + { + for (auto& block : blocks) + { + block = static_cast( + static_cast(*first) + + (static_cast(*(first + 1U)) << 8U) + + (static_cast(*(first + 2U)) << 16U) + + (static_cast(*(first + 3U)) << 24U) + ); + + first += 4U; + } + } + else + { + // We need to conclude the message correctly with padding, and the message length + const auto message_length {static_cast(last - first) * 8UL}; + + boost::crypt::size_t current_block {}; + while (first + 4U < last) + { + blocks[current_block] = static_cast( + static_cast(*first) + + (static_cast(*(first + 1U)) << 8U) + + (static_cast(*(first + 2U)) << 16U) + + (static_cast(*(first + 3U)) << 24U) + ); + + first += 4U; + ++current_block; + } + + // Need to tack on the 0x80 as the last byte after the message + switch (last - first) + { + case 0: + blocks[current_block] = static_cast(0x80); + ++current_block; + break; + case 1: + blocks[current_block] = static_cast( + static_cast(*first) + + (static_cast(0x80) << 8U) + ); + ++current_block; + ++first; + break; + case 2: + blocks[current_block] = static_cast( + static_cast(*first) + + (static_cast(*(first + 1U)) << 8U) + + (static_cast(0x80) << 16U) + ); + ++current_block; + first += 2U; + break; + case 3: + blocks[current_block] = static_cast( + static_cast(*first) + + (static_cast(*(first + 1U)) << 8U) + + (static_cast(*(first + 2U)) << 16U) + + (static_cast(0x80) << 24U) + ); + ++current_block; + first += 3U; + break; + // LCOV_EXCL_START + default: + BOOST_CRYPT_UNREACHABLE; + // LCOV_EXCL_STOP + } + + while (current_block < 14U) + { + // Zero Pad + blocks[current_block] = static_cast(0x0); + ++current_block; + } + + // Now we need add the original string length + if (current_block == 14U) + { + blocks[current_block] = static_cast(message_length & 0xFFFFFFFF); + blocks[current_block + 1] = static_cast((message_length >> 32) & 0xFFFFFFFF); + } + else + { + // We need to do another loop + BOOST_CRYPT_ASSERT(current_block == 15U); + blocks[current_block] = static_cast(0x0); + md5_body(blocks, a0, b0, c0, d0); + + // The length is always last + current_block = 0; + ++current_block; + while (current_block < 14U) + { + blocks[current_block] = static_cast(0x0); + ++current_block; + } + + blocks[current_block] = static_cast(message_length & 0xFFFFFFFF); + blocks[current_block + 1] = static_cast((message_length >> 32) & 0xFFFFFFFF); + } + } + + md5_body(blocks, a0, b0, c0, d0); + + } while (first != last); + + return ResultType {swap_endian(a0), + swap_endian(b0), + swap_endian(c0), + swap_endian(d0)}; +} + } // namespace detail template , typename T> @@ -207,9 +337,7 @@ ResultType md5(const char* str) } const auto message_len {std::strlen(str)}; - const auto message {detail::md5_preprocess(str, message_len)}; - const auto padded_message {detail::md5_pad(message)}; - return detail::md5_impl(padded_message); + return detail::md5_impl(str, str + message_len); } template > From 2a07c51f01c0eb5b35ed4b213a725dc239e6371d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 19:11:00 -0400 Subject: [PATCH 43/76] Simplifications and corrections --- include/boost/crypt/hash/md5.hpp | 125 +++++++++++++------------------ 1 file changed, 52 insertions(+), 73 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 345902c8..10029dee 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -187,6 +187,7 @@ auto md5_impl(const std::vector& padded_message) -> Resul template auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType { + // Initial MD5 buffer values boost::crypt::uint32_t a0 {0x67452301}; boost::crypt::uint32_t b0 {0xefcdab89}; boost::crypt::uint32_t c0 {0x98badcfe}; @@ -194,14 +195,26 @@ auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType boost::crypt::array blocks {}; - do + // Store the original 'first' to compute the total message length + const auto total_message_length {static_cast(last - first) * 8UL}; + + // Handles the empty case with known values + if (first == last) + { + return ResultType{0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e}; + } + + while (first != last) { - if (first + 64U <= last) + boost::crypt::size_t current_block = 0; + + // Process as many full 64-byte blocks as possible + if (last - first >= 64) { for (auto& block : blocks) { block = static_cast( - static_cast(*first) + + static_cast(*first) + (static_cast(*(first + 1U)) << 8U) + (static_cast(*(first + 2U)) << 16U) + (static_cast(*(first + 3U)) << 24U) @@ -209,14 +222,16 @@ auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType first += 4U; } + md5_body(blocks, a0, b0, c0, d0); } else { - // We need to conclude the message correctly with padding, and the message length - const auto message_length {static_cast(last - first) * 8UL}; + // Process remaining bytes + // Initialize blocks to zero + blocks.fill(0); - boost::crypt::size_t current_block {}; - while (first + 4U < last) + // Process complete 4-byte chunks + while (last - first >= 4) { blocks[current_block] = static_cast( static_cast(*first) + @@ -229,83 +244,47 @@ auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType ++current_block; } - // Need to tack on the 0x80 as the last byte after the message - switch (last - first) + // Process remaining bytes (less than 4) + blocks[current_block] = 0; + auto byte_offset = 0U; + while (first != last) { - case 0: - blocks[current_block] = static_cast(0x80); - ++current_block; - break; - case 1: - blocks[current_block] = static_cast( - static_cast(*first) + - (static_cast(0x80) << 8U) - ); - ++current_block; - ++first; - break; - case 2: - blocks[current_block] = static_cast( - static_cast(*first) + - (static_cast(*(first + 1U)) << 8U) + - (static_cast(0x80) << 16U) - ); - ++current_block; - first += 2U; - break; - case 3: - blocks[current_block] = static_cast( - static_cast(*first) + - (static_cast(*(first + 1U)) << 8U) + - (static_cast(*(first + 2U)) << 16U) + - (static_cast(0x80) << 24U) - ); - ++current_block; - first += 3U; - break; - // LCOV_EXCL_START - default: - BOOST_CRYPT_UNREACHABLE; - // LCOV_EXCL_STOP + blocks[current_block] |= static_cast(*first) << (8U * byte_offset); + ++first; + ++byte_offset; } - while (current_block < 14U) - { - // Zero Pad - blocks[current_block] = static_cast(0x0); - ++current_block; - } + // Append the '1' bit (0x80) after the last byte + blocks[current_block] |= static_cast(0x80) << (8U * byte_offset); + ++current_block; - // Now we need add the original string length - if (current_block == 14U) - { - blocks[current_block] = static_cast(message_length & 0xFFFFFFFF); - blocks[current_block + 1] = static_cast((message_length >> 32) & 0xFFFFFFFF); - } - else + // Check if there is enough space to append the length + if (current_block > 14U) { - // We need to do another loop - BOOST_CRYPT_ASSERT(current_block == 15U); - blocks[current_block] = static_cast(0x0); + // Not enough space, process this block and start a new one md5_body(blocks, a0, b0, c0, d0); - - // The length is always last + blocks.fill(0); current_block = 0; + } + + // Pad with zeros until block[14] + while (current_block < 14U) + { + blocks[current_block] = 0; ++current_block; - while (current_block < 14U) - { - blocks[current_block] = static_cast(0x0); - ++current_block; - } - - blocks[current_block] = static_cast(message_length & 0xFFFFFFFF); - blocks[current_block + 1] = static_cast((message_length >> 32) & 0xFFFFFFFF); } - } - md5_body(blocks, a0, b0, c0, d0); + // Append the 64-bit length in bits in little-endian format + blocks[14] = static_cast(total_message_length & 0xFFFFFFFF); + blocks[15] = static_cast((total_message_length >> 32) & 0xFFFFFFFF); + + // Process the final block + md5_body(blocks, a0, b0, c0, d0); - } while (first != last); + // Break out of the loop as we've processed all data + break; + } + } return ResultType {swap_endian(a0), swap_endian(b0), From b51d2801d1feeb124fa79a45a252d9f8e874155b Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 19:24:58 -0400 Subject: [PATCH 44/76] Fix conversion warning --- include/boost/crypt/utility/byte.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/crypt/utility/byte.hpp b/include/boost/crypt/utility/byte.hpp index 1856801e..cf392988 100644 --- a/include/boost/crypt/utility/byte.hpp +++ b/include/boost/crypt/utility/byte.hpp @@ -98,7 +98,7 @@ class byte constexpr auto operator~() noexcept -> byte& { - bits_ = ~bits_; + bits_ = static_cast(~bits_); return *this; } }; From 20ccddac69e2b966875462d59e6a2c8df03609a5 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 9 Oct 2024 19:25:05 -0400 Subject: [PATCH 45/76] Fix concept namespace --- include/boost/crypt/utility/concepts.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt/utility/concepts.hpp b/include/boost/crypt/utility/concepts.hpp index 069598cd..3c05c3a2 100644 --- a/include/boost/crypt/utility/concepts.hpp +++ b/include/boost/crypt/utility/concepts.hpp @@ -50,7 +50,7 @@ namespace boost::crypt::concepts { template -concept integral = boost::crypt::detail::is_integral_v; +concept integral = boost::crypt::is_integral_v; template concept signed_integral = integral && boost::crypt::is_signed_v; @@ -59,7 +59,7 @@ template concept unsigned_integral = integral && boost::crypt::is_unsigned_v; template -concept real = boost::crypt::detail::is_floating_point_v; +concept real = boost::crypt::is_floating_point_v; } // boost::crypt::concepts From ff7ffc4725ca3bb2997879dbd88f55e53d1da2d6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 09:39:25 -0400 Subject: [PATCH 46/76] Remove old impls --- include/boost/crypt/hash/md5.hpp | 93 ++------------------------------ 1 file changed, 3 insertions(+), 90 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 10029dee..901ec990 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -11,13 +11,11 @@ #include #include -#include -#include -#include -#include +#ifndef BOOST_CRYPT_BUILD_MODULE #include #include #include +#endif namespace boost { namespace crypt { @@ -50,55 +48,6 @@ static constexpr boost::crypt::array K { 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; -template -auto md5_preprocess(T begin, T end) -> std::vector -{ - std::vector vec; - vec.reserve(static_cast(end - begin)); - - // Like std::copy but gives us the correct cast - std::transform(begin, end, std::back_inserter(vec), - [](const auto& element) { - return static_cast(element); - }); - - return vec; -} - -template -auto md5_preprocess(T begin, boost::crypt::size_t len) -> std::vector -{ - std::vector vec; - vec.reserve(len); - - std::transform(begin, begin + len, std::back_inserter(vec), - [](const auto& element) { - return static_cast(element); - }); - - return vec; -} - -auto md5_pad(const std::vector& message) noexcept -> std::vector -{ - std::vector padded_message {message}; - const boost::crypt::uint64_t original_length {message.size() * 8U}; - padded_message.emplace_back(static_cast(0x80)); - - while ((padded_message.size() * 8U) % 512U != 448U) - { - padded_message.emplace_back(static_cast(0x00)); - } - - // Add the original length as a 64-bit number - for (boost::crypt::size_t i = 0; i < 8; ++i) - { - padded_message.emplace_back(static_cast((original_length >> (8 * i)) & 0xFF)); - } - - return padded_message; -} - // TODO(mborland): Replace the loop with the known statements auto md5_body(const boost::crypt::array& blocks, boost::crypt::uint32_t& a, boost::crypt::uint32_t& b, @@ -150,40 +99,6 @@ auto md5_body(const boost::crypt::array& blocks, d += D; } -template -auto md5_impl(const std::vector& padded_message) -> ResultType -{ - boost::crypt::uint32_t a0 {0x67452301}; - boost::crypt::uint32_t b0 {0xefcdab89}; - boost::crypt::uint32_t c0 {0x98badcfe}; - boost::crypt::uint32_t d0 {0x10325476}; - - boost::crypt::array blocks {}; - - boost::crypt::size_t message_chunk {}; - while (message_chunk < padded_message.size()) - { - for (auto& block : blocks) - { - block = static_cast( - (static_cast(padded_message[message_chunk])) + - (static_cast(padded_message[message_chunk + 1U]) << 8U) + - (static_cast(padded_message[message_chunk + 2U]) << 16U) + - (static_cast(padded_message[message_chunk + 3U]) << 24U) - ); - - message_chunk += 4U; - } - - md5_body(blocks, a0, b0, c0, d0); - } - - return ResultType {swap_endian(a0), - swap_endian(b0), - swap_endian(c0), - swap_endian(d0)}; -} - template auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType { @@ -302,9 +217,7 @@ ResultType md5(T begin, T end) return ResultType {0, 0, 0, 0}; } - const auto message {detail::md5_preprocess(begin, end)}; - const auto padded_message {detail::md5_pad(message)}; - return detail::md5_impl(padded_message); + return detail::md5_impl(begin, end); } template > From 24ec67d516eddaa34881d39209d776498d4e33a0 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 11:04:37 -0400 Subject: [PATCH 47/76] Add generic strlen --- include/boost/crypt/utility/strlen.hpp | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 include/boost/crypt/utility/strlen.hpp diff --git a/include/boost/crypt/utility/strlen.hpp b/include/boost/crypt/utility/strlen.hpp new file mode 100644 index 00000000..e81acd47 --- /dev/null +++ b/include/boost/crypt/utility/strlen.hpp @@ -0,0 +1,30 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CRYPT_UTILITY_STRLEN_HPP +#define BOOST_CRYPT_UTILITY_STRLEN_HPP + +#include + +namespace boost { +namespace crypt { +namespace utility { + +template +constexpr auto strlen(ForwardIter str) noexcept -> boost::crypt::size_t +{ + boost::crypt::size_t len {}; + while (*(str + len) != static_cast('\0')) + { + ++len; + } + + return len; +} + +} // namespace utility +} // namespace crypt +} // namespace boost + +#endif //BOOST_CRYPT_UTILITY_STRLEN_HPP From 14177ef57d182137f9f7cb04a7e02a4c0de06614 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 12:00:40 -0400 Subject: [PATCH 48/76] Make separate cstddef header --- include/boost/crypt/utility/cstddef.hpp | 44 +++++++++++++++++++++++++ include/boost/crypt/utility/cstdint.hpp | 5 --- 2 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 include/boost/crypt/utility/cstddef.hpp diff --git a/include/boost/crypt/utility/cstddef.hpp b/include/boost/crypt/utility/cstddef.hpp new file mode 100644 index 00000000..3fb2a1c8 --- /dev/null +++ b/include/boost/crypt/utility/cstddef.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matt Borland +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CRYPT_TOOLS_CSTDDEF +#define BOOST_CRYPT_TOOLS_CSTDDEF + +#include + +#ifdef BOOST_CRYPT_HAS_CUDA + +namespace boost { +namespace crypt { + +using size_t = unsigned long; +using ptrdiff_t = long; +using nullptr_t = void; +using std::max_align_t = double; + + +} // namespace crypt +} // namespace boost + +#else // No cude + +#ifndef BOOST_CRYPT_BUILD_MODULE +#include +#endif + +namespace boost { +namespace crypt { + +using std::size_t; +using std::ptrdiff_t; +using std::nullptr_t; +using std::max_align_t; + +} // namespace crypt +} // namespace boost + +#endif // BOOST_CRYPT_HAS_CUDA + +#endif //BOOST_CSTDDEF_HPP diff --git a/include/boost/crypt/utility/cstdint.hpp b/include/boost/crypt/utility/cstdint.hpp index 975230a1..12f512ab 100644 --- a/include/boost/crypt/utility/cstdint.hpp +++ b/include/boost/crypt/utility/cstdint.hpp @@ -51,13 +51,10 @@ using cuda::std::uint_least64_t; using cuda::std::uintmax_t; using cuda::std::uintptr_t; -using size_t = unsigned long; - #else #ifndef BOOST_CRYPT_BUILD_MODULE #include -#include #endif namespace boost { @@ -99,8 +96,6 @@ using std::uint_least64_t; using std::uintmax_t; using std::uintptr_t; -using std::size_t; - #endif } // namespace crypt From cd9d907fc91d210786c6b62f4479bcb641ff027e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 12:22:04 -0400 Subject: [PATCH 49/76] Implement our own array class --- include/boost/crypt/utility/array.hpp | 98 ++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp index fdeeee74..60c7a4dc 100644 --- a/include/boost/crypt/utility/array.hpp +++ b/include/boost/crypt/utility/array.hpp @@ -7,33 +7,99 @@ #define BOOST_CRYPT_UTILITIES_ARRAY_HPP #include - -#ifdef BOOST_CRYPT_HAS_CUDA - -#include +#include +#include namespace boost { namespace crypt { -using cuda::std::array; +template +class array +{ +public: + using reference = T&; + using const_reference = const T&; + using iterator = T*; + using const_iterator = const T*; + using size_type = boost::crypt::size_t; + using difference_type = boost::crypt::ptrdiff_t; + using value_type = T; + using pointer = T*; + using const_pointer = const T*; -} // namespace crypt -} // namespace boost + T elements[N]; -#else // Use the STL + constexpr array() = default; -#ifndef BOOST_CRYPT_BUILD_MODULE -#include -#endif + // Iterators + constexpr auto begin() noexcept -> iterator { return elements; } + constexpr auto cbegin() const noexcept -> const_iterator { return elements; } + constexpr auto end() noexcept -> iterator { return elements + N; } + constexpr auto cend() const noexcept -> const_iterator { return elements + N; } -namespace boost { -namespace crypt { + // Sizing + constexpr auto size() noexcept -> size_type { return N; } + constexpr auto max_size() noexcept -> size_type { return N; } + + // Accessors + constexpr auto operator[](size_type n) noexcept -> reference + { + BOOST_CRYPT_ASSERT(n < N); + return elements[n]; + } -using std::array; + constexpr auto operator[](size_type n) const noexcept -> const_reference + { + BOOST_CRYPT_ASSERT(n < N); + return elements[n]; + } + + // For at instead of throwing on out of range return the last element since throwing doesn't work on device + constexpr auto at(size_type n) noexcept -> reference + { + if (n >= N) + { + return elements[N - 1U]; + } + return elements[n]; + } + + constexpr auto at(size_type n) const noexcept -> const_reference + { + if (n >= N) + { + return elements[N - 1U]; + } + return elements[n]; + } + + // Front and back + constexpr auto front() noexcept -> reference { return elements[0]; } + constexpr auto front() const noexcept -> const_reference { return elements[0]; } + constexpr auto back() noexcept -> reference { return elements[N - 1]; } + constexpr auto back() const noexcept -> const_reference { return elements[N - 1]; } + + constexpr auto data() noexcept -> pointer { return elements; } + constexpr auto data() const noexcept -> const_pointer { return elements; } + + // Fill and swap + constexpr auto fill(const value_type& v) -> void + { + for (size_type i {}; i < N; ++i) + { + elements[i] = v; + } + } + + constexpr auto swap(array& a) + { + const auto temp {a}; + a = *this; + *this = temp; + } +}; } // namespace crypt } // namespace boost -#endif // CUDA - #endif // BOOST_CRYPT_UTILITIES_ARRAY_HPP From 12478730a2e23e7b63df18e249b80e96637f641f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 12:51:49 -0400 Subject: [PATCH 50/76] Replace std::array calls with our array --- include/boost/crypt/hash/md5.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 901ec990..c9eb923f 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #ifndef BOOST_CRYPT_BUILD_MODULE #include @@ -209,7 +212,7 @@ auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType } // namespace detail -template , typename T> +template , typename T> ResultType md5(T begin, T end) { if (end <= begin) @@ -220,7 +223,7 @@ ResultType md5(T begin, T end) return detail::md5_impl(begin, end); } -template > +template > ResultType md5(const char* str) { if (str == nullptr) @@ -232,7 +235,7 @@ ResultType md5(const char* str) return detail::md5_impl(str, str + message_len); } -template > +template > ResultType md5(const std::string& str) { return md5(str.begin(), str.end()); From 6d16853911e620352c877efa926e8e9ee73b167d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 16:35:31 -0400 Subject: [PATCH 51/76] Add fill --- include/boost/crypt/utility/array.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp index 60c7a4dc..0662ef42 100644 --- a/include/boost/crypt/utility/array.hpp +++ b/include/boost/crypt/utility/array.hpp @@ -99,6 +99,15 @@ class array } }; +template +constexpr auto fill_array(ForwardIter first, ForwardIter last, T value) +{ + while (first != last) + { + *first++ = static_cast(value); + } +} + } // namespace crypt } // namespace boost From 44983794735a90e905477502bdad079ec2a25182 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 16:35:42 -0400 Subject: [PATCH 52/76] Add missing type_trait --- include/boost/crypt/utility/type_traits.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/crypt/utility/type_traits.hpp b/include/boost/crypt/utility/type_traits.hpp index 94635498..61033a22 100644 --- a/include/boost/crypt/utility/type_traits.hpp +++ b/include/boost/crypt/utility/type_traits.hpp @@ -488,6 +488,9 @@ BOOST_CRYPT_INLINE_CONSTEXPR bool is_same_v = boost::crypt::is_same::value template BOOST_CRYPT_INLINE_CONSTEXPR bool is_base_of_v = boost::crypt::is_base_of::value; +template +BOOST_CRYPT_INLINE_CONSTEXPR bool is_convertible_v = boost::crypt::is_convertible::value; + } // namespace crypt } // namespace boost From 9f324b74ee95044a0be455487a52e670ea6f7b8f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 16:35:52 -0400 Subject: [PATCH 53/76] Add concept for conversion --- include/boost/crypt/utility/concepts.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/crypt/utility/concepts.hpp b/include/boost/crypt/utility/concepts.hpp index 3c05c3a2..47037ea9 100644 --- a/include/boost/crypt/utility/concepts.hpp +++ b/include/boost/crypt/utility/concepts.hpp @@ -75,7 +75,7 @@ concept real = boost::crypt::is_floating_point_v; #define BOOST_CRYPT_REQUIRES_TWO_RETURN(X1, T1, X2, T2, ReturnType) -> ReturnType requires X1 && X2 #define BOOST_CRYPT_REQUIRES_THREE(X1, T1, X2, T2, X3, T3) -> detail::promote_args_t requires X1 && X2 && X3 #define BOOST_CRYPT_REQUIRES_RETURN(X, T, ReturnType) -> ReturnType requires X - +#define BOOST_CRYPT_REQUIRES_CONVERSION(T1, T2) -> void requires boost::crypt::is_convertible_v #endif // Has #endif // C++20 @@ -117,4 +117,8 @@ concept real = boost::crypt::is_floating_point_v; # define BOOST_CRYPT_REQUIRES_RETURN(X, T, ReturnType) -> boost::crypt::enable_if_t, ReturnType> #endif +#ifndef BOOST_CRYPT_REQUIRES_CONVERSION +# define BOOST_CRYPT_REQUIRES_CONVERSION(T1, T2) -> boost::crypt::enable_if_t, void> +#endif + #endif //BOOST_CRYPT_UTILITY_CONCEPTS_HPP From 510c53e305189d2d76c148da7332592aea961048 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 16:36:09 -0400 Subject: [PATCH 54/76] Add class based design --- include/boost/crypt/hash/md5.hpp | 180 +++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index c9eb923f..a5215c38 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -102,6 +102,186 @@ auto md5_body(const boost::crypt::array& blocks, d += D; } +class md5 +{ +private: + boost::crypt::uint32_t a0_ {0x67452301}; + boost::crypt::uint32_t b0_ {0xefcdab89}; + boost::crypt::uint32_t c0_ {0x98badcfe}; + boost::crypt::uint32_t d0_ {0x10325476}; + + boost::crypt::size_t low_ {}; + boost::crypt::size_t high_ {}; + + boost::crypt::array buffer_ {}; + boost::crypt::array blocks_ {}; + + template + constexpr auto md5_update(ForwardIter data, boost::crypt::size_t size) noexcept; + + constexpr auto md5_convert_buffer_to_blocks() noexcept; + + template + constexpr auto md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept; + +public: + constexpr auto init() noexcept -> void; + + template + constexpr auto process_byte(ByteType byte) noexcept + BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t); + + template + constexpr auto process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept + BOOST_CRYPT_REQUIRES_CONVERSION(boost::crypt::uint8_t, decltype(*buffer)); + + template + constexpr auto get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept; +}; + +constexpr auto md5::init() noexcept -> void +{ + a0_ = 0x67452301U; + b0_ = 0xefcdab89U; + c0_ = 0x98badcfeU; + d0_ = 0x10325476U; + + low_ = 0U; + high_ = 0U; + + buffer_.fill(static_cast(0)); + blocks_.fill(0U); +} + +constexpr auto md5::md5_convert_buffer_to_blocks() noexcept +{ + boost::crypt::size_t buffer_index {}; + for (auto& block : blocks_) + { + block = static_cast( + static_cast(buffer_[buffer_index]) | + (static_cast(buffer_[buffer_index + 1U]) << 8U) | + (static_cast(buffer_[buffer_index + 2U]) << 16U) | + (static_cast(buffer_[buffer_index + 3U]) << 24U) + ); + + buffer_index += 4U; + } +} + +template +constexpr auto md5::md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept +{ + for (boost::crypt::size_t i {}; i < size; ++i) + { + BOOST_CRYPT_ASSERT(offset + i < buffer_.size()); + buffer_[offset + i] = static_cast(*(data + i)); + } +} + +template +constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noexcept +{ + const auto input_bits {size << 3U}; // Convert size to bits + const auto old_low {low_}; + low_ += input_bits; + if (low_ < old_low) + { + ++high_; + } + high_ += size >> 29U; + + auto used {(old_low >> 3U) & 0x3F}; // Number of bytes used in buffer + + if (used) + { + auto available = 64U - used; + if (size < available) + { + md5_copy_data(data, used, size); + return; + } + + md5_copy_data(data, used, available); + md5_convert_buffer_to_blocks(); + md5_body(blocks_, a0_, b0_, c0_, d0_); + data += available; + size -= available; + } + + while (size >= 64U) + { + md5_copy_data(data, 0U, 64U); + md5_convert_buffer_to_blocks(); + md5_body(blocks_, a0_, b0_, c0_, d0_); + data += 64U; + size -= 64U; + } + + if (size > 0) + { + md5_copy_data(data, 0U, size); + } +} + +template +constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept +{ + auto used {(low_ >> 3U) & 0x3F}; // Number of bytes used in buffer + buffer_[used++] = 0x80; + auto available {buffer_.size() - used}; + + if (available < 8U) + { + fill_array(buffer_.begin() + used, buffer_.end(), static_cast(0)); + md5_convert_buffer_to_blocks(); + md5_body(blocks_, a0_, b0_, c0_, d0_); + used = 0; + buffer_.fill(0); + } + else + { + fill_array(buffer_.begin() + used, buffer_.end() - 8, static_cast(0)); + } + + uint64_t total_bits = (static_cast(high_) << 32) | low_; + + // Append the length in bits as a 64-bit little-endian integer + buffer_[56] = static_cast(total_bits & 0xFF); + buffer_[57] = static_cast((total_bits >> 8) & 0xFF); + buffer_[58] = static_cast((total_bits >> 16) & 0xFF); + buffer_[59] = static_cast((total_bits >> 24) & 0xFF); + buffer_[60] = static_cast((total_bits >> 32) & 0xFF); + buffer_[61] = static_cast((total_bits >> 40) & 0xFF); + buffer_[62] = static_cast((total_bits >> 48) & 0xFF); + buffer_[63] = static_cast((total_bits >> 56) & 0xFF); + + md5_convert_buffer_to_blocks(); + md5_body(blocks_, a0_, b0_, c0_, d0_); + + if (digest_size >= 4) + { + digest[0] = swap_endian(a0_); + digest[1] = swap_endian(b0_); + digest[2] = swap_endian(c0_); + digest[3] = swap_endian(d0_); + } +} + +template +constexpr auto md5::process_byte(ByteType byte) noexcept + BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t) +{ + md5_update(&byte, 1UL); +} + +template +constexpr auto md5::process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept + BOOST_CRYPT_REQUIRES_CONVERSION(boost::crypt::uint8_t, decltype(*buffer)) +{ + md5_update(buffer, byte_count); +} + template auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType { From 1727a0af32f7def6f74002382d36eff98cba3f83 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 16:45:14 -0400 Subject: [PATCH 55/76] Add class design test --- test/test_md5.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 04470d42..02a6850a 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -7,6 +7,7 @@ #include #include #include +#include void basic_tests() { @@ -71,11 +72,28 @@ void bad_input() BOOST_TEST_EQ(message_1_result[3], 0x0); } +void test_class() +{ + boost::crypt::detail::md5 hasher; + constexpr auto msg = "The quick brown fox jumps over the lazy dog"; + hasher.process_bytes(msg, std::strlen(msg)); + std::array message_1_result {}; + hasher.get_digest(message_1_result.begin(), message_1_result.size()); + + BOOST_TEST_EQ(message_1_result[0], 0x9e107d9d); + BOOST_TEST_EQ(message_1_result[1], 0x372bb682); + BOOST_TEST_EQ(message_1_result[2], 0x6bd81d35); + BOOST_TEST_EQ(message_1_result[3], 0x42a419d6); +} + + int main() { basic_tests(); string_test(); bad_input(); + test_class(); + return boost::report_errors(); } From fdecb4ba5ab5749d08f58e0ef072cd681b54c6d3 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 18:33:04 -0400 Subject: [PATCH 56/76] Make array an aggregate --- include/boost/crypt/utility/array.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp index 0662ef42..a70107d6 100644 --- a/include/boost/crypt/utility/array.hpp +++ b/include/boost/crypt/utility/array.hpp @@ -29,8 +29,6 @@ class array T elements[N]; - constexpr array() = default; - // Iterators constexpr auto begin() noexcept -> iterator { return elements; } constexpr auto cbegin() const noexcept -> const_iterator { return elements; } From 98a50607c850e9548df652db3ce42f41decaf4b3 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 10 Oct 2024 18:34:51 -0400 Subject: [PATCH 57/76] Remove bad concept --- include/boost/crypt/hash/md5.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index a5215c38..8dd45249 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -132,8 +132,7 @@ class md5 BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t); template - constexpr auto process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept - BOOST_CRYPT_REQUIRES_CONVERSION(boost::crypt::uint8_t, decltype(*buffer)); + constexpr auto process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept; template constexpr auto get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept; @@ -277,7 +276,6 @@ constexpr auto md5::process_byte(ByteType byte) noexcept template constexpr auto md5::process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept - BOOST_CRYPT_REQUIRES_CONVERSION(boost::crypt::uint8_t, decltype(*buffer)) { md5_update(buffer, byte_count); } From 2885eb9ec2b5516f7b3dd5e35b7a0611d797acce Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 10:08:11 -0400 Subject: [PATCH 58/76] Fix 0 length string --- include/boost/crypt/hash/md5.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 8dd45249..b7b28128 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -393,10 +393,14 @@ auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType template , typename T> ResultType md5(T begin, T end) { - if (end <= begin) + if (end < begin) { return ResultType {0, 0, 0, 0}; } + else if (end == begin) + { + return ResultType{0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e}; + } return detail::md5_impl(begin, end); } From 5969bca96879adab7b8b1b3aee1712625b135d16 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 10:08:23 -0400 Subject: [PATCH 59/76] Improve testing methodology --- test/test_md5.cpp | 107 ++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 02a6850a..89387646 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -8,52 +8,54 @@ #include #include #include +#include -void basic_tests() +constexpr std::array, 3> test_values = { - const auto message_1_result {boost::crypt::md5("The quick brown fox jumps over the lazy dog")}; - BOOST_TEST_EQ(message_1_result[0], 0x9e107d9d); - BOOST_TEST_EQ(message_1_result[1], 0x372bb682); - BOOST_TEST_EQ(message_1_result[2], 0x6bd81d35); - BOOST_TEST_EQ(message_1_result[3], 0x42a419d6); - - const auto message_2_result {boost::crypt::md5("The quick brown fox jumps over the lazy dog.")}; - BOOST_TEST_EQ(message_2_result[0], 0xe4d909c2); - BOOST_TEST_EQ(message_2_result[1], 0x90d0fb1c); - BOOST_TEST_EQ(message_2_result[2], 0xa068ffad); - BOOST_TEST_EQ(message_2_result[3], 0xdf22cbd0); + std::make_tuple("The quick brown fox jumps over the lazy dog", 0x9e107d9d, 0x372bb682, 0x6bd81d35, 0x42a419d6), + std::make_tuple("The quick brown fox jumps over the lazy dog.", 0xe4d909c2, 0x90d0fb1c, 0xa068ffad, 0xdf22cbd0), + std::make_tuple("", 0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e) +}; - const auto message_3_result {boost::crypt::md5("")}; - BOOST_TEST_EQ(message_3_result[0], 0xd41d8cd9); - BOOST_TEST_EQ(message_3_result[1], 0x8f00b204); - BOOST_TEST_EQ(message_3_result[2], 0xe9800998); - BOOST_TEST_EQ(message_3_result[3], 0xecf8427e); +void basic_tests() +{ + for (const auto& test_value : test_values) + { + const auto message_result {boost::crypt::md5(std::get<0>(test_value))}; + BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + } } void string_test() { - std::string message_1 {"The quick brown fox jumps over the lazy dog"}; - const auto message_1_result {boost::crypt::md5(message_1)}; - BOOST_TEST_EQ(message_1_result[0], 0x9e107d9d); - BOOST_TEST_EQ(message_1_result[1], 0x372bb682); - BOOST_TEST_EQ(message_1_result[2], 0x6bd81d35); - BOOST_TEST_EQ(message_1_result[3], 0x42a419d6); + for (const auto& test_value : test_values) + { + const std::string string_message {std::get<0>(test_value)}; + const auto message_result {boost::crypt::md5(string_message)}; + BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + } +} +void string_view_test() +{ #ifdef BOOST_CRYPT_HAS_STRING_VIEW - std::string_view view_1 {message_1}; - const auto view_1_result {boost::crypt::md5(view_1)}; - BOOST_TEST_EQ(view_1_result[0], 0x9e107d9d); - BOOST_TEST_EQ(view_1_result[1], 0x372bb682); - BOOST_TEST_EQ(view_1_result[2], 0x6bd81d35); - BOOST_TEST_EQ(view_1_result[3], 0x42a419d6); + for (const auto& test_value : test_values) + { + const std::string string_message {std::get<0>(test_value)}; + const std::string_view string_view_message {string_message}; + const auto message_result {boost::crypt::md5(string_view_message)}; + BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + } #endif - - std::string message_2 {"The quick brown fox jumps over the lazy dog."}; - const auto message_2_result {boost::crypt::md5(message_2.begin(), message_2.end())}; - BOOST_TEST_EQ(message_2_result[0], 0xe4d909c2); - BOOST_TEST_EQ(message_2_result[1], 0x90d0fb1c); - BOOST_TEST_EQ(message_2_result[2], 0xa068ffad); - BOOST_TEST_EQ(message_2_result[3], 0xdf22cbd0); } void bad_input() @@ -63,34 +65,35 @@ void bad_input() BOOST_TEST_EQ(null_message[1], 0x0); BOOST_TEST_EQ(null_message[2], 0x0); BOOST_TEST_EQ(null_message[3], 0x0); - - std::string message_1 {"The quick brown fox jumps over the lazy dog"}; - const auto message_1_result {boost::crypt::md5(message_1.begin(), message_1.begin())}; - BOOST_TEST_EQ(message_1_result[0], 0x0); - BOOST_TEST_EQ(message_1_result[1], 0x0); - BOOST_TEST_EQ(message_1_result[2], 0x0); - BOOST_TEST_EQ(message_1_result[3], 0x0); } void test_class() { boost::crypt::detail::md5 hasher; - constexpr auto msg = "The quick brown fox jumps over the lazy dog"; - hasher.process_bytes(msg, std::strlen(msg)); - std::array message_1_result {}; - hasher.get_digest(message_1_result.begin(), message_1_result.size()); - BOOST_TEST_EQ(message_1_result[0], 0x9e107d9d); - BOOST_TEST_EQ(message_1_result[1], 0x372bb682); - BOOST_TEST_EQ(message_1_result[2], 0x6bd81d35); - BOOST_TEST_EQ(message_1_result[3], 0x42a419d6); -} + for (const auto& test_value : test_values) + { + const auto msg {std::get<0>(test_value)}; + hasher.process_bytes(msg, std::strlen(msg)); + std::array message_result {}; + hasher.get_digest(message_result.begin(), message_result.size()); + + BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + hasher.init(); + } +} int main() { basic_tests(); string_test(); + string_test(); + string_view_test(); + bad_input(); test_class(); From d1ffa8eed8068434583d618fe6452c8b9916fd0a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 10:19:08 -0400 Subject: [PATCH 60/76] Add additional test sets --- test/test_md5.cpp | 55 +++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 89387646..c0554269 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -6,15 +6,22 @@ #include #include +#include #include #include #include -constexpr std::array, 3> test_values = +constexpr std::array, 9> test_values = { std::make_tuple("The quick brown fox jumps over the lazy dog", 0x9e107d9d, 0x372bb682, 0x6bd81d35, 0x42a419d6), std::make_tuple("The quick brown fox jumps over the lazy dog.", 0xe4d909c2, 0x90d0fb1c, 0xa068ffad, 0xdf22cbd0), - std::make_tuple("", 0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e) + std::make_tuple("", 0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e), + std::make_tuple("ddcc8542894a27456bbeb43f51f38764c32f72ae", 0x3b340f00, 0x97312ec8, 0x2fa4da0d, 0x7da53002), + std::make_tuple("webmin1980", 0xb78aae35, 0x6709f8c3, 0x1118ea61, 0x3980954b), + std::make_tuple("$2y$10$EQAmcJw0cg.rt.6..SJ2bulFhDo0eWtuMhkfDMPGsNdap4xrOY61K", 0x40bbe664, 0x4efd9354, 0x078d8c70, 0xfb6c9f42), + std::make_tuple("pkirsanov", 0x8793ce04, 0xf0c5f1e8, 0xed1e0c78, 0xf249fe1b), + std::make_tuple("Eleanor", 0xd37e4317, 0x4905de70, 0xfbb5b038, 0xd7247f57), + std::make_tuple("The Whirlpool Galaxy is about 88% the size of the Milky Way, with a diameter of 76,900 light-years", 0xd5dfd7b4, 0x1235abc7, 0xa9a3205b, 0x6896f34d), }; void basic_tests() @@ -22,10 +29,13 @@ void basic_tests() for (const auto& test_value : test_values) { const auto message_result {boost::crypt::md5(std::get<0>(test_value))}; - BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + { + std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + } } } @@ -35,10 +45,13 @@ void string_test() { const std::string string_message {std::get<0>(test_value)}; const auto message_result {boost::crypt::md5(string_message)}; - BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + { + std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + } } } @@ -50,10 +63,13 @@ void string_view_test() const std::string string_message {std::get<0>(test_value)}; const std::string_view string_view_message {string_message}; const auto message_result {boost::crypt::md5(string_view_message)}; - BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + { + std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + } } #endif } @@ -78,10 +94,13 @@ void test_class() std::array message_result {}; hasher.get_digest(message_result.begin(), message_result.size()); - BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)); - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)); - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)); - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)); + if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && + BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && + BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && + BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + { + std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + } hasher.init(); } From fa72b53bf1ec57548093689c4ab170c924c672e5 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 10:39:45 -0400 Subject: [PATCH 61/76] Convert all usage to the class --- include/boost/crypt/hash/md5.hpp | 235 +++++++++---------------------- test/test_md5.cpp | 2 +- 2 files changed, 67 insertions(+), 170 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index b7b28128..39c9d04d 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -51,58 +51,9 @@ static constexpr boost::crypt::array K { 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; -// TODO(mborland): Replace the loop with the known statements -auto md5_body(const boost::crypt::array& blocks, - boost::crypt::uint32_t& a, boost::crypt::uint32_t& b, - boost::crypt::uint32_t& c, boost::crypt::uint32_t& d) noexcept -{ - boost::crypt::uint32_t A {a}; - boost::crypt::uint32_t B {b}; - boost::crypt::uint32_t C {c}; - boost::crypt::uint32_t D {d}; - - for (boost::crypt::uint32_t i {}; i < 64U; ++i) - { - boost::crypt::uint32_t F {}; - boost::crypt::uint32_t g {}; - - if (i <= 15U) - { - F = (B & C) | ((~B) & D); - g = i; - } - else if (i <= 31U) - { - F = (D & B) | ((~D) & C); - g = (5U * i + 1U) % 16U; - } - else if (i <= 47U) - { - F = B ^ C ^ D; - g = (3U * i + 5U) % 16U; - } - else - { - F = C ^ (B | (~D)); - g = (7U * i) % 16U; - } - - BOOST_CRYPT_ASSERT(i <= 63U); - - F = F + A + K[i] + blocks[g]; - A = D; - D = C; - C = B; - B = B + rotl(F, S[i]); - } - - a += A; - b += B; - c += C; - d += D; -} +} // namespace detail -class md5 +class md5_hasher { private: boost::crypt::uint32_t a0_ {0x67452301}; @@ -124,6 +75,8 @@ class md5 template constexpr auto md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept; + constexpr auto md5_body() noexcept -> void; + public: constexpr auto init() noexcept -> void; @@ -138,7 +91,7 @@ class md5 constexpr auto get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept; }; -constexpr auto md5::init() noexcept -> void +constexpr auto md5_hasher::init() noexcept -> void { a0_ = 0x67452301U; b0_ = 0xefcdab89U; @@ -152,7 +105,7 @@ constexpr auto md5::init() noexcept -> void blocks_.fill(0U); } -constexpr auto md5::md5_convert_buffer_to_blocks() noexcept +constexpr auto md5_hasher::md5_convert_buffer_to_blocks() noexcept { boost::crypt::size_t buffer_index {}; for (auto& block : blocks_) @@ -169,17 +122,17 @@ constexpr auto md5::md5_convert_buffer_to_blocks() noexcept } template -constexpr auto md5::md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept +constexpr auto md5_hasher::md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept { for (boost::crypt::size_t i {}; i < size; ++i) { BOOST_CRYPT_ASSERT(offset + i < buffer_.size()); - buffer_[offset + i] = static_cast(*(data + i)); + buffer_[offset + i] = static_cast(*(data + static_cast(i))); } } template -constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noexcept +constexpr auto md5_hasher::md5_update(ForwardIter data, boost::crypt::size_t size) noexcept { const auto input_bits {size << 3U}; // Convert size to bits const auto old_low {low_}; @@ -203,8 +156,8 @@ constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noex md5_copy_data(data, used, available); md5_convert_buffer_to_blocks(); - md5_body(blocks_, a0_, b0_, c0_, d0_); - data += available; + md5_body(); + data += static_cast(available); size -= available; } @@ -212,7 +165,7 @@ constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noex { md5_copy_data(data, 0U, 64U); md5_convert_buffer_to_blocks(); - md5_body(blocks_, a0_, b0_, c0_, d0_); + md5_body(); data += 64U; size -= 64U; } @@ -224,7 +177,7 @@ constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noex } template -constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept +constexpr auto md5_hasher::get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept { auto used {(low_ >> 3U) & 0x3F}; // Number of bytes used in buffer buffer_[used++] = 0x80; @@ -234,7 +187,7 @@ constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_si { fill_array(buffer_.begin() + used, buffer_.end(), static_cast(0)); md5_convert_buffer_to_blocks(); - md5_body(blocks_, a0_, b0_, c0_, d0_); + md5_body(); used = 0; buffer_.fill(0); } @@ -256,140 +209,79 @@ constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_si buffer_[63] = static_cast((total_bits >> 56) & 0xFF); md5_convert_buffer_to_blocks(); - md5_body(blocks_, a0_, b0_, c0_, d0_); + md5_body(); if (digest_size >= 4) { - digest[0] = swap_endian(a0_); - digest[1] = swap_endian(b0_); - digest[2] = swap_endian(c0_); - digest[3] = swap_endian(d0_); + digest[0] = detail::swap_endian(a0_); + digest[1] = detail::swap_endian(b0_); + digest[2] = detail::swap_endian(c0_); + digest[3] = detail::swap_endian(d0_); } } template -constexpr auto md5::process_byte(ByteType byte) noexcept +constexpr auto md5_hasher::process_byte(ByteType byte) noexcept BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t) { md5_update(&byte, 1UL); } template -constexpr auto md5::process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept +constexpr auto md5_hasher::process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept { md5_update(buffer, byte_count); } -template -auto md5_impl(ForwardIterator first, ForwardIterator last) -> ResultType +// TODO(mborland): Replace the loop with the known statements +constexpr auto md5_hasher::md5_body() noexcept -> void { - // Initial MD5 buffer values - boost::crypt::uint32_t a0 {0x67452301}; - boost::crypt::uint32_t b0 {0xefcdab89}; - boost::crypt::uint32_t c0 {0x98badcfe}; - boost::crypt::uint32_t d0 {0x10325476}; - - boost::crypt::array blocks {}; - - // Store the original 'first' to compute the total message length - const auto total_message_length {static_cast(last - first) * 8UL}; - - // Handles the empty case with known values - if (first == last) - { - return ResultType{0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e}; - } + boost::crypt::uint32_t A {a0_}; + boost::crypt::uint32_t B {b0_}; + boost::crypt::uint32_t C {c0_}; + boost::crypt::uint32_t D {d0_}; - while (first != last) + for (boost::crypt::uint32_t i {}; i < 64U; ++i) { - boost::crypt::size_t current_block = 0; + boost::crypt::uint32_t F {}; + boost::crypt::uint32_t g {}; - // Process as many full 64-byte blocks as possible - if (last - first >= 64) + if (i <= 15U) + { + F = (B & C) | ((~B) & D); + g = i; + } + else if (i <= 31U) { - for (auto& block : blocks) - { - block = static_cast( - static_cast(*first) + - (static_cast(*(first + 1U)) << 8U) + - (static_cast(*(first + 2U)) << 16U) + - (static_cast(*(first + 3U)) << 24U) - ); - - first += 4U; - } - md5_body(blocks, a0, b0, c0, d0); + F = (D & B) | ((~D) & C); + g = (5U * i + 1U) % 16U; + } + else if (i <= 47U) + { + F = B ^ C ^ D; + g = (3U * i + 5U) % 16U; } else { - // Process remaining bytes - // Initialize blocks to zero - blocks.fill(0); - - // Process complete 4-byte chunks - while (last - first >= 4) - { - blocks[current_block] = static_cast( - static_cast(*first) + - (static_cast(*(first + 1U)) << 8U) + - (static_cast(*(first + 2U)) << 16U) + - (static_cast(*(first + 3U)) << 24U) - ); - - first += 4U; - ++current_block; - } - - // Process remaining bytes (less than 4) - blocks[current_block] = 0; - auto byte_offset = 0U; - while (first != last) - { - blocks[current_block] |= static_cast(*first) << (8U * byte_offset); - ++first; - ++byte_offset; - } - - // Append the '1' bit (0x80) after the last byte - blocks[current_block] |= static_cast(0x80) << (8U * byte_offset); - ++current_block; - - // Check if there is enough space to append the length - if (current_block > 14U) - { - // Not enough space, process this block and start a new one - md5_body(blocks, a0, b0, c0, d0); - blocks.fill(0); - current_block = 0; - } - - // Pad with zeros until block[14] - while (current_block < 14U) - { - blocks[current_block] = 0; - ++current_block; - } - - // Append the 64-bit length in bits in little-endian format - blocks[14] = static_cast(total_message_length & 0xFFFFFFFF); - blocks[15] = static_cast((total_message_length >> 32) & 0xFFFFFFFF); - - // Process the final block - md5_body(blocks, a0, b0, c0, d0); - - // Break out of the loop as we've processed all data - break; + F = C ^ (B | (~D)); + g = (7U * i) % 16U; } + + BOOST_CRYPT_ASSERT(i <= 63U); + + F = F + A + detail::K[i] + blocks_[g]; + A = D; + D = C; + C = B; + B = B + detail::rotl(F, detail::S[i]); } - return ResultType {swap_endian(a0), - swap_endian(b0), - swap_endian(c0), - swap_endian(d0)}; + a0_ += A; + b0_ += B; + c0_ += C; + d0_ += D; } -} // namespace detail - template , typename T> ResultType md5(T begin, T end) { @@ -402,7 +294,12 @@ ResultType md5(T begin, T end) return ResultType{0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e}; } - return detail::md5_impl(begin, end); + boost::crypt::md5_hasher hasher; + hasher.process_bytes(begin, static_cast(end - begin)); + ResultType result; + hasher.get_digest(result.begin(), result.size()); + + return result; } template > @@ -414,20 +311,20 @@ ResultType md5(const char* str) } const auto message_len {std::strlen(str)}; - return detail::md5_impl(str, str + message_len); + return md5(str, str + message_len); } template > ResultType md5(const std::string& str) { - return md5(str.begin(), str.end()); + return md5(str.begin(), str.end()); } #ifdef BOOST_CRYPT_HAS_STRING_VIEW template > ResultType md5(const std::string_view& str) { - return md5(str.begin(), str.end()); + return md5(str.begin(), str.end()); } #endif diff --git a/test/test_md5.cpp b/test/test_md5.cpp index c0554269..870c1e44 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -85,7 +85,7 @@ void bad_input() void test_class() { - boost::crypt::detail::md5 hasher; + boost::crypt::md5_hasher hasher; for (const auto& test_value : test_values) { From a7bf2475950e6125f4e19e6e13b4eb0699972914 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 10:45:50 -0400 Subject: [PATCH 62/76] Add GPU markers --- include/boost/crypt/hash/md5.hpp | 42 ++++++++++++++------------ include/boost/crypt/utility/array.hpp | 38 +++++++++++------------ include/boost/crypt/utility/bit.hpp | 18 +++++------ include/boost/crypt/utility/strlen.hpp | 2 +- 4 files changed, 51 insertions(+), 49 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 39c9d04d..91deb090 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -68,30 +68,30 @@ class md5_hasher boost::crypt::array blocks_ {}; template - constexpr auto md5_update(ForwardIter data, boost::crypt::size_t size) noexcept; + BOOST_CRYPT_GPU_ENABLED constexpr auto md5_update(ForwardIter data, boost::crypt::size_t size) noexcept; - constexpr auto md5_convert_buffer_to_blocks() noexcept; + BOOST_CRYPT_GPU_ENABLED constexpr auto md5_convert_buffer_to_blocks() noexcept; template - constexpr auto md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept; + BOOST_CRYPT_GPU_ENABLED constexpr auto md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept; - constexpr auto md5_body() noexcept -> void; + BOOST_CRYPT_GPU_ENABLED constexpr auto md5_body() noexcept -> void; public: - constexpr auto init() noexcept -> void; + BOOST_CRYPT_GPU_ENABLED constexpr auto init() noexcept -> void; template - constexpr auto process_byte(ByteType byte) noexcept + BOOST_CRYPT_GPU_ENABLED constexpr auto process_byte(ByteType byte) noexcept BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t); template - constexpr auto process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept; + BOOST_CRYPT_GPU_ENABLED constexpr auto process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept; template - constexpr auto get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept; + BOOST_CRYPT_GPU_ENABLED constexpr auto get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept; }; -constexpr auto md5_hasher::init() noexcept -> void +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::init() noexcept -> void { a0_ = 0x67452301U; b0_ = 0xefcdab89U; @@ -105,7 +105,7 @@ constexpr auto md5_hasher::init() noexcept -> void blocks_.fill(0U); } -constexpr auto md5_hasher::md5_convert_buffer_to_blocks() noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_convert_buffer_to_blocks() noexcept { boost::crypt::size_t buffer_index {}; for (auto& block : blocks_) @@ -122,7 +122,7 @@ constexpr auto md5_hasher::md5_convert_buffer_to_blocks() noexcept } template -constexpr auto md5_hasher::md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept { for (boost::crypt::size_t i {}; i < size; ++i) { @@ -132,7 +132,7 @@ constexpr auto md5_hasher::md5_copy_data(ForwardIter data, boost::crypt::size_t } template -constexpr auto md5_hasher::md5_update(ForwardIter data, boost::crypt::size_t size) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_update(ForwardIter data, boost::crypt::size_t size) noexcept { const auto input_bits {size << 3U}; // Convert size to bits const auto old_low {low_}; @@ -177,7 +177,7 @@ constexpr auto md5_hasher::md5_update(ForwardIter data, boost::crypt::size_t siz } template -constexpr auto md5_hasher::get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept { auto used {(low_ >> 3U) & 0x3F}; // Number of bytes used in buffer buffer_[used++] = 0x80; @@ -221,20 +221,20 @@ constexpr auto md5_hasher::get_digest(DigestType digest, boost::crypt::size_t di } template -constexpr auto md5_hasher::process_byte(ByteType byte) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::process_byte(ByteType byte) noexcept BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t) { md5_update(&byte, 1UL); } template -constexpr auto md5_hasher::process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept { md5_update(buffer, byte_count); } // TODO(mborland): Replace the loop with the known statements -constexpr auto md5_hasher::md5_body() noexcept -> void +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_body() noexcept -> void { boost::crypt::uint32_t A {a0_}; boost::crypt::uint32_t B {b0_}; @@ -283,7 +283,7 @@ constexpr auto md5_hasher::md5_body() noexcept -> void } template , typename T> -ResultType md5(T begin, T end) +BOOST_CRYPT_GPU_ENABLED constexpr ResultType md5(T begin, T end) noexcept { if (end < begin) { @@ -303,7 +303,7 @@ ResultType md5(T begin, T end) } template > -ResultType md5(const char* str) +BOOST_CRYPT_GPU_ENABLED ResultType md5(const char* str) noexcept { if (str == nullptr) { @@ -314,15 +314,17 @@ ResultType md5(const char* str) return md5(str, str + message_len); } +// ----- String and String view aren't in the libcu++ STL so they so not have device markers ----- + template > -ResultType md5(const std::string& str) +constexpr ResultType md5(const std::string& str) noexcept { return md5(str.begin(), str.end()); } #ifdef BOOST_CRYPT_HAS_STRING_VIEW template > -ResultType md5(const std::string_view& str) +constexpr ResultType md5(const std::string_view& str) { return md5(str.begin(), str.end()); } diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp index a70107d6..1a41c680 100644 --- a/include/boost/crypt/utility/array.hpp +++ b/include/boost/crypt/utility/array.hpp @@ -30,30 +30,30 @@ class array T elements[N]; // Iterators - constexpr auto begin() noexcept -> iterator { return elements; } - constexpr auto cbegin() const noexcept -> const_iterator { return elements; } - constexpr auto end() noexcept -> iterator { return elements + N; } - constexpr auto cend() const noexcept -> const_iterator { return elements + N; } + BOOST_CRYPT_GPU_ENABLED constexpr auto begin() noexcept -> iterator { return elements; } + BOOST_CRYPT_GPU_ENABLED constexpr auto cbegin() const noexcept -> const_iterator { return elements; } + BOOST_CRYPT_GPU_ENABLED constexpr auto end() noexcept -> iterator { return elements + N; } + BOOST_CRYPT_GPU_ENABLED constexpr auto cend() const noexcept -> const_iterator { return elements + N; } // Sizing - constexpr auto size() noexcept -> size_type { return N; } - constexpr auto max_size() noexcept -> size_type { return N; } + BOOST_CRYPT_GPU_ENABLED constexpr auto size() noexcept -> size_type { return N; } + BOOST_CRYPT_GPU_ENABLED constexpr auto max_size() noexcept -> size_type { return N; } // Accessors - constexpr auto operator[](size_type n) noexcept -> reference + BOOST_CRYPT_GPU_ENABLED constexpr auto operator[](size_type n) noexcept -> reference { BOOST_CRYPT_ASSERT(n < N); return elements[n]; } - constexpr auto operator[](size_type n) const noexcept -> const_reference + BOOST_CRYPT_GPU_ENABLED constexpr auto operator[](size_type n) const noexcept -> const_reference { BOOST_CRYPT_ASSERT(n < N); return elements[n]; } // For at instead of throwing on out of range return the last element since throwing doesn't work on device - constexpr auto at(size_type n) noexcept -> reference + BOOST_CRYPT_GPU_ENABLED constexpr auto at(size_type n) noexcept -> reference { if (n >= N) { @@ -62,7 +62,7 @@ class array return elements[n]; } - constexpr auto at(size_type n) const noexcept -> const_reference + BOOST_CRYPT_GPU_ENABLED constexpr auto at(size_type n) const noexcept -> const_reference { if (n >= N) { @@ -72,16 +72,16 @@ class array } // Front and back - constexpr auto front() noexcept -> reference { return elements[0]; } - constexpr auto front() const noexcept -> const_reference { return elements[0]; } - constexpr auto back() noexcept -> reference { return elements[N - 1]; } - constexpr auto back() const noexcept -> const_reference { return elements[N - 1]; } + BOOST_CRYPT_GPU_ENABLED constexpr auto front() noexcept -> reference { return elements[0]; } + BOOST_CRYPT_GPU_ENABLED constexpr auto front() const noexcept -> const_reference { return elements[0]; } + BOOST_CRYPT_GPU_ENABLED constexpr auto back() noexcept -> reference { return elements[N - 1]; } + BOOST_CRYPT_GPU_ENABLED constexpr auto back() const noexcept -> const_reference { return elements[N - 1]; } - constexpr auto data() noexcept -> pointer { return elements; } - constexpr auto data() const noexcept -> const_pointer { return elements; } + BOOST_CRYPT_GPU_ENABLED constexpr auto data() noexcept -> pointer { return elements; } + BOOST_CRYPT_GPU_ENABLED constexpr auto data() const noexcept -> const_pointer { return elements; } // Fill and swap - constexpr auto fill(const value_type& v) -> void + BOOST_CRYPT_GPU_ENABLED constexpr auto fill(const value_type& v) -> void { for (size_type i {}; i < N; ++i) { @@ -89,7 +89,7 @@ class array } } - constexpr auto swap(array& a) + BOOST_CRYPT_GPU_ENABLED constexpr auto swap(array& a) { const auto temp {a}; a = *this; @@ -98,7 +98,7 @@ class array }; template -constexpr auto fill_array(ForwardIter first, ForwardIter last, T value) +BOOST_CRYPT_GPU_ENABLED constexpr auto fill_array(ForwardIter first, ForwardIter last, T value) { while (first != last) { diff --git a/include/boost/crypt/utility/bit.hpp b/include/boost/crypt/utility/bit.hpp index 55b2ec4c..b0d679f7 100644 --- a/include/boost/crypt/utility/bit.hpp +++ b/include/boost/crypt/utility/bit.hpp @@ -16,18 +16,18 @@ namespace detail { // Forward decls template ::value, bool> = true> -constexpr T rotl(T x, U s) noexcept; +BOOST_CRYPT_GPU_ENABLED constexpr T rotl(T x, U s) noexcept; template ::value, bool> = true> -constexpr T rotl(T x, U s) noexcept; +BOOST_CRYPT_GPU_ENABLED constexpr T rotl(T x, U s) noexcept; template ::value, bool> = true> -constexpr T rotr(T x, U s) noexcept; +BOOST_CRYPT_GPU_ENABLED constexpr T rotr(T x, U s) noexcept; template ::value, bool> = true> -constexpr T rotr(T x, U s) noexcept; +BOOST_CRYPT_GPU_ENABLED constexpr T rotr(T x, U s) noexcept; // Only works for unsigned s so we can optimize away the call to rotr template ::value, bool>> -constexpr T rotl(T x, U s) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr T rotl(T x, U s) noexcept { constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; @@ -41,7 +41,7 @@ constexpr T rotl(T x, U s) noexcept } template ::value, bool>> -constexpr T rotl(T x, U s) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr T rotl(T x, U s) noexcept { constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; @@ -59,7 +59,7 @@ constexpr T rotl(T x, U s) noexcept } template ::value, bool>> -constexpr T rotr(T x, U s) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr T rotr(T x, U s) noexcept { constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; @@ -73,7 +73,7 @@ constexpr T rotr(T x, U s) noexcept } template ::value, bool>> -constexpr T rotr(T x, U s) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr T rotr(T x, U s) noexcept { constexpr auto N {boost::crypt::numeric_limits::digits}; const auto r {s % N}; @@ -90,7 +90,7 @@ constexpr T rotr(T x, U s) noexcept return (x >> r) | (x << (N - r)); } -constexpr auto swap_endian(const boost::crypt::uint32_t val) -> boost::crypt::uint32_t +BOOST_CRYPT_GPU_ENABLED constexpr auto swap_endian(const boost::crypt::uint32_t val) -> boost::crypt::uint32_t { return ((val & 0xFF000000) >> 24U) | ((val & 0x00FF0000) >> 8U) | diff --git a/include/boost/crypt/utility/strlen.hpp b/include/boost/crypt/utility/strlen.hpp index e81acd47..6f6e3856 100644 --- a/include/boost/crypt/utility/strlen.hpp +++ b/include/boost/crypt/utility/strlen.hpp @@ -12,7 +12,7 @@ namespace crypt { namespace utility { template -constexpr auto strlen(ForwardIter str) noexcept -> boost::crypt::size_t +BOOST_CRYPT_GPU_ENABLED constexpr auto strlen(ForwardIter str) noexcept -> boost::crypt::size_t { boost::crypt::size_t len {}; while (*(str + len) != static_cast('\0')) From 5887c9376ee7681c05f0a67a2739a9f920413b70 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 14:04:24 -0400 Subject: [PATCH 63/76] Switch test over to 8 bits instead of 32 --- test/test_md5.cpp | 73 ++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 870c1e44..838eee38 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -11,17 +11,26 @@ #include #include -constexpr std::array, 9> test_values = +constexpr std::array>, 9> test_values = { - std::make_tuple("The quick brown fox jumps over the lazy dog", 0x9e107d9d, 0x372bb682, 0x6bd81d35, 0x42a419d6), - std::make_tuple("The quick brown fox jumps over the lazy dog.", 0xe4d909c2, 0x90d0fb1c, 0xa068ffad, 0xdf22cbd0), - std::make_tuple("", 0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e), - std::make_tuple("ddcc8542894a27456bbeb43f51f38764c32f72ae", 0x3b340f00, 0x97312ec8, 0x2fa4da0d, 0x7da53002), - std::make_tuple("webmin1980", 0xb78aae35, 0x6709f8c3, 0x1118ea61, 0x3980954b), - std::make_tuple("$2y$10$EQAmcJw0cg.rt.6..SJ2bulFhDo0eWtuMhkfDMPGsNdap4xrOY61K", 0x40bbe664, 0x4efd9354, 0x078d8c70, 0xfb6c9f42), - std::make_tuple("pkirsanov", 0x8793ce04, 0xf0c5f1e8, 0xed1e0c78, 0xf249fe1b), - std::make_tuple("Eleanor", 0xd37e4317, 0x4905de70, 0xfbb5b038, 0xd7247f57), - std::make_tuple("The Whirlpool Galaxy is about 88% the size of the Milky Way, with a diameter of 76,900 light-years", 0xd5dfd7b4, 0x1235abc7, 0xa9a3205b, 0x6896f34d), + std::make_tuple("The quick brown fox jumps over the lazy dog", + std::array{0x9e, 0x10, 0x7d, 0x9d, 0x37, 0x2b, 0xb6, 0x82, 0x6b, 0xd8, 0x1d, 0x35, 0x42, 0xa4, 0x19, 0xd6}), + std::make_tuple("The quick brown fox jumps over the lazy dog.", + std::array{0xe4, 0xd9, 0x09, 0xc2, 0x90, 0xd0, 0xfb, 0x1c, 0xa0, 0x68, 0xff, 0xad, 0xdf, 0x22, 0xcb, 0xd0}), + std::make_tuple("", + std::array{0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e}), + std::make_tuple("ddcc8542894a27456bbeb43f51f38764c32f72ae", + std::array{0x3b, 0x34, 0x0f, 0x00, 0x97, 0x31, 0x2e, 0xc8, 0x2f, 0xa4, 0xda, 0x0d, 0x7d, 0xa5, 0x30, 0x02}), + std::make_tuple("webmin1980", + std::array{0xb7, 0x8a, 0xae, 0x35, 0x67, 0x09, 0xf8, 0xc3, 0x11, 0x18, 0xea, 0x61, 0x39, 0x80, 0x95, 0x4b}), + std::make_tuple("$2y$10$EQAmcJw0cg.rt.6..SJ2bulFhDo0eWtuMhkfDMPGsNdap4xrOY61K", + std::array{0x40, 0xbb, 0xe6, 0x64, 0x4e, 0xfd, 0x93, 0x54, 0x07, 0x8d, 0x8c, 0x70, 0xfb, 0x6c, 0x9f, 0x42}), + std::make_tuple("pkirsanov", + std::array{0x87, 0x93, 0xce, 0x04, 0xf0, 0xc5, 0xf1, 0xe8, 0xed, 0x1e, 0x0c, 0x78, 0xf2, 0x49, 0xfe, 0x1b}), + std::make_tuple("Eleanor", + std::array{0xd3, 0x7e, 0x43, 0x17, 0x49, 0x05, 0xde, 0x70, 0xfb, 0xb5, 0xb0, 0x38, 0xd7, 0x24, 0x7f, 0x57}), + std::make_tuple("The Whirlpool Galaxy is about 88% the size of the Milky Way, with a diameter of 76,900 light-years", + std::array{0xd5, 0xdf, 0xd7, 0xb4, 0x12, 0x35, 0xab, 0xc7, 0xa9, 0xa3, 0x20, 0x5b, 0x68, 0x96, 0xf3, 0x4d}), }; void basic_tests() @@ -29,12 +38,13 @@ void basic_tests() for (const auto& test_value : test_values) { const auto message_result {boost::crypt::md5(std::get<0>(test_value))}; - if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + const auto valid_result {std::get<1>(test_value)}; + for (std::size_t i {}; i < message_result.size(); ++i) { - std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) + { + std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + } } } } @@ -45,12 +55,13 @@ void string_test() { const std::string string_message {std::get<0>(test_value)}; const auto message_result {boost::crypt::md5(string_message)}; - if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + const auto valid_result {std::get<1>(test_value)}; + for (std::size_t i {}; i < message_result.size(); ++i) { - std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) + { + std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + } } } } @@ -63,12 +74,13 @@ void string_view_test() const std::string string_message {std::get<0>(test_value)}; const std::string_view string_view_message {string_message}; const auto message_result {boost::crypt::md5(string_view_message)}; - if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + const auto valid_result {std::get<1>(test_value)}; + for (std::size_t i {}; i < message_result.size(); ++i) { - std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) + { + std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + } } } #endif @@ -94,12 +106,13 @@ void test_class() std::array message_result {}; hasher.get_digest(message_result.begin(), message_result.size()); - if (!(BOOST_TEST_EQ(message_result[0], std::get<1>(test_value)) && - BOOST_TEST_EQ(message_result[1], std::get<2>(test_value)) && - BOOST_TEST_EQ(message_result[2], std::get<3>(test_value)) && - BOOST_TEST_EQ(message_result[3], std::get<4>(test_value)))) + const auto valid_result {std::get<1>(test_value)}; + for (std::size_t i {}; i < message_result.size(); ++i) { - std::cerr << "Failure with message: " << std::get<0>(test_value) << '\n'; + if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) + { + std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + } } hasher.init(); From 019f2c543252447fbd661c431753010962119216 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 14:04:37 -0400 Subject: [PATCH 64/76] Add more const markers --- include/boost/crypt/utility/array.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt/utility/array.hpp b/include/boost/crypt/utility/array.hpp index 1a41c680..302aefa1 100644 --- a/include/boost/crypt/utility/array.hpp +++ b/include/boost/crypt/utility/array.hpp @@ -31,13 +31,15 @@ class array // Iterators BOOST_CRYPT_GPU_ENABLED constexpr auto begin() noexcept -> iterator { return elements; } + BOOST_CRYPT_GPU_ENABLED constexpr auto begin() const noexcept -> iterator { return elements; } BOOST_CRYPT_GPU_ENABLED constexpr auto cbegin() const noexcept -> const_iterator { return elements; } BOOST_CRYPT_GPU_ENABLED constexpr auto end() noexcept -> iterator { return elements + N; } + BOOST_CRYPT_GPU_ENABLED constexpr auto end() const noexcept -> iterator { return elements + N; } BOOST_CRYPT_GPU_ENABLED constexpr auto cend() const noexcept -> const_iterator { return elements + N; } // Sizing - BOOST_CRYPT_GPU_ENABLED constexpr auto size() noexcept -> size_type { return N; } - BOOST_CRYPT_GPU_ENABLED constexpr auto max_size() noexcept -> size_type { return N; } + BOOST_CRYPT_GPU_ENABLED constexpr auto size() const noexcept -> size_type { return N; } + BOOST_CRYPT_GPU_ENABLED constexpr auto max_size() const noexcept -> size_type { return N; } // Accessors BOOST_CRYPT_GPU_ENABLED constexpr auto operator[](size_type n) noexcept -> reference From f777ff60bd1ee83e12a6cf41c89d3dbd172563d0 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 14:16:51 -0400 Subject: [PATCH 65/76] Always return an array of bytes --- include/boost/crypt/hash/md5.hpp | 50 +++++++++++++++----------------- test/test_md5.cpp | 7 +++-- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 91deb090..edf3e8c6 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -87,8 +87,7 @@ class md5_hasher template BOOST_CRYPT_GPU_ENABLED constexpr auto process_bytes(ForwardIter buffer, boost::crypt::size_t byte_count) noexcept; - template - BOOST_CRYPT_GPU_ENABLED constexpr auto get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept; + BOOST_CRYPT_GPU_ENABLED constexpr auto get_digest() noexcept -> boost::crypt::array; }; BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::init() noexcept -> void @@ -176,9 +175,9 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_update(ForwardIter data, } } -template -BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::get_digest() noexcept -> boost::crypt::array { + boost::crypt::array digest {}; auto used {(low_ >> 3U) & 0x3F}; // Number of bytes used in buffer buffer_[used++] = 0x80; auto available {buffer_.size() - used}; @@ -196,7 +195,7 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::get_digest(DigestType digest, fill_array(buffer_.begin() + used, buffer_.end() - 8, static_cast(0)); } - uint64_t total_bits = (static_cast(high_) << 32) | low_; + const auto total_bits {(static_cast(high_) << 32) | low_}; // Append the length in bits as a 64-bit little-endian integer buffer_[56] = static_cast(total_bits & 0xFF); @@ -211,13 +210,16 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::get_digest(DigestType digest, md5_convert_buffer_to_blocks(); md5_body(); - if (digest_size >= 4) + for (boost::crypt::size_t i = 0; i < 4; ++i) { - digest[0] = detail::swap_endian(a0_); - digest[1] = detail::swap_endian(b0_); - digest[2] = detail::swap_endian(c0_); - digest[3] = detail::swap_endian(d0_); + const auto value {(i == 0 ? a0_ : (i == 1 ? b0_ : (i == 2 ? c0_ : d0_)))}; + digest[i*4] = static_cast(value & 0xFF); + digest[i*4 + 1] = static_cast((value >> 8U) & 0xFF); + digest[i*4 + 2] = static_cast((value >> 16U) & 0xFF); + digest[i*4 + 3] = static_cast((value >> 24U) & 0xFF); } + + return digest; } template @@ -282,51 +284,47 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_body() noexcept -> void d0_ += D; } -template , typename T> -BOOST_CRYPT_GPU_ENABLED constexpr ResultType md5(T begin, T end) noexcept +template +BOOST_CRYPT_GPU_ENABLED constexpr auto md5(T begin, T end) noexcept -> boost::crypt::array { if (end < begin) { - return ResultType {0, 0, 0, 0}; + return boost::crypt::array {}; } else if (end == begin) { - return ResultType{0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e}; + return boost::crypt::array{0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e}; } boost::crypt::md5_hasher hasher; hasher.process_bytes(begin, static_cast(end - begin)); - ResultType result; - hasher.get_digest(result.begin(), result.size()); + auto result {hasher.get_digest()}; return result; } -template > -BOOST_CRYPT_GPU_ENABLED ResultType md5(const char* str) noexcept +BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str) noexcept -> boost::crypt::array { if (str == nullptr) { - return ResultType {0, 0, 0, 0}; + return boost::crypt::array{}; } const auto message_len {std::strlen(str)}; - return md5(str, str + message_len); + return md5(str, str + message_len); } // ----- String and String view aren't in the libcu++ STL so they so not have device markers ----- -template > -constexpr ResultType md5(const std::string& str) noexcept +inline auto md5(const std::string& str) noexcept -> boost::crypt::array { - return md5(str.begin(), str.end()); + return md5(str.begin(), str.end()); } #ifdef BOOST_CRYPT_HAS_STRING_VIEW -template > -constexpr ResultType md5(const std::string_view& str) +inline auto md5(const std::string_view& str) -> boost::crypt::array { - return md5(str.begin(), str.end()); + return md5(str.begin(), str.end()); } #endif diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 838eee38..365375bf 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -44,6 +44,7 @@ void basic_tests() if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + break; } } } @@ -61,6 +62,7 @@ void string_test() if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + break; } } } @@ -80,6 +82,7 @@ void string_view_test() if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + break; } } } @@ -103,8 +106,7 @@ void test_class() { const auto msg {std::get<0>(test_value)}; hasher.process_bytes(msg, std::strlen(msg)); - std::array message_result {}; - hasher.get_digest(message_result.begin(), message_result.size()); + const auto message_result {hasher.get_digest()}; const auto valid_result {std::get<1>(test_value)}; for (std::size_t i {}; i < message_result.size(); ++i) @@ -112,6 +114,7 @@ void test_class() if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; + break; } } From 5269ece9ab13bb5aaa327e42167348f9518a8aeb Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 16:45:00 -0400 Subject: [PATCH 66/76] Unroll the hash loop --- include/boost/crypt/hash/md5.hpp | 204 ++++++++++++++++++++----------- 1 file changed, 133 insertions(+), 71 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index edf3e8c6..a8f3099e 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -23,36 +23,6 @@ namespace boost { namespace crypt { -namespace detail { - -static constexpr boost::crypt::array S { - 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 -}; - -static constexpr boost::crypt::array K { - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 -}; - -} // namespace detail - class md5_hasher { private: @@ -235,53 +205,145 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::process_bytes(ForwardIter buf md5_update(buffer, byte_count); } -// TODO(mborland): Replace the loop with the known statements -BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_body() noexcept -> void +// See: Applied Cryptography - Bruce Schneier +// Section 18.5 +namespace md5_body_detail { + +BOOST_CRYPT_GPU_ENABLED constexpr auto F(boost::crypt::uint32_t x, boost::crypt::uint32_t y, boost::crypt::uint32_t z) noexcept { - boost::crypt::uint32_t A {a0_}; - boost::crypt::uint32_t B {b0_}; - boost::crypt::uint32_t C {c0_}; - boost::crypt::uint32_t D {d0_}; + return (x & y) | ((~x) & z); +} - for (boost::crypt::uint32_t i {}; i < 64U; ++i) - { - boost::crypt::uint32_t F {}; - boost::crypt::uint32_t g {}; +BOOST_CRYPT_GPU_ENABLED constexpr auto G(boost::crypt::uint32_t x, boost::crypt::uint32_t y, boost::crypt::uint32_t z) noexcept +{ + return (x & z) | (y & (~z)); +} - if (i <= 15U) - { - F = (B & C) | ((~B) & D); - g = i; - } - else if (i <= 31U) - { - F = (D & B) | ((~D) & C); - g = (5U * i + 1U) % 16U; - } - else if (i <= 47U) - { - F = B ^ C ^ D; - g = (3U * i + 5U) % 16U; - } - else - { - F = C ^ (B | (~D)); - g = (7U * i) % 16U; - } +BOOST_CRYPT_GPU_ENABLED constexpr auto H(boost::crypt::uint32_t x, boost::crypt::uint32_t y, boost::crypt::uint32_t z) noexcept +{ + return x ^ y ^ z; +} - BOOST_CRYPT_ASSERT(i <= 63U); +BOOST_CRYPT_GPU_ENABLED constexpr auto I(boost::crypt::uint32_t x, boost::crypt::uint32_t y, boost::crypt::uint32_t z) noexcept +{ + return y ^ (x | (~z)); +} - F = F + A + detail::K[i] + blocks_[g]; - A = D; - D = C; - C = B; - B = B + detail::rotl(F, detail::S[i]); - } +BOOST_CRYPT_GPU_ENABLED constexpr auto FF(boost::crypt::uint32_t& a, boost::crypt::uint32_t b, boost::crypt::uint32_t c, + boost::crypt::uint32_t d, boost::crypt::uint32_t Mj, boost::crypt::uint32_t si, + boost::crypt::uint32_t ti) noexcept +{ + a = b + detail::rotl((a + F(b, c, d) + Mj + ti), si); +} + +BOOST_CRYPT_GPU_ENABLED constexpr auto GG(boost::crypt::uint32_t& a, boost::crypt::uint32_t b, boost::crypt::uint32_t c, + boost::crypt::uint32_t d, boost::crypt::uint32_t Mj, boost::crypt::uint32_t si, + boost::crypt::uint32_t ti) noexcept +{ + a = b + detail::rotl((a + G(b, c, d) + Mj + ti), si); +} - a0_ += A; - b0_ += B; - c0_ += C; - d0_ += D; +BOOST_CRYPT_GPU_ENABLED constexpr auto HH(boost::crypt::uint32_t& a, boost::crypt::uint32_t b, boost::crypt::uint32_t c, + boost::crypt::uint32_t d, boost::crypt::uint32_t Mj, boost::crypt::uint32_t si, + boost::crypt::uint32_t ti) noexcept +{ + a = b + detail::rotl((a + H(b, c, d) + Mj + ti), si); +} + +BOOST_CRYPT_GPU_ENABLED constexpr auto II(boost::crypt::uint32_t& a, boost::crypt::uint32_t b, boost::crypt::uint32_t c, + boost::crypt::uint32_t d, boost::crypt::uint32_t Mj, boost::crypt::uint32_t si, + boost::crypt::uint32_t ti) noexcept +{ + a = b + detail::rotl((a + I(b, c, d) + Mj + ti), si); +} + +} // md5_body_detail + +BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_body() noexcept -> void +{ + using namespace md5_body_detail; + + boost::crypt::uint32_t a {a0_}; + boost::crypt::uint32_t b {b0_}; + boost::crypt::uint32_t c {c0_}; + boost::crypt::uint32_t d {d0_}; + + // Round 1 + FF(a, b, c, d, blocks_[0], 7, 0xd76aa478); + FF(d, a, b, c, blocks_[1], 12, 0xe8c7b756); + FF(c, d, a, b, blocks_[2], 17, 0x242070db); + FF(b, c, d, a, blocks_[3], 22, 0xc1bdceee); + FF(a, b, c, d, blocks_[4], 7, 0xf57c0faf); + FF(d, a, b, c, blocks_[5], 12, 0x4787c62a); + FF(c, d, a, b, blocks_[6], 17, 0xa8304613); + FF(b, c, d, a, blocks_[7], 22, 0xfd469501); + FF(a, b, c, d, blocks_[8], 7, 0x698098d8); + FF(d, a, b, c, blocks_[9], 12, 0x8b44f7af); + FF(c, d, a, b, blocks_[10], 17, 0xffff5bb1); + FF(b, c, d, a, blocks_[11], 22, 0x895cd7be); + FF(a, b, c, d, blocks_[12], 7, 0x6b901122); + FF(d, a, b, c, blocks_[13], 12, 0xfd987193); + FF(c, d, a, b, blocks_[14], 17, 0xa679438e); + FF(b, c, d, a, blocks_[15], 22, 0x49b40821); + + // Round 2 + GG(a, b, c, d, blocks_[1], 5, 0xf61e2562); + GG(d, a, b, c, blocks_[6], 9, 0xc040b340); + GG(c, d, a, b, blocks_[11], 14, 0x265e5a51); + GG(b, c, d, a, blocks_[0], 20, 0xe9b6c7aa); + GG(a, b, c, d, blocks_[5], 5, 0xd62f105d); + GG(d, a, b, c, blocks_[10], 9, 0x02441453); + GG(c, d, a, b, blocks_[15], 14, 0xd8a1e681); + GG(b, c, d, a, blocks_[4], 20, 0xe7d3fbc8); + GG(a, b, c, d, blocks_[9], 5, 0x21e1cde6); + GG(d, a, b, c, blocks_[14], 9, 0xc33707d6); + GG(c, d, a, b, blocks_[3], 14, 0xf4d50d87); + GG(b, c, d, a, blocks_[8], 20, 0x455a14ed); + GG(a, b, c, d, blocks_[13], 5, 0xa9e3e905); + GG(d, a, b, c, blocks_[2], 9, 0xfcefa3f8); + GG(c, d, a, b, blocks_[7], 14, 0x676f02d9); + GG(b, c, d, a, blocks_[12], 20, 0x8d2a4c8a); + + // Round 3 + HH(a, b, c, d, blocks_[5], 4, 0xfffa3942); + HH(d, a, b, c, blocks_[8], 11, 0x8771f681); + HH(c, d, a, b, blocks_[11], 16, 0x6d9d6122); + HH(b, c, d, a, blocks_[14], 23, 0xfde5380c); + HH(a, b, c, d, blocks_[1], 4, 0xa4beea44); + HH(d, a, b, c, blocks_[4], 11, 0x4bdecfa9); + HH(c, d, a, b, blocks_[7], 16, 0xf6bb4b60); + HH(b, c, d, a, blocks_[10], 23, 0xbebfbc70); + HH(a, b, c, d, blocks_[13], 4, 0x289b7ec6); + HH(d, a, b, c, blocks_[0], 11, 0xeaa127fa); + HH(c, d, a, b, blocks_[3], 16, 0xd4ef3085); + HH(b, c, d, a, blocks_[6], 23, 0x04881d05); + HH(a, b, c, d, blocks_[9], 4, 0xd9d4d039); + HH(d, a, b, c, blocks_[12], 11, 0xe6db99e5); + HH(c, d, a, b, blocks_[15], 16, 0x1fa27cf8); + HH(b, c, d, a, blocks_[2], 23, 0xc4ac5665); + + // Round 4 + II(a, b, c, d, blocks_[0], 6, 0xf4292244); + II(d, a, b, c, blocks_[7], 10, 0x432aff97); + II(c, d, a, b, blocks_[14], 15, 0xab9423a7); + II(b, c, d, a, blocks_[5], 21, 0xfc93a039); + II(a, b, c, d, blocks_[12], 6, 0x655b59c3); + II(d, a, b, c, blocks_[3], 10, 0x8f0ccc92); + II(c, d, a, b, blocks_[10], 15, 0xffeff47d); + II(b, c, d, a, blocks_[1], 21, 0x85845dd1); + II(a, b, c, d, blocks_[8], 6, 0x6fa87e4f); + II(d, a, b, c, blocks_[15], 10, 0xfe2ce6e0); + II(c, d, a, b, blocks_[6], 15, 0xa3014314); + II(b, c, d, a, blocks_[13], 21, 0x4e0811a1); + II(a, b, c, d, blocks_[4], 6, 0xf7537e82); + II(d, a, b, c, blocks_[11], 10, 0xbd3af235); + II(c, d, a, b, blocks_[2], 15, 0x2ad7d2bb); + II(b, c, d, a, blocks_[9], 21, 0xeb86d391); + + a0_ += a; + b0_ += b; + c0_ += c; + d0_ += d; } template From 241961a680c64044266d59d39996fe484f5def60 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 16:50:38 -0400 Subject: [PATCH 67/76] Add pointer + len interface --- include/boost/crypt/hash/md5.hpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index a8f3099e..680722a0 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -372,10 +372,20 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str) noexcept -> boost::c return boost::crypt::array{}; } - const auto message_len {std::strlen(str)}; + const auto message_len {utility::strlen(str)}; return md5(str, str + message_len); } +BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str, boost::crypt::size_t len) noexcept -> boost::crypt::array +{ + if (str == nullptr) + { + return boost::crypt::array{}; + } + + return md5(str, str + len); +} + // ----- String and String view aren't in the libcu++ STL so they so not have device markers ----- inline auto md5(const std::string& str) noexcept -> boost::crypt::array From ebc10a32e8f2a63f58f341f008faac5b7049f2d4 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 16:51:08 -0400 Subject: [PATCH 68/76] Adding fuzzing to additional interfaces --- fuzzing/fuzz_md5.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fuzzing/fuzz_md5.cpp b/fuzzing/fuzz_md5.cpp index ee708888..a2044272 100644 --- a/fuzzing/fuzz_md5.cpp +++ b/fuzzing/fuzz_md5.cpp @@ -15,6 +15,12 @@ extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size std::string c_data_str {c_data, size}; // Guarantee null termination since we can't pass the size argument boost::crypt::md5(c_data_str); + boost::crypt::md5(c_data, size); + + #ifdef BOOST_CRYPT_HAS_STRING_VIEW + std::string_view view {c_data_str}; + boost::crypt::md5(view); + #endif } catch(...) { From dd7e9ae45d0ae4d62a87b7bd754ad32d437070ef Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 11 Oct 2024 16:59:30 -0400 Subject: [PATCH 69/76] Move template pair into detail namespace so we can do u16, u32, etc --- include/boost/crypt/hash/md5.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 680722a0..d290a1f9 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -346,6 +346,8 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5_hasher::md5_body() noexcept -> void d0_ += d; } +namespace detail { + template BOOST_CRYPT_GPU_ENABLED constexpr auto md5(T begin, T end) noexcept -> boost::crypt::array { @@ -355,7 +357,9 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(T begin, T end) noexcept -> boost::cr } else if (end == begin) { - return boost::crypt::array{0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e}; + return boost::crypt::array { + 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e + }; } boost::crypt::md5_hasher hasher; @@ -365,6 +369,8 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(T begin, T end) noexcept -> boost::cr return result; } +} // Namespace detail + BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str) noexcept -> boost::crypt::array { if (str == nullptr) @@ -373,7 +379,7 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str) noexcept -> boost::c } const auto message_len {utility::strlen(str)}; - return md5(str, str + message_len); + return detail::md5(str, str + message_len); } BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str, boost::crypt::size_t len) noexcept -> boost::crypt::array @@ -383,20 +389,20 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str, boost::crypt::size_t return boost::crypt::array{}; } - return md5(str, str + len); + return detail::md5(str, str + len); } // ----- String and String view aren't in the libcu++ STL so they so not have device markers ----- inline auto md5(const std::string& str) noexcept -> boost::crypt::array { - return md5(str.begin(), str.end()); + return detail::md5(str.begin(), str.end()); } #ifdef BOOST_CRYPT_HAS_STRING_VIEW inline auto md5(const std::string_view& str) -> boost::crypt::array { - return md5(str.begin(), str.end()); + return detail::md5(str.begin(), str.end()); } #endif From efa66d0a3c468de643101ec0514f86a9ba9ffe60 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 15 Oct 2024 10:13:46 -0400 Subject: [PATCH 70/76] Add std::uint8_t* interface --- include/boost/crypt/hash/md5.hpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index d290a1f9..2fe3e9fd 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -392,6 +392,27 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str, boost::crypt::size_t return detail::md5(str, str + len); } +BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const boost::crypt::uint8_t* str) noexcept -> boost::crypt::array +{ + if (str == nullptr) + { + return boost::crypt::array{}; + } + + const auto message_len {utility::strlen(str)}; + return detail::md5(str, str + message_len); +} + +BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const boost::crypt::uint8_t* str, boost::crypt::size_t len) noexcept -> boost::crypt::array +{ + if (str == nullptr) + { + return boost::crypt::array{}; + } + + return detail::md5(str, str + len); +} + // ----- String and String view aren't in the libcu++ STL so they so not have device markers ----- inline auto md5(const std::string& str) noexcept -> boost::crypt::array From 6a300ae13810a996313738fea4eb316e53871540 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 15 Oct 2024 10:13:55 -0400 Subject: [PATCH 71/76] Fuzz and test additional interface --- fuzzing/fuzz_md5.cpp | 1 + test/test_md5.cpp | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fuzzing/fuzz_md5.cpp b/fuzzing/fuzz_md5.cpp index a2044272..584ccce4 100644 --- a/fuzzing/fuzz_md5.cpp +++ b/fuzzing/fuzz_md5.cpp @@ -16,6 +16,7 @@ extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size boost::crypt::md5(c_data_str); boost::crypt::md5(c_data, size); + boost::crypt::md5(data, size); #ifdef BOOST_CRYPT_HAS_STRING_VIEW std::string_view view {c_data_str}; diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 365375bf..c757e87e 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -91,11 +91,29 @@ void string_view_test() void bad_input() { - const auto null_message {boost::crypt::md5(nullptr)}; + const auto null_message {boost::crypt::md5(static_cast(nullptr))}; BOOST_TEST_EQ(null_message[0], 0x0); BOOST_TEST_EQ(null_message[1], 0x0); BOOST_TEST_EQ(null_message[2], 0x0); BOOST_TEST_EQ(null_message[3], 0x0); + + const auto null_message_len {boost::crypt::md5(static_cast(nullptr), 100)}; + BOOST_TEST_EQ(null_message_len[0], 0x0); + BOOST_TEST_EQ(null_message_len[1], 0x0); + BOOST_TEST_EQ(null_message_len[2], 0x0); + BOOST_TEST_EQ(null_message_len[3], 0x0); + + const auto unsigned_null_message {boost::crypt::md5(static_cast(nullptr))}; + BOOST_TEST_EQ(unsigned_null_message[0], 0x0); + BOOST_TEST_EQ(unsigned_null_message[1], 0x0); + BOOST_TEST_EQ(unsigned_null_message[2], 0x0); + BOOST_TEST_EQ(unsigned_null_message[3], 0x0); + + const auto unsigned_null_message_len {boost::crypt::md5(static_cast(nullptr), 100)}; + BOOST_TEST_EQ(unsigned_null_message_len[0], 0x0); + BOOST_TEST_EQ(unsigned_null_message_len[1], 0x0); + BOOST_TEST_EQ(unsigned_null_message_len[2], 0x0); + BOOST_TEST_EQ(unsigned_null_message_len[3], 0x0); } void test_class() From bb860641f114e56cf27e3e00f53e103d6caad730 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 15 Oct 2024 10:41:50 -0400 Subject: [PATCH 72/76] Add random values testing --- test/CMakeLists.txt | 2 +- test/Jamfile | 2 + test/test_md5.cpp | 102 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index eb310951..60767959 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,6 +7,6 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) if(HAVE_BOOST_TEST) - boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::crypt Boost::core) + boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::crypt Boost::core Boost::uuid) endif() diff --git a/test/Jamfile b/test/Jamfile index 201cf17f..37a5fd33 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -11,6 +11,8 @@ import testing ; project : requirements + /boost/uuid//boost_uuid + gcc:-Wall gcc:-Wextra diff --git a/test/test_md5.cpp b/test/test_md5.cpp index c757e87e..97c724b7 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -6,10 +6,71 @@ #include #include + +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wconversion" +# pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +#include + +#ifdef __clang__ +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + + +#include #include #include #include #include +#include +#include +#include + +void generate_random_cstring(char* str, std::size_t length) +{ + + const char charset[] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + + const std::size_t charset_size = sizeof(charset) - 1; + + std::mt19937_64 rng(42); + std::uniform_int_distribution dist(0, charset_size); + + for (std::size_t i = 0; i < length - 1; ++i) + { + int index = dist(rng); + str[i] = charset[index]; + } + + str[length - 1] = '\0'; +} + +auto get_boost_uuid_result(const char* str, size_t length) +{ + unsigned char digest[16]; + boost::uuids::detail::md5 hasher; + hasher.process_bytes(str, length); + hasher.get_digest(digest); + + std::array return_array {}; + for (std::size_t i {}; i < 16U; ++i) + { + return_array[i] = digest[i]; + } + + return return_array; +} constexpr std::array>, 9> test_values = { @@ -43,8 +104,10 @@ void basic_tests() { if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { + // LCOV_EXCL_START std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; break; + // LCOV_EXCL_STOP } } } @@ -61,8 +124,10 @@ void string_test() { if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { + // LCOV_EXCL_START std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; break; + // LCOV_EXCL_STOP } } } @@ -81,8 +146,10 @@ void string_view_test() { if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { + // LCOV_EXCL_START std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; break; + // LCOV_EXCL_STOP } } } @@ -131,8 +198,10 @@ void test_class() { if (!BOOST_TEST_EQ(message_result[i], valid_result[i])) { + // LCOV_EXCL_START std::cerr << "Failure with: " << std::get<0>(test_value) << '\n'; break; + // LCOV_EXCL_STOP } } @@ -140,6 +209,37 @@ void test_class() } } +void test_random_values() +{ + constexpr std::size_t max_str_len {65535U}; + std::mt19937_64 rng(42); + std::uniform_int_distribution str_len(1, max_str_len - 1); + + char* str {new char[max_str_len]}; + + for (std::size_t i {}; i < 1024; ++i) + { + std::memset(str, '\0', max_str_len); + const std::size_t current_str_len {str_len(rng)}; + generate_random_cstring(str, current_str_len); + const auto uuid_res {get_boost_uuid_result(str, current_str_len)}; + const auto crypt_res {boost::crypt::md5(str, current_str_len)}; + + for (std::size_t j {}; j < crypt_res.size(); ++j) + { + if (!BOOST_TEST_EQ(uuid_res[j], crypt_res[j])) + { + // LCOV_EXCL_START + std::cerr << "Failure with string: " << str << std::endl; + break; + // LCOV_EXCL_STOP + } + } + } + + delete[] str; +} + int main() { basic_tests(); @@ -151,5 +251,7 @@ int main() test_class(); + test_random_values(); + return boost::report_errors(); } From 261461436323942fe6e11866dc856639e28e2b5f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 15 Oct 2024 11:20:53 -0400 Subject: [PATCH 73/76] Add missing codecov lib --- .github/workflows/codecov.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index e37414c7..00694bab 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -49,6 +49,9 @@ jobs: git submodule update --init libs/predef git submodule update --init libs/static_assert git submodule update --init libs/test + git submodule update --init libs/uuid + git submodule update --init libs/throw_exception + git submodule update --init libs/type_traits ./bootstrap.sh ./b2 headers - name: gcc-gcov-native From 70e04ab87fbee70678de5a6368330a388c3042b5 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 15 Oct 2024 11:40:58 -0400 Subject: [PATCH 74/76] Exclude LCOV constexpr lines --- include/boost/crypt/hash/md5.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/crypt/hash/md5.hpp b/include/boost/crypt/hash/md5.hpp index 2fe3e9fd..d74061dd 100644 --- a/include/boost/crypt/hash/md5.hpp +++ b/include/boost/crypt/hash/md5.hpp @@ -375,7 +375,7 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str) noexcept -> boost::c { if (str == nullptr) { - return boost::crypt::array{}; + return boost::crypt::array{}; // LCOV_EXCL_LINE } const auto message_len {utility::strlen(str)}; @@ -386,7 +386,7 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const char* str, boost::crypt::size_t { if (str == nullptr) { - return boost::crypt::array{}; + return boost::crypt::array{}; // LCOV_EXCL_LINE } return detail::md5(str, str + len); @@ -396,7 +396,7 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const boost::crypt::uint8_t* str) noe { if (str == nullptr) { - return boost::crypt::array{}; + return boost::crypt::array{}; // LCOV_EXCL_LINE } const auto message_len {utility::strlen(str)}; @@ -407,7 +407,7 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto md5(const boost::crypt::uint8_t* str, boo { if (str == nullptr) { - return boost::crypt::array{}; + return boost::crypt::array{}; // LCOV_EXCL_LINE } return detail::md5(str, str + len); From 0dfd72c6ddabf0e3b4f8aed0356b30516c331d73 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 15 Oct 2024 11:41:15 -0400 Subject: [PATCH 75/76] Add piecewise parsing test --- test/test_md5.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index 97c724b7..dfd91072 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -240,6 +240,58 @@ void test_random_values() delete[] str; } +void test_random_piecewise_values() +{ + constexpr std::size_t max_str_len {65535U}; + std::mt19937_64 rng(42); + std::uniform_int_distribution str_len(1, max_str_len - 1); + + char* str {new char[max_str_len]}; + char* str_2 {new char[max_str_len]}; + + for (std::size_t i {}; i < 1024; ++i) + { + boost::uuids::detail::md5 boost_hasher; + boost::crypt::md5_hasher md5_hasher; + + std::memset(str, '\0', max_str_len); + std::memset(str_2, '\0', max_str_len); + + const std::size_t current_str_len {str_len(rng)}; + generate_random_cstring(str, current_str_len); + generate_random_cstring(str_2, current_str_len); + + boost_hasher.process_bytes(str, current_str_len); + boost_hasher.process_bytes(str_2, current_str_len); + unsigned char digest[16]; + boost_hasher.get_digest(digest); + + std::array uuid_res {}; + for (std::size_t j {}; j < 16U; ++j) + { + uuid_res[j] = digest[j]; + } + + md5_hasher.process_bytes(str, current_str_len); + md5_hasher.process_bytes(str_2, current_str_len); + const auto crypt_res {md5_hasher.get_digest()}; + + for (std::size_t j {}; j < crypt_res.size(); ++j) + { + if (!BOOST_TEST_EQ(uuid_res[j], crypt_res[j])) + { + // LCOV_EXCL_START + std::cerr << "Failure with string: " << str << std::endl; + break; + // LCOV_EXCL_STOP + } + } + } + + delete[] str; + delete[] str_2; +} + int main() { basic_tests(); @@ -252,6 +304,7 @@ int main() test_class(); test_random_values(); + test_random_piecewise_values(); return boost::report_errors(); } From 21def3862776e6b4e876dbcf60182186ff37ed17 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 15 Oct 2024 11:58:14 -0400 Subject: [PATCH 76/76] Improve coverage --- test/test_md5.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/test_md5.cpp b/test/test_md5.cpp index dfd91072..67c1e3a2 100644 --- a/test/test_md5.cpp +++ b/test/test_md5.cpp @@ -181,6 +181,13 @@ void bad_input() BOOST_TEST_EQ(unsigned_null_message_len[1], 0x0); BOOST_TEST_EQ(unsigned_null_message_len[2], 0x0); BOOST_TEST_EQ(unsigned_null_message_len[3], 0x0); + + std::string test_str {"Test string"}; + const auto reveresed_input {boost::crypt::detail::md5(test_str.end(), test_str.begin())}; + BOOST_TEST_EQ(reveresed_input[0], 0x0); + BOOST_TEST_EQ(reveresed_input[1], 0x0); + BOOST_TEST_EQ(reveresed_input[2], 0x0); + BOOST_TEST_EQ(reveresed_input[3], 0x0); } void test_class() @@ -263,6 +270,7 @@ void test_random_piecewise_values() boost_hasher.process_bytes(str, current_str_len); boost_hasher.process_bytes(str_2, current_str_len); + boost_hasher.process_byte(52); // "4" unsigned char digest[16]; boost_hasher.get_digest(digest); @@ -274,6 +282,7 @@ void test_random_piecewise_values() md5_hasher.process_bytes(str, current_str_len); md5_hasher.process_bytes(str_2, current_str_len); + md5_hasher.process_byte(52); // "4" const auto crypt_res {md5_hasher.get_digest()}; for (std::size_t j {}; j < crypt_res.size(); ++j)