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;
provider() const29       std::string provider() const override { return "openssl"; }
name() const30       std::string name() const override { return m_cipher_name; }
31       BlockCipher* clone() const override;
32 
block_size() const33       size_t block_size() const override { return m_block_sz; }
34 
key_spec() const35       Key_Length_Specification key_spec() const override { return m_cipher_key_spec; }
36 
encrypt_n(const uint8_t in[],uint8_t out[],size_t blocks) const37       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", ERR_get_error());
43          }
44 
decrypt_n(const uint8_t in[],uint8_t out[],size_t blocks) const45       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", ERR_get_error());
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 
OpenSSL_BlockCipher(const std::string & algo_name,const EVP_CIPHER * algo)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", ERR_get_error());
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", ERR_get_error());
83    if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
84       throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
85 
86    if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
87       throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt", ERR_get_error());
88    if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
89       throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt", ERR_get_error());
90    }
91 
OpenSSL_BlockCipher(const std::string & algo_name,const EVP_CIPHER * algo,size_t key_min,size_t key_max,size_t key_mod)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", ERR_get_error());
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", ERR_get_error());
115    if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
116       throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
117 
118    if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
119       throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt", ERR_get_error());
120    if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
121       throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt", ERR_get_error());
122    }
123 
~OpenSSL_BlockCipher()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 */
key_schedule(const uint8_t key[],size_t length)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", ERR_get_error());
154    if(!EVP_DecryptInit_ex(m_decrypt, nullptr, nullptr, full_key.data(), nullptr))
155       throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
156 
157    m_key_set = true;
158    }
159 
160 /*
161 * Return a clone of this object
162 */
clone() const163 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 */
clear()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", ERR_get_error());
183    if(!EVP_CIPHER_CTX_cleanup(m_decrypt))
184       throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup decrypt", ERR_get_error());
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", ERR_get_error());
189    if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
190       throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
191    if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
192       throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt", ERR_get_error());
193    if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
194       throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt", ERR_get_error());
195    }
196 
197 }
198 
199 std::unique_ptr<BlockCipher>
make_openssl_block_cipher(const std::string & name)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 == "TripleDES")
227       return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_des_ede3_ecb, 16, 24, 8);
228 #endif
229 
230    return nullptr;
231    }
232 
233 }
234 
235