From: Stewart Smith Date: June 30 2008 1:31am Subject: bzr commit into mysql-6.0-backup branch (stewart:2654) WL#4271 List-Archive: http://lists.mysql.com/commits/48723 Message-Id: <20080630013158.7A1A82C61575@willster> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/stewart/mysql/stew-encrypted-backup-preview1/ 2654 stewart@stripped 2008-06-30 [patch 10/10] WL4271 Encrypted online backup: decrypt encrytped backup--- mysql-test/r/backup_encrypt_larger.result | 29 ++++++++++++ mysql-test/r/backup_encrypted_syntax_basic.result | 3 - mysql-test/t/backup_encrypt_larger.test | 21 +++++++++ mysql-test/t/backup_encrypted.test | 20 ++++++++ mysql-test/t/backup_encrypted_syntax_basic.test | 1 sql/backup/kernel.cc | 44 ++++++++++++++++++ sql/backup/stream.cc | 51 +++++++++++++++++++--- sql/backup/stream.h | 2 8 files changed, 159 insertions(+), 12 deletions(-) Index: stew-encrypted-backup/sql/backup/kernel.cc =================================================================== added: mysql-test/r/backup_encrypt_larger.result mysql-test/t/backup_encrypt_larger.test modified: mysql-test/r/backup_encrypted_syntax_basic.result mysql-test/t/backup_encrypted.test mysql-test/t/backup_encrypted_syntax_basic.test sql/backup/kernel.cc sql/backup/stream.cc sql/backup/stream.h === added file 'mysql-test/r/backup_encrypt_larger.result' --- a/mysql-test/r/backup_encrypt_larger.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/r/backup_encrypt_larger.result 2008-06-30 01:31:53 +0000 @@ -0,0 +1,29 @@ +create table t1 (a int); +insert into t1 values (1),(2),(42),(3),(4),(1); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +BACKUP DATABASE test TO 'test.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; +backup_id +1 +BACKUP DATABASE test TO 'test1.ba' WITH COMPRESSION COMPRESSION_ALGORITHM=gzip ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; +backup_id +2 +use test; +RESTORE FROM 'test.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; +backup_id +3 +RESTORE FROM 'test1.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; +backup_id +4 === modified file 'mysql-test/r/backup_encrypted_syntax_basic.result' --- a/mysql-test/r/backup_encrypted_syntax_basic.result 2008-06-30 01:31:45 +0000 +++ b/mysql-test/r/backup_encrypted_syntax_basic.result 2008-06-30 01:31:53 +0000 @@ -14,4 +14,5 @@ BACKUP DATABASE test TO 'test5.ba' ENCRY ERROR 42000: This version of MySQL doesn't yet support 'Encryption with keyfile' use test; RESTORE FROM 'test4.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; -ERROR 42000: This version of MySQL doesn't yet support 'Encrypted Restore' +backup_id +7 === added file 'mysql-test/t/backup_encrypt_larger.test' --- a/mysql-test/t/backup_encrypt_larger.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/t/backup_encrypt_larger.test 2008-06-30 01:31:53 +0000 @@ -0,0 +1,21 @@ +create table t1 (a int); +insert into t1 values (1),(2),(42),(3),(4),(1); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +BACKUP DATABASE test TO 'test.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; +BACKUP DATABASE test TO 'test1.ba' WITH COMPRESSION COMPRESSION_ALGORITHM=gzip ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; +use test; +RESTORE FROM 'test.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; +RESTORE FROM 'test1.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; === modified file 'mysql-test/t/backup_encrypted.test' --- a/mysql-test/t/backup_encrypted.test 2008-06-30 01:31:21 +0000 +++ b/mysql-test/t/backup_encrypted.test 2008-06-30 01:31:53 +0000 @@ -1,3 +1,10 @@ +--disable_warnings +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/master-data/test.ba +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/master-data/test.ba +--enable_warnings + create table t1 (a int); insert into t1 values (1),(2),(42),(3),(4),(1); insert into t1 select * from t1; @@ -10,4 +17,15 @@ insert into t1 values (1),(2),(42),(3),( insert into t1 select * from t1; insert into t1 select * from t1; insert into t1 select * from t1; - BACKUP DATABASE test TO 'test42.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128 PASSWORD='pants'; +BACKUP DATABASE test TO 'test.ba'; +BACKUP DATABASE test TO 'test2.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128 PASSWORD='pants'; + +use test; +select 'restore'; +RESTORE FROM 'test.ba'; +select 'restore enc'; +RESTORE FROM 'test2.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; + +--remove_file $MYSQLTEST_VARDIR/master-data/test.ba +--remove_file $MYSQLTEST_VARDIR/master-data/test2.ba + === modified file 'mysql-test/t/backup_encrypted_syntax_basic.test' --- a/mysql-test/t/backup_encrypted_syntax_basic.test 2008-06-30 01:31:45 +0000 +++ b/mysql-test/t/backup_encrypted_syntax_basic.test 2008-06-30 01:31:53 +0000 @@ -12,7 +12,6 @@ BACKUP DATABASE test TO 'test4.ba' ENCRY BACKUP DATABASE test TO 'test5.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128 ENCRYPTION_KEYFILE='foo.key'; use test; ---error 1235 RESTORE FROM 'test4.ba' ENCRYPTION_ALGORITHM=aes PASSWORD='pants'; --remove_file $MYSQLTEST_VARDIR/master-data/test.ba === modified file 'sql/backup/kernel.cc' --- a/sql/backup/kernel.cc 2008-06-30 01:31:45 +0000 +++ b/sql/backup/kernel.cc 2008-06-30 01:31:53 +0000 @@ -542,6 +542,7 @@ Backup_restore_ctx::prepare_for_backup(L (byte*)encryption_password_str.ptr(), encryption_password_str.length(), 1, key, iv); + cipher= new yaSSL::AES; cipher->set_encryptKey(key,iv); } @@ -643,16 +644,55 @@ Backup_restore_ctx::prepare_for_restore( backup::String encryption_keyfile_str(encryption_keyfile); backup::String encryption_password_str(encryption_password); +#ifdef HAVE_YASSL + yaSSL::BulkCipher *cipher= NULL; +#endif + if(encryption_algorithm_str.ptr() || encryption_keyfile_str.ptr() || encryption_password_str.ptr() || encryption_keysize) { - fatal_error(ER_NOT_SUPPORTED_YET, "Encrypted Restore"); +#ifndef HAVE_YASSL + fatal_error(ER_NOT_SUPPORTED_YET, "Need YaSSL to support encrypted restore"); return NULL; +#else + if(encryption_keyfile_str.ptr()) + { + fatal_error(ER_NOT_SUPPORTED_YET, "Decryption with keyfile"); + return NULL; + } + + if(strcmp(encryption_algorithm_str.ptr(),"aes")==0) + { + if(!encryption_password_str.ptr()) + { + fatal_error(ER_SYNTAX_ERROR, "Decryption requires password"); + return NULL; + } + byte key[yaSSL::AES_256_KEY_SZ]; + byte iv[yaSSL::AES_IV_SZ]; + + memset(key,0,yaSSL::AES_256_KEY_SZ); + memset(iv,0,yaSSL::AES_IV_SZ); + + EVP_BytesToKey("AES-128-CBC", "MD5", NULL, + (byte*)encryption_password_str.ptr(), + encryption_password_str.length(), + 1, key, iv); + + cipher= new yaSSL::AES; + cipher->set_decryptKey(key,iv); + } + else + { + fatal_error(ER_NOT_SUPPORTED_YET, encryption_algorithm_str.ptr()); + return NULL; + } +#endif } - Input_stream *s= new Input_stream(*this, path); + Input_stream *s= new Input_stream(*this, path, cipher); if (!s) { === modified file 'sql/backup/stream.cc' --- a/sql/backup/stream.cc 2008-06-30 01:31:21 +0000 +++ b/sql/backup/stream.cc 2008-06-30 01:31:53 +0000 @@ -145,7 +145,14 @@ extern "C" int stream_read(void *instanc { if (!zstream->avail_in) { - zstream->avail_in= my_read(fd, s->zbuf, ZBUF_SIZE, MYF(0)); +#ifdef HAVE_YASSL + if (s->m_cipher) + zstream->avail_in= my_crypt_read(&(s->m_cfd), s->zbuf, ZBUF_SIZE); + else +#endif + { + zstream->avail_in= my_read(fd, s->zbuf, ZBUF_SIZE, MYF(0)); + } if (zstream->avail_in == (size_t) -1) DBUG_RETURN(BSTREAM_ERROR); else if (!zstream->avail_in) @@ -166,7 +173,12 @@ extern "C" int stream_read(void *instanc else #endif { - howmuch= my_read(fd, buf->begin, howmuch, MYF(0)); +#ifdef HAVE_YASSL + if (s->m_cipher) + howmuch= my_crypt_read(&(s->m_cfd), buf->begin, howmuch); + else +#endif + howmuch= my_read(fd, buf->begin, howmuch, MYF(0)); } /* @@ -200,6 +212,7 @@ Stream::Stream(Logger &log, const ::Stri bzero(&data_buf, sizeof(data_buf)); block_size= 0; state= CLOSED; + m_cipher= NULL; } bool Stream::open() @@ -298,6 +311,13 @@ int enc_filter(void* obj,char* obuf,char return 0; } +int dec_filter(void* obj,char* obuf,char* ibuf,size_t sz) +{ + yaSSL::BulkCipher *c= (yaSSL::BulkCipher*)obj; + c->decrypt((yaSSL::byte*)obuf, (yaSSL::byte*)ibuf, sz); + return 0; +} + /** Open and initialize backup stream for writing. @@ -438,10 +458,11 @@ bool Output_stream::rewind() } -Input_stream::Input_stream(Logger &log, const ::String &name) +Input_stream::Input_stream(Logger &log, const ::String &name, yaSSL::BulkCipher *cipher) :Stream(log, name, O_RDONLY) { stream.read= stream_read; + m_cipher= cipher; } /** @@ -513,12 +534,30 @@ bool Input_stream::open() bool ret= Stream::open(); +#ifdef HAVE_YASSL + int r= 0; + if(m_cipher) + r= my_crypt_fdopen(&m_cfd, m_fd, O_RDONLY, &dec_filter, (void*)m_cipher, + m_cipher->get_blockSize()); +#endif + if (!ret) return FALSE; - if (my_read(m_fd, m_header_buf, sizeof(m_header_buf), - MY_NABP /* error if not all bytes read */ )) - return FALSE; +#ifdef HAVE_YASSL + if (m_cipher) + { + if (sizeof(m_header_buf)!= my_crypt_read(&m_cfd, m_header_buf, + sizeof(m_header_buf))) + return FALSE; + } + else +#endif + { + if (my_read(m_fd, m_header_buf, sizeof(m_header_buf), + MY_NABP /* error if not all bytes read */ )) + return FALSE; + } #ifdef HAVE_COMPRESS if (!memcmp(m_header_buf, "\x1f\x8b\x08", 3)) === modified file 'sql/backup/stream.h' --- a/sql/backup/stream.h 2008-06-30 01:31:21 +0000 +++ b/sql/backup/stream.h 2008-06-30 01:31:53 +0000 @@ -136,7 +136,7 @@ class Input_stream: { public: - Input_stream(Logger&, const ::String &name); + Input_stream(Logger&, const ::String &name, yaSSL::BulkCipher *cipher); bool open(); void close();