YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/encryption/encryption_util.h
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
#ifndef YB_ENCRYPTION_ENCRYPTION_UTIL_H
15
#define YB_ENCRYPTION_ENCRYPTION_UTIL_H
16
17
#include <stdint.h>
18
19
#include <cstdarg>
20
#include <string>
21
22
#include "yb/encryption/cipher_stream.h"
23
#include "yb/encryption/header_manager.h"
24
25
#include "yb/util/status_fwd.h"
26
#include "yb/util/file_system.h"
27
#include "yb/util/result.h"
28
#include "yb/util/status_format.h"
29
30
namespace yb {
31
namespace encryption {
32
33
class EncryptionParamsPB;
34
class RandomAccessFile;
35
class HeaderManager;
36
class BlockAccessCipherStream;
37
class OpenSSLInitializer;
38
39
// Struct generated for encryption status of existing files.
40
struct FileEncryptionStatus {
41
  bool is_encrypted;
42
  uint32_t header_size;
43
};
44
45
// Encryption params consisting of key size 16, 24, or 32, nonce size 12, and counter size 4.
46
struct EncryptionParams {
47
  static constexpr uint32_t kBlockSize = 16;
48
  static constexpr uint32_t kMaxKeySize = 32;
49
50
  uint8_t key[kMaxKeySize];
51
  // Nonce of 12 bytes for encryption.
52
  uint8_t nonce[kBlockSize - sizeof(uint32_t)];
53
  // Counter of 4 bytes incremented for each block.
54
  uint32_t counter;
55
  uint32_t key_size;
56
57
  // When computing counter increment, do we want to overflow the counter into the rest of the
58
  // initialization vector as part of the new format.
59
  bool openssl_compatible_counter_overflow;
60
61
  void ToEncryptionParamsPB(EncryptionParamsPB* encryption_header) const;
62
63
  static Result<std::unique_ptr<EncryptionParams>> FromEncryptionParamsPB(
64
      const EncryptionParamsPB& encryption_header);
65
66
  // Given a slice, convert contents to encryption params. Used to read latest universe key.
67
  static Result<std::unique_ptr<EncryptionParams>> FromSlice(const Slice& s);
68
69
  static std::unique_ptr<EncryptionParams> NewEncryptionParams();
70
71
  static CHECKED_STATUS IsValidKeySize(size_t size);
72
73
  bool Equals(const EncryptionParams& other);
74
};
75
76
typedef std::unique_ptr<EncryptionParams> EncryptionParamsPtr;
77
78
// Since this will typically be passed in by an external user (YW or yb-admin), UniverseKeyId
79
// will be a generic string for ease of use.
80
using UniverseKeyId = std::string;
81
82
struct UniverseKeyParams {
83
  UniverseKeyId version_id;
84
  EncryptionParamsPtr params;
85
};
86
87
// Thread local buffer for any encryption operations.
88
class EncryptionBuffer {
89
 public:
90
  void* GetBuffer(size_t size_needed);
91
  ~EncryptionBuffer();
92
  static EncryptionBuffer* Get();
93
 private:
94
  size_t size = 0;
95
  void* buffer = nullptr;
96
};
97
98
99
// Given a readable file, generate a cipher stream and header size for that file.
100
template <typename BufType, typename Readable>
101
Result<bool> GetEncryptionInfoFromFile(HeaderManager* header_manager,
102
                                       Readable* underlying_r,
103
                                       std::unique_ptr<BlockAccessCipherStream>* stream,
104
1.90M
                                       uint32_t* header_size) {
105
1.90M
  if (!header_manager) {
106
0
    return STATUS(InvalidArgument, "header_manager must be non-null.");
107
0
  }
108
109
1.90M
  Slice encryption_info;
110
1.90M
  auto metadata_start = header_manager->GetEncryptionMetadataStartIndex();
111
1.90M
  auto buf = std::unique_ptr<BufType[]>(new BufType[metadata_start]);
112
1.90M
  RETURN_NOT_OK(underlying_r->Read(0, metadata_start, &encryption_info, buf.get()));
113
1.90M
  auto encryption_status = VERIFY_RESULT(
114
1.90M
      header_manager->GetFileEncryptionStatusFromPrefix(encryption_info));
115
1.90M
  if (!encryption_status.is_encrypted) {
116
1.89M
    return false;
117
1.89M
  }
118
119
1.26k
  *header_size = metadata_start + encryption_status.header_size;
120
1.26k
  buf = std::unique_ptr<BufType[]>(new BufType[*header_size]);
121
1.26k
  RETURN_NOT_OK(underlying_r->Read(
122
1.26k
      metadata_start, encryption_status.header_size, &encryption_info, buf.get()));
123
1.26k
  auto encryption_params = VERIFY_RESULT(
124
1.26k
      header_manager->DecodeEncryptionParamsFromEncryptionMetadata(encryption_info));
125
126
1.26k
  *stream = std::make_unique<BlockAccessCipherStream>(std::move(encryption_params));
127
1.26k
  RETURN_NOT_OK((*stream)->Init());
128
1.26k
  return true;
129
1.26k
}
130
131
CHECKED_STATUS CompleteCreateEncryptionInfoForWrite(
132
    const std::string& header, std::unique_ptr<EncryptionParams> encryption_params,
133
    std::unique_ptr<BlockAccessCipherStream>* stream, uint32_t* header_size);
134
135
// Given a writable file, generate a new stream and header for that file.
136
template <typename Writable>
137
Status CreateEncryptionInfoForWrite(HeaderManager* header_manager,
138
                                    Writable* underlying_w,
139
                                    std::unique_ptr<BlockAccessCipherStream>* stream,
140
39
                                    uint32_t* header_size) {
141
39
  auto encryption_params = EncryptionParams::NewEncryptionParams();
142
39
  string header = VERIFY_RESULT(
143
39
      header_manager->SerializeEncryptionParams(*encryption_params.get()));
144
39
  RETURN_NOT_OK(underlying_w->Append(header));
145
39
  return CompleteCreateEncryptionInfoForWrite(
146
39
      header, std::move(encryption_params), stream, header_size);
147
39
}
_ZN2yb10encryption28CreateEncryptionInfoForWriteINS_12WritableFileEEENS_6StatusEPNS0_13HeaderManagerEPT_PNSt3__110unique_ptrINS0_23BlockAccessCipherStreamENS8_14default_deleteISA_EEEEPj
Line
Count
Source
140
1
                                    uint32_t* header_size) {
141
1
  auto encryption_params = EncryptionParams::NewEncryptionParams();
142
1
  string header = VERIFY_RESULT(
143
1
      header_manager->SerializeEncryptionParams(*encryption_params.get()));
144
1
  RETURN_NOT_OK(underlying_w->Append(header));
145
1
  return CompleteCreateEncryptionInfoForWrite(
146
1
      header, std::move(encryption_params), stream, header_size);
147
1
}
_ZN2yb10encryption28CreateEncryptionInfoForWriteIN7rocksdb12WritableFileEEENS_6StatusEPNS0_13HeaderManagerEPT_PNSt3__110unique_ptrINS0_23BlockAccessCipherStreamENS9_14default_deleteISB_EEEEPj
Line
Count
Source
140
38
                                    uint32_t* header_size) {
141
38
  auto encryption_params = EncryptionParams::NewEncryptionParams();
142
38
  string header = VERIFY_RESULT(
143
38
      header_manager->SerializeEncryptionParams(*encryption_params.get()));
144
38
  RETURN_NOT_OK(underlying_w->Append(header));
145
38
  return CompleteCreateEncryptionInfoForWrite(
146
38
      header, std::move(encryption_params), stream, header_size);
147
38
}
148
149
template <typename EncryptedFile, typename BufType, typename ReadablePtr>
150
Status CreateRandomAccessFile(ReadablePtr* result,
151
                              HeaderManager* header_manager,
152
319k
                              ReadablePtr underlying) {
153
319k
  result->reset();
154
319k
  std::unique_ptr<BlockAccessCipherStream> stream;
155
319k
  uint32_t header_size;
156
157
319k
  const auto file_encrypted = VERIFY_RESULT(GetEncryptionInfoFromFile<BufType>(
158
319k
      header_manager, underlying.get(), &stream, &header_size));
159
160
319k
  if (!file_encrypted) {
161
319k
    *result = std::move(underlying);
162
319k
    return Status::OK();
163
319k
  }
164
165
589
  result->reset(new EncryptedFile(std::move(underlying), std::move(stream), header_size));
166
589
  return Status::OK();
167
589
}
168
169
template <typename EncryptedFile, typename WritablePtr>
170
Status CreateWritableFile(WritablePtr* result,
171
                          HeaderManager* header_manager,
172
3.39M
                          WritablePtr underlying) {
173
3.39M
  result->reset();
174
3.39M
  if (!header_manager->IsEncryptionEnabled()) {
175
3.39M
    *result = std::move(underlying);
176
3.39M
    return Status::OK();
177
3.39M
  }
178
179
18.4E
  std::unique_ptr<BlockAccessCipherStream> stream;
180
18.4E
  uint32_t header_size = 0;
181
18.4E
  RETURN_NOT_OK(CreateEncryptionInfoForWrite(
182
18.4E
      header_manager, underlying.get(), &stream, &header_size));
183
18.4E
  result->reset(new EncryptedFile(std::move(underlying), std::move(stream), header_size));
184
18.4E
  return Status::OK();
185
18.4E
}
_ZN2yb10encryption18CreateWritableFileINS0_21EncryptedWritableFileENSt3__110unique_ptrINS_12WritableFileENS3_14default_deleteIS5_EEEEEENS_6StatusEPT0_PNS0_13HeaderManagerESA_
Line
Count
Source
172
693k
                          WritablePtr underlying) {
173
693k
  result->reset();
174
693k
  if (!header_manager->IsEncryptionEnabled()) {
175
693k
    *result = std::move(underlying);
176
693k
    return Status::OK();
177
693k
  }
178
179
18.4E
  std::unique_ptr<BlockAccessCipherStream> stream;
180
18.4E
  uint32_t header_size = 0;
181
18.4E
  RETURN_NOT_OK(CreateEncryptionInfoForWrite(
182
18.4E
      header_manager, underlying.get(), &stream, &header_size));
183
18.4E
  result->reset(new EncryptedFile(std::move(underlying), std::move(stream), header_size));
184
18.4E
  return Status::OK();
185
18.4E
}
_ZN2yb10encryption18CreateWritableFileINS_28RocksDBEncryptedWritableFileENSt3__110unique_ptrIN7rocksdb12WritableFileENS3_14default_deleteIS6_EEEEEENS_6StatusEPT0_PNS0_13HeaderManagerESB_
Line
Count
Source
172
2.69M
                          WritablePtr underlying) {
173
2.69M
  result->reset();
174
2.69M
  if (!header_manager->IsEncryptionEnabled()) {
175
2.69M
    *result = std::move(underlying);
176
2.69M
    return Status::OK();
177
2.69M
  }
178
179
18.4E
  std::unique_ptr<BlockAccessCipherStream> stream;
180
18.4E
  uint32_t header_size = 0;
181
18.4E
  RETURN_NOT_OK(CreateEncryptionInfoForWrite(
182
18.4E
      header_manager, underlying.get(), &stream, &header_size));
183
18.4E
  result->reset(new EncryptedFile(std::move(underlying), std::move(stream), header_size));
184
18.4E
  return Status::OK();
185
18.4E
}
186
187
Result<uint32_t> GetHeaderSize(SequentialFile* file, HeaderManager* header_manager);
188
189
OpenSSLInitializer& InitOpenSSL();
190
191
} // namespace encryption
192
} // namespace yb
193
194
#endif // YB_ENCRYPTION_ENCRYPTION_UTIL_H