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