12#include <botan/internal/blake2s.h>
14#include <botan/exceptn.h>
15#include <botan/internal/fmt.h>
16#include <botan/internal/loadstor.h>
17#include <botan/internal/rotate.h>
18#include <botan/internal/stl_util.h>
26constexpr std::array<uint32_t, 8> blake2s_iv{
27 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19};
31template <u
int8_t a, u
int8_t b, u
int8_t c, u
int8_t d>
32 requires(a < 16 && b < 16 && c < 16 && d < 16)
33constexpr void B2S_G(uint32_t x, uint32_t y, std::span<uint32_t, 16> v) {
34 v[a] = v[a] + v[b] + x;
38 v[a] = v[a] + v[b] + y;
47 return fmt(
"BLAKE2s({})", m_outlen << 3);
53void BLAKE2s::state_init(
size_t outlen) {
55 m_h[0] ^= 0x01010000 ^ outlen;
57 m_bytes_processed = 0;
63void BLAKE2s::compress(
bool last, std::span<const uint8_t> buf) {
65 constexpr std::array<std::array<uint8_t, 16>, 10>
sigma{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
66 {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
67 {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
68 {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
69 {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
70 {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
71 {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
72 {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
73 {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
74 {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}}};
77 std::array<uint32_t, 16> v =
concat(m_h, blake2s_iv);
79 v[12] ^=
static_cast<uint32_t
>(m_bytes_processed);
80 v[13] ^=
static_cast<uint32_t
>(m_bytes_processed >> 32);
87 for(
const auto& perm :
sigma) {
88 B2S_G<0, 4, 8, 12>(m[perm[0]], m[perm[1]], v);
89 B2S_G<1, 5, 9, 13>(m[perm[2]], m[perm[3]], v);
90 B2S_G<2, 6, 10, 14>(m[perm[4]], m[perm[5]], v);
91 B2S_G<3, 7, 11, 15>(m[perm[6]], m[perm[7]], v);
92 B2S_G<0, 5, 10, 15>(m[perm[8]], m[perm[9]], v);
93 B2S_G<1, 6, 11, 12>(m[perm[10]], m[perm[11]], v);
94 B2S_G<2, 7, 8, 13>(m[perm[12]], m[perm[13]], v);
95 B2S_G<3, 4, 9, 14>(m[perm[14]], m[perm[15]], v);
98 for(
size_t i = 0; i < 8; ++i) {
99 m_h[i] ^= v[i] ^ v[i + 8];
107 state_init(m_outlen);
110void BLAKE2s::add_data(std::span<const uint8_t> input) {
115 m_bytes_processed += block_size;
116 compress(
false, *one_block);
121 m_bytes_processed += block_size;
122 compress(
false, *aligned_block);
128void BLAKE2s::final_result(std::span<uint8_t> out) {
129 m_bytes_processed += m_buffer.elements_in_buffer();
131 m_buffer.fill_up_with_zeros();
132 compress(
true, m_buffer.consume());
141 return std::make_unique<BLAKE2s>(*
this);
148 if(output_bits == 0 || output_bits > 256 || output_bits % 8 != 0) {
151 state_init(output_bits >> 3);
#define BOTAN_ASSERT_NOMSG(expr)
std::optional< std::span< const uint8_t > > next_aligned_block_to_process(BufferSlicer &slicer) const
std::optional< std::span< const T > > handle_unaligned_data(BufferSlicer &slicer)
bool in_alignment() const
std::unique_ptr< HashFunction > copy_state() const override
BLAKE2s(size_t output_bits=256)
std::string name() const override
size_t output_length() const override
std::string fmt(std::string_view format, const T &... args)
void copy_out_le(std::span< uint8_t > out, const InR &in)
BOTAN_FORCE_INLINE constexpr T rotr(T input)
void secure_scrub_memory(void *ptr, size_t n)
constexpr auto concat(Rs &&... ranges)
BOTAN_FORCE_INLINE constexpr T sigma(T x)
constexpr auto load_le(ParamTs &&... params)