// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef TINK_REGISTRY_H_
#define TINK_REGISTRY_H_

#include <mutex>  // NOLINT(build/c++11)
#include <typeinfo>
#include <unordered_map>

#include "tink/catalogue.h"
#include "tink/key_manager.h"
#include "tink/keyset_handle.h"
#include "tink/primitive_set.h"
#include "tink/util/errors.h"
#include "tink/util/protobuf_helper.h"
#include "tink/util/status.h"
#include "tink/util/validation.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {

// Registry for KeyMangers.
//
// It is essentially a big container (map) that for each supported key
// type holds a corresponding KeyManager object, which "understands"
// the key type (i.e. the KeyManager can instantiate the primitive
// corresponding to given key, or can generate new keys of the
// supported key type).  Registry is initialized at startup, and is
// later used to instantiate primitives for given keys or keysets.
// Keeping KeyManagers for all primitives in a single Registry (rather
// than having a separate KeyManager per primitive) enables modular
// construction of compound primitives from "simple" ones, e.g.,
// AES-CTR-HMAC AEAD encryption uses IND-CPA encryption and a MAC.
//
// Note that regular users will usually not work directly with
// Registry, but rather via primitive factories, which in the
// background query the Registry for specific KeyManagers.  Registry
// is public though, to enable configurations with custom primitives
// and KeyManagers.
class Registry {
 public:
  // Returns a catalogue with the given name (if any found).
  // Keeps the ownership of the catalogue.
  // TODO(przydatek): consider changing return value to
  //   StatusOr<std::reference_wrapper<KeyManager<P>>>
  // (cannot return reference directly, as StatusOr does not support it,
  // see https://goo.gl/x0ymDz)
  template <class P>
  static crypto::tink::util::StatusOr<const Catalogue<P>*> get_catalogue(
      const std::string& catalogue_name);

  // Adds the given 'catalogue' under the specified 'catalogue_name',
  // to enable custom configuration of key types and key managers.
  //
  // Adding a custom catalogue should be a one-time operation,
  // and fails if the given 'catalogue' tries to override
  // an existing, different catalogue for the specified name.
  //
  // Takes ownership of 'catalogue', which must be non-nullptr
  // (in case of failure, 'catalogue' is deleted).
  template <class P>
  static crypto::tink::util::Status AddCatalogue(
      const std::string& catalogue_name, Catalogue<P>* catalogue);

  // Registers the given 'manager' for the key type 'manager->get_key_type()'.
  // Takes ownership of 'manager', which must be non-nullptr.
  template <class P>
  static crypto::tink::util::Status RegisterKeyManager(
      KeyManager<P>* manager, bool new_key_allowed);

  template <class P>
  static crypto::tink::util::Status RegisterKeyManager(KeyManager<P>* manager) {
    return RegisterKeyManager(manager, /* new_key_allowed= */ true);
  }

  // Returns a key manager for the given type_url (if any found).
  // Keeps the ownership of the manager.
  // TODO(przydatek): consider changing return value to
  //   StatusOr<std::reference_wrapper<KeyManager<P>>>
  // (cannot return reference directly, as StatusOr does not support it,
  // see https://goo.gl/x0ymDz)
  template <class P>
  static crypto::tink::util::StatusOr<const KeyManager<P>*> get_key_manager(
      const std::string& type_url);

  // Convenience method for creating a new primitive for the key given
  // in 'key_data'.  It looks up a KeyManager identified by key_data.type_url,
  // and calls manager's GetPrimitive(key_data)-method.
  template <class P>
  static crypto::tink::util::StatusOr<std::unique_ptr<P>> GetPrimitive(
      const google::crypto::tink::KeyData& key_data);

  // Convenience method for creating a new primitive for the key given
  // in 'key'.  It looks up a KeyManager identified by type_url,
  // and calls manager's GetPrimitive(key)-method.
  template <class P>
  static crypto::tink::util::StatusOr<std::unique_ptr<P>> GetPrimitive(
      const std::string& type_url, const portable_proto::MessageLite& key);

  // Creates a set of primitives corresponding to the keys with
  // (status == ENABLED) in the keyset given in 'keyset_handle',
  // assuming all the corresponding key managers are present (keys
  // with (status != ENABLED) are skipped).
  //
  // The returned set is usually later "wrapped" into a class that
  // implements the corresponding Primitive-interface.
  template <class P>
  static crypto::tink::util::StatusOr<std::unique_ptr<PrimitiveSet<P>>>
  GetPrimitives(const KeysetHandle& keyset_handle,
                const KeyManager<P>* custom_manager);

  // Generates a new KeyData for the specified 'key_template'.
  // It looks up a KeyManager identified by key_template.type_url,
  // and calls KeyManager::NewKeyData.
  // This method should be used solely for key management.
  static crypto::tink::util::StatusOr<
    std::unique_ptr<google::crypto::tink::KeyData>>
  NewKeyData(const google::crypto::tink::KeyTemplate& key_template);

