8#include <botan/internal/skein_512.h>
10#include <botan/exceptn.h>
11#include <botan/internal/fmt.h>
12#include <botan/internal/loadstor.h>
13#include <botan/internal/stl_util.h>
19 m_personalization(arg_personalization),
20 m_output_bits(arg_output_bits),
23 if(m_output_bits == 0 || m_output_bits % 8 != 0 || m_output_bits > 512) {
31 if(m_personalization.empty()) {
32 return fmt(
"Skein-512({})", m_output_bits);
34 return fmt(
"Skein-512({},{})", m_output_bits, m_personalization);
39 return std::make_unique<Skein_512>(m_output_bits, m_personalization);
43 auto copy = std::make_unique<Skein_512>(m_output_bits, m_personalization);
44 copy->m_threefish->m_K = this->m_threefish->m_K;
45 copy->m_T = this->m_T;
46 copy->m_buffer = this->m_buffer;
56void Skein_512::reset_tweak(type_code type,
bool is_final) {
60 (
static_cast<uint64_t
>(type) << 56) | (
static_cast<uint64_t
>(1) << 62) | (
static_cast<uint64_t
>(is_final) << 63);
63void Skein_512::initial_block() {
64 const uint8_t zeros[64] = {0};
66 m_threefish->set_key(zeros,
sizeof(zeros));
69 uint8_t config_str[32] = {0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0};
70 store_le(uint32_t(m_output_bits), config_str + 8);
72 reset_tweak(SKEIN_CONFIG,
true);
73 ubi_512(config_str,
sizeof(config_str));
75 if(!m_personalization.empty()) {
81 if(m_personalization.length() > 64) {
82 throw Invalid_Argument(
"Skein personalization must be less than 64 bytes");
86 reset_tweak(SKEIN_PERSONALIZATION,
true);
87 ubi_512(bits, m_personalization.length());
90 reset_tweak(SKEIN_MSG,
false);
93void Skein_512::ubi_512(
const uint8_t msg[],
size_t msg_len) {
97 const size_t to_proc = std::min<size_t>(msg_len, 64);
100 load_le(M.data(), msg, to_proc / 8);
103 for(
size_t j = 0; j != to_proc % 8; ++j) {
104 M[to_proc / 8] |=
static_cast<uint64_t
>(msg[8 * (to_proc / 8) + j]) << (8 * j);
108 m_threefish->skein_feedfwd(M, m_T);
111 m_T[1] &= ~(
static_cast<uint64_t
>(1) << 62);
118void Skein_512::add_data(std::span<const uint8_t> input) {
119 BufferSlicer in(input);
123 ubi_512(one_block->data(), one_block->size());
128 if(full_blocks > 0) {
129 ubi_512(aligned_data.data(), aligned_data.size());
135void Skein_512::final_result(std::span<uint8_t> out) {
136 m_T[1] |= (
static_cast<uint64_t
>(1) << 63);
140 ubi_512(m_buffer.
consume().data(), pos);
142 const uint8_t counter[8] = {0};
144 reset_tweak(SKEIN_OUTPUT,
true);
145 ubi_512(counter,
sizeof(counter));
147 copy_out_le(out.first(m_output_bits / 8), m_threefish->m_K);
size_t elements_in_buffer() const
std::tuple< std::span< const uint8_t >, size_t > aligned_data_to_process(BufferSlicer &slicer) const
std::optional< std::span< const T > > handle_unaligned_data(BufferSlicer &slicer)
std::span< const T > consume()
void fill_up_with_zeros()
bool in_alignment() const
std::unique_ptr< HashFunction > copy_state() const override
std::unique_ptr< HashFunction > new_object() const override
std::string name() const override
Skein_512(size_t output_bits=512, std::string_view personalization="")
std::string fmt(std::string_view format, const T &... args)
constexpr auto store_le(ParamTs &&... params)
void copy_out_le(std::span< uint8_t > out, InR &&in)
constexpr auto load_le(ParamTs &&... params)
std::vector< T, secure_allocator< T > > secure_vector
const uint8_t * cast_char_ptr_to_uint8(const char *s)