diff options
-rw-r--r-- | cmake/ssl.cmake | 5 | ||||
-rw-r--r-- | config.h.cmake | 2 | ||||
-rw-r--r-- | include/my_crypt.h | 13 | ||||
-rw-r--r-- | mysys_ssl/my_crypt.cc | 86 |
4 files changed, 103 insertions, 3 deletions
diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake index f91821ec905..1926f8b1b8e 100644 --- a/cmake/ssl.cmake +++ b/cmake/ssl.cmake @@ -55,7 +55,8 @@ MACRO (MYSQL_USE_BUNDLED_SSL) SET(SSL_INCLUDE_DIRS ${INC_DIRS}) SET(SSL_INTERNAL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL) SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PREFIX -DHAVE_OPENSSL -DMULTI_THREADED") - SET(HAVE_EncryptAes128Ctr OFF CACHE INTERNAL "yassl doesn't have EncryptAes128Ctr") + SET(HAVE_EncryptAes128Ctr OFF CACHE INTERNAL "yassl doesn't support AES-CTR") + SET(HAVE_EncryptAes128Gcm OFF CACHE INTERNAL "yassl doesn't support AES-GCM") CHANGE_SSL_SETTINGS("bundled") ADD_SUBDIRECTORY(extra/yassl) ADD_SUBDIRECTORY(extra/yassl/taocrypt) @@ -199,6 +200,8 @@ MACRO (MYSQL_CHECK_SSL) SET(CMAKE_REQUIRED_LIBRARIES ${SSL_LIBRARIES}) CHECK_SYMBOL_EXISTS(EVP_aes_128_ctr "openssl/evp.h" HAVE_EncryptAes128Ctr) + CHECK_SYMBOL_EXISTS(EVP_aes_128_gcm "openssl/evp.h" + HAVE_EncryptAes128Gcm) ELSE() IF(WITH_SSL STREQUAL "system") MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support") diff --git a/config.h.cmake b/config.h.cmake index 7964bf30ded..6d90bf565c6 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -591,7 +591,7 @@ #cmakedefine HAVE_UCA_COLLATIONS 1 #cmakedefine HAVE_COMPRESS 1 #cmakedefine HAVE_EncryptAes128Ctr 1 - +#cmakedefine HAVE_EncryptAes128Gcm 1 /* Stuff that always need to be defined (compile breaks without it) diff --git a/include/my_crypt.h b/include/my_crypt.h index 821b4d2fa8c..3e6da6aa212 100644 --- a/include/my_crypt.h +++ b/include/my_crypt.h @@ -47,6 +47,19 @@ int my_aes_encrypt_ctr(const uchar* source, uint source_length, #endif +#ifdef HAVE_EncryptAes128Gcm + +int my_aes_encrypt_gcm(const uchar* source, uint source_length, + uchar* dest, uint* dest_length, + const uchar* key, uint key_length, + const uchar* iv, uint iv_length); + +int my_aes_decrypt_gcm(const uchar* source, uint source_length, + uchar* dest, uint* dest_length, + const uchar* key, uint key_length, + const uchar* iv, uint iv_length); +#endif + int my_aes_encrypt_cbc(const uchar* source, uint source_length, uchar* dest, uint* dest_length, const uchar* key, uint key_length, diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc index 04771aeb954..9f37883a9b8 100644 --- a/mysys_ssl/my_crypt.cc +++ b/mysys_ssl/my_crypt.cc @@ -195,7 +195,7 @@ int my_aes_encrypt_ctr(const uchar* source, uint source_length, return MY_AES_OPENSSL_ERROR; DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == (int)key_length); - DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(&ctx) == (int)iv_length); + DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(&ctx) <= (int)iv_length); DBUG_ASSERT(EVP_CIPHER_CTX_block_size(&ctx) == 1); if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length, source, source_length)) @@ -209,6 +209,90 @@ int my_aes_encrypt_ctr(const uchar* source, uint source_length, #endif /* HAVE_EncryptAes128Ctr */ +#ifdef HAVE_EncryptAes128Gcm +make_aes_dispatcher(gcm) + +/* + special implementation for GCM; to fit OpenSSL AES-GCM into the + existing my_aes_* API it does the following: + - IV tail (over 12 bytes) goes to AAD + - the tag is appended to the ciphertext +*/ +int do_gcm(const uchar* source, uint source_length, + uchar* dest, uint* dest_length, + const uchar* key, uint key_length, + const uchar* iv, uint iv_length, Dir dir) +{ + CipherMode cipher= aes_gcm(key_length); + struct MyCTX ctx; + int fin; + uint real_iv_length; + + if (unlikely(!cipher)) + return MY_AES_BAD_KEYSIZE; + + if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, dir)) + return MY_AES_OPENSSL_ERROR; + + real_iv_length= EVP_CIPHER_CTX_iv_length(&ctx); + + DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == (int)key_length); + DBUG_ASSERT(real_iv_length <= iv_length); + DBUG_ASSERT(EVP_CIPHER_CTX_block_size(&ctx) == 1); + + if (dir == CRYPT_DECRYPT) + { + source_length-= MY_AES_BLOCK_SIZE; + if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, MY_AES_BLOCK_SIZE, + (void*)(source + source_length))) + return MY_AES_OPENSSL_ERROR; + } + + if (real_iv_length < iv_length) + { + if (!EVP_CipherUpdate(&ctx, NULL, &fin, + iv + real_iv_length, iv_length - real_iv_length)) + return MY_AES_OPENSSL_ERROR; + } + + if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length, source, source_length)) + return MY_AES_OPENSSL_ERROR; + + if (!EVP_CipherFinal_ex(&ctx, dest + *dest_length, &fin)) + return MY_AES_BAD_DATA; + DBUG_ASSERT(fin == 0); + + if (dir == CRYPT_ENCRYPT) + { + if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, MY_AES_BLOCK_SIZE, + dest + *dest_length)) + return MY_AES_OPENSSL_ERROR; + *dest_length+= MY_AES_BLOCK_SIZE; + } + + return MY_AES_OK; +} + +int my_aes_encrypt_gcm(const uchar* source, uint source_length, + uchar* dest, uint* dest_length, + const uchar* key, uint key_length, + const uchar* iv, uint iv_length) +{ + return do_gcm(source, source_length, dest, dest_length, + key, key_length, iv, iv_length, CRYPT_ENCRYPT); +} + +int my_aes_decrypt_gcm(const uchar* source, uint source_length, + uchar* dest, uint* dest_length, + const uchar* key, uint key_length, + const uchar* iv, uint iv_length) +{ + return do_gcm(source, source_length, dest, dest_length, + key, key_length, iv, iv_length, CRYPT_DECRYPT); +} + +#endif + int my_aes_encrypt_ecb(const uchar* source, uint source_length, uchar* dest, uint* dest_length, const uchar* key, uint key_length, |