remove ceph code
[stor4nfv.git] / src / ceph / src / rgw / rgw_crypt.cc
diff --git a/src/ceph/src/rgw/rgw_crypt.cc b/src/ceph/src/rgw/rgw_crypt.cc
deleted file mode 100644 (file)
index 81a84ad..0000000
+++ /dev/null
@@ -1,1414 +0,0 @@
-// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/**
- * Crypto filters for Put/Post/Get operations.
- */
-#include <rgw/rgw_op.h>
-#include <rgw/rgw_crypt.h>
-#include <auth/Crypto.h>
-#include <rgw/rgw_b64.h>
-#include <rgw/rgw_rest_s3.h>
-#include "include/assert.h"
-#include <boost/utility/string_view.hpp>
-#include <rgw/rgw_keystone.h>
-#include "include/str_map.h"
-#include "crypto/crypto_accel.h"
-#include "crypto/crypto_plugin.h"
-#ifdef USE_NSS
-# include <nspr.h>
-# include <nss.h>
-# include <pk11pub.h>
-#endif
-
-#ifdef USE_CRYPTOPP
-#include <cryptopp/cryptlib.h>
-#include <cryptopp/modes.h>
-#include <cryptopp/aes.h>
-using namespace CryptoPP;
-#endif
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rgw
-
-using namespace rgw;
-
-/**
- * Encryption in CTR mode. offset is used as IV for each block.
- */
-#warning "TODO: move this code to auth/Crypto for others to reuse."
-
-class AES_256_CTR : public BlockCrypt {
-public:
-  static const size_t AES_256_KEYSIZE = 256 / 8;
-  static const size_t AES_256_IVSIZE = 128 / 8;
-private:
-  static const uint8_t IV[AES_256_IVSIZE];
-  CephContext* cct;
-  uint8_t key[AES_256_KEYSIZE];
-public:
-  AES_256_CTR(CephContext* cct): cct(cct) {
-  }
-  ~AES_256_CTR() {
-    memset(key, 0, AES_256_KEYSIZE);
-  }
-  bool set_key(const uint8_t* _key, size_t key_size) {
-    if (key_size != AES_256_KEYSIZE) {
-      return false;
-    }
-    memcpy(key, _key, AES_256_KEYSIZE);
-    return true;
-  }
-  size_t get_block_size() {
-    return AES_256_IVSIZE;
-  }
-
-#ifdef USE_CRYPTOPP
-
-  bool encrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset) {
-    byte iv[AES_256_IVSIZE];
-    ldout(cct, 25)
-        << "Encrypt in_ofs " << in_ofs
-        << " size=" << size
-        << " stream_offset=" << stream_offset
-        << dendl;
-    if (input.length() < in_ofs + size) {
-      return false;
-    }
-
-    output.clear();
-    buffer::ptr buf((size + AES_256_KEYSIZE - 1) / AES_256_KEYSIZE * AES_256_KEYSIZE);
-    /*create CTR mask*/
-    prepare_iv(iv, stream_offset);
-    CTR_Mode< AES >::Encryption e;
-    e.SetKeyWithIV(key, AES_256_KEYSIZE, iv, AES_256_IVSIZE);
-    buf.zero();
-    e.ProcessData((byte*)buf.c_str(), (byte*)buf.c_str(), buf.length());
-    buf.set_length(size);
-    off_t plaintext_pos = in_ofs;
-    off_t crypt_pos = 0;
-    auto iter = input.buffers().begin();
-    //skip unaffected begin
-    while ((iter != input.buffers().end()) && (plaintext_pos >= iter->length())) {
-      plaintext_pos -= iter->length();
-      ++iter;
-    }
-    while (iter != input.buffers().end()) {
-      off_t cnt = std::min<off_t>(iter->length() - plaintext_pos, size - crypt_pos);
-      byte* src = (byte*)iter->c_str() + plaintext_pos;
-      byte* dst = (byte*)buf.c_str() + crypt_pos;
-      for (off_t i = 0; i < cnt; i++) {
-        dst[i] ^= src[i];
-      }
-      ++iter;
-      plaintext_pos = 0;
-      crypt_pos += cnt;
-    }
-    output.append(buf);
-    return true;
-  }
-
-#elif defined(USE_NSS)
-
-  bool encrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset)
-  {
-    bool result = false;
-    PK11SlotInfo *slot;
-    SECItem keyItem;
-    PK11SymKey *symkey;
-    CK_AES_CTR_PARAMS ctr_params = {0};
-    SECItem ivItem;
-    SECItem *param;
-    SECStatus ret;
-    PK11Context *ectx;
-    int written;
-    unsigned int written2;
-
-    slot = PK11_GetBestSlot(CKM_AES_CTR, NULL);
-    if (slot) {
-      keyItem.type = siBuffer;
-      keyItem.data = key;
-      keyItem.len = AES_256_KEYSIZE;
-
-      symkey = PK11_ImportSymKey(slot, CKM_AES_CTR, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
-      if (symkey) {
-        static_assert(sizeof(ctr_params.cb) >= AES_256_IVSIZE, "Must fit counter");
-        ctr_params.ulCounterBits = 128;
-        prepare_iv(reinterpret_cast<unsigned char*>(&ctr_params.cb), stream_offset);
-
-        ivItem.type = siBuffer;
-        ivItem.data = (unsigned char*)&ctr_params;
-        ivItem.len = sizeof(ctr_params);
-
-        param = PK11_ParamFromIV(CKM_AES_CTR, &ivItem);
-        if (param) {
-          ectx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, symkey, param);
-          if (ectx) {
-            buffer::ptr buf((size + AES_256_KEYSIZE - 1) / AES_256_KEYSIZE * AES_256_KEYSIZE);
-            ret = PK11_CipherOp(ectx,
-                                (unsigned char*)buf.c_str(), &written, buf.length(),
-                                (unsigned char*)input.c_str() + in_ofs, size);
-            if (ret == SECSuccess) {
-              ret = PK11_DigestFinal(ectx,
-                                     (unsigned char*)buf.c_str() + written, &written2,
-                                     buf.length() - written);
-              if (ret == SECSuccess) {
-                buf.set_length(written + written2);
-                output.append(buf);
-                result = true;
-              }
-            }
-            PK11_DestroyContext(ectx, PR_TRUE);
-          }
-          SECITEM_FreeItem(param, PR_TRUE);
-        }
-        PK11_FreeSymKey(symkey);
-      }
-      PK11_FreeSlot(slot);
-    }
-    if (result == false) {
-      ldout(cct, 5) << "Failed to perform AES-CTR encryption: " << PR_GetError() << dendl;
-    }
-    return result;
-  }
-
-#else
-#error Must define USE_CRYPTOPP or USE_NSS
-#endif
-  /* in CTR encrypt is the same as decrypt */
-  bool decrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset) {
-         return encrypt(input, in_ofs, size, output, stream_offset);
-  }
-
-  void prepare_iv(byte iv[AES_256_IVSIZE], off_t offset) {
-    off_t index = offset / AES_256_IVSIZE;
-    off_t i = AES_256_IVSIZE - 1;
-    unsigned int val;
-    unsigned int carry = 0;
-    while (i>=0) {
-      val = (index & 0xff) + IV[i] + carry;
-      iv[i] = val;
-      carry = val >> 8;
-      index = index >> 8;
-      i--;
-    }
-  }
-};
-
-const uint8_t AES_256_CTR::IV[AES_256_CTR::AES_256_IVSIZE] =
-    { 'a', 'e', 's', '2', '5', '6', 'i', 'v', '_', 'c', 't', 'r', '1', '3', '3', '7' };
-
-
-CryptoAccelRef get_crypto_accel(CephContext *cct)
-{
-  CryptoAccelRef ca_impl = nullptr;
-  stringstream ss;
-  PluginRegistry *reg = cct->get_plugin_registry();
-  string crypto_accel_type = cct->_conf->plugin_crypto_accelerator;
-
-  CryptoPlugin *factory = dynamic_cast<CryptoPlugin*>(reg->get_with_load("crypto", crypto_accel_type));
-  if (factory == nullptr) {
-    lderr(cct) << __func__ << " cannot load crypto accelerator of type " << crypto_accel_type << dendl;
-    return nullptr;
-  }
-  int err = factory->factory(&ca_impl, &ss);
-  if (err) {
-    lderr(cct) << __func__ << " factory return error " << err <<
-        " with description: " << ss.str() << dendl;
-  }
-  return ca_impl;
-}
-
-
-/**
- * Encryption in CBC mode. Chunked to 4K blocks. Offset is used as IV for each 4K block.
- *
- *
- *
- * A. Encryption
- * 1. Input is split to 4K chunks + remainder in one, smaller chunk
- * 2. Each full chunk is encrypted separately with CBC chained mode, with initial IV derived from offset
- * 3. Last chunk is 16*m + n.
- * 4. 16*m bytes are encrypted with CBC chained mode, with initial IV derived from offset
- * 5. Last n bytes are xor-ed with pattern obtained by CBC encryption of
- *    last encrypted 16 byte block <16m-16, 16m-15) with IV = {0}.
- * 6. (Special case) If m == 0 then last n bytes are xor-ed with pattern
- *    obtained by CBC encryption of {0} with IV derived from offset
- *
- * B. Decryption
- * 1. Input is split to 4K chunks + remainder in one, smaller chunk
- * 2. Each full chunk is decrypted separately with CBC chained mode, with initial IV derived from offset
- * 3. Last chunk is 16*m + n.
- * 4. 16*m bytes are decrypted with CBC chained mode, with initial IV derived from offset
- * 5. Last n bytes are xor-ed with pattern obtained by CBC ENCRYPTION of
- *    last (still encrypted) 16 byte block <16m-16,16m-15) with IV = {0}
- * 6. (Special case) If m == 0 then last n bytes are xor-ed with pattern
- *    obtained by CBC ENCRYPTION of {0} with IV derived from offset
- */
-#warning "TODO: use auth/Crypto instead of reimplementing."
-class AES_256_CBC : public BlockCrypt {
-public:
-  static const size_t AES_256_KEYSIZE = 256 / 8;
-  static const size_t AES_256_IVSIZE = 128 / 8;
-  static const size_t CHUNK_SIZE = 4096;
-private:
-  static const uint8_t IV[AES_256_IVSIZE];
-  CephContext* cct;
-  uint8_t key[AES_256_KEYSIZE];
-public:
-  AES_256_CBC(CephContext* cct): cct(cct) {
-  }
-  ~AES_256_CBC() {
-    memset(key, 0, AES_256_KEYSIZE);
-  }
-  bool set_key(const uint8_t* _key, size_t key_size) {
-    if (key_size != AES_256_KEYSIZE) {
-      return false;
-    }
-    memcpy(key, _key, AES_256_KEYSIZE);
-    return true;
-  }
-  size_t get_block_size() {
-    return CHUNK_SIZE;
-  }
-
-#ifdef USE_CRYPTOPP
-
-  bool cbc_transform(unsigned char* out,
-                     const unsigned char* in,
-                     size_t size,
-                     const unsigned char (&iv)[AES_256_IVSIZE],
-                     const unsigned char (&key)[AES_256_KEYSIZE],
-                     bool encrypt)
-  {
-    if (encrypt) {
-      CBC_Mode< AES >::Encryption e;
-      e.SetKeyWithIV(key, AES_256_KEYSIZE, iv, AES_256_IVSIZE);
-      e.ProcessData((byte*)out, (byte*)in, size);
-    } else {
-      CBC_Mode< AES >::Decryption d;
-      d.SetKeyWithIV(key, AES_256_KEYSIZE, iv, AES_256_IVSIZE);
-      d.ProcessData((byte*)out, (byte*)in, size);
-    }
-    return true;
-  }
-
-#elif defined(USE_NSS)
-
-  bool cbc_transform(unsigned char* out,
-                     const unsigned char* in,
-                     size_t size,
-                     const unsigned char (&iv)[AES_256_IVSIZE],
-                     const unsigned char (&key)[AES_256_KEYSIZE],
-                     bool encrypt)
-  {
-    bool result = false;
-    PK11SlotInfo *slot;
-    SECItem keyItem;
-    PK11SymKey *symkey;
-    CK_AES_CBC_ENCRYPT_DATA_PARAMS ctr_params = {0};
-    SECItem ivItem;
-    SECItem *param;
-    SECStatus ret;
-    PK11Context *ectx;
-    int written;
-
-    slot = PK11_GetBestSlot(CKM_AES_CBC, NULL);
-    if (slot) {
-      keyItem.type = siBuffer;
-      keyItem.data = const_cast<unsigned char*>(&key[0]);
-      keyItem.len = AES_256_KEYSIZE;
-      symkey = PK11_ImportSymKey(slot, CKM_AES_CBC, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
-      if (symkey) {
-        memcpy(ctr_params.iv, iv, AES_256_IVSIZE);
-        ivItem.type = siBuffer;
-        ivItem.data = (unsigned char*)&ctr_params;
-        ivItem.len = sizeof(ctr_params);
-
-        param = PK11_ParamFromIV(CKM_AES_CBC, &ivItem);
-        if (param) {
-          ectx = PK11_CreateContextBySymKey(CKM_AES_CBC, encrypt?CKA_ENCRYPT:CKA_DECRYPT, symkey, param);
-          if (ectx) {
-            ret = PK11_CipherOp(ectx,
-                                out, &written, size,
-                                in, size);
-            if ((ret == SECSuccess) && (written == (int)size)) {
-              result = true;
-            }
-            PK11_DestroyContext(ectx, PR_TRUE);
-          }
-          SECITEM_FreeItem(param, PR_TRUE);
-        }
-        PK11_FreeSymKey(symkey);
-      }
-      PK11_FreeSlot(slot);
-    }
-    if (result == false) {
-      ldout(cct, 5) << "Failed to perform AES-CBC encryption: " << PR_GetError() << dendl;
-    }
-    return result;
-  }
-
-#else
-#error Must define USE_CRYPTOPP or USE_NSS
-#endif
-
-  bool cbc_transform(unsigned char* out,
-                     const unsigned char* in,
-                     size_t size,
-                     off_t stream_offset,
-                     const unsigned char (&key)[AES_256_KEYSIZE],
-                     bool encrypt)
-  {
-    static std::atomic<bool> failed_to_get_crypto(false);
-    CryptoAccelRef crypto_accel;
-    if (! failed_to_get_crypto.load())
-    {
-      crypto_accel = get_crypto_accel(cct);
-      if (!crypto_accel)
-        failed_to_get_crypto = true;
-    }
-    bool result = true;
-    unsigned char iv[AES_256_IVSIZE];
-    for (size_t offset = 0; result && (offset < size); offset += CHUNK_SIZE) {
-      size_t process_size = offset + CHUNK_SIZE <= size ? CHUNK_SIZE : size - offset;
-      prepare_iv(iv, stream_offset + offset);
-      if (crypto_accel != nullptr) {
-        if (encrypt) {
-          result = crypto_accel->cbc_encrypt(out + offset, in + offset,
-                                             process_size, iv, key);
-        } else {
-          result = crypto_accel->cbc_decrypt(out + offset, in + offset,
-                                             process_size, iv, key);
-        }
-      } else {
-        result = cbc_transform(
-            out + offset, in + offset, process_size,
-            iv, key, encrypt);
-      }
-    }
-    return result;
-  }
-
-
-  bool encrypt(bufferlist& input,
-               off_t in_ofs,
-               size_t size,
-               bufferlist& output,
-               off_t stream_offset)
-  {
-    bool result = false;
-    size_t aligned_size = size / AES_256_IVSIZE * AES_256_IVSIZE;
-    size_t unaligned_rest_size = size - aligned_size;
-    output.clear();
-    buffer::ptr buf(aligned_size + AES_256_IVSIZE);
-    unsigned char* buf_raw = reinterpret_cast<unsigned char*>(buf.c_str());
-    const unsigned char* input_raw = reinterpret_cast<const unsigned char*>(input.c_str());
-
-    /* encrypt main bulk of data */
-    result = cbc_transform(buf_raw,
-                           input_raw + in_ofs,
-                           aligned_size,
-                           stream_offset, key, true);
-    if (result && (unaligned_rest_size > 0)) {
-      /* remainder to encrypt */
-      if (aligned_size % CHUNK_SIZE > 0) {
-        /* use last chunk for unaligned part */
-        unsigned char iv[AES_256_IVSIZE] = {0};
-        result = cbc_transform(buf_raw + aligned_size,
-                               buf_raw + aligned_size - AES_256_IVSIZE,
-                               AES_256_IVSIZE,
-                               iv, key, true);
-      } else {
-        /* 0 full blocks in current chunk, use IV as base for unaligned part */
-        unsigned char iv[AES_256_IVSIZE] = {0};
-        unsigned char data[AES_256_IVSIZE];
-        prepare_iv(data, stream_offset + aligned_size);
-        result = cbc_transform(buf_raw + aligned_size,
-                               data,
-                               AES_256_IVSIZE,
-                               iv, key, true);
-      }
-      if (result) {
-        for(size_t i = aligned_size; i < size; i++) {
-          *(buf_raw + i) ^= *(input_raw + in_ofs + i);
-        }
-      }
-    }
-    if (result) {
-      ldout(cct, 25) << "Encrypted " << size << " bytes"<< dendl;
-      buf.set_length(size);
-      output.append(buf);
-    } else {
-      ldout(cct, 5) << "Failed to encrypt" << dendl;
-    }
-    return result;
-  }
-
-
-  bool decrypt(bufferlist& input,
-               off_t in_ofs,
-               size_t size,
-               bufferlist& output,
-               off_t stream_offset)
-  {
-    bool result = false;
-    size_t aligned_size = size / AES_256_IVSIZE * AES_256_IVSIZE;
-    size_t unaligned_rest_size = size - aligned_size;
-    output.clear();
-    buffer::ptr buf(aligned_size + AES_256_IVSIZE);
-    unsigned char* buf_raw = reinterpret_cast<unsigned char*>(buf.c_str());
-    unsigned char* input_raw = reinterpret_cast<unsigned char*>(input.c_str());
-
-    /* decrypt main bulk of data */
-    result = cbc_transform(buf_raw,
-                           input_raw + in_ofs,
-                           aligned_size,
-                           stream_offset, key, false);
-    if (result && unaligned_rest_size > 0) {
-      /* remainder to decrypt */
-      if (aligned_size % CHUNK_SIZE > 0) {
-        /*use last chunk for unaligned part*/
-        unsigned char iv[AES_256_IVSIZE] = {0};
-        result = cbc_transform(buf_raw + aligned_size,
-                               input_raw + in_ofs + aligned_size - AES_256_IVSIZE,
-                               AES_256_IVSIZE,
-                               iv, key, true);
-      } else {
-        /* 0 full blocks in current chunk, use IV as base for unaligned part */
-        unsigned char iv[AES_256_IVSIZE] = {0};
-        unsigned char data[AES_256_IVSIZE];
-        prepare_iv(data, stream_offset + aligned_size);
-        result = cbc_transform(buf_raw + aligned_size,
-                               data,
-                               AES_256_IVSIZE,
-                               iv, key, true);
-      }
-      if (result) {
-        for(size_t i = aligned_size; i < size; i++) {
-          *(buf_raw + i) ^= *(input_raw + in_ofs + i);
-        }
-      }
-    }
-    if (result) {
-      ldout(cct, 25) << "Decrypted " << size << " bytes"<< dendl;
-      buf.set_length(size);
-      output.append(buf);
-    } else {
-      ldout(cct, 5) << "Failed to decrypt" << dendl;
-    }
-    return result;
-  }
-
-
-  void prepare_iv(byte (&iv)[AES_256_IVSIZE], off_t offset) {
-    off_t index = offset / AES_256_IVSIZE;
-    off_t i = AES_256_IVSIZE - 1;
-    unsigned int val;
-    unsigned int carry = 0;
-    while (i>=0) {
-      val = (index & 0xff) + IV[i] + carry;
-      iv[i] = val;
-      carry = val >> 8;
-      index = index >> 8;
-      i--;
-    }
-  }
-};
-
-
-std::unique_ptr<BlockCrypt> AES_256_CBC_create(CephContext* cct, const uint8_t* key, size_t len)
-{
-  auto cbc = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(cct));
-  cbc->set_key(key, AES_256_KEYSIZE);
-  return std::move(cbc);
-}
-
-
-const uint8_t AES_256_CBC::IV[AES_256_CBC::AES_256_IVSIZE] =
-    { 'a', 'e', 's', '2', '5', '6', 'i', 'v', '_', 'c', 't', 'r', '1', '3', '3', '7' };
-
-
-#ifdef USE_CRYPTOPP
-
-bool AES_256_ECB_encrypt(CephContext* cct,
-                         const uint8_t* key,
-                         size_t key_size,
-                         const uint8_t* data_in,
-                         uint8_t* data_out,
-                         size_t data_size)
-{
-  bool res = false;
-  if (key_size == AES_256_KEYSIZE) {
-    try {
-      ECB_Mode< AES >::Encryption e;
-      e.SetKey( key, key_size );
-      e.ProcessData(data_out, data_in, data_size);
-      res = true;
-    } catch( CryptoPP::Exception& ex ) {
-      ldout(cct, 5) << "AES-ECB encryption failed with: " << ex.GetWhat() << dendl;
-    }
-  }
-  return res;
-}
-
-#elif defined USE_NSS
-
-bool AES_256_ECB_encrypt(CephContext* cct,
-                         const uint8_t* key,
-                         size_t key_size,
-                         const uint8_t* data_in,
-                         uint8_t* data_out,
-                         size_t data_size) {
-  bool result = false;
-  PK11SlotInfo *slot;
-  SECItem keyItem;
-  PK11SymKey *symkey;
-  SECItem *param;
-  SECStatus ret;
-  PK11Context *ectx;
-  int written;
-  unsigned int written2;
-  if (key_size == AES_256_KEYSIZE) {
-    slot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
-    if (slot) {
-      keyItem.type = siBuffer;
-      keyItem.data = const_cast<uint8_t*>(key);
-      keyItem.len = AES_256_KEYSIZE;
-
-      param = PK11_ParamFromIV(CKM_AES_ECB, NULL);
-      if (param) {
-        symkey = PK11_ImportSymKey(slot, CKM_AES_ECB, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
-        if (symkey) {
-          ectx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, symkey, param);
-          if (ectx) {
-            ret = PK11_CipherOp(ectx,
-                                data_out, &written, data_size,
-                                data_in, data_size);
-            if (ret == SECSuccess) {
-              ret = PK11_DigestFinal(ectx,
-                                     data_out + written, &written2,
-                                     data_size - written);
-              if (ret == SECSuccess) {
-                result = true;
-              }
-            }
-            PK11_DestroyContext(ectx, PR_TRUE);
-          }
-          PK11_FreeSymKey(symkey);
-        }
-        SECITEM_FreeItem(param, PR_TRUE);
-      }
-      PK11_FreeSlot(slot);
-    }
-    if (result == false) {
-      ldout(cct, 5) << "Failed to perform AES-ECB encryption: " << PR_GetError() << dendl;
-    }
-  } else {
-    ldout(cct, 5) << "Key size must be 256 bits long" << dendl;
-  }
-  return result;
-}
-
-#else
-#error Must define USE_CRYPTOPP or USE_NSS
-#endif
-
-
-RGWGetObj_BlockDecrypt::RGWGetObj_BlockDecrypt(CephContext* cct,
-                                               RGWGetDataCB* next,
-                                               std::unique_ptr<BlockCrypt> crypt):
-    RGWGetObj_Filter(next),
-    cct(cct),
-    crypt(std::move(crypt)),
-    enc_begin_skip(0),
-    ofs(0),
-    end(0),
-    cache()
-{
-  block_size = this->crypt->get_block_size();
-}
-
-RGWGetObj_BlockDecrypt::~RGWGetObj_BlockDecrypt() {
-}
-
-int RGWGetObj_BlockDecrypt::read_manifest(bufferlist& manifest_bl) {
-  parts_len.clear();
-  RGWObjManifest manifest;
-  if (manifest_bl.length()) {
-    bufferlist::iterator miter = manifest_bl.begin();
-    try {
-      ::decode(manifest, miter);
-    } catch (buffer::error& err) {
-      ldout(cct, 0) << "ERROR: couldn't decode manifest" << dendl;
-      return -EIO;
-    }
-    RGWObjManifest::obj_iterator mi;
-    for (mi = manifest.obj_begin(); mi != manifest.obj_end(); ++mi) {
-      if (mi.get_cur_stripe() == 0) {
-        parts_len.push_back(0);
-      }
-      parts_len.back() += mi.get_stripe_size();
-    }
-    if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
-      for (size_t i = 0; i<parts_len.size(); i++) {
-        ldout(cct, 20) << "Manifest part " << i << ", size=" << parts_len[i] << dendl;
-      }
-    }
-  }
-  return 0;
-}
-
-int RGWGetObj_BlockDecrypt::fixup_range(off_t& bl_ofs, off_t& bl_end) {
-  off_t inp_ofs = bl_ofs;
-  off_t inp_end = bl_end;
-  if (parts_len.size() > 0) {
-    off_t in_ofs = bl_ofs;
-    off_t in_end = bl_end;
-
-    size_t i = 0;
-    while (i<parts_len.size() && (in_ofs > (off_t)parts_len[i])) {
-      in_ofs -= parts_len[i];
-      i++;
-    }
-    //in_ofs is inside block i
-    size_t j = 0;
-    while (j<parts_len.size() && (in_end > (off_t)parts_len[j])) {
-      in_end -= parts_len[j];
-      j++;
-    }
-    //in_end is inside block j
-
-    size_t rounded_end;
-    rounded_end = ( in_end & ~(block_size - 1) ) + (block_size - 1);
-    if (rounded_end + 1 >= parts_len[j]) {
-      rounded_end = parts_len[j] - 1;
-    }
-
-    enc_begin_skip = in_ofs & (block_size - 1);
-    ofs = bl_ofs - enc_begin_skip;
-    end = bl_end;
-    bl_ofs = bl_ofs - enc_begin_skip;
-    bl_end += rounded_end - in_end;
-  }
-  else
-  {
-    enc_begin_skip = bl_ofs & (block_size - 1);
-    ofs = bl_ofs & ~(block_size - 1);
-    end = bl_end;
-    bl_ofs = bl_ofs & ~(block_size - 1);
-    bl_end = ( bl_end & ~(block_size - 1) ) + (block_size - 1);
-  }
-  ldout(cct, 20) << "fixup_range [" << inp_ofs << "," << inp_end
-      << "] => [" << bl_ofs << "," << bl_end << "]" << dendl;
-  return 0;
-}
-
-
-int RGWGetObj_BlockDecrypt::handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) {
-  int res = 0;
-  ldout(cct, 25) << "Decrypt " << bl_len << " bytes" << dendl;
-  size_t part_ofs = ofs;
-  size_t i = 0;
-  while (i<parts_len.size() && (part_ofs >= parts_len[i])) {
-    part_ofs -= parts_len[i];
-    i++;
-  }
-  bl.copy(bl_ofs, bl_len, cache);
-  off_t aligned_size = cache.length() & ~(block_size - 1);
-  if (aligned_size > 0) {
-    bufferlist data;
-    if (! crypt->decrypt(cache, 0, aligned_size, data, part_ofs) ) {
-      return -ERR_INTERNAL_ERROR;
-    }
-    off_t send_size = aligned_size - enc_begin_skip;
-    if (ofs + enc_begin_skip + send_size > end + 1) {
-      send_size = end + 1 - ofs - enc_begin_skip;
-    }
-    res = next->handle_data(data, enc_begin_skip, send_size);
-    enc_begin_skip = 0;
-    ofs += aligned_size;
-    cache.splice(0, aligned_size);
-  }
-  return res;
-}
-
-/**
- * flush remainder of data to output
- */
-int RGWGetObj_BlockDecrypt::flush() {
-  int res = 0;
-  size_t part_ofs = ofs;
-  size_t i = 0;
-  while (i<parts_len.size() && (part_ofs > parts_len[i])) {
-    part_ofs -= parts_len[i];
-    i++;
-  }
-  if (cache.length() > 0) {
-    bufferlist data;
-    if (! crypt->decrypt(cache, 0, cache.length(), data, part_ofs) ) {
-      return -ERR_INTERNAL_ERROR;
-    }
-    off_t send_size = cache.length() - enc_begin_skip;
-    if (ofs + enc_begin_skip + send_size > end + 1) {
-      send_size = end + 1 - ofs - enc_begin_skip;
-    }
-    res = next->handle_data(data, enc_begin_skip, send_size);
-    enc_begin_skip = 0;
-    ofs += send_size;
-  }
-  return res;
-}
-
-RGWPutObj_BlockEncrypt::RGWPutObj_BlockEncrypt(CephContext* cct,
-                                               RGWPutObjDataProcessor* next,
-                                               std::unique_ptr<BlockCrypt> crypt):
-    RGWPutObj_Filter(next),
-    cct(cct),
-    crypt(std::move(crypt)),
-    ofs(0),
-    cache()
-{
-  block_size = this->crypt->get_block_size();
-}
-
-RGWPutObj_BlockEncrypt::~RGWPutObj_BlockEncrypt() {
-}
-
-int RGWPutObj_BlockEncrypt::handle_data(bufferlist& bl,
-                                        off_t in_ofs,
-                                        void **phandle,
-                                        rgw_raw_obj *pobj,
-                                        bool *again) {
-  int res = 0;
-  ldout(cct, 25) << "Encrypt " << bl.length() << " bytes" << dendl;
-
-  if (*again) {
-    bufferlist no_data;
-    res = next->handle_data(no_data, in_ofs, phandle, pobj, again);
-    //if *again is not set to false, we will have endless loop
-    //drop info on log
-    if (*again) {
-      ldout(cct, 20) << "*again==true" << dendl;
-    }
-    return res;
-  }
-
-  cache.append(bl);
-  off_t proc_size = cache.length() & ~(block_size - 1);
-  if (bl.length() == 0) {
-    proc_size = cache.length();
-  }
-  if (proc_size > 0) {
-    bufferlist data;
-    if (! crypt->encrypt(cache, 0, proc_size, data, ofs) ) {
-      return -ERR_INTERNAL_ERROR;
-    }
-    res = next->handle_data(data, ofs, phandle, pobj, again);
-    ofs += proc_size;
-    cache.splice(0, proc_size);
-    if (res < 0)
-      return res;
-  }
-
-  if (bl.length() == 0) {
-    /*replicate 0-sized handle_data*/
-    res = next->handle_data(bl, ofs, phandle, pobj, again);
-  }
-  return res;
-}
-
-int RGWPutObj_BlockEncrypt::throttle_data(void *handle,
-                                          const rgw_raw_obj& obj,
-                                          uint64_t size,
-                                          bool need_to_wait) {
-  return next->throttle_data(handle, obj, size, need_to_wait);
-}
-
-std::string create_random_key_selector(CephContext * const cct) {
-  char random[AES_256_KEYSIZE];
-  if (get_random_bytes(&random[0], sizeof(random)) != 0) {
-    ldout(cct, 0) << "ERROR: cannot get_random_bytes. " << dendl;
-    for (char& v:random) v=rand();
-  }
-  return std::string(random, sizeof(random));
-}
-
-static int get_barbican_url(CephContext * const cct,
-                     std::string& url)
-{
-  url = cct->_conf->rgw_barbican_url;
-  if (url.empty()) {
-    ldout(cct, 0) << "ERROR: conf rgw_barbican_url is not set" << dendl;
-    return -EINVAL;
-  }
-
-  if (url.back() != '/') {
-    url.append("/");
-  }
-
-  return 0;
-}
-
-static int request_key_from_barbican(CephContext *cct,
-                              boost::string_view key_id,
-                              boost::string_view key_selector,
-                              const std::string& barbican_token,
-                              std::string& actual_key) {
-  std::string secret_url;
-  int res;
-  res = get_barbican_url(cct, secret_url);
-  if (res < 0) {
-     return res;
-  }
-  secret_url += "v1/secrets/" + std::string(key_id);
-
-  bufferlist secret_bl;
-  RGWHTTPTransceiver secret_req(cct, &secret_bl);
-  secret_req.append_header("Accept", "application/octet-stream");
-  secret_req.append_header("X-Auth-Token", barbican_token);
-
-  res = secret_req.process("GET", secret_url.c_str());
-  if (res < 0) {
-    return res;
-  }
-  if (secret_req.get_http_status() ==
-      RGWHTTPTransceiver::HTTP_STATUS_UNAUTHORIZED) {
-    return -EACCES;
-  }
-
-  if (secret_req.get_http_status() >=200 &&
-      secret_req.get_http_status() < 300 &&
-      secret_bl.length() == AES_256_KEYSIZE) {
-    actual_key.assign(secret_bl.c_str(), secret_bl.length());
-    memset(secret_bl.c_str(), 0, secret_bl.length());
-    } else {
-      res = -EACCES;
-    }
-  return res;
-}
-
-static map<string,string> get_str_map(const string &str) {
-  map<string,string> m;
-  get_str_map(str, &m, ";, \t");
-  return m;
-}
-
-static int get_actual_key_from_kms(CephContext *cct,
-                            boost::string_view key_id,
-                            boost::string_view key_selector,
-                            std::string& actual_key)
-{
-  int res = 0;
-  ldout(cct, 20) << "Getting KMS encryption key for key=" << key_id << dendl;
-  static map<string,string> str_map = get_str_map(
-      cct->_conf->rgw_crypt_s3_kms_encryption_keys);
-
-  map<string, string>::iterator it = str_map.find(std::string(key_id));
-  if (it != str_map.end() ) {
-    std::string master_key;
-    try {
-      master_key = from_base64((*it).second);
-    } catch (...) {
-      ldout(cct, 5) << "ERROR: get_actual_key_from_kms invalid encryption key id "
-                    << "which contains character that is not base64 encoded."
-                    << dendl;
-      return -EINVAL;
-    }
-
-    if (master_key.length() == AES_256_KEYSIZE) {
-      uint8_t _actual_key[AES_256_KEYSIZE];
-      if (AES_256_ECB_encrypt(cct,
-          reinterpret_cast<const uint8_t*>(master_key.c_str()), AES_256_KEYSIZE,
-          reinterpret_cast<const uint8_t*>(key_selector.data()),
-          _actual_key, AES_256_KEYSIZE)) {
-        actual_key = std::string((char*)&_actual_key[0], AES_256_KEYSIZE);
-      } else {
-        res = -EIO;
-      }
-      memset(_actual_key, 0, sizeof(_actual_key));
-    } else {
-      ldout(cct, 20) << "Wrong size for key=" << key_id << dendl;
-      res = -EIO;
-    }
-  } else {
-    std::string token;
-    if (rgw::keystone::Service::get_keystone_barbican_token(cct, token) < 0) {
-      ldout(cct, 5) << "Failed to retrieve token for barbican" << dendl;
-      res = -EINVAL;
-      return res;
-    }
-
-    res = request_key_from_barbican(cct, key_id, key_selector, token, actual_key);
-    if (res != 0) {
-      ldout(cct, 5) << "Failed to retrieve secret from barbican:" << key_id << dendl;
-    }
-  }
-  return res;
-}
-
-static inline void set_attr(map<string, bufferlist>& attrs,
-                            const char* key,
-                            boost::string_view value)
-{
-  bufferlist bl;
-  bl.append(value.data(), value.size());
-  attrs[key] = std::move(bl);
-}
-
-static inline std::string get_str_attribute(map<string, bufferlist>& attrs,
-                                            const char *name)
-{
-  auto iter = attrs.find(name);
-  if (iter == attrs.end()) {
-    return {};
-  }
-  return iter->second.to_str();
-}
-
-typedef enum {
-  X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM=0,
-  X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY,
-  X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5,
-  X_AMZ_SERVER_SIDE_ENCRYPTION,
-  X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID,
-  X_AMZ_SERVER_SIDE_ENCRYPTION_LAST
-} crypt_option_e;
-
-typedef struct {
-  const char* http_header_name;
-  const std::string post_part_name;
-} crypt_option_names;
-
-static const crypt_option_names crypt_options[] = {
-    {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM",  "x-amz-server-side-encryption-customer-algorithm"},
-    {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY",        "x-amz-server-side-encryption-customer-key"},
-    {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5",    "x-amz-server-side-encryption-customer-key-md5"},
-    {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION",                     "x-amz-server-side-encryption"},
-    {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID",      "x-amz-server-side-encryption-aws-kms-key-id"},
-};
-
-static boost::string_view get_crypt_attribute(
-    const RGWEnv* env,
-    std::map<std::string,
-             RGWPostObj_ObjStore::post_form_part,
-             const ltstr_nocase>* parts,
-    crypt_option_e option)
-{
-  static_assert(
-      X_AMZ_SERVER_SIDE_ENCRYPTION_LAST == sizeof(crypt_options)/sizeof(*crypt_options),
-      "Missing items in crypt_options");
-  if (parts != nullptr) {
-    auto iter
-      = parts->find(crypt_options[option].post_part_name);
-    if (iter == parts->end())
-      return boost::string_view();
-    bufferlist& data = iter->second.data;
-    boost::string_view str = boost::string_view(data.c_str(), data.length());
-    return rgw_trim_whitespace(str);
-  } else {
-    const char* hdr = env->get(crypt_options[option].http_header_name, nullptr);
-    if (hdr != nullptr) {
-      return boost::string_view(hdr);
-    } else {
-      return boost::string_view();
-    }
-  }
-}
-
-
-int rgw_s3_prepare_encrypt(struct req_state* s,
-                           std::map<std::string, ceph::bufferlist>& attrs,
-                           std::map<std::string,
-                                    RGWPostObj_ObjStore::post_form_part,
-                                    const ltstr_nocase>* parts,
-                           std::unique_ptr<BlockCrypt>* block_crypt,
-                           std::map<std::string, std::string>& crypt_http_responses)
-{
-  int res = 0;
-  crypt_http_responses.clear();
-  {
-    boost::string_view req_sse_ca =
-        get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM);
-    if (! req_sse_ca.empty()) {
-      if (req_sse_ca != "AES256") {
-        ldout(s->cct, 5) << "ERROR: Invalid value for header "
-                         << "x-amz-server-side-encryption-customer-algorithm"
-                         << dendl;
-        s->err.message = "The requested encryption algorithm is not valid, must be AES256.";
-        return -ERR_INVALID_ENCRYPTION_ALGORITHM;
-      }
-      if (s->cct->_conf->rgw_crypt_require_ssl &&
-          !s->info.env->exists("SERVER_PORT_SECURE")) {
-        ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
-        return -ERR_INVALID_REQUEST;
-      }
-
-      std::string key_bin;
-      try {
-        key_bin = from_base64(
-          get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY) );
-      } catch (...) {
-        ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid encryption "
-                         << "key which contains character that is not base64 encoded."
-                         << dendl;
-        s->err.message = "Requests specifying Server Side Encryption with Customer "
-                         "provided keys must provide an appropriate secret key.";
-        return -EINVAL;
-      }
-
-      if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
-        ldout(s->cct, 5) << "ERROR: invalid encryption key size" << dendl;
-        s->err.message = "Requests specifying Server Side Encryption with Customer "
-                         "provided keys must provide an appropriate secret key.";
-        return -EINVAL;
-      }
-
-      boost::string_view keymd5 =
-          get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
-
-      std::string keymd5_bin;
-      try {
-        keymd5_bin = from_base64(keymd5);
-      } catch (...) {
-        ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid encryption key "
-                         << "md5 which contains character that is not base64 encoded."
-                         << dendl;
-        s->err.message = "Requests specifying Server Side Encryption with Customer "
-                         "provided keys must provide an appropriate secret key md5.";
-        return -EINVAL;
-      }
-
-      if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
-        ldout(s->cct, 5) << "ERROR: Invalid key md5 size" << dendl;
-        s->err.message = "Requests specifying Server Side Encryption with Customer "
-                         "provided keys must provide an appropriate secret key md5.";
-        return -EINVAL;
-      }
-
-      MD5 key_hash;
-      byte key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
-      key_hash.Update(reinterpret_cast<const byte*>(key_bin.c_str()), key_bin.size());
-      key_hash.Final(key_hash_res);
-
-      if (memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) {
-        ldout(s->cct, 5) << "ERROR: Invalid key md5 hash" << dendl;
-        s->err.message = "The calculated MD5 hash of the key did not match the hash that was provided.";
-        return -EINVAL;
-      }
-
-      set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-C-AES256");
-      set_attr(attrs, RGW_ATTR_CRYPT_KEYMD5, keymd5_bin);
-
-      if (block_crypt) {
-        auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
-        aes->set_key(reinterpret_cast<const uint8_t*>(key_bin.c_str()), AES_256_KEYSIZE);
-        *block_crypt = std::move(aes);
-      }
-
-      crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
-      crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5.to_string();
-      return 0;
-    } else {
-      boost::string_view customer_key =
-          get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY);
-      if (!customer_key.empty()) {
-        ldout(s->cct, 5) << "ERROR: SSE-C encryption request is missing the header "
-                         << "x-amz-server-side-encryption-customer-algorithm"
-                         << dendl;
-        s->err.message = "Requests specifying Server Side Encryption with Customer "
-                         "provided keys must provide a valid encryption algorithm.";
-        return -EINVAL;
-      }
-
-      boost::string_view customer_key_md5 =
-          get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
-      if (!customer_key_md5.empty()) {
-        ldout(s->cct, 5) << "ERROR: SSE-C encryption request is missing the header "
-                         << "x-amz-server-side-encryption-customer-algorithm"
-                         << dendl;
-        s->err.message = "Requests specifying Server Side Encryption with Customer "
-                         "provided keys must provide a valid encryption algorithm.";
-        return -EINVAL;
-      }
-    }
-
-    /* AMAZON server side encryption with KMS (key management service) */
-    boost::string_view req_sse =
-        get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION);
-    if (! req_sse.empty()) {
-      if (req_sse != "aws:kms") {
-        ldout(s->cct, 5) << "ERROR: Invalid value for header x-amz-server-side-encryption"
-                         << dendl;
-        s->err.message = "Server Side Encryption with KMS managed key requires "
-                         "HTTP header x-amz-server-side-encryption : aws:kms";
-        return -EINVAL;
-      }
-      if (s->cct->_conf->rgw_crypt_require_ssl &&
-          !s->info.env->exists("SERVER_PORT_SECURE")) {
-        ldout(s->cct, 5) << "ERROR: insecure request, rgw_crypt_require_ssl is set" << dendl;
-        return -ERR_INVALID_REQUEST;
-      }
-      boost::string_view key_id =
-          get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
-      if (key_id.empty()) {
-        ldout(s->cct, 5) << "ERROR: not provide a valid key id" << dendl;
-        s->err.message = "Server Side Encryption with KMS managed key requires "
-                         "HTTP header x-amz-server-side-encryption-aws-kms-key-id";
-        return -ERR_INVALID_ACCESS_KEY;
-      }
-      /* try to retrieve actual key */
-      std::string key_selector = create_random_key_selector(s->cct);
-      std::string actual_key;
-      res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
-      if (res != 0) {
-        ldout(s->cct, 5) << "ERROR: failed to retrieve actual key from key_id: " << key_id << dendl;
-        s->err.message = "Failed to retrieve the actual key, kms-keyid: " + key_id.to_string();
-        return res;
-      }
-      if (actual_key.size() != AES_256_KEYSIZE) {
-        ldout(s->cct, 5) << "ERROR: key obtained from key_id:" <<
-            key_id << " is not 256 bit size" << dendl;
-        s->err.message = "KMS provided an invalid key for the given kms-keyid.";
-        return -ERR_INVALID_ACCESS_KEY;
-      }
-      set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-KMS");
-      set_attr(attrs, RGW_ATTR_CRYPT_KEYID, key_id);
-      set_attr(attrs, RGW_ATTR_CRYPT_KEYSEL, key_selector);
-
-      if (block_crypt) {
-        auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
-        aes->set_key(reinterpret_cast<const uint8_t*>(actual_key.c_str()), AES_256_KEYSIZE);
-        *block_crypt = std::move(aes);
-      }
-      actual_key.replace(0, actual_key.length(), actual_key.length(), '\000');
-
-      crypt_http_responses["x-amz-server-side-encryption"] = "aws:kms";
-      crypt_http_responses["x-amz-server-side-encryption-aws-kms-key-id"] = key_id.to_string();
-      return 0;
-    } else {
-      boost::string_view key_id =
-          get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
-      if (!key_id.empty()) {
-        ldout(s->cct, 5) << "ERROR: SSE-KMS encryption request is missing the header "
-                         << "x-amz-server-side-encryption"
-                         << dendl;
-        s->err.message = "Server Side Encryption with KMS managed key requires "
-                         "HTTP header x-amz-server-side-encryption : aws:kms";
-        return -EINVAL;
-      }
-    }
-
-    /* no other encryption mode, check if default encryption is selected */
-    if (s->cct->_conf->rgw_crypt_default_encryption_key != "") {
-      std::string master_encryption_key;
-      try {
-        master_encryption_key = from_base64(s->cct->_conf->rgw_crypt_default_encryption_key);
-      } catch (...) {
-        ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid default encryption key "
-                         << "which contains character that is not base64 encoded."
-                         << dendl;
-        s->err.message = "Requests specifying Server Side Encryption with Customer "
-                         "provided keys must provide an appropriate secret key.";
-        return -EINVAL;
-      }
-
-      if (master_encryption_key.size() != 256 / 8) {
-        ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
-        /* not an error to return; missing encryption does not inhibit processing */
-        return 0;
-      }
-
-      set_attr(attrs, RGW_ATTR_CRYPT_MODE, "RGW-AUTO");
-      std::string key_selector = create_random_key_selector(s->cct);
-      set_attr(attrs, RGW_ATTR_CRYPT_KEYSEL, key_selector);
-
-      uint8_t actual_key[AES_256_KEYSIZE];
-      if (AES_256_ECB_encrypt(s->cct,
-                              reinterpret_cast<const uint8_t*>(master_encryption_key.c_str()), AES_256_KEYSIZE,
-                              reinterpret_cast<const uint8_t*>(key_selector.c_str()),
-                              actual_key, AES_256_KEYSIZE) != true) {
-        memset(actual_key, 0, sizeof(actual_key));
-        return -EIO;
-      }
-      if (block_crypt) {
-        auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
-        aes->set_key(reinterpret_cast<const uint8_t*>(actual_key), AES_256_KEYSIZE);
-        *block_crypt = std::move(aes);
-      }
-      memset(actual_key, 0, sizeof(actual_key));
-      return 0;
-    }
-  }
-  /*no encryption*/
-  return 0;
-}
-
-
-int rgw_s3_prepare_decrypt(struct req_state* s,
-                       map<string, bufferlist>& attrs,
-                       std::unique_ptr<BlockCrypt>* block_crypt,
-                       std::map<std::string, std::string>& crypt_http_responses)
-{
-  int res = 0;
-  std::string stored_mode = get_str_attribute(attrs, RGW_ATTR_CRYPT_MODE);
-  ldout(s->cct, 15) << "Encryption mode: " << stored_mode << dendl;
-
-  const char *req_sse = s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION", NULL);
-  if (nullptr != req_sse && (s->op == OP_GET || s->op == OP_HEAD)) {
-    return -ERR_INVALID_REQUEST;
-  }
-
-  if (stored_mode == "SSE-C-AES256") {
-    if (s->cct->_conf->rgw_crypt_require_ssl &&
-        !s->info.env->exists("SERVER_PORT_SECURE")) {
-      ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
-      return -ERR_INVALID_REQUEST;
-    }
-    const char *req_cust_alg =
-        s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM", NULL);
-
-    if (nullptr == req_cust_alg)  {
-      ldout(s->cct, 5) << "ERROR: Request for SSE-C encrypted object missing "
-                       << "x-amz-server-side-encryption-customer-algorithm"
-                       << dendl;
-      s->err.message = "Requests specifying Server Side Encryption with Customer "
-                       "provided keys must provide a valid encryption algorithm.";
-      return -EINVAL;
-    } else if (strcmp(req_cust_alg, "AES256") != 0) {
-      ldout(s->cct, 5) << "ERROR: The requested encryption algorithm is not valid, must be AES256." << dendl;
-      s->err.message = "The requested encryption algorithm is not valid, must be AES256.";
-      return -ERR_INVALID_ENCRYPTION_ALGORITHM;
-    }
-
-    std::string key_bin;
-    try {
-      key_bin = from_base64(s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY", ""));
-    } catch (...) {
-      ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid encryption key "
-                       << "which contains character that is not base64 encoded."
-                       << dendl;
-      s->err.message = "Requests specifying Server Side Encryption with Customer "
-                       "provided keys must provide an appropriate secret key.";
-      return -EINVAL;
-    }
-
-    if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
-      ldout(s->cct, 5) << "ERROR: Invalid encryption key size" << dendl;
-      s->err.message = "Requests specifying Server Side Encryption with Customer "
-                       "provided keys must provide an appropriate secret key.";
-      return -EINVAL;
-    }
-
-    std::string keymd5 =
-        s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5", "");
-    std::string keymd5_bin;
-    try {
-      keymd5_bin = from_base64(keymd5);
-    } catch (...) {
-      ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid encryption key md5 "
-                       << "which contains character that is not base64 encoded."
-                       << dendl;
-      s->err.message = "Requests specifying Server Side Encryption with Customer "
-                       "provided keys must provide an appropriate secret key md5.";
-      return -EINVAL;
-    }
-
-
-    if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
-      ldout(s->cct, 5) << "ERROR: Invalid key md5 size " << dendl;
-      s->err.message = "Requests specifying Server Side Encryption with Customer "
-                       "provided keys must provide an appropriate secret key md5.";
-      return -EINVAL;
-    }
-
-    MD5 key_hash;
-    uint8_t key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
-    key_hash.Update(reinterpret_cast<const byte*>(key_bin.c_str()), key_bin.size());
-    key_hash.Final(key_hash_res);
-
-    if ((memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) ||
-        (get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYMD5) != keymd5_bin)) {
-      s->err.message = "The calculated MD5 hash of the key did not match the hash that was provided.";
-      return -EINVAL;
-    }
-    auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
-    aes->set_key(reinterpret_cast<const uint8_t*>(key_bin.c_str()), AES_256_CBC::AES_256_KEYSIZE);
-    if (block_crypt) *block_crypt = std::move(aes);
-
-    crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
-    crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5;
-    return 0;
-  }
-
-  if (stored_mode == "SSE-KMS") {
-    if (s->cct->_conf->rgw_crypt_require_ssl &&
-        !s->info.env->exists("SERVER_PORT_SECURE")) {
-      ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
-      return -ERR_INVALID_REQUEST;
-    }
-    /* try to retrieve actual key */
-    std::string key_id = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYID);
-    std::string key_selector = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYSEL);
-    std::string actual_key;
-    res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
-    if (res != 0) {
-      ldout(s->cct, 10) << "ERROR: failed to retrieve actual key from key_id: " << key_id << dendl;
-      s->err.message = "Failed to retrieve the actual key, kms-keyid: " + key_id;
-      return res;
-    }
-    if (actual_key.size() != AES_256_KEYSIZE) {
-      ldout(s->cct, 0) << "ERROR: key obtained from key_id:" <<
-          key_id << " is not 256 bit size" << dendl;
-      s->err.message = "KMS provided an invalid key for the given kms-keyid.";
-      return -ERR_INVALID_ACCESS_KEY;
-    }
-
-    auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
-    aes->set_key(reinterpret_cast<const uint8_t*>(actual_key.c_str()), AES_256_KEYSIZE);
-    actual_key.replace(0, actual_key.length(), actual_key.length(), '\000');
-    if (block_crypt) *block_crypt = std::move(aes);
-
-    crypt_http_responses["x-amz-server-side-encryption"] = "aws:kms";
-    crypt_http_responses["x-amz-server-side-encryption-aws-kms-key-id"] = key_id;
-    return 0;
-  }
-
-  if (stored_mode == "RGW-AUTO") {
-    std::string master_encryption_key;
-    try {
-      master_encryption_key = from_base64(std::string(s->cct->_conf->rgw_crypt_default_encryption_key));
-    } catch (...) {
-      ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid default encryption key "
-                       << "which contains character that is not base64 encoded."
-                       << dendl;
-      s->err.message = "The default encryption key is not valid base64.";
-      return -EINVAL;
-    }
-
-    if (master_encryption_key.size() != 256 / 8) {
-      ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
-      return -EIO;
-    }
-    std::string attr_key_selector = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYSEL);
-    if (attr_key_selector.size() != AES_256_CBC::AES_256_KEYSIZE) {
-      ldout(s->cct, 0) << "ERROR: missing or invalid " RGW_ATTR_CRYPT_KEYSEL << dendl;
-      return -EIO;
-    }
-    uint8_t actual_key[AES_256_KEYSIZE];
-    if (AES_256_ECB_encrypt(s->cct,
-                            reinterpret_cast<const uint8_t*>(master_encryption_key.c_str()),
-                            AES_256_KEYSIZE,
-                            reinterpret_cast<const uint8_t*>(attr_key_selector.c_str()),
-                            actual_key, AES_256_KEYSIZE) != true) {
-      memset(actual_key, 0, sizeof(actual_key));
-      return -EIO;
-    }
-    auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
-    aes->set_key(actual_key, AES_256_KEYSIZE);
-    memset(actual_key, 0, sizeof(actual_key));
-    if (block_crypt) *block_crypt = std::move(aes);
-    return 0;
-  }
-  /*no decryption*/
-  return 0;
-}