summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_crypt.cc
diff options
context:
space:
mode:
authorRadoslaw Zarzynski <rzarzyns@redhat.com>2019-04-17 16:11:59 +0200
committerRadoslaw Zarzynski <rzarzyns@redhat.com>2019-06-17 14:45:27 +0200
commit16c5c46ecdbc992a2d779521468117de7c0683cc (patch)
tree47ca613eac0bc947d7517cdb56e5bf04758bf0b7 /src/rgw/rgw_crypt.cc
parentrgw: switch AES_256_CBC::cbc_transform() from NSS to OpenSSL. (diff)
downloadceph-16c5c46ecdbc992a2d779521468117de7c0683cc.tar.xz
ceph-16c5c46ecdbc992a2d779521468117de7c0683cc.zip
rgw: generalize the symmetric crypto with evp_sym_transform().
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
Diffstat (limited to 'src/rgw/rgw_crypt.cc')
-rw-r--r--src/rgw/rgw_crypt.cc132
1 files changed, 72 insertions, 60 deletions
diff --git a/src/rgw/rgw_crypt.cc b/src/rgw/rgw_crypt.cc
index d669355b86f..907f6ecc592 100644
--- a/src/rgw/rgw_crypt.cc
+++ b/src/rgw/rgw_crypt.cc
@@ -174,6 +174,74 @@ CryptoAccelRef get_crypto_accel(CephContext *cct)
}
+#ifdef USE_OPENSSL
+template <std::size_t KeySizeV, std::size_t IvSizeV>
+static inline
+bool evp_sym_transform(CephContext* const cct,
+ const EVP_CIPHER* const type,
+ unsigned char* const out,
+ const unsigned char* const in,
+ const size_t size,
+ const unsigned char* const iv,
+ const unsigned char* const key,
+ const bool encrypt)
+{
+ using pctx_t = \
+ std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>;
+ pctx_t pctx{ EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free };
+
+ if (!pctx) {
+ return false;
+ }
+
+ if (1 != EVP_CipherInit_ex(pctx.get(), type, nullptr,
+ nullptr, nullptr, encrypt)) {
+ ldout(cct, 5) << "EVP: failed to 1st initialization stage" << dendl;
+ return false;
+ }
+
+ // we want to support ciphers that don't use IV at all like AES-256-ECB
+ if constexpr (IvSizeV) {
+ ceph_assert(EVP_CIPHER_CTX_iv_length(pctx.get()) == IvSizeV);
+ ceph_assert(EVP_CIPHER_CTX_block_size(pctx.get()) == IvSizeV);
+ }
+ ceph_assert(EVP_CIPHER_CTX_key_length(pctx.get()) == KeySizeV);
+
+ if (1 != EVP_CipherInit_ex(pctx.get(), nullptr, nullptr, key, iv, encrypt)) {
+ ldout(cct, 5) << "EVP: failed to 2nd initialization stage" << dendl;
+ return false;
+ }
+
+ // disable padding
+ if (1 != EVP_CIPHER_CTX_set_padding(pctx.get(), 0)) {
+ ldout(cct, 5) << "EVP: cannot disable PKCS padding" << dendl;
+ return false;
+ }
+
+ // operate!
+ int written = 0;
+ ceph_assert(size <= std::numeric_limits<int>::max());
+ if (1 != EVP_CipherUpdate(pctx.get(), out, &written, in, size)) {
+ ldout(cct, 5) << "EVP: EVP_CipherUpdate failed" << dendl;
+ return false;
+ }
+
+ int finally_written = 0;
+ static_assert(sizeof(*out) == 1);
+ if (1 != EVP_CipherFinal_ex(pctx.get(), out + written, &finally_written)) {
+ ldout(cct, 5) << "EVP: EVP_CipherFinal_ex failed" << dendl;
+ return false;
+ }
+
+ // padding is disabled so EVP_CipherFinal_ex should not append anything
+ ceph_assert(finally_written == 0);
+ return (written + finally_written) == static_cast<int>(size);
+}
+#else // USE_OPENSSL
+# error "No supported crypto implementation found."
+#endif
+
+
/**
* Encryption in CBC mode. Chunked to 4K blocks. Offset is used as IV for each 4K block.
*
@@ -234,69 +302,13 @@ public:
const unsigned char (&key)[AES_256_KEYSIZE],
bool encrypt)
{
-# if OPENSSL_VERSION_NUMBER < 0x10100000L
- // In older OpenSSL versions putting EVP context on stack and ending
- // its life with EVP_CIPHER_CTX_cleanup() was legit.
- // XXX: do we really want this optimization?
- EVP_CIPHER_CTX ctx;
-
- using pctx_t = \
- std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_cleanup)>;
- pctx_t pctx{ &ctx, EVP_CIPHER_CTX_cleanup };
-#else
- using pctx_t = \
- std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>;
- pctx_t pctx{ EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free };
-
- if (!pctx) {
- return false;
- }
-#endif // OPENSSL_VERSION_NUMBER < 0x10100000L
-
- if (1 != EVP_CipherInit_ex(pctx.get(), EVP_aes_256_cbc(),
- nullptr, nullptr, nullptr, encrypt)) {
- ldout(cct, 5) << "AES-CBC: failed to 1st initialization stage" << dendl;
- return false;
- }
-
- ceph_assert(EVP_CIPHER_CTX_key_length(pctx.get()) == AES_256_KEYSIZE);
- ceph_assert(EVP_CIPHER_CTX_iv_length(pctx.get()) == AES_256_IVSIZE);
- ceph_assert(EVP_CIPHER_CTX_block_size(pctx.get()) == AES_256_IVSIZE);
-
- if (1 != EVP_CipherInit_ex(pctx.get(), nullptr, nullptr, key, iv, encrypt)) {
- ldout(cct, 5) << "AES-CBC: failed to 2nd initialization stage" << dendl;
- return false;
- }
-
- // disable padding
- if (1 != EVP_CIPHER_CTX_set_padding(pctx.get(), 0)) {
- ldout(cct, 5) << "AES-CBC: cannot disable PKCS padding" << dendl;
- return false;
- }
-
- // operate!
- int written = 0;
- ceph_assert(size <= std::numeric_limits<int>::max());
- if (1 != EVP_CipherUpdate(pctx.get(), out, &written, in, size)) {
- ldout(cct, 5) << "AES-CBC: EVP_CipherUpdate failed" << dendl;
- return false;
- }
-
- int finally_written = 0;
- static_assert(sizeof(*out) == 1);
- if (1 != EVP_CipherFinal_ex(pctx.get(), out + written, &finally_written)) {
- ldout(cct, 5) << "AES-CBC: EVP_CipherFinal_ex failed" << dendl;
- return false;
- }
-
- // as padding is disabled EVP_CipherFinal_ex should not append anything
- ceph_assert(finally_written == 0);
- return (written + finally_written) == static_cast<int>(size);
+ return evp_sym_transform<AES_256_KEYSIZE, AES_256_IVSIZE>(
+ cct, EVP_aes_256_cbc(), out, in, size, iv, key, encrypt);
}
-#else // USE_OPENSSL
+#else
# error "No supported crypto implementation found."
-#endif
+#endif // USE_OPENSSL
bool cbc_transform(unsigned char* out,
const unsigned char* in,