xref: /aosp_15_r20/external/tink/cc/internal/key_parser.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2022 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 
17 #ifndef TINK_INTERNAL_KEY_PARSER_H_
18 #define TINK_INTERNAL_KEY_PARSER_H_
19 
20 #include <functional>
21 #include <memory>
22 #include <string>
23 #include <typeindex>
24 #include <utility>
25 
26 #include "absl/functional/function_ref.h"
27 #include "absl/log/log.h"
28 #include "absl/status/status.h"
29 #include "absl/strings/string_view.h"
30 #include "absl/types/optional.h"
31 #include "tink/internal/parser_index.h"
32 #include "tink/internal/serialization.h"
33 #include "tink/key.h"
34 #include "tink/secret_key_access_token.h"
35 #include "tink/util/status.h"
36 #include "tink/util/statusor.h"
37 
38 namespace crypto {
39 namespace tink {
40 namespace internal {
41 
42 // Non-template base class that can be used with internal registry map.
43 class KeyParser {
44  public:
45   // Parses a `serialization` into a key.
46   //
47   // This function is usually called on a `Serialization` subclass matching the
48   // value returned by `ObjectIdentifier()`. However, implementations should
49   // check that this is the case.
50   virtual util::StatusOr<std::unique_ptr<Key>> ParseKey(
51       const Serialization& serialization,
52       absl::optional<SecretKeyAccessToken> token) const = 0;
53 
54   // Returns the object identifier for `SerializationT`, which is only valid
55   // for the lifetime of this object.
56   //
57   // The object identifier is a unique identifier per registry for this object
58   // (in the standard proto serialization, it is the type URL). In other words,
59   // when registering a `KeyParser`, the registry will invoke this to get
60   // the handled object identifier. In order to parse an object of
61   // `SerializationT`, the registry will then obtain the object identifier of
62   // this serialization object, and call the parser corresponding to this
63   // object.
64   virtual absl::string_view ObjectIdentifier() const = 0;
65 
66   // Returns an index that can be used to look up the `KeyParser`
67   // object registered for the `KeyT` type in a registry.
68   virtual ParserIndex Index() const = 0;
69 
70   virtual ~KeyParser() = default;
71 };
72 
73 // Parses `SerializationT` objects into `KeyT` objects.
74 template <typename SerializationT, typename KeyT>
75 class KeyParserImpl : public KeyParser {
76  public:
77   // Creates a key parser with `object_identifier` and parsing `function`. The
78   // referenced `function` should outlive the created key parser object.
KeyParserImpl(absl::string_view object_identifier,absl::FunctionRef<util::StatusOr<KeyT> (SerializationT,absl::optional<SecretKeyAccessToken>)> function)79   explicit KeyParserImpl(
80       absl::string_view object_identifier,
81       absl::FunctionRef<util::StatusOr<KeyT>(
82           SerializationT, absl::optional<SecretKeyAccessToken>)>
83           function)
84       : object_identifier_(object_identifier), function_(function) {}
85 
ParseKey(const Serialization & serialization,absl::optional<SecretKeyAccessToken> token)86   util::StatusOr<std::unique_ptr<Key>> ParseKey(
87       const Serialization& serialization,
88       absl::optional<SecretKeyAccessToken> token) const override {
89     if (serialization.ObjectIdentifier() != object_identifier_) {
90       return util::Status(absl::StatusCode::kInvalidArgument,
91                           "Invalid object identifier for this key parser.");
92     }
93     const SerializationT* st =
94         dynamic_cast<const SerializationT*>(&serialization);
95     if (st == nullptr) {
96       return util::Status(absl::StatusCode::kInvalidArgument,
97                           "Invalid serialization type for this key parser.");
98     }
99     util::StatusOr<KeyT> key = function_(*st, token);
100     if (!key.ok()) return key.status();
101     return {absl::make_unique<KeyT>(std::move(*key))};
102   }
103 
ObjectIdentifier()104   absl::string_view ObjectIdentifier() const override {
105     return object_identifier_;
106   }
107 
Index()108   ParserIndex Index() const override {
109     return ParserIndex::Create<SerializationT>(object_identifier_);
110   }
111 
112  private:
113   std::string object_identifier_;
114   std::function<util::StatusOr<KeyT>(SerializationT,
115                                      absl::optional<SecretKeyAccessToken>)>
116       function_;
117 };
118 
119 }  // namespace internal
120 }  // namespace tink
121 }  // namespace crypto
122 
123 #endif  // TINK_INTERNAL_KEY_PARSER_H_
124