Botan: src/engine/openssl/ossl_bc.cpp Source File

Botan 1.10.17

ossl_bc.cpp
Go to the documentation of this file.
1 /*
2 * OpenSSL Block Cipher
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7
8 #include <botan/internal/openssl_engine.h>
9 #include <openssl/evp.h>
10
11 #if OPENSSL_VERSION_NUMBER >= 0x10100000
12 #error "OpenSSL 1.1 API not supported in Botan 1.10, upgrade to 2.x"
13 #endif
14
15 namespace Botan {
16
17 namespace {
18
19 /*
20 * EVP Block Cipher
21 */
22 class EVP_BlockCipher : public BlockCipher
23 {
24 public:
25 void clear();
26 std::string name() const { return cipher_name; }
27 BlockCipher* clone() const;
28
29 size_t block_size() const { return block_sz; }
30
31 EVP_BlockCipher(const EVP_CIPHER*, const std::string&);
32
33 EVP_BlockCipher(const EVP_CIPHER*, const std::string&,
34 size_t, size_t, size_t);
35
36 Key_Length_Specification key_spec() const { return cipher_key_spec; }
37
38 ~EVP_BlockCipher();
39 private:
40 void encrypt_n(const byte in[], byte out[], size_t blocks) const;
41 void decrypt_n(const byte in[], byte out[], size_t blocks) const;
42 void key_schedule(const byte[], size_t);
43
44 size_t block_sz;
45 Key_Length_Specification cipher_key_spec;
46 std::string cipher_name;
47 mutable EVP_CIPHER_CTX encrypt, decrypt;
48 };
49
50 /*
51 * EVP Block Cipher Constructor
52 */
53 EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
54 const std::string& algo_name) :
55 block_sz(EVP_CIPHER_block_size(algo)),
56 cipher_key_spec(EVP_CIPHER_key_length(algo)),
57 cipher_name(algo_name)
58 {
59 if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
60 throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
61
62 EVP_CIPHER_CTX_init(&encrypt);
63 EVP_CIPHER_CTX_init(&decrypt);
64
65 EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
66 EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
67
68 EVP_CIPHER_CTX_set_padding(&encrypt, 0);
69 EVP_CIPHER_CTX_set_padding(&decrypt, 0);
70 }
71
72 /*
73 * EVP Block Cipher Constructor
74 */
75 EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
76 const std::string& algo_name,
77 size_t key_min, size_t key_max,
78 size_t key_mod) :
79 block_sz(EVP_CIPHER_block_size(algo)),
80 cipher_key_spec(key_min, key_max, key_mod),
81 cipher_name(algo_name)
82 {
83 if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
84 throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
85
86 EVP_CIPHER_CTX_init(&encrypt);
87 EVP_CIPHER_CTX_init(&decrypt);
88
89 EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
90 EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
91
92 EVP_CIPHER_CTX_set_padding(&encrypt, 0);
93 EVP_CIPHER_CTX_set_padding(&decrypt, 0);
94 }
95
96 /*
97 * EVP Block Cipher Destructor
98 */
99 EVP_BlockCipher::~EVP_BlockCipher()
100 {
101 EVP_CIPHER_CTX_cleanup(&encrypt);
102 EVP_CIPHER_CTX_cleanup(&decrypt);
103 }
104
105 /*
106 * Encrypt a block
107 */
108 void EVP_BlockCipher::encrypt_n(const byte in[], byte out[],
109 size_t blocks) const
110 {
111 int out_len = 0;
112 EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz);
113 }
114
115 /*
116 * Decrypt a block
117 */
118 void EVP_BlockCipher::decrypt_n(const byte in[], byte out[],
119 size_t blocks) const
120 {
121 int out_len = 0;
122 EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz);
123 }
124
125 /*
126 * Set the key
127 */
128 void EVP_BlockCipher::key_schedule(const byte key[], size_t length)
129 {
130 SecureVector<byte> full_key(key, length);
131
132 if(cipher_name == "TripleDES" && length == 16)
133 {
134 full_key += std::make_pair(key, 8);
135 }
136 else
137 if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 ||
138 EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0)
139 throw Invalid_Argument("EVP_BlockCipher: Bad key length for " +
140 cipher_name);
141
142 if(cipher_name == "RC2")
143 {
144 EVP_CIPHER_CTX_ctrl(&encrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
145 EVP_CIPHER_CTX_ctrl(&decrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
146 }
147
148 EVP_EncryptInit_ex(&encrypt, 0, 0, full_key.begin(), 0);
149 EVP_DecryptInit_ex(&decrypt, 0, 0, full_key.begin(), 0);
150 }
151
152 /*
153 * Return a clone of this object
154 */
155 BlockCipher* EVP_BlockCipher::clone() const
156 {
157 return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt),
158 cipher_name,
159 cipher_key_spec.minimum_keylength(),
160 cipher_key_spec.maximum_keylength(),
161 cipher_key_spec.keylength_multiple());
162 }
163
164 /*
165 * Clear memory of sensitive data
166 */
167 void EVP_BlockCipher::clear()
168 {
169 const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt);
170
171 EVP_CIPHER_CTX_cleanup(&encrypt);
172 EVP_CIPHER_CTX_cleanup(&decrypt);
173 EVP_CIPHER_CTX_init(&encrypt);
174 EVP_CIPHER_CTX_init(&decrypt);
175 EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
176 EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
177 EVP_CIPHER_CTX_set_padding(&encrypt, 0);
178 EVP_CIPHER_CTX_set_padding(&decrypt, 0);
179 }
180
181 }
182
183 /*
184 * Look for an algorithm with this name
185 */
186 BlockCipher*
187 OpenSSL_Engine::find_block_cipher(const SCAN_Name& request,
188 Algorithm_Factory&) const
189 {
190 #define HANDLE_EVP_CIPHER(NAME, EVP) \
191 if(request.algo_name() == NAME && request.arg_count() == 0) \
192 return new EVP_BlockCipher(EVP, NAME);
193
194 #define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD) \
195 if(request.algo_name() == NAME && request.arg_count() == 0) \
196 return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD);
197
198 #if !defined(OPENSSL_NO_AES)
199 /*
200 Using OpenSSL's AES causes crashes inside EVP on x86-64 with OpenSSL 0.9.8g
201 cause is unknown
202 */
203 HANDLE_EVP_CIPHER("AES-128", EVP_aes_128_ecb());
204 HANDLE_EVP_CIPHER("AES-192", EVP_aes_192_ecb());
205 HANDLE_EVP_CIPHER("AES-256", EVP_aes_256_ecb());
206 #endif
207
208 #if !defined(OPENSSL_NO_DES)
209 HANDLE_EVP_CIPHER("DES", EVP_des_ecb());
210 HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8);
211 #endif
212
213 #if !defined(OPENSSL_NO_BF)
214 HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1);
215 #endif
216
217 #if !defined(OPENSSL_NO_CAST)
218 HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1);
219 #endif
220
221 #if !defined(OPENSSL_NO_CAMELLIA)
222 HANDLE_EVP_CIPHER("Camellia-128", EVP_camellia_128_ecb());
223 HANDLE_EVP_CIPHER("Camellia-192", EVP_camellia_192_ecb());
224 HANDLE_EVP_CIPHER("Camellia-256", EVP_camellia_256_ecb());
225 #endif
226
227 #if !defined(OPENSSL_NO_RC2)
228 HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1);
229 #endif
230
231 #if !defined(OPENSSL_NO_RC5) && 0
232 if(request.algo_name() == "RC5")
233 if(request.arg_as_integer(0, 12) == 12)
234 return new EVP_BlockCipher(EVP_rc5_32_12_16_ecb(),
235 "RC5(12)", 1, 32, 1);
236 #endif
237
238 #if !defined(OPENSSL_NO_IDEA) && 0
239 HANDLE_EVP_CIPHER("IDEA", EVP_idea_ecb());
240 #endif
241
242 #if !defined(OPENSSL_NO_SEED)
243 HANDLE_EVP_CIPHER("SEED", EVP_seed_ecb());
244 #endif
245
246 #undef HANDLE_EVP_CIPHER
247 #undef HANDLE_EVP_CIPHER_KEYLEN
248
249 return 0;
250 }
251
252 }
Botan::Algorithm_Factory
Definition: algo_factory.h:34
HANDLE_EVP_CIPHER_KEYLEN
#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD)
Botan::Key_Length_Specification::maximum_keylength
size_t maximum_keylength() const
Definition: key_spec.h:69
Botan::SCAN_Name::arg_as_integer
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:167
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
HANDLE_EVP_CIPHER
#define HANDLE_EVP_CIPHER(NAME, EVP)
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::Key_Length_Specification::keylength_multiple
size_t keylength_multiple() const
Definition: key_spec.h:77
Botan
Definition: algo_base.h:14
Botan::OpenSSL_Engine::find_block_cipher
BlockCipher * find_block_cipher(const SCAN_Name &, Algorithm_Factory &) const
Definition: ossl_bc.cpp:187
Botan::SCAN_Name
Definition: scan_name.h:21
Botan::Key_Length_Specification::minimum_keylength
size_t minimum_keylength() const
Definition: key_spec.h:61
Botan::SCAN_Name::algo_name
std::string algo_name() const
Definition: scan_name.h:37