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/mem_utils.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(std::span{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");
85 reset_tweak(SKEIN_PERSONALIZATION,
true);
89 reset_tweak(SKEIN_MSG,
false);
92void Skein_512::ubi_512(std::span<const uint8_t> msg) {
97 const size_t to_proc = std::min<size_t>(msg.size(), 64);
100 load_le(M.data(), msg.data(), to_proc / 8);
102 if(to_proc % 8 > 0) {
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);
113 msg = msg.subspan(to_proc);
114 }
while(!msg.empty());
117void Skein_512::add_data(std::span<const uint8_t> input) {
118 BufferSlicer in(input);
121 if(
const auto one_block = m_buffer.handle_unaligned_data(in)) {
122 ubi_512(one_block->data(), one_block->size());
125 if(m_buffer.in_alignment()) {
126 const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
127 if(full_blocks > 0) {
128 ubi_512(aligned_data.data(), aligned_data.size());
134void Skein_512::final_result(std::span<uint8_t> out) {
135 m_T[1] |= (
static_cast<uint64_t
>(1) << 63);
137 const auto pos = m_buffer.elements_in_buffer();
138 m_buffer.fill_up_with_zeros();
139 ubi_512(m_buffer.consume().data(), pos);
141 std::array<uint8_t, 8> counter{};
143 reset_tweak(SKEIN_OUTPUT,
true);
146 copy_out_le(out.first(m_output_bits / 8), m_threefish->m_K);
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::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
std::string fmt(std::string_view format, const T &... args)
void copy_out_le(std::span< uint8_t > out, const InR &in)
constexpr auto store_le(ParamTs &&... params)
constexpr auto load_le(ParamTs &&... params)
std::vector< T, secure_allocator< T > > secure_vector