From 8df03f119e1dcc7d6ff4dba51666163e922e4af2 Mon Sep 17 00:00:00 2001 From: Rene Meusel Date: Thu, 11 Jan 2024 15:53:01 +0100 Subject: [PATCH 1/2] add range based overloads of copy_out_be/le Co-Authored-By: Fabian Albert --- src/lib/utils/loadstor.h | 51 +++++++++++++++++++++++++++++ src/tests/test_utils.cpp | 70 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/src/lib/utils/loadstor.h b/src/lib/utils/loadstor.h index 09c372fd29f..bec52fba04c 100644 --- a/src/lib/utils/loadstor.h +++ b/src/lib/utils/loadstor.h @@ -712,6 +712,57 @@ inline constexpr auto store_be(ParamTs&&... params) { return detail::store_any(std::forward(params)...); } +namespace detail { + +template +size_t copy_out_any_word_aligned_portion(std::span& out, std::span& in) { + const size_t full_words = out.size() / sizeof(T); + const size_t full_word_bytes = full_words * sizeof(T); + const size_t remaining_bytes = out.size() - full_word_bytes; + BOTAN_ASSERT_NOMSG(in.size_bytes() >= full_word_bytes + remaining_bytes); + + // copy full words + store_any(out.first(full_word_bytes), in.first(full_words)); + out = out.subspan(full_word_bytes); + in = in.subspan(full_words); + + return remaining_bytes; +} + +} // namespace detail + +/** + * Partially copy a subset of @p in into @p out using big-endian + * byte order. + */ +template +void copy_out_be(std::span out, InR&& in) { + using T = std::ranges::range_value_t; + std::span in_s{in}; + const auto remaining_bytes = detail::copy_out_any_word_aligned_portion(out, in_s); + + // copy remaining bytes as a partial word + for(size_t i = 0; i < remaining_bytes; ++i) { + out[i] = get_byte_var(i, in_s.front()); + } +} + +/** + * Partially copy a subset of @p in into @p out using little-endian + * byte order. + */ +template +void copy_out_le(std::span out, InR&& in) { + using T = std::ranges::range_value_t; + std::span in_s{in}; + const auto remaining_bytes = detail::copy_out_any_word_aligned_portion(out, in_s); + + // copy remaining bytes as a partial word + for(size_t i = 0; i < remaining_bytes; ++i) { + out[i] = get_byte_var(sizeof(T) - 1 - i, in_s.front()); + } +} + template void copy_out_be(uint8_t out[], size_t out_bytes, const T in[]) { while(out_bytes >= sizeof(T)) { diff --git a/src/tests/test_utils.cpp b/src/tests/test_utils.cpp index 8a9e30a6e90..ae6781fd183 100644 --- a/src/tests/test_utils.cpp +++ b/src/tests/test_utils.cpp @@ -67,7 +67,7 @@ class Utility_Function_Tests final : public Text_Based_Test { results.push_back(test_loadstore()); results.push_back(test_loadstore_fallback()); results.push_back(test_loadstore_constexpr()); - return results; + return Botan::concat(results, test_copy_out_be_le()); } private: @@ -577,6 +577,74 @@ class Utility_Function_Tests final : public Text_Based_Test { return result; } + + static std::vector test_copy_out_be_le() { + return { + Botan_Tests::CHECK("copy_out_be with 16bit input (word aligned)", + [&](auto& result) { + std::vector out_vector(4); + const std::array in_array = {0x0A0B, 0x0C0D}; + Botan::copy_out_be(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C0D")); + }), + + Botan_Tests::CHECK("copy_out_be with 16bit input (partial words)", + [&](auto& result) { + std::vector out_vector(3); + const std::array in_array = {0x0A0B, 0x0C0D}; + Botan::copy_out_be(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C")); + }), + + Botan_Tests::CHECK("copy_out_le with 16bit input (word aligned)", + [&](auto& result) { + std::vector out_vector(4); + const std::array in_array = {0x0A0B, 0x0C0D}; + Botan::copy_out_le(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("0B0A0D0C")); + }), + + Botan_Tests::CHECK("copy_out_le with 16bit input (partial words)", + [&](auto& result) { + std::vector out_vector(3); + const std::array in_array = {0x0A0B, 0x0C0D}; + Botan::copy_out_le(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("0B0A0D")); + }), + + Botan_Tests::CHECK("copy_out_be with 64bit input (word aligned)", + [&](auto& result) { + std::vector out_vector(16); + const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; + Botan::copy_out_be(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C0D0E0F10111213141516171819")); + }), + + Botan_Tests::CHECK("copy_out_le with 64bit input (word aligned)", + [&](auto& result) { + std::vector out_vector(16); + const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; + Botan::copy_out_le(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("11100F0E0D0C0B0A1918171615141312")); + }), + + Botan_Tests::CHECK("copy_out_be with 64bit input (partial words)", + [&](auto& result) { + std::vector out_vector(15); + const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; + Botan::copy_out_be(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("0A0B0C0D0E0F101112131415161718")); + }), + + Botan_Tests::CHECK("copy_out_le with 64bit input (partial words)", + [&](auto& result) { + std::vector out_vector(15); + const std::array in_array = {0x0A0B0C0D0E0F1011, 0x1213141516171819}; + Botan::copy_out_le(out_vector, in_array); + result.test_is_eq(out_vector, Botan::hex_decode("11100F0E0D0C0B0A19181716151413")); + }), + }; + } }; BOTAN_REGISTER_SMOKE_TEST("utils", "util", Utility_Function_Tests); From bd94e8e449cd46b837b6e78764c5fb489e1146ba Mon Sep 17 00:00:00 2001 From: Rene Meusel Date: Mon, 25 Mar 2024 11:29:17 +0100 Subject: [PATCH 2/2] Replace legacy copy_out_be/le Co-Authored-By: Fabian Albert --- src/lib/block/aes/aes.cpp | 4 +-- src/lib/compat/sodium/sodium_salsa.cpp | 3 +- src/lib/hash/blake2/blake2b.cpp | 2 +- src/lib/hash/blake2s/blake2s.cpp | 2 +- src/lib/hash/mdx_hash/mdx_hash.h | 4 +-- src/lib/hash/skein/skein_512.cpp | 2 +- src/lib/utils/loadstor.h | 38 -------------------------- src/lib/utils/poly_dbl/poly_dbl.cpp | 4 +-- 8 files changed, 10 insertions(+), 49 deletions(-) diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp index ac055a91ec9..9f110892b88 100644 --- a/src/lib/block/aes/aes.cpp +++ b/src/lib/block/aes/aes.cpp @@ -550,7 +550,7 @@ void aes_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks, const secur CT::unpoison(B, 8); - copy_out_be(out, this_loop * 4 * sizeof(uint32_t), B); + copy_out_be(std::span(out, this_loop * 4 * sizeof(uint32_t)), B); in += this_loop * BLOCK_SIZE; out += this_loop * BLOCK_SIZE; @@ -610,7 +610,7 @@ void aes_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks, const secur CT::unpoison(B, 8); - copy_out_be(out, this_loop * 4 * sizeof(uint32_t), B); + copy_out_be(std::span(out, this_loop * 4 * sizeof(uint32_t)), B); in += this_loop * BLOCK_SIZE; out += this_loop * BLOCK_SIZE; diff --git a/src/lib/compat/sodium/sodium_salsa.cpp b/src/lib/compat/sodium/sodium_salsa.cpp index aac6df98fa3..6ada79e9e03 100644 --- a/src/lib/compat/sodium/sodium_salsa.cpp +++ b/src/lib/compat/sodium/sodium_salsa.cpp @@ -45,8 +45,7 @@ int Sodium::crypto_core_hsalsa20(uint8_t out[], const uint8_t in[], const uint8_ uint32_t out32[8] = {0}; Salsa20::hsalsa20(out32, in32); - - copy_out_le(out, 32, out32); + store_le(std::span(out, 32), out32); return 0; } diff --git a/src/lib/hash/blake2/blake2b.cpp b/src/lib/hash/blake2/blake2b.cpp index 14673e6dc4e..f3f2b1c9330 100644 --- a/src/lib/hash/blake2/blake2b.cpp +++ b/src/lib/hash/blake2/blake2b.cpp @@ -161,7 +161,7 @@ void BLAKE2b::final_result(std::span output) { m_F = 0xFFFFFFFFFFFFFFFF; compress(m_buffer.consume().data(), 1, pos); - copy_out_vec_le(output.data(), output_length(), m_H); + copy_out_le(output.first(output_length()), m_H); state_init(); } diff --git a/src/lib/hash/blake2s/blake2s.cpp b/src/lib/hash/blake2s/blake2s.cpp index 60252a39a1f..6bbfe31424b 100644 --- a/src/lib/hash/blake2s/blake2s.cpp +++ b/src/lib/hash/blake2s/blake2s.cpp @@ -141,7 +141,7 @@ void BLAKE2s::final_result(std::span out) { compress(true); // final block flag = 1 // little endian convert and store - copy_out_le(out.data(), m_outlen, m_h); + copy_out_le(out.first(output_length()), m_h); clear(); }; diff --git a/src/lib/hash/mdx_hash/mdx_hash.h b/src/lib/hash/mdx_hash/mdx_hash.h index 7514b1c9784..1c1969409c7 100644 --- a/src/lib/hash/mdx_hash/mdx_hash.h +++ b/src/lib/hash/mdx_hash/mdx_hash.h @@ -114,9 +114,9 @@ class MerkleDamgard_Hash final { BOTAN_ASSERT_NOMSG(output.size() >= MD::output_bytes); if constexpr(MD::byte_endianness == MD_Endian::Big) { - copy_out_vec_be(output.data(), MD::output_bytes, m_digest); + copy_out_be(output.first(MD::output_bytes), m_digest); } else { - copy_out_vec_le(output.data(), MD::output_bytes, m_digest); + copy_out_le(output.first(MD::output_bytes), m_digest); } } diff --git a/src/lib/hash/skein/skein_512.cpp b/src/lib/hash/skein/skein_512.cpp index 568bfba0b26..90a3e2fcd61 100644 --- a/src/lib/hash/skein/skein_512.cpp +++ b/src/lib/hash/skein/skein_512.cpp @@ -144,7 +144,7 @@ void Skein_512::final_result(std::span out) { reset_tweak(SKEIN_OUTPUT, true); ubi_512(counter, sizeof(counter)); - copy_out_vec_le(out.data(), m_output_bits / 8, m_threefish->m_K); + copy_out_le(out.first(m_output_bits / 8), m_threefish->m_K); initial_block(); } diff --git a/src/lib/utils/loadstor.h b/src/lib/utils/loadstor.h index bec52fba04c..d163b00ec91 100644 --- a/src/lib/utils/loadstor.h +++ b/src/lib/utils/loadstor.h @@ -763,44 +763,6 @@ void copy_out_le(std::span out, InR&& in) { } } -template -void copy_out_be(uint8_t out[], size_t out_bytes, const T in[]) { - while(out_bytes >= sizeof(T)) { - store_be(in[0], out); - out += sizeof(T); - out_bytes -= sizeof(T); - in += 1; - } - - for(size_t i = 0; i != out_bytes; ++i) { - out[i] = get_byte_var(i % 8, in[0]); - } -} - -template -void copy_out_vec_be(uint8_t out[], size_t out_bytes, const std::vector& in) { - copy_out_be(out, out_bytes, in.data()); -} - -template -void copy_out_le(uint8_t out[], size_t out_bytes, const T in[]) { - while(out_bytes >= sizeof(T)) { - store_le(in[0], out); - out += sizeof(T); - out_bytes -= sizeof(T); - in += 1; - } - - for(size_t i = 0; i != out_bytes; ++i) { - out[i] = get_byte_var(sizeof(T) - 1 - (i % 8), in[0]); - } -} - -template -void copy_out_vec_le(uint8_t out[], size_t out_bytes, const std::vector& in) { - copy_out_le(out, out_bytes, in.data()); -} - } // namespace Botan #endif diff --git a/src/lib/utils/poly_dbl/poly_dbl.cpp b/src/lib/utils/poly_dbl/poly_dbl.cpp index 0ff5255d7b2..e1d1a68e95a 100644 --- a/src/lib/utils/poly_dbl/poly_dbl.cpp +++ b/src/lib/utils/poly_dbl/poly_dbl.cpp @@ -46,7 +46,7 @@ void poly_double(uint8_t out[], const uint8_t in[]) { W[LIMBS - 1] = (W[LIMBS - 1] << 1) ^ carry; - copy_out_be(out, LIMBS * 8, W); + copy_out_be(std::span(out, LIMBS * 8), W); } template @@ -66,7 +66,7 @@ void poly_double_le(uint8_t out[], const uint8_t in[]) { W[0] = (W[0] << 1) ^ carry; - copy_out_le(out, LIMBS * 8, W); + copy_out_le(std::span(out, LIMBS * 8), W); } } // namespace