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 8 #if !defined(ROCKSDB_LITE) 9 10 #include "rocksdb/env_encryption.h" 11 12 namespace ROCKSDB_NAMESPACE { 13 14 // Implements a BlockCipher using ROT13. 15 // 16 // Note: This is a sample implementation of BlockCipher, 17 // it is NOT considered safe and should NOT be used in production. 18 class ROT13BlockCipher : public BlockCipher { 19 private: 20 size_t blockSize_; 21 22 public: ROT13BlockCipher(size_t blockSize)23 ROT13BlockCipher(size_t blockSize) : blockSize_(blockSize) {} ~ROT13BlockCipher()24 virtual ~ROT13BlockCipher(){}; 25 const char* Name() const override; 26 // BlockSize returns the size of each block supported by this cipher stream. BlockSize()27 size_t BlockSize() override { return blockSize_; } 28 29 // Encrypt a block of data. 30 // Length of data is equal to BlockSize(). 31 Status Encrypt(char* data) override; 32 33 // Decrypt a block of data. 34 // Length of data is equal to BlockSize(). 35 Status Decrypt(char* data) override; 36 }; 37 38 // CTRCipherStream implements BlockAccessCipherStream using an 39 // Counter operations mode. 40 // See https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation 41 // 42 // Note: This is a possible implementation of BlockAccessCipherStream, 43 // it is considered suitable for use. 44 class CTRCipherStream final : public BlockAccessCipherStream { 45 private: 46 std::shared_ptr<BlockCipher> cipher_; 47 std::string iv_; 48 uint64_t initialCounter_; 49 50 public: CTRCipherStream(const std::shared_ptr<BlockCipher> & c,const char * iv,uint64_t initialCounter)51 CTRCipherStream(const std::shared_ptr<BlockCipher>& c, const char* iv, 52 uint64_t initialCounter) 53 : cipher_(c), iv_(iv, c->BlockSize()), initialCounter_(initialCounter){}; ~CTRCipherStream()54 virtual ~CTRCipherStream(){}; 55 56 // BlockSize returns the size of each block supported by this cipher stream. BlockSize()57 size_t BlockSize() override { return cipher_->BlockSize(); } 58 59 protected: 60 // Allocate scratch space which is passed to EncryptBlock/DecryptBlock. 61 void AllocateScratch(std::string&) override; 62 63 // Encrypt a block of data at the given block index. 64 // Length of data is equal to BlockSize(); 65 Status EncryptBlock(uint64_t blockIndex, char* data, char* scratch) override; 66 67 // Decrypt a block of data at the given block index. 68 // Length of data is equal to BlockSize(); 69 Status DecryptBlock(uint64_t blockIndex, char* data, char* scratch) override; 70 }; 71 72 // This encryption provider uses a CTR cipher stream, with a given block cipher 73 // and IV. 74 // 75 // Note: This is a possible implementation of EncryptionProvider, 76 // it is considered suitable for use, provided a safe BlockCipher is used. 77 class CTREncryptionProvider : public EncryptionProvider { 78 private: 79 std::shared_ptr<BlockCipher> cipher_; 80 81 protected: 82 // For optimal performance when using direct IO, the prefix length should be a 83 // multiple of the page size. This size is to ensure the first real data byte 84 // is placed at largest known alignment point for direct io. 85 const static size_t defaultPrefixLength = 4096; 86 87 public: 88 explicit CTREncryptionProvider( 89 const std::shared_ptr<BlockCipher>& c = nullptr) cipher_(c)90 : cipher_(c){}; ~CTREncryptionProvider()91 virtual ~CTREncryptionProvider() {} 92 93 const char* Name() const override; 94 95 // GetPrefixLength returns the length of the prefix that is added to every 96 // file 97 // and used for storing encryption options. 98 // For optimal performance when using direct IO, the prefix length should be a 99 // multiple of the page size. 100 size_t GetPrefixLength() const override; 101 102 // CreateNewPrefix initialized an allocated block of prefix memory 103 // for a new file. 104 Status CreateNewPrefix(const std::string& fname, char* prefix, 105 size_t prefixLength) const override; 106 107 // CreateCipherStream creates a block access cipher stream for a file given 108 // given name and options. 109 Status CreateCipherStream( 110 const std::string& fname, const EnvOptions& options, Slice& prefix, 111 std::unique_ptr<BlockAccessCipherStream>* result) override; 112 113 Status AddCipher(const std::string& descriptor, const char* /*cipher*/, 114 size_t /*len*/, bool /*for_write*/) override; 115 116 protected: 117 Status TEST_Initialize() override; 118 119 // PopulateSecretPrefixPart initializes the data into a new prefix block 120 // that will be encrypted. This function will store the data in plain text. 121 // It will be encrypted later (before written to disk). 122 // Returns the amount of space (starting from the start of the prefix) 123 // that has been initialized. 124 virtual size_t PopulateSecretPrefixPart(char* prefix, size_t prefixLength, 125 size_t blockSize) const; 126 127 // CreateCipherStreamFromPrefix creates a block access cipher stream for a 128 // file given 129 // given name and options. The given prefix is already decrypted. 130 virtual Status CreateCipherStreamFromPrefix( 131 const std::string& fname, const EnvOptions& options, 132 uint64_t initialCounter, const Slice& iv, const Slice& prefix, 133 std::unique_ptr<BlockAccessCipherStream>* result); 134 }; 135 } // namespace ROCKSDB_NAMESPACE 136 137 #endif // !defined(ROCKSDB_LITE) 138