Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

commoncrypto_mode.cpp
Go to the documentation of this file.
1 /*
2 * Cipher Modes via CommonCrypto
3 * (C) 2018 Jose Pereira
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/cipher_mode.h>
9 #include <botan/internal/rounding.h>
10 #include <botan/internal/commoncrypto.h>
11
12 #include "commoncrypto_utils.h"
13
14 #include <limits.h>
15
16 namespace Botan {
17
18 namespace {
19
20 class CommonCrypto_Cipher_Mode final : public Cipher_Mode
21 {
22 public:
23 CommonCrypto_Cipher_Mode(const std::string& name,
24 Cipher_Dir direction,
25 const CommonCryptor_Opts& opts);
26
27 ~CommonCrypto_Cipher_Mode();
28
29 std::string provider() const override { return "commoncrypto"; }
30 std::string name() const override { return m_mode_name; }
31
32 void start_msg(const uint8_t nonce[], size_t nonce_len) override;
33 size_t process(uint8_t msg[], size_t msg_len) override;
34 void finish(secure_vector<uint8_t>& final_block, size_t offset0) override;
35 size_t output_length(size_t input_length) const override;
36 size_t update_granularity() const override;
37 size_t minimum_final_size() const override;
38 size_t default_nonce_length() const override;
39 bool valid_nonce_length(size_t nonce_len) const override;
40 void clear() override;
41 void reset() override;
42 Key_Length_Specification key_spec() const override;
43
44 private:
45 void key_schedule(const uint8_t key[], size_t length) override;
46
47 const std::string m_mode_name;
48 Cipher_Dir m_direction;
49 CommonCryptor_Opts m_opts;
50 CCCryptorRef m_cipher = nullptr;
51 bool m_key_set;
52 bool m_nonce_set;
53 };
54
55 CommonCrypto_Cipher_Mode::CommonCrypto_Cipher_Mode(const std::string& name,
56 Cipher_Dir direction, const CommonCryptor_Opts& opts) :
57 m_mode_name(name),
58 m_direction(direction),
59 m_opts(opts),
60 m_key_set(false),
61 m_nonce_set(false)
62 {
63 }
64
65 CommonCrypto_Cipher_Mode::~CommonCrypto_Cipher_Mode()
66 {
67 if(m_cipher)
68 {
69 CCCryptorRelease(m_cipher);
70 }
71 }
72
73 void CommonCrypto_Cipher_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
74 {
75 verify_key_set(m_key_set);
76
77 if(!valid_nonce_length(nonce_len))
78 { throw Invalid_IV_Length(name(), nonce_len); }
79 if(nonce_len)
80 {
81 CCCryptorStatus status = CCCryptorReset(m_cipher, nonce);
82 if(status != kCCSuccess)
83 {
84 throw CommonCrypto_Error("CCCryptorReset on start_msg", status);
85 }
86 }
87 m_nonce_set = true;
88 }
89
90 size_t CommonCrypto_Cipher_Mode::process(uint8_t msg[], size_t msg_len)
91 {
92 verify_key_set(m_key_set);
93 BOTAN_STATE_CHECK(m_nonce_set);
94
95 if(msg_len == 0)
96 { return 0; }
97 if(msg_len > INT_MAX)
98 { throw Internal_Error("msg_len overflow"); }
99 size_t outl = CCCryptorGetOutputLength(m_cipher, msg_len, false);
100
101 secure_vector<uint8_t> out(outl);
102
103 if(m_opts.padding == ccNoPadding && msg_len % m_opts.block_size)
104 {
105 msg_len = outl;
106 }
107
108 CCCryptorStatus status = CCCryptorUpdate(m_cipher, msg, msg_len,
109 out.data(), outl, &outl);
110 if(status != kCCSuccess)
111 {
112 throw CommonCrypto_Error("CCCryptorUpdate", status);
113 }
114 copy_mem(msg, out.data(), outl);
115
116 return outl;
117 }
118
119 void CommonCrypto_Cipher_Mode::finish(secure_vector<uint8_t>& buffer,
120 size_t offset)
121 {
122 verify_key_set(m_key_set);
123 BOTAN_STATE_CHECK(m_nonce_set);
124
125 BOTAN_ASSERT(buffer.size() >= offset, "Offset ok");
126 uint8_t* buf = buffer.data() + offset;
127 const size_t buf_size = buffer.size() - offset;
128
129 size_t written = process(buf, buf_size);
130
131 size_t outl = CCCryptorGetOutputLength(m_cipher, buf_size - written, true);
132 secure_vector<uint8_t> out(outl);
133
134 CCCryptorStatus status = CCCryptorFinal(
135 m_cipher, out.data(), outl, &outl);
136 if(status != kCCSuccess)
137 {
138 throw CommonCrypto_Error("CCCryptorFinal", status);
139 }
140
141 size_t new_len = offset + written + outl;
142 if(m_opts.padding != ccNoPadding || buffer.size() < new_len)
143 {
144 buffer.resize(new_len);
145 }
146 copy_mem(buffer.data() - offset + written, out.data(), outl);
147 written += outl;
148 }
149
150 size_t CommonCrypto_Cipher_Mode::update_granularity() const
151 {
152 return m_opts.block_size * BOTAN_BLOCK_CIPHER_PAR_MULT;
153 }
154
155 size_t CommonCrypto_Cipher_Mode::minimum_final_size() const
156 {
157 if(m_direction == ENCRYPTION)
158 return 0;
159 else
160 return m_opts.block_size;
161 }
162
163 size_t CommonCrypto_Cipher_Mode::default_nonce_length() const
164 {
165 return m_opts.block_size;
166 }
167
168 bool CommonCrypto_Cipher_Mode::valid_nonce_length(size_t nonce_len) const
169 {
170 return (nonce_len == 0 || nonce_len == m_opts.block_size);
171 }
172
173 size_t CommonCrypto_Cipher_Mode::output_length(size_t input_length) const
174 {
175 if(input_length == 0)
176 { return m_opts.block_size; }
177 else
178 { return round_up(input_length, m_opts.block_size); }
179 }
180
181 void CommonCrypto_Cipher_Mode::clear()
182 {
183 m_key_set = false;
184
185 if(m_cipher == nullptr)
186 {
187 return;
188 }
189
190 if(m_cipher)
191 {
192 CCCryptorRelease(m_cipher);
193 m_cipher = nullptr;
194 }
195 }
196
197 void CommonCrypto_Cipher_Mode::reset()
198 {
199 if(m_cipher == nullptr)
200 {
201 return;
202 }
203
204 m_nonce_set = false;
205
206 CCCryptorStatus status = CCCryptorReset(m_cipher, nullptr);
207 if(status != kCCSuccess)
208 {
209 throw CommonCrypto_Error("CCCryptorReset", status);
210 }
211 }
212
213 Key_Length_Specification CommonCrypto_Cipher_Mode::key_spec() const
214 {
215 return m_opts.key_spec;
216 }
217
218 void CommonCrypto_Cipher_Mode::key_schedule(const uint8_t key[], size_t length)
219 {
220 CCCryptorStatus status;
221 CCOperation op = m_direction == ENCRYPTION ? kCCEncrypt : kCCDecrypt;
222 status = CCCryptorCreateWithMode(op, m_opts.mode, m_opts.algo, m_opts.padding,
223 nullptr, key, length, nullptr, 0, 0, 0, &m_cipher);
224 if(status != kCCSuccess)
225 {
226 throw CommonCrypto_Error("CCCryptorCreate", status);
227 }
228
229 m_key_set = true;
230 m_nonce_set = false;
231 }
232 }
233
234 Cipher_Mode*
235 make_commoncrypto_cipher_mode(const std::string& name, Cipher_Dir direction)
236 {
237
238 try
239 {
240 CommonCryptor_Opts opts = commoncrypto_opts_from_algo(name);
241 return new CommonCrypto_Cipher_Mode(name, direction, opts);
242 }
243 catch(CommonCrypto_Error& e)
244 {
245 return nullptr;
246 }
247 }
248 }
m_cipher
CCCryptorRef m_cipher
Definition: commoncrypto_mode.cpp:50
Botan::commoncrypto_opts_from_algo
CommonCryptor_Opts commoncrypto_opts_from_algo(const std::string &algo)
Definition: commoncrypto_utils.cpp:52
m_opts
CommonCryptor_Opts m_opts
Definition: commoncrypto_mode.cpp:49
m_mode_name
const std::string m_mode_name
Definition: commoncrypto_mode.cpp:47
commoncrypto_utils.h
final
int(* final)(unsigned char *, CTX *)
Definition: commoncrypto_hash.cpp:28
BOTAN_STATE_CHECK
#define BOTAN_STATE_CHECK(expr)
Definition: assert.h:49
Botan::CommonCrypto_Error
Definition: commoncrypto.h:25
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
name
std::string name
Definition: commoncrypto_hash.cpp:23
m_nonce_set
bool m_nonce_set
Definition: commoncrypto_mode.cpp:52
Botan::CommonCryptor_Opts
Definition: commoncrypto_utils.h:19
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:132
Botan
Definition: alg_id.cpp:13
m_direction
Cipher_Dir m_direction
Definition: commoncrypto_mode.cpp:48
Botan::Cipher_Dir
Cipher_Dir
Definition: cipher_mode.h:23
m_key_set
bool m_key_set
Definition: commoncrypto_mode.cpp:51
Botan::ENCRYPTION
Definition: cipher_mode.h:23
Botan::OCSP::Response_Status_Code::Internal_Error
Botan::round_up
size_t round_up(size_t n, size_t align_to)
Definition: rounding.h:21
Botan::make_commoncrypto_cipher_mode
Cipher_Mode * make_commoncrypto_cipher_mode(const std::string &name, Cipher_Dir direction)
Definition: commoncrypto_mode.cpp:235