Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
m_cipher_key_spec
Key_Length_Specification m_cipher_key_spec
Definition: openssl_block.cpp:52
m_decrypt
EVP_CIPHER_CTX m_decrypt
Definition: openssl_block.cpp:54
m_cipher_name
std::string m_cipher_name
Definition: openssl_block.cpp:53
m_block_sz
size_t m_block_sz
Definition: openssl_block.cpp:51
m_encrypt
EVP_CIPHER_CTX m_encrypt
Definition: openssl_block.cpp:54
Botan
Definition: alg_id.cpp:13
MAKE_OPENSSL_BLOCK
#define MAKE_OPENSSL_BLOCK(evp_fn)
MAKE_OPENSSL_BLOCK_KEYLEN
#define MAKE_OPENSSL_BLOCK_KEYLEN(evp_fn, kl_min, kl_max, kl_mod)
Botan::make_openssl_block_cipher
std::unique_ptr< BlockCipher > make_openssl_block_cipher(const std::string &name)
Definition: openssl_block.cpp:157