Botan  2.6.0
Crypto and TLS for C++11
openssl_block.cpp
Go to the documentation of this file.
1 /*
2 * Block Ciphers via OpenSSL
3 * (C) 1999-2010,2015 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/block_cipher.h>
9 #include <botan/internal/openssl.h>
10 #include <openssl/evp.h>
11 
12 namespace Botan {
13 
14 namespace {
15 
16 class OpenSSL_BlockCipher final : public BlockCipher
17  {
18  public:
19  OpenSSL_BlockCipher(const std::string& name,
20  const EVP_CIPHER* cipher);
21 
22  OpenSSL_BlockCipher(const std::string& name,
23  const EVP_CIPHER* cipher,
24  size_t kl_min, size_t kl_max, size_t kl_mod);
25 
26  ~OpenSSL_BlockCipher();
27 
28  void clear() override;
29  std::string provider() const override { return "openssl"; }
30  std::string name() const override { return m_cipher_name; }
31  BlockCipher* clone() const override;
32 
33  size_t block_size() const override { return m_block_sz; }
34 
35  Key_Length_Specification key_spec() const override { return m_cipher_key_spec; }
36 
37  void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
38  {
39  verify_key_set(m_key_set);
40  int out_len = 0;
41  if(!EVP_EncryptUpdate(m_encrypt, out, &out_len, in, blocks * m_block_sz))
42  throw OpenSSL_Error("EVP_EncryptUpdate");
43  }
44 
45  void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
46  {
47  verify_key_set(m_key_set);
48  int out_len = 0;
49  if(!EVP_DecryptUpdate(m_decrypt, out, &out_len, in, blocks * m_block_sz))
50  throw OpenSSL_Error("EVP_DecryptUpdate");
51  }
52 
53  void key_schedule(const uint8_t key[], size_t key_len) override;
54 
55  size_t m_block_sz;
56  Key_Length_Specification m_cipher_key_spec;
57  std::string m_cipher_name;
58  EVP_CIPHER_CTX *m_encrypt;
59  EVP_CIPHER_CTX *m_decrypt;
60  bool m_key_set;
61  };
62 
63 OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
64  const EVP_CIPHER* algo) :
65  m_block_sz(EVP_CIPHER_block_size(algo)),
66  m_cipher_key_spec(EVP_CIPHER_key_length(algo)),
67  m_cipher_name(algo_name),
68  m_key_set(false)
69  {
70  if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
71  throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
72 
73  m_encrypt = EVP_CIPHER_CTX_new();
74  m_decrypt = EVP_CIPHER_CTX_new();
75  if (m_encrypt == nullptr || m_decrypt == nullptr)
76  throw OpenSSL_Error("Can't allocate new context");
77 
78  EVP_CIPHER_CTX_init(m_encrypt);
79  EVP_CIPHER_CTX_init(m_decrypt);
80 
81  if(!EVP_EncryptInit_ex(m_encrypt, algo, nullptr, nullptr, nullptr))
82  throw OpenSSL_Error("EVP_EncryptInit_ex");
83  if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
84  throw OpenSSL_Error("EVP_DecryptInit_ex");
85 
86  if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
87  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt");
88  if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
89  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt");
90  }
91 
92 OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
93  const EVP_CIPHER* algo,
94  size_t key_min,
95  size_t key_max,
96  size_t key_mod) :
97  m_block_sz(EVP_CIPHER_block_size(algo)),
98  m_cipher_key_spec(key_min, key_max, key_mod),
99  m_cipher_name(algo_name),
100  m_key_set(false)
101  {
102  if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
103  throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
104 
105  m_encrypt = EVP_CIPHER_CTX_new();
106  m_decrypt = EVP_CIPHER_CTX_new();
107  if (m_encrypt == nullptr || m_decrypt == nullptr)
108  throw OpenSSL_Error("Can't allocate new context");
109 
110  EVP_CIPHER_CTX_init(m_encrypt);
111  EVP_CIPHER_CTX_init(m_decrypt);
112 
113  if(!EVP_EncryptInit_ex(m_encrypt, algo, nullptr, nullptr, nullptr))
114  throw OpenSSL_Error("EVP_EncryptInit_ex");
115  if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
116  throw OpenSSL_Error("EVP_DecryptInit_ex");
117 
118  if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
119  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt");
120  if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
121  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt");
122  }
123 
124 OpenSSL_BlockCipher::~OpenSSL_BlockCipher()
125  {
126  EVP_CIPHER_CTX_cleanup(m_encrypt);
127  EVP_CIPHER_CTX_cleanup(m_decrypt);
128 
129  EVP_CIPHER_CTX_free(m_encrypt);
130  EVP_CIPHER_CTX_free(m_decrypt);
131  }
132 
133 /*
134 * Set the key
135 */
136 void OpenSSL_BlockCipher::key_schedule(const uint8_t key[], size_t length)
137  {
138  secure_vector<uint8_t> full_key(key, key + length);
139 
140  if(m_cipher_name == "TripleDES" && length == 16)
141  {
142  full_key += std::make_pair(key, 8);
143  }
144  else
145  {
146  if(EVP_CIPHER_CTX_set_key_length(m_encrypt, length) == 0 ||
147  EVP_CIPHER_CTX_set_key_length(m_decrypt, length) == 0)
148  throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " +
149  m_cipher_name);
150  }
151 
152  if(!EVP_EncryptInit_ex(m_encrypt, nullptr, nullptr, full_key.data(), nullptr))
153  throw OpenSSL_Error("EVP_EncryptInit_ex");
154  if(!EVP_DecryptInit_ex(m_decrypt, nullptr, nullptr, full_key.data(), nullptr))
155  throw OpenSSL_Error("EVP_DecryptInit_ex");
156 
157  m_key_set = true;
158  }
159 
160 /*
161 * Return a clone of this object
162 */
163 BlockCipher* OpenSSL_BlockCipher::clone() const
164  {
165  return new OpenSSL_BlockCipher(m_cipher_name,
166  EVP_CIPHER_CTX_cipher(m_encrypt),
167  m_cipher_key_spec.minimum_keylength(),
168  m_cipher_key_spec.maximum_keylength(),
169  m_cipher_key_spec.keylength_multiple());
170  }
171 
172 /*
173 * Clear memory of sensitive data
174 */
175 void OpenSSL_BlockCipher::clear()
176  {
177  const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(m_encrypt);
178 
179  m_key_set = false;
180 
181  if(!EVP_CIPHER_CTX_cleanup(m_encrypt))
182  throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup encrypt");
183  if(!EVP_CIPHER_CTX_cleanup(m_decrypt))
184  throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup decrypt");
185  EVP_CIPHER_CTX_init(m_encrypt);
186  EVP_CIPHER_CTX_init(m_decrypt);
187  if(!EVP_EncryptInit_ex(m_encrypt, algo, nullptr, nullptr, nullptr))
188  throw OpenSSL_Error("EVP_EncryptInit_ex");
189  if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
190  throw OpenSSL_Error("EVP_DecryptInit_ex");
191  if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
192  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt");
193  if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
194  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt");
195  }
196 
197 }
198 
199 std::unique_ptr<BlockCipher>
200 make_openssl_block_cipher(const std::string& name)
201  {
202 #define MAKE_OPENSSL_BLOCK(evp_fn) \
203  std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn()))
204 #define MAKE_OPENSSL_BLOCK_KEYLEN(evp_fn, kl_min, kl_max, kl_mod) \
205  std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn(), kl_min, kl_max, kl_mod))
206 
207 #if defined(BOTAN_HAS_AES) && !defined(OPENSSL_NO_AES)
208  if(name == "AES-128")
209  return MAKE_OPENSSL_BLOCK(EVP_aes_128_ecb);
210  if(name == "AES-192")
211  return MAKE_OPENSSL_BLOCK(EVP_aes_192_ecb);
212  if(name == "AES-256")
213  return MAKE_OPENSSL_BLOCK(EVP_aes_256_ecb);
214 #endif
215 
216 #if defined(BOTAN_HAS_CAMELLIA) && !defined(OPENSSL_NO_CAMELLIA)
217  if(name == "Camellia-128")
218  return MAKE_OPENSSL_BLOCK(EVP_camellia_128_ecb);
219  if(name == "Camellia-192")
220  return MAKE_OPENSSL_BLOCK(EVP_camellia_192_ecb);
221  if(name == "Camellia-256")
222  return MAKE_OPENSSL_BLOCK(EVP_camellia_256_ecb);
223 #endif
224 
225 #if defined(BOTAN_HAS_DES) && !defined(OPENSSL_NO_DES)
226  if(name == "DES")
227  return MAKE_OPENSSL_BLOCK(EVP_des_ecb);
228  if(name == "TripleDES")
229  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_des_ede3_ecb, 16, 24, 8);
230 #endif
231 
232 #if defined(BOTAN_HAS_BLOWFISH) && !defined(OPENSSL_NO_BF)
233  if(name == "Blowfish")
234  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_bf_ecb, 1, 56, 1);
235 #endif
236 
237 #if defined(BOTAN_HAS_CAST) && !defined(OPENSSL_NO_CAST)
238  if(name == "CAST-128")
239  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_cast5_ecb, 1, 16, 1);
240 #endif
241 
242 #if defined(BOTAN_HAS_IDEA) && !defined(OPENSSL_NO_IDEA)
243  if(name == "IDEA")
244  return MAKE_OPENSSL_BLOCK(EVP_idea_ecb);
245 #endif
246 
247 #if defined(BOTAN_HAS_SEED) && !defined(OPENSSL_NO_SEED)
248  if(name == "SEED")
249  return MAKE_OPENSSL_BLOCK(EVP_seed_ecb);
250 #endif
251 
252  return nullptr;
253  }
254 
255 }
256 
Key_Length_Specification m_cipher_key_spec
std::string m_cipher_name
size_t m_block_sz
EVP_CIPHER_CTX * m_decrypt
Definition: alg_id.cpp:13
EVP_CIPHER_CTX * m_encrypt
bool m_key_set
#define MAKE_OPENSSL_BLOCK(evp_fn)
#define MAKE_OPENSSL_BLOCK_KEYLEN(evp_fn, kl_min, kl_max, kl_mod)
std::unique_ptr< BlockCipher > make_openssl_block_cipher(const std::string &name)