Botan  2.4.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 
130 /*
131 * Set the key
132 */
133 void OpenSSL_BlockCipher::key_schedule(const uint8_t key[], size_t length)
134  {
135  secure_vector<uint8_t> full_key(key, key + length);
136 
137  if(m_cipher_name == "TripleDES" && length == 16)
138  {
139  full_key += std::make_pair(key, 8);
140  }
141  else
142  {
143  if(EVP_CIPHER_CTX_set_key_length(m_encrypt, length) == 0 ||
144  EVP_CIPHER_CTX_set_key_length(m_decrypt, length) == 0)
145  throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " +
146  m_cipher_name);
147  }
148 
149  if(!EVP_EncryptInit_ex(m_encrypt, nullptr, nullptr, full_key.data(), nullptr))
150  throw OpenSSL_Error("EVP_EncryptInit_ex");
151  if(!EVP_DecryptInit_ex(m_decrypt, nullptr, nullptr, full_key.data(), nullptr))
152  throw OpenSSL_Error("EVP_DecryptInit_ex");
153 
154  m_key_set = true;
155  }
156 
157 /*
158 * Return a clone of this object
159 */
160 BlockCipher* OpenSSL_BlockCipher::clone() const
161  {
162  return new OpenSSL_BlockCipher(m_cipher_name,
163  EVP_CIPHER_CTX_cipher(m_encrypt),
164  m_cipher_key_spec.minimum_keylength(),
165  m_cipher_key_spec.maximum_keylength(),
166  m_cipher_key_spec.keylength_multiple());
167  }
168 
169 /*
170 * Clear memory of sensitive data
171 */
172 void OpenSSL_BlockCipher::clear()
173  {
174  const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(m_encrypt);
175 
176  m_key_set = false;
177 
178  if(!EVP_CIPHER_CTX_cleanup(m_encrypt))
179  throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup encrypt");
180  if(!EVP_CIPHER_CTX_cleanup(m_decrypt))
181  throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup decrypt");
182  EVP_CIPHER_CTX_init(m_encrypt);
183  EVP_CIPHER_CTX_init(m_decrypt);
184  if(!EVP_EncryptInit_ex(m_encrypt, algo, nullptr, nullptr, nullptr))
185  throw OpenSSL_Error("EVP_EncryptInit_ex");
186  if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
187  throw OpenSSL_Error("EVP_DecryptInit_ex");
188  if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
189  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt");
190  if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
191  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt");
192  }
193 
194 }
195 
196 std::unique_ptr<BlockCipher>
197 make_openssl_block_cipher(const std::string& name)
198  {
199 #define MAKE_OPENSSL_BLOCK(evp_fn) \
200  std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn()))
201 #define MAKE_OPENSSL_BLOCK_KEYLEN(evp_fn, kl_min, kl_max, kl_mod) \
202  std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn(), kl_min, kl_max, kl_mod))
203 
204 #if defined(BOTAN_HAS_AES) && !defined(OPENSSL_NO_AES)
205  if(name == "AES-128")
206  return MAKE_OPENSSL_BLOCK(EVP_aes_128_ecb);
207  if(name == "AES-192")
208  return MAKE_OPENSSL_BLOCK(EVP_aes_192_ecb);
209  if(name == "AES-256")
210  return MAKE_OPENSSL_BLOCK(EVP_aes_256_ecb);
211 #endif
212 
213 #if defined(BOTAN_HAS_CAMELLIA) && !defined(OPENSSL_NO_CAMELLIA)
214  if(name == "Camellia-128")
215  return MAKE_OPENSSL_BLOCK(EVP_camellia_128_ecb);
216  if(name == "Camellia-192")
217  return MAKE_OPENSSL_BLOCK(EVP_camellia_192_ecb);
218  if(name == "Camellia-256")
219  return MAKE_OPENSSL_BLOCK(EVP_camellia_256_ecb);
220 #endif
221 
222 #if defined(BOTAN_HAS_DES) && !defined(OPENSSL_NO_DES)
223  if(name == "DES")
224  return MAKE_OPENSSL_BLOCK(EVP_des_ecb);
225  if(name == "TripleDES")
226  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_des_ede3_ecb, 16, 24, 8);
227 #endif
228 
229 #if defined(BOTAN_HAS_BLOWFISH) && !defined(OPENSSL_NO_BF)
230  if(name == "Blowfish")
231  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_bf_ecb, 1, 56, 1);
232 #endif
233 
234 #if defined(BOTAN_HAS_CAST) && !defined(OPENSSL_NO_CAST)
235  if(name == "CAST-128")
236  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_cast5_ecb, 1, 16, 1);
237 #endif
238 
239 #if defined(BOTAN_HAS_IDEA) && !defined(OPENSSL_NO_IDEA)
240  if(name == "IDEA")
241  return MAKE_OPENSSL_BLOCK(EVP_idea_ecb);
242 #endif
243 
244 #if defined(BOTAN_HAS_SEED) && !defined(OPENSSL_NO_SEED)
245  if(name == "SEED")
246  return MAKE_OPENSSL_BLOCK(EVP_seed_ecb);
247 #endif
248 
249  return nullptr;
250  }
251 
252 }
253 
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)