  // Convenience method for extracting the public key data from the
  // private key given in serialized_private_key.
  // It looks up a KeyManager identified by type_url, which must
  // be a PrivateKeyManager, and calls PrivateKeyManager::GetPublicKeyData.
  static crypto::tink::util::StatusOr<
    std::unique_ptr<google::crypto::tink::KeyData>>
  GetPublicKeyData(const std::string& type_url,
                   const std::string& serialized_private_key);

  // Resets the registry.
  // After reset the registry is empty, i.e. it contains neither catalogues
  // nor key managers. This method is intended for testing only.
  static void Reset();

 private:
  typedef std::unordered_map<std::string,
                             std::unique_ptr<void, void (*)(void*)>>
      LabelToObjectMap;
  typedef std::unordered_map<std::string, const char*> LabelToTypeNameMap;
  typedef std::unordered_map<std::string, bool> LabelToBoolMap;
  typedef std::unordered_map<std::string, const KeyFactory*>
      LabelToKeyFactoryMap;

  static std::recursive_mutex maps_mutex_;
  // Maps for key manager data.
  static LabelToObjectMap type_to_manager_map_;      // guarded by maps_mutex_
  static LabelToTypeNameMap type_to_primitive_map_;  // guarded by maps_mutex_
  static LabelToBoolMap type_to_new_key_allowed_map_;        // by maps_mutex_
  static LabelToKeyFactoryMap type_to_key_factory_map_;      // by maps_mutex_
  // Maps for catalogue-data.
  static LabelToObjectMap name_to_catalogue_map_;    // guarded by maps_mutex_
  static LabelToTypeNameMap name_to_primitive_map_;  // guarded by maps_mutex_

  static crypto::tink::util::StatusOr<bool> get_new_key_allowed(
      const std::string& type_url);
  static crypto::tink::util::StatusOr<const KeyFactory*> get_key_factory(
      const std::string& type_url);
};

///////////////////////////////////////////////////////////////////////////////
// Implementation details.

template <class P>
void delete_manager(void* t) {
  delete static_cast<KeyManager<P>*>(t);
}

template <class P>
void delete_catalogue(void* t) {
  delete static_cast<Catalogue<P>*>(t);
}

// static
template <class P>
crypto::tink::util::Status Registry::AddCatalogue(
    const std::string& catalogue_name, Catalogue<P>* catalogue) {
  if (catalogue == nullptr) {
    return crypto::tink::util::Status(
        crypto::tink::util::error::INVALID_ARGUMENT,
        "Parameter 'catalogue' must be non-null.");
  }
  std::unique_ptr<void, void (*)(void*)> entry(catalogue, delete_catalogue<P>);
  std::lock_guard<std::recursive_mutex> lock(maps_mutex_);
  auto curr_catalogue = name_to_catalogue_map_.find(catalogue_name);
  if (curr_catalogue != name_to_catalogue_map_.end()) {
    auto existing = static_cast<Catalogue<P>*>(curr_catalogue->second.get());
    if (typeid(*existing).name() != typeid(*catalogue).name()) {
      return ToStatusF(crypto::tink::util::error::ALREADY_EXISTS,
                       "A catalogue named '%s' has been already added.",
                       catalogue_name.c_str());
    }
  } else {
    name_to_catalogue_map_.insert(
        std::make_pair(catalogue_name, std::move(entry)));
    name_to_primitive_map_.insert(
        std::make_pair(catalogue_name, typeid(P).name()));
  }
  return crypto::tink::util::Status::OK;
}

// static
template <class P>
crypto::tink::util::StatusOr<const Catalogue<P>*> Registry::get_catalogue(
    const std::string& catalogue_name) {
  std::lock_guard<std::recursive_mutex> lock(maps_mutex_);
  auto catalogue_entry = name_to_catalogue_map_.find(catalogue_name);
  if (catalogue_entry == name_to_catalogue_map_.end()) {
    return ToStatusF(crypto::tink::util::error::NOT_FOUND,
                     "No catalogue named '%s' has been added.",
                     catalogue_name.c_str());
  }
  if (name_to_primitive_map_[catalogue_name] != typeid(P).name()) {
    return ToStatusF(crypto::tink::util::error::INVALID_ARGUMENT,
                     "Wrong Primitive type for catalogue named '%s': "
                     "got '%s', expected '%s'",
                     catalogue_name.c_str(), typeid(P).name(),
                     name_to_primitive_map_[catalogue_name]);
  }
  return static_cast<Catalogue<P>*>(catalogue_entry->second.get());
}

