Coverage Report

Created: 2026-02-07 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/build/include/public/botan/xof.h
Line
Count
Source
1
/*
2
* Extendable Output Function Base Class
3
* (C) 2023 Jack Lloyd
4
*     2023 Fabian Albert, René Meusel - Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#ifndef BOTAN_XOF_BASE_CLASS_H_
10
#define BOTAN_XOF_BASE_CLASS_H_
11
12
#include <botan/concepts.h>
13
#include <botan/secmem.h>
14
#include <botan/sym_algo.h>
15
16
#include <memory>
17
#include <string>
18
#include <string_view>
19
20
namespace Botan {
21
22
/**
23
 * This class represents an eXtendable Output Function (XOF) objects
24
 *
25
 * A XOF transforms an arbitrary length input message into an indefinite
26
 * stream of output bits. Typically, it is illegal to call `update()` after
27
 * the first call to `output()`.
28
 */
29
class BOTAN_PUBLIC_API(3, 2) XOF /* NOLINT(*special-member-functions) */ {
30
   public:
31
0
      virtual ~XOF() = default;
32
33
      /**
34
       * Create an instance based on a name, or return null if the
35
       * algo/provider combination cannot be found. If provider is
36
       * empty then best available is chosen.
37
       */
38
      static std::unique_ptr<XOF> create(std::string_view algo_spec, std::string_view provider = "");
39
40
      /**
41
       * Create an instance based on a name
42
       * If provider is empty then best available is chosen.
43
       * @param algo_spec algorithm name
44
       * @param provider provider implementation to use
45
       * Throws Lookup_Error if not found.
46
       */
47
      static std::unique_ptr<XOF> create_or_throw(std::string_view algo_spec, std::string_view provider = "");
48
49
      /**
50
       * @return list of available providers for this algorithm, empty if not available
51
       * @param algo_spec algorithm name
52
       */
53
      static std::vector<std::string> providers(std::string_view algo_spec);
54
55
      /**
56
       * @return provider information about this implementation. Default is "base",
57
       * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
58
       */
59
      virtual std::string provider() const;
60
61
      /**
62
       * Reset the state.
63
       */
64
0
      void clear() {
65
0
         m_xof_started = false;
66
0
         reset();
67
0
      }
68
69
      /**
70
       * @return the hash function name
71
       */
72
      virtual std::string name() const = 0;
73
74
      /**
75
       * Some XOFs can be parameterized with a @p salt and/or @p key. If required,
76
       * this must be called before calling XOF::update().
77
       *
78
       * @sa XOF::valid_salt_length()
79
       * @sa XOF::key_spec()
80
       *
81
       * @param salt  a salt value to parameterize the XOF
82
       * @param key   a key to parameterize the XOF
83
       */
84
      void start(std::span<const uint8_t> salt = {}, std::span<const uint8_t> key = {});
85
86
      /**
87
       * @returns true if salt length is acceptable, false otherwise
88
       */
89
0
      virtual bool valid_salt_length(size_t salt_len) const {
90
         // Salts are not supported by default
91
0
         return salt_len == 0;
92
0
      }
93
94
      /**
95
       * @returns an object describing limits on the key size
96
       */
97
0
      virtual Key_Length_Specification key_spec() const {
98
         // Keys are not supported by default
99
0
         return Key_Length_Specification(0);
100
0
      }
101
102
      /**
103
       * @return the intrinsic processing block size of this XOF
104
       */
105
      virtual size_t block_size() const = 0;
106
107
      /**
108
       * Return a new XOF object with the same state as *this.
109
       *
110
       * If the XOF is not yet in the output phase, it efficiently allows
111
       * using several messages with a common prefix.
112
       * Otherwise, the copied state will produce the same output
113
       * bit stream as the original object at the time of this invocation.
114
       *
115
       * This function should be called `clone` but for consistency with
116
       * other classes it is called `copy_state`.
117
       *
118
       * @return new XOF object
119
       */
120
      virtual std::unique_ptr<XOF> copy_state() const = 0;
121
122
      /**
123
       * @return new object representing the same algorithm as *this
124
       */
125
      virtual std::unique_ptr<XOF> new_object() const = 0;
126
127
      /**
128
       * Typically, this is `true` for new objects and becomes `false`
129
       * once `output()` was called for the first time.
130
       *
131
       * @returns true iff calling `update()` is legal in the current object state
132
       */
133
      virtual bool accepts_input() const = 0;
134
135
      /**
136
       * Add @p input data to the XOF's internal state
137
       *
138
       * @param input  the data that shall be
139
       */
140
0
      void update(std::span<const uint8_t> input) {
141
0
         if(!m_xof_started) {
142
            // If the user didn't start() before the first input, we enforce
143
            // it with a default value, here.
144
0
            start();
145
0
         }
146
0
         add_data(input);
147
0
      }
148
149
      /**
150
       * @return the next @p bytes output bytes as the specified container type @p T.
151
       */
152
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
153
0
      T output(size_t bytes) {
154
0
         T out(bytes);
155
0
         generate_bytes(out);
156
0
         return out;
157
0
      }
158
159
      /**
160
       * @return the next @p count output bytes as a std::array<>.
161
       */
162
      template <size_t count>
163
      std::array<uint8_t, count> output() {
164
         std::array<uint8_t, count> out;  // NOLINT(*-member-init)
165
         generate_bytes(out);
166
         return out;
167
      }
168
169
      /**
170
       * Convenience overload to generate a std::vector<uint8_t>. Same as calling
171
       * `XOF::output<std::vector<uint8_t>>()`.
172
       *
173
       * @return the next @p bytes output bytes as a byte vector.
174
       */
175
0
      std::vector<uint8_t> output_stdvec(size_t bytes) { return output<std::vector<uint8_t>>(bytes); }
176
177
      /**
178
       * Fill @p output with the next output bytes. The number of bytes
179
       * depends on the size of @p output.
180
       */
181
0
      void output(std::span<uint8_t> output) { generate_bytes(output); }
182
183
      /**
184
       * @return the next single output byte
185
       */
186
0
      uint8_t output_next_byte() {
187
0
         uint8_t out = 0;
188
0
         generate_bytes({&out, 1});
189
0
         return out;
190
0
      }
191
192
   private:
193
      /**
194
       * Take @p salt and/or @p key to pre-parameterize the XOF. This must be called
195
       * before calling XOF::update().
196
       *
197
       * @param salt  a salt value to parameterize the XOF
198
       * @param key   a key to parameterize the XOF
199
       */
200
      virtual void start_msg(std::span<const uint8_t> salt, std::span<const uint8_t> key);
201
202
      /**
203
       * Consume @p input data bytes into the XOF's internal state
204
       *
205
       * Typically, XOFs may consume an arbitrary length of input data but
206
       * should refuse accepting more input once the first output bit was
207
       * generated. Implementations should throw `Invalid_State` in this
208
       * case.
209
       *
210
       * @param input  the span to be consumed entirely into the internal state
211
       * @throws        Invalid_State if input is added after generating output
212
       */
213
      virtual void add_data(std::span<const uint8_t> input) = 0;
214
215
      /**
216
       * Fill the entire @p output span with the next bytes in their output
217
       * stream.
218
       *
219
       * The first invocation to `generate_bytes()` should typically transition
220
       * the XOF's state to "output mode" and prevent any further calls to
221
       * `XOF::add_data()`.
222
       *
223
       * @param output  the span to be filled entirely with output bytes
224
       */
225
      virtual void generate_bytes(std::span<uint8_t> output) = 0;
226
227
      /**
228
       * Clear the XOF's internal state and allow for new input.
229
       */
230
      virtual void reset() = 0;
231
232
   private:
233
      bool m_xof_started = false;
234
};
235
236
}  // namespace Botan
237
238
#endif