]>
Commit | Line | Data |
---|---|---|
1e59de90 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
11fdf7f2 | 3 | |
7c673cae FG |
4 | /** |
5 | * Crypto filters for Put/Post/Get operations. | |
6 | */ | |
11fdf7f2 | 7 | |
1e59de90 | 8 | #pragma once |
7c673cae | 9 | |
f67539c2 TL |
10 | #include <string_view> |
11 | ||
7c673cae FG |
12 | #include <rgw/rgw_op.h> |
13 | #include <rgw/rgw_rest.h> | |
14 | #include <rgw/rgw_rest_s3.h> | |
11fdf7f2 | 15 | #include "rgw_putobj.h" |
7c673cae FG |
16 | |
17 | /** | |
18 | * \brief Interface for block encryption methods | |
19 | * | |
20 | * Encrypts and decrypts data. | |
21 | * Operations are performed in context of larger stream being divided into blocks. | |
22 | * Each block can be processed independently, but only as a whole. | |
23 | * Part block cannot be properly processed. | |
24 | * Each request must start on block-aligned offset. | |
25 | * Each request should have length that is multiply of block size. | |
26 | * Request with unaligned length is only acceptable for last part of stream. | |
27 | */ | |
28 | class BlockCrypt { | |
29 | public: | |
30 | BlockCrypt(){}; | |
31 | virtual ~BlockCrypt(){}; | |
32 | ||
33 | /** | |
34 | * Determines size of encryption block. | |
35 | * This is usually multiply of key size. | |
36 | * It determines size of chunks that should be passed to \ref encrypt and \ref decrypt. | |
37 | */ | |
38 | virtual size_t get_block_size() = 0; | |
39 | ||
40 | /** | |
41 | * Encrypts data. | |
42 | * Argument \ref stream_offset shows where in generalized stream chunk is located. | |
43 | * Input for encryption is \ref input buffer, with relevant data in range <in_ofs, in_ofs+size). | |
44 | * \ref input and \output may not be the same buffer. | |
45 | * | |
46 | * \params | |
47 | * input - source buffer of data | |
48 | * in_ofs - offset of chunk inside input | |
49 | * size - size of chunk, must be chunk-aligned unless last part is processed | |
50 | * output - destination buffer to encrypt to | |
51 | * stream_offset - location of <in_ofs,in_ofs+size) chunk in data stream, must be chunk-aligned | |
52 | * \return true iff successfully encrypted | |
53 | */ | |
54 | virtual bool encrypt(bufferlist& input, | |
55 | off_t in_ofs, | |
56 | size_t size, | |
57 | bufferlist& output, | |
58 | off_t stream_offset) = 0; | |
59 | ||
60 | /** | |
61 | * Decrypts data. | |
62 | * Argument \ref stream_offset shows where in generalized stream chunk is located. | |
63 | * Input for decryption is \ref input buffer, with relevant data in range <in_ofs, in_ofs+size). | |
64 | * \ref input and \output may not be the same buffer. | |
65 | * | |
66 | * \params | |
67 | * input - source buffer of data | |
68 | * in_ofs - offset of chunk inside input | |
69 | * size - size of chunk, must be chunk-aligned unless last part is processed | |
70 | * output - destination buffer to encrypt to | |
71 | * stream_offset - location of <in_ofs,in_ofs+size) chunk in data stream, must be chunk-aligned | |
72 | * \return true iff successfully encrypted | |
73 | */ | |
74 | virtual bool decrypt(bufferlist& input, | |
75 | off_t in_ofs, | |
76 | size_t size, | |
77 | bufferlist& output, | |
78 | off_t stream_offset) = 0; | |
79 | }; | |
80 | ||
81 | static const size_t AES_256_KEYSIZE = 256 / 8; | |
20effc67 TL |
82 | bool AES_256_ECB_encrypt(const DoutPrefixProvider* dpp, |
83 | CephContext* cct, | |
7c673cae FG |
84 | const uint8_t* key, |
85 | size_t key_size, | |
86 | const uint8_t* data_in, | |
87 | uint8_t* data_out, | |
88 | size_t data_size); | |
89 | ||
90 | class RGWGetObj_BlockDecrypt : public RGWGetObj_Filter { | |
20effc67 | 91 | const DoutPrefixProvider *dpp; |
7c673cae | 92 | CephContext* cct; |
7c673cae FG |
93 | std::unique_ptr<BlockCrypt> crypt; /**< already configured stateless BlockCrypt |
94 | for operations when enough data is accumulated */ | |
95 | off_t enc_begin_skip; /**< amount of data to skip from beginning of received data */ | |
96 | off_t ofs; /**< stream offset of data we expect to show up next through \ref handle_data */ | |
97 | off_t end; /**< stream offset of last byte that is requested */ | |
98 | bufferlist cache; /**< stores extra data that could not (yet) be processed by BlockCrypt */ | |
99 | size_t block_size; /**< snapshot of \ref BlockCrypt.get_block_size() */ | |
aee94f69 | 100 | std::vector<size_t> parts_len; /**< size of parts of multipart object, parsed from manifest */ |
a8e16298 TL |
101 | |
102 | int process(bufferlist& cipher, size_t part_ofs, size_t size); | |
103 | ||
7c673cae | 104 | public: |
20effc67 TL |
105 | RGWGetObj_BlockDecrypt(const DoutPrefixProvider *dpp, |
106 | CephContext* cct, | |
11fdf7f2 | 107 | RGWGetObj_Filter* next, |
aee94f69 TL |
108 | std::unique_ptr<BlockCrypt> crypt, |
109 | std::vector<size_t> parts_len); | |
7c673cae FG |
110 | virtual ~RGWGetObj_BlockDecrypt(); |
111 | ||
112 | virtual int fixup_range(off_t& bl_ofs, | |
113 | off_t& bl_end) override; | |
114 | virtual int handle_data(bufferlist& bl, | |
115 | off_t bl_ofs, | |
116 | off_t bl_len) override; | |
117 | virtual int flush() override; | |
118 | ||
aee94f69 TL |
119 | static int read_manifest_parts(const DoutPrefixProvider *dpp, |
120 | const bufferlist& manifest_bl, | |
121 | std::vector<size_t>& parts_len); | |
7c673cae FG |
122 | }; /* RGWGetObj_BlockDecrypt */ |
123 | ||
124 | ||
11fdf7f2 | 125 | class RGWPutObj_BlockEncrypt : public rgw::putobj::Pipe |
7c673cae | 126 | { |
20effc67 | 127 | const DoutPrefixProvider *dpp; |
7c673cae FG |
128 | CephContext* cct; |
129 | std::unique_ptr<BlockCrypt> crypt; /**< already configured stateless BlockCrypt | |
130 | for operations when enough data is accumulated */ | |
7c673cae | 131 | bufferlist cache; /**< stores extra data that could not (yet) be processed by BlockCrypt */ |
11fdf7f2 | 132 | const size_t block_size; /**< snapshot of \ref BlockCrypt.get_block_size() */ |
7c673cae | 133 | public: |
20effc67 TL |
134 | RGWPutObj_BlockEncrypt(const DoutPrefixProvider *dpp, |
135 | CephContext* cct, | |
136 | rgw::sal::DataProcessor *next, | |
7c673cae | 137 | std::unique_ptr<BlockCrypt> crypt); |
11fdf7f2 TL |
138 | |
139 | int process(bufferlist&& data, uint64_t logical_offset) override; | |
7c673cae FG |
140 | }; /* RGWPutObj_BlockEncrypt */ |
141 | ||
142 | ||
1e59de90 | 143 | int rgw_s3_prepare_encrypt(req_state* s, |
7c673cae | 144 | std::map<std::string, ceph::bufferlist>& attrs, |
7c673cae FG |
145 | std::unique_ptr<BlockCrypt>* block_crypt, |
146 | std::map<std::string, | |
147 | std::string>& crypt_http_responses); | |
148 | ||
1e59de90 | 149 | int rgw_s3_prepare_decrypt(req_state* s, |
7c673cae FG |
150 | std::map<std::string, ceph::bufferlist>& attrs, |
151 | std::unique_ptr<BlockCrypt>* block_crypt, | |
152 | std::map<std::string, | |
153 | std::string>& crypt_http_responses); | |
154 | ||
20effc67 | 155 | static inline void set_attr(std::map<std::string, bufferlist>& attrs, |
f67539c2 TL |
156 | const char* key, |
157 | std::string_view value) | |
158 | { | |
159 | bufferlist bl; | |
160 | bl.append(value.data(), value.size()); | |
161 | attrs[key] = std::move(bl); | |
162 | } | |
163 | ||
20effc67 | 164 | static inline std::string get_str_attribute(std::map<std::string, bufferlist>& attrs, |
f67539c2 TL |
165 | const char *name) |
166 | { | |
167 | auto iter = attrs.find(name); | |
168 | if (iter == attrs.end()) { | |
169 | return {}; | |
170 | } | |
171 | return iter->second.to_str(); | |
172 | } | |
173 | ||
2a845540 | 174 | int rgw_remove_sse_s3_bucket_key(req_state *s); |