@@ -227,6 +227,33 @@ native_transform(state_t& state, const auto& block) NOEXCEPT
227227// There is no benefit to caching pading because it is not prescheduled.
228228// ----------------------------------------------------------------------------
229229
230+ // TODO: These transitions require state to be unloaded/loaded and
231+ // shuffled/unshuffled, whereas this is not logically necessary. This is a
232+ // fixed cost imposed once for any accumulation (which is inconsequential for
233+ // larger iterations), but reduces efficiency for lower block counts and hash
234+ // doubling. Large iterations are 15-16% wheras small iterations are 20-26%.
235+ // native_transform -> native_transform -> native_finalize
236+ // native_transform -> native_finalize
237+ // This can be resolved in the non-iterator scenarios (below) through
238+ // implementation of a finalizing and a doubling native_transform. This means
239+ // that padding must be incorporated, however since it is not prescheduled or
240+ // cached this is not an issue.
241+
242+ TEMPLATE
243+ template <size_t Blocks>
244+ typename CLASS::digest_t CLASS::
245+ native_finalize (state_t & state) NOEXCEPT
246+ {
247+ return native_finalize (state, Blocks);
248+ }
249+
250+ TEMPLATE
251+ typename CLASS::digest_t CLASS::
252+ native_finalize (state_t & state, size_t blocks) NOEXCEPT
253+ {
254+ return native_finalize (state, pad_blocks (blocks));
255+ }
256+
230257TEMPLATE
231258typename CLASS::digest_t CLASS::
232259native_finalize (state_t & state, const words_t & pad) NOEXCEPT
@@ -248,21 +275,6 @@ native_finalize(state_t& state, const words_t& pad) NOEXCEPT
248275 return digest;
249276}
250277
251- TEMPLATE
252- template <size_t Blocks>
253- typename CLASS::digest_t CLASS::
254- native_finalize (state_t & state) NOEXCEPT
255- {
256- return native_finalize (state, Blocks);
257- }
258-
259- TEMPLATE
260- typename CLASS::digest_t CLASS::
261- native_finalize (state_t & state, size_t blocks) NOEXCEPT
262- {
263- return native_finalize (state, pad_blocks (blocks));
264- }
265-
266278TEMPLATE
267279typename CLASS::digest_t CLASS::
268280native_finalize_second (const state_t & state) NOEXCEPT
@@ -273,9 +285,9 @@ native_finalize_second(const state_t& state) NOEXCEPT
273285 // Hash a state value and finalize it.
274286 auto state2 = H::get;
275287 words_t block{};
276- inject_left (block, state); // swapped
277- pad_half (block); // swapped
278- return native_finalize (state2, block); // no block swap (swaps state)
288+ inject_left (block, state);
289+ pad_half (block);
290+ return native_finalize (state2, block);
279291}
280292
281293TEMPLATE
@@ -284,30 +296,40 @@ native_finalize_double(state_t& state, size_t blocks) NOEXCEPT
284296{
285297 // Complete first hash by transforming padding, but don't convert state.
286298 auto block = pad_blocks (blocks);
287- native_transform<false >(state, block); // no swap
299+ native_transform<false >(state, block);
288300
289301 // This is native_finalize_second() but reuses the initial block.
290302 auto state2 = H::get;
291- inject_left (block, state); // swapped
292- pad_half (block); // swapped
293- return native_finalize (state2, block); // no block swap (swaps state)
303+ inject_left (block, state);
304+ pad_half (block);
305+ return native_finalize (state2, block);
294306}
295307
296308// Hash functions start with BE data and end with BE digest_t.
297309// ----------------------------------------------------------------------------
298310
311+ TEMPLATE
312+ typename CLASS::digest_t CLASS::
313+ native_hash (const block_t & block) NOEXCEPT
314+ {
315+ auto state = H::get;
316+ native_transform<true >(state, block);
317+ return native_finalize (state, pad_block ());
318+ }
319+
299320TEMPLATE
300321typename CLASS::digest_t CLASS::
301322native_hash (const half_t & half) NOEXCEPT
302323{
303324 // No hash(state_t) optimizations for sha160 (requires chunk_t/half_t).
304325 static_assert (is_same_type<state_t , chunk_t >);
305326
327+ // input_left is a non-native endianness conversion.
306328 auto state = H::get;
307329 words_t block{};
308- input_left (block, half); // swaps
309- pad_half (block); // swapped
310- return native_finalize (state, block); // no block swap (swaps state)
330+ input_left (block, half);
331+ pad_half (block);
332+ return native_finalize (state, block);
311333}
312334
313335TEMPLATE
@@ -316,10 +338,10 @@ native_hash(const half_t& left, const half_t& right) NOEXCEPT
316338{
317339 auto state = H::get;
318340 words_t block{};
319- inject_left (block, array_cast<word_t >(left)); // unswapped
320- inject_right (block, array_cast<word_t >(right)); // unswapped
321- native_transform<true >(state, block); // swap
322- return native_finalize<one>(state); // no block swap (swaps state)
341+ inject_left (block, array_cast<word_t >(left));
342+ inject_right (block, array_cast<word_t >(right));
343+ native_transform<true >(state, block);
344+ return native_finalize<one>(state);
323345}
324346
325347// Double hash functions start with BE data and end with BE digest_t.
@@ -330,32 +352,33 @@ typename CLASS::digest_t CLASS::
330352native_double_hash (const block_t & block) NOEXCEPT
331353{
332354 auto state = H::get;
333- native_transform<true >(state, block); // swap
334- native_transform<false >(state, pad_block ()); // swapped
355+ native_transform<true >(state, block);
356+ native_transform<false >(state, pad_block ());
335357
336358 // Second hash
337359 words_t block2{};
338- inject_left (block2, state); // swapped
339- pad_half (block2); // swapped
340- state = H::get; // [reuse state var]
341- return native_finalize (state, block2); // no block swap (swaps state)
360+ inject_left (block2, state);
361+ pad_half (block2);
362+ state = H::get;
363+ return native_finalize (state, block2);
342364}
343365
344366TEMPLATE
345367typename CLASS::digest_t CLASS::
346368native_double_hash (const half_t & half) NOEXCEPT
347369{
370+ // input_left is a non-native endianness conversion.
348371 auto state = H::get;
349372 words_t block{};
350- input_left (block, half); // swaps
351- pad_half (block); // swapped
352- native_transform<false >(state, block); // no block swap
373+ input_left (block, half);
374+ pad_half (block);
375+ native_transform<false >(state, block);
353376
354377 // Second hash
355- inject_left (block, state); // swapped
356- pad_half (block); // swapped
357- state = H::get; // [reuse state var]
358- return native_finalize (state, block); // no block swap (swaps state)
378+ inject_left (block, state);
379+ pad_half (block);
380+ state = H::get;
381+ return native_finalize (state, block);
359382}
360383
361384TEMPLATE
@@ -364,16 +387,16 @@ native_double_hash(const half_t& left, const half_t& right) NOEXCEPT
364387{
365388 auto state = H::get;
366389 words_t block{};
367- inject_left (block, array_cast<word_t >(left)); // unswapped
368- inject_right (block, array_cast<word_t >(right)); // unswapped
369- native_transform<true >(state, block); // swap
370- native_transform<false >(state, pad_block ()); // swapped
390+ inject_left (block, array_cast<word_t >(left));
391+ inject_right (block, array_cast<word_t >(right));
392+ native_transform<true >(state, block);
393+ native_transform<false >(state, pad_block ());
371394
372395 // Second hash
373- inject_left (block, state); // swapped
374- pad_half (block); // swapped
375- state = H::get; // [reuse state var]
376- return native_finalize (state, block); // no block swap (swaps state)
396+ inject_left (block, state);
397+ pad_half (block);
398+ state = H::get;
399+ return native_finalize (state, block);
377400}
378401
379402} // namespace sha
0 commit comments