MySQL 9.1.0
Source Code Documentation
keyring_encryption_service_impl_template.h
Go to the documentation of this file.
1/* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
2
3This program is free software; you can redistribute it and/or modify
4it under the terms of the GNU General Public License, version 2.0,
5as published by the Free Software Foundation.
6
7This program is designed to work with certain software (including
8but not limited to OpenSSL) that is licensed under separate terms,
9as designated in a particular file or component or in included license
10documentation. The authors of MySQL hereby grant you an additional
11permission to link the program and your derivative works with the
12separately licensed software that they have either included with
13the program or referenced in the documentation.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License, version 2.0, for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef KEYRING_ENCRYPTION_SERVICE_IMPL_TEMPLATE_INCLUDED
25#define KEYRING_ENCRYPTION_SERVICE_IMPL_TEMPLATE_INCLUDED
26
27#include <algorithm> /* std::transform */
28#include <cctype>
29#include <cstring>
30#include <functional>
31#include <memory> /* std::unique_ptr */
32#include <sstream> /* std::stringstream */
33
34#include <my_dbug.h>
35#include <mysql/components/services/log_builtins.h> /* LogComponentErr */
36#include <mysqld_error.h>
37#include <scope_guard.h>
38
42#include <components/keyrings/common/encryption/aes.h> /* AES encryption */
44
45namespace keyring_common {
46
49using aes_encryption::Aes_operation_context;
53using data::Data;
54using operations::Keyring_operations;
55
56namespace service_implementation {
57/**
58 Retrieve required out buffer length information
59
60 @param [in] input_length Length of input text
61 @param [in] mode Block encryption mode
62 @param [in] block_size AES block size
63 @param [out] out_size Out buffer length
64
65 @returns Output buffer length or error
66 @retval false Success
67 @retval true Error processing given mode and/or block size
68*/
69bool aes_get_encrypted_size_template(size_t input_length, const char *mode,
70 size_t block_size, size_t *out_size) {
71 try {
72 if (mode == nullptr || block_size == 0) {
73 LogComponentErr(ERROR_LEVEL,
74 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_MODE_BLOCK_SIZE);
75 return true;
76 }
77
78 const Aes_operation_context context(std::string{}, std::string{}, mode,
79 block_size);
80 if (!context.valid()) return true;
81 *out_size = get_ciphertext_size(input_length, context.opmode());
82 return false;
83 } catch (...) {
84 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_EXCEPTION, "get_size",
85 "keyring_aes");
86 return true;
87 }
88}
89
90/**
91 Encrypt given piece of plaintext
92
93 @param [in] data_id Name of the key
94 @param [in] auth_id Owner of the key
95 @param [in] mode AES mode
96 @param [in] block_size AES block size information
97 @param [in] iv Initialization vector
98 @param [in] padding padding preference
99 @param [in] data_buffer Input buffer
100 @param [in] data_buffer_length Input buffer length
101 @param [out] out_buffer Output buffer
102 @param [in] out_buffer_length Output buffer length
103 @param [out] out_length Length of encrypted data
104 @param [in] keyring_operations Reference to the object
105 that handles cache and backend
106 @param [in] callbacks Handle to component specific callbacks
107
108 @returns status of the operation
109 @retval false Success
110 @retval true Failure
111
112*/
113template <typename Backend, typename Data_extension = Data>
115 const char *data_id, const char *auth_id, const char *mode,
116 size_t block_size, const unsigned char *iv, bool padding,
117 const unsigned char *data_buffer, size_t data_buffer_length,
118 unsigned char *out_buffer, size_t out_buffer_length, size_t *out_length,
120 Component_callbacks &callbacks) {
121 try {
122 if (!callbacks.keyring_initialized()) {
123 return true;
124 }
125
126 if (mode == nullptr || block_size == 0) {
127 LogComponentErr(ERROR_LEVEL,
128 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_MODE_BLOCK_SIZE);
129 return true;
130 }
131
132 if (data_id == nullptr) {
133 LogComponentErr(INFORMATION_LEVEL,
134 ER_NOTE_KEYRING_COMPONENT_AES_DATA_IDENTIFIER_EMPTY);
135 return true;
136 }
137
138 const Aes_operation_context context(data_id, auth_id, mode, block_size);
139
140 const Keyring_aes_opmode opmode = context.opmode();
141 const size_t required_out_buffer_size =
142 get_ciphertext_size(data_buffer_length, opmode);
143 if (out_buffer == nullptr || required_out_buffer_size > out_buffer_length) {
144 assert(false);
145 return true;
146 }
147
148 size_t key_length = 0;
149 size_t key_type_length = 0;
150 std::unique_ptr<Iterator<Data_extension>> it;
151 int retval = init_reader_template<Backend, Data_extension>(
152 data_id, auth_id, it, keyring_operations, callbacks);
153 auto cleanup_guard = create_scope_guard([&] {
154 (void)deinit_reader_template<Backend, Data_extension>(
155 it, keyring_operations, callbacks);
156 });
157 if (retval < 1) {
158 // Error would have been raised
159 return true;
160 }
161 if (fetch_length_template<Backend, Data_extension>(
162 it, &key_length, &key_type_length, keyring_operations, callbacks)) {
163 // Error would have been raised
164 return true;
165 }
166
167 const std::unique_ptr<unsigned char[]> key_buffer =
168 std::make_unique<unsigned char[]>(key_length);
169 if (key_buffer == nullptr) {
170 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_MEMORY_ALLOCATION_ERROR,
171 "key buffer", "encrypt", "keyring_aes");
172 }
173
174 char key_type_buffer[32] = {0};
175 size_t dummy_key_buffer_size, dummy_key_type_buffer_size;
176
177 if (fetch_template<Backend, Data_extension>(
178 it, key_buffer.get(), key_length, &dummy_key_buffer_size,
179 key_type_buffer, 32, &dummy_key_type_buffer_size,
180 keyring_operations, callbacks)) {
181 // Error would have been raised
182 return true;
183 }
184
185 std::string key_type(key_type_buffer);
186 std::transform(key_type.begin(), key_type.end(), key_type.begin(),
187 ::tolower);
188 if (key_type != "aes") {
189 LogComponentErr(INFORMATION_LEVEL,
190 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_KEY, data_id,
191 (auth_id == nullptr || !*auth_id) ? "NULL" : auth_id);
192 return true;
193 }
194
195 const aes_return_status ret =
196 aes_encrypt(data_buffer, (unsigned int)data_buffer_length, out_buffer,
197 key_buffer.get(), (unsigned int)key_length, opmode, iv,
198 padding, out_length);
199
201 std::stringstream ss;
202 switch (ret) {
204 ss << "'Output size buffer is NULL'";
205 break;
207 ss << "'Key transformation error'";
208 break;
210 ss << "'Failed to allocate memory for encryption context'";
211 break;
213 ss << "'Invalid block mode'";
214 break;
216 ss << "'IV is empty'";
217 break;
219 ss << "'Could not complete operation'";
220 break;
221 default:
222 ss << "'Unknown error number: '" << ret;
223 break;
224 }
225 const std::string ss_str = ss.str();
226 LogComponentErr(INFORMATION_LEVEL,
227 ER_NOTE_KEYRING_COMPONENT_AES_OPERATION_ERROR,
228 ss_str.c_str(), "encrypt", data_id,
229 (auth_id == nullptr || *auth_id) ? "NULL" : auth_id);
230 return true;
231 }
232
233 /* All is well */
234 return false;
235 } catch (...) {
236 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_EXCEPTION, "encrypt",
237 "keyring_aes");
238 return true;
239 }
240}
241
242/**
243 Decrypt given piece ciphertext
244
245 @param [in] data_id Name of the key
246 @param [in] auth_id Owner of the key
247 @param [in] mode AES mode
248 @param [in] block_size AES block size information
249 @param [in] iv Initialization vector
250 @param [in] padding padding preference
251 @param [in] data_buffer Input buffer
252 @param [in] data_buffer_length Input buffer length
253 @param [out] out_buffer Output buffer
254 @param [in] out_buffer_length Output buffer length
255 @param [out] out_length Length of decrypted data
256 @param [in] keyring_operations Reference to the object
257 that handles cache and backend
258 @param [in] callbacks Handle to component specific callbacks
259
260 @returns status of the operation
261 @retval false Success
262 @retval true Failure
263
264*/
265template <typename Backend, typename Data_extension = Data>
267 const char *data_id, const char *auth_id, const char *mode,
268 size_t block_size, const unsigned char *iv, bool padding,
269 const unsigned char *data_buffer, size_t data_buffer_length,
270 unsigned char *out_buffer, size_t out_buffer_length, size_t *out_length,
272 Component_callbacks &callbacks) {
273 try {
274 if (!callbacks.keyring_initialized()) {
275 return true;
276 }
277
278 if (mode == nullptr || block_size == 0) {
279 LogComponentErr(ERROR_LEVEL,
280 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_MODE_BLOCK_SIZE);
281 return true;
282 }
283
284 if (data_id == nullptr) {
285 LogComponentErr(INFORMATION_LEVEL,
286 ER_NOTE_KEYRING_COMPONENT_AES_DATA_IDENTIFIER_EMPTY);
287 return true;
288 }
289
290 Aes_operation_context context(data_id, auth_id, mode, block_size);
291
292 Keyring_aes_opmode opmode = context.opmode();
293
294 if (out_buffer == nullptr || data_buffer_length > out_buffer_length) {
295 assert(false);
296 return true;
297 }
298
299 size_t key_length = 0;
300 size_t key_type_length = 0;
301 std::unique_ptr<Iterator<Data_extension>> it;
302 int retval = init_reader_template<Backend, Data_extension>(
303 data_id, auth_id, it, keyring_operations, callbacks);
304 auto cleanup_guard = create_scope_guard([&] {
305 (void)deinit_reader_template<Backend, Data_extension>(
306 it, keyring_operations, callbacks);
307 });
308 if (retval < 1) {
309 // Error would have been raised
310 return true;
311 }
312 if (fetch_length_template<Backend, Data_extension>(
313 it, &key_length, &key_type_length, keyring_operations, callbacks)) {
314 // Error would have been raised
315 return true;
316 }
317
318 std::unique_ptr<unsigned char[]> key_buffer =
319 std::make_unique<unsigned char[]>(key_length);
320 if (key_buffer.get() == nullptr) {
321 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_MEMORY_ALLOCATION_ERROR,
322 "key buffer", "decrypt", "keyring_aes");
323 }
324
325 char key_type_buffer[32] = {0};
326 size_t dummy_key_buffer_size, dummy_key_type_buffer_size;
327
328 if (fetch_template<Backend, Data_extension>(
329 it, key_buffer.get(), key_length, &dummy_key_buffer_size,
330 key_type_buffer, 32, &dummy_key_type_buffer_size,
331 keyring_operations, callbacks)) {
332 // Error would have been raised
333 return true;
334 }
335
336 std::string key_type(key_type_buffer);
337 std::transform(key_type.begin(), key_type.end(), key_type.begin(),
338 ::tolower);
339 if (key_type != "aes") {
340 LogComponentErr(INFORMATION_LEVEL,
341 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_KEY, data_id,
342 (auth_id == nullptr || !*auth_id) ? "NULL" : auth_id);
343 return true;
344 }
345
347 aes_decrypt(data_buffer, (unsigned int)data_buffer_length, out_buffer,
348 key_buffer.get(), (unsigned int)key_length, opmode, iv,
349 padding, out_length);
350
352 std::stringstream ss;
353 switch (ret) {
355 ss << "'Output size buffer is NULL'";
356 break;
358 ss << "'Key transformation error'";
359 break;
361 ss << "'Failed to allocate memory for encryption context'";
362 break;
364 ss << "'Invalid block mode'";
365 break;
367 ss << "'IV is empty'";
368 break;
370 ss << "'Could not complete operation'";
371 break;
372 default:
373 ss << "'Unknown error number: '" << ret;
374 break;
375 }
376 const std::string ss_str = ss.str();
377 LogComponentErr(INFORMATION_LEVEL,
378 ER_NOTE_KEYRING_COMPONENT_AES_OPERATION_ERROR,
379 ss_str.c_str(), "decrypt", data_id,
380 (auth_id == nullptr || *auth_id) ? "NULL" : auth_id);
381 return true;
382 }
383
384 /* All is well */
385 return false;
386 } catch (...) {
387 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_EXCEPTION, "decrypt",
388 "keyring_aes");
389 return true;
390 }
391}
392
393} // namespace service_implementation
394} // namespace keyring_common
395
396#endif // !KEYRING_ENCRYPTION_SERVICE_IMPL_TEMPLATE_INCLUDED
Keyring_aes_opmode opmode() const
Definition: aes.h:68
Keyring operations A class to perform operations on keyring.
Definition: operations.h:482
bool keyring_initialized()
Keyring component status.
Definition: component_callbacks.cc:28
@ ERROR_LEVEL
Definition: my_loglevel.h:43
@ INFORMATION_LEVEL
Definition: my_loglevel.h:45
bool transform(const dd::Spatial_reference_system *source_srs, const Geometry &in, const dd::Spatial_reference_system *target_srs, const char *func_name, std::unique_ptr< Geometry > *out) noexcept
Transforms a geometry from one SRS to another.
Definition: transform.cc:216
int key_type
Definition: method.h:38
aes_return_status
Definition: aes.h:47
@ AES_OP_OK
Definition: aes.h:48
@ AES_DECRYPTION_ERROR
Definition: aes.h:55
@ AES_IV_EMPTY
Definition: aes.h:53
@ AES_CTX_ALLOCATION_ERROR
Definition: aes.h:51
@ AES_INVALID_BLOCK_MODE
Definition: aes.h:52
@ AES_KEY_TRANSFORMATION_ERROR
Definition: aes.h:50
@ AES_OUTPUT_SIZE_NULL
Definition: aes.h:49
@ AES_ENCRYPTION_ERROR
Definition: aes.h:54
aes_return_status aes_decrypt(const unsigned char *source, unsigned int source_length, unsigned char *dest, const unsigned char *key, unsigned int key_length, enum Keyring_aes_opmode mode, const unsigned char *iv, bool padding, size_t *decrypted_length)
Definition: aes.cc:187
aes_return_status aes_encrypt(const unsigned char *source, unsigned int source_length, unsigned char *dest, const unsigned char *key, unsigned int key_length, Keyring_aes_opmode mode, const unsigned char *iv, bool padding, size_t *encrypted_length)
Definition: aes.cc:137
Keyring_aes_opmode
Supported AES cipher/block mode combos.
Definition: aes.h:37
size_t get_ciphertext_size(size_t input_size, const Keyring_aes_opmode mode)
Definition: aes.cc:127
bool aes_decrypt_template(const char *data_id, const char *auth_id, const char *mode, size_t block_size, const unsigned char *iv, bool padding, const unsigned char *data_buffer, size_t data_buffer_length, unsigned char *out_buffer, size_t out_buffer_length, size_t *out_length, Keyring_operations< Backend, Data_extension > &keyring_operations, Component_callbacks &callbacks)
Decrypt given piece ciphertext.
Definition: keyring_encryption_service_impl_template.h:266
bool aes_get_encrypted_size_template(size_t input_length, const char *mode, size_t block_size, size_t *out_size)
Retrieve required out buffer length information.
Definition: keyring_encryption_service_impl_template.h:69
bool aes_encrypt_template(const char *data_id, const char *auth_id, const char *mode, size_t block_size, const unsigned char *iv, bool padding, const unsigned char *data_buffer, size_t data_buffer_length, unsigned char *out_buffer, size_t out_buffer_length, size_t *out_length, Keyring_operations< Backend, Data_extension > &keyring_operations, Component_callbacks &callbacks)
Encrypt given piece of plaintext.
Definition: keyring_encryption_service_impl_template.h:114
Definition: keyring_encryption_service_definition.h:32
char tolower(const char &ch)
Definition: parsing_helpers.h:41
mode
Definition: file_handle.h:61
Scope_guard< TLambda > create_scope_guard(const TLambda rollback_lambda)
Create a scope guard object.
Definition: scope_guard.h:113