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
15namespace Botan {
16
17namespace {
18
19/*
20* EVP Block Cipher
21*/
22class 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*/
53EVP_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*/
75EVP_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*/
99EVP_BlockCipher::~EVP_BlockCipher()
100 {
101 EVP_CIPHER_CTX_cleanup(&encrypt);
102 EVP_CIPHER_CTX_cleanup(&decrypt);
103 }
104
105/*
106* Encrypt a block
107*/
108void 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*/
118void 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*/
128void 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*/
155BlockCipher* 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*/
167void 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*/
186BlockCipher*
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}
BlockCipher * find_block_cipher(const SCAN_Name &, Algorithm_Factory &) const
Definition ossl_bc.cpp:187
std::string algo_name() const
Definition scan_name.h:37
size_t arg_as_integer(size_t i, size_t def_value) const
#define HANDLE_EVP_CIPHER(NAME, EVP)
#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD)