Skip to content

Commit fd74d86

Browse files
committed
Separate const and non-const get_digest methods
1 parent 2d4581b commit fd74d86

File tree

1 file changed

+123
-69
lines changed

1 file changed

+123
-69
lines changed

include/boost/crypt2/hash/detail/sha3_base.hpp

Lines changed: 123 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,39 @@ class sha3_base final {
6464

6565
BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto finalize() noexcept -> state;
6666

67+
// SHA 3 get_digest is idempotent so make as const
68+
template <bool Const = !is_xof>
6769
[[nodiscard("Digest is the function return value")]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
68-
auto get_digest() noexcept -> compat::expected<return_type, state>;
70+
compat::enable_if_t<Const, compat::expected<return_type, state>> get_digest() const noexcept;
6971

70-
template <compat::size_t Extent = compat::dynamic_extent>
72+
template <bool Const = !is_xof, compat::size_t Extent = compat::dynamic_extent>
7173
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
72-
auto get_digest(compat::span<compat::byte, Extent> data) noexcept -> state;
74+
compat::enable_if_t<Const, state> get_digest(compat::span<compat::byte, Extent> data) const noexcept;
7375

74-
template <concepts::writable_output_range Range>
75-
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED auto get_digest(Range&& data) noexcept -> state;
76+
template <bool Const = !is_xof, concepts::writable_output_range Range>
77+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED
78+
compat::enable_if_t<Const, state> get_digest(Range&& data) const noexcept;
7679

77-
template <compat::size_t Extent = compat::dynamic_extent>
80+
// XOF get_digest is not idempotent so we need separate impls
81+
template <bool Const = is_xof>
82+
[[nodiscard("Digest is the function return value")]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
83+
compat::enable_if_t<Const, compat::expected<return_type, state>> get_digest() noexcept;
84+
85+
template <bool Const = is_xof, compat::size_t Extent = compat::dynamic_extent>
86+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
87+
compat::enable_if_t<Const, state> get_digest(compat::span<compat::byte, Extent> data) noexcept;
88+
89+
template <bool Const = is_xof, concepts::writable_output_range Range>
90+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED
91+
compat::enable_if_t<Const, state> get_digest(Range&& data) noexcept;
92+
93+
template <bool Const = is_xof, compat::size_t Extent = compat::dynamic_extent>
7894
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
79-
auto get_digest(compat::span<compat::byte, Extent> data, std::size_t amount) noexcept -> state;
95+
compat::enable_if_t<Const, state> get_digest(compat::span<compat::byte, Extent> data, std::size_t amount) noexcept;
8096

81-
template <concepts::writable_output_range Range>
82-
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED auto get_digest(Range&& data, std::size_t amount) noexcept -> state;
97+
template <bool Const = is_xof, concepts::writable_output_range Range>
98+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED
99+
compat::enable_if_t<Const, state> get_digest(Range&& data, std::size_t amount) noexcept;
83100
};
84101

85102
namespace sha3_detail {
@@ -345,78 +362,95 @@ auto sha3_base<digest_size, is_xof>::sha_digest_impl(compat::span<compat::byte,
345362
}
346363

347364
template <compat::size_t digest_size, bool is_xof>
365+
template <bool Const>
348366
[[nodiscard("Digest is the function return value")]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
349-
auto sha3_base<digest_size, is_xof>::get_digest() noexcept -> compat::expected<return_type, state>
367+
compat::enable_if_t<Const, compat::expected<typename sha3_base<digest_size, is_xof>::return_type, state>>
368+
sha3_base<digest_size, is_xof>::get_digest() const noexcept
350369
{
351-
return_type digest {};
352-
353370
if (!computed_ || corrupted_)
354371
{
355372
return compat::unexpected<state>(state::state_error);
356373
}
357374

358-
if constexpr (is_xof)
359-
{
360-
xof_digest_impl(digest, digest_size);
361-
}
362-
else
375+
return_type digest {};
376+
sha_digest_impl(digest);
377+
378+
return digest;
379+
}
380+
381+
template <compat::size_t digest_size, bool is_xof>
382+
template <bool Const>
383+
[[nodiscard("Digest is the function return value")]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
384+
compat::enable_if_t<Const, compat::expected<typename sha3_base<digest_size, is_xof>::return_type, state>>
385+
sha3_base<digest_size, is_xof>::get_digest() noexcept
386+
{
387+
if (!computed_ || corrupted_)
363388
{
364-
sha_digest_impl(digest);
389+
return compat::unexpected<state>(state::state_error);
365390
}
366391

392+
return_type digest {};
393+
xof_digest_impl(digest, digest_size);
394+
367395
return digest;
368396
}
369397

370398
template <compat::size_t digest_size, bool is_xof>
371-
template <compat::size_t Extent>
372-
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto
373-
sha3_base<digest_size, is_xof>::get_digest(compat::span<compat::byte, Extent> data) noexcept -> state
399+
template <bool Const, compat::size_t Extent>
400+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
401+
compat::enable_if_t<Const, state> sha3_base<digest_size, is_xof>::get_digest(compat::span<compat::byte, Extent> data) const noexcept
374402
{
375403
if (!computed_ || corrupted_)
376404
{
377405
return state::state_error;
378406
}
379-
if constexpr (!is_xof)
407+
if (data.size() < digest_size)
380408
{
381-
if (data.size() < digest_size)
382-
{
383-
return state::insufficient_output_length;
384-
}
409+
return state::insufficient_output_length;
385410
}
386411

387-
// XOF will fill the entire provided span whereas SHA will only fill the digest size
388-
if constexpr (is_xof)
412+
if constexpr (Extent == digest_size)
389413
{
390-
xof_digest_impl(data, data.size());
414+
sha_digest_impl(data);
391415
}
392416
else
393417
{
394-
if constexpr (Extent == digest_size)
395-
{
396-
sha_digest_impl(data);
397-
}
398-
else
399-
{
400-
// We have verified the length of the span is correct so using a fixed length section of it is safe
401-
#if defined(__clang__) && __clang_major__ >= 19
402-
#pragma clang diagnostic push
403-
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
404-
#endif
418+
// We have verified the length of the span is correct so using a fixed length section of it is safe
419+
#if defined(__clang__) && __clang_major__ >= 19
420+
#pragma clang diagnostic push
421+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
422+
#endif
405423

406-
sha_digest_impl(compat::span<compat::byte, digest_size>(data.data(), digest_size));
424+
sha_digest_impl(compat::span<compat::byte, digest_size>(data.data(), digest_size));
407425

408-
#if defined(__clang__) && __clang_major__ >= 19
409-
#pragma clang diagnostic pop
410-
#endif
411-
}
426+
#if defined(__clang__) && __clang_major__ >= 19
427+
#pragma clang diagnostic pop
428+
#endif
412429
}
413430

414431
return state::success;
415432
}
416433

417434
template <compat::size_t digest_size, bool is_xof>
418-
template <concepts::writable_output_range Range>
419-
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED auto sha3_base<digest_size, is_xof>::get_digest(Range&& data) noexcept -> state
435+
template <bool Const, compat::size_t Extent>
436+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
437+
compat::enable_if_t<Const, state> sha3_base<digest_size, is_xof>::get_digest(compat::span<compat::byte, Extent> data) noexcept
438+
{
439+
if (!computed_ || corrupted_)
440+
{
441+
return state::state_error;
442+
}
443+
444+
// XOF will fill the entire provided span whereas SHA will only fill the digest size
445+
xof_digest_impl(data, data.size());
446+
447+
return state::success;
448+
}
449+
450+
template <compat::size_t digest_size, bool is_xof>
451+
template <bool Const, concepts::writable_output_range Range>
452+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED
453+
compat::enable_if_t<Const, state> sha3_base<digest_size, is_xof>::get_digest(Range&& data) const noexcept
420454
{
421455
using value_type = compat::range_value_t<Range>;
422456

@@ -427,12 +461,9 @@ template <concepts::writable_output_range Range>
427461

428462
const auto data_size {std::size(data)};
429463

430-
if constexpr (!is_xof)
464+
if (data_size < digest_size)
431465
{
432-
if (data_size < digest_size)
433-
{
434-
return state::insufficient_output_length;
435-
}
466+
return state::insufficient_output_length;
436467
}
437468

438469
auto data_span {compat::span<value_type>(compat::forward<Range>(data))};
@@ -442,20 +473,42 @@ template <concepts::writable_output_range Range>
442473
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
443474
#endif
444475

445-
if constexpr (is_xof)
446-
{
447-
xof_digest_impl(compat::span<compat::byte>(compat::as_writable_bytes(data_span).data(), data_size), data_size);
448-
}
449-
else
476+
sha_digest_impl(
477+
compat::span<compat::byte, digest_size>(
478+
compat::as_writable_bytes(data_span).data(),
479+
digest_size
480+
)
481+
);
482+
483+
#if defined(__clang__) && __clang_major__ >= 19
484+
#pragma clang diagnostic pop
485+
#endif
486+
487+
return state::success;
488+
}
489+
490+
template <compat::size_t digest_size, bool is_xof>
491+
template <bool Const, concepts::writable_output_range Range>
492+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED
493+
compat::enable_if_t<Const, state> sha3_base<digest_size, is_xof>::get_digest(Range&& data) noexcept
494+
{
495+
using value_type = compat::range_value_t<Range>;
496+
497+
if (!computed_ || corrupted_)
450498
{
451-
sha_digest_impl(
452-
compat::span<compat::byte, digest_size>(
453-
compat::as_writable_bytes(data_span).data(),
454-
digest_size
455-
)
456-
);
499+
return state::state_error;
457500
}
458-
501+
502+
const auto data_size {std::size(data)};
503+
auto data_span {compat::span<value_type>(compat::forward<Range>(data))};
504+
505+
#if defined(__clang__) && __clang_major__ >= 19
506+
#pragma clang diagnostic push
507+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
508+
#endif
509+
510+
xof_digest_impl(compat::span<compat::byte>(compat::as_writable_bytes(data_span).data(), data_size), data_size);
511+
459512
#if defined(__clang__) && __clang_major__ >= 19
460513
#pragma clang diagnostic pop
461514
#endif
@@ -464,9 +517,9 @@ template <concepts::writable_output_range Range>
464517
}
465518

466519
template <compat::size_t digest_size, bool is_xof>
467-
template <compat::size_t Extent>
468-
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR auto
469-
sha3_base<digest_size, is_xof>::get_digest(compat::span<compat::byte, Extent> data, std::size_t amount) noexcept -> state
520+
template <bool Const, compat::size_t Extent>
521+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED_CONSTEXPR
522+
compat::enable_if_t<Const, state> sha3_base<digest_size, is_xof>::get_digest(compat::span<compat::byte, Extent> data, std::size_t amount) noexcept
470523
{
471524
if (!computed_ || corrupted_)
472525
{
@@ -485,8 +538,9 @@ sha3_base<digest_size, is_xof>::get_digest(compat::span<compat::byte, Extent> da
485538
}
486539

487540
template <compat::size_t digest_size, bool is_xof>
488-
template <concepts::writable_output_range Range>
489-
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED auto sha3_base<digest_size, is_xof>::get_digest(Range&& data, std::size_t amount) noexcept -> state
541+
template <bool Const, concepts::writable_output_range Range>
542+
[[nodiscard]] BOOST_CRYPT_GPU_ENABLED
543+
compat::enable_if_t<Const, state> sha3_base<digest_size, is_xof>::get_digest(Range&& data, std::size_t amount) noexcept
490544
{
491545
using value_type = compat::range_value_t<Range>;
492546

0 commit comments

Comments
 (0)