//***************************************************************************** // (C) Automotive Lighting Reutlingen GmbH // Tuebinger Strasse 123, 72762 Reutlingen, Germany // // Automotive Lighting Reutlingen GmbH owns all the rights to this work. // This work shall not be copied, reproduced, used, modified, transferred // or its information shall not be disclosed without the prior written // authorization of Automotive Lighting Reutlingen GmbH. //***************************************************************************** //----------------------------------------------------------------------------- /// \file hash_sha_base.h /// /// \brief /// //----------------------------------------------------------------------------- #ifndef HASH_SHA_BASE_2019_06_13_H #define HASH_SHA_BASE_2019_06_13_H #include #if(__cplusplus >= 201703L) namespace al::crypto::stream::hash { #else namespace al { namespace crypto { namespace stream { namespace hash { #endif template class hash_sha_base : public al::crypto::stream::hash::hash_base { private: using base_class_type = al::crypto::stream::hash::hash_base; static_assert((MessageLengthTotalBitCount % 8U) == 0U, "Error: Wrong granularity of MessageLengthTotalBitCount. Must be multiple of 8."); static constexpr auto message_length_total_width() noexcept -> std::size_t { return static_cast ( MessageLengthTotalBitCount / static_cast(UINT8_C(8)) ); } public: ~hash_sha_base() override = default; auto finalize() -> void override { // Create the padding. Begin by setting the leading padding byte to 0x80. base_class_type::message_buffer[base_class_type::message_index] = static_cast(UINT8_C(0x80)); ++base_class_type::message_index; // We need an extra block because there are not enough bytes // available for storing the total bit count. So we must // transform the current block, then create and pad yet another // additional block. const auto buffer_top = static_cast(base_class_type::message_buffer_static_size - message_length_total_width()); if(base_class_type::message_index > static_cast(buffer_top)) { this->transform(); } // Encode the total number of bits in the final transform buffer. // Here, we can easily see the conversion of the number of bytes // to the number of bits. This is done by performing a left-shift // of 3 on "base_class_type::message_length_total". auto carry = static_cast(UINT8_C(0)); for(auto ri = base_class_type::message_buffer.rbegin(); ri != base_class_type::message_buffer.rbegin() + static_cast(message_length_total_width()); ++ri) { const auto the_word = static_cast ( static_cast(base_class_type::message_length_total) << static_cast(UINT8_C(3)) ); *ri = static_cast(the_word | static_cast(carry)); base_class_type::message_length_total = static_cast ( base_class_type::message_length_total >> static_cast(UINT8_C(8)) ); carry = static_cast ( static_cast ( static_cast(the_word >> static_cast(UINT8_C(8))) & static_cast(UINT8_C(0x07)) ) ); } this->transform(); } AL_CRYPTO_NODISCARD auto get_result() const -> typename base_class_type::result_type override { typename base_class_type::result_type result; // Extract the hash result base_class_type::copy_transform_context_reverse(result.data()); return result; } auto finalize_and_get_result(typename base_class_type::result_type::pointer result_data) -> void override { finalize(); base_class_type::copy_transform_context_reverse(result_data); } protected: hash_sha_base() = default; hash_sha_base(const hash_sha_base&) = default; hash_sha_base(hash_sha_base&&) noexcept = default; // AXIVION Next Line AutosarC++19_03-A10.2.1: AUTOSAR permitted auto operator=(const hash_sha_base&) -> hash_sha_base& = default; // AXIVION Next Line AutosarC++19_03-A10.2.1: AUTOSAR permitted auto operator=(hash_sha_base&&) noexcept -> hash_sha_base& = default; }; #if(__cplusplus >= 201703L) } // namespace al::crypto::stream::hash #else } // namespace hash } // namespace stream } // namespace crypto } // namespace al #endif #endif // HASH_SHA_BASE_2019_06_13_H