8 #include <botan/skein_512.h>
9 #include <botan/loadstor.h>
10 #include <botan/parsing.h>
11 #include <botan/exceptn.h>
12 #include <botan/rotate.h>
22 SKEIN_PERSONALIZATION = 8,
23 SKEIN_PUBLIC_KEY = 12,
24 SKEIN_KEY_IDENTIFIER = 16,
30 void ubi_512(MemoryRegion<u64bit>& H,
31 MemoryRegion<u64bit>& T,
32 const byte msg[],
size_t msg_len)
36 const size_t to_proc = std::min<size_t>(msg_len, 64);
45 for(
size_t j = 0; j != to_proc % 8; ++j)
46 M[to_proc/8] |= static_cast<u64bit>(msg[8*(to_proc/8)+j]) << (8*j);
49 H[8] = H[0] ^ H[1] ^ H[2] ^ H[3] ^
50 H[4] ^ H[5] ^ H[6] ^ H[7] ^ 0x1BD11BDAA9FC1A22;
59 u64bit X5 = M[5] + H[5] + T[0];
60 u64bit X6 = M[6] + H[6] + T[1];
63 #define THREEFISH_ROUND(I1,I2,I3,I4,I5,I6,I7,I8,ROT1,ROT2,ROT3,ROT4) \
65 X##I1 += X##I2; X##I2 = rotate_left(X##I2, ROT1) ^ X##I1; \
66 X##I3 += X##I4; X##I4 = rotate_left(X##I4, ROT2) ^ X##I3; \
67 X##I5 += X##I6; X##I6 = rotate_left(X##I6, ROT3) ^ X##I5; \
68 X##I7 += X##I8; X##I8 = rotate_left(X##I8, ROT4) ^ X##I7; \
71 #define THREEFISH_INJECT_KEY(r) \
78 X5 += H[(r+5) % 9] + T[(r ) % 3]; \
79 X6 += H[(r+6) % 9] + T[(r+1) % 3]; \
80 X7 += H[(r+7) % 9] + (r); \
83 #define THREEFISH_8_ROUNDS(R1,R2) \
85 THREEFISH_ROUND(0,1,2,3,4,5,6,7, 46,36,19,37); \
86 THREEFISH_ROUND(2,1,4,7,6,5,0,3, 33,27,14,42); \
87 THREEFISH_ROUND(4,1,6,3,0,5,2,7, 17,49,36,39); \
88 THREEFISH_ROUND(6,1,0,7,2,5,4,3, 44, 9,54,56); \
90 THREEFISH_INJECT_KEY(R1); \
92 THREEFISH_ROUND(0,1,2,3,4,5,6,7, 39,30,34,24); \
93 THREEFISH_ROUND(2,1,4,7,6,5,0,3, 13,50,10,17); \
94 THREEFISH_ROUND(4,1,6,3,0,5,2,7, 25,29,39,43); \
95 THREEFISH_ROUND(6,1,0,7,2,5,4,3, 8,35,56,22); \
97 THREEFISH_INJECT_KEY(R2); \
121 T[1] &= ~(
static_cast<u64bit>(1) << 62);
128 void reset_tweak(MemoryRegion<u64bit>& T,
129 type_code type,
bool final)
133 T[1] = (
static_cast<u64bit>(type) << 56) |
134 (
static_cast<u64bit>(1) << 62) |
135 (
static_cast<u64bit>(
final) << 63);
138 void initial_block(MemoryRegion<u64bit>& H,
139 MemoryRegion<u64bit>& T,
141 const std::string& personalization)
146 byte config_str[32] = { 0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0 };
149 reset_tweak(T, SKEIN_CONFIG,
true);
150 ubi_512(H, T, config_str,
sizeof(config_str));
152 if(personalization !=
"")
159 if(personalization.length() > 64)
162 const byte* bits =
reinterpret_cast<const byte*
>(personalization.data());
164 reset_tweak(T, SKEIN_PERSONALIZATION,
true);
165 ubi_512(H, T, bits, personalization.length());
168 reset_tweak(T, SKEIN_MSG,
false);
174 const std::string& arg_personalization) :
175 personalization(arg_personalization),
176 output_bits(arg_output_bits),
177 H(9), T(3), buffer(64), buf_pos(0)
179 if(output_bits == 0 || output_bits % 8 != 0 || output_bits > 64*1024)
182 initial_block(H, T, output_bits, personalization);
187 if(personalization !=
"")
188 return "Skein-512(" +
to_string(output_bits) +
"," + personalization +
")";
189 return "Skein-512(" +
to_string(output_bits) +
")";
194 return new Skein_512(output_bits, personalization);
205 void Skein_512::add_data(
const byte input[],
size_t length)
212 buffer.
copy(buf_pos, input, length);
213 if(buf_pos + length > 64)
215 ubi_512(H, T, &buffer[0], buffer.
size());
217 input += (64 - buf_pos);
218 length -= (64 - buf_pos);
223 const size_t full_blocks = (length - 1) / 64;
226 ubi_512(H, T, input, 64*full_blocks);
228 length -= full_blocks * 64;
230 buffer.
copy(buf_pos, input + full_blocks * 64, length);
234 void Skein_512::final_result(
byte out[])
236 T[1] |= (
static_cast<u64bit>(1) << 63);
238 for(
size_t i = buf_pos; i != buffer.
size(); ++i)
241 ubi_512(H, T, &buffer[0], buf_pos);
243 byte counter[8] = { 0 };
245 size_t out_bytes = output_bits / 8;
247 SecureVector<u64bit> H_out(9);
251 const size_t to_proc = std::min<size_t>(out_bytes, 64);
253 H_out.copy(&H[0], 8);
255 reset_tweak(T, SKEIN_OUTPUT,
true);
256 ubi_512(H_out, T, counter,
sizeof(counter));
258 for(
size_t i = 0; i != to_proc; ++i)
259 out[i] =
get_byte(7-i%8, H_out[i/8]);
261 out_bytes -= to_proc;
264 for(
size_t i = 0; i !=
sizeof(counter); ++i)
270 initial_block(H, T, output_bits, personalization);
T load_le(const byte in[], size_t off)
void store_le(u16bit in, byte out[2])
std::invalid_argument Invalid_Argument
byte get_byte(size_t byte_num, T input)
void copy(const T in[], size_t n)
unsigned long long u64bit
#define THREEFISH_8_ROUNDS(R1, R2)
HashFunction * clone() const
Skein_512(size_t output_bits=512, const std::string &personalization="")
std::string to_string(u64bit n, size_t min_len)
void zeroise(MemoryRegion< T > &vec)