From: Date: June 30 2008 3:22am Subject: [patch 10/10] WL4271 Encrypted online backup: decrypt encrytped backup List-Archive: http://lists.mysql.com/internals/35769 Message-Id: <20080630012612.934389753@flamingspork.com> --- 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 =================================================================== --- stew-encrypted-backup.orig/sql/backup/kernel.cc 2008-06-26 15:55:32.344836233 +1000 +++ stew-encrypted-backup/sql/backup/kernel.cc 2008-06-26 15:55:32.384844774 +1000 @@ -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) { Index: stew-encrypted-backup/sql/backup/stream.cc =================================================================== --- stew-encrypted-backup.orig/sql/backup/stream.cc 2008-06-26 15:55:32.264835495 +1000 +++ stew-encrypted-backup/sql/backup/stream.cc 2008-06-26 15:55:32.396864677 +1000 @@ -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)) Index: stew-encrypted-backup/sql/backup/stream.h =================================================================== --- stew-encrypted-backup.orig/sql/backup/stream.h 2008-06-26 15:55:32.264835495 +1000 +++ stew-encrypted-backup/sql/backup/stream.h 2008-06-26 15:55:32.396864677 +1000 @@ -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(); Index: stew-encrypted-backup/mysql-test/r/backup_encrypted_syntax_basic.result =================================================================== --- stew-encrypted-backup.orig/mysql-test/r/backup_encrypted_syntax_basic.result 2008-06-26 15:55:32.348835628 +1000 +++ stew-encrypted-backup/mysql-test/r/backup_encrypted_syntax_basic.result 2008-06-26 15:55:32.400847171 +1000 @@ -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 Index: stew-encrypted-backup/mysql-test/t/backup_encrypted_syntax_basic.test =================================================================== --- stew-encrypted-backup.orig/mysql-test/t/backup_encrypted_syntax_basic.test 2008-06-26 15:55:32.348835628 +1000 +++ stew-encrypted-backup/mysql-test/t/backup_encrypted_syntax_basic.test 2008-06-26 15:55:32.408843585 +1000 @@ -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 Index: stew-encrypted-backup/mysql-test/t/backup_encrypted.test =================================================================== --- stew-encrypted-backup.orig/mysql-test/t/backup_encrypted.test 2008-06-26 15:55:32.268836007 +1000 +++ stew-encrypted-backup/mysql-test/t/backup_encrypted.test 2008-06-26 15:55:32.408843585 +1000 @@ -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 + Index: stew-encrypted-backup/mysql-test/t/backup_encrypt_larger.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ stew-encrypted-backup/mysql-test/t/backup_encrypt_larger.test 2008-06-26 15:55:32.416836577 +1000 @@ -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'; Index: stew-encrypted-backup/mysql-test/r/backup_encrypt_larger.result =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ stew-encrypted-backup/mysql-test/r/backup_encrypt_larger.result 2008-06-26 16:28:42.347832957 +1000 @@ -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 -- Stewart Smith