Botan  2.1.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 : 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  int out_len = 0;
40  EVP_EncryptUpdate(&m_encrypt, out, &out_len, in, blocks * m_block_sz);
41  }
42 
43  void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
44  {
45  int out_len = 0;
46  EVP_DecryptUpdate(&m_decrypt, out, &out_len, in, blocks * m_block_sz);
47  }
48 
49  void key_schedule(const uint8_t key[], size_t key_len) override;
50 
51  size_t m_block_sz;
52  Key_Length_Specification m_cipher_key_spec;
53  std::string m_cipher_name;
54  mutable EVP_CIPHER_CTX m_encrypt, m_decrypt;
55  };
56 
57 OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
58  const EVP_CIPHER* algo) :
59  m_block_sz(EVP_CIPHER_block_size(algo)),
60  m_cipher_key_spec(EVP_CIPHER_key_length(algo)),
61  m_cipher_name(algo_name)
62  {
63  if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
64  throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
65 
66  EVP_CIPHER_CTX_init(&m_encrypt);
67  EVP_CIPHER_CTX_init(&m_decrypt);
68 
69  EVP_EncryptInit_ex(&m_encrypt, algo, nullptr, nullptr, nullptr);
70  EVP_DecryptInit_ex(&m_decrypt, algo, nullptr, nullptr, nullptr);
71 
72  EVP_CIPHER_CTX_set_padding(&m_encrypt, 0);
73  EVP_CIPHER_CTX_set_padding(&m_decrypt, 0);
74  }
75 
76 OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
77  const EVP_CIPHER* algo,
78  size_t key_min,
79  size_t key_max,
80  size_t key_mod) :
81  m_block_sz(EVP_CIPHER_block_size(algo)),
82  m_cipher_key_spec(key_min, key_max, key_mod),
83  m_cipher_name(algo_name)
84  {
85  if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
86  throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
87 
88  EVP_CIPHER_CTX_init(&m_encrypt);
89  EVP_CIPHER_CTX_init(&m_decrypt);
90 
91  EVP_EncryptInit_ex(&m_encrypt, algo, nullptr, nullptr, nullptr);
92  EVP_DecryptInit_ex(&m_decrypt, algo, nullptr, nullptr, nullptr);
93 
94  EVP_CIPHER_CTX_set_padding(&m_encrypt, 0);
95  EVP_CIPHER_CTX_set_padding(&m_decrypt, 0);
96  }
97 
98 OpenSSL_BlockCipher::~OpenSSL_BlockCipher()
99  {
100  EVP_CIPHER_CTX_cleanup(&m_encrypt);
101  EVP_CIPHER_CTX_cleanup(&m_decrypt);
102  }
103 
104 /*
105 * Set the key
106 */
107 void OpenSSL_BlockCipher::key_schedule(const uint8_t key[], size_t length)
108  {
109  secure_vector<uint8_t> full_key(key, key + length);
110 
111  if(m_cipher_name == "TripleDES" && length == 16)
112  {
113  full_key += std::make_pair(key, 8);
114  }
115  else
116  if(EVP_CIPHER_CTX_set_key_length(&m_encrypt, length) == 0 ||
117  EVP_CIPHER_CTX_set_key_length(&m_decrypt, length) == 0)
118  throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " +
119  m_cipher_name);
120 
121  EVP_EncryptInit_ex(&m_encrypt, nullptr, nullptr, full_key.data(), nullptr);
122  EVP_DecryptInit_ex(&m_decrypt, nullptr, nullptr, full_key.data(), nullptr);
123  }
124 
125 /*
126 * Return a clone of this object
127 */
128 BlockCipher* OpenSSL_BlockCipher::clone() const
129  {
130  return new OpenSSL_BlockCipher(m_cipher_name,
131  EVP_CIPHER_CTX_cipher(&m_encrypt),
132  m_cipher_key_spec.minimum_keylength(),
133  m_cipher_key_spec.maximum_keylength(),
134  m_cipher_key_spec.keylength_multiple());
135  }
136 
137 /*
138 * Clear memory of sensitive data
139 */
140 void OpenSSL_BlockCipher::clear()
141  {
142  const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&m_encrypt);
143 
144  EVP_CIPHER_CTX_cleanup(&m_encrypt);
145  EVP_CIPHER_CTX_cleanup(&m_decrypt);
146  EVP_CIPHER_CTX_init(&m_encrypt);
147  EVP_CIPHER_CTX_init(&m_decrypt);
148  EVP_EncryptInit_ex(&m_encrypt, algo, nullptr, nullptr, nullptr);
149  EVP_DecryptInit_ex(&m_decrypt, algo, nullptr, nullptr, nullptr);
150  EVP_CIPHER_CTX_set_padding(&m_encrypt, 0);
151  EVP_CIPHER_CTX_set_padding(&m_decrypt, 0);
152  }
153 
154 }
155 
156 std::unique_ptr<BlockCipher>
157 make_openssl_block_cipher(const std::string& name)
158  {
159 #define MAKE_OPENSSL_BLOCK(evp_fn) \
160  std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn()))
161 #define MAKE_OPENSSL_BLOCK_KEYLEN(evp_fn, kl_min, kl_max, kl_mod) \
162  std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn(), kl_min, kl_max, kl_mod))
163 
164 #if defined(BOTAN_HAS_AES) && !defined(OPENSSL_NO_AES)
165  if(name == "AES-128")
166  return MAKE_OPENSSL_BLOCK(EVP_aes_128_ecb);
167  if(name == "AES-192")
168  return MAKE_OPENSSL_BLOCK(EVP_aes_192_ecb);
169  if(name == "AES-256")
170  return MAKE_OPENSSL_BLOCK(EVP_aes_256_ecb);
171 #endif
172 
173 #if defined(BOTAN_HAS_CAMELLIA) && !defined(OPENSSL_NO_CAMELLIA)
174  if(name == "Camellia-128")
175  return MAKE_OPENSSL_BLOCK(EVP_camellia_128_ecb);
176  if(name == "Camellia-192")
177  return MAKE_OPENSSL_BLOCK(EVP_camellia_192_ecb);
178  if(name == "Camellia-256")
179  return MAKE_OPENSSL_BLOCK(EVP_camellia_256_ecb);
180 #endif
181 
182 #if defined(BOTAN_HAS_DES) && !defined(OPENSSL_NO_DES)
183  if(name == "DES")
184  return MAKE_OPENSSL_BLOCK(EVP_des_ecb);
185  if(name == "TripleDES")
186  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_des_ede3_ecb, 16, 24, 8);
187 #endif
188 
189 #if defined(BOTAN_HAS_BLOWFISH) && !defined(OPENSSL_NO_BF)
190  if(name == "Blowfish")
191  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_bf_ecb, 1, 56, 1);
192 #endif
193 
194 #if defined(BOTAN_HAS_CAST) && !defined(OPENSSL_NO_CAST)
195  if(name == "CAST-128")
196  return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_cast5_ecb, 1, 16, 1);
197 #endif
198 
199 #if defined(BOTAN_HAS_IDEA) && !defined(OPENSSL_NO_IDEA)
200  if(name == "IDEA")
201  return MAKE_OPENSSL_BLOCK(EVP_idea_ecb);
202 #endif
203 
204 #if defined(BOTAN_HAS_SEED) && !defined(OPENSSL_NO_SEED)
205  if(name == "SEED")
206  return MAKE_OPENSSL_BLOCK(EVP_seed_ecb);
207 #endif
208 
209  return nullptr;
210  }
211 
212 }
213 
Key_Length_Specification m_cipher_key_spec
EVP_CIPHER_CTX m_decrypt
std::string m_cipher_name
size_t m_block_sz
EVP_CIPHER_CTX m_encrypt
Definition: alg_id.cpp:13
#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)