From c3682b4542ad57aa4bbcd713052c93514ff664ae Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 17 Jan 2025 14:06:16 -0500 Subject: [PATCH 01/25] Add class outline --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 include/boost/crypt2/drbg/detail/hash_drbg.hpp diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp new file mode 100644 index 00000000..0eb3e4a8 --- /dev/null +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -0,0 +1,68 @@ +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CRYPT2_DRBG_HASH_DRBG_HPP +#define BOOST_CRYPT2_DRBG_HASH_DRBG_HPP + +#include +#include +#include +#include + +namespace boost::crypt::drbg_detail { + +// Max hasher security is defined in NIST SP 800-57 Table 3: +// See: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf +// +// 112: None +// 128: SHA-1 +// 192: SHA-224, SHA-512/224, SHA3-224 +// 256: SHA-256, SHA-512/256, SHA-384, SHA-512, SHA3-256, SHA3-384, SHA3-512 +// +// Outlen is defined in NIST SP 800-90A Rev 1 Section 10.1 table 2 +// 160: SHA-1 +// 224: SHA-224, SHA-512/224 +// 256: SHA-256, SHA-512/256 +// 384: SHA-384 +// 512: SHA-512 +template +class hash_drbg +{ +private: + + static constexpr compat::size_t outlen_bytes {outlen / 8U}; + static constexpr compat::size_t max_bytes_per_request {65536U}; + static constexpr compat::size_t min_length {max_hasher_security / 8U}; + static constexpr compat::size_t min_entropy {min_length * 3U / 2U}; + static constexpr compat::size_t seedlen {outlen >= 384 ? 888U : 440U}; + static constexpr compat::size_t seedlen_bytes {seedlen / 8U}; + + static constexpr compat::uint64_t max_length {4294967296ULL}; // 2^35 / 8 + static constexpr compat::uint64_t reseed_interval {281474976710656ULL}; // 2^48 + + compat::array constant_ {}; + compat::array value_ {}; + + compat::uint64_t reseed_counter_ {}; + bool initialized_ {}; + +public: + + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg() noexcept = default; + + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR ~hash_drbg() noexcept; +}; + +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg::~hash_drbg() noexcept +{ + detail::clear_mem(constant_); + detail::clear_mem(value_); + reseed_counter_ = 0U; + initialized_ = false; +} + +} // namespace boost::crypt::drbg_detail + +#endif //BOOST_CRYPT2_DRBG_HASH_DRBG_HPP From ffeee384340980def51c9ba49e8f15a335fdadc3 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 17 Jan 2025 14:29:41 -0500 Subject: [PATCH 02/25] Add ability to process single byte in hashers --- include/boost/crypt2/hash/detail/sha3_base.hpp | 9 +++++++++ include/boost/crypt2/hash/detail/sha512_base.hpp | 9 +++++++++ .../crypt2/hash/detail/sha_1_2_hasher_base.hpp | 13 +++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt2/hash/detail/sha3_base.hpp b/include/boost/crypt2/hash/detail/sha3_base.hpp index 697c3397..44b7f5fa 100644 --- a/include/boost/crypt2/hash/detail/sha3_base.hpp +++ b/include/boost/crypt2/hash/detail/sha3_base.hpp @@ -65,6 +65,8 @@ class sha3_base final { template BOOST_CRYPT_GPU_ENABLED auto process_bytes(SizedRange&& data) noexcept -> state; + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto process_byte(const compat::byte data) noexcept -> state; + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto finalize() noexcept -> state; // SHA 3 get_digest is idempotent so make as const @@ -330,6 +332,13 @@ BOOST_CRYPT_GPU_ENABLED auto sha3_base::process_bytes(Sized return update(compat::as_bytes(data_span)); } +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha3_base::process_byte(const compat::byte data) noexcept -> state +{ + const compat::span data_span {&data, 1U}; + return update(data_span); +} + template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha3_base::finalize() noexcept -> state { diff --git a/include/boost/crypt2/hash/detail/sha512_base.hpp b/include/boost/crypt2/hash/detail/sha512_base.hpp index 8efb740f..9bf4c478 100644 --- a/include/boost/crypt2/hash/detail/sha512_base.hpp +++ b/include/boost/crypt2/hash/detail/sha512_base.hpp @@ -63,6 +63,8 @@ class sha512_base final template BOOST_CRYPT_GPU_ENABLED auto process_bytes(SizedRange&& data) noexcept -> state; + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto process_byte(compat::byte data) noexcept -> state; + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto finalize() noexcept -> state; [[nodiscard("Digest is the function return value")]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR @@ -510,6 +512,13 @@ BOOST_CRYPT_GPU_ENABLED auto sha512_base::process_bytes(SizedRange& return update(compat::as_bytes(data_span)); } +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha512_base::process_byte(compat::byte data) noexcept -> state +{ + const compat::span data_span {&data, 1U}; + return update(data_span); +} + template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha512_base::pad_message() noexcept -> void { diff --git a/include/boost/crypt2/hash/detail/sha_1_2_hasher_base.hpp b/include/boost/crypt2/hash/detail/sha_1_2_hasher_base.hpp index 551ab560..34140cc5 100644 --- a/include/boost/crypt2/hash/detail/sha_1_2_hasher_base.hpp +++ b/include/boost/crypt2/hash/detail/sha_1_2_hasher_base.hpp @@ -52,7 +52,9 @@ class sha_1_2_hasher_base BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto process_bytes(compat::span data) noexcept -> state; template - BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto process_bytes(SizedRange&& data) noexcept -> state; + BOOST_CRYPT_GPU_ENABLED auto process_bytes(SizedRange&& data) noexcept -> state; + + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto process_byte(const compat::byte data) noexcept -> state; BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto finalize() noexcept -> state; @@ -231,7 +233,7 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha_1_2_hasher_base template -BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha_1_2_hasher_base::process_bytes(SizedRange&& data) noexcept -> state +BOOST_CRYPT_GPU_ENABLED auto sha_1_2_hasher_base::process_bytes(SizedRange&& data) noexcept -> state { auto data_span {compat::make_span(compat::forward(data))}; return update(compat::as_bytes(data_span)); @@ -244,6 +246,13 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha_1_2_hasher_base +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto sha_1_2_hasher_base::process_byte(const compat::byte data) noexcept -> state +{ + const compat::span data_span {&data, 1U}; + return update(data_span); +} + template template [[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR From c1a29d52888988aa7928858cb8676f727e0dddc7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 17 Jan 2025 15:25:11 -0500 Subject: [PATCH 03/25] Implement hash_drbg --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 0eb3e4a8..a1dd4107 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace boost::crypt::drbg_detail { @@ -47,6 +48,13 @@ class hash_drbg compat::uint64_t reseed_counter_ {}; bool initialized_ {}; + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_df(compat::uint32_t no_of_bits_to_return, + compat::span return_container, + compat::span provided_data_1, + compat::span provided_data_2, + compat::span provided_data_3, + compat::span provided_data_4) noexcept -> state; + public: BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg() noexcept = default; @@ -54,6 +62,62 @@ class hash_drbg BOOST_CRYPT_GPU_ENABLED_CONSTEXPR ~hash_drbg() noexcept; }; +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::hash_df( + compat::uint32_t no_of_bits_to_return, + compat::span return_container, + compat::span provided_data_1, + compat::span provided_data_2, + compat::span provided_data_3, + compat::span provided_data_4) noexcept -> state +{ + const auto no_of_bytes_to_return {(no_of_bits_to_return + 7U) / 8U}; + const auto len {(no_of_bytes_to_return + outlen_bytes - 1U) / outlen_bytes}; + + if (len > 255U) [[unlikely]] + { + return state::requested_too_many_bits; + } + else if (return_container.size() < no_of_bytes_to_return) [[unlikely]] + { + return state::out_of_memory; + } + + // The hash string concatenates the value of no_of_bits_to_return + const compat::array bits_to_return_array { + static_cast((no_of_bits_to_return >> 24) & 0xFF), + static_cast((no_of_bits_to_return >> 16) & 0xFF), + static_cast((no_of_bits_to_return >> 8) & 0xFF), + static_cast(no_of_bits_to_return & 0xFF) + }; + const compat::span bits_to_return_span {bits_to_return_array}; + + // See 10.3.1 + // temp = temp || HASH(counter, no_of_bits_to_return || input_string) + compat::size_t offset {}; + for (compat::size_t counter {1}; counter <= len; ++counter) + { + HasherType hasher; + hasher.process_byte(static_cast(counter)); + hasher.process_bytes(bits_to_return_span); + hasher.process_bytes(provided_data_1); + hasher.process_bytes(provided_data_2); + hasher.process_bytes(provided_data_3); + hasher.process_bytes(provided_data_4); + hasher.finalize(); + const auto return_val {hasher.get_digest()}; + + BOOST_CRYPT_ASSERT(return_val.has_value()); + + const auto return_val_array {return_val.value()}; + + for (compat::size_t i {}; i < return_val_array.size() && offset < no_of_bytes_to_return; ++i) + { + return_container[offset++] = return_val[i]; + } + } +} + template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg::~hash_drbg() noexcept { From 8280c2f682a1ecc290604b5973719bfe1d749ecd Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 17 Jan 2025 15:36:26 -0500 Subject: [PATCH 04/25] Statically handle extents --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index a1dd4107..309988db 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -48,12 +48,20 @@ class hash_drbg compat::uint64_t reseed_counter_ {}; bool initialized_ {}; + template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_df(compat::uint32_t no_of_bits_to_return, - compat::span return_container, - compat::span provided_data_1, - compat::span provided_data_2, - compat::span provided_data_3, - compat::span provided_data_4) noexcept -> state; + compat::span return_container, + compat::span provided_data_1, + compat::span provided_data_2, + compat::span provided_data_3, + compat::span provided_data_4) noexcept -> state; + + template + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hashgen(compat::span returned_bits, compat::size_t requested_number_of_bytes) noexcept -> state public: @@ -63,13 +71,18 @@ class hash_drbg }; template +template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::hash_df( compat::uint32_t no_of_bits_to_return, - compat::span return_container, - compat::span provided_data_1, - compat::span provided_data_2, - compat::span provided_data_3, - compat::span provided_data_4) noexcept -> state + compat::span return_container, + compat::span provided_data_1, + compat::span provided_data_2, + compat::span provided_data_3, + compat::span provided_data_4) noexcept -> state { const auto no_of_bytes_to_return {(no_of_bits_to_return + 7U) / 8U}; const auto len {(no_of_bytes_to_return + outlen_bytes - 1U) / outlen_bytes}; @@ -100,10 +113,27 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg(counter)); hasher.process_bytes(bits_to_return_span); - hasher.process_bytes(provided_data_1); - hasher.process_bytes(provided_data_2); - hasher.process_bytes(provided_data_3); - hasher.process_bytes(provided_data_4); + + if constexpr (Extent1 != 0U) + { + hasher.process_bytes(provided_data_1); + } + + if constexpr (Extent2 != 0U) + { + hasher.process_bytes(provided_data_2); + } + + if constexpr (Extent3 != 0U) + { + hasher.process_bytes(provided_data_3); + } + + if constexpr (Extent4 != 0U) + { + hasher.process_bytes(provided_data_4); + } + hasher.finalize(); const auto return_val {hasher.get_digest()}; From 0eb809dbb841d25f898fa52d5cfc09335a383e44 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 17 Jan 2025 16:01:37 -0500 Subject: [PATCH 05/25] Add uint16_t type --- include/boost/crypt2/detail/compat.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/crypt2/detail/compat.hpp b/include/boost/crypt2/detail/compat.hpp index d0529867..413ca9ae 100644 --- a/include/boost/crypt2/detail/compat.hpp +++ b/include/boost/crypt2/detail/compat.hpp @@ -46,10 +46,12 @@ namespace boost::crypt::compat { // Fixed width types #if BOOST_CRYPT_HAS_CUDA using size_t = cuda::std::size_t; +using uint16_t = cuda::std::uint16_t; using uint32_t = cuda::std::uint32_t; using uint64_t = cuda::std::uint64_t; #else using size_t = std::size_t; +using uint16_t = std::uint16_t; using uint32_t = std::uint32_t; using uint64_t = std::uint64_t; #endif From dc9aa716cc41f97e9db93a6fa7935f534a1dd4da Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 17 Jan 2025 16:15:46 -0500 Subject: [PATCH 06/25] Add the hashgen function --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 61 +++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 309988db..26bf80bf 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -116,25 +116,30 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto +hash_drbg::hashgen(compat::span returned_bits, compat::size_t requested_number_of_bytes) noexcept -> state +{ + if (returned_bits.size() < requested_number_of_bytes) + { + return state::out_of_memory; + } + + const compat::span value_span {value_}; + compat::size_t offset {}; + HasherType hasher; + while (offset < requested_number_of_bytes) + { + // Step 1: hash the current state of the value array + hasher.init(); + [[maybe_unused]] const auto process_bytes_status {hasher.process_bytes(value_span)}; + BOOST_CRYPT_ASSERT(process_bytes_status == state::success); + [[maybe_unused]] const auto finalize_status {hasher.finalize()}; + BOOST_CRYPT_ASSERT(finalize_status == state::success); + const auto w_expected {hasher.get_digest()}; + BOOST_CRYPT_ASSERT(w_expected.has_value()); + + // Step 2: Write the output of the hash(value_) for return + const auto w {w_expected.value()}; + for (compat::size_t i {}; offset < requested_number_of_bytes && i < w.size(); ++i) + { + returned_bits[offset++] = w[i]; + } + + // Step 3: Increment value_ by 1 modulo 2^seedlen + compat::uint16_t carry {1}; + auto value_position {value_.rbegin()}; + + while (value_position != value_.rend() && carry) + { + const auto sum {static_cast(static_cast(*value_position) + carry)}; + carry = static_cast(sum >> 8U); + *value_position-- = static_cast(sum & 0xFFU); + } + } + + return state::success; +} + template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg::~hash_drbg() noexcept { From abbd8a8e3fc00d9a5f76dddd23ba51114683205a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 27 Jan 2025 15:25:16 -0500 Subject: [PATCH 07/25] Add init functions --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 90 ++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 26bf80bf..2630bf12 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -43,7 +43,9 @@ class hash_drbg static constexpr compat::uint64_t reseed_interval {281474976710656ULL}; // 2^48 compat::array constant_ {}; + compat::span constant_span_ {constant_}; compat::array value_ {}; + compat::span value_span_ {value_}; compat::uint64_t reseed_counter_ {}; bool initialized_ {}; @@ -61,13 +63,27 @@ class hash_drbg compat::span provided_data_4) noexcept -> state; template - BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hashgen(compat::span returned_bits, compat::size_t requested_number_of_bytes) noexcept -> state + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hashgen(compat::span returned_bits, compat::size_t requested_number_of_bytes) noexcept -> state; public: BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg() noexcept = default; BOOST_CRYPT_GPU_ENABLED_CONSTEXPR ~hash_drbg() noexcept; + + template + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto init(compat::span entropy, + compat::span nonce = compat::span{}, + compat::span personalization = compat::span{}) noexcept -> state; + + template + BOOST_CRYPT_GPU_ENABLED auto init(SizedRange1&& entropy, + SizedRange2&& nonce = compat::array {}, + SizedRange3&& personalization = compat::array {}) noexcept -> state; }; template @@ -208,6 +224,78 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::init( + compat::span entropy, + compat::span nonce, + compat::span personalization) noexcept -> state +{ + if (entropy.size() + nonce.size() < min_entropy) + { + return state::insufficient_entropy; + } + + auto seed_status {hash_df(seedlen, entropy, nonce, personalization)}; + + if (seed_status != state::success) [[unlikely]] + { + return seed_status; + } + + constexpr compat::array offset_array {compat::byte {0x00}}; + const compat::span offset_span {offset_array}; + seed_status = hash_df(seedlen, constant_span_, offset_span, value_span_); + + if (seed_status != state::success) + { + return seed_status; + } + + initialized_ = true; + reseed_counter_ = 1U; + + return state::success; +} + +template +template +BOOST_CRYPT_GPU_ENABLED auto hash_drbg::init( + SizedRange1&& entropy, + SizedRange2&& nonce, + SizedRange3&& personalization) noexcept -> state +{ + // First check to see if conversion to spans is even worthwhile + if (entropy.size() + nonce.size() < min_entropy) + { + return state::insufficient_entropy; + } + else + { + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" + #endif + + // Since these are sized ranges we can safely convert them into spans + auto entropy_span {compat::make_span(compat::forward(entropy))}; + auto nonce_span {compat::make_span(compat::forward(nonce))}; + auto personalization_span {compat::make_span(compat::forward(personalization))}; + + return init(compat::as_bytes(entropy_span), + compat::as_bytes(nonce_span), + compat::as_bytes(personalization_span)); + + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic pop + #endif + } +} + } // namespace boost::crypt::drbg_detail #endif //BOOST_CRYPT2_DRBG_HASH_DRBG_HPP From 1d8824a17afe7ffb382f7a9ef463da1fdcccaa66 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 27 Jan 2025 16:26:13 -0500 Subject: [PATCH 08/25] Add reseed impl --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 2630bf12..73fac52d 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -84,6 +84,16 @@ class hash_drbg BOOST_CRYPT_GPU_ENABLED auto init(SizedRange1&& entropy, SizedRange2&& nonce = compat::array {}, SizedRange3&& personalization = compat::array {}) noexcept -> state; + + template + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto reseed(compat::span entropy, + compat::span additional_input = compat::span{}) noexcept -> state; + + template + BOOST_CRYPT_GPU_ENABLED auto reseed(SizedRange1&& entropy, + SizedRange2&& additional_input = compat::array {}) noexcept -> state; }; template @@ -296,6 +306,80 @@ BOOST_CRYPT_GPU_ENABLED auto hash_drbg +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::reseed( + compat::span entropy, + compat::span additional_input) noexcept -> state +{ + constexpr auto min_reseed_entropy {max_hasher_security / 8U}; + + if (entropy.size() < min_reseed_entropy) + { + return state::insufficient_entropy; + } + + compat::array seed {}; + compat::span seed_span {seed}; + constexpr compat::array offset_array { compat::byte{0x01} }; + compat::span offset_array_span {offset_array}; + + auto seed_status {hash_df(seedlen, + seed_span, + offset_array_span, + value_span_, + entropy, + additional_input)}; + + if (seed_status != state::success) + { + return seed_status; + } + + value_ = seed; + + constexpr compat::array c_offset_array { compat::byte{0x00} }; + compat::span c_offset_span {c_offset_array}; + + seed_status = hash_df(seedlen, + constant_span_, + c_offset_span, + value_span_); + + if (seed_status != state::success) + { + return seed_status; + } + + reseed_counter_ = 1U; + return state::success; +} + +template +template +BOOST_CRYPT_GPU_ENABLED auto hash_drbg::reseed( + SizedRange1&& entropy, + SizedRange2&& additional_input) noexcept -> state +{ + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" + #endif + + // Since these are sized ranges we can safely convert them into spans + auto entropy_span {compat::make_span(compat::forward(entropy))}; + auto additional_input_span {compat::make_span(compat::forward(additional_input))}; + + return reseed(compat::as_bytes(entropy_span), + compat::as_bytes(additional_input)); + + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic pop + #endif +} + } // namespace boost::crypt::drbg_detail #endif //BOOST_CRYPT2_DRBG_HASH_DRBG_HPP From 195f7bc4c76fe106101c201aa013cccd867a5ed4 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 14:48:46 -0500 Subject: [PATCH 09/25] Add no_pr generate --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 73fac52d..1902a28b 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -65,6 +65,11 @@ class hash_drbg template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hashgen(compat::span returned_bits, compat::size_t requested_number_of_bytes) noexcept -> state; + template + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto no_pr_generate_impl(compat::span return_data, compat::size_t requested_bits, + compat::span additional_data = compat::span {}) noexcept -> state; + public: BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg() noexcept = default; @@ -380,6 +385,157 @@ BOOST_CRYPT_GPU_ENABLED auto hash_drbg +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::no_pr_generate_impl( + compat::span return_data, compat::size_t requested_bits, + compat::span additional_data) noexcept -> state +{ + if (reseed_counter_ > reseed_interval) + { + return state::requires_reseed; + } + if (!initialized_) + { + return state::uninitialized; + } + + const compat::size_t requested_bytes {(requested_bits + 7U) / 8U}; + if (requested_bytes > max_bytes_per_request) + { + return state::requested_too_many_bits; + } + + if constexpr (Extent2 != 0U) + { + // Step 2.1 and 2.2 + // If we are on a different 32 bit or smaller platform and using clang ignore the warning + #ifdef __clang__ + # pragma clang diagnostic push + # pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" + #endif + + #if !defined(__i386__) && !defined(_M_IX86) + if (additional_data.size() > max_length) + { + return state::input_too_long; // LCOV_EXCL_LINE + } + #endif // 32-bit platforms + + #ifdef __clang__ + # pragma clang diagnostic pop + #endif + + HasherType hasher {}; + hasher.process_byte(compat::byte{0x02}); + hasher.process_bytes(value_span_); + hasher.process_bytes(additional_data); + const auto w {hasher.get()}; + + // V = (v + w) mode 2^seedlen + auto w_iter {w.crbegin()}; + const auto w_end {w.crend()}; + + auto v_iter {value_.rbegin()}; + const auto v_end {value_.rend()}; + + // Since the size of V depends on the size of w we will never have an overflow situation + compat::uint16_t carry {}; + while (w_iter != w_end) + { + const auto sum {static_cast(static_cast(*w_iter) + static_cast(*v_iter) + carry)}; + carry = static_cast(sum >> 8U); + *v_iter++ = static_cast(sum & 0xFFU); + ++w_iter; + } + } + + // Step 3: Fill the buffer with the bytes to return to the user + const auto hashgen_return {hashgen(return_data, requested_bytes)}; + if (hashgen_return != state::success) [[unlikely]] + { + return hashgen_return; + } + + // Step 4: H = Hash(0x03 || V) + HasherType hasher {}; + hasher.process_byte(compat::byte{0x03}); + hasher.process_bytes(value_span_); + const auto h {hasher.get_digest()}; + if (!h.has_value()) [[unlikely]] + { + return h.err(); + } + + // Step 5: v = (v + h + c + reseed counter) mod 2^seedlen + // Rather than converting V, H, C and reseed to bignums and applying big num modular arithmetic + // we add all bytes of the same offset at once and have an integer rather than boolean carry + // we also terminate the calculation at mod 2^seedlen since anything past that is irrelevant + // It just so happens that value_ is 2^seedlen long + // + // The rub is that everything is to be in big endian order so we use reverse iterators + const compat::array reseed_counter_bytes = { + static_cast((reseed_counter_ >> 56U) & 0xFFU), + static_cast((reseed_counter_ >> 48U) & 0xFFU), + static_cast((reseed_counter_ >> 40U) & 0xFFU), + static_cast((reseed_counter_ >> 32U) & 0xFFU), + static_cast((reseed_counter_ >> 24U) & 0xFFU), + static_cast((reseed_counter_ >> 16U) & 0xFFU), + static_cast((reseed_counter_ >> 8U) & 0xFFU), + static_cast(reseed_counter_ & 0xFFU), + }; + + // Initialize iterators for V + auto value_iter {value_.rbegin()}; + const auto value_end {value_.rend()}; + + // Initialize iterators for H, C, and reseed_counter_bytes + auto h_iter {h.crbegin()}; + const auto h_end {h.crend()}; + + auto c_iter {constant_.crbegin()}; + + auto reseed_counter_iter {reseed_counter_bytes.crbegin()}; + const auto reseed_counter_end {reseed_counter_bytes.crend()}; + + // Older GCC warns the += is int instead of uint16_t + #if defined(__GNUC__) && __GNUC__ >= 5 && __GNUC__ < 10 + # pragma GCC diagnostic push + # pragma GCC diagnostic ignored "-Wconversion" + #endif + + compat::uint16_t carry {}; + // Since the length of constant and value are known to be the same we only boundary check one of the two + while (value_iter != value_end) + { + compat::uint16_t sum {static_cast( + static_cast(*value_iter) + + static_cast(*c_iter++) + carry + )}; + + if (h_iter != h_end) + { + sum += static_cast(*h_iter++); + } + + if (reseed_counter_iter != reseed_counter_end) + { + sum += static_cast(*reseed_counter_iter++); + } + + carry = static_cast(sum >> 8U); + *value_iter++ = static_cast(sum & 0xFFU); + } + + #if defined(__GNUC__) && __GNUC__ >= 5 && __GNUC__ < 10 + # pragma GCC diagnostic pop + #endif + + ++reseed_counter_; + return state::success; +} + } // namespace boost::crypt::drbg_detail #endif //BOOST_CRYPT2_DRBG_HASH_DRBG_HPP From 94db6a761204bec632f18cb964067156b8b39ae3 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 14:53:43 -0500 Subject: [PATCH 10/25] Add prediction resistant generate --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 1902a28b..a23c7e87 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -70,6 +70,12 @@ class hash_drbg BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto no_pr_generate_impl(compat::span return_data, compat::size_t requested_bits, compat::span additional_data = compat::span {}) noexcept -> state; + template + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto pr_generate_impl(compat::span return_data, compat::size_t requested_bits, + compat::span entropy, + compat::span additional_data = compat::span {}) noexcept -> state; public: BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg() noexcept = default; @@ -536,6 +542,34 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::pr_generate_impl( + compat::span return_data, compat::size_t requested_bits, + compat::span entropy, + compat::span additional_data) noexcept -> state +{ + if (reseed_counter_ > reseed_interval) + { + return state::requires_reseed; + } + if (!initialized_) + { + return state::uninitialized; + } + + // 9.3.3 Reseed using the entropy and the additional data, then set additional data to NULL + const auto reseed_return {reseed(entropy, additional_data)}; + if (reseed_return != state::success) [[unlikely]] + { + return reseed_return; + } + + return no_pr_generate_impl(return_data, requested_bits); +} + } // namespace boost::crypt::drbg_detail #endif //BOOST_CRYPT2_DRBG_HASH_DRBG_HPP From 0524f87922574094711a03d5d50b18f22819ab0a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 16:12:10 -0500 Subject: [PATCH 11/25] Add master generate impl --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index a23c7e87..56f39bfe 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -68,14 +68,14 @@ class hash_drbg template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto no_pr_generate_impl(compat::span return_data, compat::size_t requested_bits, - compat::span additional_data = compat::span {}) noexcept -> state; + compat::span additional_data = compat::span {}) noexcept -> state; template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto pr_generate_impl(compat::span return_data, compat::size_t requested_bits, compat::span entropy, - compat::span additional_data = compat::span {}) noexcept -> state; + compat::span additional_data = compat::span {}) noexcept -> state; public: BOOST_CRYPT_GPU_ENABLED_CONSTEXPR hash_drbg() noexcept = default; @@ -105,6 +105,13 @@ class hash_drbg concepts::sized_range SizedRange2> BOOST_CRYPT_GPU_ENABLED auto reseed(SizedRange1&& entropy, SizedRange2&& additional_input = compat::array {}) noexcept -> state; + + template + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto generate(compat::span return_data, compat::size_t requested_bits, + compat::span additional_data1 = compat::span {}, + [[maybe_unused]] compat::span additional_data2 = compat::span {}) noexcept -> state; }; template @@ -570,6 +577,25 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg +template +BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::generate( + compat::span return_data, compat::size_t requested_bits, + compat::span additional_data1, + [[maybe_unused]] compat::span additional_data2) noexcept -> state +{ + if constexpr (prediction_resistance) + { + return pr_generate_impl(return_data, requested_bits, additional_data1, additional_data2); + } + else + { + return no_pr_generate_impl(return_data, requested_bits, additional_data1); + } +} + } // namespace boost::crypt::drbg_detail #endif //BOOST_CRYPT2_DRBG_HASH_DRBG_HPP From 9d26ff31baf5749d02373150ae1f0b1704f554fc Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 16:28:19 -0500 Subject: [PATCH 12/25] Add user facing generate --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 56f39bfe..cc13eef3 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -112,6 +112,13 @@ class hash_drbg BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto generate(compat::span return_data, compat::size_t requested_bits, compat::span additional_data1 = compat::span {}, [[maybe_unused]] compat::span additional_data2 = compat::span {}) noexcept -> state; + + template + BOOST_CRYPT_GPU_ENABLED auto generate(SizedRange1&& return_data, compat::size_t requested_bits, + SizedRange2&& additional_data1 = compat::array{}, + [[maybe_unused]] SizedRange3&& additional_data2 = compat::array{}) noexcept -> state; }; template @@ -596,6 +603,54 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg +template +BOOST_CRYPT_GPU_ENABLED auto hash_drbg::generate(SizedRange1&& return_data, compat::size_t requested_bits, + SizedRange2&& additional_data1, + [[maybe_unused]] SizedRange3&& additional_data2) noexcept -> state +{ + if constexpr (prediction_resistance) + { + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" + #endif + + // Since these are sized ranges we can safely convert them into spans + auto return_data_span {compat::make_span(compat::forward(return_data))}; + auto additional_data1_span {compat::make_span(compat::forward(additional_data1))}; + auto additional_data2_span {compat::make_span(compat::forward(additional_data2))}; + + return reseed(compat::as_writable_bytes(return_data_span), requested_bits, + compat::as_bytes(additional_data1_span), + compat::as_bytes(additional_data2_span)); + + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic pop + #endif + } + else + { + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" + #endif + + // Since these are sized ranges we can safely convert them into spans + auto return_data_span {compat::make_span(compat::forward(return_data))}; + auto additional_data1_span {compat::make_span(compat::forward(additional_data1))}; + + return reseed(compat::as_writable_bytes(return_data_span), requested_bits, + compat::as_bytes(additional_data1_span)); + + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic pop + #endif + } +} + } // namespace boost::crypt::drbg_detail #endif //BOOST_CRYPT2_DRBG_HASH_DRBG_HPP From 3b6b85cd5ff7c3ca7b723972a5b30e3757ade3b7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 16:58:35 -0500 Subject: [PATCH 13/25] Various fixes --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index cc13eef3..71053913 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -91,7 +91,7 @@ class hash_drbg template + concepts::sized_range SizedRange3 = compat::array> BOOST_CRYPT_GPU_ENABLED auto init(SizedRange1&& entropy, SizedRange2&& nonce = compat::array {}, SizedRange3&& personalization = compat::array {}) noexcept -> state; @@ -102,7 +102,7 @@ class hash_drbg compat::span additional_input = compat::span{}) noexcept -> state; template + concepts::sized_range SizedRange2 = compat::array> BOOST_CRYPT_GPU_ENABLED auto reseed(SizedRange1&& entropy, SizedRange2&& additional_input = compat::array {}) noexcept -> state; @@ -114,8 +114,8 @@ class hash_drbg [[maybe_unused]] compat::span additional_data2 = compat::span {}) noexcept -> state; template + concepts::sized_range SizedRange2 = compat::array, + concepts::sized_range SizedRange3 = compat::array> BOOST_CRYPT_GPU_ENABLED auto generate(SizedRange1&& return_data, compat::size_t requested_bits, SizedRange2&& additional_data1 = compat::array{}, [[maybe_unused]] SizedRange3&& additional_data2 = compat::array{}) noexcept -> state; @@ -398,7 +398,7 @@ BOOST_CRYPT_GPU_ENABLED auto hash_drbg(additional_input))}; return reseed(compat::as_bytes(entropy_span), - compat::as_bytes(additional_input)); + compat::as_bytes(additional_input_span)); #if defined(__clang__) && __clang_major__ >= 19 #pragma clang diagnostic pop @@ -451,7 +451,13 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg(static_cast(*w_iter) + static_cast(*v_iter) + carry)}; carry = static_cast(sum >> 8U); @@ -482,11 +488,12 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg(additional_data1))}; auto additional_data2_span {compat::make_span(compat::forward(additional_data2))}; - return reseed(compat::as_writable_bytes(return_data_span), requested_bits, - compat::as_bytes(additional_data1_span), - compat::as_bytes(additional_data2_span)); + return pr_generate_impl(compat::as_writable_bytes(return_data_span), requested_bits, + compat::as_bytes(additional_data1_span), + compat::as_bytes(additional_data2_span)); #if defined(__clang__) && __clang_major__ >= 19 #pragma clang diagnostic pop @@ -642,8 +649,8 @@ BOOST_CRYPT_GPU_ENABLED auto hash_drbg(return_data))}; auto additional_data1_span {compat::make_span(compat::forward(additional_data1))}; - return reseed(compat::as_writable_bytes(return_data_span), requested_bits, - compat::as_bytes(additional_data1_span)); + return no_pr_generate_impl(compat::as_writable_bytes(return_data_span), requested_bits, + compat::as_bytes(additional_data1_span)); #if defined(__clang__) && __clang_major__ >= 19 #pragma clang diagnostic pop From 2f19cf84015cb6f80bca906790cb33568d91f477 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 16:58:47 -0500 Subject: [PATCH 14/25] Add SHA1 drbg definition --- include/boost/crypt2/drbg/sha1_drbg.hpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/boost/crypt2/drbg/sha1_drbg.hpp diff --git a/include/boost/crypt2/drbg/sha1_drbg.hpp b/include/boost/crypt2/drbg/sha1_drbg.hpp new file mode 100644 index 00000000..3443f632 --- /dev/null +++ b/include/boost/crypt2/drbg/sha1_drbg.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_CRYPT2_DRBG_SHA1_DRBG_HPP +#define BOOST_CRYPT2_DRBG_SHA1_DRBG_HPP + +#include +#include + +namespace boost::crypt { + +namespace drbg_detail { + +template +using sha1_hash_drbg_t = hash_drbg; + +} // namespace drbg_detail + +BOOST_CRYPT_EXPORT using sha1_hash_drbg = drbg_detail::sha1_hash_drbg_t; +BOOST_CRYPT_EXPORT using sha1_hash_drbg_pr = drbg_detail::sha1_hash_drbg_t; + +} // namespace boost::crypt + +#endif // BOOST_CRYPT2_DRBG_SHA1_DRBG_HPP From c5e6e219ae2cae9d59af3c7a6b0332708320a2ca Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 16:58:56 -0500 Subject: [PATCH 15/25] Update test set --- test/Jamfile | 2 +- test/test_hash_drbg.cpp | 277 ++++++++++------------------------------ 2 files changed, 72 insertions(+), 207 deletions(-) diff --git a/test/Jamfile b/test/Jamfile index 14ca4e16..da90f271 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -77,7 +77,7 @@ run test_hmac.cpp ; #run test_hmac_drbg.cpp ; -#run test_hash_drbg.cpp ; +run test_hash_drbg.cpp ; #run test_aes.cpp ; diff --git a/test/test_hash_drbg.cpp b/test/test_hash_drbg.cpp index 603cabdc..8c2c0934 100644 --- a/test/test_hash_drbg.cpp +++ b/test/test_hash_drbg.cpp @@ -3,48 +3,46 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_CRYPT_DEBUG -#include -#include +#include #include #include -#include #include void sha_1_basic_correctness() { boost::crypt::sha1_hash_drbg rng; - constexpr boost::crypt::array entropy = { + constexpr std::array entropy = { 0x13, 0x6c, 0xf1, 0xc1, 0x74, 0xe5, 0xa0, 0x9f, 0x66, 0xb9, 0x62, 0xd9, 0x94, 0x39, 0x65, 0x25 }; - constexpr boost::crypt::array nonce = { + constexpr std::array nonce = { 0xff, 0xf1, 0xc6, 0x64, 0x5f, 0x19, 0x23, 0x1f }; - boost::crypt::array return_bits {}; + std::array return_bits {}; // Test process is: // 1) Instantiate drbg // 2) Generate bits, do not compare // 3) Generate bits, compare // 4) Destroy drbg - BOOST_TEST(rng.init(entropy, entropy.size(), nonce, nonce.size()) == boost::crypt::state::success); + BOOST_TEST(rng.init(entropy, nonce) == boost::crypt::state::success); // ** INSTANTIATE: // V = a8 84 a8 3f a4 0b cf 73 0e 73 95 dd 58 00 ea 71 01 b4 87 7a aa 29 da 9b 7b c0 bd 2b d0 52 b9 b4 02 2f 83 ba e3 80 64 13 4a 23 38 35 84 5f dd 14 42 bf 3a 02 21 bd c8 // C = 49 77 fb 12 68 c1 f6 28 6b 5b 39 69 d4 16 fb 8c a7 e4 ea ab 7f d2 ed ef c2 39 20 2b aa 03 3f 8b 44 e9 14 51 48 ad 24 ce 83 d5 97 17 6a 0b ac c8 4c 99 24 6f 15 e0 88 - BOOST_TEST(rng.generate(return_bits.begin(), 640U) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U) == boost::crypt::state::success); // ** GENERATE (FIRST CALL): // V = f1 fc a3 52 0c cd c5 9b 79 ce cf 47 2c 17 e5 fd a9 99 72 26 29 fc c8 8b 3d f9 dd 57 7a 55 f9 3f 47 18 98 92 b1 8e 1c 5f 39 df c0 77 ae 25 65 88 ee ce c7 bb d0 32 3c // C = 49 77 fb 12 68 c1 f6 28 6b 5b 39 69 d4 16 fb 8c a7 e4 ea ab 7f d2 ed ef c2 39 20 2b aa 03 3f 8b 44 e9 14 51 48 ad 24 ce 83 d5 97 17 6a 0b ac c8 4c 99 24 6f 15 e0 88 - BOOST_TEST(rng.generate(return_bits.begin(), 640U) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U) == boost::crypt::state::success); // ** GENERATE (SECOND CALL): // V = 3b 74 9e 64 75 8f bb c3 e5 2a 08 b1 00 2e e1 8a 51 7e 5c d1 a9 cf b6 7b 00 32 fd 83 24 59 38 ca 8c 01 ad d7 70 68 51 5b de 24 8c 75 ad ea 10 bb aa f0 bc 18 e6 6a 2c // C = 49 77 fb 12 68 c1 f6 28 6b 5b 39 69 d4 16 fb 8c a7 e4 ea ab 7f d2 ed ef c2 39 20 2b aa 03 3f 8b 44 e9 14 51 48 ad 24 ce 83 d5 97 17 6a 0b ac c8 4c 99 24 6f 15 e0 88 - constexpr boost::crypt::array nist_return = { + constexpr std::array nist_return = { 0x0e, 0x28, 0x13, 0x0f, 0xa5, 0xca, 0x11, 0xed, 0xd3, 0x29, 0x3c, 0xa2, 0x6f, 0xdb, 0x8a, 0xe1, 0x81, 0x06, 0x11, 0xf7, 0x87, 0x15, 0x08, 0x2e, 0xd3, 0x84, 0x1e, 0x74, 0x86, 0xf1, @@ -55,14 +53,14 @@ void sha_1_basic_correctness() 0xbd, 0x1c, 0xe7, 0x02, 0xad, 0x53, 0x4d, 0xda, 0x0e, 0xd8 }; - for (boost::crypt::size_t i {}; i < return_bits.size(); ++i) + for (std::size_t i {}; i < return_bits.size(); ++i) { if (!BOOST_TEST_EQ(return_bits[i], nist_return[i])) { // LCOV_EXCL_START std::cerr << std::hex - << "Got: " << static_cast(return_bits[i]) - << "\nExpected: " << static_cast(nist_return[i]) << std::endl; + << "Got: " << static_cast(return_bits[i]) + << "\nExpected: " << static_cast(nist_return[i]) << std::endl; // LCOV_EXCL_STOP } } @@ -72,26 +70,26 @@ void sha1_pr_false() { boost::crypt::sha1_hash_drbg rng; - constexpr boost::crypt::array entropy = { + constexpr std::array entropy = { 0x16, 0x10, 0xb8, 0x28, 0xcc, 0xd2, 0x7d, 0xe0, 0x8c, 0xee, 0xa0, 0x32, 0xa2, 0x0e, 0x92, 0x08 }; - constexpr boost::crypt::array nonce = { + constexpr std::array nonce = { 0x49, 0x2c, 0xf1, 0x70, 0x92, 0x42, 0xf6, 0xb5 }; - constexpr boost::crypt::array entropy_reseed = { + constexpr std::array entropy_reseed = { 0x72, 0xd2, 0x8c, 0x90, 0x8e, 0xda, 0xf9, 0xa4, 0xd1, 0xe5, 0x26, 0xd8, 0xf2, 0xde, 0xd5, 0x44 }; - boost::crypt::array return_bits {}; + std::array return_bits {}; // Test process is: // 1) Instantiate drbg // 2) reseed // 3) Generate no-compare // 4) Generate compare - BOOST_TEST(rng.init(entropy, entropy.size(), nonce, nonce.size()) == boost::crypt::state::success); + BOOST_TEST(rng.init(entropy, nonce) == boost::crypt::state::success); // ** INSTANTIATE: // V = 9e 83 01 72 5d 5f 13 3b 4a b7 d3 29 fd 2f 87 ae 5f 89 d9 6a 9d d7 e2 b9 8b ee e1 c7 07 b8 c3 fe 41 2d 11 25 b5 8b ae 5d c0 8a 11 da c3 be 4a 31 47 34 71 60 fe f2 18 // C = e5 e1 24 50 45 0e fe 5f dc 77 7c 95 b8 c2 3c 93 8f cd 59 2e 2d 78 8f 12 46 19 36 e4 a1 61 31 b1 f2 d1 1c e7 f0 15 9e e1 e6 35 e6 2f 3d f8 bd a4 fe a0 77 ad 5f 9d 06 @@ -101,16 +99,16 @@ void sha1_pr_false() // V = 74 5c 65 9f 29 44 82 9c a6 e2 09 c8 ca 2d dd ec f9 f1 86 13 83 e3 4e 94 00 7a 3a 51 b8 44 4f d5 ae 73 8e 7d 9c 0d 5e 69 aa 97 ee 16 c4 9c fd 24 32 eb 32 ba 57 38 fa // C = a1 fc 40 00 93 57 a0 24 d8 78 81 8c f6 f9 79 a8 8d 4c c5 d7 60 b3 08 ae 1a 5b 9f 06 79 72 e6 f7 cf 92 dd b1 29 a8 d3 c1 bb 00 05 bc f3 f8 87 1f d6 5e 79 4f 19 90 b7 - BOOST_TEST(rng.generate(return_bits.begin(), 640U) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U) == boost::crypt::state::success); // ** GENERATE (FIRST CALL): // V = 1658a59fbc9c22c17f5a8b55c1275795873e4beae49657421ad5d95831b736cd7e066c738bcbb343933c411c7c17917593c03a77bed56b // C = a1fc40009357a024d878818cf6f979a88d4cc5d760b308ae1a5b9f067972e6f7cf92ddb129a8d3c1bb0005bcf3f8871fd65e794f1990b7 - BOOST_TEST(rng.generate(return_bits.begin(), 640U) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U) == boost::crypt::state::success); // ** GENERATE (SECOND CALL): // V = b854e5a04ff3c2e657d30ce2b820d13e148b11c245495ff03531785eab2a1dc54d994a5597b15c5b10001f49606c88b4ff0d61acb61820 // C = a1fc40009357a024d878818cf6f979a88d4cc5d760b308ae1a5b9f067972e6f7cf92ddb129a8d3c1bb0005bcf3f8871fd65e794f1990b7 - constexpr boost::crypt::array nist_return = { + constexpr std::array nist_return = { 0x56, 0xf3, 0x3d, 0x4f, 0xdb, 0xb9, 0xa5, 0xb6, 0x4d, 0x26, 0x23, 0x44, 0x97, 0xe9, 0xdc, 0xb8, 0x77, 0x98, 0xc6, 0x8d, 0x08, 0xf7, 0xc4, 0x11, 0x99, 0xd4, 0xbd, 0xdf, 0x97, 0xeb, @@ -121,64 +119,62 @@ void sha1_pr_false() 0xab, 0xff, 0x22, 0xff, 0xa6, 0xde, 0x3e, 0x22, 0xac, 0xa2 }; - for (boost::crypt::size_t i {}; i < return_bits.size(); ++i) + for (std::size_t i {}; i < return_bits.size(); ++i) { if (!BOOST_TEST_EQ(return_bits[i], nist_return[i])) { // LCOV_EXCL_START std::cerr << std::hex - << "Got: " << static_cast(return_bits[i]) - << "\nExpected: " << static_cast(nist_return[i]) << std::endl; + << "Got: " << static_cast(return_bits[i]) + << "\nExpected: " << static_cast(nist_return[i]) << std::endl; // LCOV_EXCL_STOP } } - - rng.destroy(); } void sha_1_pr_true() { boost::crypt::sha1_hash_drbg_pr rng; - constexpr boost::crypt::array entropy = { + constexpr std::array entropy = { 0x21, 0x29, 0x56, 0x39, 0x07, 0x83, 0x38, 0x1d, 0xbf, 0xc6, 0x36, 0x2d, 0xd0, 0xda, 0x9a, 0x09 }; - constexpr boost::crypt::array nonce = { + constexpr std::array nonce = { 0x52, 0x80, 0x98, 0x7f, 0xc5, 0xe2, 0x7a, 0x49 }; - constexpr boost::crypt::array entropy_gen_1 = { + constexpr std::array entropy_gen_1 = { 0x2e, 0xdb, 0x39, 0x6e, 0xeb, 0x89, 0x60, 0xf7, 0x79, 0x43, 0xc2, 0xa5, 0x90, 0x75, 0xa7, 0x86 }; - constexpr boost::crypt::array entropy_gen_2 = { + constexpr std::array entropy_gen_2 = { 0x30, 0xb5, 0x65, 0xb6, 0x3a, 0x50, 0x12, 0x67, 0x69, 0x40, 0xd3, 0xef, 0x17, 0xd9, 0xe9, 0x96 }; - boost::crypt::array return_bits {}; + std::array return_bits {}; // Test process is: // 1) Instantiate drbg // 2) Generate bits, do not compare // 3) Generate bits, compare // 4) Destroy drbg - BOOST_TEST(rng.init(entropy, entropy.size(), nonce, nonce.size()) == boost::crypt::state::success); + BOOST_TEST(rng.init(entropy, nonce) == boost::crypt::state::success); // ** INSTANTIATE: // V = 02b84eba8121ca090b6b66d3371609eaf76405a5c2807d80035c1a13dfed5aa18e536af599a7b3c68b2c56240ed11997f4048910d84604 // C = a677e4921587563eebe55d1b25e59c3f3d200bc61aaee665e7a6858c2857c45dba4bce8182252962ae86de491046a5e3450eec44938a0a - BOOST_TEST(rng.generate(return_bits.begin(), 640U, entropy_gen_1.begin(), entropy_gen_1.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, entropy_gen_1) == boost::crypt::state::success); // ** GENERATE (FIRST CALL): // V = f9afadfbbf2c3d1004f9baca38be247342e5fbb83281915d5de18beb963712a344e89bb0e6b925a7bbc32eadb8b441efc1fa0c649df42a // C = 1d41cbbd634909e4761c232fcfd6a6c2edf0a7f4d3d3c164f74a88955f355efce2d86c1e9fa897b7005ef9d4d3a51bf4fc0b805ab896c9 - BOOST_TEST(rng.generate(return_bits.begin(), 640U, entropy_gen_2.begin(), entropy_gen_2.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, entropy_gen_2) == boost::crypt::state::success); // ** GENERATE (SECOND CALL): // V = 7e4596f5a17447b6116788b5d8789fe99256c27a6842bd8d11f20df7f3ddcab9faae524cb72fffd56cd92b3f2393f35f606cf6d46c815e // C = 317ac6e7a87b57f0828cde8a4ccf6ad666670f4cffd628670fb9239563452eb3721db06ee06e8c08d78c555a833a8d91053dcf4c343003 - constexpr boost::crypt::array nist_return = { + constexpr std::array nist_return = { 0xca, 0x50, 0xec, 0x95, 0xc7, 0xc3, 0x8a, 0x58, 0x12, 0x9f, 0xd3, 0x75, 0x23, 0xd1, 0xf2, 0x59, 0x8c, 0xe6, 0xde, 0x98, 0xa6, 0xf1, 0x07, 0x72, 0x4c, 0x55, 0x46, 0xbe, 0xad, 0xaa, @@ -189,14 +185,14 @@ void sha_1_pr_true() 0xb2, 0xf8, 0xd1, 0xa3, 0xa8, 0x99, 0xf5, 0xa0, 0x0a, 0xf7 }; - for (boost::crypt::size_t i {}; i < return_bits.size(); ++i) + for (std::size_t i {}; i < return_bits.size(); ++i) { if (!BOOST_TEST_EQ(return_bits[i], nist_return[i])) { // LCOV_EXCL_START std::cerr << std::hex - << "Got: " << static_cast(return_bits[i]) - << "\nExpected: " << static_cast(nist_return[i]) << std::endl; + << "Got: " << static_cast(return_bits[i]) + << "\nExpected: " << static_cast(nist_return[i]) << std::endl; // LCOV_EXCL_STOP } } @@ -206,27 +202,27 @@ void sha1_additional_data() { boost::crypt::sha1_hash_drbg_pr rng; - constexpr boost::crypt::array entropy = { + constexpr std::array entropy = { 0x46, 0x52, 0xda, 0x57, 0x42, 0x9a, 0x76, 0xd6, 0xfe, 0x9e, 0x0e, 0x1f, 0xbb, 0x2f, 0x3c, 0xcd }; - constexpr boost::crypt::array nonce = { + constexpr std::array nonce = { 0x50, 0x44, 0xe6, 0xab, 0x2b, 0x55, 0x20, 0x66 }; - constexpr boost::crypt::array personalization_string = { + constexpr std::array personalization_string = { 0x96, 0xf1, 0x87, 0x86, 0x7c, 0x05, 0x7a, 0xe9, 0x82, 0xe0, 0x3a, 0x05, 0x6b, 0xbf, 0x0f, 0x48 }; - constexpr boost::crypt::array entropy_gen_1 = { + constexpr std::array entropy_gen_1 = { 0xca, 0x89, 0x0d, 0x84, 0x53, 0x82, 0x1c, 0x32, 0xc4, 0xed, 0xe3, 0xd3, 0x90, 0x2b, 0x13, 0x06 }; - constexpr boost::crypt::array entropy_gen_2 = { + constexpr std::array entropy_gen_2 = { 0x09, 0x9a, 0x2a, 0x45, 0x52, 0x60, 0x29, 0xfc, 0xdd, 0x2d, 0xa7, 0x4f, 0x63, 0x85, 0x00, 0xa9 }; - boost::crypt::array return_bits {}; + std::array return_bits {}; // Test process is: // 1) Instantiate drbg @@ -238,17 +234,17 @@ void sha1_additional_data() // V = da28c28db25547d1459e5952935d40c652d2f5e0375850341bcd91eef3b0a9eacf90a7ed159f4d4b2c0b1efbeaec05651851ee3f509775 // C = b1957c4ebf2706019352971dacd9bb7fe8583d5e0e15de09d63ecacabb30890ad52fdfca97aece42f4eed36d059f50945c1fbb0c0dfce9 - BOOST_TEST(rng.generate(return_bits.begin(), 640U, entropy_gen_1.begin(), entropy_gen_1.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, entropy_gen_1) == boost::crypt::state::success); // ** GENERATE (FIRST CALL): // V = 3e2a05e87aa688f9d1d875b84e68414216848078ed80c7341e707d36d29cd673f10d16a22b602e3231aa56f19bc500e6d2cff2fc19a2bb // C = ace58c1b7185a9369788314b8e8f867e22f7d9c71c0e559308d3ce948f17dc2c78e6aa804227b24354f8a0dfa9facfe630c620048681af - BOOST_TEST(rng.generate(return_bits.begin(), 640U, entropy_gen_2.begin(), entropy_gen_2.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, entropy_gen_2) == boost::crypt::state::success); // ** GENERATE (SECOND CALL): // V = 54ad6e24a43198965889bbf6030c9eca46e67cf0efca63ce1bbb34ba7945f394125f635aeb7f7948f1b215ab8bbca6c007a7325f508989 // C = 169a17564f69eaaf820f8cc44dce9bdfb3e96976935744cf99bf5da3c78cc0bd937ad642264756db4092556037108289de3042dc57d46e - constexpr boost::crypt::array nist_return = { + constexpr std::array nist_return = { 0x68, 0x4c, 0xc1, 0x69, 0x5b, 0x5a, 0x4b, 0x5d, 0x50, 0xd7, 0x42, 0x90, 0x52, 0x8a, 0xd5, 0x56, 0x22, 0x59, 0x86, 0x18, 0xeb, 0x8e, 0xda, 0xf1, 0x41, 0xe4, 0x1a, 0x89, 0x06, 0xf3, @@ -259,14 +255,14 @@ void sha1_additional_data() 0xd5, 0x66, 0x9a, 0x6a, 0xaf, 0xbd, 0xc8, 0xd4, 0xff, 0xf9 }; - for (boost::crypt::size_t i {}; i < return_bits.size(); ++i) + for (std::size_t i {}; i < return_bits.size(); ++i) { if (!BOOST_TEST_EQ(return_bits[i], nist_return[i])) { // LCOV_EXCL_START std::cerr << std::hex - << "Got: " << static_cast(return_bits[i]) - << "\nExpected: " << static_cast(nist_return[i]) << std::endl; + << "Got: " << static_cast(return_bits[i]) + << "\nExpected: " << static_cast(nist_return[i]) << std::endl; // LCOV_EXCL_STOP } } @@ -276,35 +272,35 @@ void sha1_additional_gen_input() { boost::crypt::sha1_hash_drbg_pr rng; - constexpr boost::crypt::array entropy = { + constexpr std::array entropy = { 0x8b, 0x76, 0x99, 0x15, 0x91, 0x7b, 0xbf, 0x4e, 0x4b, 0x48, 0xf2, 0x66, 0x39, 0x30, 0x61, 0x52 }; - constexpr boost::crypt::array nonce = { + constexpr std::array nonce = { 0x17, 0xea, 0x14, 0xe8, 0xad, 0x54, 0x46, 0xaa }; - constexpr boost::crypt::array personalization_string = { + constexpr std::array personalization_string = { 0x99, 0x94, 0xed, 0x56, 0xb1, 0x35, 0x5a, 0x6d, 0x60, 0x3e, 0x36, 0x6a, 0x8f, 0x9c, 0x04, 0xa9 }; - constexpr boost::crypt::array additional_input_1 = { + constexpr std::array additional_input_1 = { 0x1b, 0x8c, 0x8b, 0x88, 0xd7, 0xce, 0x96, 0xeb, 0x7a, 0xbd, 0x03, 0xb5, 0x55, 0x1c, 0xe9, 0x9d }; - constexpr boost::crypt::array entropy_gen_1 = { + constexpr std::array entropy_gen_1 = { 0x36, 0x39, 0x1d, 0x0d, 0x89, 0x75, 0x10, 0xaa, 0x84, 0x4c, 0x99, 0x20, 0x48, 0x8d, 0x49, 0xf2 }; - constexpr boost::crypt::array additional_input_2 = { + constexpr std::array additional_input_2 = { 0xfa, 0xb6, 0xfc, 0x0a, 0xcb, 0x22, 0x98, 0x38, 0x65, 0xc3, 0x83, 0x62, 0x53, 0x71, 0x8f, 0x31 }; - constexpr boost::crypt::array entropy_gen_2 = { + constexpr std::array entropy_gen_2 = { 0x74, 0xc7, 0xb5, 0x4e, 0x9f, 0xdc, 0x82, 0x4f, 0xc8, 0xe0, 0x46, 0x36, 0x73, 0xef, 0x92, 0xbc }; - boost::crypt::array return_bits {}; + std::array return_bits {}; // Test process is: // 1) Instantiate drbg @@ -316,17 +312,17 @@ void sha1_additional_gen_input() // V = 1bd499277b1c3b8ea183b2a924669ab99cb7dec9ef7709b6e1f11bf3e2199b09984c869669b268de0d09128fc9b4be5fc417d1c3ed9aa6 // C = de0f063ebdb0219fbfe6c9b3ac9271758423ff0394779e446f74dc977aded577e109efed627abf164873af417b6589ea4293c79c83cd6d - BOOST_TEST(rng.generate(return_bits.begin(), 640U, entropy_gen_1.begin(), entropy_gen_1.size(), additional_input_1.begin(), additional_input_1.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, entropy_gen_1, additional_input_1) == boost::crypt::state::success); // ** GENERATE (FIRST CALL): // V = 5175a69940d5ffd54c444fbf42716d910785b4eb11d26b2254ee5784295a8b21e61d38c7e7fde8353b7a0be7a13a9fb3e699e902574eb9 // C = 2d6bf03f0da8e4d4f3c0648bae0b9be4911cf870ca8789a16886a9b9fe64338012b6feae2c889cc78553c2a6a7c9829b32a57316e14042 - BOOST_TEST(rng.generate(return_bits.begin(), 640U, entropy_gen_2.begin(), entropy_gen_2.size(), additional_input_2.begin(), additional_input_2.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, entropy_gen_2, additional_input_2) == boost::crypt::state::success); // ** GENERATE (SECOND CALL): // V = c35d4a033e2541a93e3e7ff5840f30f90a99775273cea47d3c16280bd36655e9314f15c43df89cd668dd79385287de9b87e5577e623354 // C = 9767cd1c4a51fc33f046e281aa2c5c98b116364638f46271951c38db1d246eadc92b977b0643183c39ae95184e2f147f9c8b7f5d6158d5 - constexpr boost::crypt::array nist_return = { + constexpr std::array nist_return = { 0x1f, 0x07, 0x77, 0x2a, 0x46, 0x66, 0x2b, 0x37, 0x50, 0xe3, 0x9b, 0x31, 0x91, 0xfa, 0x74, 0xc8, 0x35, 0x4f, 0x9d, 0x7e, 0xae, 0xa5, 0x6b, 0xa0, 0xd2, 0x92, 0x72, 0xd0, 0x71, 0xef, @@ -337,14 +333,14 @@ void sha1_additional_gen_input() 0x51, 0x59, 0xbc, 0x8e, 0xa3, 0xa6, 0xdb, 0x12, 0x15, 0xab }; - for (boost::crypt::size_t i {}; i < return_bits.size(); ++i) + for (std::size_t i {}; i < return_bits.size(); ++i) { if (!BOOST_TEST_EQ(return_bits[i], nist_return[i])) { // LCOV_EXCL_START std::cerr << std::hex - << "Got: " << static_cast(return_bits[i]) - << "\nExpected: " << static_cast(nist_return[i]) << std::endl; + << "Got: " << static_cast(return_bits[i]) + << "\nExpected: " << static_cast(nist_return[i]) << std::endl; // LCOV_EXCL_STOP } } @@ -354,23 +350,23 @@ void sha1_no_reseed_additional_input() { boost::crypt::sha1_hash_drbg rng; - constexpr boost::crypt::array entropy = { + constexpr std::array entropy = { 0xc3, 0xef, 0x82, 0xce, 0x24, 0x1f, 0x02, 0xe4, 0x29, 0x8b, 0x11, 0x8c, 0xa4, 0xf1, 0x62, 0x25 }; - constexpr boost::crypt::array nonce = { + constexpr std::array nonce = { 0x15, 0xe3, 0x2a, 0xbb, 0xae, 0x6b, 0x74, 0x33 }; - constexpr boost::crypt::array additional_input_1 = { + constexpr std::array additional_input_1 = { 0x2b, 0x79, 0x00, 0x52, 0xf0, 0x9b, 0x36, 0x4d, 0x4a, 0x82, 0x67, 0xa0, 0xa7, 0xde, 0x63, 0xb8 }; - constexpr boost::crypt::array additional_input_2 = { + constexpr std::array additional_input_2 = { 0x2e, 0xe0, 0x81, 0x9a, 0x67, 0x1d, 0x07, 0xb5, 0x08, 0x5c, 0xc4, 0x6a, 0xa0, 0xe6, 0x1b, 0x56 }; - boost::crypt::array return_bits {}; + std::array return_bits {}; // Test process is: // 1) Instantiate drbg @@ -382,17 +378,17 @@ void sha1_no_reseed_additional_input() // V = 062e928dbf6ef8f7b57467a2a956f4754b094b5f5a9515fe0059a35d449b74485eac06f0671eaa6ec313fc52da015f69b18cc670d9e89a // C = 0fb2fcface8fe5876199565b26d3db365037da40291d67915426959d90c8beba18e3dd1961b48a1ac62b0150cdefa5dc077daf27b4cf3e - BOOST_TEST(rng.generate(return_bits.begin(), 640U, additional_input_1.begin(), additional_input_1.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, additional_input_1) == boost::crypt::state::success); // ** GENERATE (FIRST CALL): // V = 15e18f888dfede7f170dbdfdd02acfab9b41259f83b27d8f548038fad5643302778fe466a1b0a63b22b39b4c59a4b7f151bec718d08a16 // C = 0fb2fcface8fe5876199565b26d3db365037da40291d67915426959d90c8beba18e3dd1961b48a1ac62b0150cdefa5dc077daf27b4cf3e - BOOST_TEST(rng.generate(return_bits.begin(), 640U, additional_input_2.begin(), additional_input_2.size()) == boost::crypt::state::success); + BOOST_TEST(rng.generate(return_bits, 640U, additional_input_2) == boost::crypt::state::success); // ** GENERATE (SECOND CALL): // V = 25948c835c8ec40678a71458f6feaae1eb78ffdfaccfe520a8a6ce98662cf1bc9073c28d8664f953ae0352e0b5a7ecc5577d08a0babfc3 // C = 0fb2fcface8fe5876199565b26d3db365037da40291d67915426959d90c8beba18e3dd1961b48a1ac62b0150cdefa5dc077daf27b4cf3e - constexpr boost::crypt::array nist_return = { + constexpr std::array nist_return = { 0x58, 0x25, 0xfa, 0x1d, 0x1d, 0xc3, 0x3c, 0x64, 0xcd, 0xc8, 0x69, 0x06, 0x82, 0xef, 0xf0, 0x60, 0x39, 0xe7, 0x95, 0x08, 0xc3, 0xaf, 0x48, 0xe8, 0x80, 0xf8, 0x22, 0x7d, 0x5f, 0x9a, @@ -403,147 +399,19 @@ void sha1_no_reseed_additional_input() 0x77, 0xea, 0xb3, 0x23, 0x9c, 0x94, 0xeb, 0xe3, 0xf7, 0xfa }; - for (boost::crypt::size_t i {}; i < return_bits.size(); ++i) + for (std::size_t i {}; i < return_bits.size(); ++i) { if (!BOOST_TEST_EQ(return_bits[i], nist_return[i])) { // LCOV_EXCL_START std::cerr << std::hex - << "Got: " << static_cast(return_bits[i]) - << "\nExpected: " << static_cast(nist_return[i]) << std::endl; + << "Got: " << static_cast(return_bits[i]) + << "\nExpected: " << static_cast(nist_return[i]) << std::endl; // LCOV_EXCL_STOP } } } -void sha256_no_reseed_additional_input() -{ - boost::crypt::sha256_hash_drbg rng; - - constexpr boost::crypt::array entropy = { - 0xe9, 0x04, 0xf1, 0x70, 0xa6, 0xbc, 0x1f, 0xb6, - 0x58, 0xf6, 0xbd, 0x0a, 0xe5, 0xb3, 0xb7, 0x5a, - 0xff, 0x1c, 0x72, 0x77, 0xfb, 0xf5, 0x76, 0x24, - 0x72, 0x26, 0x25, 0x0f, 0xb2, 0x34, 0x24, 0xe3 - }; - - constexpr boost::crypt::array nonce = { - 0x32, 0x3f, 0xcc, 0xd0, 0xc9, 0xed, 0xaf, 0x32, - 0x5e, 0x38, 0xaa, 0x78, 0x9f, 0x3c, 0x01, 0x72 - }; - - constexpr boost::crypt::array additional_input_1 = { - 0xa5, 0xc2, 0x57, 0xbb, 0xa6, 0x41, 0x85, 0x64, - 0x85, 0x89, 0x90, 0xb1, 0xcd, 0xcd, 0xa3, 0x4f, - 0x79, 0xb4, 0x8d, 0x2a, 0xc3, 0xeb, 0xe2, 0x5e, - 0x23, 0x21, 0x95, 0x42, 0x56, 0x69, 0x81, 0xb1 - }; - - constexpr boost::crypt::array additional_input_2 = { - 0x4c, 0x91, 0xb2, 0xf0, 0xe1, 0x77, 0x26, 0xb6, - 0x53, 0xe4, 0xb1, 0x42, 0xb4, 0xa3, 0x19, 0xec, - 0x95, 0x2f, 0xe4, 0xd2, 0xb7, 0x1d, 0xe3, 0x1f, - 0xf1, 0x44, 0x60, 0xc3, 0xf4, 0xf5, 0x59, 0x91 - }; - - boost::crypt::array return_bits {}; - - // Test process is: - // 1) Instantiate drbg - // 2) Generate bits, do not compare - // 3) Generate bits, compare - // 4) Destroy drbg - BOOST_TEST(rng.init(entropy, nonce) == boost::crypt::state::success); - // ** INSTANTIATE: - // V = 79c9006c01bc4a73d23f1d3404ac08c7df25b755de5d6ef94b16383dc057f10f05676d98c9a160c7ea7d66c51bdae736391b3a9dc3c486 - // C = c5077efae1e97cd10e4d1c1a562f8adb3e39e97b5c288f21932244c0164a1d81bff0d608a47c4306c55cad02bc9a36e12d97c1dbf5f5c9 - - constexpr boost::crypt::array v1 = { - 0x79, 0xc9, 0x00, 0x6c, 0x01, 0xbc, 0x4a, 0x73, 0xd2, 0x3f, 0x1d, - 0x34, 0x04, 0xac, 0x08, 0xc7, 0xdf, 0x25, 0xb7, 0x55, 0xde, 0x5d, - 0x6e, 0xf9, 0x4b, 0x16, 0x38, 0x3d, 0xc0, 0x57, 0xf1, 0x0f, 0x05, - 0x67, 0x6d, 0x98, 0xc9, 0xa1, 0x60, 0xc7, 0xea, 0x7d, 0x66, 0xc5, - 0x1b, 0xda, 0xe7, 0x36, 0x39, 0x1b, 0x3a, 0x9d, 0xc3, 0xc4, 0x86 - }; - - constexpr boost::crypt::array c1 = { - 0xc5, 0x07, 0x7e, 0xfa, 0xe1, 0xe9, 0x7c, 0xd1, 0x0e, 0x4d, 0x1c, - 0x1a, 0x56, 0x2f, 0x8a, 0xdb, 0x3e, 0x39, 0xe9, 0x7b, 0x5c, 0x28, - 0x8f, 0x21, 0x93, 0x22, 0x44, 0xc0, 0x16, 0x4a, 0x1d, 0x81, 0xbf, - 0xf0, 0xd6, 0x08, 0xa4, 0x7c, 0x43, 0x06, 0xc5, 0x5c, 0xad, 0x02, - 0xbc, 0x9a, 0x36, 0xe1, 0x2d, 0x97, 0xc1, 0xdb, 0xf5, 0xf5, 0xc9 - }; - - BOOST_TEST(v1 == rng.get_v()); - BOOST_TEST(c1 == rng.get_c()); - - BOOST_TEST(rng.generate(return_bits.begin(), 1024U, additional_input_1.begin(), additional_input_1.size()) == boost::crypt::state::success); - // ** GENERATE (FIRST CALL): - // V = 3ed07f66e3a5c744e08c394e5adb93a31d5fa0d13a85ff2d8cfb3d2c6144ed1ff4e228639db8b107d2d0115b446166ec87fb1134c84267 - // C = c5077efae1e97cd10e4d1c1a562f8adb3e39e97b5c288f21932244c0164a1d81bff0d608a47c4306c55cad02bc9a36e12d97c1dbf5f5c9 - - constexpr boost::crypt::array v2 = { - 0x3e, 0xd0, 0x7f, 0x66, 0xe3, 0xa5, 0xc7, 0x44, 0xe0, 0x8c, 0x39, - 0x4e, 0x5a, 0xdb, 0x93, 0xa3, 0x1d, 0x5f, 0xa0, 0xd1, 0x3a, 0x85, - 0xff, 0x2d, 0x8c, 0xfb, 0x3d, 0x2c, 0x61, 0x44, 0xed, 0x1f, 0xf4, - 0xe2, 0x28, 0x63, 0x9d, 0xb8, 0xb1, 0x07, 0xd2, 0xd0, 0x11, 0x5b, - 0x44, 0x61, 0x66, 0xec, 0x87, 0xfb, 0x11, 0x34, 0xc8, 0x42, 0x67 - }; - - constexpr boost::crypt::array c2 = { - 0xc5, 0x07, 0x7e, 0xfa, 0xe1, 0xe9, 0x7c, 0xd1, 0x0e, 0x4d, 0x1c, - 0x1a, 0x56, 0x2f, 0x8a, 0xdb, 0x3e, 0x39, 0xe9, 0x7b, 0x5c, 0x28, - 0x8f, 0x21, 0x93, 0x22, 0x44, 0xc0, 0x16, 0x4a, 0x1d, 0x81, 0xbf, - 0xf0, 0xd6, 0x08, 0xa4, 0x7c, 0x43, 0x06, 0xc5, 0x5c, 0xad, 0x02, - 0xbc, 0x9a, 0x36, 0xe1, 0x2d, 0x97, 0xc1, 0xdb, 0xf5, 0xf5, 0xc9 - }; - - BOOST_TEST(v2 == rng.get_v()); - BOOST_TEST(c2 == rng.get_c()); - - BOOST_TEST(rng.generate(return_bits.begin(), 1024U, additional_input_2.begin(), additional_input_2.size()) == boost::crypt::state::success); - // ** GENERATE (SECOND CALL): - // V = 03d7fe61c58f4415eed95568b10b1e7e5b998a4c96ae8ff112c0a730b5e58c3978b2f790333bd2bc1d59799949720389923234e500f663 - // C = c5077efae1e97cd10e4d1c1a562f8adb3e39e97b5c288f21932244c0164a1d81bff0d608a47c4306c55cad02bc9a36e12d97c1dbf5f5c9 - - constexpr boost::crypt::array v3 = { - 0x03, 0xd7, 0xfe, 0x61, 0xc5, 0x8f, 0x44, 0x15, 0xee, 0xd9, 0x55, - 0x68, 0xb1, 0x0b, 0x1e, 0x7e, 0x5b, 0x99, 0x8a, 0x4c, 0x96, 0xae, - 0x8f, 0xf1, 0x12, 0xc0, 0xa7, 0x30, 0xb5, 0xe5, 0x8c, 0x39, 0x78, - 0xb2, 0xf7, 0x90, 0x33, 0x3b, 0xd2, 0xbc, 0x1d, 0x59, 0x79, 0x99, - 0x49, 0x72, 0x03, 0x89, 0x92, 0x32, 0x34, 0xe5, 0x00, 0xf6, 0x63 - }; - - constexpr boost::crypt::array c3 = { - 0xc5, 0x07, 0x7e, 0xfa, 0xe1, 0xe9, 0x7c, 0xd1, 0x0e, 0x4d, 0x1c, - 0x1a, 0x56, 0x2f, 0x8a, 0xdb, 0x3e, 0x39, 0xe9, 0x7b, 0x5c, 0x28, - 0x8f, 0x21, 0x93, 0x22, 0x44, 0xc0, 0x16, 0x4a, 0x1d, 0x81, 0xbf, - 0xf0, 0xd6, 0x08, 0xa4, 0x7c, 0x43, 0x06, 0xc5, 0x5c, 0xad, 0x02, - 0xbc, 0x9a, 0x36, 0xe1, 0x2d, 0x97, 0xc1, 0xdb, 0xf5, 0xf5, 0xc9 - }; - - BOOST_TEST(v3 == rng.get_v()); - BOOST_TEST(c3 == rng.get_c()); - - constexpr boost::crypt::array nist_return = { - 0x43, 0x34, 0xec, 0x67, 0x2d, 0x6a, 0x9c, 0x69, 0xa5, 0x20, 0x31, 0x26, - 0xa9, 0xdb, 0x2c, 0xe3, 0x5e, 0x19, 0xec, 0x0a, 0x4a, 0xc3, 0xc0, 0x71, - 0x30, 0x62, 0x79, 0x2a, 0x8c, 0x0a, 0x16, 0x93, 0x4b, 0x8e, 0xd8, 0x5d, - 0xf8, 0x08, 0x90, 0x55, 0x02, 0x65, 0x61, 0x46, 0x25, 0xa5, 0x14, 0x5e, - 0xac, 0xc2, 0x0d, 0xf8, 0x13, 0x70, 0x46, 0xb5, 0x3f, 0xf4, 0xfb, 0xbf, - 0x9d, 0x50, 0x60, 0x7c, 0x73, 0x1e, 0x3b, 0x82, 0xa4, 0x1a, 0x1b, 0x74, - 0xc8, 0xab, 0x25, 0xf5, 0x4a, 0x19, 0x55, 0x10, 0x5a, 0xae, 0xda, 0xcc, - 0x5d, 0x77, 0x59, 0xa8, 0xb6, 0x0a, 0x70, 0x62, 0x3a, 0x37, 0xf4, 0xde, - 0x7c, 0x18, 0xc7, 0x60, 0x5e, 0x99, 0xe3, 0xf5, 0x32, 0xad, 0x8c, 0x27, - 0x7a, 0x7f, 0xc4, 0x4d, 0xd3, 0x8d, 0xe2, 0xca, 0xec, 0x60, 0x31, 0x0e, - 0xf7, 0xf1, 0x54, 0x4e, 0x34, 0xa4, 0x9b, 0xca - }; - - BOOST_TEST(nist_return == return_bits); - - rng.destroy(); -} - int main() { sha_1_basic_correctness(); @@ -553,8 +421,5 @@ int main() sha1_additional_gen_input(); sha1_no_reseed_additional_input(); - // Previous failures - sha256_no_reseed_additional_input(); - return boost::report_errors(); } From 4813283e17595f8e07050b4453dc7d1edea38f82 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 3 Feb 2025 17:11:04 -0500 Subject: [PATCH 16/25] Correct const --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 71053913..f2a6f625 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -58,9 +58,9 @@ class hash_drbg BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_df(compat::uint32_t no_of_bits_to_return, compat::span return_container, compat::span provided_data_1, - compat::span provided_data_2, - compat::span provided_data_3, - compat::span provided_data_4) noexcept -> state; + compat::span provided_data_2 = compat::span {}, + compat::span provided_data_3 = compat::span {}, + compat::span provided_data_4 = compat::span {}) noexcept -> state; template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hashgen(compat::span returned_bits, compat::size_t requested_number_of_bytes) noexcept -> state; @@ -85,9 +85,9 @@ class hash_drbg template - BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto init(compat::span entropy, - compat::span nonce = compat::span{}, - compat::span personalization = compat::span{}) noexcept -> state; + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto init(compat::span entropy, + compat::span nonce = compat::span{}, + compat::span personalization = compat::span{}) noexcept -> state; template @@ -264,16 +266,17 @@ template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::init( - compat::span entropy, - compat::span nonce, - compat::span personalization) noexcept -> state + compat::span entropy, + compat::span nonce, + compat::span personalization) noexcept -> state { if (entropy.size() + nonce.size() < min_entropy) { return state::insufficient_entropy; } - auto seed_status {hash_df(seedlen, entropy, nonce, personalization)}; + auto writeable_value_span {compat::span(value_)}; + auto seed_status {hash_df(seedlen, writeable_value_span, entropy, nonce, personalization)}; if (seed_status != state::success) [[unlikely]] { @@ -282,7 +285,8 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg offset_array {compat::byte {0x00}}; const compat::span offset_span {offset_array}; - seed_status = hash_df(seedlen, constant_span_, offset_span, value_span_); + auto writeable_constant_span {compat::span(constant_)}; + seed_status = hash_df(seedlen, writeable_constant_span, offset_span, value_span_); if (seed_status != state::success) { From 69200ec651739df051b101486c9c1fa89f822c5d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 4 Feb 2025 10:46:53 -0500 Subject: [PATCH 17/25] Collected fixes for basic correctness test --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 131 ++++++++++-------- 1 file changed, 72 insertions(+), 59 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index f2a6f625..60a733e4 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -216,36 +216,47 @@ hash_drbg::hashg return state::out_of_memory; } - const compat::span value_span {value_}; + auto data {value_}; + const auto data_span {compat::span(data)}; compat::size_t offset {}; HasherType hasher; while (offset < requested_number_of_bytes) { // Step 1: hash the current state of the value array hasher.init(); - [[maybe_unused]] const auto process_bytes_status {hasher.process_bytes(value_span)}; + [[maybe_unused]] const auto process_bytes_status {hasher.process_bytes(data_span)}; BOOST_CRYPT_ASSERT(process_bytes_status == state::success); [[maybe_unused]] const auto finalize_status {hasher.finalize()}; BOOST_CRYPT_ASSERT(finalize_status == state::success); const auto w_expected {hasher.get_digest()}; BOOST_CRYPT_ASSERT(w_expected.has_value()); - // Step 2: Write the output of the hash(value_) for return + // Step 2: Write the output of the hash(data) for return const auto w {w_expected.value()}; - for (compat::size_t i {}; offset < requested_number_of_bytes && i < w.size(); ++i) + if (offset + w.size() <= requested_number_of_bytes) { - returned_bits[offset++] = w[i]; + for (const auto byte : w) + { + returned_bits[offset++] = byte; + } + } + else + { + for (compat::size_t i {}; offset < requested_number_of_bytes && i < w.size(); ++i) + { + returned_bits[offset++] = w[i]; + } } - // Step 3: Increment value_ by 1 modulo 2^seedlen + // Step 3: Increment data by 1 modulo 2^seedlen compat::uint16_t carry {1}; - auto value_position {value_.rbegin()}; + auto data_position {data.rbegin()}; - while (value_position != value_.rend() && carry) + while (carry && data_position != data.rend()) { - const auto sum {static_cast(static_cast(*value_position) + carry)}; + const auto sum {static_cast(static_cast(*data_position) + carry)}; carry = static_cast(sum >> 8U); - *value_position-- = static_cast(sum & 0xFFU); + *data_position++ = static_cast(sum & 0xFFU); } } @@ -431,53 +442,57 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg max_length) - { - return state::input_too_long; // LCOV_EXCL_LINE - } - #endif // 32-bit platforms - - #ifdef __clang__ - # pragma clang diagnostic pop - #endif - - HasherType hasher {}; - hasher.process_byte(compat::byte{0x02}); - hasher.process_bytes(value_span_); - hasher.process_bytes(additional_data); - const auto w_exp {hasher.get_digest()}; - - if (!w_exp.has_value()) [[unlikely]] + if (!additional_data.empty()) { - return w_exp.error(); - } - const auto w {w_exp.value()}; - - // V = (v + w) mode 2^seedlen - auto w_iter {w.crbegin()}; - const auto w_end {w.crend()}; - - auto v_iter {value_.rbegin()}; - const auto v_end {value_.rend()}; - - // Since the size of V depends on the size of w we will never have an overflow situation - compat::uint16_t carry {}; - while (w_iter != w_end && v_iter != v_end) - { - const auto sum {static_cast(static_cast(*w_iter) + static_cast(*v_iter) + carry)}; - carry = static_cast(sum >> 8U); - *v_iter++ = static_cast(sum & 0xFFU); - ++w_iter; + // Step 2.1 and 2.2 + // If we are on a different 32 bit or smaller platform and using clang ignore the warning + #ifdef __clang__ + # pragma clang diagnostic push + # pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" + #endif + + #if !defined(__i386__) && !defined(_M_IX86) + if (additional_data.size() > max_length) + { + return state::input_too_long; // LCOV_EXCL_LINE + } + #endif // 32-bit platforms + + #ifdef __clang__ + # pragma clang diagnostic pop + #endif + + HasherType hasher {}; + hasher.process_byte(compat::byte{0x02}); + hasher.process_bytes(value_span_); + hasher.process_bytes(additional_data); + hasher.finalize(); + const auto w_exp {hasher.get_digest()}; + + if (!w_exp.has_value()) [[unlikely]] + { + return w_exp.error(); + } + const auto w {w_exp.value()}; + + // V = (v + w) mode 2^seedlen + auto w_iter {w.crbegin()}; + const auto w_end {w.crend()}; + + auto v_iter {value_.rbegin()}; + const auto v_end {value_.rend()}; + + // Since the size of V depends on the size of w we will never have an overflow situation + compat::uint16_t carry {}; + while (w_iter != w_end && v_iter != v_end) + { + const auto sum {static_cast(static_cast(*w_iter) + static_cast(*v_iter) + carry)}; + carry = static_cast(sum >> 8U); + *v_iter++ = static_cast(sum & 0xFFU); + ++w_iter; + } } } @@ -492,11 +507,9 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg Date: Tue, 4 Feb 2025 11:28:30 -0500 Subject: [PATCH 18/25] Fixes for PR false test --- include/boost/crypt2/drbg/detail/hash_drbg.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 60a733e4..514c2552 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -98,8 +98,8 @@ class hash_drbg template - BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto reseed(compat::span entropy, - compat::span additional_input = compat::span{}) noexcept -> state; + BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto reseed(compat::span entropy, + compat::span additional_input = compat::span{}) noexcept -> state; template > @@ -350,8 +350,8 @@ template BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg::reseed( - compat::span entropy, - compat::span additional_input) noexcept -> state + compat::span entropy, + compat::span additional_input) noexcept -> state { constexpr auto min_reseed_entropy {max_hasher_security / 8U}; @@ -362,7 +362,7 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg seed {}; compat::span seed_span {seed}; - constexpr compat::array offset_array { compat::byte{0x01} }; + constexpr compat::array offset_array { compat::byte{0x01} }; compat::span offset_array_span {offset_array}; auto seed_status {hash_df(seedlen, @@ -379,11 +379,12 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg c_offset_array { compat::byte{0x00} }; + constexpr compat::array c_offset_array { compat::byte{0x00} }; compat::span c_offset_span {c_offset_array}; + compat::span writeable_constant_span {constant_}; seed_status = hash_df(seedlen, - constant_span_, + writeable_constant_span, c_offset_span, value_span_); From fefe5c9e8810d1dc569c0f9d8212b1efb93553ce Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 4 Feb 2025 11:35:49 -0500 Subject: [PATCH 19/25] Fix carry --- include/boost/crypt2/drbg/detail/hash_drbg.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 514c2552..7658fae1 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -487,12 +487,20 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg(static_cast(*w_iter) + static_cast(*v_iter) + carry)}; carry = static_cast(sum >> 8U); + *v_iter = static_cast(sum & 0xFFU); + } + + // Handle final carry past the end of w + // Since we are to do v = (v+w) mod seedlen we don't concern ourselves past v_end + while (carry && v_iter != v_end) + { + const auto sum {static_cast(static_cast(*v_iter) + carry)}; + carry = static_cast(sum >> 8U); *v_iter++ = static_cast(sum & 0xFFU); - ++w_iter; } } } From 3634069e327d876046445365ca20015a9c39b168 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 4 Feb 2025 13:41:02 -0500 Subject: [PATCH 20/25] Improve coverage --- test/Jamfile | 2 ++ test/test_hash_drbg.cpp | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/test/Jamfile b/test/Jamfile index da90f271..901083c5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -42,6 +42,8 @@ project : requirements clang:-Wthread-safety clang:-Wunused-lambda-capture clang:-Wassign-enum + clang-19:-Wunsafe-buffer-usage + clang-20:-Wunsafe-buffer-usage msvc:on clang:on diff --git a/test/test_hash_drbg.cpp b/test/test_hash_drbg.cpp index 8c2c0934..6c024d14 100644 --- a/test/test_hash_drbg.cpp +++ b/test/test_hash_drbg.cpp @@ -4,7 +4,18 @@ #define BOOST_CRYPT_DEBUG #include + +#if defined(__clang__) && __clang_major__ >= 19 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif + #include + +#if defined(__clang__) && __clang_major__ >= 19 +#pragma clang diagnostic pop +#endif + #include #include @@ -412,6 +423,37 @@ void sha1_no_reseed_additional_input() } } +void sha1_error_cases() +{ + constexpr std::array entropy = { + 0xc3, 0xef, 0x82, 0xce, 0x24, 0x1f, 0x02, 0xe4, 0x29, 0x8b, 0x11, 0x8c, 0xa4, 0xf1, 0x62, 0x25 + }; + + constexpr std::array nonce = { + 0x15, 0xe3, 0x2a, 0xbb, 0xae, 0x6b, 0x74, 0x33 + }; + + constexpr std::array bad_entropy = { + 0xc3, 0xef, 0x82 + }; + + constexpr std::array bad_nonce = { + 0x15 + }; + + std::array bad_return_container {}; + + boost::crypt::sha1_hash_drbg rng; + BOOST_TEST(rng.init(bad_entropy, bad_nonce) == boost::crypt::state::insufficient_entropy); + BOOST_TEST(rng.generate(bad_return_container, 1) == boost::crypt::state::uninitialized); + BOOST_TEST(rng.init(entropy, nonce) == boost::crypt::state::success); + BOOST_TEST(rng.generate(bad_return_container, 1000000U) == boost::crypt::state::requested_too_many_bits); + BOOST_TEST(rng.generate(bad_return_container, 1000) == boost::crypt::state::out_of_memory); + + boost::crypt::sha1_hash_drbg_pr pr_rng; + BOOST_TEST(pr_rng.generate(bad_return_container, 1, entropy, nonce) == boost::crypt::state::uninitialized); +} + int main() { sha_1_basic_correctness(); @@ -420,6 +462,7 @@ int main() sha1_additional_data(); sha1_additional_gen_input(); sha1_no_reseed_additional_input(); + sha1_error_cases(); return boost::report_errors(); } From 9492daa3813fe5add5054d94279cd48f2588b87f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 4 Feb 2025 13:41:22 -0500 Subject: [PATCH 21/25] Adjust conceptual requirements for make_span --- include/boost/crypt2/detail/compat.hpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/include/boost/crypt2/detail/compat.hpp b/include/boost/crypt2/detail/compat.hpp index 413ca9ae..e4b5fe0e 100644 --- a/include/boost/crypt2/detail/compat.hpp +++ b/include/boost/crypt2/detail/compat.hpp @@ -202,7 +202,7 @@ struct is_span> : true_type {}; template inline constexpr bool is_span_v = is_span::value; -template +template BOOST_CRYPT_GPU_ENABLED constexpr auto make_span(R&& r) { if constexpr (is_span_v>) @@ -215,11 +215,22 @@ BOOST_CRYPT_GPU_ENABLED constexpr auto make_span(R&& r) } else { + // Since we know that this is a sized range creating the span should also be safe + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + #if BOOST_CRYPT_HAS_CUDA return cuda::std::span{cuda::std::forward(r).data(), cuda::std::forward(r).size()}; #else return std::span{std::forward(r).data(), std::forward(r).size()}; #endif + + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif } } From 09bc6d4a468e44dd2c70c7c65e33f3409046fac9 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 4 Feb 2025 13:41:31 -0500 Subject: [PATCH 22/25] Improve coverage --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 52 ++++++++----------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 7658fae1..da277daf 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -138,11 +138,11 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg 255U) [[unlikely]] + if (len > 255U) { return state::requested_too_many_bits; } - else if (return_container.size() < no_of_bytes_to_return) [[unlikely]] + else if (return_container.size() < no_of_bytes_to_return) { return state::out_of_memory; } @@ -291,7 +291,7 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg offset_array {compat::byte {0x00}}; @@ -299,9 +299,9 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg(constant_)}; seed_status = hash_df(seedlen, writeable_constant_span, offset_span, value_span_); - if (seed_status != state::success) + if (seed_status != state::success) [[unlikely]] { - return seed_status; + return seed_status; // LCOV_EXCL_LINE } initialized_ = true; @@ -319,31 +319,23 @@ BOOST_CRYPT_GPU_ENABLED auto hash_drbg state { - // First check to see if conversion to spans is even worthwhile - if (entropy.size() + nonce.size() < min_entropy) - { - return state::insufficient_entropy; - } - else - { - #if defined(__clang__) && __clang_major__ >= 19 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" - #endif + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" + #endif - // Since these are sized ranges we can safely convert them into spans - auto entropy_span {compat::make_span(compat::forward(entropy))}; - auto nonce_span {compat::make_span(compat::forward(nonce))}; - auto personalization_span {compat::make_span(compat::forward(personalization))}; + // Since these are sized ranges we can safely convert them into spans + auto entropy_span {compat::make_span(compat::forward(entropy))}; + auto nonce_span {compat::make_span(compat::forward(nonce))}; + auto personalization_span {compat::make_span(compat::forward(personalization))}; - return init(compat::as_bytes(entropy_span), - compat::as_bytes(nonce_span), - compat::as_bytes(personalization_span)); + return init(compat::as_bytes(entropy_span), + compat::as_bytes(nonce_span), + compat::as_bytes(personalization_span)); - #if defined(__clang__) && __clang_major__ >= 19 - #pragma clang diagnostic pop - #endif - } + #if defined(__clang__) && __clang_major__ >= 19 + #pragma clang diagnostic pop + #endif } template @@ -428,7 +420,7 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg return_data, compat::size_t requested_bits, compat::span additional_data) noexcept -> state { - if (reseed_counter_ > reseed_interval) + if (reseed_counter_ > reseed_interval) [[unlikely]] { return state::requires_reseed; } @@ -598,9 +590,9 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg entropy, compat::span additional_data) noexcept -> state { - if (reseed_counter_ > reseed_interval) + if (reseed_counter_ > reseed_interval) [[unlikely]] { - return state::requires_reseed; + return state::requires_reseed; // LCOV_EXCL_LINE } if (!initialized_) { From bebcca0582e46c87d2e3def78cbb39db88acbb0c Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 4 Feb 2025 14:08:05 -0500 Subject: [PATCH 23/25] More coverage --- .../boost/crypt2/drbg/detail/hash_drbg.hpp | 34 +++++++++++-------- test/test_hash_drbg.cpp | 1 + 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index da277daf..19aa0d36 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -138,13 +138,15 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg 255U) + // Neither of these should be possible since this is an internal method, but it's best + // to check in case we messed something else up somewhere + if (len > 255U) [[unlikely]] { - return state::requested_too_many_bits; + return state::requested_too_many_bits; // LCOV_EXCL_LINE } - else if (return_container.size() < no_of_bytes_to_return) + else if (return_container.size() < no_of_bytes_to_return) [[unlikely]] { - return state::out_of_memory; + return state::out_of_memory; // LCOV_EXCL_LINE } // The hash string concatenates the value of no_of_bits_to_return @@ -189,8 +191,12 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg reseed_interval) [[unlikely]] { - return state::requires_reseed; + return state::requires_reseed; // LCOV_EXCL_LINE } if (!initialized_) { @@ -466,7 +472,7 @@ BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto hash_drbg Date: Tue, 4 Feb 2025 12:07:59 -0500 Subject: [PATCH 24/25] Update test harness for new hash drbg implementations --- test/Jamfile | 2 +- test/test_nist_cavs_detail.hpp | 56 +++++++++++++------------- test/test_nist_cavs_sha1_hash_drbg.cpp | 2 +- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/Jamfile b/test/Jamfile index 901083c5..f6f3211c 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -88,7 +88,7 @@ run test_nist_cavs_sha1_monte.cpp ; run test_nist_cavs_sha1_short_long.cpp ; run test_nist_cavs_sha1_hmac.cpp ; #run test_nist_cavs_sha1_hmac_drbg.cpp ; -#run test_nist_cavs_sha1_hash_drbg.cpp ; +run test_nist_cavs_sha1_hash_drbg.cpp ; run test_nist_cavs_sha224_monte.cpp ; run test_nist_cavs_sha224_short_long.cpp ; diff --git a/test/test_nist_cavs_detail.hpp b/test/test_nist_cavs_detail.hpp index 8ecffd75..afb8a018 100644 --- a/test/test_nist_cavs_detail.hpp +++ b/test/test_nist_cavs_detail.hpp @@ -2197,18 +2197,18 @@ auto test_vectors_drbg_no_reseed(const nist::cavs::test_vector_container_drbg_no for (const auto& test_vector : test_vectors) { DRBGType rng; - rng.init(test_vector.initial_entropy.begin(), test_vector.initial_entropy.size(), - test_vector.drbg_nonce.begin(), test_vector.drbg_nonce.size(), - test_vector.personalization_string.begin(), test_vector.personalization_string.size()); + rng.init(test_vector.initial_entropy, + test_vector.drbg_nonce, + test_vector.personalization_string); - std::vector return_bits {}; + std::vector return_bits {}; return_bits.resize(test_vector.result.size()); - rng.generate(return_bits.begin(), return_bits.size() * 8U, - test_vector.additional_input_1.begin(), test_vector.additional_input_1.size()); + rng.generate(return_bits, return_bits.size() * 8U, + test_vector.additional_input_1); - rng.generate(return_bits.begin(), return_bits.size() * 8U, - test_vector.additional_input_2.begin(), test_vector.additional_input_2.size()); + rng.generate(return_bits, return_bits.size() * 8U, + test_vector.additional_input_2); for (std::size_t i {}; i < return_bits.size(); ++i) { @@ -2241,21 +2241,21 @@ auto test_vectors_drbg_pr_false(const nist::cavs::test_vector_container_drbg_pr_ for (const auto& test_vector : test_vectors) { DRBGType rng; - rng.init(test_vector.initial_entropy.begin(), test_vector.initial_entropy.size(), - test_vector.drbg_nonce.begin(), test_vector.drbg_nonce.size(), - test_vector.personalization_string.begin(), test_vector.personalization_string.size()); + rng.init(test_vector.initial_entropy, + test_vector.drbg_nonce, + test_vector.personalization_string); - rng.reseed(test_vector.reseed_entropy.begin(), test_vector.reseed_entropy.size(), - test_vector.reseed_additional_input.begin(), test_vector.reseed_additional_input.size()); + rng.reseed(test_vector.reseed_entropy, + test_vector.reseed_additional_input); - std::vector return_bits {}; + std::vector return_bits {}; return_bits.resize(test_vector.result.size()); - rng.generate(return_bits.begin(), return_bits.size() * 8U, - test_vector.additional_input_1.begin(), test_vector.additional_input_1.size()); + rng.generate(return_bits, return_bits.size() * 8U, + test_vector.additional_input_1); - rng.generate(return_bits.begin(), return_bits.size() * 8U, - test_vector.additional_input_2.begin(), test_vector.additional_input_2.size()); + rng.generate(return_bits, return_bits.size() * 8U, + test_vector.additional_input_2); for (std::size_t i {}; i < return_bits.size(); ++i) { @@ -2288,20 +2288,20 @@ auto test_vectors_drbg_pr_true(const nist::cavs::test_vector_container_drbg_pr_t for (const auto& test_vector : test_vectors) { DRBGType rng; - rng.init(test_vector.initial_entropy.begin(), test_vector.initial_entropy.size(), - test_vector.drbg_nonce.begin(), test_vector.drbg_nonce.size(), - test_vector.personalization_string.begin(), test_vector.personalization_string.size()); + rng.init(test_vector.initial_entropy, + test_vector.drbg_nonce, + test_vector.personalization_string); - std::vector return_bits {}; + std::vector return_bits {}; return_bits.resize(test_vector.result.size()); - rng.generate(return_bits.begin(), return_bits.size() * 8U, - test_vector.additional_entropy_1.begin(), test_vector.additional_entropy_1.size(), - test_vector.additional_input_1.begin(), test_vector.additional_input_1.size()); + rng.generate(return_bits, return_bits.size() * 8U, + test_vector.additional_entropy_1, + test_vector.additional_input_1); - rng.generate(return_bits.begin(), return_bits.size() * 8U, - test_vector.additional_entropy_2.begin(), test_vector.additional_entropy_2.size(), - test_vector.additional_input_2.begin(), test_vector.additional_input_2.size()); + rng.generate(return_bits, return_bits.size() * 8U, + test_vector.additional_entropy_2, + test_vector.additional_input_2); for (std::size_t i {}; i < return_bits.size(); ++i) { diff --git a/test/test_nist_cavs_sha1_hash_drbg.cpp b/test/test_nist_cavs_sha1_hash_drbg.cpp index 3a03ebfe..28add420 100644 --- a/test/test_nist_cavs_sha1_hash_drbg.cpp +++ b/test/test_nist_cavs_sha1_hash_drbg.cpp @@ -3,7 +3,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include "test_nist_cavs_detail.hpp" auto main() -> int From 728e70ed424554760c248e4eb71afe3c87b66882 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 4 Feb 2025 14:27:56 -0500 Subject: [PATCH 25/25] Don't allow possible invalid state --- include/boost/crypt2/drbg/detail/hash_drbg.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/crypt2/drbg/detail/hash_drbg.hpp b/include/boost/crypt2/drbg/detail/hash_drbg.hpp index 19aa0d36..889e5e16 100644 --- a/include/boost/crypt2/drbg/detail/hash_drbg.hpp +++ b/include/boost/crypt2/drbg/detail/hash_drbg.hpp @@ -235,7 +235,10 @@ hash_drbg::hashg [[maybe_unused]] const auto finalize_status {hasher.finalize()}; BOOST_CRYPT_ASSERT(finalize_status == state::success); const auto w_expected {hasher.get_digest()}; - BOOST_CRYPT_ASSERT(w_expected.has_value()); + if (!w_expected.has_value()) [[unlikely]] + { + return w_expected.error(); // LCOV_EXCL_LINE + } // Step 2: Write the output of the hash(data) for return const auto w {w_expected.value()};