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