]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/include/rocksdb/env_encryption.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / include / rocksdb / env_encryption.h
CommitLineData
11fdf7f2
TL
1// Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
2// This source code is licensed under both the GPLv2 (found in the
3// COPYING file in the root directory) and Apache 2.0 License
4// (found in the LICENSE.Apache file in the root directory).
5
6#pragma once
7
494da23a 8#if !defined(ROCKSDB_LITE)
11fdf7f2
TL
9
10#include <string>
11
20effc67
TL
12#include "rocksdb/env.h"
13#include "rocksdb/rocksdb_namespace.h"
11fdf7f2 14
f67539c2 15namespace ROCKSDB_NAMESPACE {
11fdf7f2
TL
16
17class EncryptionProvider;
18
20effc67
TL
19struct ConfigOptions;
20
494da23a 21// Returns an Env that encrypts data when stored on disk and decrypts data when
11fdf7f2 22// read from disk.
20effc67
TL
23Env* NewEncryptedEnv(Env* base_env,
24 const std::shared_ptr<EncryptionProvider>& provider);
11fdf7f2 25
494da23a
TL
26// BlockAccessCipherStream is the base class for any cipher stream that
27// supports random access at block level (without requiring data from other
28// blocks). E.g. CTR (Counter operation mode) supports this requirement.
11fdf7f2 29class BlockAccessCipherStream {
494da23a
TL
30 public:
31 virtual ~BlockAccessCipherStream(){};
11fdf7f2 32
494da23a
TL
33 // BlockSize returns the size of each block supported by this cipher stream.
34 virtual size_t BlockSize() = 0;
11fdf7f2 35
494da23a
TL
36 // Encrypt one or more (partial) blocks of data at the file offset.
37 // Length of data is given in dataSize.
38 virtual Status Encrypt(uint64_t fileOffset, char* data, size_t dataSize);
11fdf7f2 39
494da23a
TL
40 // Decrypt one or more (partial) blocks of data at the file offset.
41 // Length of data is given in dataSize.
42 virtual Status Decrypt(uint64_t fileOffset, char* data, size_t dataSize);
11fdf7f2 43
494da23a
TL
44 protected:
45 // Allocate scratch space which is passed to EncryptBlock/DecryptBlock.
46 virtual void AllocateScratch(std::string&) = 0;
11fdf7f2 47
494da23a
TL
48 // Encrypt a block of data at the given block index.
49 // Length of data is equal to BlockSize();
50 virtual Status EncryptBlock(uint64_t blockIndex, char* data,
51 char* scratch) = 0;
11fdf7f2 52
494da23a
TL
53 // Decrypt a block of data at the given block index.
54 // Length of data is equal to BlockSize();
55 virtual Status DecryptBlock(uint64_t blockIndex, char* data,
56 char* scratch) = 0;
11fdf7f2
TL
57};
58
494da23a 59// BlockCipher
11fdf7f2 60class BlockCipher {
494da23a
TL
61 public:
62 virtual ~BlockCipher(){};
11fdf7f2 63
20effc67
TL
64 // Creates a new BlockCipher from the input config_options and value
65 // The value describes the type of provider (and potentially optional
66 // configuration parameters) used to create this provider.
67 // For example, if the value is "ROT13", a ROT13BlockCipher is created.
68 //
69 // @param config_options Options to control how this cipher is created
70 // and initialized.
71 // @param value The value might be:
72 // - ROT13 Create a ROT13 Cipher
73 // - ROT13:nn Create a ROT13 Cipher with block size of nn
74 // @param result The new cipher object
75 // @return OK if the cipher was sucessfully created
76 // @return NotFound if an invalid name was specified in the value
77 // @return InvalidArgument if either the options were not valid
78 static Status CreateFromString(const ConfigOptions& config_options,
79 const std::string& value,
80 std::shared_ptr<BlockCipher>* result);
81
82 // Short-cut method to create a ROT13 BlockCipher.
83 // This cipher is only suitable for test purposes and should not be used in
84 // production!!!
85 static std::shared_ptr<BlockCipher> NewROT13Cipher(size_t block_size);
86
87 virtual const char* Name() const = 0;
494da23a
TL
88 // BlockSize returns the size of each block supported by this cipher stream.
89 virtual size_t BlockSize() = 0;
11fdf7f2 90
494da23a
TL
91 // Encrypt a block of data.
92 // Length of data is equal to BlockSize().
93 virtual Status Encrypt(char* data) = 0;
11fdf7f2 94
494da23a
TL
95 // Decrypt a block of data.
96 // Length of data is equal to BlockSize().
97 virtual Status Decrypt(char* data) = 0;
11fdf7f2
TL
98};
99
494da23a
TL
100// The encryption provider is used to create a cipher stream for a specific
101// file. The returned cipher stream will be used for actual
102// encryption/decryption actions.
11fdf7f2
TL
103class EncryptionProvider {
104 public:
494da23a
TL
105 virtual ~EncryptionProvider(){};
106
20effc67
TL
107 // Creates a new EncryptionProvider from the input config_options and value
108 // The value describes the type of provider (and potentially optional
109 // configuration parameters) used to create this provider.
110 // For example, if the value is "CTR", a CTREncryptionProvider will be
111 // created. If the value is preceded by "test://" (e.g test://CTR"), the
112 // TEST_Initialize method will be invoked prior to returning the provider.
113 //
114 // @param config_options Options to control how this provider is created
115 // and initialized.
116 // @param value The value might be:
117 // - CTR Create a CTR provider
118 // - test://CTR Create a CTR provider and initialize it for tests.
119 // @param result The new provider object
120 // @return OK if the provider was sucessfully created
121 // @return NotFound if an invalid name was specified in the value
122 // @return InvalidArgument if either the options were not valid
123 static Status CreateFromString(const ConfigOptions& config_options,
124 const std::string& value,
125 std::shared_ptr<EncryptionProvider>* result);
126
127 // Short-cut method to create a CTR-provider
128 static std::shared_ptr<EncryptionProvider> NewCTRProvider(
129 const std::shared_ptr<BlockCipher>& cipher);
130
131 // Returns the name of this EncryptionProvider
132 virtual const char* Name() const = 0;
133
494da23a
TL
134 // GetPrefixLength returns the length of the prefix that is added to every
135 // file and used for storing encryption options. For optimal performance, the
136 // prefix length should be a multiple of the page size.
20effc67 137 virtual size_t GetPrefixLength() const = 0;
494da23a
TL
138
139 // CreateNewPrefix initialized an allocated block of prefix memory
140 // for a new file.
141 virtual Status CreateNewPrefix(const std::string& fname, char* prefix,
20effc67
TL
142 size_t prefixLength) const = 0;
143
144 // Method to add a new cipher key for use by the EncryptionProvider.
145 // @param description Descriptor for this key.
146 // @param cipher The cryptographic key to use
147 // @param len The length of the cipher key
148 // @param for_write If true, this cipher should be used for writing files.
149 // If false, this cipher should only be used for reading
150 // files
151 // @return OK if the cipher was successfully added to the provider, non-OK
152 // otherwise
153 virtual Status AddCipher(const std::string& descriptor, const char* cipher,
154 size_t len, bool for_write) = 0;
494da23a
TL
155
156 // CreateCipherStream creates a block access cipher stream for a file given
157 // given name and options.
158 virtual Status CreateCipherStream(
159 const std::string& fname, const EnvOptions& options, Slice& prefix,
160 std::unique_ptr<BlockAccessCipherStream>* result) = 0;
11fdf7f2 161
20effc67
TL
162 // Returns a string representing an encryption marker prefix for this
163 // provider. If a marker is provided, this marker can be used to tell whether
164 // or not a file is encrypted by this provider. The maker will also be part
165 // of any encryption prefix for this provider.
166 virtual std::string GetMarker() const { return ""; }
494da23a
TL
167
168 protected:
20effc67
TL
169 // Optional method to initialize an EncryptionProvider in the TEST
170 // environment.
171 virtual Status TEST_Initialize() { return Status::OK(); }
172};
173
174class EncryptedSequentialFile : public SequentialFile {
175 protected:
176 std::unique_ptr<SequentialFile> file_;
177 std::unique_ptr<BlockAccessCipherStream> stream_;
178 uint64_t offset_;
179 size_t prefixLength_;
11fdf7f2
TL
180
181 public:
20effc67
TL
182 // Default ctor. Given underlying sequential file is supposed to be at
183 // offset == prefixLength.
184 EncryptedSequentialFile(std::unique_ptr<SequentialFile>&& f,
185 std::unique_ptr<BlockAccessCipherStream>&& s,
186 size_t prefixLength)
187 : file_(std::move(f)),
188 stream_(std::move(s)),
189 offset_(prefixLength),
190 prefixLength_(prefixLength) {}
191
192 // Read up to "n" bytes from the file. "scratch[0..n-1]" may be
193 // written by this routine. Sets "*result" to the data that was
194 // read (including if fewer than "n" bytes were successfully read).
195 // May set "*result" to point at data in "scratch[0..n-1]", so
196 // "scratch[0..n-1]" must be live when "*result" is used.
197 // If an error was encountered, returns a non-OK status.
198 //
199 // REQUIRES: External synchronization
200 virtual Status Read(size_t n, Slice* result, char* scratch) override;
201
202 // Skip "n" bytes from the file. This is guaranteed to be no
203 // slower that reading the same data, but may be faster.
204 //
205 // If end of file is reached, skipping will stop at the end of the
206 // file, and Skip will return OK.
207 //
208 // REQUIRES: External synchronization
209 virtual Status Skip(uint64_t n) override;
210
211 // Indicates the upper layers if the current SequentialFile implementation
212 // uses direct IO.
213 virtual bool use_direct_io() const override;
214
215 // Use the returned alignment value to allocate
216 // aligned buffer for Direct I/O
217 virtual size_t GetRequiredBufferAlignment() const override;
218
219 // Remove any kind of caching of data from the offset to offset+length
220 // of this file. If the length is 0, then it refers to the end of file.
221 // If the system is not caching the file contents, then this is a noop.
222 virtual Status InvalidateCache(size_t offset, size_t length) override;
223
224 // Positioned Read for direct I/O
225 // If Direct I/O enabled, offset, n, and scratch should be properly aligned
226 virtual Status PositionedRead(uint64_t offset, size_t n, Slice* result,
227 char* scratch) override;
228};
494da23a 229
20effc67
TL
230// A file abstraction for randomly reading the contents of a file.
231class EncryptedRandomAccessFile : public RandomAccessFile {
232 protected:
233 std::unique_ptr<RandomAccessFile> file_;
234 std::unique_ptr<BlockAccessCipherStream> stream_;
235 size_t prefixLength_;
494da23a 236
20effc67
TL
237 public:
238 EncryptedRandomAccessFile(std::unique_ptr<RandomAccessFile>&& f,
239 std::unique_ptr<BlockAccessCipherStream>&& s,
240 size_t prefixLength)
241 : file_(std::move(f)),
242 stream_(std::move(s)),
243 prefixLength_(prefixLength) {}
244
245 // Read up to "n" bytes from the file starting at "offset".
246 // "scratch[0..n-1]" may be written by this routine. Sets "*result"
247 // to the data that was read (including if fewer than "n" bytes were
248 // successfully read). May set "*result" to point at data in
249 // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when
250 // "*result" is used. If an error was encountered, returns a non-OK
251 // status.
252 //
253 // Safe for concurrent use by multiple threads.
254 // If Direct I/O enabled, offset, n, and scratch should be aligned properly.
255 virtual Status Read(uint64_t offset, size_t n, Slice* result,
256 char* scratch) const override;
257
258 // Readahead the file starting from offset by n bytes for caching.
259 virtual Status Prefetch(uint64_t offset, size_t n) override;
260
261 // Tries to get an unique ID for this file that will be the same each time
262 // the file is opened (and will stay the same while the file is open).
263 // Furthermore, it tries to make this ID at most "max_size" bytes. If such an
264 // ID can be created this function returns the length of the ID and places it
265 // in "id"; otherwise, this function returns 0, in which case "id"
266 // may not have been modified.
267 //
268 // This function guarantees, for IDs from a given environment, two unique ids
269 // cannot be made equal to each other by adding arbitrary bytes to one of
270 // them. That is, no unique ID is the prefix of another.
271 //
272 // This function guarantees that the returned ID will not be interpretable as
273 // a single varint.
274 //
275 // Note: these IDs are only valid for the duration of the process.
276 virtual size_t GetUniqueId(char* id, size_t max_size) const override;
277
278 virtual void Hint(AccessPattern pattern) override;
279
280 // Indicates the upper layers if the current RandomAccessFile implementation
281 // uses direct IO.
282 virtual bool use_direct_io() const override;
283
284 // Use the returned alignment value to allocate
285 // aligned buffer for Direct I/O
286 virtual size_t GetRequiredBufferAlignment() const override;
287
288 // Remove any kind of caching of data from the offset to offset+length
289 // of this file. If the length is 0, then it refers to the end of file.
290 // If the system is not caching the file contents, then this is a noop.
291 virtual Status InvalidateCache(size_t offset, size_t length) override;
292};
494da23a 293
20effc67
TL
294// A file abstraction for sequential writing. The implementation
295// must provide buffering since callers may append small fragments
296// at a time to the file.
297class EncryptedWritableFile : public WritableFileWrapper {
298 protected:
299 std::unique_ptr<WritableFile> file_;
300 std::unique_ptr<BlockAccessCipherStream> stream_;
301 size_t prefixLength_;
302
303 public:
304 // Default ctor. Prefix is assumed to be written already.
305 EncryptedWritableFile(std::unique_ptr<WritableFile>&& f,
306 std::unique_ptr<BlockAccessCipherStream>&& s,
307 size_t prefixLength)
308 : WritableFileWrapper(f.get()),
309 file_(std::move(f)),
310 stream_(std::move(s)),
311 prefixLength_(prefixLength) {}
312
313 Status Append(const Slice& data) override;
314
315 Status PositionedAppend(const Slice& data, uint64_t offset) override;
316
317 // Indicates the upper layers if the current WritableFile implementation
318 // uses direct IO.
319 virtual bool use_direct_io() const override;
320
321 // Use the returned alignment value to allocate
322 // aligned buffer for Direct I/O
323 virtual size_t GetRequiredBufferAlignment() const override;
324
325 /*
326 * Get the size of valid data in the file.
327 */
328 virtual uint64_t GetFileSize() override;
329
330 // Truncate is necessary to trim the file to the correct size
331 // before closing. It is not always possible to keep track of the file
332 // size due to whole pages writes. The behavior is undefined if called
333 // with other writes to follow.
334 virtual Status Truncate(uint64_t size) override;
335
336 // Remove any kind of caching of data from the offset to offset+length
337 // of this file. If the length is 0, then it refers to the end of file.
338 // If the system is not caching the file contents, then this is a noop.
339 // This call has no effect on dirty pages in the cache.
340 virtual Status InvalidateCache(size_t offset, size_t length) override;
341
342 // Sync a file range with disk.
343 // offset is the starting byte of the file range to be synchronized.
344 // nbytes specifies the length of the range to be synchronized.
345 // This asks the OS to initiate flushing the cached data to disk,
346 // without waiting for completion.
347 // Default implementation does nothing.
348 virtual Status RangeSync(uint64_t offset, uint64_t nbytes) override;
349
350 // PrepareWrite performs any necessary preparation for a write
351 // before the write actually occurs. This allows for pre-allocation
352 // of space on devices where it can result in less file
353 // fragmentation and/or less waste from over-zealous filesystem
354 // pre-allocation.
355 virtual void PrepareWrite(size_t offset, size_t len) override;
356
357 // Pre-allocates space for a file.
358 virtual Status Allocate(uint64_t offset, uint64_t len) override;
359};
494da23a 360
20effc67
TL
361// A file abstraction for random reading and writing.
362class EncryptedRandomRWFile : public RandomRWFile {
494da23a 363 protected:
20effc67
TL
364 std::unique_ptr<RandomRWFile> file_;
365 std::unique_ptr<BlockAccessCipherStream> stream_;
366 size_t prefixLength_;
367
368 public:
369 EncryptedRandomRWFile(std::unique_ptr<RandomRWFile>&& f,
370 std::unique_ptr<BlockAccessCipherStream>&& s,
371 size_t prefixLength)
372 : file_(std::move(f)),
373 stream_(std::move(s)),
374 prefixLength_(prefixLength) {}
375
376 // Indicates if the class makes use of direct I/O
377 // If false you must pass aligned buffer to Write()
378 virtual bool use_direct_io() const override;
379
380 // Use the returned alignment value to allocate
381 // aligned buffer for Direct I/O
382 virtual size_t GetRequiredBufferAlignment() const override;
383
384 // Write bytes in `data` at offset `offset`, Returns Status::OK() on success.
385 // Pass aligned buffer when use_direct_io() returns true.
386 virtual Status Write(uint64_t offset, const Slice& data) override;
387
388 // Read up to `n` bytes starting from offset `offset` and store them in
389 // result, provided `scratch` size should be at least `n`.
390 // Returns Status::OK() on success.
391 virtual Status Read(uint64_t offset, size_t n, Slice* result,
392 char* scratch) const override;
393
394 virtual Status Flush() override;
395
396 virtual Status Sync() override;
397
398 virtual Status Fsync() override;
399
400 virtual Status Close() override;
11fdf7f2
TL
401};
402
f67539c2 403} // namespace ROCKSDB_NAMESPACE
11fdf7f2
TL
404
405#endif // !defined(ROCKSDB_LITE)