1 /***********************************************************************
2 
3 Copyright (c) 2019, 2020, Oracle and/or its affiliates.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 
25 ***********************************************************************/
26 
27 /** @file include/os0enc.h
28  Page encryption infrastructure. */
29 
30 #ifndef os0enc_h
31 #define os0enc_h
32 
33 #include "univ.i"
34 
35 // Forward declaration.
36 class IORequest;
37 
38 /** Encryption algorithm. */
39 class Encryption {
40  public:
41   /** Algorithm types supported */
42   enum Type {
43 
44     /** No encryption */
45     NONE = 0,
46 
47     /** Use AES */
48     AES = 1,
49   };
50 
51   /** Encryption information format version */
52   enum Version {
53 
54     /** Version in 5.7.11 */
55     VERSION_1 = 0,
56 
57     /** Version in > 5.7.11 */
58     VERSION_2 = 1,
59 
60     /** Version in > 8.0.4 */
61     VERSION_3 = 2,
62   };
63 
64   /** Encryption magic bytes for 5.7.11, it's for checking the encryption
65   information version. */
66   static constexpr char KEY_MAGIC_V1[] = "lCA";
67 
68   /** Encryption magic bytes for 5.7.12+, it's for checking the encryption
69   information version. */
70   static constexpr char KEY_MAGIC_V2[] = "lCB";
71 
72   /** Encryption magic bytes for 8.0.5+, it's for checking the encryption
73   information version. */
74   static constexpr char KEY_MAGIC_V3[] = "lCC";
75 
76   /** Encryption master key prifix */
77   static constexpr char MASTER_KEY_PREFIX[] = "INNODBKey";
78 
79   /** Default master key for bootstrap */
80   static constexpr char DEFAULT_MASTER_KEY[] = "DefaultMasterKey";
81 
82   /** Encryption key length */
83   static constexpr size_t KEY_LEN = 32;
84 
85   /** Encryption magic bytes size */
86   static constexpr size_t MAGIC_SIZE = 3;
87 
88   /** Encryption master key prifix size */
89   static constexpr size_t MASTER_KEY_PRIFIX_LEN = 9;
90 
91   /** Encryption master key prifix size */
92   static constexpr size_t MASTER_KEY_NAME_MAX_LEN = 100;
93 
94   /** UUID of server instance, it's needed for composing master key name */
95   static constexpr size_t SERVER_UUID_LEN = 36;
96 
97   /** Encryption information total size: magic number + master_key_id +
98   key + iv + server_uuid + checksum */
99   static constexpr size_t INFO_SIZE =
100       (MAGIC_SIZE + sizeof(uint32) + (KEY_LEN * 2) + SERVER_UUID_LEN +
101        sizeof(uint32));
102 
103   /** Maximum size of Encryption information considering all
104   formats v1, v2 & v3. */
105   static constexpr size_t INFO_MAX_SIZE = INFO_SIZE + sizeof(uint32);
106 
107   /** Default master key id for bootstrap */
108   static constexpr size_t DEFAULT_MASTER_KEY_ID = 0;
109 
110   /** (De)Encryption Operation information size */
111   static constexpr size_t OPERATION_INFO_SIZE = 1;
112 
113   /** Encryption Progress information size */
114   static constexpr size_t PROGRESS_INFO_SIZE = sizeof(uint);
115 
116   /** Flag bit to indicate if Encryption/Decryption is in progress */
117   static constexpr size_t ENCRYPT_IN_PROGRESS = 1 << 0;
118 
119   /** Decryption in progress. */
120   static constexpr size_t DECRYPT_IN_PROGRESS = 1 << 1;
121 
122   /** Default constructor */
Encryption()123   Encryption() noexcept : m_type(NONE) {}
124 
125   /** Specific constructor
126   @param[in]  type    Algorithm type */
Encryption(Type type)127   explicit Encryption(Type type) noexcept : m_type(type) {
128 #ifdef UNIV_DEBUG
129     switch (m_type) {
130       case NONE:
131       case AES:
132 
133       default:
134         ut_error;
135     }
136 #endif /* UNIV_DEBUG */
137   }
138 
139   /** Copy constructor */
Encryption(const Encryption & other)140   Encryption(const Encryption &other) noexcept
141       : m_type(other.m_type),
142         m_key(other.m_key),
143         m_klen(other.m_klen),
144         m_iv(other.m_iv) {}
145 
146   Encryption &operator=(const Encryption &) = default;
147 
148   static void set_master_key(ulint master_key_id);
149 
150   /** Check if page is encrypted page or not
151   @param[in]  page  page which need to check
152   @return true if it is an encrypted page */
153   static bool is_encrypted_page(const byte *page) noexcept
154       MY_ATTRIBUTE((warn_unused_result));
155 
156   /** Check if a log block is encrypted or not
157   @param[in]  block block which need to check
158   @return true if it is an encrypted block */
159   static bool is_encrypted_log(const byte *block) noexcept
160       MY_ATTRIBUTE((warn_unused_result));
161 
162   /** Check the encryption option and set it
163   @param[in]      option      encryption option
164   @param[in,out]  type        The encryption type
165   @return DB_SUCCESS or DB_UNSUPPORTED */
166   dberr_t set_algorithm(const char *option, Encryption *type) noexcept
167       MY_ATTRIBUTE((warn_unused_result));
168 
169   /** Validate the algorithm string.
170   @param[in]  option  Encryption option
171   @return DB_SUCCESS or error code */
172   static dberr_t validate(const char *option) noexcept
173       MY_ATTRIBUTE((warn_unused_result));
174 
175   /** Convert to a "string".
176   @param[in]  type  The encryption type
177   @return the string representation */
178   static const char *to_string(Type type) noexcept
179       MY_ATTRIBUTE((warn_unused_result));
180 
181   /** Check if the string is "empty" or "none".
182   @param[in]  algorithm  Encryption algorithm to check
183   @return true if no algorithm requested */
184   static bool is_none(const char *algorithm) noexcept
185       MY_ATTRIBUTE((warn_unused_result));
186 
187   /** Generate random encryption value for key and iv.
188   @param[in,out]  value Encryption value */
189   static void random_value(byte *value) noexcept;
190 
191   /** Create new master key for key rotation.
192   @param[in,out]  master_key  master key */
193   static void create_master_key(byte **master_key) noexcept;
194 
195   /** Get master key by key id.
196   @param[in]      master_key_id master key id
197   @param[in]      srv_uuid      uuid of server instance
198   @param[in,out]  master_key    master key */
199   static void get_master_key(ulint master_key_id, char *srv_uuid,
200                              byte **master_key) noexcept;
201 
202   /** Get current master key and key id.
203   @param[in,out]  master_key_id master key id
204   @param[in,out]  master_key    master key */
205   static void get_master_key(ulint *master_key_id, byte **master_key) noexcept;
206 
207   /** Fill the encryption information.
208   @param[in]      key           encryption key
209   @param[in]      iv            encryption iv
210   @param[in,out]  encrypt_info  encryption information
211   @param[in]      is_boot       if it's for bootstrap
212   @param[in]      encrypt_key   encrypt with master key
213   @return true if success. */
214   static bool fill_encryption_info(byte *key, byte *iv, byte *encrypt_info,
215                                    bool is_boot, bool encrypt_key) noexcept;
216 
217   /** Get master key from encryption information
218   @param[in]      encrypt_info  encryption information
219   @param[in]      version       version of encryption information
220   @param[in,out]  m_key_id      master key id
221   @param[in,out]  srv_uuid      server uuid
222   @param[in,out]  master_key    master key
223   @return position after master key id or uuid, or the old position
224   if can't get the master key. */
225   static byte *get_master_key_from_info(byte *encrypt_info, Version version,
226                                         uint32_t *m_key_id, char *srv_uuid,
227                                         byte **master_key) noexcept;
228 
229   /** Decoding the encryption info from the first page of a tablespace.
230   @param[in,out]  key             key
231   @param[in,out]  iv              iv
232   @param[in]      encryption_info encryption info
233   @param[in]      decrypt_key     decrypt key using master key
234   @return true if success */
235   static bool decode_encryption_info(byte *key, byte *iv, byte *encryption_info,
236                                      bool decrypt_key) noexcept;
237 
238   /** Encrypt the redo log block.
239   @param[in]      type      IORequest
240   @param[in,out]  src_ptr   log block which need to encrypt
241   @param[in,out]  dst_ptr   destination area
242   @return true if success. */
243   bool encrypt_log_block(const IORequest &type, byte *src_ptr,
244                          byte *dst_ptr) noexcept;
245 
246   /** Encrypt the redo log data contents.
247   @param[in]      type      IORequest
248   @param[in,out]  src       page data which need to encrypt
249   @param[in]      src_len   size of the source in bytes
250   @param[in,out]  dst       destination area
251   @param[in,out]  dst_len   size of the destination in bytes
252   @return buffer data, dst_len will have the length of the data */
253   byte *encrypt_log(const IORequest &type, byte *src, ulint src_len, byte *dst,
254                     ulint *dst_len) noexcept;
255 
256   /** Encrypt the page data contents. Page type can't be
257   FIL_PAGE_ENCRYPTED, FIL_PAGE_COMPRESSED_AND_ENCRYPTED,
258   FIL_PAGE_ENCRYPTED_RTREE.
259   @param[in]      type      IORequest
260   @param[in,out]  src       page data which need to encrypt
261   @param[in]      src_len   size of the source in bytes
262   @param[in,out]  dst       destination area
263   @param[in,out]  dst_len   size of the destination in bytes
264   @return buffer data, dst_len will have the length of the data */
265   byte *encrypt(const IORequest &type, byte *src, ulint src_len, byte *dst,
266                 ulint *dst_len) noexcept MY_ATTRIBUTE((warn_unused_result));
267 
268   /** Decrypt the log block.
269   @param[in]      type  IORequest
270   @param[in,out]  src   data read from disk, decrypted data
271                         will be copied to this page
272   @param[in,out]  dst   scratch area to use for decryption
273   @return DB_SUCCESS or error code */
274   dberr_t decrypt_log_block(const IORequest &type, byte *src,
275                             byte *dst) noexcept;
276 
277   /** Decrypt the log data contents.
278   @param[in]      type      IORequest
279   @param[in,out]  src       data read from disk, decrypted data
280                             will be copied to this page
281   @param[in]      src_len   source data length
282   @param[in,out]  dst       scratch area to use for decryption
283   @param[in]      dst_len   size of the scratch area in bytes
284   @return DB_SUCCESS or error code */
285   dberr_t decrypt_log(const IORequest &type, byte *src, ulint src_len,
286                       byte *dst, ulint dst_len) noexcept;
287 
288   /** Decrypt the page data contents. Page type must be
289   FIL_PAGE_ENCRYPTED, FIL_PAGE_COMPRESSED_AND_ENCRYPTED,
290   FIL_PAGE_ENCRYPTED_RTREE, if not then the source contents are
291   left unchanged and DB_SUCCESS is returned.
292   @param[in]      type    IORequest
293   @param[in,out]  src     data read from disk, decrypt
294                           data will be copied to this page
295   @param[in]      src_len source data length
296   @param[in,out]  dst     scratch area to use for decrypt
297   @param[in]  dst_len     size of the scratch area in bytes
298   @return DB_SUCCESS or error code */
299   dberr_t decrypt(const IORequest &type, byte *src, ulint src_len, byte *dst,
300                   ulint dst_len) noexcept MY_ATTRIBUTE((warn_unused_result));
301 
302   /** Check if keyring plugin loaded. */
303   static bool check_keyring() noexcept;
304 
305   /** Get encryption type
306   @return encryption type **/
307   Type get_type() const;
308 
309   /** Set encryption type
310   @param[in]  type  encryption type **/
311   void set_type(Type type);
312 
313   /** Get encryption key
314   @return encryption key **/
315   byte *get_key() const;
316 
317   /** Set encryption key
318   @param[in]  key  encryption key **/
319   void set_key(byte *key);
320 
321   /** Get key length
322   @return  key length **/
323   ulint get_key_length() const;
324 
325   /** Set key length
326   @param[in]  klen  key length **/
327   void set_key_length(ulint klen);
328 
329   /** Get initial vector
330   @return initial vector **/
331   byte *get_initial_vector() const;
332 
333   /** Set initial vector
334   @param[in]  iv  initial_vector **/
335   void set_initial_vector(byte *iv);
336 
337   /** Get master key id
338   @return master key id **/
339   static ulint get_master_key_id();
340 
341  private:
342   /** Encrypt type */
343   Type m_type;
344 
345   /** Encrypt key */
346   byte *m_key;
347 
348   /** Encrypt key length*/
349   ulint m_klen;
350 
351   /** Encrypt initial vector */
352   byte *m_iv;
353 
354   /** Current master key id */
355   static ulint s_master_key_id;
356 
357   /** Current uuid of server instance */
358   static char s_uuid[SERVER_UUID_LEN + 1];
359 };
360 
361 #endif /* os0enc_h */
362