From: Date: June 30 2008 3:22am Subject: [patch 07/10] WL4271 Encrytped backup: implement basic AES Encyrption List-Archive: http://lists.mysql.com/internals/35767 Message-Id: <20080630012612.311436075@flamingspork.com> --- mysql-test/r/backup_encrypted.result | 15 ++++ mysql-test/t/backup_encrypted.test | 13 ++++ mysql-test/t/backup_encrypted_syntax_basic.test | 5 - sql/Makefile.am | 6 - sql/backup/Makefile.am | 5 + sql/backup/kernel.cc | 44 +++++++++++++- sql/backup/stream.cc | 73 ++++++++++++++++++++---- sql/backup/stream.h | 12 +++ 8 files changed, 151 insertions(+), 22 deletions(-) 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 02:59:29.002616740 +1000 +++ stew-encrypted-backup/mysql-test/t/backup_encrypted_syntax_basic.test 2008-06-26 13:42:15.792049536 +1000 @@ -3,11 +3,10 @@ BACKUP DATABASE test TO 'test.ba'; --error 1235 BACKUP DATABASE test TO 'test1.ba' ENCRYPTION_ALGORITHM=foo; ---error 1235 +--error 1149 BACKUP DATABASE test TO 'test2.ba' ENCRYPTION_ALGORITHM=aes; ---error 1235 +--error 1149 BACKUP DATABASE test TO 'test3.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128; ---error 1235 BACKUP DATABASE test TO 'test4.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128 PASSWORD='pants'; --error 1235 BACKUP DATABASE test TO 'test5.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128 ENCRYPTION_KEYFILE='foo.key'; Index: stew-encrypted-backup/sql/backup/Makefile.am =================================================================== --- stew-encrypted-backup.orig/sql/backup/Makefile.am 2008-06-26 02:33:16.975621412 +1000 +++ stew-encrypted-backup/sql/backup/Makefile.am 2008-06-26 03:09:27.899623071 +1000 @@ -24,7 +24,10 @@ INCLUDES = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/sql \ - -I$(top_srcdir)/regex + -I$(top_srcdir)/regex \ + -I$(top_srcdir)/extra/yassl/include \ + -I$(top_srcdir)/extra/yassl/taocrypt/include + libbackup_la_SOURCES = \ stream.cc \ Index: stew-encrypted-backup/sql/backup/kernel.cc =================================================================== --- stew-encrypted-backup.orig/sql/backup/kernel.cc 2008-06-26 03:03:29.670639990 +1000 +++ stew-encrypted-backup/sql/backup/kernel.cc 2008-06-26 13:42:13.123048043 +1000 @@ -64,6 +64,11 @@ #include "../mysql_priv.h" #include "../si_objects.h" +#ifdef HAVE_YASSL +#include +#include +#endif + #include "backup_kernel.h" #include "backup_info.h" #include "restore_info.h" @@ -497,6 +502,10 @@ Backup_restore_ctx::prepare_for_backup(L 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() @@ -506,8 +515,37 @@ Backup_restore_ctx::prepare_for_backup(L fatal_error(ER_NOT_SUPPORTED_YET, "Need YaSSL to support encrypted backup"); return NULL; #else - fatal_error(ER_NOT_SUPPORTED_YET, "Encrypted backup not yet implemented"); - return NULL; + if(encryption_keyfile_str.ptr()) + { + fatal_error(ER_NOT_SUPPORTED_YET, "Encryption with keyfile"); + return NULL; + } + + if(strcmp(encryption_algorithm_str.ptr(),"aes")==0) + { + if(!encryption_password_str.ptr()) + { + fatal_error(ER_SYNTAX_ERROR, "Encryption 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_encryptKey(key,iv); + } + else + { + fatal_error(ER_NOT_SUPPORTED_YET, encryption_algorithm_str.ptr()); + return NULL; + } #endif } @@ -515,7 +553,7 @@ Backup_restore_ctx::prepare_for_backup(L Open output stream. */ - Output_stream *s= new Output_stream(*this, path, with_compression); + Output_stream *s= new Output_stream(*this, path, with_compression, cipher); if (!s) { Index: stew-encrypted-backup/sql/backup/stream.cc =================================================================== --- stew-encrypted-backup.orig/sql/backup/stream.cc 2008-06-26 02:33:17.646618152 +1000 +++ stew-encrypted-backup/sql/backup/stream.cc 2008-06-26 13:47:41.031040513 +1000 @@ -1,5 +1,11 @@ #include "../mysql_priv.h" +#ifdef HAVE_YASSL +#include +#include "crypto_wrapper.hpp" +#include +#endif + #include "backup_stream.h" #include "stream.h" @@ -33,7 +39,7 @@ namespace backup { extern "C" int stream_write(void *instance, bstream_blob *buf, bstream_blob) { int fd; - int res; + int res= 0; DBUG_ENTER("backup::stream_write"); @@ -62,8 +68,13 @@ extern "C" int stream_write(void *instan { if (!zstream->avail_out) { - if (my_write(fd, s->zbuf, ZBUF_SIZE, MYF(MY_NABP))) - DBUG_RETURN(BSTREAM_ERROR); +#ifdef HAVE_YASSL + if (s->m_cipher) + res= (howmuch==my_crypt_write(&(s->m_cfd), s->zbuf, ZBUF_SIZE))?0:-1; + else +#endif + if (my_write(fd, s->zbuf, ZBUF_SIZE, MYF(MY_NABP))) + DBUG_RETURN(BSTREAM_ERROR); zstream->next_out= s->zbuf; zstream->avail_out= ZBUF_SIZE; } @@ -74,8 +85,13 @@ extern "C" int stream_write(void *instan else #endif { - res= my_write(fd, buf->begin, howmuch, - MY_NABP /* error if not all bytes written */ ); +#ifdef HAVE_YASSL + if (s->m_cipher) + res= (howmuch==my_crypt_write(&(s->m_cfd), buf->begin, howmuch))?0:-1; + else +#endif + res= my_write(fd, buf->begin, howmuch, + MY_NABP /* error if not all bytes written */ ); if (res) DBUG_RETURN(BSTREAM_ERROR); @@ -214,12 +230,13 @@ bool Stream::rewind() Output_stream::Output_stream(Logger &log, const ::String &name, - bool with_compression) + bool with_compression, yaSSL::BulkCipher *cipher) :Stream(log, name, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC) { m_with_compression= with_compression; stream.write= stream_write; m_block_size=0; // use default block size provided by the backup stram library + m_cipher= cipher; } /** @@ -274,6 +291,13 @@ bool Output_stream::init() return TRUE; } +int enc_filter(void* obj,char* obuf,char* ibuf,size_t sz) +{ + yaSSL::BulkCipher *c= (yaSSL::BulkCipher*)obj; + c->encrypt((yaSSL::byte*)obuf, (yaSSL::byte*)ibuf, sz); + return 0; +} + /** Open and initialize backup stream for writing. @@ -288,6 +312,13 @@ bool Output_stream::open() bool ret= Stream::open(); +#ifdef HAVE_YASSL + int r= 0; + if(m_cipher) + r= my_crypt_fdopen(&m_cfd, m_fd, O_WRONLY, &enc_filter, (void*)m_cipher, + m_cipher->get_blockSize()); +#endif + if (!ret) return FALSE; @@ -348,11 +379,25 @@ void Output_stream::close() m_log.report_error(ER_GET_ERRMSG, zerr, zstream.msg, "deflate"); break; } - if (my_write(m_fd, zbuf, ZBUF_SIZE - zstream.avail_out, - MYF(MY_NABP))) +#ifdef HAVE_YASSL + if(m_cipher) { - m_log.report_error(ER_GET_ERRMSG, my_errno, "", "my_write"); - break; + int sz= ZBUF_SIZE - zstream.avail_out; + if (my_crypt_write(&m_cfd, zbuf, sz)!=sz) + { + m_log.report_error(ER_GET_ERRMSG, my_errno, "", "my_write"); + break; + } + } + else +#endif + { + if (my_write(m_fd, zbuf, ZBUF_SIZE - zstream.avail_out, + MYF(MY_NABP))) + { + m_log.report_error(ER_GET_ERRMSG, my_errno, "", "my_write"); + break; + } } zstream.next_out= zbuf; zstream.avail_out= ZBUF_SIZE; @@ -362,6 +407,14 @@ void Output_stream::close() my_free(zbuf, MYF(0)); } #endif + +#ifdef HAVE_YASSL + if(m_cipher) + { + my_crypt_close(&m_cfd, 0); + } +#endif + Stream::close(); } Index: stew-encrypted-backup/sql/backup/stream.h =================================================================== --- stew-encrypted-backup.orig/sql/backup/stream.h 2008-06-26 02:33:17.818625434 +1000 +++ stew-encrypted-backup/sql/backup/stream.h 2008-06-26 13:42:12.159050036 +1000 @@ -11,6 +11,9 @@ #include #endif +#include +#include + /** @file @@ -64,7 +67,12 @@ struct fd_stream: public backup_stream z_stream zstream; uchar *zbuf; #endif - + +#ifdef HAVE_YASSL + yaSSL::BulkCipher *m_cipher; + struct my_crypt_fd m_cfd; +#endif + fd_stream() :m_fd(-1), bytes(0) {} }; @@ -110,7 +118,7 @@ class Output_stream: { public: - Output_stream(Logger&, const ::String&, bool); + Output_stream(Logger&, const ::String&, bool, yaSSL::BulkCipher*); bool open(); void close(); Index: stew-encrypted-backup/sql/Makefile.am =================================================================== --- stew-encrypted-backup.orig/sql/Makefile.am 2008-06-25 01:43:36.216194493 +1000 +++ stew-encrypted-backup/sql/Makefile.am 2008-06-26 03:09:28.115656988 +1000 @@ -46,15 +46,15 @@ SUPPORTING_LIBS = $(top_builddir)/vio/li $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/regex/libregex.a \ $(top_builddir)/strings/libmystrings.a -mysqld_DEPENDENCIES= @mysql_plugin_libs@ $(SUPPORTING_LIBS) backup/libbackup.la libndb.la +mysqld_DEPENDENCIES= backup/libbackup.la @mysql_plugin_libs@ $(SUPPORTING_LIBS) libndb.la LDADD = $(SUPPORTING_LIBS) @ZLIB_LIBS@ @NDB_SCI_LIBS@ mysqld_LDADD = libndb.la \ + backup/libbackup.la \ @MYSQLD_EXTRA_LDFLAGS@ \ @pstack_libs@ $(libevent_libs) \ @mysql_plugin_libs@ \ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \ - $(yassl_libs) $(openssl_libs) @MYSQLD_EXTRA_LIBS@ \ - backup/libbackup.la + $(yassl_libs) $(openssl_libs) @MYSQLD_EXTRA_LIBS@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h \ Index: stew-encrypted-backup/mysql-test/t/backup_encrypted.test =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ stew-encrypted-backup/mysql-test/t/backup_encrypted.test 2008-06-26 13:42:12.195064313 +1000 @@ -0,0 +1,13 @@ +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; + BACKUP DATABASE test TO 'test42.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128 PASSWORD='pants'; Index: stew-encrypted-backup/mysql-test/r/backup_encrypted.result =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ stew-encrypted-backup/mysql-test/r/backup_encrypted.result 2008-06-26 03:09:28.151618373 +1000 @@ -0,0 +1,15 @@ +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; +BACKUP DATABASE test TO 'test42.ba' ENCRYPTION_ALGORITHM=aes ENCRYPTION_KEYSIZE=128 PASSWORD='pants'; +backup_id +1 -- Stewart Smith