/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 |