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