From 487296875b2d28bf30778b0455b91550ec7180d7 Mon Sep 17 00:00:00 2001 From: Hang Li Date: Wed, 8 Jan 2020 08:57:03 +0800 Subject: [PATCH] crypto/openssl: update to use evp functions Openssl evp functions are a high level interface to openssl crypto functions and can use external crypto engines, hardware accelerator and AES instruction set. It is more flexible than AES_encrypt. There is up to 6x faster than the AES_cbc_encrypt implementation on armv8 server with armv8 cryptographic extensions. Signed-off-by: Hang Li Signed-off-by: luo rixin --- src/crypto/openssl/openssl_crypto_accel.cc | 85 ++++++++++++++++++---- 1 file changed, 70 insertions(+), 15 deletions(-) diff --git a/src/crypto/openssl/openssl_crypto_accel.cc b/src/crypto/openssl/openssl_crypto_accel.cc index 156a2771e0910..2eae753068452 100644 --- a/src/crypto/openssl/openssl_crypto_accel.cc +++ b/src/crypto/openssl/openssl_crypto_accel.cc @@ -13,8 +13,68 @@ */ #include "crypto/openssl/openssl_crypto_accel.h" -#include +#include +#include +#include "common/debug.h" +// ----------------------------------------------------------------------------- +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_crypto +#undef dout_prefix +#define dout_prefix _prefix(_dout) + +static ostream& +_prefix(std::ostream* _dout) +{ + return *_dout << "OpensslCryptoAccel: "; +} +// ----------------------------------------------------------------------------- + +#define EVP_SUCCESS 1 +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +bool evp_transform(unsigned char* out, const unsigned char* in, size_t size, + const unsigned char* iv, + const unsigned char* key, + ENGINE* engine, + const EVP_CIPHER* const type, + const int encrypt) +{ + using pctx_t = std::unique_ptr; + pctx_t pctx{ EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free }; + + if (!pctx) { + derr << "failed to create evp cipher context" << dendl; + return false; + } + + if (EVP_CipherInit_ex(pctx.get(), type, engine, key, iv, encrypt) != EVP_SUCCESS) { + derr << "EVP_CipherInit_ex failed" << dendl; + return false; + } + + if (EVP_CIPHER_CTX_set_padding(pctx.get(), 0) != EVP_SUCCESS) { + derr << "failed to disable PKCS padding" << dendl; + return false; + } + + int len_update = 0; + if (EVP_CipherUpdate(pctx.get(), out, &len_update, in, size) != EVP_SUCCESS) { + derr << "EVP_CipherUpdate failed" << dendl; + return false; + } + + int len_final = 0; + if (EVP_CipherFinal_ex(pctx.get(), out + len_update, &len_final) != EVP_SUCCESS) { + derr << "EVP_CipherFinal_ex failed" << dendl; + return false; + } + + ceph_assert(len_final == 0); + return (len_update + len_final) == static_cast(size); +} + bool OpenSSLCryptoAccel::cbc_encrypt(unsigned char* out, const unsigned char* in, size_t size, const unsigned char (&iv)[AES_256_IVSIZE], const unsigned char (&key)[AES_256_KEYSIZE]) @@ -23,14 +83,12 @@ bool OpenSSLCryptoAccel::cbc_encrypt(unsigned char* out, const unsigned char* in return false; } - AES_KEY aes_key; - if (AES_set_encrypt_key(const_cast(&key[0]), 256, &aes_key) < 0) - return false; - - AES_cbc_encrypt(const_cast(in), out, size, &aes_key, - const_cast(&iv[0]), AES_ENCRYPT); - return true; + return evp_transform(out, in, size, const_cast(&iv[0]), + const_cast(&key[0]), + nullptr, // Hardware acceleration engine can be used in the future + EVP_aes_256_cbc(), AES_ENCRYPT); } + bool OpenSSLCryptoAccel::cbc_decrypt(unsigned char* out, const unsigned char* in, size_t size, const unsigned char (&iv)[AES_256_IVSIZE], const unsigned char (&key)[AES_256_KEYSIZE]) @@ -39,11 +97,8 @@ bool OpenSSLCryptoAccel::cbc_decrypt(unsigned char* out, const unsigned char* in return false; } - AES_KEY aes_key; - if (AES_set_decrypt_key(const_cast(&key[0]), 256, &aes_key) < 0) - return false; - - AES_cbc_encrypt(const_cast(in), out, size, &aes_key, - const_cast(&iv[0]), AES_DECRYPT); - return true; + return evp_transform(out, in, size, const_cast(&iv[0]), + const_cast(&key[0]), + nullptr, // Hardware acceleration engine can be used in the future + EVP_aes_256_cbc(), AES_DECRYPT); } -- 2.39.5