YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/encryption/header_manager_impl.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/header_manager_impl.h"
15
16
#include <string>
17
18
#include "yb/encryption/cipher_stream_fwd.h"
19
#include "yb/encryption/encryption.pb.h"
20
#include "yb/encryption/header_manager.h"
21
#include "yb/encryption/universe_key_manager.h"
22
23
#include "yb/gutil/casts.h"
24
25
#include "yb/util/status_fwd.h"
26
#include "yb/util/errno.h"
27
#include "yb/util/pb_util.h"
28
#include "yb/util/status_format.h"
29
30
static const string kEncryptionMagic = "encrypt!";
31
32
namespace yb {
33
namespace encryption {
34
35
class HeaderManagerImpl : public HeaderManager {
36
 public:
37
  explicit HeaderManagerImpl(UniverseKeyManager* universe_key_manager)
38
12.2k
      : universe_key_manager_(universe_key_manager) {}
39
40
39
  Result<string> SerializeEncryptionParams(const EncryptionParams& encryption_info) override {
41
    // 1. Generate the EncrytionParamsPB string to be encrypted.
42
39
    EncryptionParamsPB encryption_params_pb;
43
39
    encryption_info.ToEncryptionParamsPB(&encryption_params_pb);
44
39
    string encryption_params_pb_str;
45
39
    encryption_params_pb.SerializeToString(&encryption_params_pb_str);
46
47
    // 2. Encrypt the encryption params with the latest universe key.
48
39
    auto universe_params = VERIFY_RESULT(universe_key_manager_->GetLatestUniverseParams());
49
39
    auto stream = VERIFY_RESULT(BlockAccessCipherStream::FromEncryptionParams(
50
39
        std::move(universe_params.params)));
51
39
    auto encrypted_data_key = static_cast<char*>(
52
39
        EncryptionBuffer::Get()->GetBuffer(encryption_params_pb_str.size()));
53
39
    RETURN_NOT_OK(stream->Encrypt(0, encryption_params_pb_str, encrypted_data_key));
54
55
    // 3. Serialize the universe key id.
56
39
    auto universe_key_id_str = universe_params.version_id;
57
39
    char universe_key_size[sizeof(uint32_t)];
58
39
    BigEndian::Store32(universe_key_size, narrow_cast<uint32_t>(universe_key_id_str.size()));
59
60
    // 4. Serialize the encrypted encryption params.
61
39
    char encrypted_data_key_size[sizeof(uint32_t)];
62
39
    BigEndian::Store32(
63
39
        encrypted_data_key_size, narrow_cast<uint32_t>(encryption_params_pb_str.size()));
64
65
    // 5. Generate the encryption metadata string.
66
39
    auto metadata_str = string(universe_key_size, sizeof(universe_key_size)) + universe_key_id_str +
67
39
                        string(encrypted_data_key_size, sizeof(encrypted_data_key_size)) +
68
39
                        string(encrypted_data_key, encryption_params_pb_str.size());
69
70
    // 6. Serialize the header size.
71
39
    char header_size[sizeof(uint32_t)];
72
39
    BigEndian::Store32(header_size, narrow_cast<uint32_t>(metadata_str.size()));
73
74
39
    return kEncryptionMagic + string(header_size, sizeof(header_size)) + metadata_str;
75
39
  }
76
77
  Result<EncryptionParamsPtr>
78
35
  DecodeEncryptionParamsFromEncryptionMetadata(const Slice& s) override {
79
35
    Slice s_mutable(s);
80
    // 1. Get the size of the universe key id.
81
35
    RETURN_NOT_OK(CheckSliceCanBeDecoded(s_mutable, sizeof(uint32_t), "universe key id size"));
82
35
    auto universe_key_size = BigEndian::Load32(s_mutable.data());
83
35
    s_mutable.remove_prefix(sizeof(uint32_t));
84
85
    // 2. Get the universe key id.
86
35
    RETURN_NOT_OK(CheckSliceCanBeDecoded(s_mutable, universe_key_size, "universe key id"));
87
35
    std::string universe_key_id(s_mutable.cdata(), universe_key_size);
88
35
    s_mutable.remove_prefix(universe_key_size);
89
90
    // 3. Create an encryption stream from the universe key.
91
35
    auto universe_params = VERIFY_RESULT(
92
35
        universe_key_manager_->GetUniverseParamsWithVersion(universe_key_id));
93
35
    auto stream = VERIFY_RESULT(BlockAccessCipherStream::FromEncryptionParams(
94
35
        std::move(universe_params)));
95
96
    // 4. Get the size of the encryption params pb.
97
35
    RETURN_NOT_OK(CheckSliceCanBeDecoded(s_mutable, sizeof(uint32_t), "encryption params size"));
98
35
    auto encryption_params_pb_size = BigEndian::Load32(s_mutable.data());
99
35
    s_mutable.remove_prefix(sizeof(uint32_t));
100
101
    // 5. Decrypt the resulting data key.
102
35
    auto decrypted_data_key = static_cast<uint8_t*>(
103
35
        EncryptionBuffer::Get()->GetBuffer(s_mutable.size()));
104
35
    RETURN_NOT_OK(stream->Decrypt(0, s_mutable, decrypted_data_key));
105
106
    // 6. Convert the resulting decrypted data key into encryption params.
107
35
    RETURN_NOT_OK(CheckSliceCanBeDecoded(
108
35
        s_mutable, encryption_params_pb_size, "encryption params"));
109
35
    auto encryption_params_pb = VERIFY_RESULT(pb_util::ParseFromSlice<EncryptionParamsPB>(
110
35
        Slice(decrypted_data_key, encryption_params_pb_size)));
111
35
    return EncryptionParams::FromEncryptionParamsPB(encryption_params_pb);
112
35
  }
113
114
1.90M
  uint32_t GetEncryptionMetadataStartIndex() override {
115
1.90M
    return narrow_cast<uint32_t>(kEncryptionMagic.size() + sizeof(uint32_t));
116
1.90M
  }
117
118
  Result<FileEncryptionStatus> GetFileEncryptionStatusFromPrefix(
119
1.90M
      const Slice& s) override {
120
1.90M
    FileEncryptionStatus status;
121
1.90M
    status.is_encrypted = s.compare_prefix(Slice(kEncryptionMagic)) == 0;
122
1.90M
    if (status.is_encrypted) {
123
39
      status.header_size = BigEndian::Load32(s.data() + kEncryptionMagic.size());
124
39
    }
125
1.90M
    return status;
126
1.90M
  }
127
128
3.39M
  bool IsEncryptionEnabled() override {
129
3.39M
    return universe_key_manager_->IsEncryptionEnabled();
130
3.39M
  }
131
132
 private:
133
140
  Status CheckSliceCanBeDecoded(const Slice& s, uint32_t expected_length, const string& field) {
134
140
    if (s.size() < expected_length) {
135
0
      return STATUS_SUBSTITUTE(InvalidArgument,
136
0
                               "Error parsing field $0: expect $1 bytes found $2",
137
0
                               field, expected_length, s.size());
138
0
    }
139
140
    return Status::OK();
140
140
  }
141
142
  UniverseKeyManager* universe_key_manager_;
143
144
};
145
146
12.2k
std::unique_ptr<HeaderManager> DefaultHeaderManager(UniverseKeyManager* universe_key_manager) {
147
12.2k
  return std::make_unique<HeaderManagerImpl>(universe_key_manager);
148
12.2k
}
149
150
} // namespace encryption
151
} // namespace yb