]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_crypt.cc
update sources to v12.1.3
[ceph.git] / ceph / src / rgw / rgw_crypt.cc
1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /**
4 * Crypto filters for Put/Post/Get operations.
5 */
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"
17 #ifdef USE_NSS
18 # include <nspr.h>
19 # include <nss.h>
20 # include <pk11pub.h>
21 #endif
22
23 #ifdef USE_CRYPTOPP
24 #include <cryptopp/cryptlib.h>
25 #include <cryptopp/modes.h>
26 #include <cryptopp/aes.h>
27 using namespace CryptoPP;
28 #endif
29
30 #define dout_context g_ceph_context
31 #define dout_subsys ceph_subsys_rgw
32
33 using namespace rgw;
34
35 /**
36 * Encryption in CTR mode. offset is used as IV for each block.
37 */
38 #warning "TODO: move this code to auth/Crypto for others to reuse."
39
40 class AES_256_CTR : public BlockCrypt {
41 public:
42 static const size_t AES_256_KEYSIZE = 256 / 8;
43 static const size_t AES_256_IVSIZE = 128 / 8;
44 private:
45 static const uint8_t IV[AES_256_IVSIZE];
46 CephContext* cct;
47 uint8_t key[AES_256_KEYSIZE];
48 public:
49 AES_256_CTR(CephContext* cct): cct(cct) {
50 }
51 ~AES_256_CTR() {
52 memset(key, 0, AES_256_KEYSIZE);
53 }
54 bool set_key(const uint8_t* _key, size_t key_size) {
55 if (key_size != AES_256_KEYSIZE) {
56 return false;
57 }
58 memcpy(key, _key, AES_256_KEYSIZE);
59 return true;
60 }
61 size_t get_block_size() {
62 return AES_256_IVSIZE;
63 }
64
65 #ifdef USE_CRYPTOPP
66
67 bool encrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset) {
68 byte iv[AES_256_IVSIZE];
69 ldout(cct, 25)
70 << "Encrypt in_ofs " << in_ofs
71 << " size=" << size
72 << " stream_offset=" << stream_offset
73 << dendl;
74 if (input.length() < in_ofs + size) {
75 return false;
76 }
77
78 output.clear();
79 buffer::ptr buf((size + AES_256_KEYSIZE - 1) / AES_256_KEYSIZE * AES_256_KEYSIZE);
80 /*create CTR mask*/
81 prepare_iv(iv, stream_offset);
82 CTR_Mode< AES >::Encryption e;
83 e.SetKeyWithIV(key, AES_256_KEYSIZE, iv, AES_256_IVSIZE);
84 buf.zero();
85 e.ProcessData((byte*)buf.c_str(), (byte*)buf.c_str(), buf.length());
86 buf.set_length(size);
87 off_t plaintext_pos = in_ofs;
88 off_t crypt_pos = 0;
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();
93 ++iter;
94 }
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++) {
100 dst[i] ^= src[i];
101 }
102 ++iter;
103 plaintext_pos = 0;
104 crypt_pos += cnt;
105 }
106 output.append(buf);
107 return true;
108 }
109
110 #elif defined(USE_NSS)
111
112 bool encrypt(bufferlist& input, off_t in_ofs, size_t size, bufferlist& output, off_t stream_offset)
113 {
114 bool result = false;
115 PK11SlotInfo *slot;
116 SECItem keyItem;
117 PK11SymKey *symkey;
118 CK_AES_CTR_PARAMS ctr_params = {0};
119 SECItem ivItem;
120 SECItem *param;
121 SECStatus ret;
122 PK11Context *ectx;
123 int written;
124 unsigned int written2;
125
126 slot = PK11_GetBestSlot(CKM_AES_CTR, NULL);
127 if (slot) {
128 keyItem.type = siBuffer;
129 keyItem.data = key;
130 keyItem.len = AES_256_KEYSIZE;
131
132 symkey = PK11_ImportSymKey(slot, CKM_AES_CTR, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
133 if (symkey) {
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);
137
138 ivItem.type = siBuffer;
139 ivItem.data = (unsigned char*)&ctr_params;
140 ivItem.len = sizeof(ctr_params);
141
142 param = PK11_ParamFromIV(CKM_AES_CTR, &ivItem);
143 if (param) {
144 ectx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, symkey, param);
145 if (ectx) {
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);
156 output.append(buf);
157 result = true;
158 }
159 }
160 PK11_DestroyContext(ectx, PR_TRUE);
161 }
162 SECITEM_FreeItem(param, PR_TRUE);
163 }
164 PK11_FreeSymKey(symkey);
165 }
166 PK11_FreeSlot(slot);
167 }
168 if (result == false) {
169 ldout(cct, 5) << "Failed to perform AES-CTR encryption: " << PR_GetError() << dendl;
170 }
171 return result;
172 }
173
174 #else
175 #error Must define USE_CRYPTOPP or USE_NSS
176 #endif
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);
180 }
181
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;
185 unsigned int val;
186 unsigned int carry = 0;
187 while (i>=0) {
188 val = (index & 0xff) + IV[i] + carry;
189 iv[i] = val;
190 carry = val >> 8;
191 index = index >> 8;
192 i--;
193 }
194 }
195 };
196
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' };
199
200
201 CryptoAccelRef get_crypto_accel(CephContext *cct)
202 {
203 CryptoAccelRef ca_impl = nullptr;
204 stringstream ss;
205 PluginRegistry *reg = cct->get_plugin_registry();
206 string crypto_accel_type = cct->_conf->plugin_crypto_accelerator;
207
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;
211 return nullptr;
212 }
213 int err = factory->factory(&ca_impl, &ss);
214 if (err) {
215 lderr(cct) << __func__ << " factory return error " << err <<
216 " with description: " << ss.str() << dendl;
217 }
218 return ca_impl;
219 }
220
221
222 /**
223 * Encryption in CBC mode. Chunked to 4K blocks. Offset is used as IV for each 4K block.
224 *
225 *
226 *
227 * A. Encryption
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
236 *
237 * B. Decryption
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
246 */
247 #warning "TODO: use auth/Crypto instead of reimplementing."
248 class AES_256_CBC : public BlockCrypt {
249 public:
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;
253 private:
254 static const uint8_t IV[AES_256_IVSIZE];
255 CephContext* cct;
256 uint8_t key[AES_256_KEYSIZE];
257 public:
258 AES_256_CBC(CephContext* cct): cct(cct) {
259 }
260 ~AES_256_CBC() {
261 memset(key, 0, AES_256_KEYSIZE);
262 }
263 bool set_key(const uint8_t* _key, size_t key_size) {
264 if (key_size != AES_256_KEYSIZE) {
265 return false;
266 }
267 memcpy(key, _key, AES_256_KEYSIZE);
268 return true;
269 }
270 size_t get_block_size() {
271 return CHUNK_SIZE;
272 }
273
274 #ifdef USE_CRYPTOPP
275
276 bool cbc_transform(unsigned char* out,
277 const unsigned char* in,
278 size_t size,
279 const unsigned char (&iv)[AES_256_IVSIZE],
280 const unsigned char (&key)[AES_256_KEYSIZE],
281 bool encrypt)
282 {
283 if (encrypt) {
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);
287 } else {
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);
291 }
292 return true;
293 }
294
295 #elif defined(USE_NSS)
296
297 bool cbc_transform(unsigned char* out,
298 const unsigned char* in,
299 size_t size,
300 const unsigned char (&iv)[AES_256_IVSIZE],
301 const unsigned char (&key)[AES_256_KEYSIZE],
302 bool encrypt)
303 {
304 bool result = false;
305 PK11SlotInfo *slot;
306 SECItem keyItem;
307 PK11SymKey *symkey;
308 CK_AES_CBC_ENCRYPT_DATA_PARAMS ctr_params = {0};
309 SECItem ivItem;
310 SECItem *param;
311 SECStatus ret;
312 PK11Context *ectx;
313 int written;
314
315 slot = PK11_GetBestSlot(CKM_AES_CBC, NULL);
316 if (slot) {
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);
321 if (symkey) {
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);
326
327 param = PK11_ParamFromIV(CKM_AES_CBC, &ivItem);
328 if (param) {
329 ectx = PK11_CreateContextBySymKey(CKM_AES_CBC, encrypt?CKA_ENCRYPT:CKA_DECRYPT, symkey, param);
330 if (ectx) {
331 ret = PK11_CipherOp(ectx,
332 out, &written, size,
333 in, size);
334 if ((ret == SECSuccess) && (written == (int)size)) {
335 result = true;
336 }
337 PK11_DestroyContext(ectx, PR_TRUE);
338 }
339 SECITEM_FreeItem(param, PR_TRUE);
340 }
341 PK11_FreeSymKey(symkey);
342 }
343 PK11_FreeSlot(slot);
344 }
345 if (result == false) {
346 ldout(cct, 5) << "Failed to perform AES-CBC encryption: " << PR_GetError() << dendl;
347 }
348 return result;
349 }
350
351 #else
352 #error Must define USE_CRYPTOPP or USE_NSS
353 #endif
354
355 bool cbc_transform(unsigned char* out,
356 const unsigned char* in,
357 size_t size,
358 off_t stream_offset,
359 const unsigned char (&key)[AES_256_KEYSIZE],
360 bool encrypt)
361 {
362 static std::atomic<bool> failed_to_get_crypto(false);
363 CryptoAccelRef crypto_accel;
364 if (! failed_to_get_crypto.load())
365 {
366 crypto_accel = get_crypto_accel(cct);
367 if (!crypto_accel)
368 failed_to_get_crypto = true;
369 }
370 bool result = 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) {
376 if (encrypt) {
377 result = crypto_accel->cbc_encrypt(out + offset, in + offset,
378 process_size, iv, key);
379 } else {
380 result = crypto_accel->cbc_decrypt(out + offset, in + offset,
381 process_size, iv, key);
382 }
383 } else {
384 result = cbc_transform(
385 out + offset, in + offset, process_size,
386 iv, key, encrypt);
387 }
388 }
389 return result;
390 }
391
392
393 bool encrypt(bufferlist& input,
394 off_t in_ofs,
395 size_t size,
396 bufferlist& output,
397 off_t stream_offset)
398 {
399 bool result = false;
400 size_t aligned_size = size / AES_256_IVSIZE * AES_256_IVSIZE;
401 size_t unaligned_rest_size = size - aligned_size;
402 output.clear();
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());
406
407 /* encrypt main bulk of data */
408 result = cbc_transform(buf_raw,
409 input_raw + in_ofs,
410 aligned_size,
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,
419 AES_256_IVSIZE,
420 iv, key, true);
421 } else {
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,
427 data,
428 AES_256_IVSIZE,
429 iv, key, true);
430 }
431 if (result) {
432 for(size_t i = aligned_size; i < size; i++) {
433 *(buf_raw + i) ^= *(input_raw + in_ofs + i);
434 }
435 }
436 }
437 if (result) {
438 ldout(cct, 25) << "Encrypted " << size << " bytes"<< dendl;
439 buf.set_length(size);
440 output.append(buf);
441 } else {
442 ldout(cct, 5) << "Failed to encrypt" << dendl;
443 }
444 return result;
445 }
446
447
448 bool decrypt(bufferlist& input,
449 off_t in_ofs,
450 size_t size,
451 bufferlist& output,
452 off_t stream_offset)
453 {
454 bool result = false;
455 size_t aligned_size = size / AES_256_IVSIZE * AES_256_IVSIZE;
456 size_t unaligned_rest_size = size - aligned_size;
457 output.clear();
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());
461
462 /* decrypt main bulk of data */
463 result = cbc_transform(buf_raw,
464 input_raw + in_ofs,
465 aligned_size,
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,
474 AES_256_IVSIZE,
475 iv, key, true);
476 } else {
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,
482 data,
483 AES_256_IVSIZE,
484 iv, key, true);
485 }
486 if (result) {
487 for(size_t i = aligned_size; i < size; i++) {
488 *(buf_raw + i) ^= *(input_raw + in_ofs + i);
489 }
490 }
491 }
492 if (result) {
493 ldout(cct, 25) << "Decrypted " << size << " bytes"<< dendl;
494 buf.set_length(size);
495 output.append(buf);
496 } else {
497 ldout(cct, 5) << "Failed to decrypt" << dendl;
498 }
499 return result;
500 }
501
502
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;
506 unsigned int val;
507 unsigned int carry = 0;
508 while (i>=0) {
509 val = (index & 0xff) + IV[i] + carry;
510 iv[i] = val;
511 carry = val >> 8;
512 index = index >> 8;
513 i--;
514 }
515 }
516 };
517
518
519 std::unique_ptr<BlockCrypt> AES_256_CBC_create(CephContext* cct, const uint8_t* key, size_t len)
520 {
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);
524 }
525
526
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' };
529
530
531 #ifdef USE_CRYPTOPP
532
533 bool AES_256_ECB_encrypt(CephContext* cct,
534 const uint8_t* key,
535 size_t key_size,
536 const uint8_t* data_in,
537 uint8_t* data_out,
538 size_t data_size)
539 {
540 bool res = false;
541 if (key_size == AES_256_KEYSIZE) {
542 try {
543 ECB_Mode< AES >::Encryption e;
544 e.SetKey( key, key_size );
545 e.ProcessData(data_out, data_in, data_size);
546 res = true;
547 } catch( CryptoPP::Exception& ex ) {
548 ldout(cct, 5) << "AES-ECB encryption failed with: " << ex.GetWhat() << dendl;
549 }
550 }
551 return res;
552 }
553
554 #elif defined USE_NSS
555
556 bool AES_256_ECB_encrypt(CephContext* cct,
557 const uint8_t* key,
558 size_t key_size,
559 const uint8_t* data_in,
560 uint8_t* data_out,
561 size_t data_size) {
562 bool result = false;
563 PK11SlotInfo *slot;
564 SECItem keyItem;
565 PK11SymKey *symkey;
566 SECItem *param;
567 SECStatus ret;
568 PK11Context *ectx;
569 int written;
570 unsigned int written2;
571 if (key_size == AES_256_KEYSIZE) {
572 slot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
573 if (slot) {
574 keyItem.type = siBuffer;
575 keyItem.data = const_cast<uint8_t*>(key);
576 keyItem.len = AES_256_KEYSIZE;
577
578 param = PK11_ParamFromIV(CKM_AES_ECB, NULL);
579 if (param) {
580 symkey = PK11_ImportSymKey(slot, CKM_AES_ECB, PK11_OriginUnwrap, CKA_UNWRAP, &keyItem, NULL);
581 if (symkey) {
582 ectx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, symkey, param);
583 if (ectx) {
584 ret = PK11_CipherOp(ectx,
585 data_out, &written, data_size,
586 data_in, data_size);
587 if (ret == SECSuccess) {
588 ret = PK11_DigestFinal(ectx,
589 data_out + written, &written2,
590 data_size - written);
591 if (ret == SECSuccess) {
592 result = true;
593 }
594 }
595 PK11_DestroyContext(ectx, PR_TRUE);
596 }
597 PK11_FreeSymKey(symkey);
598 }
599 SECITEM_FreeItem(param, PR_TRUE);
600 }
601 PK11_FreeSlot(slot);
602 }
603 if (result == false) {
604 ldout(cct, 5) << "Failed to perform AES-ECB encryption: " << PR_GetError() << dendl;
605 }
606 } else {
607 ldout(cct, 5) << "Key size must be 256 bits long" << dendl;
608 }
609 return result;
610 }
611
612 #else
613 #error Must define USE_CRYPTOPP or USE_NSS
614 #endif
615
616
617 RGWGetObj_BlockDecrypt::RGWGetObj_BlockDecrypt(CephContext* cct,
618 RGWGetDataCB* next,
619 std::unique_ptr<BlockCrypt> crypt):
620 RGWGetObj_Filter(next),
621 cct(cct),
622 crypt(std::move(crypt)),
623 enc_begin_skip(0),
624 ofs(0),
625 end(0),
626 cache()
627 {
628 block_size = this->crypt->get_block_size();
629 }
630
631 RGWGetObj_BlockDecrypt::~RGWGetObj_BlockDecrypt() {
632 }
633
634 int RGWGetObj_BlockDecrypt::read_manifest(bufferlist& manifest_bl) {
635 parts_len.clear();
636 RGWObjManifest manifest;
637 if (manifest_bl.length()) {
638 bufferlist::iterator miter = manifest_bl.begin();
639 try {
640 ::decode(manifest, miter);
641 } catch (buffer::error& err) {
642 ldout(cct, 0) << "ERROR: couldn't decode manifest" << dendl;
643 return -EIO;
644 }
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);
649 }
650 parts_len.back() += mi.get_stripe_size();
651 }
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;
655 }
656 }
657 }
658 return 0;
659 }
660
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;
667
668 size_t i = 0;
669 while (i<parts_len.size() && (in_ofs > (off_t)parts_len[i])) {
670 in_ofs -= parts_len[i];
671 i++;
672 }
673 //in_ofs is inside block i
674 size_t j = 0;
675 while (j<parts_len.size() && (in_end > (off_t)parts_len[j])) {
676 in_end -= parts_len[j];
677 j++;
678 }
679 //in_end is inside block j
680
681 size_t rounded_end;
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;
685 }
686
687 enc_begin_skip = in_ofs & (block_size - 1);
688 ofs = bl_ofs - enc_begin_skip;
689 end = bl_end;
690 bl_ofs = bl_ofs - enc_begin_skip;
691 bl_end += rounded_end - in_end;
692 }
693 else
694 {
695 enc_begin_skip = bl_ofs & (block_size - 1);
696 ofs = bl_ofs & ~(block_size - 1);
697 end = bl_end;
698 bl_ofs = bl_ofs & ~(block_size - 1);
699 bl_end = ( bl_end & ~(block_size - 1) ) + (block_size - 1);
700 }
701 ldout(cct, 20) << "fixup_range [" << inp_ofs << "," << inp_end
702 << "] => [" << bl_ofs << "," << bl_end << "]" << dendl;
703 return 0;
704 }
705
706
707 int RGWGetObj_BlockDecrypt::handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) {
708 int res = 0;
709 ldout(cct, 25) << "Decrypt " << bl_len << " bytes" << dendl;
710 size_t part_ofs = ofs;
711 size_t i = 0;
712 while (i<parts_len.size() && (part_ofs >= parts_len[i])) {
713 part_ofs -= parts_len[i];
714 i++;
715 }
716 bl.copy(bl_ofs, bl_len, cache);
717 off_t aligned_size = cache.length() & ~(block_size - 1);
718 if (aligned_size > 0) {
719 bufferlist data;
720 if (! crypt->decrypt(cache, 0, aligned_size, data, part_ofs) ) {
721 return -ERR_INTERNAL_ERROR;
722 }
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;
726 }
727 res = next->handle_data(data, enc_begin_skip, send_size);
728 enc_begin_skip = 0;
729 ofs += aligned_size;
730 cache.splice(0, aligned_size);
731 }
732 return res;
733 }
734
735 /**
736 * flush remainder of data to output
737 */
738 int RGWGetObj_BlockDecrypt::flush() {
739 int res = 0;
740 size_t part_ofs = ofs;
741 size_t i = 0;
742 while (i<parts_len.size() && (part_ofs > parts_len[i])) {
743 part_ofs -= parts_len[i];
744 i++;
745 }
746 if (cache.length() > 0) {
747 bufferlist data;
748 if (! crypt->decrypt(cache, 0, cache.length(), data, part_ofs) ) {
749 return -ERR_INTERNAL_ERROR;
750 }
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;
754 }
755 res = next->handle_data(data, enc_begin_skip, send_size);
756 enc_begin_skip = 0;
757 ofs += send_size;
758 }
759 return res;
760 }
761
762 RGWPutObj_BlockEncrypt::RGWPutObj_BlockEncrypt(CephContext* cct,
763 RGWPutObjDataProcessor* next,
764 std::unique_ptr<BlockCrypt> crypt):
765 RGWPutObj_Filter(next),
766 cct(cct),
767 crypt(std::move(crypt)),
768 ofs(0),
769 cache()
770 {
771 block_size = this->crypt->get_block_size();
772 }
773
774 RGWPutObj_BlockEncrypt::~RGWPutObj_BlockEncrypt() {
775 }
776
777 int RGWPutObj_BlockEncrypt::handle_data(bufferlist& bl,
778 off_t in_ofs,
779 void **phandle,
780 rgw_raw_obj *pobj,
781 bool *again) {
782 int res = 0;
783 ldout(cct, 25) << "Encrypt " << bl.length() << " bytes" << dendl;
784
785 if (*again) {
786 bufferlist no_data;
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
789 //drop info on log
790 if (*again) {
791 ldout(cct, 20) << "*again==true" << dendl;
792 }
793 return res;
794 }
795
796 cache.append(bl);
797 off_t proc_size = cache.length() & ~(block_size - 1);
798 if (bl.length() == 0) {
799 proc_size = cache.length();
800 }
801 if (proc_size > 0) {
802 bufferlist data;
803 if (! crypt->encrypt(cache, 0, proc_size, data, ofs) ) {
804 return -ERR_INTERNAL_ERROR;
805 }
806 res = next->handle_data(data, ofs, phandle, pobj, again);
807 ofs += proc_size;
808 cache.splice(0, proc_size);
809 if (res < 0)
810 return res;
811 }
812
813 if (bl.length() == 0) {
814 /*replicate 0-sized handle_data*/
815 res = next->handle_data(bl, ofs, phandle, pobj, again);
816 }
817 return res;
818 }
819
820 int RGWPutObj_BlockEncrypt::throttle_data(void *handle,
821 const rgw_raw_obj& obj,
822 uint64_t size,
823 bool need_to_wait) {
824 return next->throttle_data(handle, obj, size, need_to_wait);
825 }
826
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();
832 }
833 return std::string(random, sizeof(random));
834 }
835
836 static int get_barbican_url(CephContext * const cct,
837 std::string& url)
838 {
839 url = cct->_conf->rgw_barbican_url;
840 if (url.empty()) {
841 ldout(cct, 0) << "ERROR: conf rgw_barbican_url is not set" << dendl;
842 return -EINVAL;
843 }
844
845 if (url.back() != '/') {
846 url.append("/");
847 }
848
849 return 0;
850 }
851
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;
858 int res;
859 res = get_barbican_url(cct, secret_url);
860 if (res < 0) {
861 return res;
862 }
863 secret_url += "v1/secrets/" + std::string(key_id);
864
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);
869
870 res = secret_req.process("GET", secret_url.c_str());
871 if (res < 0) {
872 return res;
873 }
874 if (secret_req.get_http_status() ==
875 RGWHTTPTransceiver::HTTP_STATUS_UNAUTHORIZED) {
876 return -EACCES;
877 }
878
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());
884 } else {
885 res = -EACCES;
886 }
887 return res;
888 }
889
890 static map<string,string> get_str_map(const string &str) {
891 map<string,string> m;
892 get_str_map(str, &m, ";, \t");
893 return m;
894 }
895
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)
900 {
901 int res = 0;
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);
905
906 map<string, string>::iterator it = str_map.find(std::string(key_id));
907 if (it != str_map.end() ) {
908 std::string master_key = from_base64((*it).second);
909 if (master_key.length() == AES_256_KEYSIZE) {
910 uint8_t _actual_key[AES_256_KEYSIZE];
911 if (AES_256_ECB_encrypt(cct,
912 reinterpret_cast<const uint8_t*>(master_key.c_str()), AES_256_KEYSIZE,
913 reinterpret_cast<const uint8_t*>(key_selector.data()),
914 _actual_key, AES_256_KEYSIZE)) {
915 actual_key = std::string((char*)&_actual_key[0], AES_256_KEYSIZE);
916 } else {
917 res = -EIO;
918 }
919 memset(_actual_key, 0, sizeof(_actual_key));
920 } else {
921 ldout(cct, 20) << "Wrong size for key=" << key_id << dendl;
922 res = -EIO;
923 }
924 } else {
925 std::string token;
926 if (rgw::keystone::Service::get_keystone_barbican_token(cct, token) < 0) {
927 ldout(cct, 5) << "Failed to retrieve token for barbican" << dendl;
928 res = -EINVAL;
929 return res;
930 }
931
932 res = request_key_from_barbican(cct, key_id, key_selector, token, actual_key);
933 if (res != 0) {
934 ldout(cct, 5) << "Failed to retrieve secret from barbican:" << key_id << dendl;
935 }
936 }
937 return res;
938 }
939
940 static inline void set_attr(map<string, bufferlist>& attrs,
941 const char* key,
942 boost::string_view value)
943 {
944 bufferlist bl;
945 bl.append(value.data(), value.size());
946 attrs[key] = std::move(bl);
947 }
948
949 static inline std::string get_str_attribute(map<string, bufferlist>& attrs,
950 const char *name)
951 {
952 auto iter = attrs.find(name);
953 if (iter == attrs.end()) {
954 return {};
955 }
956 return iter->second.to_str();
957 }
958
959 typedef enum {
960 X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM=0,
961 X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY,
962 X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5,
963 X_AMZ_SERVER_SIDE_ENCRYPTION,
964 X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID,
965 X_AMZ_SERVER_SIDE_ENCRYPTION_LAST
966 } crypt_option_e;
967
968 typedef struct {
969 const char* http_header_name;
970 const std::string post_part_name;
971 } crypt_option_names;
972
973 static const crypt_option_names crypt_options[] = {
974 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM", "x-amz-server-side-encryption-customer-algorithm"},
975 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY", "x-amz-server-side-encryption-customer-key"},
976 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5", "x-amz-server-side-encryption-customer-key-md5"},
977 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION", "x-amz-server-side-encryption"},
978 {"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID", "x-amz-server-side-encryption-aws-kms-key-id"},
979 };
980
981 static boost::string_view get_crypt_attribute(
982 const RGWEnv* env,
983 std::map<std::string,
984 RGWPostObj_ObjStore::post_form_part,
985 const ltstr_nocase>* parts,
986 crypt_option_e option)
987 {
988 static_assert(
989 X_AMZ_SERVER_SIDE_ENCRYPTION_LAST == sizeof(crypt_options)/sizeof(*crypt_options),
990 "Missing items in crypt_options");
991 if (parts != nullptr) {
992 auto iter
993 = parts->find(crypt_options[option].post_part_name);
994 if (iter == parts->end())
995 return boost::string_view();
996 bufferlist& data = iter->second.data;
997 boost::string_view str = boost::string_view(data.c_str(), data.length());
998 return rgw_trim_whitespace(str);
999 } else {
1000 const char* hdr = env->get(crypt_options[option].http_header_name, nullptr);
1001 if (hdr != nullptr) {
1002 return boost::string_view(hdr);
1003 } else {
1004 return boost::string_view();
1005 }
1006 }
1007 }
1008
1009
1010 int rgw_s3_prepare_encrypt(struct req_state* s,
1011 std::map<std::string, ceph::bufferlist>& attrs,
1012 std::map<std::string,
1013 RGWPostObj_ObjStore::post_form_part,
1014 const ltstr_nocase>* parts,
1015 std::unique_ptr<BlockCrypt>* block_crypt,
1016 std::map<std::string, std::string>& crypt_http_responses)
1017 {
1018 int res = 0;
1019 crypt_http_responses.clear();
1020 {
1021 boost::string_view req_sse_ca =
1022 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM);
1023 if (! req_sse_ca.empty()) {
1024 if (req_sse_ca != "AES256") {
1025 ldout(s->cct, 5) << "ERROR: Invalid value for header "
1026 << "x-amz-server-side-encryption-customer-algorithm"
1027 << dendl;
1028 return -ERR_INVALID_REQUEST;
1029 }
1030 if (s->cct->_conf->rgw_crypt_require_ssl &&
1031 !s->info.env->exists("SERVER_PORT_SECURE")) {
1032 ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
1033 return -ERR_INVALID_REQUEST;
1034 }
1035 std::string key_bin = from_base64(
1036 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY) );
1037 if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
1038 ldout(s->cct, 5) << "ERROR: invalid encryption key size" << dendl;
1039 return -ERR_INVALID_REQUEST;
1040 }
1041 boost::string_view keymd5 =
1042 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
1043 std::string keymd5_bin = from_base64(keymd5);
1044 if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
1045 ldout(s->cct, 5) << "ERROR: Invalid key md5 size" << dendl;
1046 return -ERR_INVALID_DIGEST;
1047 }
1048 MD5 key_hash;
1049 byte key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
1050 key_hash.Update(reinterpret_cast<const byte*>(key_bin.c_str()), key_bin.size());
1051 key_hash.Final(key_hash_res);
1052
1053 if (memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) {
1054 ldout(s->cct, 5) << "ERROR: Invalid key md5 hash" << dendl;
1055 return -ERR_INVALID_DIGEST;
1056 }
1057
1058 set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-C-AES256");
1059 set_attr(attrs, RGW_ATTR_CRYPT_KEYMD5, keymd5_bin);
1060
1061 if (block_crypt) {
1062 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1063 aes->set_key(reinterpret_cast<const uint8_t*>(key_bin.c_str()), AES_256_KEYSIZE);
1064 *block_crypt = std::move(aes);
1065 }
1066
1067 crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
1068 crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5.to_string();
1069 return 0;
1070 }
1071 /* AMAZON server side encryption with KMS (key management service) */
1072 boost::string_view req_sse =
1073 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION);
1074 if (! req_sse.empty()) {
1075 if (req_sse != "aws:kms") {
1076 ldout(s->cct, 5) << "ERROR: Invalid value for header x-amz-server-side-encryption"
1077 << dendl;
1078 return -ERR_INVALID_REQUEST;
1079 }
1080 if (s->cct->_conf->rgw_crypt_require_ssl &&
1081 !s->info.env->exists("SERVER_PORT_SECURE")) {
1082 ldout(s->cct, 5) << "ERROR: insecure request, rgw_crypt_require_ssl is set" << dendl;
1083 return -ERR_INVALID_REQUEST;
1084 }
1085 boost::string_view key_id =
1086 get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
1087 if (key_id.empty()) {
1088 return -ERR_INVALID_ACCESS_KEY;
1089 }
1090 /* try to retrieve actual key */
1091 std::string key_selector = create_random_key_selector(s->cct);
1092 std::string actual_key;
1093 res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
1094 if (res != 0)
1095 return res;
1096 if (actual_key.size() != AES_256_KEYSIZE) {
1097 ldout(s->cct, 5) << "ERROR: key obtained from key_id:" <<
1098 key_id << " is not 256 bit size" << dendl;
1099 return -ERR_INVALID_ACCESS_KEY;
1100 }
1101 set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-KMS");
1102 set_attr(attrs, RGW_ATTR_CRYPT_KEYID, key_id);
1103 set_attr(attrs, RGW_ATTR_CRYPT_KEYSEL, key_selector);
1104
1105 if (block_crypt) {
1106 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1107 aes->set_key(reinterpret_cast<const uint8_t*>(actual_key.c_str()), AES_256_KEYSIZE);
1108 *block_crypt = std::move(aes);
1109 }
1110 actual_key.replace(0, actual_key.length(), actual_key.length(), '\000');
1111 return 0;
1112 }
1113
1114 /* no other encryption mode, check if default encryption is selected */
1115 if (s->cct->_conf->rgw_crypt_default_encryption_key != "") {
1116 std::string master_encryption_key =
1117 from_base64(s->cct->_conf->rgw_crypt_default_encryption_key);
1118 if (master_encryption_key.size() != 256 / 8) {
1119 ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
1120 /* not an error to return; missing encryption does not inhibit processing */
1121 return 0;
1122 }
1123
1124 set_attr(attrs, RGW_ATTR_CRYPT_MODE, "RGW-AUTO");
1125 std::string key_selector = create_random_key_selector(s->cct);
1126 set_attr(attrs, RGW_ATTR_CRYPT_KEYSEL, key_selector);
1127
1128 uint8_t actual_key[AES_256_KEYSIZE];
1129 if (AES_256_ECB_encrypt(s->cct,
1130 reinterpret_cast<const uint8_t*>(master_encryption_key.c_str()), AES_256_KEYSIZE,
1131 reinterpret_cast<const uint8_t*>(key_selector.c_str()),
1132 actual_key, AES_256_KEYSIZE) != true) {
1133 memset(actual_key, 0, sizeof(actual_key));
1134 return -EIO;
1135 }
1136 if (block_crypt) {
1137 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1138 aes->set_key(reinterpret_cast<const uint8_t*>(actual_key), AES_256_KEYSIZE);
1139 *block_crypt = std::move(aes);
1140 }
1141 memset(actual_key, 0, sizeof(actual_key));
1142 return 0;
1143 }
1144 }
1145 /*no encryption*/
1146 return 0;
1147 }
1148
1149
1150 int rgw_s3_prepare_decrypt(struct req_state* s,
1151 map<string, bufferlist>& attrs,
1152 std::unique_ptr<BlockCrypt>* block_crypt,
1153 std::map<std::string, std::string>& crypt_http_responses)
1154 {
1155 int res = 0;
1156 std::string stored_mode = get_str_attribute(attrs, RGW_ATTR_CRYPT_MODE);
1157 ldout(s->cct, 15) << "Encryption mode: " << stored_mode << dendl;
1158 if (stored_mode == "SSE-C-AES256") {
1159 if (s->cct->_conf->rgw_crypt_require_ssl &&
1160 !s->info.env->exists("SERVER_PORT_SECURE")) {
1161 ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
1162 return -ERR_INVALID_REQUEST;
1163 }
1164 const char *req_cust_alg =
1165 s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM", NULL);
1166
1167 if ((nullptr == req_cust_alg) || (strcmp(req_cust_alg, "AES256") != 0)) {
1168 ldout(s->cct, 5) << "ERROR: Invalid value for header "
1169 << "x-amz-server-side-encryption-customer-algorithm"
1170 << dendl;
1171 return -ERR_INVALID_REQUEST;
1172 }
1173
1174 std::string key_bin =
1175 from_base64(s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY", ""));
1176 if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
1177 ldout(s->cct, 5) << "ERROR: Invalid encryption key size" << dendl;
1178 return -ERR_INVALID_REQUEST;
1179 }
1180
1181 std::string keymd5 =
1182 s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5", "");
1183 std::string keymd5_bin = from_base64(keymd5);
1184 if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
1185 ldout(s->cct, 5) << "ERROR: Invalid key md5 size " << dendl;
1186 return -ERR_INVALID_DIGEST;
1187 }
1188
1189 MD5 key_hash;
1190 uint8_t key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
1191 key_hash.Update(reinterpret_cast<const byte*>(key_bin.c_str()), key_bin.size());
1192 key_hash.Final(key_hash_res);
1193
1194 if ((memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) ||
1195 (get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYMD5) != keymd5_bin)) {
1196 return -ERR_INVALID_DIGEST;
1197 }
1198 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1199 aes->set_key(reinterpret_cast<const uint8_t*>(key_bin.c_str()), AES_256_CBC::AES_256_KEYSIZE);
1200 if (block_crypt) *block_crypt = std::move(aes);
1201
1202 crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
1203 crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5;
1204 return 0;
1205 }
1206
1207 if (stored_mode == "SSE-KMS") {
1208 if (s->cct->_conf->rgw_crypt_require_ssl &&
1209 !s->info.env->exists("SERVER_PORT_SECURE")) {
1210 ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
1211 return -ERR_INVALID_REQUEST;
1212 }
1213 /* try to retrieve actual key */
1214 std::string key_id = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYID);
1215 std::string key_selector = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYSEL);
1216 std::string actual_key;
1217 res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
1218 if (res != 0) {
1219 ldout(s->cct, 10) << "No encryption key for key-id=" << key_id << dendl;
1220 return res;
1221 }
1222 if (actual_key.size() != AES_256_KEYSIZE) {
1223 ldout(s->cct, 0) << "ERROR: key obtained from key_id:" <<
1224 key_id << " is not 256 bit size" << dendl;
1225 return -ERR_INVALID_ACCESS_KEY;
1226 }
1227
1228 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1229 aes->set_key(reinterpret_cast<const uint8_t*>(actual_key.c_str()), AES_256_KEYSIZE);
1230 actual_key.replace(0, actual_key.length(), actual_key.length(), '\000');
1231 if (block_crypt) *block_crypt = std::move(aes);
1232
1233 crypt_http_responses["x-amz-server-side-encryption"] = "aws:kms";
1234 crypt_http_responses["x-amz-server-side-encryption-aws-kms-key-id"] = key_id;
1235 return 0;
1236 }
1237
1238 if (stored_mode == "RGW-AUTO") {
1239 std::string master_encryption_key =
1240 from_base64(std::string(s->cct->_conf->rgw_crypt_default_encryption_key));
1241 if (master_encryption_key.size() != 256 / 8) {
1242 ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
1243 return -EIO;
1244 }
1245 std::string attr_key_selector = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYSEL);
1246 if (attr_key_selector.size() != AES_256_CBC::AES_256_KEYSIZE) {
1247 ldout(s->cct, 0) << "ERROR: missing or invalid " RGW_ATTR_CRYPT_KEYSEL << dendl;
1248 return -EIO;
1249 }
1250 uint8_t actual_key[AES_256_KEYSIZE];
1251 if (AES_256_ECB_encrypt(s->cct,
1252 reinterpret_cast<const uint8_t*>(master_encryption_key.c_str()),
1253 AES_256_KEYSIZE,
1254 reinterpret_cast<const uint8_t*>(attr_key_selector.c_str()),
1255 actual_key, AES_256_KEYSIZE) != true) {
1256 memset(actual_key, 0, sizeof(actual_key));
1257 return -EIO;
1258 }
1259 auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
1260 aes->set_key(actual_key, AES_256_KEYSIZE);
1261 memset(actual_key, 0, sizeof(actual_key));
1262 if (block_crypt) *block_crypt = std::move(aes);
1263 return 0;
1264 }
1265 /*no decryption*/
1266 return 0;
1267 }