YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/encryption/encryption_util.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/encryption/encryption_util.h"
15
16
#include <openssl/err.h>
17
#include <openssl/rand.h>
18
#include <openssl/ssl.h>
19
20
#include <memory>
21
22
#include <boost/pointer_cast.hpp>
23
24
#include "yb/gutil/casts.h"
25
#include "yb/gutil/endian.h"
26
27
#include "yb/encryption/cipher_stream.h"
28
#include "yb/encryption/encryption.pb.h"
29
#include "yb/encryption/header_manager.h"
30
31
#include "yb/util/atomic.h"
32
#include "yb/util/flag_tags.h"
33
#include "yb/util/logging.h"
34
#include "yb/util/random_util.h"
35
#include "yb/util/status_format.h"
36
37
DEFINE_int64(encryption_counter_min, 0,
38
             "Minimum value (inclusive) for the randomly generated 32-bit encryption counter at "
39
             "the beginning of a file");
40
TAG_FLAG(encryption_counter_min, advanced);
41
TAG_FLAG(encryption_counter_min, hidden);
42
43
DEFINE_int64(encryption_counter_max, 0x7fffffffLL,
44
             "Maximum value (inclusive) for the randomly generated 32-bit encryption counter at "
45
             "the beginning of a file. Setting to 2147483647 by default to reduce the probability "
46
             "of #3707 until it is fixed. This only reduces the key size by 1 bit but eliminates "
47
             "the encryption overflow issue for files up to 32 GiB in size.");
48
49
TAG_FLAG(encryption_counter_max, advanced);
50
TAG_FLAG(encryption_counter_max, hidden);
51
52
DEFINE_test_flag(bool, encryption_use_openssl_compatible_counter_overflow, true,
53
                 "Overflow into the rest of the initialization vector when computing counter"
54
                 "increment for newly created keys.")
