Botan 3.7.1
Crypto and TLS for C&
cipher_mode.h
Go to the documentation of this file.
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
20namespace Botan {
21
22/**
23* The two possible directions a Cipher_Mode can operate in
24*/
25enum class Cipher_Dir : int {
28
29 ENCRYPTION BOTAN_DEPRECATED("Use Cipher_Dir::Encryption") = Encryption,
30 DECRYPTION BOTAN_DEPRECATED("Use Cipher_Dir::Decryption") = Decryption,
31};
32
33/**
34* Interface for cipher modes
35*/
37 public:
38 /**
39 * @return list of available providers for this algorithm, empty if not available
40 * @param algo_spec algorithm name
41 */
42 static std::vector<std::string> providers(std::string_view algo_spec);
43
44 /**
45 * Create an AEAD mode
46 * @param algo the algorithm to create
47 * @param direction specify if this should be an encryption or decryption AEAD
48 * @param provider optional specification for provider to use
49 * @return an AEAD mode or a null pointer if not available
50 */
51 static std::unique_ptr<Cipher_Mode> create(std::string_view algo,
52 Cipher_Dir direction,
53 std::string_view provider = "");
54
55 /**
56 * Create an AEAD mode, or throw
57 * @param algo the algorithm to create
58 * @param direction specify if this should be an encryption or decryption AEAD
59 * @param provider optional specification for provider to use
60 * @return an AEAD mode, or throw an exception
61 */
62 static std::unique_ptr<Cipher_Mode> create_or_throw(std::string_view algo,
63 Cipher_Dir direction,
64 std::string_view provider = "");
65
66 protected:
67 /*
68 * Prepare for processing a message under the specified nonce
69 */
70 virtual void start_msg(const uint8_t nonce[], size_t nonce_len) = 0;
71
72 /*
73 * Process message blocks
74 * Input must be a multiple of update_granularity.
75 */
76 virtual size_t process_msg(uint8_t msg[], size_t msg_len) = 0;
77
78 /*
79 * Finishes a message
80 */
81 virtual void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) = 0;
82
83 public:
84 /**
85 * Begin processing a message with a fresh nonce.
86 *
87 * @warning Typically one must not reuse the same nonce for more than one
88 * message under the same key. For most cipher modes this would
89 * mean total loss of security and/or authenticity guarantees.
90 *
91 * @note If reliably generating unique nonces is difficult in your
92 * environment, use SIV which retains security even if nonces
93 * are repeated.
94 *
95 * @param nonce the per message nonce
96 */
97 void start(std::span<const uint8_t> nonce) { start_msg(nonce.data(), nonce.size()); }
98
99 /**
100 * Begin processing a message with a fresh nonce.
101 * @param nonce the per message nonce
102 * @param nonce_len length of nonce
103 */
104 void start(const uint8_t nonce[], size_t nonce_len) { start_msg(nonce, nonce_len); }
105
106 /**
107 * Begin processing a message.
108 *
109 * The exact semantics of this depend on the mode. For many modes, the call
110 * will fail since a nonce must be provided.
111 *
112 * For certain modes such as CBC this will instead cause the last
113 * ciphertext block to be used as the nonce of the new message; doing this
114 * isn't a good idea, but some (mostly older) protocols do this.
115 */
116 void start() { return start_msg(nullptr, 0); }
117
118 /**
119 * Process message blocks
120 *
121 * Input must be a multiple of update_granularity
122 *
123 * Processes msg in place and returns bytes written. Normally
124 * this will be either msg_len (indicating the entire message was
125 * processed) or for certain AEAD modes zero (indicating that the
126 * mode requires the entire message be processed in one pass).
127 *
128 * @param msg the message to be processed
129 * @return bytes written in-place
130 */
131 size_t process(std::span<uint8_t> msg) { return this->process_msg(msg.data(), msg.size()); }
132
133 size_t process(uint8_t msg[], size_t msg_len) { return this->process_msg(msg, msg_len); }
134
135 /**
136 * Process some data. Input must be in size update_granularity() uint8_t
137 * blocks. The @p buffer is an in/out parameter and may be resized. In
138 * particular, some modes require that all input be consumed before any
139 * output is produced; with these modes, @p buffer will be returned empty.
140 *
141 * The first @p offset bytes of @p buffer will be ignored (this allows in
142 * place processing of a buffer that contains an initial plaintext header).
143 *
144 * @param buffer in/out parameter which will possibly be resized
145 * @param offset an offset into blocks to begin processing
146 */
147 template <concepts::resizable_byte_buffer T>
148 void update(T& buffer, size_t offset = 0) {
149 BOTAN_ASSERT(buffer.size() >= offset, "Offset ok");
150 const size_t written = process(std::span(buffer).subspan(offset));
151 buffer.resize(offset + written);
152 }
153
154 /**
155 * Complete procession of a message with a final input of @p buffer, which
156 * is treated the same as with update(). If you have the entire message in
157 * hand, calling finish() without ever calling update() is both efficient
158 * and convenient.
159 *
160 * When using an AEAD_Mode, if the supplied authentication tag does not
161 * validate, this will throw an instance of Invalid_Authentication_Tag.
162 *
163 * If this occurs, all plaintext previously output via calls to update must
164 * be destroyed and not used in any way that an attacker could observe the
165 * effects of. This could be anything from echoing the plaintext back
166 * (perhaps in an error message), or by making an external RPC whose
167 * destination or contents depend on the plaintext. The only thing you can
168 * do is buffer it, and in the event of an invalid tag, erase the
169 * previously decrypted content from memory.
170 *
171 * One simple way to assure this could never happen is to never call
172 * update, and instead always marshal the entire message into a single
173 * buffer and call finish on it when decrypting.
174 *
175 * @param final_block in/out parameter which must be at least
176 * minimum_final_size() bytes, and will be set to any final output
177 * @param offset an offset into final_block to begin processing
178 */
179 void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) { finish_msg(final_block, offset); }
180
181 /**
182 * Complete procession of a message.
183 *
184 * Note: Using this overload with anything but a Botan::secure_vector<>
185 * is copying the bytes in the in/out buffer.
186 *
187 * @param final_block in/out parameter which must be at least
188 * minimum_final_size() bytes, and will be set to any final output
189 * @param offset an offset into final_block to begin processing
190 */
191 template <concepts::resizable_byte_buffer T>
192 void finish(T& final_block, size_t offset = 0) {
193 Botan::secure_vector<uint8_t> tmp(final_block.begin(), final_block.end());
194 finish_msg(tmp, offset);
195 final_block.resize(tmp.size());
196 std::copy(tmp.begin(), tmp.end(), final_block.begin());
197 }
198
199 /**
200 * Returns the size of the output if this transform is used to process a
201 * message with input_length bytes. In most cases the answer is precise.
202 * If it is not possible to precise (namely for CBC decryption) instead an
203 * upper bound is returned.
204 */
205 virtual size_t output_length(size_t input_length) const = 0;
206
207 /**
208 * The :cpp:class:`Cipher_Mode` interface requires message processing in
209 * multiples of the block size. This returns size of required blocks to
210 * update. If the mode implementation does not require buffering it will
211 * return 1.
212 * @return size of required blocks to update
213 */
214 virtual size_t update_granularity() const = 0;
215
216 /**
217 * Return an ideal granularity. This will be a multiple of the result of
218 * update_granularity but may be larger. If so it indicates that better
219 * performance may be achieved by providing buffers that are at least that
220 * size (due to SIMD execution, etc).
221 */
222 virtual size_t ideal_granularity() const = 0;
223
224 /**
225 * Certain modes require the entire message be available before
226 * any processing can occur. For such modes, input will be consumed
227 * but not returned, until `finish` is called, which returns the
228 * entire message.
229 *
230 * This function returns true if this mode has this style of
231 * operation.
232 */
233 virtual bool requires_entire_message() const { return false; }
234
235 /**
236 * @return required minimium size to finalize() - may be any
237 * length larger than this.
238 */
239 virtual size_t minimum_final_size() const = 0;
240
241 /**
242 * @return the default size for a nonce
243 */
244 virtual size_t default_nonce_length() const = 0;
245
246 /**
247 * @return true iff nonce_len is a valid length for the nonce
248 */
249 virtual bool valid_nonce_length(size_t nonce_len) const = 0;
250
251 /**
252 * Resets just the message specific state and allows encrypting again under the existing key
253 */
254 virtual void reset() = 0;
255
256 /**
257 * Return the length in bytes of the authentication tag this algorithm
258 * generates. If the mode is not authenticated, this will return 0.
259 *
260 * @return true iff this mode provides authentication as well as
261 * confidentiality.
262 */
263 bool authenticated() const { return this->tag_size() > 0; }
264
265 /**
266 * @return the size of the authentication tag used (in bytes)
267 */
268 virtual size_t tag_size() const { return 0; }
269
270 /**
271 * @return provider information about this implementation. Default is "base",
272 * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
273 */
274 virtual std::string provider() const { return "base"; }
275};
276
277/**
278* Get a cipher mode by name (eg "AES-128/CBC" or "Serpent/XTS")
279* @param algo_spec cipher name
280* @param direction Cipher_Dir::Encryption or Cipher_Dir::Decryption
281* @param provider provider implementation to choose
282*/
283BOTAN_DEPRECATED("Use Cipher_Mode::create")
284inline Cipher_Mode* get_cipher_mode(std::string_view algo_spec, Cipher_Dir direction, std::string_view provider = "") {
285 return Cipher_Mode::create(algo_spec, direction, provider).release();
286}
287
288} // namespace Botan
289
290#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:19
#define BOTAN_DEPRECATED(msg)
Definition api.h:59
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
virtual void start_msg(const uint8_t nonce[], size_t nonce_len)=0
static std::unique_ptr< Cipher_Mode > create(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
virtual std::string provider() const
void start(std::span< const uint8_t > nonce)
Definition cipher_mode.h:97
bool authenticated() const
virtual void finish_msg(secure_vector< uint8_t > &final_block, size_t offset=0)=0
void start(const uint8_t nonce[], size_t nonce_len)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0)
virtual size_t default_nonce_length() const =0
size_t process(uint8_t msg[], size_t msg_len)
virtual void reset()=0
virtual bool requires_entire_message() const
virtual size_t ideal_granularity() const =0
void update(T &buffer, size_t offset=0)
size_t process(std::span< uint8_t > msg)
virtual size_t output_length(size_t input_length) const =0
void finish(T &final_block, size_t offset=0)
virtual size_t tag_size() const
virtual size_t process_msg(uint8_t msg[], size_t msg_len)=0
virtual size_t minimum_final_size() const =0
virtual size_t update_granularity() const =0
virtual bool valid_nonce_length(size_t nonce_len) const =0
FE_25519 T
Definition ge.cpp:34
Cipher_Mode * get_cipher_mode(std::string_view algo_spec, Cipher_Dir direction, std::string_view provider="")
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61