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

Botan 1.10.16

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