55
56
namespace yb {
57
namespace encryption {
58
59
namespace {
60
61
std::vector<std::unique_ptr<std::mutex>> crypto_mutexes;
62
63
}  // anonymous namespace
64
65
constexpr uint32_t kDefaultKeySize = 16;
66
67
67
void EncryptionParams::ToEncryptionParamsPB(EncryptionParamsPB* encryption_header) const {
68
67
  encryption_header->set_data_key(key, key_size);
69
67
  encryption_header->set_nonce(nonce, kBlockSize - 4);
70
67
  encryption_header->set_counter(counter);
71
67
  encryption_header->set_openssl_compatible_counter_overflow(openssl_compatible_counter_overflow);
72
67
}
73
74
Result<EncryptionParamsPtr> EncryptionParams::FromEncryptionParamsPB(
75
109
    const EncryptionParamsPB& encryption_header) {
76
109
  auto encryption_params = std::make_unique<EncryptionParams>();
77
109
  memcpy(encryption_params->key, encryption_header.data_key().c_str(),
78
109
         encryption_header.data_key().size());
79
109
  memcpy(encryption_params->nonce, encryption_header.nonce().c_str(), kBlockSize - 4);
80
109
  encryption_params->counter = encryption_header.counter();
81
109
  auto size = encryption_header.data_key().size();
82
109
  RETURN_NOT_OK(IsValidKeySize(size));
83
109
  encryption_params->key_size = narrow_cast<uint32_t>(size);
84
109
  encryption_params->openssl_compatible_counter_overflow =
85
109
      encryption_header.openssl_compatible_counter_overflow();
86
109
  return encryption_params;
87
109
}
88
89
106
Result<EncryptionParamsPtr> EncryptionParams::FromSlice(const Slice& s) {
90
106
  auto params = std::make_unique<EncryptionParams>();
91
106
  Slice mutable_s(s);
92
106
  memcpy(params->nonce, s.data(), sizeof(params->nonce));
93
106
  memcpy(&params->counter, s.data() + sizeof(params->nonce), sizeof(params->counter));
94
106
  mutable_s.remove_prefix(sizeof(params->nonce) + sizeof(params->counter));
95
106
  RETURN_NOT_OK(IsValidKeySize(mutable_s.size()));
96
106
  memcpy(params->key, mutable_s.data(), mutable_s.size());
97
106
  params->key_size = narrow_cast<uint32_t>(mutable_s.size());
98
106
  return params;
99
106
}
100
101
399k
EncryptionParamsPtr EncryptionParams::NewEncryptionParams() {
102
399k
  auto encryption_params = std::make_unique<EncryptionParams>();
103
399k
  RAND_bytes(encryption_params->key, kDefaultKeySize);
104
399k
  RAND_bytes(encryption_params->nonce, kBlockSize - 4);
105
399k
  RAND_bytes(boost::reinterpret_pointer_cast<uint8_t>(&encryption_params->counter), 4);
106
107
399k
  const int64_t ctr_min = GetAtomicFlag(&FLAGS_encryption_counter_min);
108
399k
  const int64_t ctr_max = GetAtomicFlag(&FLAGS_encryption_counter_max);
109
400k
  if (
0 <= ctr_min399k
&&
ctr_min <= ctr_max400k
&& ctr_max <= std::numeric_limits<uint32_t>::max()) {
110
400k
    encryption_params->counter = narrow_cast<uint32_t>(
111
400k
        ctr_min + encryption_params->counter % (ctr_max - ctr_min + 1));
112
18.4E
  } else {
113
18.4E
    YB_LOG_EVERY_N_SECS(WARNING, 10)
114
0
        << "Invalid encrypted counter range: "
115
0
        << "[" << ctr_min << ", " << ctr_max << "] specified by --encryption_counter_{min,max}, "
116
0
        << "falling back to using the full unsigned 32-bit integer range.";
117
18.4E
  }
118
399k
  encryption_params->key_size = kDefaultKeySize;
119
399k
  encryption_params->openssl_compatible_counter_overflow =
120
399k
      FLAGS_TEST_encryption_use_openssl_compatible_counter_overflow;
121
399k
  return encryption_params;
122
399k
}
123
124
226
Status EncryptionParams::IsValidKeySize(size_t size) {
125
226
  if (size != 16 && 
size != 240
&&
size != 320
) {
126
0
    return STATUS_SUBSTITUTE(
127
0
        InvalidArgument,
128
0
        "After parsing nonce and counter, expect 16, 24, or 32 bytes, found $0", size);
129
0
  }
130
226
  return Status::OK();
131
226
}
132
133
1
bool EncryptionParams::Equals(const EncryptionParams& other) {
134
1
  return memcmp(key, other.key, other.key_size) == 0 &&
135
1
         memcmp(nonce, other.nonce, sizeof(nonce)) == 0 &&
136
1
         counter == other.counter &&
137
1
         key_size == other.key_size &&
138
1
         openssl_compatible_counter_overflow == other.openssl_compatible_counter_overflow;
139
1
}
140
141
205k
void* EncryptionBuffer::GetBuffer(size_t size_needed) {
142
205k
  if (size_needed > size) {
143
789
    size = size_needed;
144
789
    if (buffer) {
145
68
      free(buffer);
146
68
    }
147
789
    buffer = malloc(size_needed);
148
789
  }
149
205k
  return buffer;
150
205k
}
151
152
176
EncryptionBuffer::~EncryptionBuffer() {
153
176
  if (buffer) {
154
176
    free(buffer);
155
176
  }
156
176
}
157
158
205k
EncryptionBuffer* EncryptionBuffer::Get() {
159
205k
  static thread_local EncryptionBuffer encryption_buffer;
160
205k
  return &encryption_buffer;
161
205k
}
162
163
5.31k
Result<uint32_t> GetHeaderSize(SequentialFile* file, HeaderManager* header_manager) {
164
5.31k
  if (!header_manager) {
165
0
    return STATUS(InvalidArgument, "header_manager argument must be non null.");
166
0
  }
167
5.31k
  Slice encryption_info;
168
5.31k
  auto metadata_start = header_manager->GetEncryptionMetadataStartIndex();
169
5.31k
  auto buf = static_cast<uint8_t*>(EncryptionBuffer::Get()->GetBuffer(metadata_start));
170
171
5.31k
  RETURN_NOT_OK(file->Read(metadata_start, &encryption_info, buf));
172
5.31k
  auto status = VERIFY_RESULT(header_manager->GetFileEncryptionStatusFromPrefix(encryption_info));
173
5.31k
  return status.is_encrypted ? 
(status.header_size + metadata_start)4
:
05.30k
;
174
5.31k
}
175
176
class OpenSSLInitializer {
177
 public:
178
15.8k
  OpenSSLInitializer() {
179
15.8k
    SSL_library_init();
180
15.8k
    SSL_load_error_strings();
181
15.8k
    OpenSSL_add_all_algorithms();
182
15.8k
    OpenSSL_add_all_ciphers();
183
15.8k
  }
184
185
145
  ~OpenSSLInitializer() {
186
145
    ERR_free_strings();
187
145
    EVP_cleanup();
188
145
    CRYPTO_cleanup_all_ex_data();
189
145
    ERR_remove_thread_state(nullptr);
190
145
    SSL_COMP_free_compression_methods();
191
145
  }
192
};
193
194
26.6k
OpenSSLInitializer& InitOpenSSL() {
195
26.6k
  static OpenSSLInitializer initializer;
196
26.6k
  return initializer;
197
26.6k
}
198
199
Status CompleteCreateEncryptionInfoForWrite(const std::string& header,
200
                                            std::unique_ptr<EncryptionParams> encryption_params,
201
                                            std::unique_ptr<BlockAccessCipherStream>* stream,
202
40
                                            uint32_t* header_size) {
203
  // Since file doesn't exist or this overwrites, append key to the name and create.
204
40
  *stream = std::make_unique<BlockAccessCipherStream>(std::move(encryption_params));
205
40
  RETURN_NOT_OK((*stream)->Init());
206
40
  if (header.size() > std::numeric_limits<uint32_t>::max()) {
207
0
    return STATUS_FORMAT(Corruption, "Invalid encryption header size: $0", header.size());
208
0
  }
209
40
  *header_size = static_cast<uint32_t>(header.size());
210
40
  return Status::OK();
211
40
}
212
213
} // namespace encryption
214
} // namespace yb