1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/keyset_manager.h"
18
19 #include <memory>
20 #include <utility>
21
22 #include "absl/memory/memory.h"
23 #include "absl/status/status.h"
24 #include "tink/internal/key_gen_configuration_impl.h"
25 #include "tink/key_gen_configuration.h"
26 #include "tink/keyset_handle.h"
27 #include "tink/util/enums.h"
28 #include "tink/util/errors.h"
29 #include "tink/util/status.h"
30 #include "tink/util/statusor.h"
31 #include "proto/tink.pb.h"
32
33 namespace crypto {
34 namespace tink {
35
36 using ::crypto::tink::util::Enums;
37 using ::crypto::tink::util::Status;
38 using ::crypto::tink::util::StatusOr;
39 using google::crypto::tink::Keyset;
40 using google::crypto::tink::KeyStatusType;
41 using google::crypto::tink::KeyTemplate;
42
43 // static
New(const KeyTemplate & key_template)44 StatusOr<std::unique_ptr<KeysetManager>> KeysetManager::New(
45 const KeyTemplate& key_template) {
46 auto manager = absl::make_unique<KeysetManager>();
47 auto rotate_result = manager->Rotate(key_template);
48 if (!rotate_result.ok()) return rotate_result.status();
49 return std::move(manager);
50 }
51
52 // static
New(const KeysetHandle & keyset_handle)53 StatusOr<std::unique_ptr<KeysetManager>> KeysetManager::New(
54 const KeysetHandle& keyset_handle) {
55 auto manager = absl::make_unique<KeysetManager>();
56 absl::MutexLock lock(&manager->keyset_mutex_);
57 manager->keyset_ = keyset_handle.get_keyset();
58 return std::move(manager);
59 }
60
GetKeysetHandle()61 std::unique_ptr<KeysetHandle> KeysetManager::GetKeysetHandle() {
62 absl::MutexLock lock(&keyset_mutex_);
63 std::unique_ptr<Keyset> keyset_copy(new Keyset(keyset_));
64 std::unique_ptr<KeysetHandle> handle(
65 new KeysetHandle(std::move(keyset_copy)));
66 return handle;
67 }
68
Add(const KeyTemplate & key_template)69 StatusOr<uint32_t> KeysetManager::Add(const KeyTemplate& key_template) {
70 return Add(key_template, false);
71 }
72
Add(const google::crypto::tink::KeyTemplate & key_template,bool as_primary)73 StatusOr<uint32_t> KeysetManager::Add(
74 const google::crypto::tink::KeyTemplate& key_template, bool as_primary) {
75 KeyGenConfiguration config;
76 Status status =
77 internal::KeyGenConfigurationImpl::SetGlobalRegistryMode(config);
78 if (!status.ok()) {
79 return status;
80 }
81 absl::MutexLock lock(&keyset_mutex_);
82 return KeysetHandle::AddToKeyset(key_template, as_primary, config, &keyset_);
83 }
84
Rotate(const KeyTemplate & key_template)85 StatusOr<uint32_t> KeysetManager::Rotate(const KeyTemplate& key_template) {
86 return Add(key_template, true);
87 }
88
Enable(uint32_t key_id)89 Status KeysetManager::Enable(uint32_t key_id) {
90 absl::MutexLock lock(&keyset_mutex_);
91 for (auto& key : *(keyset_.mutable_key())) {
92 if (key.key_id() == key_id) {
93 if (key.status() != KeyStatusType::DISABLED &&
94 key.status() != KeyStatusType::ENABLED) {
95 return ToStatusF(absl::StatusCode::kInvalidArgument,
96 "Cannot enable key with key_id %u and status %s.",
97 key_id, Enums::KeyStatusName(key.status()));
98 }
99 key.set_status(KeyStatusType::ENABLED);
100 return util::OkStatus();
101 }
102 }
103 return ToStatusF(absl::StatusCode::kNotFound,
104 "No key with key_id %u found in the keyset.", key_id);
105 }
106
Disable(uint32_t key_id)107 Status KeysetManager::Disable(uint32_t key_id) {
108 absl::MutexLock lock(&keyset_mutex_);
109 if (keyset_.primary_key_id() == key_id) {
110 return ToStatusF(absl::StatusCode::kInvalidArgument,
111 "Cannot disable primary key (key_id %u).", key_id);
112 }
113 for (auto& key : *(keyset_.mutable_key())) {
114 if (key.key_id() == key_id) {
115 if (key.status() != KeyStatusType::DISABLED &&
116 key.status() != KeyStatusType::ENABLED) {
117 return ToStatusF(absl::StatusCode::kInvalidArgument,
118 "Cannot disable key with key_id %u and status %s.",
119 key_id, Enums::KeyStatusName(key.status()));
120 }
121 key.set_status(KeyStatusType::DISABLED);
122 return util::OkStatus();
123 }
124 }
125 return ToStatusF(absl::StatusCode::kNotFound,
126 "No key with key_id %u found in the keyset.", key_id);
127 }
128
Delete(uint32_t key_id)129 Status KeysetManager::Delete(uint32_t key_id) {
130 absl::MutexLock lock(&keyset_mutex_);
131 if (keyset_.primary_key_id() == key_id) {
132 return ToStatusF(absl::StatusCode::kInvalidArgument,
133 "Cannot delete primary key (key_id %u).", key_id);
134 }
135 auto key_field = keyset_.mutable_key();
136 for (auto key_iter = key_field->begin(); key_iter != key_field->end();
137 key_iter++) {
138 auto key = *key_iter;
139 if (key.key_id() == key_id) {
140 keyset_.mutable_key()->erase(key_iter);
141 return util::OkStatus();
142 }
143 }
144 return ToStatusF(absl::StatusCode::kNotFound,
145 "No key with key_id %u found in the keyset.", key_id);
146 }
147
Destroy(uint32_t key_id)148 Status KeysetManager::Destroy(uint32_t key_id) {
149 absl::MutexLock lock(&keyset_mutex_);
150 if (keyset_.primary_key_id() == key_id) {
151 return ToStatusF(absl::StatusCode::kInvalidArgument,
152 "Cannot destroy primary key (key_id %u).", key_id);
153 }
154 for (auto& key : *(keyset_.mutable_key())) {
155 if (key.key_id() == key_id) {
156 if (key.status() != KeyStatusType::DISABLED &&
157 key.status() != KeyStatusType::DESTROYED &&
158 key.status() != KeyStatusType::ENABLED) {
159 return ToStatusF(absl::StatusCode::kInvalidArgument,
160 "Cannot destroy key with key_id %u and status %s.",
161 key_id, Enums::KeyStatusName(key.status()));
162 }
163 key.clear_key_data();
164 key.set_status(KeyStatusType::DESTROYED);
165 return util::OkStatus();
166 }
167 }
168 return ToStatusF(absl::StatusCode::kNotFound,
169 "No key with key_id %u found in the keyset.", key_id);
170 }
171
SetPrimary(uint32_t key_id)172 Status KeysetManager::SetPrimary(uint32_t key_id) {
173 absl::MutexLock lock(&keyset_mutex_);
174 for (auto& key : keyset_.key()) {
175 if (key.key_id() == key_id) {
176 if (key.status() != KeyStatusType::ENABLED) {
177 return ToStatusF(absl::StatusCode::kInvalidArgument,
178 "The candidate for the primary key must be ENABLED"
179 " (key_id %u).",
180 key_id);
181 }
182 keyset_.set_primary_key_id(key_id);
183 return util::OkStatus();
184 }
185 }
186 return ToStatusF(absl::StatusCode::kNotFound,
187 "No key with key_id %u found in the keyset.", key_id);
188 }
189
KeyCount() const190 int KeysetManager::KeyCount() const {
191 absl::MutexLock lock(&keyset_mutex_);
192 return keyset_.key_size();
193 }
194
195 } // namespace tink
196 } // namespace crypto
197