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 #ifndef TINK_REGISTRY_H_ 18 #define TINK_REGISTRY_H_ 19 20 #include <memory> 21 #include <string> 22 23 #include "absl/strings/string_view.h" 24 #include "tink/internal/registry_impl.h" 25 #include "tink/util/status.h" 26 #include "tink/util/statusor.h" 27 28 namespace crypto { 29 namespace tink { 30 31 // Registry for KeyMangers and PrimitiveWrappers. 32 // 33 // It is essentially a big container (map) that for each supported key type 34 // holds a corresponding KeyManager object, which "understands" the key type 35 // (i.e. the KeyManager can instantiate the primitive corresponding to given 36 // key, or can generate new keys of the supported key type). It holds also 37 // a so-called PrimitiveWrapper for each supported primitive, so that it can 38 // wrap a set of primitives (corresponding to a keyset) into a single primitive. 39 // 40 // Registry is initialized at startup, and is later used to instantiate 41 // primitives for given keys or keysets. Keeping KeyManagers for all primitives 42 // in a single Registry (rather than having a separate KeyManager per primitive) 43 // enables modular construction of compound primitives from "simple" ones, e.g., 44 // AES-CTR-HMAC AEAD encryption uses IND-CPA encryption and a MAC. 45 // 46 // Note that regular users will usually not work directly with Registry, but 47 // rather via KeysetHandle::GetPrimitive()-methods, which in the background 48 // query the Registry for specific KeyManagers and PrimitiveWrappers. 49 // Registry is public though, to enable configurations with custom primitives 50 // and KeyManagers. 51 class Registry { 52 public: 53 // Registers the given 'manager' for the key type 'manager->get_key_type()'. 54 template <class ConcreteKeyManager> RegisterKeyManager(std::unique_ptr<ConcreteKeyManager> manager,bool new_key_allowed)55 static crypto::tink::util::Status RegisterKeyManager( 56 std::unique_ptr<ConcreteKeyManager> manager, bool new_key_allowed) { 57 return internal::RegistryImpl::GlobalInstance().RegisterKeyManager( 58 manager.release(), new_key_allowed); 59 } 60 61 template <class KTManager> RegisterKeyTypeManager(std::unique_ptr<KTManager> manager,bool new_key_allowed)62 static crypto::tink::util::Status RegisterKeyTypeManager( 63 std::unique_ptr<KTManager> manager, bool new_key_allowed) { 64 return internal::RegistryImpl::GlobalInstance() 65 .RegisterKeyTypeManager<typename KTManager::KeyProto, 66 typename KTManager::KeyFormatProto, 67 typename KTManager::PrimitiveList>( 68 std::move(manager), new_key_allowed); 69 } 70 71 template <class PrivateKeyTypeManager, class KeyTypeManager> RegisterAsymmetricKeyManagers(std::unique_ptr<PrivateKeyTypeManager> private_key_manager,std::unique_ptr<KeyTypeManager> public_key_manager,bool new_key_allowed)72 static crypto::tink::util::Status RegisterAsymmetricKeyManagers( 73 std::unique_ptr<PrivateKeyTypeManager> private_key_manager, 74 std::unique_ptr<KeyTypeManager> public_key_manager, 75 bool new_key_allowed) { 76 return internal::RegistryImpl::GlobalInstance() 77 .RegisterAsymmetricKeyManagers(private_key_manager.release(), 78 public_key_manager.release(), 79 new_key_allowed); 80 } 81 82 template <class ConcretePrimitiveWrapper> RegisterPrimitiveWrapper(std::unique_ptr<ConcretePrimitiveWrapper> wrapper)83 static crypto::tink::util::Status RegisterPrimitiveWrapper( 84 std::unique_ptr<ConcretePrimitiveWrapper> wrapper) { 85 return internal::RegistryImpl::GlobalInstance().RegisterPrimitiveWrapper( 86 wrapper.release()); 87 } 88 89 // Returns a key manager for the given type_url (if any found). 90 // Keeps the ownership of the manager. Returned key_managers are guaranteed 91 // to stay valid for the lifetime of the binary (with the exception of a user 92 // calling Reset()). 93 // TODO(tholenst): Remove Reset() from the interface, as it could violate this 94 // but should be test only anyhow. 95 template <class P> get_key_manager(absl::string_view type_url)96 static crypto::tink::util::StatusOr<const KeyManager<P>*> get_key_manager( 97 absl::string_view type_url) { 98 return internal::RegistryImpl::GlobalInstance().get_key_manager<P>( 99 type_url); 100 } 101 102 // Convenience method for creating a new primitive for the key given 103 // in 'key_data'. It looks up a KeyManager identified by key_data.type_url, 104 // and calls manager's GetPrimitive(key_data)-method. 105 template <class P> GetPrimitive(const google::crypto::tink::KeyData & key_data)106 static crypto::tink::util::StatusOr<std::unique_ptr<P>> GetPrimitive( 107 const google::crypto::tink::KeyData& key_data) { 108 return internal::RegistryImpl::GlobalInstance().GetPrimitive<P>(key_data); 109 } 110 111 // Generates a new KeyData for the specified 'key_template'. 112 // It looks up a KeyManager identified by key_template.type_url, 113 // and calls KeyManager::NewKeyData. 114 // This method should be used solely for key management. 115 static crypto::tink::util::StatusOr< 116 std::unique_ptr<google::crypto::tink::KeyData>> NewKeyData(const google::crypto::tink::KeyTemplate & key_template)117 NewKeyData(const google::crypto::tink::KeyTemplate& key_template) { 118 return internal::RegistryImpl::GlobalInstance().NewKeyData(key_template); 119 } 120 121 // Convenience method for extracting the public key data from the 122 // private key given in serialized_private_key. 123 // It looks up a KeyManager identified by type_url, whose KeyFactory must be 124 // a PrivateKeyFactory, and calls PrivateKeyFactory::GetPublicKeyData. 125 static crypto::tink::util::StatusOr< 126 std::unique_ptr<google::crypto::tink::KeyData>> GetPublicKeyData(absl::string_view type_url,absl::string_view serialized_private_key)127 GetPublicKeyData(absl::string_view type_url, 128 absl::string_view serialized_private_key) { 129 return internal::RegistryImpl::GlobalInstance().GetPublicKeyData( 130 type_url, serialized_private_key); 131 } 132 133 // Looks up the globally registered PrimitiveWrapper for this primitive 134 // and wraps the given PrimitiveSet with it. 135 template <class P> Wrap(std::unique_ptr<PrimitiveSet<P>> primitive_set)136 static crypto::tink::util::StatusOr<std::unique_ptr<P>> Wrap( 137 std::unique_ptr<PrimitiveSet<P>> primitive_set) { 138 return internal::RegistryImpl::GlobalInstance().Wrap<P>( 139 std::move(primitive_set)); 140 } 141 142 // Resets the registry. 143 // After reset the registry is empty, i.e. it contains neither catalogues 144 // nor key managers. This method is intended for testing only. Reset()145 static void Reset() { 146 return internal::RegistryImpl::GlobalInstance().Reset(); 147 } 148 }; 149 150 } // namespace tink 151 } // namespace crypto 152 153 #endif // TINK_REGISTRY_H_ 154