Botan 3.3.0
Crypto and TLS for C&
mdx_hash.h
Go to the documentation of this file.
1/*
2* MDx Hash Function
3* (C) 1999-2008 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_MDX_BASE_H_
9#define BOTAN_MDX_BASE_H_
10
11#include <botan/hash.h>
12
13#include <botan/internal/alignment_buffer.h>
14#include <botan/internal/bit_ops.h>
15#include <botan/internal/loadstor.h>
16#include <botan/internal/stl_util.h>
17
18namespace Botan {
19
20enum class MD_Endian {
21 Little,
22 Big,
23};
24
25template <typename T>
28 requires(typename T::digest_type& digest, std::span<const uint8_t> input, size_t blocks) {
29 { T::init(digest) } -> std::same_as<void>;
30 { T::compress_n(digest, input, blocks) } -> std::same_as<void>;
31 T::bit_endianness;
32 T::byte_endianness;
33 T::block_bytes;
34 T::output_bytes;
35 T::ctr_bytes;
36 } && T::block_bytes >= 64 && is_power_of_2(T::block_bytes) && T::output_bytes >= 16 && T::ctr_bytes >= 8 &&
37 is_power_of_2(T::ctr_bytes) && T::ctr_bytes < T::block_bytes;
38
39template <md_hash_implementation MD>
41 public:
43
44 void update(std::span<const uint8_t> input) {
45 BufferSlicer in(input);
46
47 while(!in.empty()) {
48 if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
49 MD::compress_n(m_digest, one_block.value(), 1);
50 }
51
52 if(m_buffer.in_alignment()) {
53 const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
54 if(full_blocks > 0) {
55 MD::compress_n(m_digest, aligned_data, full_blocks);
56 }
57 }
58 }
59
60 m_count += input.size();
61 }
62
63 void final(std::span<uint8_t> output) {
64 append_padding_bit();
65 append_counter_and_finalize();
66 copy_output(output);
67 clear();
68 }
69
70 void clear() {
71 MD::init(m_digest);
72 m_buffer.clear();
73 m_count = 0;
74 }
75
76 private:
77 void append_padding_bit() {
79 if constexpr(MD::bit_endianness == MD_Endian::Big) {
80 const uint8_t final_byte = 0x80;
81 m_buffer.append({&final_byte, 1});
82 } else {
83 const uint8_t final_byte = 0x01;
84 m_buffer.append({&final_byte, 1});
85 }
86 }
87
88 void append_counter_and_finalize() {
89 // Compress the remaining data if the final data block does not provide
90 // enough space for the counter bytes.
91 if(m_buffer.elements_until_alignment() < MD::ctr_bytes) {
92 m_buffer.fill_up_with_zeros();
93 MD::compress_n(m_digest, m_buffer.consume(), 1);
94 }
95
96 // Make sure that any remaining bytes in the very last block are zero.
97 BOTAN_ASSERT_NOMSG(m_buffer.elements_until_alignment() >= MD::ctr_bytes);
98 m_buffer.fill_up_with_zeros();
99
100 // Replace a bunch of the right-most zero-padding with the counter bytes.
101 const uint64_t bit_count = m_count * 8;
102 auto last_bytes = m_buffer.directly_modify_last(sizeof(bit_count));
103 if constexpr(MD::byte_endianness == MD_Endian::Big) {
104 store_be(bit_count, last_bytes.data());
105 } else {
106 store_le(bit_count, last_bytes.data());
107 }
108
109 // Compress the very last block.
110 MD::compress_n(m_digest, m_buffer.consume(), 1);
111 }
112
113 void copy_output(std::span<uint8_t> output) {
114 BOTAN_ASSERT_NOMSG(output.size() >= MD::output_bytes);
115
116 if constexpr(MD::byte_endianness == MD_Endian::Big) {
117 copy_out_vec_be(output.data(), MD::output_bytes, m_digest);
118 } else {
119 copy_out_vec_le(output.data(), MD::output_bytes, m_digest);
120 }
121 }
122
123 private:
124 typename MD::digest_type m_digest;
125 uint64_t m_count;
126
127 AlignmentBuffer<uint8_t, MD::block_bytes> m_buffer;
128};
129
130} // namespace Botan
131
132#endif
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
std::tuple< std::span< const uint8_t >, size_t > aligned_data_to_process(BufferSlicer &slicer) const
void append(std::span< const T > elements)
size_t elements_until_alignment() const
std::optional< std::span< const T > > handle_unaligned_data(BufferSlicer &slicer)
std::span< T > directly_modify_last(size_t elements)
std::span< const T > consume()
bool empty() const
Definition stl_util.h:186
void update(std::span< const uint8_t > input)
Definition mdx_hash.h:44
int(* final)(unsigned char *, CTX *)
constexpr bool is_power_of_2(T arg)
Definition bit_ops.h:45
constexpr void store_be(T in, OutR &&out_range)
Definition loadstor.h:358
void copy_out_vec_le(uint8_t out[], size_t out_bytes, const std::vector< T, Alloc > &in)
Definition loadstor.h:540
constexpr void store_le(T in, OutR &&out_range)
Definition loadstor.h:383
MD_Endian
Definition mdx_hash.h:20
void copy_out_vec_be(uint8_t out[], size_t out_bytes, const std::vector< T, Alloc > &in)
Definition loadstor.h:521