1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
/*
* Block Cipher Base Class
* (C) 1999-2009 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#ifndef BOTAN_BLOCK_CIPHER_H_
#define BOTAN_BLOCK_CIPHER_H_
#include <botan/sym_algo.h>
#include <string>
#include <memory>
namespace Botan {
/**
* This class represents a block cipher object.
*/
class BOTAN_PUBLIC_API(2,0) BlockCipher : public SymmetricAlgorithm
{
public:
/**
* Create an instance based on a name
* If provider is empty then best available is chosen.
* @param algo_spec algorithm name
* @param provider provider implementation to choose
* @return a null pointer if the algo/provider combination cannot be found
*/
static std::unique_ptr<BlockCipher>
create(const std::string& algo_spec,
const std::string& provider = "");
/**
* Create an instance based on a name, or throw if the
* algo/provider combination cannot be found. If provider is
* empty then best available is chosen.
*/
static std::unique_ptr<BlockCipher>
create_or_throw(const std::string& algo_spec,
const std::string& provider = "");
/**
* @return list of available providers for this algorithm, empty if not available
* @param algo_spec algorithm name
*/
static std::vector<std::string> providers(const std::string& algo_spec);
/**
* @return block size of this algorithm
*/
virtual size_t block_size() const = 0;
/**
* @return native parallelism of this cipher in blocks
*/
virtual size_t parallelism() const { return 1; }
/**
* @return prefererred parallelism of this cipher in bytes
*/
size_t parallel_bytes() const
{
return parallelism() * block_size() * BOTAN_BLOCK_CIPHER_PAR_MULT;
}
/**
* @return provider information about this implementation. Default is "base",
* might also return "sse2", "avx2", "openssl", or some other arbitrary string.
*/
virtual std::string provider() const { return "base"; }
/**
* Encrypt a block.
* @param in The plaintext block to be encrypted as a byte array.
* Must be of length block_size().
* @param out The byte array designated to hold the encrypted block.
* Must be of length block_size().
*/
void encrypt(const uint8_t in[], uint8_t out[]) const
{ encrypt_n(in, out, 1); }
/**
* Decrypt a block.
* @param in The ciphertext block to be decypted as a byte array.
* Must be of length block_size().
* @param out The byte array designated to hold the decrypted block.
* Must be of length block_size().
*/
void decrypt(const uint8_t in[], uint8_t out[]) const
{ decrypt_n(in, out, 1); }
/**
* Encrypt a block.
* @param block the plaintext block to be encrypted
* Must be of length block_size(). Will hold the result when the function
* has finished.
*/
void encrypt(uint8_t block[]) const { encrypt_n(block, block, 1); }
/**
* Decrypt a block.
* @param block the ciphertext block to be decrypted
* Must be of length block_size(). Will hold the result when the function
* has finished.
*/
void decrypt(uint8_t block[]) const { decrypt_n(block, block, 1); }
/**
* Encrypt one or more blocks
* @param block the input/output buffer (multiple of block_size())
*/
template<typename Alloc>
void encrypt(std::vector<uint8_t, Alloc>& block) const
{
return encrypt_n(block.data(), block.data(), block.size() / block_size());
}
/**
* Decrypt one or more blocks
* @param block the input/output buffer (multiple of block_size())
*/
template<typename Alloc>
void decrypt(std::vector<uint8_t, Alloc>& block) const
{
return decrypt_n(block.data(), block.data(), block.size() / block_size());
}
/**
* Encrypt one or more blocks
* @param in the input buffer (multiple of block_size())
* @param out the output buffer (same size as in)
*/
template<typename Alloc, typename Alloc2>
void encrypt(const std::vector<uint8_t, Alloc>& in,
std::vector<uint8_t, Alloc2>& out) const
{
return encrypt_n(in.data(), out.data(), in.size() / block_size());
}
/**
* Decrypt one or more blocks
* @param in the input buffer (multiple of block_size())
* @param out the output buffer (same size as in)
*/
template<typename Alloc, typename Alloc2>
void decrypt(const std::vector<uint8_t, Alloc>& in,
std::vector<uint8_t, Alloc2>& out) const
{
return decrypt_n(in.data(), out.data(), in.size() / block_size());
}
/**
* Encrypt one or more blocks
* @param in the input buffer (multiple of block_size())
* @param out the output buffer (same size as in)
* @param blocks the number of blocks to process
*/
virtual void encrypt_n(const uint8_t in[], uint8_t out[],
size_t blocks) const = 0;
/**
* Decrypt one or more blocks
* @param in the input buffer (multiple of block_size())
* @param out the output buffer (same size as in)
* @param blocks the number of blocks to process
*/
virtual void decrypt_n(const uint8_t in[], uint8_t out[],
size_t blocks) const = 0;
virtual void encrypt_n_xex(uint8_t data[],
const uint8_t mask[],
size_t blocks) const
{
const size_t BS = block_size();
xor_buf(data, mask, blocks * BS);
encrypt_n(data, data, blocks);
xor_buf(data, mask, blocks * BS);
}
virtual void decrypt_n_xex(uint8_t data[],
const uint8_t mask[],
size_t blocks) const
{
const size_t BS = block_size();
xor_buf(data, mask, blocks * BS);
decrypt_n(data, data, blocks);
xor_buf(data, mask, blocks * BS);
}
/**
* @return new object representing the same algorithm as *this
*/
virtual BlockCipher* clone() const = 0;
virtual ~BlockCipher() = default;
};
/**
* Tweakable block ciphers allow setting a tweak which is a non-keyed
* value which affects the encryption/decryption operation.
*/
class BOTAN_PUBLIC_API(2,8) Tweakable_Block_Cipher : public BlockCipher
{
public:
/**
* Set the tweak value. This must be called after setting a key. The value
* persists until either set_tweak, set_key, or clear is called.
* Different algorithms support different tweak length(s). If called with
* an unsupported length, Invalid_Argument will be thrown.
*/
virtual void set_tweak(const uint8_t tweak[], size_t len) = 0;
};
/**
* Represents a block cipher with a single fixed block size
*/
template<size_t BS, size_t KMIN, size_t KMAX = 0, size_t KMOD = 1, typename BaseClass = BlockCipher>
class Block_Cipher_Fixed_Params : public BaseClass
{
public:
enum { BLOCK_SIZE = BS };
size_t block_size() const final override { return BS; }
// override to take advantage of compile time constant block size
void encrypt_n_xex(uint8_t data[],
const uint8_t mask[],
size_t blocks) const final override
{
xor_buf(data, mask, blocks * BS);
this->encrypt_n(data, data, blocks);
xor_buf(data, mask, blocks * BS);
}
void decrypt_n_xex(uint8_t data[],
const uint8_t mask[],
size_t blocks) const final override
{
xor_buf(data, mask, blocks * BS);
this->decrypt_n(data, data, blocks);
xor_buf(data, mask, blocks * BS);
}
Key_Length_Specification key_spec() const final override
{
return Key_Length_Specification(KMIN, KMAX, KMOD);
}
};
}
#endif
|