Botan  2.8.0
Crypto and TLS for C++11
streebog.cpp
Go to the documentation of this file.
1 /*
2 * Streebog
3 * (C) 2017 Ribose Inc.
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/streebog.h>
9 #include <botan/exceptn.h>
10 
11 namespace Botan {
12 
13 extern const uint64_t STREEBOG_Ax[8][256];
14 extern const uint64_t STREEBOG_C[12][8];
15 
16 std::unique_ptr<HashFunction> Streebog::copy_state() const
17  {
18  return std::unique_ptr<HashFunction>(new Streebog(*this));
19  }
20 
21 namespace {
22 
23 static inline void addm(const uint8_t* m, uint64_t* h)
24  {
25  uint64_t carry = false;
26  for(int i = 0; i < 8; i++)
27  {
28  const uint64_t m64 = load_le<uint64_t>(m, i);
29  const uint64_t hi = load_le<uint64_t>(reinterpret_cast<uint8_t*>(h), i);
30  const uint64_t t = hi + m64;
31 
32  const uint64_t overflow = (t < hi ? 1 : 0) | (t < m64 ? 1 : 0);
33  store_le(t + carry, reinterpret_cast<uint8_t*>(&h[i]));
34  carry = overflow;
35  }
36  }
37 
38 inline void lps(uint64_t* block)
39  {
40  uint8_t r[64];
41  std::memcpy(r, block, 64);
42 
43  for(int i = 0; i < 8; ++i)
44  {
45  block[i] = load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[0][r[i]]), 0) ^
46  load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[1][r[i + 8]]), 0) ^
47  load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[2][r[i + 16]]), 0) ^
48  load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[3][r[i + 24]]), 0) ^
49  load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[4][r[i + 32]]), 0) ^
50  load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[5][r[i + 40]]), 0) ^
51  load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[6][r[i + 48]]), 0) ^
52  load_le<uint64_t>(reinterpret_cast<const uint8_t*>(&STREEBOG_Ax[7][r[i + 56]]), 0);
53  }
54  }
55 
56 inline void e(uint64_t* K, const uint64_t* m)
57  {
58  uint64_t A[8];
59  uint64_t C[8];
60 
61  copy_mem(A, K, 8);
62 
63  for(size_t i = 0; i != 8; ++i)
64  {
65  K[i] ^= m[i];
66  }
67 
68  for(size_t i = 0; i < 12; ++i)
69  {
70  lps(K);
71  load_le(C, reinterpret_cast<const uint8_t*>(&STREEBOG_C[i][0]), 8);
72 
73  for(size_t j = 0; j != 8; ++j)
74  A[j] ^= C[j];
75  lps(A);
76  for(size_t j = 0; j != 8; ++j)
77  K[j] ^= A[j];
78  }
79  }
80 
81 inline void g(uint64_t* h, const uint8_t* m, uint64_t N)
82  {
83  uint64_t hN[8];
84 
85  // force N to little-endian
86  store_le(N, reinterpret_cast<uint8_t*>(&N));
87 
88  copy_mem(hN, h, 8);
89  hN[0] ^= N;
90  lps(hN);
91  const uint64_t* m64 = reinterpret_cast<const uint64_t*>(m);
92 
93  e(hN, m64);
94 
95  for(size_t i = 0; i != 8; ++i)
96  {
97  h[i] ^= hN[i] ^ m64[i];
98  }
99  }
100 
101 } //namespace
102 
103 Streebog::Streebog(size_t output_bits) :
104  m_output_bits(output_bits),
105  m_count(0),
106  m_position(0),
107  m_buffer(64),
108  m_h(8),
109  m_S(8)
110  {
111  if(output_bits != 256 && output_bits != 512)
112  throw Invalid_Argument("Streebog: Invalid output length " +
113  std::to_string(output_bits));
114 
115  clear();
116  }
117 
118 std::string Streebog::name() const
119  {
120  return "Streebog-" + std::to_string(m_output_bits);
121  }
122 
123 /*
124 * Clear memory of sensitive data
125 */
127  {
128  m_count = 0;
129  m_position = 0;
130  zeroise(m_buffer);
131  zeroise(m_S);
132 
133  const uint64_t fill = (m_output_bits == 512) ? 0 : 0x0101010101010101;
134  std::fill(m_h.begin(), m_h.end(), fill);
135  }
136 
137 /*
138 * Update the hash
139 */
140 void Streebog::add_data(const uint8_t input[], size_t length)
141  {
142  while(m_position + length >= 64)
143  {
144  buffer_insert(m_buffer, m_position, input, 64 - m_position);
145  compress(m_buffer.data());
146  m_count += 512;
147  input += (64 - m_position);
148  length -= (64 - m_position);
149  m_position = 0;
150  }
151 
152  buffer_insert(m_buffer, m_position, input, length);
153  m_position += length;
154  }
155 
156 /*
157 * Finalize a hash
158 */
159 void Streebog::final_result(uint8_t output[])
160  {
161  m_buffer[m_position++] = 0x01;
162 
163  if(m_position != m_buffer.size())
164  clear_mem(&m_buffer[m_position], m_buffer.size() - m_position);
165 
166  compress(m_buffer.data());
167  m_count += (m_position - 1) * 8;
168 
169  zeroise(m_buffer);
170  store_le(m_count, m_buffer.data());
171  compress(m_buffer.data(), true);
172 
173  compress(reinterpret_cast<const uint8_t*>(m_S.data()), true);
174  std::memcpy(output, &m_h[8 - output_length() / 8], output_length());
175  clear();
176  }
177 
178 void Streebog::compress(const uint8_t input[], bool last_block)
179  {
180  g(m_h.data(), input, last_block ? 0ULL : m_count);
181  if(!last_block)
182  { addm(input, m_S.data()); }
183  }
184 
185 }
std::string name() const override
Definition: streebog.cpp:118
void carry(int64_t &h0, int64_t &h1)
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:97
size_t output_length() const override
Definition: streebog.h:22
const uint64_t STREEBOG_C[12][8]
void clear() override
Definition: streebog.cpp:126
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
std::unique_ptr< HashFunction > copy_state() const override
Definition: streebog.cpp:16
void add_data(const uint8_t input[], size_t length) override
Definition: streebog.cpp:140
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:235
T load_le(const uint8_t in[], size_t off)
Definition: loadstor.h:121
void compress(const uint8_t input[], bool lastblock=false)
Definition: streebog.cpp:178
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
void final_result(uint8_t out[]) override
Definition: streebog.cpp:159
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:103
const uint64_t STREEBOG_Ax[8][256]
Streebog(size_t output_bits)
Definition: streebog.cpp:103
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:450
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:183