Botan  1.10.9
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 }
#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD)
size_t block_size
Definition: ossl_md.cpp:41
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
#define HANDLE_EVP_CIPHER(NAME, EVP)
unsigned char byte
Definition: types.h:22
std::string algo_name() const
Definition: scan_name.h:37
std::string algo_name
Definition: ossl_md.cpp:42
Key_Length_Specification cipher_key_spec
Definition: ossl_bc.cpp:41
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:167
EVP_CIPHER_CTX decrypt
Definition: ossl_bc.cpp:43
EVP_CIPHER_CTX encrypt
Definition: ossl_bc.cpp:43
size_t block_sz
Definition: ossl_bc.cpp:40
std::string cipher_name
Definition: ossl_bc.cpp:42