Botan  2.11.0
Crypto and TLS for C++11
mdx_hash.cpp
Go to the documentation of this file.
1 /*
2 * Merkle-Damgard Hash Function
3 * (C) 1999-2008,2018 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/mdx_hash.h>
9 #include <botan/exceptn.h>
10 #include <botan/loadstor.h>
11 #include <botan/internal/bit_ops.h>
12 
13 namespace Botan {
14 
15 /*
16 * MDx_HashFunction Constructor
17 */
18 MDx_HashFunction::MDx_HashFunction(size_t block_len,
19  bool byte_big_endian,
20  bool bit_big_endian,
21  uint8_t cnt_size) :
22  m_pad_char(bit_big_endian == true ? 0x80 : 0x01),
23  m_counter_size(cnt_size),
24  m_block_bits(static_cast<uint8_t>(ceil_log2(block_len))),
25  m_count_big_endian(byte_big_endian),
26  m_count(0),
27  m_buffer(block_len),
28  m_position(0)
29  {
30  if(!is_power_of_2(block_len))
31  throw Invalid_Argument("MDx_HashFunction block length must be a power of 2");
32  if(m_block_bits < 3 || m_block_bits > 16)
33  throw Invalid_Argument("MDx_HashFunction block size too large or too small");
34  if(m_counter_size < 8 || m_counter_size > block_len)
35  throw Invalid_State("MDx_HashFunction invalid counter length");
36  }
37 
38 /*
39 * Clear memory of sensitive data
40 */
41 void MDx_HashFunction::clear()
42  {
43  zeroise(m_buffer);
44  m_count = m_position = 0;
45  }
46 
47 /*
48 * Update the hash
49 */
50 void MDx_HashFunction::add_data(const uint8_t input[], size_t length)
51  {
52  const size_t block_len = static_cast<size_t>(1) << m_block_bits;
53 
54  m_count += length;
55 
56  if(m_position)
57  {
58  buffer_insert(m_buffer, m_position, input, length);
59 
60  if(m_position + length >= block_len)
61  {
62  compress_n(m_buffer.data(), 1);
63  input += (block_len - m_position);
64  length -= (block_len - m_position);
65  m_position = 0;
66  }
67  }
68 
69  // Just in case the compiler can't figure out block_len is a power of 2
70  const size_t full_blocks = length >> m_block_bits;
71  const size_t remaining = length & (block_len - 1);
72 
73  if(full_blocks > 0)
74  {
75  compress_n(input, full_blocks);
76  }
77 
78  buffer_insert(m_buffer, m_position, input + full_blocks * block_len, remaining);
79  m_position += remaining;
80  }
81 
82 /*
83 * Finalize a hash
84 */
85 void MDx_HashFunction::final_result(uint8_t output[])
86  {
87  const size_t block_len = static_cast<size_t>(1) << m_block_bits;
88 
89  clear_mem(&m_buffer[m_position], block_len - m_position);
90  m_buffer[m_position] = m_pad_char;
91 
92  if(m_position >= block_len - m_counter_size)
93  {
94  compress_n(m_buffer.data(), 1);
95  zeroise(m_buffer);
96  }
97 
98  write_count(&m_buffer[block_len - m_counter_size]);
99 
100  compress_n(m_buffer.data(), 1);
101  copy_out(output);
102  clear();
103  }
104 
105 /*
106 * Write the count bits to the buffer
107 */
108 void MDx_HashFunction::write_count(uint8_t out[])
109  {
110  BOTAN_ASSERT_NOMSG(m_counter_size <= output_length());
111  BOTAN_ASSERT_NOMSG(m_counter_size >= 8);
112 
113  const uint64_t bit_count = m_count * 8;
114 
115  if(m_count_big_endian)
116  store_be(bit_count, out + m_counter_size - 8);
117  else
118  store_le(bit_count, out + m_counter_size - 8);
119  }
120 
121 }
uint32_t uint8_t output[]
Definition: ffi.h:512
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:436
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:111
size_t * output_length
Definition: ffi.h:280
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68
size_t char * out
Definition: ffi.h:162
constexpr bool is_power_of_2(T arg)
Definition: bit_ops.h:43
Definition: alg_id.cpp:13
size_t ceil_log2(T x)
Definition: bit_ops.h:119
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