// static
template <class P>
crypto::tink::util::Status Registry::RegisterKeyManager(
    KeyManager<P>* manager, bool new_key_allowed) {
  if (manager == nullptr) {
    return crypto::tink::util::Status(
        crypto::tink::util::error::INVALID_ARGUMENT,
        "Parameter 'manager' must be non-null.");
  }
  std::string type_url = manager->get_key_type();
  std::unique_ptr<void, void (*)(void*)> entry(manager, delete_manager<P>);
  if (!manager->DoesSupport(type_url)) {
    return ToStatusF(crypto::tink::util::error::INVALID_ARGUMENT,
                     "The manager does not support type '%s'.",
                     type_url.c_str());
  }
  std::lock_guard<std::recursive_mutex> lock(maps_mutex_);
  auto curr_manager = type_to_manager_map_.find(type_url);
  if (curr_manager != type_to_manager_map_.end()) {
    auto existing = static_cast<KeyManager<P>*>(curr_manager->second.get());
    if (typeid(*existing).name() != typeid(*manager).name()) {
      return ToStatusF(crypto::tink::util::error::ALREADY_EXISTS,
                       "A manager for type '%s' has been already registered.",
                       type_url.c_str());
    } else {
      auto curr_new_key_allowed = type_to_new_key_allowed_map_.find(type_url);
      if (!curr_new_key_allowed->second && new_key_allowed) {
        return ToStatusF(crypto::tink::util::error::ALREADY_EXISTS,
                         "A manager for type '%s' has been already registered "
                         "with forbidden new key operation.",
                         type_url.c_str());
      } else {
        curr_new_key_allowed->second = new_key_allowed;
      }
    }
  } else {
    type_to_manager_map_.insert(
        std::make_pair(type_url, std::move(entry)));
    type_to_primitive_map_.insert(
        std::make_pair(type_url, typeid(P).name()));
    type_to_new_key_allowed_map_.insert(
        std::make_pair(type_url, new_key_allowed));
    type_to_key_factory_map_.insert(
        std::make_pair(type_url, &(manager->get_key_factory())));
  }
  return crypto::tink::util::Status::OK;
}

// static
template <class P>
crypto::tink::util::StatusOr<const KeyManager<P>*> Registry::get_key_manager(
    const std::string& type_url) {
  std::lock_guard<std::recursive_mutex> lock(maps_mutex_);
  auto manager_entry = type_to_manager_map_.find(type_url);
  if (manager_entry == type_to_manager_map_.end()) {
    return ToStatusF(crypto::tink::util::error::NOT_FOUND,
                     "No manager for type '%s' has been registered.",
                     type_url.c_str());
  }
  if (type_to_primitive_map_[type_url] != typeid(P).name()) {
    return ToStatusF(crypto::tink::util::error::INVALID_ARGUMENT,
                     "Wrong Primitive type for key type '%s': "
                     "got '%s', expected '%s'",
                     type_url.c_str(), typeid(P).name(),
                     type_to_primitive_map_[type_url]);
  }
  return static_cast<KeyManager<P>*>(manager_entry->second.get());
}

// static
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<P>> Registry::GetPrimitive(
    const google::crypto::tink::KeyData& key_data) {
  auto key_manager_result = get_key_manager<P>(key_data.type_url());
  if (key_manager_result.ok()) {
    return key_manager_result.ValueOrDie()->GetPrimitive(key_data);
  }
  return key_manager_result.status();
}

// static
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<P>> Registry::GetPrimitive(
    const std::string& type_url, const portable_proto::MessageLite& key) {
  auto key_manager_result = get_key_manager<P>(type_url);
  if (key_manager_result.ok()) {
    return key_manager_result.ValueOrDie()->GetPrimitive(key);
  }
  return key_manager_result.status();
}

// static
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<PrimitiveSet<P>>>
Registry::GetPrimitives(const KeysetHandle& keyset_handle,
                        const KeyManager<P>* custom_manager) {
  crypto::tink::util::Status status =
      ValidateKeyset(keyset_handle.get_keyset());
  if (!status.ok()) return status;
  std::unique_ptr<PrimitiveSet<P>> primitives(new PrimitiveSet<P>());
  for (const google::crypto::tink::Keyset::Key& key :
       keyset_handle.get_keyset().key()) {
    if (key.status() == google::crypto::tink::KeyStatusType::ENABLED) {
      std::unique_ptr<P> primitive;
      if (custom_manager != nullptr &&
          custom_manager->DoesSupport(key.key_data().type_url())) {
        auto primitive_result = custom_manager->GetPrimitive(key.key_data());
        if (!primitive_result.ok()) return primitive_result.status();
        primitive = std::move(primitive_result.ValueOrDie());
      } else {
        auto primitive_result = GetPrimitive<P>(key.key_data());
        if (!primitive_result.ok()) return primitive_result.status();
        primitive = std::move(primitive_result.ValueOrDie());
      }
      auto entry_result = primitives->AddPrimitive(std::move(primitive), key);
      if (!entry_result.ok()) return entry_result.status();
      if (key.key_id() == keyset_handle.get_keyset().primary_key_id()) {
        primitives->set_primary(entry_result.ValueOrDie());
      }
    }
  }
  return std::move(primitives);
}

}  // namespace tink
}  // namespace crypto

#endif  // TINK_REGISTRY_H_
