1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Crypto filters for Put/Post/Get operations.
6 #include <rgw/rgw_op.h>
7 #include <rgw/rgw_crypt.h>
8 #include <auth/Crypto.h>
9 #include <rgw/rgw_b64.h>
10 #include <rgw/rgw_rest_s3.h>
11 #include "include/assert.h"
12 #include <boost/utility/string_view.hpp>
13 #include <rgw/rgw_keystone.h>
14 #include "include/str_map.h"
15 #include "crypto/crypto_accel.h"
16 #include "crypto/crypto_plugin.h"
24 #include <cryptopp/cryptlib.h>
25 #include <cryptopp/modes.h>
26 #include <cryptopp/aes.h>
27 using namespace CryptoPP;
30 #define dout_context g_ceph_context
31 #define dout_subsys ceph_subsys_rgw
36 * Encryption in CTR mode. offset is used as IV for each block.
38 #warning "TODO: move this code to auth/Crypto for others to reuse."
40 class AES_256_CTR : public BlockCrypt {
42 static const size_t AES_256_KEYSIZE = 256 / 8;
43 static const size_t AES_256_IVSIZE = 128 / 8;
45 static const uint8_t IV[AES_256_IVSIZE];
47 uint8_t key[AES_256_KEYSIZE];
49 AES_256_CTR(CephContext* cct): cct(cct) {
52 memset(key, 0, AES_256_KEYSIZE);
54 bool set_key(const uint8_t* _key, size_t key_size) {
55 if (key_size != AES_256_KEYSIZE) {
58 memcpy(key, _key, AES_256_KEYSIZE);
61 size_t get_block_size() {
62 return AES_256_IVSIZE;
67 bool encrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset) {
68 byte iv[AES_256_IVSIZE];
70 << "Encrypt in_ofs " << in_ofs
72 << " stream_offset=" << stream_offset
74 if (input.length() < in_ofs + size) {
79 buffer::ptr buf((size + AES_256_KEYSIZE - 1) / AES_256_KEYSIZE * AES_256_KEYSIZE);
81 prepare_iv(iv, stream_offset);
82 CTR_Mode< AES >::Encryption e;
83 e.SetKeyWithIV(key, AES_256_KEYSIZE, iv, AES_256_IVSIZE);
85 e.ProcessData((byte*)buf.c_str(), (byte*)buf.c_str(), buf.length());
87 off_t plaintext_pos = in_ofs;
89 auto iter = input.buffers().begin();
90 //skip unaffected begin
91 while ((iter != input.buffers().end()) && (plaintext_pos >= iter->length())) {
92 plaintext_pos -= iter->length();
95 while (iter != input.buffers().end()) {
96 off_t cnt = std::min<off_t>(iter->length() - plaintext_pos, size - crypt_pos);
97 byte* src = (byte*)iter->c_str() + plaintext_pos;
98 byte* dst = (byte*)buf.c_str() + crypt_pos;
99 for (off_t i = 0; i < cnt; i++) {
110 #elif defined(USE_NSS)
112 bool encrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset)
118 CK_AES_CTR_PARAMS ctr_params = {0};
124 unsigned int written2;
126 slot = PK11_GetBestSlot(CKM_AES_CTR, NULL);
128 keyItem.type = siBuffer;
130 keyItem.len = AES_256_KEYSIZE;
132 symkey = PK11_ImportSymKey(slot, CKM_AES_CTR, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
134 static_assert(sizeof(ctr_params.cb) >= AES_256_IVSIZE, "Must fit counter");
135 ctr_params.ulCounterBits = 128;
136 prepare_iv(reinterpret_cast<unsigned char*>(&ctr_params.cb), stream_offset);
138 ivItem.type = siBuffer;
139 ivItem.data = (unsigned char*)&ctr_params;
140 ivItem.len = sizeof(ctr_params);
142 param = PK11_ParamFromIV(CKM_AES_CTR, &ivItem);
144 ectx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, symkey, param);
146 buffer::ptr buf((size + AES_256_KEYSIZE - 1) / AES_256_KEYSIZE * AES_256_KEYSIZE);
147 ret = PK11_CipherOp(ectx,
148 (unsigned char*)buf.c_str(), &written, buf.length(),
149 (unsigned char*)input.c_str() + in_ofs, size);
150 if (ret == SECSuccess) {
151 ret = PK11_DigestFinal(ectx,
152 (unsigned char*)buf.c_str() + written, &written2,
153 buf.length() - written);
154 if (ret == SECSuccess) {
155 buf.set_length(written + written2);
160 PK11_DestroyContext(ectx, PR_TRUE);
162 SECITEM_FreeItem(param, PR_TRUE);
164 PK11_FreeSymKey(symkey);
168 if (result == false) {
169 ldout(cct, 5) << "Failed to perform AES-CTR encryption: " << PR_GetError() << dendl;
175 #error Must define USE_CRYPTOPP or USE_NSS
177 /* in CTR encrypt is the same as decrypt */
178 bool decrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset) {
179 return encrypt(input, in_ofs, size, output, stream_offset);
182 void prepare_iv(byte iv[AES_256_IVSIZE], off_t offset) {
183 off_t index = offset / AES_256_IVSIZE;
184 off_t i = AES_256_IVSIZE - 1;
186 unsigned int carry = 0;
188 val = (index & 0xff) + IV[i] + carry;
197 const uint8_t AES_256_CTR::IV[AES_256_CTR::AES_256_IVSIZE] =
198 { 'a', 'e', 's', '2', '5', '6', 'i', 'v', '_', 'c', 't', 'r', '1', '3', '3', '7' };
201 CryptoAccelRef get_crypto_accel(CephContext *cct)
203 CryptoAccelRef ca_impl = nullptr;
205 PluginRegistry *reg = cct->get_plugin_registry();
206 string crypto_accel_type = cct->_conf->plugin_crypto_accelerator;
208 CryptoPlugin *factory = dynamic_cast<CryptoPlugin*>(reg->get_with_load("crypto", crypto_accel_type));
209 if (factory == nullptr) {
210 lderr(cct) << __func__ << " cannot load crypto accelerator of type " << crypto_accel_type << dendl;
213 int err = factory->factory(&ca_impl, &ss);
215 lderr(cct) << __func__ << " factory return error " << err <<
216 " with description: " << ss.str() << dendl;
223 * Encryption in CBC mode. Chunked to 4K blocks. Offset is used as IV for each 4K block.
228 * 1. Input is split to 4K chunks + remainder in one, smaller chunk
229 * 2. Each full chunk is encrypted separately with CBC chained mode, with initial IV derived from offset
230 * 3. Last chunk is 16*m + n.
231 * 4. 16*m bytes are encrypted with CBC chained mode, with initial IV derived from offset
232 * 5. Last n bytes are xor-ed with pattern obtained by CBC encryption of
233 * last encrypted 16 byte block <16m-16, 16m-15) with IV = {0}.
234 * 6. (Special case) If m == 0 then last n bytes are xor-ed with pattern
235 * obtained by CBC encryption of {0} with IV derived from offset
238 * 1. Input is split to 4K chunks + remainder in one, smaller chunk
239 * 2. Each full chunk is decrypted separately with CBC chained mode, with initial IV derived from offset
240 * 3. Last chunk is 16*m + n.
241 * 4. 16*m bytes are decrypted with CBC chained mode, with initial IV derived from offset
242 * 5. Last n bytes are xor-ed with pattern obtained by CBC ENCRYPTION of
243 * last (still encrypted) 16 byte block <16m-16,16m-15) with IV = {0}
244 * 6. (Special case) If m == 0 then last n bytes are xor-ed with pattern
245 * obtained by CBC ENCRYPTION of {0} with IV derived from offset
247 #warning "TODO: use auth/Crypto instead of reimplementing."
248 class AES_256_CBC : public BlockCrypt {
250 static const size_t AES_256_KEYSIZE = 256 / 8;
251 static const size_t AES_256_IVSIZE = 128 / 8;
252 static const size_t CHUNK_SIZE = 4096;
254 static const uint8_t IV[AES_256_IVSIZE];
256 uint8_t key[AES_256_KEYSIZE];
258 AES_256_CBC(CephContext* cct): cct(cct) {
261 memset(key, 0, AES_256_KEYSIZE);
263 bool set_key(const uint8_t* _key, size_t key_size) {
264 if (key_size != AES_256_KEYSIZE) {
267 memcpy(key, _key, AES_256_KEYSIZE);
270 size_t get_block_size() {
276 bool cbc_transform(unsigned char* out,
277 const unsigned char* in,
279 const unsigned char (&iv)[AES_256_IVSIZE],
280 const unsigned char (&key)[AES_256_KEYSIZE],
284 CBC_Mode< AES >::Encryption e;
285 e.SetKeyWithIV(key, AES_256_KEYSIZE, iv, AES_256_IVSIZE);
286 e.ProcessData((byte*)out, (byte*)in, size);
288 CBC_Mode< AES >::Decryption d;
289 d.SetKeyWithIV(key, AES_256_KEYSIZE, iv, AES_256_IVSIZE);
290 d.ProcessData((byte*)out, (byte*)in, size);
295 #elif defined(USE_NSS)
297 bool cbc_transform(unsigned char* out,
298 const unsigned char* in,
300 const unsigned char (&iv)[AES_256_IVSIZE],
301 const unsigned char (&key)[AES_256_KEYSIZE],
308 CK_AES_CBC_ENCRYPT_DATA_PARAMS ctr_params = {0};
315 slot = PK11_GetBestSlot(CKM_AES_CBC, NULL);
317 keyItem.type = siBuffer;
318 keyItem.data = const_cast<unsigned char*>(&key[0]);
319 keyItem.len = AES_256_KEYSIZE;
320 symkey = PK11_ImportSymKey(slot, CKM_AES_CBC, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
322 memcpy(ctr_params.iv, iv, AES_256_IVSIZE);
323 ivItem.type = siBuffer;
324 ivItem.data = (unsigned char*)&ctr_params;
325 ivItem.len = sizeof(ctr_params);
327 param = PK11_ParamFromIV(CKM_AES_CBC, &ivItem);
329 ectx = PK11_CreateContextBySymKey(CKM_AES_CBC, encrypt?CKA_ENCRYPT:CKA_DECRYPT, symkey, param);
331 ret = PK11_CipherOp(ectx,
334 if ((ret == SECSuccess) && (written == (int)size)) {
337 PK11_DestroyContext(ectx, PR_TRUE);
339 SECITEM_FreeItem(param, PR_TRUE);
341 PK11_FreeSymKey(symkey);
345 if (result == false) {
346 ldout(cct, 5) << "Failed to perform AES-CBC encryption: " << PR_GetError() << dendl;
352 #error Must define USE_CRYPTOPP or USE_NSS
355 bool cbc_transform(unsigned char* out,
356 const unsigned char* in,
359 const unsigned char (&key)[AES_256_KEYSIZE],
362 static std::atomic<bool> failed_to_get_crypto(false);
363 CryptoAccelRef crypto_accel;
364 if (! failed_to_get_crypto.load())
366 crypto_accel = get_crypto_accel(cct);
368 failed_to_get_crypto = true;
371 unsigned char iv[AES_256_IVSIZE];
372 for (size_t offset = 0; result && (offset < size); offset += CHUNK_SIZE) {
373 size_t process_size = offset + CHUNK_SIZE <= size ? CHUNK_SIZE : size - offset;
374 prepare_iv(iv, stream_offset + offset);
375 if (crypto_accel != nullptr) {
377 result = crypto_accel->cbc_encrypt(out + offset, in + offset,
378 process_size, iv, key);
380 result = crypto_accel->cbc_decrypt(out + offset, in + offset,
381 process_size, iv, key);
384 result = cbc_transform(
385 out + offset, in + offset, process_size,
393 bool encrypt(bufferlist& input,
400 size_t aligned_size = size / AES_256_IVSIZE * AES_256_IVSIZE;
401 size_t unaligned_rest_size = size - aligned_size;
403 buffer::ptr buf(aligned_size + AES_256_IVSIZE);
404 unsigned char* buf_raw = reinterpret_cast<unsigned char*>(buf.c_str());
405 const unsigned char* input_raw = reinterpret_cast<const unsigned char*>(input.c_str());
407 /* encrypt main bulk of data */
408 result = cbc_transform(buf_raw,
411 stream_offset, key, true);
412 if (result && (unaligned_rest_size > 0)) {
413 /* remainder to encrypt */
414 if (aligned_size % CHUNK_SIZE > 0) {
415 /* use last chunk for unaligned part */
416 unsigned char iv[AES_256_IVSIZE] = {0};
417 result = cbc_transform(buf_raw + aligned_size,
418 buf_raw + aligned_size - AES_256_IVSIZE,
422 /* 0 full blocks in current chunk, use IV as base for unaligned part */
423 unsigned char iv[AES_256_IVSIZE] = {0};
424 unsigned char data[AES_256_IVSIZE];
425 prepare_iv(data, stream_offset + aligned_size);
426 result = cbc_transform(buf_raw + aligned_size,
432 for(size_t i = aligned_size; i < size; i++) {
433 *(buf_raw + i) ^= *(input_raw + in_ofs + i);
438 ldout(cct, 25) << "Encrypted " << size << " bytes"<< dendl;
439 buf.set_length(size);
442 ldout(cct, 5) << "Failed to encrypt" << dendl;
448 bool decrypt(bufferlist& input,
455 size_t aligned_size = size / AES_256_IVSIZE * AES_256_IVSIZE;
456 size_t unaligned_rest_size = size - aligned_size;
458 buffer::ptr buf(aligned_size + AES_256_IVSIZE);
459 unsigned char* buf_raw = reinterpret_cast<unsigned char*>(buf.c_str());
460 unsigned char* input_raw = reinterpret_cast<unsigned char*>(input.c_str());
462 /* decrypt main bulk of data */
463 result = cbc_transform(buf_raw,
466 stream_offset, key, false);
467 if (result && unaligned_rest_size > 0) {
468 /* remainder to decrypt */
469 if (aligned_size % CHUNK_SIZE > 0) {
470 /*use last chunk for unaligned part*/
471 unsigned char iv[AES_256_IVSIZE] = {0};
472 result = cbc_transform(buf_raw + aligned_size,
473 input_raw + in_ofs + aligned_size - AES_256_IVSIZE,
477 /* 0 full blocks in current chunk, use IV as base for unaligned part */
478 unsigned char iv[AES_256_IVSIZE] = {0};
479 unsigned char data[AES_256_IVSIZE];
480 prepare_iv(data, stream_offset + aligned_size);
481 result = cbc_transform(buf_raw + aligned_size,
487 for(size_t i = aligned_size; i < size; i++) {
488 *(buf_raw + i) ^= *(input_raw + in_ofs + i);
493 ldout(cct, 25) << "Decrypted " << size << " bytes"<< dendl;
494 buf.set_length(size);
497 ldout(cct, 5) << "Failed to decrypt" << dendl;
503 void prepare_iv(byte (&iv)[AES_256_IVSIZE], off_t offset) {
504 off_t index = offset / AES_256_IVSIZE;
505 off_t i = AES_256_IVSIZE - 1;
507 unsigned int carry = 0;
509 val = (index & 0xff) + IV[i] + carry;
519 std::unique_ptr<BlockCrypt> AES_256_CBC_create(CephContext* cct, const uint8_t* key, size_t len)
521 auto cbc = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(cct));
522 cbc->set_key(key, AES_256_KEYSIZE);
523 return std::move(cbc);
527 const uint8_t AES_256_CBC::IV[AES_256_CBC::AES_256_IVSIZE] =
528 { 'a', 'e', 's', '2', '5', '6', 'i', 'v', '_', 'c', 't', 'r', '1', '3', '3', '7' };
533 bool AES_256_ECB_encrypt(CephContext* cct,
536 const uint8_t* data_in,
541 if (key_size == AES_256_KEYSIZE) {
543 ECB_Mode< AES >::Encryption e;
544 e.SetKey( key, key_size );
545 e.ProcessData(data_out, data_in, data_size);
547 } catch( CryptoPP::Exception& ex ) {
548 ldout(cct, 5) << "AES-ECB encryption failed with: " << ex.GetWhat() << dendl;
554 #elif defined USE_NSS
556 bool AES_256_ECB_encrypt(CephContext* cct,
559 const uint8_t* data_in,
570 unsigned int written2;
571 if (key_size == AES_256_KEYSIZE) {
572 slot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
574 keyItem.type = siBuffer;
575 keyItem.data = const_cast<uint8_t*>(key);
576 keyItem.len = AES_256_KEYSIZE;
578 param = PK11_ParamFromIV(CKM_AES_ECB, NULL);
580 symkey = PK11_ImportSymKey(slot, CKM_AES_ECB, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
582 ectx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, symkey, param);
584 ret = PK11_CipherOp(ectx,
585 data_out, &written, data_size,
587 if (ret == SECSuccess) {
588 ret = PK11_DigestFinal(ectx,
589 data_out + written, &written2,
590 data_size - written);
591 if (ret == SECSuccess) {
595 PK11_DestroyContext(ectx, PR_TRUE);
597 PK11_FreeSymKey(symkey);
599 SECITEM_FreeItem(param, PR_TRUE);
603 if (result == false) {
604 ldout(cct, 5) << "Failed to perform AES-ECB encryption: " << PR_GetError() << dendl;
607 ldout(cct, 5) << "Key size must be 256 bits long" << dendl;
613 #error Must define USE_CRYPTOPP or USE_NSS
617 RGWGetObj_BlockDecrypt::RGWGetObj_BlockDecrypt(CephContext* cct,
619 std::unique_ptr<BlockCrypt> crypt):
620 RGWGetObj_Filter(next),
622 crypt(std::move(crypt)),
628 block_size = this->crypt->get_block_size();
631 RGWGetObj_BlockDecrypt::~RGWGetObj_BlockDecrypt() {
634 int RGWGetObj_BlockDecrypt::read_manifest(bufferlist& manifest_bl) {
636 RGWObjManifest manifest;
637 if (manifest_bl.length()) {
638 bufferlist::iterator miter = manifest_bl.begin();
640 ::decode(manifest, miter);
641 } catch (buffer::error& err) {
642 ldout(cct, 0) << "ERROR: couldn't decode manifest" << dendl;
645 RGWObjManifest::obj_iterator mi;
646 for (mi = manifest.obj_begin(); mi != manifest.obj_end(); ++mi) {
647 if (mi.get_cur_stripe() == 0) {
648 parts_len.push_back(0);
650 parts_len.back() += mi.get_stripe_size();
652 if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
653 for (size_t i = 0; i<parts_len.size(); i++) {
654 ldout(cct, 20) << "Manifest part " << i << ", size=" << parts_len[i] << dendl;
661 int RGWGetObj_BlockDecrypt::fixup_range(off_t& bl_ofs, off_t& bl_end) {
662 off_t inp_ofs = bl_ofs;
663 off_t inp_end = bl_end;
664 if (parts_len.size() > 0) {
665 off_t in_ofs = bl_ofs;
666 off_t in_end = bl_end;
669 while (i<parts_len.size() && (in_ofs > (off_t)parts_len[i])) {
670 in_ofs -= parts_len[i];
673 //in_ofs is inside block i
675 while (j<parts_len.size() && (in_end > (off_t)parts_len[j])) {
676 in_end -= parts_len[j];
679 //in_end is inside block j
682 rounded_end = ( in_end & ~(block_size - 1) ) + (block_size - 1);
683 if (rounded_end + 1 >= parts_len[j]) {
684 rounded_end = parts_len[j] - 1;
687 enc_begin_skip = in_ofs & (block_size - 1);
688 ofs = bl_ofs - enc_begin_skip;
690 bl_ofs = bl_ofs - enc_begin_skip;
691 bl_end += rounded_end - in_end;
695 enc_begin_skip = bl_ofs & (block_size - 1);
696 ofs = bl_ofs & ~(block_size - 1);
698 bl_ofs = bl_ofs & ~(block_size - 1);
699 bl_end = ( bl_end & ~(block_size - 1) ) + (block_size - 1);
701 ldout(cct, 20) << "fixup_range [" << inp_ofs << "," << inp_end
702 << "] => [" << bl_ofs << "," << bl_end << "]" << dendl;
707 int RGWGetObj_BlockDecrypt::handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) {
709 ldout(cct, 25) << "Decrypt " << bl_len << " bytes" << dendl;
710 size_t part_ofs = ofs;
712 while (i<parts_len.size() && (part_ofs >= parts_len[i])) {
713 part_ofs -= parts_len[i];
716 bl.copy(bl_ofs, bl_len, cache);
717 off_t aligned_size = cache.length() & ~(block_size - 1);
718 if (aligned_size > 0) {
720 if (! crypt->decrypt(cache, 0, aligned_size, data, part_ofs) ) {
721 return -ERR_INTERNAL_ERROR;
723 off_t send_size = aligned_size - enc_begin_skip;
724 if (ofs + enc_begin_skip + send_size > end + 1) {
725 send_size = end + 1 - ofs - enc_begin_skip;
727 res = next->handle_data(data, enc_begin_skip, send_size);
730 cache.splice(0, aligned_size);
736 * flush remainder of data to output
738 int RGWGetObj_BlockDecrypt::flush() {
740 size_t part_ofs = ofs;
742 while (i<parts_len.size() && (part_ofs > parts_len[i])) {
743 part_ofs -= parts_len[i];
746 if (cache.length() > 0) {
748 if (! crypt->decrypt(cache, 0, cache.length(), data, part_ofs) ) {
749 return -ERR_INTERNAL_ERROR;
751 off_t send_size = cache.length() - enc_begin_skip;
752 if (ofs + enc_begin_skip + send_size > end + 1) {
753 send_size = end + 1 - ofs - enc_begin_skip;
755 res = next->handle_data(data, enc_begin_skip, send_size);
762 RGWPutObj_BlockEncrypt::RGWPutObj_BlockEncrypt(CephContext* cct,
763 RGWPutObjDataProcessor* next,
764 std::unique_ptr<BlockCrypt> crypt):
765 RGWPutObj_Filter(next),
767 crypt(std::move(crypt)),
771 block_size = this->crypt->get_block_size();
774 RGWPutObj_BlockEncrypt::~RGWPutObj_BlockEncrypt() {
777 int RGWPutObj_BlockEncrypt::handle_data(bufferlist& bl,
783 ldout(cct, 25) << "Encrypt " << bl.length() << " bytes" << dendl;
787 res = next->handle_data(no_data, in_ofs, phandle, pobj, again);
788 //if *again is not set to false, we will have endless loop
791 ldout(cct, 20) << "*again==true" << dendl;
797 off_t proc_size = cache.length() & ~(block_size - 1);
798 if (bl.length() == 0) {
799 proc_size = cache.length();
803 if (! crypt->encrypt(cache, 0, proc_size, data, ofs) ) {
804 return -ERR_INTERNAL_ERROR;
806 res = next->handle_data(data, ofs, phandle, pobj, again);
808 cache.splice(0, proc_size);
813 if (bl.length() == 0) {
814 /*replicate 0-sized handle_data*/
815 res = next->handle_data(bl, ofs, phandle, pobj, again);
820 int RGWPutObj_BlockEncrypt::throttle_data(void *handle,
821 const rgw_raw_obj& obj,
824 return next->throttle_data(handle, obj, size, need_to_wait);
827 std::string create_random_key_selector(CephContext * const cct) {
828 char random[AES_256_KEYSIZE];
829 if (get_random_bytes(&random[0], sizeof(random)) != 0) {
830 ldout(cct, 0) << "ERROR: cannot get_random_bytes. " << dendl;
831 for (char& v:random) v=rand();
833 return std::string(random, sizeof(random));
836 static int get_barbican_url(CephContext * const cct,
839 url = cct->_conf->rgw_barbican_url;
841 ldout(cct, 0) << "ERROR: conf rgw_barbican_url is not set" << dendl;
845 if (url.back() != '/') {
852 static int request_key_from_barbican(CephContext *cct,
853 boost::string_view key_id,
854 boost::string_view key_selector,
855 const std::string& barbican_token,
856 std::string& actual_key) {
857 std::string secret_url;
859 res = get_barbican_url(cct, secret_url);
863 secret_url += "v1/secrets/" + std::string(key_id);
865 bufferlist secret_bl;
866 RGWHTTPTransceiver secret_req(cct, &secret_bl);
867 secret_req.append_header("Accept", "application/octet-stream");
868 secret_req.append_header("X-Auth-Token", barbican_token);
870 res = secret_req.process("GET", secret_url.c_str());
874 if (secret_req.get_http_status() ==
875 RGWHTTPTransceiver::HTTP_STATUS_UNAUTHORIZED) {
879 if (secret_req.get_http_status() >=200 &&
880 secret_req.get_http_status() < 300 &&
881 secret_bl.length() == AES_256_KEYSIZE) {
882 actual_key.assign(secret_bl.c_str(), secret_bl.length());
883 memset(secret_bl.c_str(), 0, secret_bl.length());
890 static map<string,string> get_str_map(const string &str) {
891 map<string,string> m;
892 get_str_map(str, &m, ";, \t");
896 static int get_actual_key_from_kms(CephContext *cct,
897 boost::string_view key_id,
898 boost::string_view key_selector,
899 std::string& actual_key)
902 ldout(cct, 20) << "Getting KMS encryption key for key=" << key_id << dendl;
903 static map<string,string> str_map = get_str_map(
904 cct->_conf->rgw_crypt_s3_kms_encryption_keys);
906 map<string, string>::iterator it = str_map.find(std::string(key_id));
907 if (it != str_map.end() ) {
908 std::string master_key;
910 master_key = from_base64((*it).second);
912 ldout(cct, 5) << "ERROR: get_actual_key_from_kms invalid encryption key id "
913 << "which contains character that is not base64 encoded."
918 if (master_key.length() == AES_256_KEYSIZE) {
919 uint8_t _actual_key[AES_256_KEYSIZE];
920 if (AES_256_ECB_encrypt(cct,
921 reinterpret_cast<const uint8_t*>(master_key.c_str()), AES_256_KEYSIZE,
922 reinterpret_cast<const uint8_t*>(key_selector.data()),
923 _actual_key, AES_256_KEYSIZE)) {
924 actual_key = std::string((char*)&_actual_key[0], AES_256_KEYSIZE);
928 memset(_actual_key, 0, sizeof(_actual_key));
930 ldout(cct, 20) << "Wrong size for key=" << key_id << dendl;
935 if (rgw::keystone::Service::get_keystone_barbican_token(cct, token) < 0) {
936 ldout(cct, 5) << "Failed to retrieve token for barbican" << dendl;
941 res = request_key_from_barbican(cct, key_id, key_selector, token, actual_key);
943 ldout(cct, 5) << "Failed to retrieve secret from barbican:" << key_id << dendl;
949 static inline void set_attr(map<string, bufferlist>& attrs,
951 boost::string_view value)
954 bl.append(value.data(), value.size());
955 attrs[key] = std::move(bl);
958 static inline std::string get_str_attribute(map<string, bufferlist>& attrs,
961 auto iter = attrs.find(name);
962 if (iter == attrs.end()) {
965 return iter->second.to_str();
969 X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM=0,
970 X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY,
971 X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5,
972 X_AMZ_SERVER_SIDE_ENCRYPTION,
973 X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID,
974 X_AMZ_SERVER_SIDE_ENCRYPTION_LAST
978 const char* http_header_name;
979 const std::string post_part_name;
980 } crypt_option_names;
982 static const crypt_option_names crypt_options[] = {
983 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM", "x-amz-server-side-encryption-customer-algorithm"},
984 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY", "x-amz-server-side-encryption-customer-key"},
985 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5", "x-amz-server-side-encryption-customer-key-md5"},
986 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION", "x-amz-server-side-encryption"},
987 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID", "x-amz-server-side-encryption-aws-kms-key-id"},
990 static boost::string_view get_crypt_attribute(
992 std::map<std::string,
993 RGWPostObj_ObjStore::post_form_part,
994 const ltstr_nocase>* parts,
995 crypt_option_e option)
998 X_AMZ_SERVER_SIDE_ENCRYPTION_LAST == sizeof(crypt_options)/sizeof(*crypt_options),
999 "Missing items in crypt_options");
1000 if (parts != nullptr) {
1002 = parts->find(crypt_options[option].post_part_name);
1003 if (iter == parts->end())
1004 return boost::string_view();
1005 bufferlist& data = iter->second.data;
1006 boost::string_view str = boost::string_view(data.c_str(), data.length());
1007 return rgw_trim_whitespace(str);
1009 const char* hdr = env->get(crypt_options[option].http_header_name, nullptr);
1010 if (hdr != nullptr) {
1011 return boost::string_view(hdr);
1013 return boost::string_view();
1019 int rgw_s3_prepare_encrypt(struct req_state* s,
1020 std::map<std::string, ceph::bufferlist>& attrs,
1021 std::map<std::string,
1022 RGWPostObj_ObjStore::post_form_part,
1023 const ltstr_nocase>* parts,
1024 std::unique_ptr<BlockCrypt>* block_crypt,
1025 std::map<std::string, std::string>& crypt_http_responses)
1028 crypt_http_responses.clear();
1030 boost::string_view req_sse_ca =
1031 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM);
1032 if (! req_sse_ca.empty()) {
1033 if (req_sse_ca != "AES256") {
1034 ldout(s->cct, 5) << "ERROR: Invalid value for header "
1035 << "x-amz-server-side-encryption-customer-algorithm"
1037 s->err.message = "The requested encryption algorithm is not valid, must be AES256.";
1038 return -ERR_INVALID_ENCRYPTION_ALGORITHM;
1040 if (s->cct->_conf->rgw_crypt_require_ssl &&
1041 !s->info.env->exists("SERVER_PORT_SECURE")) {
1042 ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
1043 return -ERR_INVALID_REQUEST;
1046 std::string key_bin;
1048 key_bin = from_base64(
1049 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY) );
1051 ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid encryption "
1052 << "key which contains character that is not base64 encoded."
1054 s->err.message = "Requests specifying Server Side Encryption with Customer "
1055 "provided keys must provide an appropriate secret key.";
1059 if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
1060 ldout(s->cct, 5) << "ERROR: invalid encryption key size" << dendl;
1061 s->err.message = "Requests specifying Server Side Encryption with Customer "
1062 "provided keys must provide an appropriate secret key.";
1066 boost::string_view keymd5 =
1067 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
1069 std::string keymd5_bin;
1071 keymd5_bin = from_base64(keymd5);
1073 ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid encryption key "
1074 << "md5 which contains character that is not base64 encoded."
1076 s->err.message = "Requests specifying Server Side Encryption with Customer "
1077 "provided keys must provide an appropriate secret key md5.";
1081 if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
1082 ldout(s->cct, 5) << "ERROR: Invalid key md5 size" << dendl;
1083 s->err.message = "Requests specifying Server Side Encryption with Customer "
1084 "provided keys must provide an appropriate secret key md5.";
1089 byte key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
1090 key_hash.Update(reinterpret_cast<const byte*>(key_bin.c_str()), key_bin.size());
1091 key_hash.Final(key_hash_res);
1093 if (memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) {
1094 ldout(s->cct, 5) << "ERROR: Invalid key md5 hash" << dendl;
1095 s->err.message = "The calculated MD5 hash of the key did not match the hash that was provided.";
1099 set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-C-AES256");
1100 set_attr(attrs, RGW_ATTR_CRYPT_KEYMD5, keymd5_bin);
1103 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1104 aes->set_key(reinterpret_cast<const uint8_t*>(key_bin.c_str()), AES_256_KEYSIZE);
1105 *block_crypt = std::move(aes);
1108 crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
1109 crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5.to_string();
1112 boost::string_view customer_key =
1113 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY);
1114 if (!customer_key.empty()) {
1115 ldout(s->cct, 5) << "ERROR: SSE-C encryption request is missing the header "
1116 << "x-amz-server-side-encryption-customer-algorithm"
1118 s->err.message = "Requests specifying Server Side Encryption with Customer "
1119 "provided keys must provide a valid encryption algorithm.";
1123 boost::string_view customer_key_md5 =
1124 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
1125 if (!customer_key_md5.empty()) {
1126 ldout(s->cct, 5) << "ERROR: SSE-C encryption request is missing the header "
1127 << "x-amz-server-side-encryption-customer-algorithm"
1129 s->err.message = "Requests specifying Server Side Encryption with Customer "
1130 "provided keys must provide a valid encryption algorithm.";
1135 /* AMAZON server side encryption with KMS (key management service) */
1136 boost::string_view req_sse =
1137 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION);
1138 if (! req_sse.empty()) {
1139 if (req_sse != "aws:kms") {
1140 ldout(s->cct, 5) << "ERROR: Invalid value for header x-amz-server-side-encryption"
1142 s->err.message = "Server Side Encryption with KMS managed key requires "
1143 "HTTP header x-amz-server-side-encryption : aws:kms";
1146 if (s->cct->_conf->rgw_crypt_require_ssl &&
1147 !s->info.env->exists("SERVER_PORT_SECURE")) {
1148 ldout(s->cct, 5) << "ERROR: insecure request, rgw_crypt_require_ssl is set" << dendl;
1149 return -ERR_INVALID_REQUEST;
1151 boost::string_view key_id =
1152 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
1153 if (key_id.empty()) {
1154 ldout(s->cct, 5) << "ERROR: not provide a valid key id" << dendl;
1155 s->err.message = "Server Side Encryption with KMS managed key requires "
1156 "HTTP header x-amz-server-side-encryption-aws-kms-key-id";
1157 return -ERR_INVALID_ACCESS_KEY;
1159 /* try to retrieve actual key */
1160 std::string key_selector = create_random_key_selector(s->cct);
1161 std::string actual_key;
1162 res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
1164 ldout(s->cct, 5) << "ERROR: failed to retrieve actual key from key_id: " << key_id << dendl;
1165 s->err.message = "Failed to retrieve the actual key, kms-keyid: " + key_id.to_string();
1168 if (actual_key.size() != AES_256_KEYSIZE) {
1169 ldout(s->cct, 5) << "ERROR: key obtained from key_id:" <<
1170 key_id << " is not 256 bit size" << dendl;
1171 s->err.message = "KMS provided an invalid key for the given kms-keyid.";
1172 return -ERR_INVALID_ACCESS_KEY;
1174 set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-KMS");
1175 set_attr(attrs, RGW_ATTR_CRYPT_KEYID, key_id);
1176 set_attr(attrs, RGW_ATTR_CRYPT_KEYSEL, key_selector);
1179 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1180 aes->set_key(reinterpret_cast<const uint8_t*>(actual_key.c_str()), AES_256_KEYSIZE);
1181 *block_crypt = std::move(aes);
1183 actual_key.replace(0, actual_key.length(), actual_key.length(), '\000');
1185 crypt_http_responses["x-amz-server-side-encryption"] = "aws:kms";
1186 crypt_http_responses["x-amz-server-side-encryption-aws-kms-key-id"] = key_id.to_string();
1189 boost::string_view key_id =
1190 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
1191 if (!key_id.empty()) {
1192 ldout(s->cct, 5) << "ERROR: SSE-KMS encryption request is missing the header "
1193 << "x-amz-server-side-encryption"
1195 s->err.message = "Server Side Encryption with KMS managed key requires "
1196 "HTTP header x-amz-server-side-encryption : aws:kms";
1201 /* no other encryption mode, check if default encryption is selected */
1202 if (s->cct->_conf->rgw_crypt_default_encryption_key != "") {
1203 std::string master_encryption_key;
1205 master_encryption_key = from_base64(s->cct->_conf->rgw_crypt_default_encryption_key);
1207 ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid default encryption key "
1208 << "which contains character that is not base64 encoded."
1210 s->err.message = "Requests specifying Server Side Encryption with Customer "
1211 "provided keys must provide an appropriate secret key.";
1215 if (master_encryption_key.size() != 256 / 8) {
1216 ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
1217 /* not an error to return; missing encryption does not inhibit processing */
1221 set_attr(attrs, RGW_ATTR_CRYPT_MODE, "RGW-AUTO");
1222 std::string key_selector = create_random_key_selector(s->cct);
1223 set_attr(attrs, RGW_ATTR_CRYPT_KEYSEL, key_selector);
1225 uint8_t actual_key[AES_256_KEYSIZE];
1226 if (AES_256_ECB_encrypt(s->cct,
1227 reinterpret_cast<const uint8_t*>(master_encryption_key.c_str()), AES_256_KEYSIZE,
1228 reinterpret_cast<const uint8_t*>(key_selector.c_str()),
1229 actual_key, AES_256_KEYSIZE) != true) {
1230 memset(actual_key, 0, sizeof(actual_key));
1234 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1235 aes->set_key(reinterpret_cast<const uint8_t*>(actual_key), AES_256_KEYSIZE);
1236 *block_crypt = std::move(aes);
1238 memset(actual_key, 0, sizeof(actual_key));
1247 int rgw_s3_prepare_decrypt(struct req_state* s,
1248 map<string, bufferlist>& attrs,
1249 std::unique_ptr<BlockCrypt>* block_crypt,
1250 std::map<std::string, std::string>& crypt_http_responses)
1253 std::string stored_mode = get_str_attribute(attrs, RGW_ATTR_CRYPT_MODE);
1254 ldout(s->cct, 15) << "Encryption mode: " << stored_mode << dendl;
1256 const char *req_sse = s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION", NULL);
1257 if (nullptr != req_sse && (s->op == OP_GET || s->op == OP_HEAD)) {
1258 return -ERR_INVALID_REQUEST;
1261 if (stored_mode == "SSE-C-AES256") {
1262 if (s->cct->_conf->rgw_crypt_require_ssl &&
1263 !s->info.env->exists("SERVER_PORT_SECURE")) {
1264 ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
1265 return -ERR_INVALID_REQUEST;
1267 const char *req_cust_alg =
1268 s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM", NULL);
1270 if (nullptr == req_cust_alg) {
1271 ldout(s->cct, 5) << "ERROR: Request for SSE-C encrypted object missing "
1272 << "x-amz-server-side-encryption-customer-algorithm"
1274 s->err.message = "Requests specifying Server Side Encryption with Customer "
1275 "provided keys must provide a valid encryption algorithm.";
1277 } else if (strcmp(req_cust_alg, "AES256") != 0) {
1278 ldout(s->cct, 5) << "ERROR: The requested encryption algorithm is not valid, must be AES256." << dendl;
1279 s->err.message = "The requested encryption algorithm is not valid, must be AES256.";
1280 return -ERR_INVALID_ENCRYPTION_ALGORITHM;
1283 std::string key_bin;
1285 key_bin = from_base64(s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY", ""));
1287 ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid encryption key "
1288 << "which contains character that is not base64 encoded."
1290 s->err.message = "Requests specifying Server Side Encryption with Customer "
1291 "provided keys must provide an appropriate secret key.";
1295 if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
1296 ldout(s->cct, 5) << "ERROR: Invalid encryption key size" << dendl;
1297 s->err.message = "Requests specifying Server Side Encryption with Customer "
1298 "provided keys must provide an appropriate secret key.";
1302 std::string keymd5 =
1303 s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5", "");
1304 std::string keymd5_bin;
1306 keymd5_bin = from_base64(keymd5);
1308 ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid encryption key md5 "
1309 << "which contains character that is not base64 encoded."
1311 s->err.message = "Requests specifying Server Side Encryption with Customer "
1312 "provided keys must provide an appropriate secret key md5.";
1317 if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
1318 ldout(s->cct, 5) << "ERROR: Invalid key md5 size " << dendl;
1319 s->err.message = "Requests specifying Server Side Encryption with Customer "
1320 "provided keys must provide an appropriate secret key md5.";
1325 uint8_t key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
1326 key_hash.Update(reinterpret_cast<const byte*>(key_bin.c_str()), key_bin.size());
1327 key_hash.Final(key_hash_res);
1329 if ((memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) ||
1330 (get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYMD5) != keymd5_bin)) {
1331 s->err.message = "The calculated MD5 hash of the key did not match the hash that was provided.";
1334 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1335 aes->set_key(reinterpret_cast<const uint8_t*>(key_bin.c_str()), AES_256_CBC::AES_256_KEYSIZE);
1336 if (block_crypt) *block_crypt = std::move(aes);
1338 crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
1339 crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5;
1343 if (stored_mode == "SSE-KMS") {
1344 if (s->cct->_conf->rgw_crypt_require_ssl &&
1345 !s->info.env->exists("SERVER_PORT_SECURE")) {
1346 ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
1347 return -ERR_INVALID_REQUEST;
1349 /* try to retrieve actual key */
1350 std::string key_id = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYID);
1351 std::string key_selector = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYSEL);
1352 std::string actual_key;
1353 res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
1355 ldout(s->cct, 10) << "ERROR: failed to retrieve actual key from key_id: " << key_id << dendl;
1356 s->err.message = "Failed to retrieve the actual key, kms-keyid: " + key_id;
1359 if (actual_key.size() != AES_256_KEYSIZE) {
1360 ldout(s->cct, 0) << "ERROR: key obtained from key_id:" <<
1361 key_id << " is not 256 bit size" << dendl;
1362 s->err.message = "KMS provided an invalid key for the given kms-keyid.";
1363 return -ERR_INVALID_ACCESS_KEY;
1366 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1367 aes->set_key(reinterpret_cast<const uint8_t*>(actual_key.c_str()), AES_256_KEYSIZE);
1368 actual_key.replace(0, actual_key.length(), actual_key.length(), '\000');
1369 if (block_crypt) *block_crypt = std::move(aes);
1371 crypt_http_responses["x-amz-server-side-encryption"] = "aws:kms";
1372 crypt_http_responses["x-amz-server-side-encryption-aws-kms-key-id"] = key_id;
1376 if (stored_mode == "RGW-AUTO") {
1377 std::string master_encryption_key;
1379 master_encryption_key = from_base64(std::string(s->cct->_conf->rgw_crypt_default_encryption_key));
1381 ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid default encryption key "
1382 << "which contains character that is not base64 encoded."
1384 s->err.message = "The default encryption key is not valid base64.";
1388 if (master_encryption_key.size() != 256 / 8) {
1389 ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
1392 std::string attr_key_selector = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYSEL);
1393 if (attr_key_selector.size() != AES_256_CBC::AES_256_KEYSIZE) {
1394 ldout(s->cct, 0) << "ERROR: missing or invalid " RGW_ATTR_CRYPT_KEYSEL << dendl;
1397 uint8_t actual_key[AES_256_KEYSIZE];
1398 if (AES_256_ECB_encrypt(s->cct,
1399 reinterpret_cast<const uint8_t*>(master_encryption_key.c_str()),
1401 reinterpret_cast<const uint8_t*>(attr_key_selector.c_str()),
1402 actual_key, AES_256_KEYSIZE) != true) {
1403 memset(actual_key, 0, sizeof(actual_key));
1406 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1407 aes->set_key(actual_key, AES_256_KEYSIZE);
1408 memset(actual_key, 0, sizeof(actual_key));
1409 if (block_crypt) *block_crypt = std::move(aes);