@@ -64,6 +64,19 @@ class hmac_drbg
64
64
template <typename ForwardIter>
65
65
BOOST_CRYPT_GPU_ENABLED inline auto update (ForwardIter provided_data, boost::crypt::size_t size) noexcept -> state;
66
66
67
+ template <typename ForwardIter1, typename ForwardIter2 = const boost::crypt::uint8_t *, typename ForwardIter3 = const boost::crypt::uint8_t *>
68
+ BOOST_CRYPT_GPU_ENABLED inline auto generate_impl (const boost::crypt::false_type&,
69
+ ForwardIter1 data, boost::crypt::size_t requested_bits,
70
+ ForwardIter2 additional_data = nullptr , boost::crypt::size_t additional_data_size = 0 ,
71
+ ForwardIter3 additional_data_2 = nullptr , boost::crypt::size_t additional_data_2_size = 0 ) noexcept -> state;
72
+
73
+ // Provides prediction resistance
74
+ template <typename ForwardIter1, typename ForwardIter2, typename ForwardIter3 = const boost::crypt::uint8_t *>
75
+ BOOST_CRYPT_GPU_ENABLED inline auto generate_impl (const boost::crypt::true_type&,
76
+ ForwardIter1 data, boost::crypt::size_t requested_bits,
77
+ ForwardIter2 entropy, boost::crypt::size_t entropy_size,
78
+ ForwardIter3 additional_data = nullptr , boost::crypt::size_t additional_data_size = 0 ) noexcept -> state;
79
+
67
80
public:
68
81
69
82
BOOST_CRYPT_GPU_ENABLED constexpr hmac_drbg () = default;
@@ -77,11 +90,24 @@ class hmac_drbg
77
90
BOOST_CRYPT_GPU_ENABLED inline auto reseed (ForwardIter1 entropy, boost::crypt::size_t entropy_size,
78
91
ForwardIter2 additional_input = nullptr , boost::crypt::size_t additional_input_size = 0 ) noexcept -> state;
79
92
80
- template <typename ForwardIter1, typename ForwardIter2 = const boost::crypt::uint8_t *, boost::crypt::enable_if_t <!prediction_resistance, bool > = true >
93
+ template <typename ForwardIter1, typename ForwardIter2 = const boost::crypt::uint8_t *, typename ForwardIter3 = const boost::crypt::uint8_t * >
81
94
BOOST_CRYPT_GPU_ENABLED inline auto generate (ForwardIter1 data, boost::crypt::size_t requested_bits,
82
- ForwardIter2 additional_data = nullptr , boost::crypt::size_t additional_data_size = 0 ) noexcept -> state;
95
+ ForwardIter2 additional_data_1 = nullptr , boost::crypt::size_t additional_data_1_size = 0 ,
96
+ ForwardIter3 additional_data_2 = nullptr , boost::crypt::size_t additional_data_2_size = 0 ) noexcept -> state;
97
+
83
98
};
84
99
100
+ template <typename HMACType, boost::crypt::size_t max_hasher_security, boost::crypt::size_t outlen, bool prediction_resistance>
101
+ template <typename ForwardIter1, typename ForwardIter2, typename ForwardIter3>
102
+ auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::generate(
103
+ ForwardIter1 data, boost::crypt::size_t requested_bits,
104
+ ForwardIter2 additional_data_1, boost::crypt::size_t additional_data_1_size,
105
+ ForwardIter3 additional_data_2, boost::crypt::size_t additional_data_2_size) noexcept -> state
106
+ {
107
+ using impl_type = boost::crypt::integral_constant<bool , prediction_resistance>;
108
+ return generate_impl (impl_type (), data, requested_bits, additional_data_1, additional_data_1_size, additional_data_2, additional_data_2_size);
109
+ }
110
+
85
111
template <typename HMACType, boost::crypt::size_t max_hasher_security, boost::crypt::size_t outlen, bool prediction_resistance>
86
112
template <typename ForwardIter1, typename ForwardIter2>
87
113
auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::update_impl(
@@ -91,6 +117,14 @@ auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::up
91
117
BOOST_CRYPT_ASSERT (value_.size () + 1U + provided_data_size <= storage_size);
92
118
static_cast <void >(storage_size);
93
119
120
+ // GCC optimizes this to memcpy (like it should),
121
+ // but then complains about theoretical array boundaries (provided_data_size can be 0)
122
+ #if defined(__GNUC__) && __GNUC__ >= 5
123
+ #pragma GCC diagnostic push
124
+ #pragma GCC diagnostic ignored "-Warray-bounds="
125
+ #pragma GCC diagnostic ignored "-Wrestrict"
126
+ #endif
127
+
94
128
// Step 1: V || 0x00 || provided data
95
129
boost::crypt::size_t offset {};
96
130
for (boost::crypt::size_t i {}; i < value_.size (); ++i)
@@ -103,6 +137,10 @@ auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::up
103
137
storage[offset++] = static_cast <boost::crypt::uint8_t >(provided_data[i]);
104
138
}
105
139
140
+ #if defined(__GNUC__) && __GNUC__ >= 5
141
+ #pragma GCC diagnostic pop
142
+ #endif
143
+
106
144
HMACType hmac (key_);
107
145
hmac.process_bytes (storage, offset);
108
146
key_ = hmac.get_digest ();
@@ -397,10 +435,12 @@ auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::re
397
435
}
398
436
399
437
template <typename HMACType, boost::crypt::size_t max_hasher_security, boost::crypt::size_t outlen, bool prediction_resistance>
400
- template <typename ForwardIter1, typename ForwardIter2, boost::crypt::enable_if_t <!prediction_resistance, bool >>
401
- auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::generate(
438
+ template <typename ForwardIter1, typename ForwardIter2, typename ForwardIter3>
439
+ auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::generate_impl(
440
+ const boost::crypt::false_type&,
402
441
ForwardIter1 data, boost::crypt::size_t requested_bits,
403
- ForwardIter2 additional_data, boost::crypt::size_t additional_data_size) noexcept -> state
442
+ ForwardIter2 additional_data, boost::crypt::size_t additional_data_size,
443
+ ForwardIter3, boost::crypt::size_t ) noexcept -> state
404
444
{
405
445
if (reseed_counter_ > reseed_interval)
406
446
{
@@ -467,6 +507,37 @@ auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::ge
467
507
return state::success;
468
508
}
469
509
510
+ template <typename HMACType, boost::crypt::size_t max_hasher_security, boost::crypt::size_t outlen, bool prediction_resistance>
511
+ template <typename ForwardIter1, typename ForwardIter2, typename ForwardIter3>
512
+ auto hmac_drbg<HMACType, max_hasher_security, outlen, prediction_resistance>::generate_impl(
513
+ const boost::crypt::true_type&,
514
+ ForwardIter1 data, boost::crypt::size_t requested_bits,
515
+ ForwardIter2 entropy, boost::crypt::size_t entropy_size,
516
+ ForwardIter3 additional_data, boost::crypt::size_t additional_data_size) noexcept -> state
517
+ {
518
+ if (reseed_counter_ > reseed_interval)
519
+ {
520
+ return state::requires_reseed;
521
+ }
522
+ if (utility::is_null (data) || utility::is_null (entropy))
523
+ {
524
+ return state::null;
525
+ }
526
+ if (!initialized_)
527
+ {
528
+ return state::uninitialized;
529
+ }
530
+
531
+ // 9.3.3 Reseed using the entropy and the additional data, then set additional data to NULL
532
+ const auto reseed_return {reseed (entropy, entropy_size, additional_data, additional_data_size)};
533
+ if (reseed_return != state::success)
534
+ {
535
+ return reseed_return;
536
+ }
537
+
538
+ return generate_impl (boost::crypt::false_type (), data, requested_bits);
539
+ }
540
+
470
541
template <bool prediction_resistance>
471
542
BOOST_CRYPT_EXPORT using sha1_hmac_drbg_t = drbg::hmac_drbg<hmac<sha1_hasher>, 128U , 160U , prediction_resistance>;
472
543
0 commit comments