Skip to content

Commit 8806ac7

Browse files
committed
Fix native_finalize for non-default digest lengths, impl native qtr opt.
1 parent d68ea96 commit 8806ac7

6 files changed

Lines changed: 88 additions & 37 deletions

File tree

include/bitcoin/system/hash/sha/algorithm.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,17 @@ class algorithm
236236
/// -----------------------------------------------------------------------
237237

238238
INLINE static constexpr void input(buffer_t& buffer, const block_t& block) NOEXCEPT;
239-
INLINE static constexpr void input_left(auto& buffer, const quart_t& quarter) NOEXCEPT;
240-
INLINE static constexpr void input_right(auto& buffer, const quart_t& quarter) NOEXCEPT;
239+
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;
240+
241241
INLINE static constexpr void input_left(auto& buffer, const half_t& half) NOEXCEPT;
242242
INLINE static constexpr void input_right(auto& buffer, const half_t& half) NOEXCEPT;
243-
INLINE static constexpr void inject_left(auto& buffer, const auto& left) NOEXCEPT;
244-
INLINE static constexpr void inject_right(auto& buffer, const auto& right) NOEXCEPT;
245-
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;
243+
INLINE static constexpr void input_left(auto& buffer, const quart_t& quarter) NOEXCEPT;
244+
INLINE static constexpr void input_right(auto& buffer, const quart_t& quarter) NOEXCEPT;
245+
246+
INLINE static constexpr void inject_left_half(auto& buffer, const auto& left) NOEXCEPT;
247+
INLINE static constexpr void inject_right_half(auto& buffer, const auto& right) NOEXCEPT;
248+
INLINE static constexpr void inject_left_quarter(auto& buffer, const auto& left) NOEXCEPT;
249+
INLINE static constexpr void inject_right_quarter(auto& buffer, const auto& right) NOEXCEPT;
246250

247251
/// Padding.
248252
/// -----------------------------------------------------------------------
@@ -409,6 +413,7 @@ class algorithm
409413
static digest_t native_hash(const block_t& block) NOEXCEPT;
410414
static digest_t native_hash(const half_t& half) NOEXCEPT;
411415
static digest_t native_hash(const half_t& left, const half_t& right) NOEXCEPT;
416+
static digest_t native_hash(const quart_t& left, const quart_t& right) NOEXCEPT;
412417
static digest_t native_hash(uint8_t byte) NOEXCEPT;
413418

414419
static digest_t native_double_hash(const block_t& block) NOEXCEPT;

include/bitcoin/system/impl/hash/sha/algorithm_double.ipp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ double_hash(const block_t& block) NOEXCEPT
9595
compress(state, buffer);
9696

9797
// Second hash
98-
inject_left(buffer, state);
98+
inject_left_half(buffer, state);
9999
pad_half(buffer);
100100
schedule(buffer);
101101
state = H::get;
@@ -134,7 +134,7 @@ double_hash(const half_t& half) NOEXCEPT
134134
compress(state, buffer);
135135

136136
// Second hash
137-
inject_left(buffer, state);
137+
inject_left_half(buffer, state);
138138
pad_half(buffer);
139139
schedule(buffer);
140140
state = H::get;
@@ -175,7 +175,7 @@ double_hash(const half_t& left, const half_t& right) NOEXCEPT
175175
compress(state, buffer);
176176

177177
// Second hash
178-
inject_left(buffer, state);
178+
inject_left_half(buffer, state);
179179
pad_half(buffer);
180180
schedule(buffer);
181181
state = H::get;

include/bitcoin/system/impl/hash/sha/algorithm_merkle.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ merkle_hash_vector(idigests_t& digests, iblocks_t& blocks) NOEXCEPT
372372
compress_(xstate, xbuffer);
373373

374374
// Second hash
375-
inject_left(xbuffer, xstate);
375+
inject_left_half(xbuffer, xstate);
376376
pad_half(xbuffer);
377377
schedule_(xbuffer);
378378
xstate = initial;

include/bitcoin/system/impl/hash/sha/algorithm_native.ipp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,10 @@ native_finalize(state_t& state, const words_t& pad) NOEXCEPT
268268
unshuffle(lo, hi);
269269

