Botan  2.7.0
Crypto and TLS for C++11
openssl_mode.cpp
Go to the documentation of this file.
1 /*
2 * Cipher Modes via OpenSSL
3 * (C) 1999-2010,2015 Jack Lloyd
4 * (C) 2017 Alexander Bluhm (genua GmbH)
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/cipher_mode.h>
10 #include <botan/internal/rounding.h>
11 #include <botan/internal/openssl.h>
12 #include <openssl/evp.h>
13 #include <limits.h>
14 
15 namespace Botan {
16 
17 namespace {
18 
19 class OpenSSL_Cipher_Mode final : public Cipher_Mode
20  {
21  public:
22  OpenSSL_Cipher_Mode(const std::string& name,
23  const EVP_CIPHER* cipher,
24  Cipher_Dir direction);
25  ~OpenSSL_Cipher_Mode();
26 
27  std::string provider() const override { return "openssl"; }
28  std::string name() const override { return m_mode_name; }
29 
30  void start_msg(const uint8_t nonce[], size_t nonce_len) override;
31  size_t process(uint8_t msg[], size_t msg_len) override;
32  void finish(secure_vector<uint8_t>& final_block, size_t offset0) override;
33  size_t output_length(size_t input_length) const override;
34  size_t update_granularity() const override;
35  size_t minimum_final_size() const override;
36  size_t default_nonce_length() const override;
37  bool valid_nonce_length(size_t nonce_len) const override;
38  void clear() override;
39  void reset() override;
40  Key_Length_Specification key_spec() const override;
41 
42  private:
43  void key_schedule(const uint8_t key[], size_t length) override;
44 
45  const std::string m_mode_name;
46  const Cipher_Dir m_direction;
47  size_t m_block_size;
48  EVP_CIPHER_CTX* m_cipher;
49  };
50 
51 OpenSSL_Cipher_Mode::OpenSSL_Cipher_Mode(const std::string& name,
52  const EVP_CIPHER* algo,
53  Cipher_Dir direction) :
54  m_mode_name(name),
55  m_direction(direction)
56  {
57  m_block_size = EVP_CIPHER_block_size(algo);
58 
59  if(EVP_CIPHER_mode(algo) != EVP_CIPH_CBC_MODE)
60  throw Invalid_Argument("OpenSSL_BlockCipher: Non-CBC EVP was passed in");
61 
62  m_cipher = EVP_CIPHER_CTX_new();
63  if (m_cipher == nullptr)
64  throw OpenSSL_Error("Can't allocate new context");
65 
66  EVP_CIPHER_CTX_init(m_cipher);
67  if(!EVP_CipherInit_ex(m_cipher, algo, nullptr, nullptr, nullptr,
68  m_direction == ENCRYPTION ? 1 : 0))
69  throw OpenSSL_Error("EVP_CipherInit_ex");
70  if(!EVP_CIPHER_CTX_set_padding(m_cipher, 0))
71  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding");
72  }
73 
74 OpenSSL_Cipher_Mode::~OpenSSL_Cipher_Mode()
75  {
76  EVP_CIPHER_CTX_free(m_cipher);
77  }
78 
79 void OpenSSL_Cipher_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
80  {
81  if(!valid_nonce_length(nonce_len))
82  throw Invalid_IV_Length(name(), nonce_len);
83  if(nonce_len)
84  {
85  if(!EVP_CipherInit_ex(m_cipher, nullptr, nullptr, nullptr, nonce, -1))
86  throw OpenSSL_Error("EVP_CipherInit_ex nonce");
87  }
88  }
89 
90 size_t OpenSSL_Cipher_Mode::process(uint8_t msg[], size_t msg_len)
91  {
92  if(msg_len == 0)
93  return 0;
94  if(msg_len > INT_MAX)
95  throw Internal_Error("msg_len overflow");
96  int outl = msg_len;
97  secure_vector<uint8_t> out(outl);
98 
99  if(!EVP_CipherUpdate(m_cipher, out.data(), &outl, msg, msg_len))
100  throw OpenSSL_Error("EVP_CipherUpdate");
101  memcpy(msg, out.data(), outl);
102  return outl;
103  }
104 
105 void OpenSSL_Cipher_Mode::finish(secure_vector<uint8_t>& buffer,
106  size_t offset)
107  {
108  BOTAN_ASSERT(buffer.size() >= offset, "Offset ok");
109  uint8_t* buf = buffer.data() + offset;
110  const size_t buf_size = buffer.size() - offset;
111 
112  size_t written = process(buf, buf_size);
113  int outl = buf_size - written;
114  secure_vector<uint8_t> out(outl);
115 
116  if(!EVP_CipherFinal_ex(m_cipher, out.data(), &outl))
117  throw OpenSSL_Error("EVP_CipherFinal_ex");
118  memcpy(buf + written, out.data(), outl);
119  written += outl;
120  buffer.resize(offset + written);
121  }
122 
123 size_t OpenSSL_Cipher_Mode::update_granularity() const
124  {
125  return m_block_size * BOTAN_BLOCK_CIPHER_PAR_MULT;
126  }
127 
128 size_t OpenSSL_Cipher_Mode::minimum_final_size() const
129  {
130  return 0; // no padding
131  }
132 
133 size_t OpenSSL_Cipher_Mode::default_nonce_length() const
134  {
135  return m_block_size;
136  }
137 
138 bool OpenSSL_Cipher_Mode::valid_nonce_length(size_t nonce_len) const
139  {
140  return (nonce_len == 0 || nonce_len == m_block_size);
141  }
142 
143 size_t OpenSSL_Cipher_Mode::output_length(size_t input_length) const
144  {
145  if(input_length == 0)
146  return m_block_size;
147  else
148  return round_up(input_length, m_block_size);
149  }
150 
151 void OpenSSL_Cipher_Mode::clear()
152  {
153  const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(m_cipher);
154 
155  if(!EVP_CIPHER_CTX_cleanup(m_cipher))
156  throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup");
157  EVP_CIPHER_CTX_init(m_cipher);
158  if(!EVP_CipherInit_ex(m_cipher, algo, nullptr, nullptr, nullptr,
159  m_direction == ENCRYPTION ? 1 : 0))
160  throw OpenSSL_Error("EVP_CipherInit_ex clear");
161  if(!EVP_CIPHER_CTX_set_padding(m_cipher, 0))
162  throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding clear");
163  }
164 
165 void OpenSSL_Cipher_Mode::reset()
166  {
167  if(!EVP_CipherInit_ex(m_cipher, nullptr, nullptr, nullptr, nullptr, -1))
168  throw OpenSSL_Error("EVP_CipherInit_ex clear");
169  }
170 
171 Key_Length_Specification OpenSSL_Cipher_Mode::key_spec() const
172  {
173  return Key_Length_Specification(EVP_CIPHER_CTX_key_length(m_cipher));
174  }
175 
176 void OpenSSL_Cipher_Mode::key_schedule(const uint8_t key[], size_t length)
177  {
178  if(!EVP_CIPHER_CTX_set_key_length(m_cipher, length))
179  throw OpenSSL_Error("EVP_CIPHER_CTX_set_key_length");
180  if(!EVP_CipherInit_ex(m_cipher, nullptr, nullptr, key, nullptr, -1))
181  throw OpenSSL_Error("EVP_CipherInit_ex key");
182  }
183 
184 }
185 
186 Cipher_Mode*
187 make_openssl_cipher_mode(const std::string& name, Cipher_Dir direction)
188  {
189 #define MAKE_OPENSSL_MODE(evp_fn) \
190  new OpenSSL_Cipher_Mode(name, (evp_fn)(), direction)
191 
192 #if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC) && !defined(OPENSSL_NO_AES)
193  if(name == "AES-128/CBC/NoPadding")
194  return MAKE_OPENSSL_MODE(EVP_aes_128_cbc);
195  if(name == "AES-192/CBC/NoPadding")
196  return MAKE_OPENSSL_MODE(EVP_aes_192_cbc);
197  if(name == "AES-256/CBC/NoPadding")
198  return MAKE_OPENSSL_MODE(EVP_aes_256_cbc);
199 #endif
200 
201 #undef MAKE_OPENSSL_MODE
202  return nullptr;
203  }
204 
205 }
Cipher_Mode * make_openssl_cipher_mode(const std::string &name, Cipher_Dir direction)
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:43
Definition: alg_id.cpp:13
Cipher_Dir
Definition: cipher_mode.h:24
size_t round_up(size_t n, size_t align_to)
Definition: rounding.h:21
#define MAKE_OPENSSL_MODE(evp_fn)