mariadb/storage/xtradb/include/fil0crypt.h
Jan Lindström f8cacd03a7 MDEV-8143: InnoDB: Database page corruption on disk or a failed file read
Analysis: Problem was that we did create crypt data for encrypted table but
this new crypt data was not written to page 0. Instead a default crypt data
was written to page 0 at table creation.

Fixed by explicitly writing new crypt data to page 0 after successfull
table creation.
2015-05-14 11:32:24 +03:00

390 lines
13 KiB
C

/*****************************************************************************
Copyright (c) 2015, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/**************************************************//**
@file include/fil0crypt.h
The low-level file system encryption support functions
Created 04/01/2015 Jan Lindström
*******************************************************/
#ifndef fil0crypt_h
#define fil0crypt_h
/* This key will be used if nothing else is given */
#define FIL_DEFAULT_ENCRYPTION_KEY 1
/** Enum values for encryption table option */
typedef enum {
FIL_SPACE_ENCRYPTION_DEFAULT = 0, /* Tablespace encrypted if
srv_encrypt_tables = ON */
FIL_SPACE_ENCRYPTION_ON = 1, /* Tablespace is encrypted always */
FIL_SPACE_ENCRYPTION_OFF = 2 /* Tablespace is not encrypted */
} fil_encryption_t;
/**
* CRYPT_SCHEME_UNENCRYPTED
*
* Used as intermediate state when convering a space from unencrypted
* to encrypted
*/
/**
* CRYPT_SCHEME_1
*
* xxx is AES_CTR or AES_CBC (or another block cypher with the same key and iv lengths)
* L = AES_ECB(KEY, IV)
* CRYPT(PAGE) = xxx(KEY=L, IV=C, PAGE)
*/
#define CRYPT_SCHEME_1 1
#define CRYPT_SCHEME_1_IV_LEN 16
#define CRYPT_SCHEME_UNENCRYPTED 0
/* Cached L or key for given key_version */
struct key_struct
{
uint key_version; /*!< Version of the key */
uint key_length; /*!< Key length */
unsigned char key[MY_AES_MAX_KEY_LENGTH]; /*!< Cached key
(that is L in CRYPT_SCHEME_1) */
};
struct fil_space_rotate_state_t
{
time_t start_time; // time when rotation started
ulint active_threads; // active threads in space
ulint next_offset; // next "free" offset
ulint max_offset; // max offset needing to be rotated
uint min_key_version_found; // min key version found but not rotated
lsn_t end_lsn; // max lsn created when rotating this space
bool starting; // initial write of IV
bool flushing; // space is being flushed at end of rotate
struct {
bool is_active; // is scrubbing active in this space
time_t last_scrub_completed; // when was last scrub completed
} scrubbing;
};
struct fil_space_crypt_struct
{
ulint type; // CRYPT_SCHEME
uint keyserver_requests; // no of key requests to key server
uint key_count; // No of initalized key-structs
uint key_id; // Key id for this space
key_struct keys[3]; // cached L = AES_ECB(KEY, IV)
uint min_key_version; // min key version for this space
ulint page0_offset; // byte offset on page 0 for crypt data
fil_encryption_t encryption; // Encryption setup
ib_mutex_t mutex; // mutex protecting following variables
bool closing; // is tablespace being closed
fil_space_rotate_state_t rotate_state;
uint iv_length; // length of IV
byte iv[1]; // IV-data
};
/* structure containing encryption specification */
typedef struct fil_space_crypt_struct fil_space_crypt_t;
/*********************************************************************
Init global resources needed for tablespace encryption/decryption */
UNIV_INTERN
void
fil_space_crypt_init();
/*********************************************************************
Cleanup global resources needed for tablespace encryption/decryption */
UNIV_INTERN
void
fil_space_crypt_cleanup();
/*********************************************************************
Create crypt data, i.e data that is used for a single tablespace */
UNIV_INTERN
fil_space_crypt_t *
fil_space_create_crypt_data(
/*========================*/
fil_encryption_t encrypt_mode, /*!< in: encryption mode */
uint key_id); /*!< in: encryption key id */
/*********************************************************************
Destroy crypt data */
UNIV_INTERN
void
fil_space_destroy_crypt_data(
/*=========================*/
fil_space_crypt_t **crypt_data); /*!< in/out: crypt data */
/*********************************************************************
Get crypt data for a space*/
UNIV_INTERN
fil_space_crypt_t *
fil_space_get_crypt_data(
/*======================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
Set crypt data for a space*/
UNIV_INTERN
void
fil_space_set_crypt_data(
/*======================*/
ulint space, /*!< in: tablespace id */
fil_space_crypt_t* crypt_data); /*!< in: crypt data to set */
/*********************************************************************
Compare crypt data*/
UNIV_INTERN
int
fil_space_crypt_compare(
/*======================*/
const fil_space_crypt_t* crypt_data1, /*!< in: crypt data */
const fil_space_crypt_t* crypt_data2); /*!< in: crypt data */
/*********************************************************************
Read crypt data from buffer page */
UNIV_INTERN
fil_space_crypt_t *
fil_space_read_crypt_data(
/*======================*/
ulint space, /*!< in: tablespace id */
const byte* page, /*!< in: buffer page */
ulint offset); /*!< in: offset where crypt data is stored */
/*********************************************************************
Write crypt data to buffer page */
UNIV_INTERN
void
fil_space_write_crypt_data(
/*=======================*/
ulint space, /*!< in: tablespace id */
byte* page, /*!< in: buffer page */
ulint offset, /*!< in: offset where to store data */
ulint maxsize, /*!< in: max space available to store crypt data in */
mtr_t * mtr); /*!< in: mini-transaction */
/*********************************************************************
Clear crypt data from page 0 (used for import tablespace) */
UNIV_INTERN
void
fil_space_clear_crypt_data(
/*======================*/
byte* page, /*!< in: buffer page */
ulint offset); /*!< in: offset where crypt data is stored */
/*********************************************************************
Parse crypt data log record */
UNIV_INTERN
byte*
fil_parse_write_crypt_data(
/*=======================*/
byte* ptr, /*!< in: start of log record */
byte* end_ptr, /*!< in: end of log record */
buf_block_t*); /*!< in: buffer page to apply record to */
/*********************************************************************
Check if extra buffer shall be allocated for decrypting after read */
UNIV_INTERN
bool
fil_space_check_encryption_read(
/*==============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
Check if page shall be encrypted before write */
UNIV_INTERN
bool
fil_space_check_encryption_write(
/*==============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
Encrypt buffer page */
UNIV_INTERN
void
fil_space_encrypt(
/*===============*/
ulint space, /*!< in: tablespace id */
ulint offset, /*!< in: page no */
lsn_t lsn, /*!< in: page lsn */
const byte* src_frame,/*!< in: page frame */
ulint size, /*!< in: size of data to encrypt */
byte* dst_frame); /*!< in: where to encrypt to */
/*********************************************************************
Decrypt buffer page */
UNIV_INTERN
void
fil_space_decrypt(
/*===============*/
ulint space, /*!< in: tablespace id */
const byte* src_frame,/*!< in: page frame */
ulint page_size, /*!< in: size of data to encrypt */
byte* dst_frame); /*!< in: where to decrypt to */
/*********************************************************************
Decrypt buffer page
@return true if page was encrypted */
UNIV_INTERN
bool
fil_space_decrypt(
/*===============*/
fil_space_crypt_t* crypt_data, /*!< in: crypt data */
const byte* src_frame,/*!< in: page frame */
ulint page_size, /*!< in: page size */
byte* dst_frame); /*!< in: where to decrypt to */
/*********************************************************************
fil_space_verify_crypt_checksum
NOTE: currently this function can only be run in single threaded mode
as it modifies srv_checksum_algorithm (temporarily)
@return true if page is encrypted AND OK, false otherwise */
UNIV_INTERN
bool
fil_space_verify_crypt_checksum(
/*===============*/
const byte* src_frame,/*!< in: page frame */
ulint zip_size); /*!< in: size of data to encrypt */
/*********************************************************************
Init threads for key rotation */
UNIV_INTERN
void
fil_crypt_threads_init();
/*********************************************************************
Set thread count (e.g start or stops threads) used for key rotation */
UNIV_INTERN
void
fil_crypt_set_thread_cnt(
/*=====================*/
uint new_cnt); /*!< in: requested #threads */
/*********************************************************************
End threads for key rotation */
UNIV_INTERN
void
fil_crypt_threads_end();
/*********************************************************************
Cleanup resources for threads for key rotation */
UNIV_INTERN
void
fil_crypt_threads_cleanup();
/*********************************************************************
Set rotate key age */
UNIV_INTERN
void
fil_crypt_set_rotate_key_age(
/*=====================*/
uint rotate_age); /*!< in: requested rotate age */
/*********************************************************************
Set rotation threads iops */
UNIV_INTERN
void
fil_crypt_set_rotation_iops(
/*=====================*/
uint iops); /*!< in: requested iops */
/*********************************************************************
Mark a space as closing */
UNIV_INTERN
void
fil_space_crypt_mark_space_closing(
/*===============*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
Wait for crypt threads to stop accessing space */
UNIV_INTERN
void
fil_space_crypt_close_tablespace(
/*===============*/
ulint space); /*!< in: tablespace id */
/** Struct for retreiving info about encryption */
struct fil_space_crypt_status_t {
ulint space; /*!< tablespace id */
ulint scheme; /*!< encryption scheme */
uint min_key_version; /*!< min key version */
uint current_key_version;/*!< current key version */
uint keyserver_requests;/*!< no of key requests to key server */
bool rotating; /*!< is key rotation ongoing */
bool flushing; /*!< is flush at end of rotation ongoing */
ulint rotate_next_page_number; /*!< next page if key rotating */
ulint rotate_max_page_number; /*!< max page if key rotating */
};
/*********************************************************************
Get crypt status for a space
@return 0 if crypt data found */
UNIV_INTERN
int
fil_space_crypt_get_status(
/*==================*/
ulint id, /*!< in: space id */
struct fil_space_crypt_status_t * status); /*!< out: status */
/** Struct for retreiving statistics about encryption key rotation */
struct fil_crypt_stat_t {
ulint pages_read_from_cache;
ulint pages_read_from_disk;
ulint pages_modified;
ulint pages_flushed;
ulint estimated_iops;
};
/*********************************************************************
Get crypt rotation statistics */
UNIV_INTERN
void
fil_crypt_total_stat(
/*==================*/
fil_crypt_stat_t* stat); /*!< out: crypt stat */
/** Struct for retreiving info about scrubbing */
struct fil_space_scrub_status_t {
ulint space; /*!< tablespace id */
bool compressed; /*!< is space compressed */
time_t last_scrub_completed; /*!< when was last scrub completed */
bool scrubbing; /*!< is scrubbing ongoing */
time_t current_scrub_started; /*!< when started current scrubbing */
ulint current_scrub_active_threads; /*!< current scrub active threads */
ulint current_scrub_page_number; /*!< current scrub page no */
ulint current_scrub_max_page_number; /*!< current scrub max page no */
};
/*********************************************************************
Get scrub status for a space
@return 0 if no scrub info found */
UNIV_INTERN
int
fil_space_get_scrub_status(
/*==================*/
ulint id, /*!< in: space id */
struct fil_space_scrub_status_t * status); /*!< out: status */
#ifndef UNIV_NONINL
#include "fil0crypt.ic"
#endif
#endif /* fil0crypt_h */