8#include <botan/skein_512.h>
9#include <botan/loadstor.h>
10#include <botan/exceptn.h>
16 const std::string& arg_personalization) :
17 m_personalization(arg_personalization),
18 m_output_bits(arg_output_bits),
20 m_T(2), m_buffer(64), m_buf_pos(0)
22 if(m_output_bits == 0 || m_output_bits % 8 != 0 || m_output_bits > 512)
30 if(m_personalization !=
"")
31 return "Skein-512(" + std::to_string(m_output_bits) +
"," +
32 m_personalization +
")";
33 return "Skein-512(" + std::to_string(m_output_bits) +
")";
38 return new Skein_512(m_output_bits, m_personalization);
43 std::unique_ptr<Skein_512> copy(
new Skein_512(m_output_bits, m_personalization));
45 copy->m_threefish->m_K = this->m_threefish->m_K;
46 copy->m_T = this->m_T;
47 copy->m_buffer = this->m_buffer;
48 copy->m_buf_pos = this->m_buf_pos;
51 return std::unique_ptr<HashFunction>(copy.release());
62void Skein_512::reset_tweak(type_code
type,
bool is_final)
66 m_T[1] = (
static_cast<uint64_t
>(
type) << 56) |
67 (
static_cast<uint64_t
>(1) << 62) |
68 (
static_cast<uint64_t
>(is_final) << 63);
71void Skein_512::initial_block()
73 const uint8_t zeros[64] = { 0 };
75 m_threefish->set_key(zeros,
sizeof(zeros));
78 uint8_t config_str[32] = { 0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0 };
79 store_le(uint32_t(m_output_bits), config_str + 8);
81 reset_tweak(SKEIN_CONFIG,
true);
82 ubi_512(config_str,
sizeof(config_str));
84 if(m_personalization !=
"")
91 if(m_personalization.length() > 64)
92 throw Invalid_Argument(
"Skein personalization must be less than 64 bytes");
95 reset_tweak(SKEIN_PERSONALIZATION,
true);
96 ubi_512(bits, m_personalization.length());
99 reset_tweak(SKEIN_MSG,
false);
102void Skein_512::ubi_512(
const uint8_t msg[],
size_t msg_len)
104 secure_vector<uint64_t> M(8);
108 const size_t to_proc = std::min<size_t>(msg_len, 64);
111 load_le(M.data(), msg, to_proc / 8);
115 for(
size_t j = 0; j != to_proc % 8; ++j)
116 M[to_proc/8] |=
static_cast<uint64_t
>(msg[8*(to_proc/8)+j]) << (8*j);
119 m_threefish->skein_feedfwd(M, m_T);
122 m_T[1] &= ~(
static_cast<uint64_t
>(1) << 62);
129void Skein_512::add_data(
const uint8_t input[],
size_t length)
137 if(m_buf_pos + length > 64)
139 ubi_512(m_buffer.data(), m_buffer.size());
141 input += (64 - m_buf_pos);
142 length -= (64 - m_buf_pos);
147 const size_t full_blocks = (length - 1) / 64;
150 ubi_512(input, 64*full_blocks);
152 length -= full_blocks * 64;
154 buffer_insert(m_buffer, m_buf_pos, input + full_blocks * 64, length);
158void Skein_512::final_result(uint8_t out[])
160 m_T[1] |= (
static_cast<uint64_t
>(1) << 63);
162 for(
size_t i = m_buf_pos; i != m_buffer.size(); ++i)
165 ubi_512(m_buffer.data(), m_buf_pos);
167 const uint8_t counter[8] = { 0 };
169 reset_tweak(SKEIN_OUTPUT,
true);
170 ubi_512(counter,
sizeof(counter));
HashFunction * clone() const override
std::unique_ptr< HashFunction > copy_state() const override
Skein_512(size_t output_bits=512, const std::string &personalization="")
std::string name() const override
void zeroise(std::vector< T, Alloc > &vec)
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
void copy_out_vec_le(uint8_t out[], size_t out_bytes, const std::vector< T, Alloc > &in)
T load_le(const uint8_t in[], size_t off)
void store_le(uint16_t in, uint8_t out[2])
const uint8_t * cast_char_ptr_to_uint8(const char *s)