Coverage Report

Created: 2024-11-21 06:51

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