270270
// digest is copied so that state remains valid (LE).
271-
digest_t digest{};
272-
auto& wdigest = array_cast<xint128_t>(digest);
271+
std::array<xint128_t, 2> wdigest{};
273272
store(wdigest[0], byteswap<uint32_t>(lo));
274273
store(wdigest[1], byteswap<uint32_t>(hi));
275-
return digest;
274+
return array_cast<byte_t, sizeof(digest_t)>(wdigest);
276275
}
277276

278277
TEMPLATE
@@ -285,7 +284,7 @@ native_finalize_second(const state_t& state) NOEXCEPT
285284
// Hash a state value and finalize it.
286285
auto state2 = H::get;
287286
words_t block{};
288-
inject_left(block, state);
287+
inject_left_half(block, state);
289288
pad_half(block);
290289
return native_finalize(state2, block);
291290
}
@@ -300,7 +299,7 @@ native_finalize_double(state_t& state, size_t blocks) NOEXCEPT
300299

301300
// This is native_finalize_second() but reuses the initial block.
302301
auto state2 = H::get;
303-
inject_left(block, state);
302+
inject_left_half(block, state);
304303
pad_half(block);
305304
return native_finalize(state2, block);
306305
}
@@ -338,8 +337,21 @@ native_hash(const half_t& left, const half_t& right) NOEXCEPT
338337
{
339338
auto state = H::get;
340339
words_t block{};
341-
inject_left(block, array_cast<word_t>(left));
342-
inject_right(block, array_cast<word_t>(right));
340+
inject_left_half(block, array_cast<word_t>(left));
341+
inject_right_half(block, array_cast<word_t>(right));
342+
native_transform<true>(state, block);
343+
return native_finalize<one>(state);
344+
}
345+
346+
TEMPLATE
347+
typename CLASS::digest_t CLASS::
348+
native_hash(const quart_t& left, const quart_t& right) NOEXCEPT
349+
{
350+
auto state = H::get;
351+
words_t block{};
352+
inject_left_quarter(block, array_cast<word_t>(left));
353+
inject_right_quarter(block, array_cast<word_t>(right));
354+
pad_half(block);
343355
native_transform<true>(state, block);
344356
return native_finalize<one>(state);
345357
}
@@ -350,11 +362,14 @@ native_hash(uint8_t byte) NOEXCEPT
350362
{
351363
constexpr auto pad = bit_hi<uint8_t>;
352364

365+
auto state = H::get;
353366
block_t block{};
354-
block.at(0) = byte;
355-
block.at(1) = pad;
356-
block.at(63) = byte_bits;
357-
return native_hash(block);
367+
368+
// Order is based on array of little-endian uint32_t.
369+
block.at(3) = byte;
370+
block.at(2) = pad;
371+
block.at(60) = byte_bits;
372+
return native_finalize(state, array_cast<word_t>(block));
358373
}
359374

360375
// Double hash functions start with BE data and end with BE digest_t.
@@ -370,7 +385,7 @@ native_double_hash(const block_t& block) NOEXCEPT
370385

371386
// Second hash
372387
words_t block2{};
373-
inject_left(block2, state);
388+
inject_left_half(block2, state);
374389
pad_half(block2);
375390
state = H::get;
376391
return native_finalize(state, block2);
@@ -388,7 +403,7 @@ native_double_hash(const half_t& half) NOEXCEPT
388403
native_transform<false>(state, block);
389404

