/src/Botan-3.4.0/build/include/public/botan/cipher_mode.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Cipher Modes |
3 | | * (C) 2013,2016 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #ifndef BOTAN_CIPHER_MODE_H_ |
9 | | #define BOTAN_CIPHER_MODE_H_ |
10 | | |
11 | | #include <botan/concepts.h> |
12 | | #include <botan/exceptn.h> |
13 | | #include <botan/secmem.h> |
14 | | #include <botan/sym_algo.h> |
15 | | #include <span> |
16 | | #include <string> |
17 | | #include <string_view> |
18 | | #include <vector> |
19 | | |
20 | | namespace Botan { |
21 | | |
22 | | /** |
23 | | * The two possible directions for cipher filters, determining whether they |
24 | | * actually perform encryption or decryption. |
25 | | */ |
26 | | enum class Cipher_Dir : int { |
27 | | Encryption, |
28 | | Decryption, |
29 | | |
30 | | ENCRYPTION BOTAN_DEPRECATED("Use Cipher_Dir::Encryption") = Encryption, |
31 | | DECRYPTION BOTAN_DEPRECATED("Use Cipher_Dir::Decryption") = Decryption, |
32 | | }; |
33 | | |
34 | | /** |
35 | | * Interface for cipher modes |
36 | | */ |
37 | | class BOTAN_PUBLIC_API(2, 0) Cipher_Mode : public SymmetricAlgorithm { |
38 | | public: |
39 | | /** |
40 | | * @return list of available providers for this algorithm, empty if not available |
41 | | * @param algo_spec algorithm name |
42 | | */ |
43 | | static std::vector<std::string> providers(std::string_view algo_spec); |
44 | | |
45 | | /** |
46 | | * Create an AEAD mode |
47 | | * @param algo the algorithm to create |
48 | | * @param direction specify if this should be an encryption or decryption AEAD |
49 | | * @param provider optional specification for provider to use |
50 | | * @return an AEAD mode or a null pointer if not available |
51 | | */ |
52 | | static std::unique_ptr<Cipher_Mode> create(std::string_view algo, |
53 | | Cipher_Dir direction, |
54 | | std::string_view provider = ""); |
55 | | |
56 | | /** |
57 | | * Create an AEAD mode, or throw |
58 | | * @param algo the algorithm to create |
59 | | * @param direction specify if this should be an encryption or decryption AEAD |
60 | | * @param provider optional specification for provider to use |
61 | | * @return an AEAD mode, or throw an exception |
62 | | */ |
63 | | static std::unique_ptr<Cipher_Mode> create_or_throw(std::string_view algo, |
64 | | Cipher_Dir direction, |
65 | | std::string_view provider = ""); |
66 | | |
67 | | protected: |
68 | | /* |
69 | | * Prepare for processing a message under the specified nonce |
70 | | */ |
71 | | virtual void start_msg(const uint8_t nonce[], size_t nonce_len) = 0; |
72 | | |
73 | | /* |
74 | | * Process message blocks |
75 | | * Input must be a multiple of update_granularity. |
76 | | */ |
77 | | virtual size_t process_msg(uint8_t msg[], size_t msg_len) = 0; |
78 | | |
79 | | /* |
80 | | * Finishes a message |
81 | | */ |
82 | | virtual void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) = 0; |
83 | | |
84 | | public: |
85 | | /** |
86 | | * Begin processing a message with a fresh nonce. |
87 | | * @param nonce the per message nonce |
88 | | */ |
89 | 0 | void start(std::span<const uint8_t> nonce) { start_msg(nonce.data(), nonce.size()); } |
90 | | |
91 | | /** |
92 | | * Begin processing a message with a fresh nonce. |
93 | | * @param nonce the per message nonce |
94 | | * @param nonce_len length of nonce |
95 | | */ |
96 | 0 | void start(const uint8_t nonce[], size_t nonce_len) { start_msg(nonce, nonce_len); } |
97 | | |
98 | | /** |
99 | | * Begin processing a message. |
100 | | * |
101 | | * The exact semantics of this depend on the mode. For many modes, the call |
102 | | * will fail since a nonce must be provided. |
103 | | * |
104 | | * For certain modes such as CBC this will instead cause the last |
105 | | * ciphertext block to be used as the nonce of the new message; doing this |
106 | | * isn't a good idea, but some (mostly older) protocols do this. |
107 | | */ |
108 | 0 | void start() { return start_msg(nullptr, 0); } |
109 | | |
110 | | /** |
111 | | * Process message blocks |
112 | | * |
113 | | * Input must be a multiple of update_granularity |
114 | | * |
115 | | * Processes msg in place and returns bytes written. Normally |
116 | | * this will be either msg_len (indicating the entire message was |
117 | | * processed) or for certain AEAD modes zero (indicating that the |
118 | | * mode requires the entire message be processed in one pass). |
119 | | * |
120 | | * @param msg the message to be processed |
121 | | * @return bytes written in-place |
122 | | */ |
123 | 0 | size_t process(std::span<uint8_t> msg) { return this->process_msg(msg.data(), msg.size()); } |
124 | | |
125 | 0 | size_t process(uint8_t msg[], size_t msg_len) { return this->process_msg(msg, msg_len); } |
126 | | |
127 | | /** |
128 | | * Process some data. Input must be in size update_granularity() uint8_t blocks. |
129 | | * @param buffer in/out parameter which will possibly be resized |
130 | | * @param offset an offset into blocks to begin processing |
131 | | */ |
132 | | template <concepts::resizable_byte_buffer T> |
133 | 0 | void update(T& buffer, size_t offset = 0) { |
134 | 0 | BOTAN_ASSERT(buffer.size() >= offset, "Offset ok"); |
135 | 0 | const size_t written = process(std::span(buffer).subspan(offset)); |
136 | 0 | buffer.resize(offset + written); |
137 | 0 | } |
138 | | |
139 | | /** |
140 | | * Complete processing of a message. |
141 | | * |
142 | | * @param final_block in/out parameter which must be at least |
143 | | * minimum_final_size() bytes, and will be set to any final output |
144 | | * @param offset an offset into final_block to begin processing |
145 | | */ |
146 | 0 | void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) { finish_msg(final_block, offset); } |
147 | | |
148 | | /** |
149 | | * Complete procession of a message. |
150 | | * |
151 | | * Note: Using this overload with anything but a Botan::secure_vector<> |
152 | | * is copying the bytes in the in/out buffer. |
153 | | * |
154 | | * @param final_block in/out parameter which must be at least |
155 | | * minimum_final_size() bytes, and will be set to any final output |
156 | | * @param offset an offset into final_block to begin processing |
157 | | */ |
158 | | template <concepts::resizable_byte_buffer T> |
159 | | void finish(T& final_block, size_t offset = 0) { |
160 | | Botan::secure_vector<uint8_t> tmp(final_block.begin(), final_block.end()); |
161 | | finish_msg(tmp, offset); |
162 | | final_block.resize(tmp.size()); |
163 | | std::copy(tmp.begin(), tmp.end(), final_block.begin()); |
164 | | } |
165 | | |
166 | | /** |
167 | | * Returns the size of the output if this transform is used to process a |
168 | | * message with input_length bytes. In most cases the answer is precise. |
169 | | * If it is not possible to precise (namely for CBC decryption) instead an |
170 | | * upper bound is returned. |
171 | | */ |
172 | | virtual size_t output_length(size_t input_length) const = 0; |
173 | | |
174 | | /** |
175 | | * @return size of required blocks to update |
176 | | */ |
177 | | virtual size_t update_granularity() const = 0; |
178 | | |
179 | | /** |
180 | | * Return an ideal granularity. This will be a multiple of the result of |
181 | | * update_granularity but may be larger. If so it indicates that better |
182 | | * performance may be achieved by providing buffers that are at least that |
183 | | * size. |
184 | | */ |
185 | | virtual size_t ideal_granularity() const = 0; |
186 | | |
187 | | /** |
188 | | * Certain modes require the entire message be available before |
189 | | * any processing can occur. For such modes, input will be consumed |
190 | | * but not returned, until `finish` is called, which returns the |
191 | | * entire message. |
192 | | * |
193 | | * This function returns true if this mode has this style of |
194 | | * operation. |
195 | | */ |
196 | 0 | virtual bool requires_entire_message() const { return false; } |
197 | | |
198 | | /** |
199 | | * @return required minimium size to finalize() - may be any |
200 | | * length larger than this. |
201 | | */ |
202 | | virtual size_t minimum_final_size() const = 0; |
203 | | |
204 | | /** |
205 | | * @return the default size for a nonce |
206 | | */ |
207 | | virtual size_t default_nonce_length() const = 0; |
208 | | |
209 | | /** |
210 | | * @return true iff nonce_len is a valid length for the nonce |
211 | | */ |
212 | | virtual bool valid_nonce_length(size_t nonce_len) const = 0; |
213 | | |
214 | | /** |
215 | | * Resets just the message specific state and allows encrypting again under the existing key |
216 | | */ |
217 | | virtual void reset() = 0; |
218 | | |
219 | | /** |
220 | | * @return true iff this mode provides authentication as well as |
221 | | * confidentiality. |
222 | | */ |
223 | 0 | bool authenticated() const { return this->tag_size() > 0; } |
224 | | |
225 | | /** |
226 | | * @return the size of the authentication tag used (in bytes) |
227 | | */ |
228 | 0 | virtual size_t tag_size() const { return 0; } |
229 | | |
230 | | /** |
231 | | * @return provider information about this implementation. Default is "base", |
232 | | * might also return "sse2", "avx2", "openssl", or some other arbitrary string. |
233 | | */ |
234 | 0 | virtual std::string provider() const { return "base"; } |
235 | | }; |
236 | | |
237 | | /** |
238 | | * Get a cipher mode by name (eg "AES-128/CBC" or "Serpent/XTS") |
239 | | * @param algo_spec cipher name |
240 | | * @param direction Cipher_Dir::Encryption or Cipher_Dir::Decryption |
241 | | * @param provider provider implementation to choose |
242 | | */ |
243 | | BOTAN_DEPRECATED("Use Cipher_Mode::create") |
244 | | |
245 | 0 | inline Cipher_Mode* get_cipher_mode(std::string_view algo_spec, Cipher_Dir direction, std::string_view provider = "") { |
246 | 0 | return Cipher_Mode::create(algo_spec, direction, provider).release(); |
247 | 0 | } |
248 | | |
249 | | } // namespace Botan |
250 | | |
251 | | #endif |