Botan  2.11.0
Crypto and TLS for C++11
skein_512.cpp
Go to the documentation of this file.
1 /*
2 * The Skein-512 hash function
3 * (C) 2009,2010,2014 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/skein_512.h>
9 #include <botan/exceptn.h>
10 #include <algorithm>
11 
12 namespace Botan {
13 
14 Skein_512::Skein_512(size_t arg_output_bits,
15  const std::string& arg_personalization) :
16  m_personalization(arg_personalization),
17  m_output_bits(arg_output_bits),
18  m_threefish(new Threefish_512),
19  m_T(2), m_buffer(64), m_buf_pos(0)
20  {
21  if(m_output_bits == 0 || m_output_bits % 8 != 0 || m_output_bits > 512)
22  throw Invalid_Argument("Bad output bits size for Skein-512");
23 
24  initial_block();
25  }
26 
27 std::string Skein_512::name() const
28  {
29  if(m_personalization != "")
30  return "Skein-512(" + std::to_string(m_output_bits) + "," +
31  m_personalization + ")";
32  return "Skein-512(" + std::to_string(m_output_bits) + ")";
33  }
34 
35 HashFunction* Skein_512::clone() const
36  {
37  return new Skein_512(m_output_bits, m_personalization);
38  }
39 
40 std::unique_ptr<HashFunction> Skein_512::copy_state() const
41  {
42  std::unique_ptr<Skein_512> copy(new Skein_512(m_output_bits, m_personalization));
43 
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;
47  copy->m_buf_pos = this->m_buf_pos;
48 
49  // work around GCC 4.8 bug
50  return std::unique_ptr<HashFunction>(copy.release());
51  }
52 
53 void Skein_512::clear()
54  {
55  zeroise(m_buffer);
56  m_buf_pos = 0;
57 
58  initial_block();
59  }
60 
61 void Skein_512::reset_tweak(type_code type, bool is_final)
62  {
63  m_T[0] = 0;
64 
65  m_T[1] = (static_cast<uint64_t>(type) << 56) |
66  (static_cast<uint64_t>(1) << 62) |
67  (static_cast<uint64_t>(is_final) << 63);
68  }
69 
70 void Skein_512::initial_block()
71  {
72  const uint8_t zeros[64] = { 0 };
73 
74  m_threefish->set_key(zeros, sizeof(zeros));
75 
76  // ASCII("SHA3") followed by version (0x0001) code
77  uint8_t config_str[32] = { 0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0 };
78  store_le(uint32_t(m_output_bits), config_str + 8);
79 
80  reset_tweak(SKEIN_CONFIG, true);
81  ubi_512(config_str, sizeof(config_str));
82 
83  if(m_personalization != "")
84  {
85  /*
86  This is a limitation of this implementation, and not of the
87  algorithm specification. Could be fixed relatively easily, but
88  doesn't seem worth the trouble.
89  */
90  if(m_personalization.length() > 64)
91  throw Invalid_Argument("Skein personalization must be less than 64 bytes");
92 
93  const uint8_t* bits = cast_char_ptr_to_uint8(m_personalization.data());
94  reset_tweak(SKEIN_PERSONALIZATION, true);
95  ubi_512(bits, m_personalization.length());
96  }
97 
98  reset_tweak(SKEIN_MSG, false);
99  }
100 
101 void Skein_512::ubi_512(const uint8_t msg[], size_t msg_len)
102  {
103  secure_vector<uint64_t> M(8);
104 
105  do
106  {
107  const size_t to_proc = std::min<size_t>(msg_len, 64);
108  m_T[0] += to_proc;
109 
110  load_le(M.data(), msg, to_proc / 8);
111 
112  if(to_proc % 8)
113  {
114  for(size_t j = 0; j != to_proc % 8; ++j)
115  M[to_proc/8] |= static_cast<uint64_t>(msg[8*(to_proc/8)+j]) << (8*j);
116  }
117 
118  m_threefish->skein_feedfwd(M, m_T);
119 
120  // clear first flag if set
121  m_T[1] &= ~(static_cast<uint64_t>(1) << 62);
122 
123  msg_len -= to_proc;
124  msg += to_proc;
125  } while(msg_len);
126  }
127 
128 void Skein_512::add_data(const uint8_t input[], size_t length)
129  {
130  if(length == 0)
131  return;
132 
133  if(m_buf_pos)
134  {
135  buffer_insert(m_buffer, m_buf_pos, input, length);
136  if(m_buf_pos + length > 64)
137  {
138  ubi_512(m_buffer.data(), m_buffer.size());
139 
140  input += (64 - m_buf_pos);
141  length -= (64 - m_buf_pos);
142  m_buf_pos = 0;
143  }
144  }
145 
146  const size_t full_blocks = (length - 1) / 64;
147 
148  if(full_blocks)
149  ubi_512(input, 64*full_blocks);
150 
151  length -= full_blocks * 64;
152 
153  buffer_insert(m_buffer, m_buf_pos, input + full_blocks * 64, length);
154  m_buf_pos += length;
155  }
156 
157 void Skein_512::final_result(uint8_t out[])
158  {
159  m_T[1] |= (static_cast<uint64_t>(1) << 63); // final block flag
160 
161  for(size_t i = m_buf_pos; i != m_buffer.size(); ++i)
162  m_buffer[i] = 0;
163 
164  ubi_512(m_buffer.data(), m_buf_pos);
165 
166  const uint8_t counter[8] = { 0 };
167 
168  reset_tweak(SKEIN_OUTPUT, true);
169  ubi_512(counter, sizeof(counter));
170 
171  copy_out_vec_le(out, m_output_bits / 8, m_threefish->m_K);
172 
173  m_buf_pos = 0;
174  initial_block();
175  }
176 
177 }
class BOTAN_PUBLIC_API(2, 11) Argon2 final class BOTAN_PUBLIC_API(2, 11) Argon2_Family final void size_t const char size_t const uint8_t size_t const uint8_t size_t const uint8_t size_t uint8_t size_t size_t M
Definition: argon2.h:87
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:159
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
char * name
Definition: ffi.h:330
MechanismType type
size_t char * out
Definition: ffi.h:162
T load_le(const uint8_t in[], size_t off)
Definition: loadstor.h:121
Definition: alg_id.cpp:13
size_t bits
Definition: ffi.h:219
size_t const uint8_t input[]
Definition: base32.h:30
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:80
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:452
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:160
void copy_out_vec_le(uint8_t out[], size_t out_bytes, const std::vector< T, Alloc > &in)
Definition: loadstor.h:692