/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 |