Coverage Report

Created: 2022-06-23 06:44

/src/botan/src/lib/hash/comb4p/comb4p.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Comb4P hash combiner
3
* (C) 2010 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/comb4p.h>
9
#include <botan/exceptn.h>
10
11
namespace Botan {
12
13
namespace {
14
15
void comb4p_round(secure_vector<uint8_t>& out,
16
                  const secure_vector<uint8_t>& in,
17
                  uint8_t round_no,
18
                  HashFunction& h1,
19
                  HashFunction& h2)
20
0
   {
21
0
   h1.update(round_no);
22
0
   h2.update(round_no);
23
24
0
   h1.update(in.data(), in.size());
25
0
   h2.update(in.data(), in.size());
26
27
0
   secure_vector<uint8_t> h_buf = h1.final();
28
0
   xor_buf(out.data(), h_buf.data(), std::min(out.size(), h_buf.size()));
29
30
0
   h_buf = h2.final();
31
0
   xor_buf(out.data(), h_buf.data(), std::min(out.size(), h_buf.size()));
32
0
   }
33
34
}
35
36
Comb4P::Comb4P(std::unique_ptr<HashFunction> h1, std::unique_ptr<HashFunction> h2) :
37
   m_hash1(std::move(h1)),
38
   m_hash2(std::move(h2))
39
0
   {
40
0
   if(m_hash1->name() == m_hash2->name())
41
0
      throw Invalid_Argument("Comb4P: Must use two distinct hashes");
42
43
0
   if(m_hash1->output_length() != m_hash2->output_length())
44
0
      throw Invalid_Argument("Comb4P: Incompatible hashes " +
45
0
                                  m_hash1->name() + " and " +
46
0
                                  m_hash2->name());
47
48
0
   clear();
49
0
   }
50
51
size_t Comb4P::hash_block_size() const
52
0
   {
53
0
   if(m_hash1->hash_block_size() == m_hash2->hash_block_size())
54
0
      return m_hash1->hash_block_size();
55
56
   /*
57
   * Return LCM of the block sizes? This would probably be OK for
58
   * HMAC, which is the main thing relying on knowing the block size.
59
   */
60
0
   return 0;
61
0
   }
62
63
void Comb4P::clear()
64
0
   {
65
0
   m_hash1->clear();
66
0
   m_hash2->clear();
67
68
   // Prep for processing next message, if any
69
0
   m_hash1->update(0);
70
0
   m_hash2->update(0);
71
0
   }
72
73
std::unique_ptr<HashFunction> Comb4P::copy_state() const
74
0
   {
75
   // Can't use make_unique as this constructor is private
76
0
   std::unique_ptr<Comb4P> copy(new Comb4P);
77
0
   copy->m_hash1 = m_hash1->copy_state();
78
0
   copy->m_hash2 = m_hash2->copy_state();
79
0
   return copy;
80
0
   }
81
82
void Comb4P::add_data(const uint8_t input[], size_t length)
83
0
   {
84
0
   m_hash1->update(input, length);
85
0
   m_hash2->update(input, length);
86
0
   }
87
88
void Comb4P::final_result(uint8_t out[])
89
0
   {
90
0
   secure_vector<uint8_t> h1 = m_hash1->final();
91
0
   secure_vector<uint8_t> h2 = m_hash2->final();
92
93
   // First round
94
0
   xor_buf(h1.data(), h2.data(), std::min(h1.size(), h2.size()));
95
96
   // Second round
97
0
   comb4p_round(h2, h1, 1, *m_hash1, *m_hash2);
98
99
   // Third round
100
0
   comb4p_round(h1, h2, 2, *m_hash1, *m_hash2);
101
102
0
   copy_mem(out            , h1.data(), h1.size());
103
0
   copy_mem(out + h1.size(), h2.data(), h2.size());
104
105
   // Prep for processing next message, if any
106
0
   m_hash1->update(0);
107
0
   m_hash2->update(0);
108
0
   }
109
110
}
111