YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/rocksutil/rocksdb_encrypted_file_factory.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/rocksutil/rocksdb_encrypted_file_factory.h"
15
16
#include "yb/encryption/cipher_stream.h"
17
#include "yb/encryption/encrypted_file.h"
18
#include "yb/encryption/encryption_util.h"
19
#include "yb/encryption/header_manager.h"
20
21
namespace yb {
22
23
// An encrypted file implementation for sequential reads.
24
class EncryptedSequentialFile : public SequentialFileWrapper {
25
 public:
26
  static Status Create(std::unique_ptr<rocksdb::SequentialFile>* result,
27
                       encryption::HeaderManager* header_manager,
28
                       std::unique_ptr<rocksdb::SequentialFile> underlying_seq,
29
2.01M
                       std::unique_ptr<rocksdb::RandomAccessFile> underlying_ra) {
30
2.01M
    result->reset();
31
2.01M
    std::unique_ptr<encryption::BlockAccessCipherStream> stream;
32
2.01M
    uint32_t header_size;
33
34
2.01M
    const auto file_encrypted = VERIFY_RESULT(encryption::GetEncryptionInfoFromFile<uint8_t>(
35
2.01M
        header_manager, underlying_ra.get(), &stream, &header_size));
36
2.01M
    if (!file_encrypted) {
37
2.01M
      *result = std::move(underlying_seq);
38
2.01M
      return Status::OK();
39
2.01M
    }
40
41
1.43k
    RETURN_NOT_OK(underlying_seq->Skip(header_size));
42
1.43k
    *result = std::make_unique<EncryptedSequentialFile>(
43
1.43k
        std::move(underlying_seq), std::move(stream));
44
1.43k
    return Status::OK();
45
1.43k
  }
46
47
  // Default constructor.
48
  EncryptedSequentialFile(std::unique_ptr<rocksdb::SequentialFile> file,
49
                          std::unique_ptr<encryption::BlockAccessCipherStream> stream)
50
19
      : SequentialFileWrapper(std::move(file)), stream_(std::move(stream)) {}
51
52
19
  ~EncryptedSequentialFile() {}
53
54
39
  Status Read(size_t n, Slice* result, uint8_t* scratch) override {
55
39
    if (!scratch) {
56
0
      return STATUS(InvalidArgument, "scratch argument is null.");
57
0
    }
58
39
    uint8_t* buf = static_cast<uint8_t*>(encryption::EncryptionBuffer::Get()->GetBuffer(n));
59
39
    RETURN_NOT_OK(SequentialFileWrapper::Read(n, result, buf));
60
39
    RETURN_NOT_OK(stream_->Decrypt(offset_, *result, scratch));
61
39
    *result = Slice(scratch, result->size());
62
39
    offset_ += result->size();
63
39
    return Status::OK();
64
39
  }
65
66
0
  Status Skip(uint64_t n) override {
67
0
    RETURN_NOT_OK(SequentialFileWrapper::Skip(n));
68
0
    offset_ += n;
69
0
    return Status::OK();
70
0
  }
71
72
 private:
73
  std::unique_ptr<encryption::BlockAccessCipherStream> stream_;
74
  uint64_t offset_ = 0;
75
};
76
77
// An encrypted file implementation for a writable file.
78
class RocksDBEncryptedWritableFile : public rocksdb::WritableFileWrapper {
79
 public:
80
  static Status Create(std::unique_ptr<rocksdb::WritableFile>* result,
81
                       encryption::HeaderManager* header_manager,
82
3.33M
                       std::unique_ptr<rocksdb::WritableFile> underlying) {
83
3.33M
    return encryption::CreateWritableFile<RocksDBEncryptedWritableFile>(
84
3.33M
        result, header_manager, std::move(underlying));
85
3.33M
  }
86
87
  // Default constructor.
88
  RocksDBEncryptedWritableFile(std::unique_ptr<rocksdb::WritableFile> file,
89
                               std::unique_ptr<encryption::BlockAccessCipherStream> stream,
90
                               uint32_t header_size)
91
      : WritableFileWrapper(std::move(file)), stream_(std::move(stream)),
92
39
        header_size_(header_size) {}
93
94
39
  ~RocksDBEncryptedWritableFile() {}
95
96
99.6k
  Status Append(const Slice& data) override {
97
99.6k
    if (data.size() > 0) {
98
99.6k
      char* buf = static_cast<char*>(encryption::EncryptionBuffer::Get()->GetBuffer(data.size()));
99
99.6k
      RETURN_NOT_OK(stream_->Encrypt(GetFileSize() - header_size_, data, buf));
100
99.6k
      RETURN_NOT_OK(WritableFileWrapper::Append(Slice(buf, data.size())));
101
99.6k
    }
102
99.6k
    return Status::OK();
103
99.6k
  }
104
105
 private:
106
  std::unique_ptr<encryption::BlockAccessCipherStream> stream_;
107
  uint32_t header_size_;
108
};
109
110
// EncryptedEnv implements an Env wrapper that adds encryption to files stored on disk.
111
class RocksDBEncryptedFileFactory : public rocksdb::RocksDBFileFactoryWrapper {
112
 public:
113
  explicit RocksDBEncryptedFileFactory(
114
      rocksdb::RocksDBFileFactory* factory,
115
      std::unique_ptr<encryption::HeaderManager> header_manager) :
116
      RocksDBFileFactoryWrapper(factory),
117
9.28k
      header_manager_(std::move(header_manager)) {
118
9.28k
    VLOG
(1) << "Created RocksDB encrypted env"0
;
119
9.28k
  }
120
121
165
  ~RocksDBEncryptedFileFactory() {}
122
123
  // NewRandomAccessFile opens a file for random read access.
124
  Status NewRandomAccessFile(const std::string& fname,
125
                             std::unique_ptr<rocksdb::RandomAccessFile>* result,
126
12.1k
                             const rocksdb::EnvOptions& options) override {
127
12.1k
    std::unique_ptr<rocksdb::RandomAccessFile> underlying;
128
12.1k
    RETURN_NOT_OK(RocksDBFileFactoryWrapper::NewRandomAccessFile(fname, &underlying, options));
129
12.1k
    return encryption::EncryptedRandomAccessFile::Create(
130
12.1k
        result, header_manager_.get(), std::move(underlying));
131
12.1k
  }
132
133
  Status NewWritableFile(const std::string& fname, std::unique_ptr<rocksdb::WritableFile>* result,
134
3.33M
                         const rocksdb::EnvOptions& options) override {
135
3.33M
    std::unique_ptr<rocksdb::WritableFile> underlying;
136
3.33M
    RETURN_NOT_OK(RocksDBFileFactoryWrapper::NewWritableFile(fname, &underlying, options));
137
3.33M
    return RocksDBEncryptedWritableFile::Create(
138
3.33M
        result, header_manager_.get(), std::move(underlying));
139
3.33M
  }
140
141
  Status NewSequentialFile(const std::string& fname,
142
                           std::unique_ptr<rocksdb::SequentialFile>* result,
143
2.01M
                           const rocksdb::EnvOptions& options) override {
144
    // Open file using underlying Env implementation
145
2.01M
    std::unique_ptr<rocksdb::RandomAccessFile> underlying_ra;
146
2.01M
    RETURN_NOT_OK(RocksDBFileFactoryWrapper::NewRandomAccessFile(fname, &underlying_ra, options));
147
148
2.01M
    std::unique_ptr<rocksdb::SequentialFile> underlying_seq;
149
2.01M
    RETURN_NOT_OK(RocksDBFileFactoryWrapper::NewSequentialFile(fname, &underlying_seq, options));
150
151
2.01M
    return EncryptedSequentialFile::Create(
152
2.01M
        result, header_manager_.get(), std::move(underlying_seq), std::move(underlying_ra));
153
2.01M
  }
154
155
5.30k
  Status GetFileSize(const std::string& fname, uint64_t* size) override {
156
5.30k
    RETURN_NOT_OK(RocksDBFileFactoryWrapper::GetFileSize(fname, size));
157
    // Determine if file is encrypted.
158
5.30k
    std::unique_ptr<rocksdb::SequentialFile> underlying;
159
5.30k
    RETURN_NOT_OK(RocksDBFileFactoryWrapper::NewSequentialFile(
160
5.30k
        fname, &underlying, rocksdb::EnvOptions()));
161
162
5.30k
    *size -= VERIFY_RESULT(encryption::GetHeaderSize(underlying.get(), header_manager_.get()));
163
0
    return Status::OK();
164
5.30k
  }
165
166
4
  bool IsPlainText() const override {
167
4
    return false;
168
4
  }
169
170
 private:
171
  std::unique_ptr<encryption::HeaderManager> header_manager_;
172
};
173
174
std::unique_ptr<rocksdb::Env> NewRocksDBEncryptedEnv(
175
9.28k
    std::unique_ptr<encryption::HeaderManager> header_manager) {
176
9.28k
  auto file_factory = rocksdb::Env::DefaultFileFactory();
177
9.28k
  auto encrypted_file_factory = std::make_unique<RocksDBEncryptedFileFactory>(
178
9.28k
      file_factory, std::move(header_manager));
179
9.28k
  auto encrypted_env = rocksdb::Env::NewRocksDBDefaultEnv(std::move(encrypted_file_factory));
180
9.28k
  return encrypted_env;
181
9.28k
}
182
183
} // namespace yb