MySQL 8.4.2
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() == false) 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() == false) {
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 Aes_operation_context context(data_id, auth_id, mode, block_size);
139
140 Keyring_aes_opmode opmode = context.opmode();
141 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 true) {
164 // Error would have been raised
165 return true;
166 }
167
168 std::unique_ptr<unsigned char[]> key_buffer =
169 std::make_unique<unsigned char[]>(key_length);
170 if (key_buffer.get() == nullptr) {
171 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_MEMORY_ALLOCATION_ERROR,
172 "key buffer", "encrypt", "keyring_aes");
173 }
174
175 char key_type_buffer[32] = {0};
176 size_t dummy_key_buffer_size, dummy_key_type_buffer_size;
177
178 if (fetch_template<Backend, Data_extension>(
179 it, key_buffer.get(), key_length, &dummy_key_buffer_size,
180 key_type_buffer, 32, &dummy_key_type_buffer_size,
181 keyring_operations, callbacks) == true) {
182 // Error would have been raised
183 return true;
184 }
185
186 std::string key_type(key_type_buffer);
187 std::transform(key_type.begin(), key_type.end(), key_type.begin(),
188 ::tolower);
189 if (key_type != "aes") {
190 LogComponentErr(INFORMATION_LEVEL,
191 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_KEY, data_id,
192 (auth_id == nullptr || !*auth_id) ? "NULL" : auth_id);
193 return true;
194 }
195
197 aes_encrypt(data_buffer, (unsigned int)data_buffer_length, out_buffer,
198 key_buffer.get(), (unsigned int)key_length, opmode, iv,
199 padding, out_length);
200
202 std::stringstream ss;
203 switch (ret) {
205 ss << "'Output size buffer is NULL'";
206 break;
208 ss << "'Key transformation error'";
209 break;
211 ss << "'Failed to allocate memory for encryption context'";
212 break;
214 ss << "'Invalid block mode'";
215 break;
217 ss << "'IV is empty'";
218 break;
220 ss << "'Could not complete operation'";
221 break;
222 default:
223 ss << "'Unknown error number: '" << ret;
224 break;
225 }
226 std::string ss_str = ss.str();
227 LogComponentErr(INFORMATION_LEVEL,
228 ER_NOTE_KEYRING_COMPONENT_AES_OPERATION_ERROR,
229 ss_str.c_str(), "encrypt", data_id,
230 (auth_id == nullptr || *auth_id) ? "NULL" : auth_id);
231 return true;
232 }
233
234 /* All is well */
235 return false;
236 } catch (...) {
237 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_EXCEPTION, "encrypt",
238 "keyring_aes");
239 return true;
240 }
241}
242
243/**
244 Decrypt given piece ciphertext
245
246 @param [in] data_id Name of the key
247 @param [in] auth_id Owner of the key
248 @param [in] mode AES mode
249 @param [in] block_size AES block size information
250 @param [in] iv Initialization vector
251 @param [in] padding padding preference
252 @param [in] data_buffer Input buffer
253 @param [in] data_buffer_length Input buffer length
254 @param [out] out_buffer Output buffer
255 @param [in] out_buffer_length Output buffer length
256 @param [out] out_length Length of decrypted data
257 @param [in] keyring_operations Reference to the object
258 that handles cache and backend
259 @param [in] callbacks Handle to component specific callbacks
260
261 @returns status of the operation
262 @retval false Success
263 @retval true Failure
264
265*/
266template <typename Backend, typename Data_extension = Data>
268 const char *data_id, const char *auth_id, const char *mode,
269 size_t block_size, const unsigned char *iv, bool padding,
270 const unsigned char *data_buffer, size_t data_buffer_length,
271 unsigned char *out_buffer, size_t out_buffer_length, size_t *out_length,
273 Component_callbacks &callbacks) {
274 try {
275 if (callbacks.keyring_initialized() == false) {
276 return true;
277 }
278
279 if (mode == nullptr || block_size == 0) {
280 LogComponentErr(ERROR_LEVEL,
281 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_MODE_BLOCK_SIZE);
282 return true;
283 }
284
285 if (data_id == nullptr) {
286 LogComponentErr(INFORMATION_LEVEL,
287 ER_NOTE_KEYRING_COMPONENT_AES_DATA_IDENTIFIER_EMPTY);
288 return true;
289 }
290
291 Aes_operation_context context(data_id, auth_id, mode, block_size);
292
293 Keyring_aes_opmode opmode = context.opmode();
294
295 if (out_buffer == nullptr || data_buffer_length > out_buffer_length) {
296 assert(false);
297 return true;
298 }
299
300 size_t key_length = 0;
301 size_t key_type_length = 0;
302 std::unique_ptr<Iterator<Data_extension>> it;
303 int retval = init_reader_template<Backend, Data_extension>(
304 data_id, auth_id, it, keyring_operations, callbacks);
305 auto cleanup_guard = create_scope_guard([&] {
306 (void)deinit_reader_template<Backend, Data_extension>(
307 it, keyring_operations, callbacks);
308 });
309 if (retval < 1) {
310 // Error would have been raised
311 return true;
312 }
313 if (fetch_length_template<Backend, Data_extension>(
314 it, &key_length, &key_type_length, keyring_operations, callbacks) ==
315 true) {
316 // Error would have been raised
317 return true;
318 }
319
320 std::unique_ptr<unsigned char[]> key_buffer =
321 std::make_unique<unsigned char[]>(key_length);
322 if (key_buffer.get() == nullptr) {
323 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_MEMORY_ALLOCATION_ERROR,
324 "key buffer", "decrypt", "keyring_aes");
325 }
326
327 char key_type_buffer[32] = {0};
328 size_t dummy_key_buffer_size, dummy_key_type_buffer_size;
329
330 if (fetch_template<Backend, Data_extension>(
331 it, key_buffer.get(), key_length, &dummy_key_buffer_size,
332 key_type_buffer, 32, &dummy_key_type_buffer_size,
333 keyring_operations, callbacks) == true) {
334 // Error would have been raised
335 return true;
336 }
337
338 std::string key_type(key_type_buffer);
339 std::transform(key_type.begin(), key_type.end(), key_type.begin(),
340 ::tolower);
341 if (key_type != "aes") {
342 LogComponentErr(INFORMATION_LEVEL,
343 ER_NOTE_KEYRING_COMPONENT_AES_INVALID_KEY, data_id,
344 (auth_id == nullptr || !*auth_id) ? "NULL" : auth_id);
345 return true;
346 }
347
349 aes_decrypt(data_buffer, (unsigned int)data_buffer_length, out_buffer,
350 key_buffer.get(), (unsigned int)key_length, opmode, iv,
351 padding, out_length);
352
354 std::stringstream ss;
355 switch (ret) {
357 ss << "'Output size buffer is NULL'";
358 break;
360 ss << "'Key transformation error'";
361 break;
363 ss << "'Failed to allocate memory for encryption context'";
364 break;
366 ss << "'Invalid block mode'";
367 break;
369 ss << "'IV is empty'";
370 break;
372 ss << "'Could not complete operation'";
373 break;
374 default:
375 ss << "'Unknown error number: '" << ret;
376 break;
377 }
378 std::string ss_str = ss.str();
379 LogComponentErr(INFORMATION_LEVEL,
380 ER_NOTE_KEYRING_COMPONENT_AES_OPERATION_ERROR,
381 ss_str.c_str(), "decrypt", data_id,
382 (auth_id == nullptr || *auth_id) ? "NULL" : auth_id);
383 return true;
384 }
385
386 /* All is well */
387 return false;
388 } catch (...) {
389 LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_EXCEPTION, "decrypt",
390 "keyring_aes");
391 return true;
392 }
393}
394
395} // namespace service_implementation
396} // namespace keyring_common
397
398#endif // !KEYRING_ENCRYPTION_SERVICE_IMPL_TEMPLATE_INCLUDED
Keyring_aes_opmode opmode() const
Definition: aes.h:70
Keyring operations A class to perform operations on keyring.
Definition: operations.h:483
bool keyring_initialized()
Keyring component status.
Definition: component_callbacks.cc:29
@ 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:49
@ AES_OP_OK
Definition: aes.h:50
@ AES_DECRYPTION_ERROR
Definition: aes.h:57
@ AES_IV_EMPTY
Definition: aes.h:55
@ AES_CTX_ALLOCATION_ERROR
Definition: aes.h:53
@ AES_INVALID_BLOCK_MODE
Definition: aes.h:54
@ AES_KEY_TRANSFORMATION_ERROR
Definition: aes.h:52
@ AES_OUTPUT_SIZE_NULL
Definition: aes.h:51
@ AES_ENCRYPTION_ERROR
Definition: aes.h:56
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:191
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:141
Keyring_aes_opmode
Supported AES cipher/block mode combos.
Definition: aes.h:38
size_t get_ciphertext_size(size_t input_size, const Keyring_aes_opmode mode)
Definition: aes.cc:131
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:267
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)
Definition: scope_guard.h:61