Botan  1.11.16
comb4p.cpp
Go to the documentation of this file.
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/hash_utils.h>
9 #include <botan/comb4p.h>
10 #include <botan/internal/xor_buf.h>
11 #include <stdexcept>
12 
13 namespace Botan {
14 
15 BOTAN_REGISTER_NAMED_T(HashFunction, "Comb4P", Comb4P, Comb4P::make);
16 
17 namespace {
18 
19 void comb4p_round(secure_vector<byte>& out,
20  const secure_vector<byte>& in,
21  byte round_no,
22  HashFunction& h1,
23  HashFunction& h2)
24  {
25  h1.update(round_no);
26  h2.update(round_no);
27 
28  h1.update(&in[0], in.size());
29  h2.update(&in[0], in.size());
30 
31  secure_vector<byte> h_buf = h1.final();
32  xor_buf(&out[0], &h_buf[0], std::min(out.size(), h_buf.size()));
33 
34  h_buf = h2.final();
35  xor_buf(&out[0], &h_buf[0], std::min(out.size(), h_buf.size()));
36  }
37 
38 }
39 
40 Comb4P* Comb4P::make(const Spec& spec)
41  {
42  if(spec.arg_count() == 2)
43  {
44  std::unique_ptr<HashFunction> h1(make_hash_function(spec.arg(0)));
45  std::unique_ptr<HashFunction> h2(make_hash_function(spec.arg(1)));
46 
47  if(h1 && h2)
48  return new Comb4P(h1.release(), h2.release());
49  }
50  return nullptr;
51  }
52 
54  m_hash1(h1), m_hash2(h2)
55  {
56  if(m_hash1->name() == m_hash2->name())
57  throw std::invalid_argument("Comb4P: Must use two distinct hashes");
58 
59  if(m_hash1->output_length() != m_hash2->output_length())
60  throw std::invalid_argument("Comb4P: Incompatible hashes " +
61  m_hash1->name() + " and " +
62  m_hash2->name());
63 
64  clear();
65  }
66 
68  {
69  if(m_hash1->hash_block_size() == m_hash2->hash_block_size())
70  return m_hash1->hash_block_size();
71 
72  /*
73  * Return LCM of the block sizes? This would probably be OK for
74  * HMAC, which is the main thing relying on knowing the block size.
75  */
76  return 0;
77  }
78 
80  {
81  m_hash1->clear();
82  m_hash2->clear();
83 
84  // Prep for processing next message, if any
85  m_hash1->update(0);
86  m_hash2->update(0);
87  }
88 
89 void Comb4P::add_data(const byte input[], size_t length)
90  {
91  m_hash1->update(input, length);
92  m_hash2->update(input, length);
93  }
94 
95 void Comb4P::final_result(byte out[])
96  {
97  secure_vector<byte> h1 = m_hash1->final();
98  secure_vector<byte> h2 = m_hash2->final();
99 
100  // First round
101  xor_buf(&h1[0], &h2[0], std::min(h1.size(), h2.size()));
102 
103  // Second round
104  comb4p_round(h2, h1, 1, *m_hash1, *m_hash2);
105 
106  // Third round
107  comb4p_round(h1, h2, 2, *m_hash1, *m_hash2);
108 
109  copy_mem(out , &h1[0], h1.size());
110  copy_mem(out + h1.size(), &h2[0], h2.size());
111 
112  // Prep for processing next message, if any
113  m_hash1->update(0);
114  m_hash2->update(0);
115  }
116 
117 }
118 
void xor_buf(T out[], const T in[], size_t length)
Definition: xor_buf.h:23
void clear()
Definition: comb4p.cpp:79
std::string arg(size_t i) const
Definition: scan_name.cpp:156
Comb4P(HashFunction *h1, HashFunction *h2)
Definition: comb4p.cpp:53
size_t arg_count() const
Definition: scan_name.h:64
size_t hash_block_size() const
Definition: comb4p.cpp:67
static Comb4P * make(const Spec &spec)
Definition: comb4p.cpp:40
uint8_t byte
Definition: types.h:31
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:39
BOTAN_REGISTER_NAMED_T(BlockCipher,"Cascade", Cascade_Cipher, Cascade_Cipher::make)
std::unique_ptr< HashFunction > make_hash_function(const std::string &algo_spec, const std::string &provider)
Definition: lookup.cpp:63