summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2018-12-28 19:18:56 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2018-12-28 19:18:56 +0530
commitce9dda37a5cc3be765208e091f83450b19a0921d (patch)
tree3dad07e656310d7f32ba6819e8a176f77ac7f09d
parentdc90234bda3e2074179a3e54c09a7c9694e69965 (diff)
downloadmariadb-git-bb-10.4-mdev-12026.tar.gz
MDEV-12026 Support encrypted SPATIAL INDEXbb-10.4-mdev-12026
- For encrypted spatial index, store ssn in space id location of PAGE_BTR_SEG_TOP while encrypting the page. - While decrypting, insert the space id of PAGE_BTR_SEG_TOP for encrypted spatial index.
-rw-r--r--mysql-test/suite/encryption/r/innodb-spatial-index.result20
-rw-r--r--mysql-test/suite/encryption/t/innodb-spatial-index.test19
-rw-r--r--storage/innobase/fil/fil0crypt.cc150
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
-rw-r--r--storage/innobase/include/fil0crypt.h5
-rw-r--r--storage/innobase/include/fil0fil.h2
-rw-r--r--storage/innobase/include/fil0fil.ic3
7 files changed, 155 insertions, 46 deletions
diff --git a/mysql-test/suite/encryption/r/innodb-spatial-index.result b/mysql-test/suite/encryption/r/innodb-spatial-index.result
index 7cc6d86e48d..cafc20448ed 100644
--- a/mysql-test/suite/encryption/r/innodb-spatial-index.result
+++ b/mysql-test/suite/encryption/r/innodb-spatial-index.result
@@ -1,22 +1,25 @@
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT,
c VARCHAR(256), coordinate POINT NOT NULL, SPATIAL index(coordinate)) ENGINE=INNODB
ENCRYPTED=YES;
-ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options")
+INSERT INTO t1(c, coordinate) values('mysql', ST_GeomFromText('POINT(903994614 180726515)'));
+INSERT INTO t1(c, coordinate) values('mariadb', ST_GeomFromText('POINT(903994614 180726515)'));
+DROP TABLE t1;
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT,
c VARCHAR(256), coordinate POINT NOT NULL, SPATIAL index(coordinate)) ENGINE=INNODB;
ALTER TABLE t1 ENCRYPTED=YES;
-ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTED'
DROP TABLE t1;
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT,
c VARCHAR(256), coordinate POINT NOT NULL) ENCRYPTED=YES ENGINE=INNODB;
ALTER TABLE t1 ADD SPATIAL INDEX b(coordinate), ALGORITHM=COPY;
-ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options")
-ALTER TABLE t1 ADD SPATIAL INDEX b(coordinate), FORCE, ALGORITHM=INPLACE;
-ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTED'
+ALTER TABLE t1 ADD SPATIAL INDEX b1(coordinate), FORCE, ALGORITHM=INPLACE;
+Warnings:
+Note 1831 Duplicate index `b1`. This is deprecated and will be disallowed in a future release
ALTER TABLE t1 ADD SPATIAL INDEX(coordinate);
-ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTED'
-CREATE SPATIAL INDEX b on t1(coordinate);
-ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTED'
+Warnings:
+Note 1831 Duplicate index `coordinate`. This is deprecated and will be disallowed in a future release
+CREATE SPATIAL INDEX b2 on t1(coordinate);
+Warnings:
+Note 1831 Duplicate index `b2`. This is deprecated and will be disallowed in a future release
DROP TABLE t1;
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT,
c VARCHAR(256), coordinate POINT NOT NULL) ENCRYPTED=DEFAULT ENGINE=INNODB;
@@ -44,4 +47,5 @@ test/t1
test/t2
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
NAME
+INSERT INTO t1 values(2, 'secret1', ST_GeomFromText('POINT(903994614 180726515)'));
DROP TABLE t1, t2;
diff --git a/mysql-test/suite/encryption/t/innodb-spatial-index.test b/mysql-test/suite/encryption/t/innodb-spatial-index.test
index 28b35379a6b..44d547519c6 100644
--- a/mysql-test/suite/encryption/t/innodb-spatial-index.test
+++ b/mysql-test/suite/encryption/t/innodb-spatial-index.test
@@ -5,22 +5,20 @@
# MDEV-11974: MariaDB 10.2 encryption does not support spatial indexes
#
-#
-# (1) Do not allow creating table with ENCRYPTED=YES
-#
-#
--replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/
---error ER_CANT_CREATE_TABLE
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT,
c VARCHAR(256), coordinate POINT NOT NULL, SPATIAL index(coordinate)) ENGINE=INNODB
ENCRYPTED=YES;
+INSERT INTO t1(c, coordinate) values('mysql', ST_GeomFromText('POINT(903994614 180726515)'));
+--source include/restart_mysqld.inc
+INSERT INTO t1(c, coordinate) values('mariadb', ST_GeomFromText('POINT(903994614 180726515)'));
+DROP TABLE t1;
#
# (2) Alter table
#
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT,
c VARCHAR(256), coordinate POINT NOT NULL, SPATIAL index(coordinate)) ENGINE=INNODB;
---error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ENCRYPTED=YES;
DROP TABLE t1;
@@ -32,14 +30,10 @@ c VARCHAR(256), coordinate POINT NOT NULL) ENCRYPTED=YES ENGINE=INNODB;
# FIXME: MDEV-13851 Encrypted table refuses some form of ALGORITHM=COPY,
# but allows rebuild by FORCE
--replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/
---error ER_CANT_CREATE_TABLE
ALTER TABLE t1 ADD SPATIAL INDEX b(coordinate), ALGORITHM=COPY;
---error ER_ILLEGAL_HA_CREATE_OPTION
-ALTER TABLE t1 ADD SPATIAL INDEX b(coordinate), FORCE, ALGORITHM=INPLACE;
---error ER_ILLEGAL_HA_CREATE_OPTION
+ALTER TABLE t1 ADD SPATIAL INDEX b1(coordinate), FORCE, ALGORITHM=INPLACE;
ALTER TABLE t1 ADD SPATIAL INDEX(coordinate);
---error ER_ILLEGAL_HA_CREATE_OPTION
-CREATE SPATIAL INDEX b on t1(coordinate);
+CREATE SPATIAL INDEX b2 on t1(coordinate);
DROP TABLE t1;
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT,
@@ -74,4 +68,5 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_
--sorted_result
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
+INSERT INTO t1 values(2, 'secret1', ST_GeomFromText('POINT(903994614 180726515)'));
DROP TABLE t1, t2;
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index a46d185051d..660b8a249e5 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -564,6 +564,8 @@ fil_encrypt_buf(
ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
ibool page_compressed = (orig_page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
uint header_len = FIL_PAGE_DATA;
+ bool rtree_page = (orig_page_type == FIL_PAGE_RTREE);
+ node_seq_t ssn_id;
if (page_compressed) {
header_len += (FIL_PAGE_COMPRESSED_SIZE + FIL_PAGE_COMPRESSION_METHOD_SIZE);
@@ -572,6 +574,12 @@ fil_encrypt_buf(
/* FIL page header is not encrypted */
memcpy(dst_frame, src_frame, header_len);
+ if (orig_page_type == FIL_PAGE_RTREE) {
+ ssn_id = static_cast<node_seq_t>(
+ mach_read_from_8(src_frame + FIL_RTREE_SPLIT_SEQ_NUM));
+ mach_write_to_2(dst_frame + FIL_PAGE_TYPE, FIL_PAGE_ENCRYPTED_RTREE);
+ }
+
/* Store key version */
mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, key_version);
@@ -586,11 +594,50 @@ fil_encrypt_buf(
srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA);
}
- int rc = encryption_scheme_encrypt(src, srclen, dst, &dstlen,
- crypt_data, key_version,
- (uint32)space, (uint32)offset, lsn);
- ut_a(rc == MY_AES_OK);
- ut_a(dstlen == srclen);
+ if (rtree_page) {
+ ulint orig_src_len = srclen;
+ byte ssn_char[4];
+
+ srclen = PAGE_BTR_SEG_TOP;
+ int rc = encryption_scheme_encrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ (uint32) space, (uint32) offset,
+ lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_a(dstlen == srclen);
+
+ /** Write the ssn number to PAGE_BTR_SEG_TOP location for
+ encrypted page. */
+ dst += srclen;
+
+ mach_write_to_4(ssn_char, ssn_id);
+
+ rc = encryption_scheme_encrypt((unsigned char*) ssn_char, 4, dst,
+ &dstlen, crypt_data, key_version,
+ (uint32) space, (uint32) offset,
+ lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_a(dstlen == 4);
+
+ /** Encrypt the remaining page from PAGE_BTR_SEG_TOP. */
+ src += srclen + 4;
+ dst += 4;
+ srclen = orig_src_len - (srclen + 4);
+
+ rc = encryption_scheme_encrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ (uint32) space, (uint32) offset,
+ lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_a(dstlen == srclen);
+ } else {
+ int rc = encryption_scheme_encrypt(
+ src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ (uint32)space, (uint32)offset, lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_a(dstlen == srclen);
+ }
/* For compressed tables we do not store the FIL header because
the whole page is not stored to the disk. In compressed tables only
@@ -643,7 +690,6 @@ fil_space_encrypt(
switch (mach_read_from_2(src_frame+FIL_PAGE_TYPE)) {
case FIL_PAGE_TYPE_FSP_HDR:
case FIL_PAGE_TYPE_XDES:
- case FIL_PAGE_RTREE:
/* File space header, extent descriptor or spatial index
are not encrypted. */
return src_frame;
@@ -667,6 +713,9 @@ fil_space_encrypt(
bool page_compressed_encrypted = (mach_read_from_2(tmp+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
byte uncomp_mem[UNIV_PAGE_SIZE_MAX];
byte tmp_mem[UNIV_PAGE_SIZE_MAX];
+ bool rtree_encrypted = (mach_read_from_2(tmp + FIL_PAGE_TYPE)
+ == FIL_PAGE_ENCRYPTED_RTREE);
+ node_seq_t ssn_value = 0;
if (page_compressed_encrypted) {
memcpy(uncomp_mem, src, srv_page_size);
@@ -680,7 +729,8 @@ fil_space_encrypt(
ut_ad(!buf_page_is_corrupted(true, src, page_size, space));
ut_ad(fil_space_decrypt(crypt_data, tmp_mem, page_size, tmp,
- &err));
+ &err, rtree_encrypted ? &ssn_value : NULL));
+
ut_ad(err == DB_SUCCESS);
/* Need to decompress the page if it was also compressed */
@@ -691,8 +741,14 @@ fil_space_encrypt(
ut_ad(unzipped2);
}
- memcpy(tmp_mem + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
- src + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 8);
+ if (rtree_encrypted) {
+ mach_write_to_4(tmp_mem + FIL_RTREE_SPLIT_SEQ_NUM, 0);
+ mach_write_to_4(tmp_mem + FIL_RTREE_SPLIT_SEQ_NUM + 4,
+ ssn_value);
+ } else {
+ memcpy(tmp_mem + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ src + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 8);
+ }
ut_ad(!memcmp(src, tmp_mem, page_size.physical()));
}
#endif /* UNIV_DEBUG */
@@ -706,6 +762,8 @@ fil_space_encrypt(
@param[in] page_size Page size
@param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
+@param[out] ssn_id split sequence number for spatial index
+ or NULL for other indexes
@return true if page decrypted, false if not.*/
UNIV_INTERN
bool
@@ -714,7 +772,8 @@ fil_space_decrypt(
byte* tmp_frame,
const page_size_t& page_size,
byte* src_frame,
- dberr_t* err)
+ dberr_t* err,
+ ib_uint32_t* ssn_id)
{
ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
uint key_version = mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
@@ -752,22 +811,69 @@ fil_space_decrypt(
srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA);
}
- int rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen,
- crypt_data, key_version,
- space, offset, lsn);
+ if (page_type == FIL_PAGE_ENCRYPTED_RTREE) {
+ int orig_src_len = srclen;
+ srclen = PAGE_BTR_SEG_TOP;
+ int rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ space, offset, lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_ad(dstlen == srclen);
+
+ src += srclen;
+ dst += srclen;
+ rc = encryption_scheme_decrypt(src, 4, dst, &dstlen,
+ crypt_data, key_version, space,
+ offset, lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_a(dstlen == 4);
+
+ src += 4;
+ dst += 4;
+ srclen = orig_src_len - (srclen + 4);
+ rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ space, offset, lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_ad(dstlen == srclen);
- if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
+ } else {
+ int rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ space, offset, lsn);
- if (rc == -1) {
- *err = DB_DECRYPTION_FAILED;
- return false;
+ if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
+
+ if (rc == -1) {
+ *err = DB_DECRYPTION_FAILED;
+ return false;
+ }
+
+ ib::fatal() << "Unable to decrypt data-block "
+ << " src: " << src << "srclen: "
+ << srclen << " buf: " << dst << "buflen: "
+ << dstlen << " return-code: " << rc
+ << " Can't continue!";
}
- ib::fatal() << "Unable to decrypt data-block "
- << " src: " << src << "srclen: "
- << srclen << " buf: " << dst << "buflen: "
- << dstlen << " return-code: " << rc
- << " Can't continue!";
+ }
+
+ if (page_type == FIL_PAGE_ENCRYPTED_RTREE) {
+ ib_uint32_t ssn_value = mach_read_from_4(
+ tmp_frame + PAGE_HEADER + PAGE_BTR_SEG_TOP);
+
+ if (ssn_id != NULL) {
+ *ssn_id = ssn_value;
+ }
+
+ memcpy(tmp_frame + PAGE_HEADER + PAGE_BTR_SEG_TOP,
+ tmp_frame + PAGE_HEADER + PAGE_BTR_SEG_LEAF, 4);
+
+ mach_write_to_2(tmp_frame + FIL_PAGE_TYPE, FIL_PAGE_RTREE);
+
+ mach_write_to_4(tmp_frame + FIL_RTREE_SPLIT_SEQ_NUM, 0);
+
+ mach_write_to_4(tmp_frame + FIL_RTREE_SPLIT_SEQ_NUM + 4, ssn_value);
}
/* For compressed tables we do not store the FIL header because
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c4fafe142e5..171cf1f0800 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -11501,7 +11501,7 @@ create_table_info_t::check_table_options()
encryption */
for(ulint i = 0; i < m_form->s->keys; i++) {
const KEY* key = m_form->key_info + i;
- if (key->flags & HA_SPATIAL && should_encrypt) {
+ if (key->flags & HA_SPATIAL && should_encrypt && options->page_compressed) {
push_warning_printf(m_thd, Sql_condition::WARN_LEVEL_WARN,
HA_ERR_UNSUPPORTED,
"InnoDB: ENCRYPTED=ON not supported for table because "
diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h
index e520f189d63..f662659494e 100644
--- a/storage/innobase/include/fil0crypt.h
+++ b/storage/innobase/include/fil0crypt.h
@@ -350,6 +350,8 @@ Decrypt a page.
@param[in] page_size Page size
@param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or error
+@param[out] ssn_id split sequence number for spatial
+ index pages.
@return true if page decrypted, false if not.*/
UNIV_INTERN
bool
@@ -358,7 +360,8 @@ fil_space_decrypt(
byte* tmp_frame,
const page_size_t& page_size,
byte* src_frame,
- dberr_t* err);
+ dberr_t* err,
+ ib_uint32_t* ssn_id = NULL);
/******************************************************************
Decrypt a page
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 53df19d6ded..e193a98e550 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -491,7 +491,7 @@ struct fil_addr_t {
//#define FIL_PAGE_COMPRESSED 14
//#define FIL_PAGE_ENCRYPTED 15
//#define FIL_PAGE_COMPRESSED_AND_ENCRYPTED 16
-//#define FIL_PAGE_ENCRYPTED_RTREE 17
+#define FIL_PAGE_ENCRYPTED_RTREE 17
/** Clustered index root page after instant ADD COLUMN */
#define FIL_PAGE_TYPE_INSTANT 18
diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic
index 2a7d06e243f..7444ef36f9c 100644
--- a/storage/innobase/include/fil0fil.ic
+++ b/storage/innobase/include/fil0fil.ic
@@ -104,7 +104,8 @@ fil_page_type_validate(
page_type == FIL_PAGE_TYPE_BLOB ||
page_type == FIL_PAGE_TYPE_ZBLOB ||
page_type == FIL_PAGE_TYPE_ZBLOB2 ||
- page_type == FIL_PAGE_TYPE_UNKNOWN))) {
+ page_type == FIL_PAGE_TYPE_UNKNOWN ||
+ page_type == FIL_PAGE_ENCRYPTED_RTREE))) {
ulint space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
ulint offset = mach_read_from_4(page + FIL_PAGE_OFFSET);