From 17034d79878d23ba255930cc9685b253a9f949f7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 11 Nov 2024 10:02:54 -0500 Subject: [PATCH 1/6] Delete old state file --- include/boost/crypt/drbg/drbg_state.hpp | 34 ------------------------- 1 file changed, 34 deletions(-) delete mode 100644 include/boost/crypt/drbg/drbg_state.hpp diff --git a/include/boost/crypt/drbg/drbg_state.hpp b/include/boost/crypt/drbg/drbg_state.hpp deleted file mode 100644 index 7f88bc82..00000000 --- a/include/boost/crypt/drbg/drbg_state.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2024 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifndef BOOST_DRBG_DRBG_STATE_HPP -#define BOOST_DRBG_DRBG_STATE_HPP - -#include -#include - -namespace boost { -namespace crypt { -namespace drbg { - -BOOST_CRYPT_EXPORT enum class drbg_state : boost::crypt::uint8_t -{ - success, // No issues - null, // nullptr as parameter - entropy_too_long, // input data exceeded the length specified in a FIPS standard - nonce_too_long, - personalization_too_long, - insufficient_entropy, // Entropy + Nonce length was not at least 3/2 security strength - out_of_memory, // Memory exhaustion reported by a function - requires_reseed, // The number of cycles has exceeded the specified amount - uninitialized, // Random bits can not be provided since the generator is uninitialized - requested_too_many_bits, // 2^19 bits is all that's allowed per request - state_error // An error has occurred -}; - -} // namespace drbg -} // namespace crypt -} // namespace boost - -#endif // BOOST_DRBG_DRBG_STATE_HPP From 32f2931f6008253dc95c8574e8787aa94a8ac044 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 11 Nov 2024 11:14:45 -0500 Subject: [PATCH 2/6] Refactor generation --- include/boost/crypt/drbg/hmac_drbg.hpp | 49 +++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/include/boost/crypt/drbg/hmac_drbg.hpp b/include/boost/crypt/drbg/hmac_drbg.hpp index d6033b7c..de6cb07b 100644 --- a/include/boost/crypt/drbg/hmac_drbg.hpp +++ b/include/boost/crypt/drbg/hmac_drbg.hpp @@ -64,6 +64,19 @@ class hmac_drbg template BOOST_CRYPT_GPU_ENABLED inline auto update(ForwardIter provided_data, boost::crypt::size_t size) noexcept -> state; + template + BOOST_CRYPT_GPU_ENABLED inline auto generate_impl(const boost::crypt::false_type&, + ForwardIter1 data, boost::crypt::size_t requested_bits, + ForwardIter2 additional_data = nullptr, boost::crypt::size_t additional_data_size = 0, + ForwardIter3 additional_data_2 = nullptr, boost::crypt::size_t additional_data_2_size = 0) noexcept -> state; + + // Provides prediction resistance + template + BOOST_CRYPT_GPU_ENABLED inline auto generate_impl(const boost::crypt::true_type&, + ForwardIter1 data, boost::crypt::size_t requested_bits, + ForwardIter2 entropy, boost::crypt::size_t entropy_size, + ForwardIter3 additional_data = nullptr, boost::crypt::size_t additional_data_size = 0) noexcept -> state; + public: BOOST_CRYPT_GPU_ENABLED constexpr hmac_drbg() = default; @@ -77,11 +90,24 @@ class hmac_drbg BOOST_CRYPT_GPU_ENABLED inline auto reseed(ForwardIter1 entropy, boost::crypt::size_t entropy_size, ForwardIter2 additional_input = nullptr, boost::crypt::size_t additional_input_size = 0) noexcept -> state; - template = true> + template BOOST_CRYPT_GPU_ENABLED inline auto generate(ForwardIter1 data, boost::crypt::size_t requested_bits, - ForwardIter2 additional_data = nullptr, boost::crypt::size_t additional_data_size = 0) noexcept -> state; + ForwardIter2 additional_data_1 = nullptr, boost::crypt::size_t additional_data_1_size = 0, + ForwardIter3 additional_data_2 = nullptr, boost::crypt::size_t additional_data_2_size = 0) noexcept -> state; + }; +template +template +auto hmac_drbg::generate( + ForwardIter1 data, boost::crypt::size_t requested_bits, + ForwardIter2 additional_data_1, boost::crypt::size_t additional_data_1_size, + ForwardIter3 additional_data_2, boost::crypt::size_t additional_data_2_size) noexcept -> state +{ + using impl_type = boost::crypt::integral_constant; + return generate_impl(impl_type(), data, requested_bits, additional_data_1, additional_data_1_size, additional_data_2, additional_data_2_size); +} + template template auto hmac_drbg::update_impl( @@ -397,10 +423,12 @@ auto hmac_drbg::re } template -template > -auto hmac_drbg::generate( +template +auto hmac_drbg::generate_impl( + const boost::crypt::false_type&, ForwardIter1 data, boost::crypt::size_t requested_bits, - ForwardIter2 additional_data, boost::crypt::size_t additional_data_size) noexcept -> state + ForwardIter2 additional_data, boost::crypt::size_t additional_data_size, + ForwardIter3, boost::crypt::size_t) noexcept -> state { if (reseed_counter_ > reseed_interval) { @@ -467,6 +495,17 @@ auto hmac_drbg::ge return state::success; } +template +template +auto hmac_drbg::generate_impl( + const boost::crypt::true_type&, + ForwardIter1 data, boost::crypt::size_t requested_bits, + ForwardIter2 entropy, boost::crypt::size_t entropy_size, + ForwardIter3 additional_data, boost::crypt::size_t additional_data_size) noexcept -> state +{ + return state::state_error; +} + template BOOST_CRYPT_EXPORT using sha1_hmac_drbg_t = drbg::hmac_drbg, 128U, 160U, prediction_resistance>; From d8ae4e5bd80b9ed3e00ef5dacac295971ed12785 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 11 Nov 2024 11:56:44 -0500 Subject: [PATCH 3/6] Add implementation of prediction resistant generation --- include/boost/crypt/drbg/hmac_drbg.hpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/boost/crypt/drbg/hmac_drbg.hpp b/include/boost/crypt/drbg/hmac_drbg.hpp index de6cb07b..d2f2bc7c 100644 --- a/include/boost/crypt/drbg/hmac_drbg.hpp +++ b/include/boost/crypt/drbg/hmac_drbg.hpp @@ -503,7 +503,27 @@ auto hmac_drbg::ge ForwardIter2 entropy, boost::crypt::size_t entropy_size, ForwardIter3 additional_data, boost::crypt::size_t additional_data_size) noexcept -> state { - return state::state_error; + if (reseed_counter_ > reseed_interval) + { + return state::requires_reseed; + } + if (utility::is_null(data) || utility::is_null(entropy)) + { + return state::null; + } + 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, entropy_size, additional_data, additional_data_size)}; + if (reseed_return != state::success) + { + return reseed_return; + } + + return generate_impl(boost::crypt::false_type(), data, requested_bits); } template From cd8bc3991de2e4d6c5f2c5e6f691d4c5dc0d9d81 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 11 Nov 2024 13:03:18 -0500 Subject: [PATCH 4/6] Add basic prediction resistant test --- test/test_hmac_drbg.cpp | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/test_hmac_drbg.cpp b/test/test_hmac_drbg.cpp index 88c35e09..1f719f82 100644 --- a/test/test_hmac_drbg.cpp +++ b/test/test_hmac_drbg.cpp @@ -129,10 +129,61 @@ void sha1_additional_input() } } +void sha1_pr() +{ + boost::crypt::sha1_hmac_drbg_pr rng; + constexpr boost::crypt::array entropy = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, 0xf7, 0x3e, 0x9c, 0x5b + }; + constexpr boost::crypt::array nonce = { + 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11 + }; + + constexpr boost::crypt::array entropy_gen_1 = { + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, 0x17, 0x60, 0x99, 0xd4 + }; + + constexpr boost::crypt::array entropy_gen_2 = { + 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 + }; + + constexpr boost::crypt::array nist_return = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, + 0xb1, 0x39, 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, + 0x0d, 0x3c, 0x1e, 0x94, 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, + 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, 0x73, 0x19, 0x70, 0xc0, + 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, 0x4b, 0xc6, + 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, + 0xee, 0xf3, 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 + }; + + boost::crypt::array return_bits {}; + + BOOST_TEST(rng.init(entropy, entropy.size(), nonce, nonce.size()) == boost::crypt::state::success); + + 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.begin(), 640U, entropy_gen_2.begin(), entropy_gen_2.size()) == boost::crypt::state::success); + + for (boost::crypt::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; + // LCOV_EXCL_STOP + } + } +} + int main() { sha1_basic_correctness(); sha1_additional_input(); + sha1_pr(); return boost::report_errors(); } From 375acff0d47a7771c09712b0273f03d9b9a0334e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 11 Nov 2024 13:41:44 -0500 Subject: [PATCH 5/6] Ignore GCC array bounds warning --- include/boost/crypt/drbg/hmac_drbg.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/boost/crypt/drbg/hmac_drbg.hpp b/include/boost/crypt/drbg/hmac_drbg.hpp index d2f2bc7c..edf4b396 100644 --- a/include/boost/crypt/drbg/hmac_drbg.hpp +++ b/include/boost/crypt/drbg/hmac_drbg.hpp @@ -117,6 +117,13 @@ auto hmac_drbg::up BOOST_CRYPT_ASSERT(value_.size() + 1U + provided_data_size <= storage_size); static_cast(storage_size); + // GCC optimizes this to memcpy (like it should), + // but then complains about theoretical array boundaries (provided_data_size can be 0) + #if defined(__GNUC__) && __GNUC__ >= 5 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds=" + #endif + // Step 1: V || 0x00 || provided data boost::crypt::size_t offset {}; for (boost::crypt::size_t i {}; i < value_.size(); ++i) @@ -129,6 +136,10 @@ auto hmac_drbg::up storage[offset++] = static_cast(provided_data[i]); } + #if defined(__GNUC__) && __GNUC__ >= 5 + #pragma GCC diagnostic pop + #endif + HMACType hmac(key_); hmac.process_bytes(storage, offset); key_ = hmac.get_digest(); From 41b06d751a575ba98548a2f35da8f9957f637efb Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 11 Nov 2024 14:36:21 -0500 Subject: [PATCH 6/6] Add additional warning --- include/boost/crypt/drbg/hmac_drbg.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/crypt/drbg/hmac_drbg.hpp b/include/boost/crypt/drbg/hmac_drbg.hpp index edf4b396..06a367c8 100644 --- a/include/boost/crypt/drbg/hmac_drbg.hpp +++ b/include/boost/crypt/drbg/hmac_drbg.hpp @@ -122,6 +122,7 @@ auto hmac_drbg::up #if defined(__GNUC__) && __GNUC__ >= 5 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Warray-bounds=" + #pragma GCC diagnostic ignored "-Wrestrict" #endif // Step 1: V || 0x00 || provided data