Coverage Report

Created: 2020-02-14 15:38

/src/botan/src/lib/hash/mdx_hash/mdx_hash.cpp
Line
Count
Source (jump to first uncovered line)
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(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
134k
   {
30
134k
   if(!is_power_of_2(block_len))
31
0
      throw Invalid_Argument("MDx_HashFunction block length must be a power of 2");
32
134k
   if(m_block_bits < 3 || m_block_bits > 16)
33
0
      throw Invalid_Argument("MDx_HashFunction block size too large or too small");
34
134k
   if(m_counter_size < 8 || m_counter_size > block_len)
35
0
      throw Invalid_State("MDx_HashFunction invalid counter length");
36
134k
   }
37
38
/*
39
* Clear memory of sensitive data
40
*/
41
void MDx_HashFunction::clear()
42
587k
   {
43
587k
   zeroise(m_buffer);
44
587k
   m_count = m_position = 0;
45
587k
   }
46
47
/*
48
* Update the hash
49
*/
50
void MDx_HashFunction::add_data(const uint8_t input[], size_t length)
51
824k
   {
52
824k
   const size_t block_len = static_cast<size_t>(1) << m_block_bits;
53
824k
54
824k
   m_count += length;
55
824k
56
824k
   if(m_position)
57
88.2k
      {
58
88.2k
      buffer_insert(m_buffer, m_position, input, length);
59
88.2k
60
88.2k
      if(m_position + length >= block_len)
61
45.3k
         {
62
45.3k
         compress_n(m_buffer.data(), 1);
63
45.3k
         input += (block_len - m_position);
64
45.3k
         length -= (block_len - m_position);
65
45.3k
         m_position = 0;
66
45.3k
         }
67
88.2k
      }
68
824k
69
824k
   // Just in case the compiler can't figure out block_len is a power of 2
70
824k
   const size_t full_blocks = length >> m_block_bits;
71
824k
   const size_t remaining   = length & (block_len - 1);
72
824k
73
824k
   if(full_blocks > 0)
74
407k
      {
75
407k
      compress_n(input, full_blocks);
76
407k
      }
77
824k
78
824k
   buffer_insert(m_buffer, m_position, input + full_blocks * block_len, remaining);
79
824k
   m_position += remaining;
80
824k
   }
81
82
/*
83
* Finalize a hash
84
*/
85
void MDx_HashFunction::final_result(uint8_t output[])
86
412k
   {
87
412k
   const size_t block_len = static_cast<size_t>(1) << m_block_bits;
88
412k
89
412k
   clear_mem(&m_buffer[m_position], block_len - m_position);
90
412k
   m_buffer[m_position] = m_pad_char;
91
412k
92
412k
   if(m_position >= block_len - m_counter_size)
93
35.4k
      {
94
35.4k
      compress_n(m_buffer.data(), 1);
95
35.4k
      zeroise(m_buffer);
96
35.4k
      }
97
412k
98
412k
   write_count(&m_buffer[block_len - m_counter_size]);
99
412k
100
412k
   compress_n(m_buffer.data(), 1);
101
412k
   copy_out(output);
102
412k
   clear();
103
412k
   }
104
105
/*
106
* Write the count bits to the buffer
107
*/
108
void MDx_HashFunction::write_count(uint8_t out[])
109
412k
   {
110
412k
   BOTAN_ASSERT_NOMSG(m_counter_size <= output_length());
111
412k
   BOTAN_ASSERT_NOMSG(m_counter_size >= 8);
112
412k
113
412k
   const uint64_t bit_count = m_count * 8;
114
412k
115
412k
   if(m_count_big_endian)
116
412k
      store_be(bit_count, out + m_counter_size - 8);
117
198
   else
118
198
      store_le(bit_count, out + m_counter_size - 8);
119
412k
   }
120
121
}