xref: /aosp_15_r20/external/tink/cc/core/key_manager_impl.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2019 Google LLC
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 #ifndef TINK_CORE_KEY_MANAGER_IMPL_H_
17 #define TINK_CORE_KEY_MANAGER_IMPL_H_
18 
19 #include <functional>
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 #include "absl/base/casts.h"
25 #include "absl/memory/memory.h"
26 #include "absl/status/status.h"
27 #include "absl/strings/str_cat.h"
28 #include "tink/core/key_type_manager.h"
29 #include "tink/key_manager.h"
30 #include "tink/util/constants.h"
31 #include "tink/util/status.h"
32 #include "proto/tink.pb.h"
33 
34 namespace crypto {
35 namespace tink {
36 namespace internal {
37 
38 // Template declaration of the class "KeyFactoryImpl" with a single template
39 // argument. We first declare it, then later give two "partial template
40 // specializations". This will imply that the KeyFactoryImpl can only be
41 // instantiated with arguments of the form KeyTypeManager<...>.
42 template <class KeyTypeManager>
43 class KeyFactoryImpl;
44 
45 // First partial template specialization for KeyFactoryImpl: the given
46 // KeyTypeManager is of the form KeyTypeManager<KeyProto,
47 // KeyFormatProto, List<Primitives...>>.
48 template <class KeyProto, class KeyFormatProto, class... Primitives>
49 class KeyFactoryImpl<
50     KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>>
51     : public KeyFactory {
52  public:
KeyFactoryImpl(KeyTypeManager<KeyProto,KeyFormatProto,List<Primitives...>> * key_type_manager)53   explicit KeyFactoryImpl(KeyTypeManager<KeyProto, KeyFormatProto,
54                                          List<Primitives...>>* key_type_manager)
55       : key_type_manager_(key_type_manager) {}
56 
57   crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
NewKey(const portable_proto::MessageLite & key_format)58   NewKey(const portable_proto::MessageLite& key_format) const override {
59     if (key_format.GetTypeName() != KeyFormatProto().GetTypeName()) {
60       return crypto::tink::util::Status(
61           absl::StatusCode::kInvalidArgument,
62           absl::StrCat("Key format proto '", key_format.GetTypeName(),
63                        "' is not supported by this manager."));
64     }
65     auto validation = key_type_manager_->ValidateKeyFormat(
66         static_cast<const KeyFormatProto&>(key_format));
67     if (!validation.ok()) {
68       return validation;
69     }
70     crypto::tink::util::StatusOr<KeyProto> new_key_result =
71         key_type_manager_->CreateKey(
72             static_cast<const KeyFormatProto&>(key_format));
73     if (!new_key_result.ok()) return new_key_result.status();
74     return absl::implicit_cast<std::unique_ptr<portable_proto::MessageLite>>(
75         absl::make_unique<KeyProto>(std::move(new_key_result.value())));
76   }
77 
78   crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
NewKey(absl::string_view serialized_key_format)79   NewKey(absl::string_view serialized_key_format) const override {
80     KeyFormatProto key_format;
81     if (!key_format.ParseFromString(std::string(serialized_key_format))) {
82       return crypto::tink::util::Status(
83           absl::StatusCode::kInvalidArgument,
84           absl::StrCat("Could not parse the passed string as proto '",
85                        KeyFormatProto().GetTypeName(), "'."));
86     }
87     auto validation = key_type_manager_->ValidateKeyFormat(key_format);
88     if (!validation.ok()) {
89       return validation;
90     }
91     return NewKey(static_cast<const portable_proto::MessageLite&>(key_format));
92   }
93 
94   crypto::tink::util::StatusOr<std::unique_ptr<google::crypto::tink::KeyData>>
NewKeyData(absl::string_view serialized_key_format)95   NewKeyData(absl::string_view serialized_key_format) const override {
96     auto new_key_result = NewKey(serialized_key_format);
97     if (!new_key_result.ok()) return new_key_result.status();
98     auto new_key = static_cast<const KeyProto&>(*(new_key_result.value()));
99     auto key_data = absl::make_unique<google::crypto::tink::KeyData>();
100     key_data->set_type_url(
101         absl::StrCat(kTypeGoogleapisCom, KeyProto().GetTypeName()));
102     key_data->set_value(new_key.SerializeAsString());
103     key_data->set_key_material_type(key_type_manager_->key_material_type());
104     return std::move(key_data);
105   }
106 
107  private:
108   KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>*
109       key_type_manager_;
110 };
111 
112 // Second partial template specialization for KeyFactoryImpl: the given
113 // KeyTypeManager is of the form KeyTypeManager<KeyProto, void,
114 // List<Primitives...>>.
115 template <class KeyProto, class... Primitives>
116 class KeyFactoryImpl<KeyTypeManager<KeyProto, void, List<Primitives...>>>
117     : public KeyFactory {
118  public:
119   // We don't need the KeyTypeManager, but this is called from a template,
120   // so the easiest way to ignore the argument is to provide a constructor which
121   // ignores the argument.
KeyFactoryImpl(KeyTypeManager<KeyProto,void,List<Primitives...>> * key_type_manager)122   explicit KeyFactoryImpl(
123       KeyTypeManager<KeyProto, void, List<Primitives...>>* key_type_manager) {}
124 
125   crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
NewKey(const portable_proto::MessageLite & key_format)126   NewKey(const portable_proto::MessageLite& key_format) const override {
127     return util::Status(
128         absl::StatusCode::kUnimplemented,
129         "Creating new keys is not supported for this key manager.");
130   }
131 
132   crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
NewKey(absl::string_view serialized_key_format)133   NewKey(absl::string_view serialized_key_format) const override {
134     return util::Status(
135         absl::StatusCode::kUnimplemented,
136         "Creating new keys is not supported for this key manager.");
137   }
138 
139   crypto::tink::util::StatusOr<std::unique_ptr<google::crypto::tink::KeyData>>
NewKeyData(absl::string_view serialized_key_format)140   NewKeyData(absl::string_view serialized_key_format) const override {
141     return util::Status(
142         absl::StatusCode::kUnimplemented,
143         "Creating new keys is not supported for this key manager.");
144   }
145 };
146 
147 // Template declaration of the class "KeyManagerImpl" with two template
148 // arguments. There is only one specialization which is defined, namely when
149 // the KeyTypeManager argument is of the form KeyTypeManager<KeyProto,
150 // KeyFormatProto, List<Primitives...>>. We don't provide a
151 // specialization for the case KeyFormatProto = void, so the compiler will pick
152 // this instantiation in this case.
153 template <class Primitive, class KeyTypeManager>
154 class KeyManagerImpl;
155 
156 // The first template argument to the KeyManagerImpl is the primitive for which
157 // we should generate a KeyManager. The second is the KeyTypeManager, which
158 // takes itself template arguments. The list of the Primitives there must
159 // contain the first Primitive argument (otherwise there will be failures at
160 // runtime).
161 template <class Primitive, class KeyProto, class KeyFormatProto,
162           class... Primitives>
163 class KeyManagerImpl<
164     Primitive, KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>>
165     : public KeyManager<Primitive> {
166  public:
KeyManagerImpl(KeyTypeManager<KeyProto,KeyFormatProto,List<Primitives...>> * key_type_manager)167   explicit KeyManagerImpl(KeyTypeManager<KeyProto, KeyFormatProto,
168                                          List<Primitives...>>* key_type_manager)
169       : key_type_manager_(key_type_manager),
170         key_factory_(
171             absl::make_unique<KeyFactoryImpl<
172                 KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>>>(
173                 key_type_manager_)) {}
174 
175   // Constructs an instance of Primitive for the given 'key_data'.
GetPrimitive(const google::crypto::tink::KeyData & key_data)176   crypto::tink::util::StatusOr<std::unique_ptr<Primitive>> GetPrimitive(
177       const google::crypto::tink::KeyData& key_data) const override {
178     if (!this->DoesSupport(key_data.type_url())) {
179       return ToStatusF(absl::StatusCode::kInvalidArgument,
180                        "Key type '%s' is not supported by this manager.",
181                        key_data.type_url());
182     }
183     KeyProto key_proto;
184     if (!key_proto.ParseFromString(key_data.value())) {
185       return ToStatusF(absl::StatusCode::kInvalidArgument,
186                        "Could not parse key_data.value as key type '%s'.",
187                        key_data.type_url());
188     }
189     auto validation = key_type_manager_->ValidateKey(key_proto);
190     if (!validation.ok()) {
191       return validation;
192     }
193     return key_type_manager_->template GetPrimitive<Primitive>(key_proto);
194   }
195 
GetPrimitive(const portable_proto::MessageLite & key)196   crypto::tink::util::StatusOr<std::unique_ptr<Primitive>> GetPrimitive(
197       const portable_proto::MessageLite& key) const override {
198     std::string key_type = absl::StrCat(kTypeGoogleapisCom, key.GetTypeName());
199     if (!this->DoesSupport(key_type)) {
200       return ToStatusF(absl::StatusCode::kInvalidArgument,
201                        "Key type '%s' is not supported by this manager.",
202                        key_type);
203     }
204     const KeyProto& key_proto = static_cast<const KeyProto&>(key);
205     auto validation = key_type_manager_->ValidateKey(key_proto);
206     if (!validation.ok()) {
207       return validation;
208     }
209     return key_type_manager_->template GetPrimitive<Primitive>(key_proto);
210   }
211 
get_version()212   uint32_t get_version() const override {
213     return key_type_manager_->get_version();
214   }
215 
get_key_type()216   const std::string& get_key_type() const override {
217     return key_type_manager_->get_key_type();
218   }
219 
get_key_factory()220   const KeyFactory& get_key_factory() const override {
221     return *key_factory_;
222   }
223 
224  private:
225   KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>*
226       key_type_manager_;
227   std::unique_ptr<KeyFactory> key_factory_;
228 };
229 
230 // Helper function to create a KeyManager<Primitive> from a KeyTypeManager.
231 // Using this, all template arguments except the first one can be infered.
232 // Example:
233 //   std::unique_ptr<KeyManager<Aead>> km =
234 //     MakeKeyManager<Aead>(my_key_type_manager.get());
235 template <class Primitive, class KeyProto, class KeyFormatProto,
236           class... Primitives>
MakeKeyManager(KeyTypeManager<KeyProto,KeyFormatProto,List<Primitives...>> * key_type_manager)237 std::unique_ptr<KeyManager<Primitive>> MakeKeyManager(
238     KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>*
239         key_type_manager) {
240   return absl::make_unique<
241       KeyManagerImpl<Primitive, KeyTypeManager<KeyProto, KeyFormatProto,
242                                                List<Primitives...>>>>(
243       key_type_manager);
244 }
245 
246 // Creates a function which can derive a key, using the given KeyTypeManager.
247 // Note that the returned function stores a pointer to the given KeyTypeManager,
248 // which must remain valid for the lifetime of the function.
249 template <class KeyProto, class KeyFormatProto, class... Primitives>
250 std::function<crypto::tink::util::StatusOr<google::crypto::tink::KeyData>(
251     absl::string_view, InputStream*)>
CreateDeriverFunctionFor(KeyTypeManager<KeyProto,KeyFormatProto,List<Primitives...>> * key_type_manager)252 CreateDeriverFunctionFor(
253     KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>*
254         key_type_manager) {
255   return [key_type_manager](absl::string_view serialized_key_format,
256                             InputStream* randomness)
257              -> crypto::tink::util::StatusOr<google::crypto::tink::KeyData> {
258     KeyFormatProto key_format;
259     if (!key_format.ParseFromString(std::string(serialized_key_format))) {
260       return crypto::tink::util::Status(
261           absl::StatusCode::kInvalidArgument,
262           absl::StrCat("Could not parse the passed string as proto '",
263                        KeyFormatProto().GetTypeName(), "'."));
264     }
265     auto status = key_type_manager->ValidateKeyFormat(key_format);
266     if (!status.ok()) {
267       return status;
268     }
269     auto key_proto_or = key_type_manager->DeriveKey(key_format, randomness);
270     if (!key_proto_or.ok()) {
271       return key_proto_or.status();
272     }
273     status = key_type_manager->ValidateKey(key_proto_or.value());
274     if (!status.ok()) {
275       return status;
276     }
277     google::crypto::tink::KeyData result;
278     result.set_type_url(key_type_manager->get_key_type());
279     result.set_value(key_proto_or.value().SerializeAsString());
280     result.set_key_material_type(key_type_manager->key_material_type());
281     return std::move(result);
282   };
283 }
284 
285 // Template specialization of CreateDeriverFor in case the KeyTypeManager has
286 // KeyFormatProto = void, and hence there is no key derivation.
287 template <class KeyProto, class... Primitives>
288 std::function<crypto::tink::util::StatusOr<google::crypto::tink::KeyData>(
289     absl::string_view, InputStream*)>
CreateDeriverFunctionFor(KeyTypeManager<KeyProto,void,List<Primitives...>> * key_type_manager)290 CreateDeriverFunctionFor(
291     KeyTypeManager<KeyProto, void, List<Primitives...>>*
292         key_type_manager) {
293   return [key_type_manager](absl::string_view serialized_key_format,
294                             InputStream* randomness)
295              -> crypto::tink::util::StatusOr<google::crypto::tink::KeyData> {
296     return crypto::tink::util::Status(
297         absl::StatusCode::kUnimplemented,
298         absl::StrCat("Registered KeyManager for type '",
299                      key_type_manager->get_key_type(),
300                      "' does not support key generation."));
301   };
302 }
303 
304 }  // namespace internal
305 }  // namespace tink
306 }  // namespace crypto
307 
308 #endif  // TINK_CORE_KEY_MANAGER_IMPL_H_
309