390405
// Second hash
391-
inject_left(block, state);
406+
inject_left_half(block, state);
392407
pad_half(block);
393408
state = H::get;
394409
return native_finalize(state, block);
@@ -400,13 +415,13 @@ native_double_hash(const half_t& left, const half_t& right) NOEXCEPT
400415
{
401416
auto state = H::get;
402417
words_t block{};
403-
inject_left(block, array_cast<word_t>(left));
404-
inject_right(block, array_cast<word_t>(right));
418+
inject_left_half(block, array_cast<word_t>(left));
419+
inject_right_half(block, array_cast<word_t>(right));
405420
native_transform<true>(state, block);
406421
native_transform<false>(state, pad_block());
407422

408423
// Second hash
409-
inject_left(block, state);
424+
inject_left_half(block, state);
410425
pad_half(block);
411426
state = H::get;
412427
return native_finalize(state, block);

include/bitcoin/system/impl/hash/sha/algorithm_parsing.ipp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,8 @@ output(const state_t& state) NOEXCEPT
410410

411411
TEMPLATE
412412
INLINE constexpr void CLASS::
413-
inject_left(auto& buffer, const auto& left) NOEXCEPT
413+
inject_left_half(auto& buffer, const auto& left) NOEXCEPT
414414
{
415-
using words = decltype(buffer);
416-
static_assert(array_count<words> >= SHA::state_words);
417-
418415
if (std::is_constant_evaluated())
419416
{
420417
buffer.at(0) = left.at(0);
@@ -428,18 +425,15 @@ inject_left(auto& buffer, const auto& left) NOEXCEPT
428425
}
429426
else
430427
{
431-
using word = array_element<words>;
428+
using word = array_element<decltype(buffer)>;
432429
array_cast<word, SHA::state_words>(buffer) = left;
433430
}
434431
}
435432

436433
TEMPLATE
437434
INLINE constexpr void CLASS::
438-
inject_right(auto& buffer, const auto& right) NOEXCEPT
435+
inject_right_half(auto& buffer, const auto& right) NOEXCEPT
439436
{
440-
using words = decltype(buffer);
441-
static_assert(array_count<words> >= SHA::state_words);
442-
443437
if (std::is_constant_evaluated())
444438
{
445439
buffer.at(8) = right.at(0);
@@ -453,11 +447,48 @@ inject_right(auto& buffer, const auto& right) NOEXCEPT
453447
}
454448
else
455449
{
456-
using word = array_element<words>;
450+
using word = array_element<decltype(buffer)>;
457451
array_cast<word, SHA::state_words, SHA::state_words>(buffer) = right;
458452
}
459453
}
460454

455+
TEMPLATE
456+
INLINE constexpr void CLASS::
457+
inject_left_quarter(auto& buffer, const auto& left) NOEXCEPT
458+
{
459+
if (std::is_constant_evaluated())
460+
{
461+
buffer.at(0) = left.at(0);
462+
buffer.at(1) = left.at(1);
463+
buffer.at(2) = left.at(2);
464+
buffer.at(3) = left.at(3);
465+
}
466+
else
467+
{
468+
using word = array_element<decltype(buffer)>;
469+
array_cast<word, to_half(SHA::state_words)>(buffer) = left;
470+
}
471+
}
472+
473+
TEMPLATE
474+
INLINE constexpr void CLASS::
475+
inject_right_quarter(auto& buffer, const auto& right) NOEXCEPT
476+
{
477+
if (std::is_constant_evaluated())
478+
{
479+
buffer.at(4) = right.at(0);
480+
buffer.at(5) = right.at(1);
481+
buffer.at(6) = right.at(2);
482+
buffer.at(7) = right.at(3);
483+
}
484+
else
485+
{
486+
using word = array_element<decltype(buffer)>;
487+
constexpr auto words = to_half(SHA::state_words);
488+
array_cast<word, words, words>(buffer) = right;
489+
}
490+
}
491+
461492
} // namespace sha
462493
} // namespace system
463494
} // namespace libbitcoin

include/bitcoin/system/impl/hash/sha/algorithm_stream.ipp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ finalize_second(const state_t& state) NOEXCEPT
116116
{
117117
auto state2 = H::get;
118118
buffer_t buffer{};
119-
inject_left(buffer, state);
119+
inject_left_half(buffer, state);
120120
pad_half(buffer);
121121
schedule(buffer);
122122
compress(state2, buffer);
@@ -150,7 +150,7 @@ finalize_double(state_t& state, size_t blocks) NOEXCEPT
150150

151151
// This is finalize_second() but reuses the initial buffer.
152152
auto state2 = H::get;
153-
inject_left(buffer, state);
153+
inject_left_half(buffer, state);
154154
pad_half(buffer);
155155
schedule(buffer);
156156
compress(state2, buffer);

0 commit comments

Comments
 (0)