1 // Copyright 2018 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/internal/registry_impl.h"
18
19 #include <functional>
20 #include <memory>
21 #include <utility>
22
23 #include "absl/status/status.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/string_view.h"
26 #include "absl/synchronization/mutex.h"
27 #include "tink/input_stream.h"
28 #include "tink/internal/keyset_wrapper_store.h"
29 #include "tink/key_manager.h"
30 #include "tink/monitoring/monitoring.h"
31 #include "tink/util/errors.h"
32 #include "tink/util/status.h"
33 #include "tink/util/statusor.h"
34 #include "proto/tink.pb.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace internal {
39
40 using ::crypto::tink::MonitoringClientFactory;
41 using ::google::crypto::tink::KeyData;
42 using ::google::crypto::tink::KeyTemplate;
43
get_key_type_info(absl::string_view type_url) const44 util::StatusOr<const KeyTypeInfoStore::Info*> RegistryImpl::get_key_type_info(
45 absl::string_view type_url) const {
46 absl::MutexLock lock(&maps_mutex_);
47 return key_type_info_store_.Get(type_url);
48 }
49
NewKeyData(const KeyTemplate & key_template) const50 util::StatusOr<std::unique_ptr<KeyData>> RegistryImpl::NewKeyData(
51 const KeyTemplate& key_template) const {
52 util::StatusOr<const internal::KeyTypeInfoStore::Info*> info =
53 get_key_type_info(key_template.type_url());
54 if (!info.ok()) {
55 return info.status();
56 }
57 if (!(*info)->new_key_allowed()) {
58 return crypto::tink::util::Status(
59 absl::StatusCode::kInvalidArgument,
60 absl::StrCat("KeyManager for type ", key_template.type_url(),
61 " does not allow for creation of new keys."));
62 }
63 return (*info)->key_factory().NewKeyData(key_template.value());
64 }
65
GetPublicKeyData(absl::string_view type_url,absl::string_view serialized_private_key) const66 util::StatusOr<std::unique_ptr<KeyData>> RegistryImpl::GetPublicKeyData(
67 absl::string_view type_url,
68 absl::string_view serialized_private_key) const {
69 util::StatusOr<const internal::KeyTypeInfoStore::Info*> info =
70 get_key_type_info(type_url);
71 if (!info.ok()) {
72 return info.status();
73 }
74 auto factory =
75 dynamic_cast<const PrivateKeyFactory*>(&(*info)->key_factory());
76 if (factory == nullptr) {
77 return ToStatusF(absl::StatusCode::kInvalidArgument,
78 "KeyManager for type '%s' does not have "
79 "a PrivateKeyFactory.",
80 type_url);
81 }
82 auto result = factory->GetPublicKeyData(serialized_private_key);
83 return result;
84 }
85
DeriveKey(const KeyTemplate & key_template,InputStream * randomness) const86 util::StatusOr<KeyData> RegistryImpl::DeriveKey(const KeyTemplate& key_template,
87 InputStream* randomness) const {
88 util::StatusOr<const internal::KeyTypeInfoStore::Info*> info =
89 get_key_type_info(key_template.type_url());
90 if (!info.ok()) {
91 return info.status();
92 }
93 if (!(*info)->key_deriver()) {
94 return crypto::tink::util::Status(
95 absl::StatusCode::kInvalidArgument,
96 absl::StrCat("Manager for type '", key_template.type_url(),
97 "' cannot derive keys."));
98 }
99 return (*info)->key_deriver()(key_template.value(), randomness);
100 }
101
RegisterMonitoringClientFactory(std::unique_ptr<MonitoringClientFactory> factory)102 util::Status RegistryImpl::RegisterMonitoringClientFactory(
103 std::unique_ptr<MonitoringClientFactory> factory) {
104 absl::MutexLock lock(&monitoring_factory_mutex_);
105 if (monitoring_factory_ != nullptr) {
106 return util::Status(absl::StatusCode::kAlreadyExists,
107 "A monitoring factory is already registered");
108 }
109 monitoring_factory_ = std::move(factory);
110 return util::OkStatus();
111 }
112
Reset()113 void RegistryImpl::Reset() {
114 {
115 absl::MutexLock lock(&maps_mutex_);
116 key_type_info_store_ = KeyTypeInfoStore();
117 keyset_wrapper_store_ = KeysetWrapperStore();
118 }
119 {
120 absl::MutexLock lock(&monitoring_factory_mutex_);
121 monitoring_factory_.reset();
122 }
123 }
124
125 } // namespace internal
126 } // namespace tink
127 } // namespace crypto
128