Coverage Report

Created: 2023-06-07 07:00

/src/botan/src/lib/hash/trunc_hash/trunc_hash.cpp
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Wrapper for truncated hashes
3
 * (C) 2023 Jack Lloyd
4
 *     2023 René Meusel - Rohde & Schwarz Cybersecurity
5
 *
6
 * Botan is released under the Simplified BSD License (see license.txt)
7
 */
8
9
#include <botan/internal/trunc_hash.h>
10
11
#include <botan/exceptn.h>
12
#include <botan/internal/fmt.h>
13
14
namespace Botan {
15
16
0
void Truncated_Hash::add_data(const uint8_t input[], size_t length) { m_hash->update(input, length); }
17
18
0
void Truncated_Hash::final_result(uint8_t out[]) {
19
0
   BOTAN_ASSERT_NOMSG(m_hash->output_length() * 8 >= m_output_bits);
20
21
0
   const auto full_output = m_hash->final();
22
23
   // truncate output to a full number of bytes
24
0
   const auto bytes = output_length();
25
0
   std::copy_n(full_output.begin(), bytes, out);
26
27
   // mask the unwanted bits in the final byte
28
0
   const uint8_t bits_in_last_byte = ((m_output_bits - 1) % 8) + 1;
29
0
   const uint8_t bitmask = ~((1 << (8 - bits_in_last_byte)) - 1);
30
31
0
   out[bytes - 1] &= bitmask;
32
0
}
33
34
0
size_t Truncated_Hash::output_length() const { return (m_output_bits + 7) / 8; }
35
36
0
std::string Truncated_Hash::name() const { return fmt("Truncated({},{})", m_hash->name(), m_output_bits); }
37
38
0
std::unique_ptr<HashFunction> Truncated_Hash::new_object() const {
39
0
   return std::make_unique<Truncated_Hash>(m_hash->new_object(), m_output_bits);
40
0
}
41
42
0
std::unique_ptr<HashFunction> Truncated_Hash::copy_state() const {
43
0
   return std::make_unique<Truncated_Hash>(m_hash->copy_state(), m_output_bits);
44
0
}
45
46
0
void Truncated_Hash::clear() { m_hash->clear(); }
47
48
Truncated_Hash::Truncated_Hash(std::unique_ptr<HashFunction> hash, size_t bits) :
49
0
      m_hash(std::move(hash)), m_output_bits(bits) {
50
0
   BOTAN_ASSERT_NONNULL(m_hash);
51
52
0
   if(m_output_bits == 0) {
53
0
      throw Invalid_Argument("Truncating a hash to 0 does not make sense");
54
0
   }
55
56
0
   if(m_hash->output_length() * 8 < m_output_bits) {
57
0
      throw Invalid_Argument("Underlying hash function does not produce enough bytes for truncation");
58
0
   }
59
0
}
60
61
}  // namespace Botan