// 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.
//
////////////////////////////////////////////////////////////////////////////////

#include <memory>
#include <string>
#include <thread>  // NOLINT(build/c++11)
#include <utility>
#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "openssl/crypto.h"
#include "tink/aead.h"
#include "tink/aead/aead_wrapper.h"
#include "tink/aead/aes_gcm_key_manager.h"
#include "tink/catalogue.h"
#include "tink/config/tink_fips.h"
#include "tink/core/key_manager_impl.h"
#include "tink/core/key_type_manager.h"
#include "tink/crypto_format.h"
#include "tink/hybrid/ecies_aead_hkdf_private_key_manager.h"
#include "tink/hybrid/ecies_aead_hkdf_public_key_manager.h"
#include "tink/keyset_manager.h"
#include "tink/monitoring/monitoring.h"
#include "tink/monitoring/monitoring_client_mocks.h"
#include "tink/registry.h"
#include "tink/subtle/aes_gcm_boringssl.h"
#include "tink/subtle/random.h"
#include "tink/util/istream_input_stream.h"
#include "tink/util/protobuf_helper.h"
#include "tink/util/secret_data.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"
#include "tink/util/test_keyset_handle.h"
#include "tink/util/test_matchers.h"
#include "tink/util/test_util.h"
#include "proto/aes_ctr_hmac_aead.pb.h"
#include "proto/aes_gcm.pb.h"
#include "proto/common.pb.h"
#include "proto/ecdsa.pb.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {
namespace internal {

namespace {

using ::crypto::tink::test::AddLegacyKey;
using ::crypto::tink::test::AddRawKey;
using ::crypto::tink::test::AddTinkKey;
using ::crypto::tink::test::DummyAead;
using ::crypto::tink::test::IsOk;
using ::crypto::tink::test::StatusIs;
using ::crypto::tink::util::Status;
using ::google::crypto::tink::AesCtrHmacAeadKey;
using ::google::crypto::tink::AesGcmKey;
using ::google::crypto::tink::AesGcmKeyFormat;
using ::google::crypto::tink::EcdsaKeyFormat;
using ::google::crypto::tink::EcdsaPrivateKey;
using ::google::crypto::tink::EcdsaPublicKey;
using ::google::crypto::tink::EcdsaSignatureEncoding;
using ::google::crypto::tink::EcPointFormat;
using ::google::crypto::tink::EllipticCurveType;
using ::google::crypto::tink::HashType;
using ::google::crypto::tink::KeyData;
using ::google::crypto::tink::Keyset;
using ::google::crypto::tink::KeysetInfo;
using ::google::crypto::tink::KeyStatusType;
using ::google::crypto::tink::KeyTemplate;
using ::google::crypto::tink::OutputPrefixType;
using ::portable_proto::MessageLite;
using ::testing::Eq;
using ::testing::HasSubstr;
using ::testing::IsNull;
using ::testing::Not;
using ::testing::SizeIs;

class RegistryTest : public ::testing::Test {
 protected:
  void SetUp() override {
    Registry::Reset();
  }

  void TearDown() override {
    // Reset is needed here to ensure Mock objects get deleted and do not leak.
    Registry::Reset();
  }
};

class TestKeyFactory : public KeyFactory {
 public:
  explicit TestKeyFactory(const std::string& key_type) : key_type_(key_type) {}

  util::StatusOr<std::unique_ptr<portable_proto::MessageLite>> NewKey(
      const MessageLite& key_format) const override {
    return util::Status(absl::StatusCode::kUnknown,
                        "TestKeyFactory cannot produce a key");
  }

  util::StatusOr<std::unique_ptr<portable_proto::MessageLite>> NewKey(
      absl::string_view serialized_key_format) const override {
    return util::Status(absl::StatusCode::kUnknown,
                        "TestKeyFactory cannot produce a key");
  }

  util::StatusOr<std::unique_ptr<KeyData>> NewKeyData(
      absl::string_view serialized_key_format) const override {
    auto key_data = absl::make_unique<KeyData>();
    key_data->set_type_url(key_type_);
    key_data->set_value(std::string(serialized_key_format));
    return std::move(key_data);
  }

 private:
  std::string key_type_;
};

class TestAeadKeyManager : public KeyManager<Aead> {
 public:
  explicit TestAeadKeyManager(const std::string& key_type)
      : key_type_(key_type), key_factory_(key_type) {}

  util::StatusOr<std::unique_ptr<Aead>>
  GetPrimitive(const KeyData& key) const override {
    std::unique_ptr<Aead> aead(new DummyAead(key_type_));
    return std::move(aead);
  }

  util::StatusOr<std::unique_ptr<Aead>>
  GetPrimitive(const MessageLite& key) const override {
    return util::Status(absl::StatusCode::kUnknown,
                        "TestKeyFactory cannot construct an aead");
  }


  uint32_t get_version() const override {
    return 0;
  }

  const std::string& get_key_type() const override { return key_type_; }

  const KeyFactory& get_key_factory() const override {
    return key_factory_;
  }

 private:
  std::string key_type_;
  TestKeyFactory key_factory_;
};

// A class for testing. We will construct objects from an aead key, so that we
// can check that a keymanager can handle multiple primitives. It is really
// insecure, as it does nothing except provide access to the key.
class AeadVariant {
 public:
  explicit AeadVariant(std::string s) : s_(s) {}

  std::string get() { return s_; }

 private:
  std::string s_;
};

class ExampleKeyTypeManager : public KeyTypeManager<AesGcmKey, AesGcmKeyFormat,
                                                    List<Aead, AeadVariant>> {
 public:
  class AeadFactory : public PrimitiveFactory<Aead> {
   public:
    crypto::tink::util::StatusOr<std::unique_ptr<Aead>> Create(
        const AesGcmKey& key) const override {
      // Ignore the key and returned one with a fixed size for this test.
      return {subtle::AesGcmBoringSsl::New(
          util::SecretDataFromStringView(key.key_value()))};
    }
  };

  class AeadVariantFactory : public PrimitiveFactory<AeadVariant> {
   public:
    crypto::tink::util::StatusOr<std::unique_ptr<AeadVariant>> Create(
        const AesGcmKey& key) const override {
      return absl::make_unique<AeadVariant>(key.key_value());
    }
  };

  ExampleKeyTypeManager()
      : KeyTypeManager(absl::make_unique<AeadFactory>(),
                       absl::make_unique<AeadVariantFactory>()) {}

  google::crypto::tink::KeyData::KeyMaterialType key_material_type()
      const override {
    return google::crypto::tink::KeyData::SYMMETRIC;
  }

  uint32_t get_version() const override { return kVersion; }

  const std::string& get_key_type() const override { return kKeyType; }

  crypto::tink::util::Status ValidateKey(const AesGcmKey& key) const override {
    return util::OkStatus();
  }

  crypto::tink::util::Status ValidateKeyFormat(
      const AesGcmKeyFormat& key_format) const override {
    return util::OkStatus();
  }

  crypto::tink::util::StatusOr<AesGcmKey> CreateKey(
      const AesGcmKeyFormat& key_format) const override {
    AesGcmKey result;
    result.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size()));
    return result;
  }

  crypto::tink::util::StatusOr<AesGcmKey> DeriveKey(
      const AesGcmKeyFormat& key_format,
      InputStream* input_stream) const override {
    // Note: in an actual key type manager we need to do more work, e.g., test
    // that the generated key is long enough.
    crypto::tink::util::StatusOr<std::string> randomness =
        ReadBytesFromStream(key_format.key_size(), input_stream);
    if (!randomness.status().ok()) {
      return randomness.status();
    }
    AesGcmKey key;
    key.set_key_value(randomness.value());
    return key;
  }

  MOCK_METHOD(FipsCompatibility, FipsStatus, (), (const, override));

 private:
  static constexpr int kVersion = 0;
  const std::string kKeyType =
      "type.googleapis.com/google.crypto.tink.AesGcmKey";
};

template <typename P, typename Q = P>
class TestWrapper : public PrimitiveWrapper<P, Q> {
 public:
  TestWrapper() {}
  crypto::tink::util::StatusOr<std::unique_ptr<Q>> Wrap(
      std::unique_ptr<PrimitiveSet<P>> primitive_set) const override {
    return util::Status(absl::StatusCode::kUnimplemented,
                        "This is a test wrapper.");
  }
};

class AeadVariantWrapper : public PrimitiveWrapper<AeadVariant, AeadVariant> {
 public:
  crypto::tink::util::StatusOr<std::unique_ptr<AeadVariant>> Wrap(
      std::unique_ptr<PrimitiveSet<AeadVariant>> primitive_set) const override {
    return absl::make_unique<AeadVariant>(
        primitive_set->get_primary()->get_primitive().get());
  }
};

class AeadVariantToStringWrapper
    : public PrimitiveWrapper<AeadVariant, std::string> {
 public:
  crypto::tink::util::StatusOr<std::unique_ptr<std::string>> Wrap(
      std::unique_ptr<PrimitiveSet<AeadVariant>> primitive_set) const override {
    return absl::make_unique<std::string>(
        primitive_set->get_primary()->get_primitive().get());
  }
};

void register_test_managers(const std::string& key_type_prefix,
                            int manager_count) {
  for (int i = 0; i < manager_count; i++) {
    std::string key_type = key_type_prefix + std::to_string(i);
    util::Status status = Registry::RegisterKeyManager(
        new TestAeadKeyManager(key_type));
    EXPECT_TRUE(status.ok()) << status;
  }
}

void verify_test_managers(const std::string& key_type_prefix,
                          int manager_count) {
  for (int i = 0; i < manager_count; i++) {
    std::string key_type = key_type_prefix + std::to_string(i);
    auto manager_result = Registry::get_key_manager<Aead>(key_type);
    EXPECT_TRUE(manager_result.ok()) << manager_result.status();
    auto manager = manager_result.value();
    EXPECT_EQ(key_type, manager->get_key_type());
  }
}

TEST_F(RegistryTest, testRegisterKeyManagerMoreRestrictiveNewKeyAllowed) {
  std::string key_type = "some_key_type";
  KeyTemplate key_template;
  key_template.set_type_url(key_type);

  // Register the key manager with new_key_allowed == true and verify that
  // new key data can be created.
  util::Status status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type),
      /* new_key_allowed= */ true);
  EXPECT_TRUE(status.ok()) << status;

  auto result_before = Registry::NewKeyData(key_template);
  EXPECT_TRUE(result_before.ok()) << result_before.status();

  // Re-register the key manager with new_key_allowed == false and check the
  // restriction (i.e. new key data cannot be created).
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type),
      /* new_key_allowed= */ false);
  EXPECT_TRUE(status.ok()) << status;

  auto result_after = Registry::NewKeyData(key_template);
  EXPECT_FALSE(result_after.ok());
  EXPECT_EQ(absl::StatusCode::kInvalidArgument, result_after.status().code());
  EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type,
                      std::string(result_after.status().message()));
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow",
                      std::string(result_after.status().message()));
}

TEST_F(RegistryTest, testRegisterKeyManagerLessRestrictiveNewKeyAllowed) {
  std::string key_type = "some_key_type";
  KeyTemplate key_template;
  key_template.set_type_url(key_type);

  // Register the key manager with new_key_allowed == false.
  util::Status status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type),
      /* new_key_allowed= */ false);
  EXPECT_TRUE(status.ok()) << status;

  // Verify that re-registering the key manager with new_key_allowed == true is
  // not possible and that the restriction still holds after that operation
  // (i.e. new key data cannot be created).
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type),
      /* new_key_allowed= */ true);
  EXPECT_FALSE(status.ok());
  EXPECT_EQ(absl::StatusCode::kAlreadyExists, status.code()) << status;
  EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type,
                      std::string(status.message()))
      << status;
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "forbidden new key operation",
                      std::string(status.message()))
      << status;

  auto result_after = Registry::NewKeyData(key_template);
  EXPECT_FALSE(result_after.ok());
  EXPECT_EQ(absl::StatusCode::kInvalidArgument, result_after.status().code());
  EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type,
                      std::string(result_after.status().message()));
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow",
                      std::string(result_after.status().message()));
}

TEST_F(RegistryTest, testConcurrentRegistration) {
  std::string key_type_prefix_a = "key_type_a_";
  std::string key_type_prefix_b = "key_type_b_";
  int count_a = 42;
  int count_b = 72;

  // Register some managers.
  std::thread register_a(register_test_managers,
                         key_type_prefix_a, count_a);
  std::thread register_b(register_test_managers,
                         key_type_prefix_b, count_b);
  register_a.join();
  register_b.join();

  // Check that the managers were registered. Also, keep registering new
  // versions while we check.
  std::thread register_more_a(register_test_managers, key_type_prefix_a,
                              count_a);
  std::thread register_more_b(register_test_managers, key_type_prefix_b,
                              count_b);
  std::thread verify_a(verify_test_managers, key_type_prefix_a, count_a);
  std::thread verify_b(verify_test_managers, key_type_prefix_b, count_b);
  verify_a.join();
  verify_b.join();
  register_more_a.join();
  register_more_b.join();

  // Check that there are no extra managers.
  std::string key_type = key_type_prefix_a + std::to_string(count_a - 1);
  auto manager_result = Registry::get_key_manager<Aead>(key_type);
  EXPECT_TRUE(manager_result.ok()) << manager_result.status();
  EXPECT_EQ(key_type, manager_result.value()->get_key_type());

  key_type = key_type_prefix_a + std::to_string(count_a);
  manager_result = Registry::get_key_manager<Aead>(key_type);
  EXPECT_FALSE(manager_result.ok());
  EXPECT_EQ(absl::StatusCode::kNotFound, manager_result.status().code());
}

TEST_F(RegistryTest, testBasic) {
  std::string key_type_1 = "google.crypto.tink.AesCtrHmacAeadKey";
  std::string key_type_2 = "google.crypto.tink.AesGcmKey";
  auto manager_result = Registry::get_key_manager<Aead>(key_type_1);
  EXPECT_FALSE(manager_result.ok());
  EXPECT_EQ(absl::StatusCode::kNotFound, manager_result.status().code());

  auto status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_1), true);


  EXPECT_TRUE(status.ok()) << status;

  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_2), true);
  EXPECT_TRUE(status.ok()) << status;

  manager_result = Registry::get_key_manager<Aead>(key_type_1);
  EXPECT_TRUE(manager_result.ok()) << manager_result.status();
  auto manager = manager_result.value();
  EXPECT_TRUE(manager->DoesSupport(key_type_1));
  EXPECT_FALSE(manager->DoesSupport(key_type_2));

  manager_result = Registry::get_key_manager<Aead>(key_type_2);
  EXPECT_TRUE(manager_result.ok()) << manager_result.status();
  manager = manager_result.value();
  EXPECT_TRUE(manager->DoesSupport(key_type_2));
  EXPECT_FALSE(manager->DoesSupport(key_type_1));
}

TEST_F(RegistryTest, testRegisterKeyManager) {
  std::string key_type_1 = AesGcmKeyManager().get_key_type();

  std::unique_ptr<TestAeadKeyManager> null_key_manager = nullptr;
  auto status = Registry::RegisterKeyManager(std::move(null_key_manager), true);
  EXPECT_FALSE(status.ok());
  EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()) << status;

  // Register a key manager.
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_1), true);
  EXPECT_TRUE(status.ok()) << status;

  // Register the same key manager again, it should work (idempotence).
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_1), true);
  EXPECT_TRUE(status.ok()) << status;

  // Try overriding a key manager.
  AesGcmKeyManager key_type_manager;
  status = Registry::RegisterKeyManager(
      crypto::tink::internal::MakeKeyManager<Aead>(&key_type_manager), true);
  EXPECT_FALSE(status.ok());
  EXPECT_EQ(absl::StatusCode::kAlreadyExists, status.code()) << status;

  // Check the key manager is still registered.
  auto manager_result = Registry::get_key_manager<Aead>(key_type_1);
  EXPECT_TRUE(manager_result.ok()) << manager_result.status();
  auto manager = manager_result.value();
  EXPECT_TRUE(manager->DoesSupport(key_type_1));
}

// Tests that if we register a key manager once more after a call to
// get_key_manager, the key manager previously obtained with "get_key_manager()"
// remains valid.
TEST_F(RegistryTest, GetKeyManagerRemainsValid) {
  std::string key_type = AesGcmKeyManager().get_key_type();
  EXPECT_THAT(Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type), true), IsOk());

  crypto::tink::util::StatusOr<const KeyManager<Aead>*> key_manager =
      Registry::get_key_manager<Aead>(key_type);
  ASSERT_THAT(key_manager, IsOk());
  EXPECT_THAT(Registry::RegisterKeyManager(
                  absl::make_unique<TestAeadKeyManager>(key_type), true),
              IsOk());
  EXPECT_THAT(key_manager.value()->get_key_type(), Eq(key_type));
}

class TestAeadCatalogue : public Catalogue<Aead> {
 public:
  TestAeadCatalogue() {}

  util::StatusOr<std::unique_ptr<KeyManager<Aead>>> GetKeyManager(
      const std::string& type_url, const std::string& primitive_name,
      uint32_t min_version) const override {
    return util::Status(absl::StatusCode::kUnimplemented,
                        "This is a test catalogue.");
  }
};

class TestAeadCatalogue2 : public TestAeadCatalogue {};

TEST_F(RegistryTest, testAddCatalogue) {
  std::string catalogue_name = "SomeCatalogue";

  std::unique_ptr<TestAeadCatalogue> null_catalogue = nullptr;
  auto status =
      Registry::AddCatalogue(catalogue_name, std::move(null_catalogue));
  EXPECT_FALSE(status.ok());
  EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code()) << status;

  // Add a catalogue.
  status = Registry::AddCatalogue(catalogue_name,
                                  absl::make_unique<TestAeadCatalogue>());
  EXPECT_TRUE(status.ok()) << status;

  // Add the same catalogue again, it should work (idempotence).
  status = Registry::AddCatalogue(catalogue_name,
                                  absl::make_unique<TestAeadCatalogue>());
  EXPECT_TRUE(status.ok()) << status;

  // Try overriding a catalogue.
  status = Registry::AddCatalogue(catalogue_name,
                                  absl::make_unique<TestAeadCatalogue2>());
  EXPECT_FALSE(status.ok());
  EXPECT_EQ(absl::StatusCode::kAlreadyExists, status.code()) << status;

  // Check the catalogue is still present.
  EXPECT_THAT(Registry::get_catalogue<Aead>(catalogue_name), IsOk());
}

TEST_F(RegistryTest, testGettingPrimitives) {
  std::string key_type_1 = "google.crypto.tink.AesCtrHmacAeadKey";
  std::string key_type_2 = "google.crypto.tink.AesGcmKey";
  AesCtrHmacAeadKey dummy_key_1;
  AesGcmKey dummy_key_2;

  // Prepare keyset.
  Keyset keyset;

  uint32_t key_id_1 = 1234543;
  AddTinkKey(key_type_1, key_id_1, dummy_key_1, KeyStatusType::ENABLED,
             KeyData::SYMMETRIC, &keyset);

  uint32_t key_id_2 = 726329;
  AddTinkKey(key_type_2, key_id_2, dummy_key_2, KeyStatusType::DISABLED,
             KeyData::SYMMETRIC, &keyset);

  uint32_t key_id_3 = 7213743;
  AddLegacyKey(key_type_2, key_id_3, dummy_key_2, KeyStatusType::ENABLED,
               KeyData::SYMMETRIC, &keyset);

  uint32_t key_id_4 = 6268492;
  AddRawKey(key_type_1, key_id_4, dummy_key_1, KeyStatusType::ENABLED,
            KeyData::SYMMETRIC, &keyset);

  uint32_t key_id_5 = 42;
  AddRawKey(key_type_2, key_id_5, dummy_key_2, KeyStatusType::ENABLED,
            KeyData::SYMMETRIC, &keyset);

  keyset.set_primary_key_id(key_id_3);

  // Register key managers.
  util::Status status;
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_1), true);
  EXPECT_TRUE(status.ok()) << status;
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_2), true);
  EXPECT_TRUE(status.ok()) << status;

  // Get and use primitives.
  std::string plaintext = "some data";
  std::string aad = "aad";

  // Key #1.
  {
    auto result = Registry::GetPrimitive<Aead>(keyset.key(0).key_data());
    EXPECT_TRUE(result.ok()) << result.status();
    auto aead = std::move(result.value());
    EXPECT_EQ(DummyAead(key_type_1).Encrypt(plaintext, aad).value(),
              aead->Encrypt(plaintext, aad).value());
  }

  // Key #3.
  {
    auto result = Registry::GetPrimitive<Aead>(keyset.key(2).key_data());
    EXPECT_TRUE(result.ok()) << result.status();
    auto aead = std::move(result.value());
    EXPECT_EQ(DummyAead(key_type_2).Encrypt(plaintext, aad).value(),
              aead->Encrypt(plaintext, aad).value());
  }
}

TEST_F(RegistryTest, testNewKeyData) {
  std::string key_type_1 = "google.crypto.tink.AesCtrHmacAeadKey";
  std::string key_type_2 = "google.crypto.tink.AesGcmKey";
  std::string key_type_3 = "yet/another/keytype";

  // Register key managers.
  util::Status status;
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_1),
      /*new_key_allowed=*/true);
  EXPECT_TRUE(status.ok()) << status;
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_2),
      /*new_key_allowed=*/true);
  EXPECT_TRUE(status.ok()) << status;
  status = Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type_3),
      /*new_key_allowed=*/false);
  EXPECT_TRUE(status.ok()) << status;

  {  // A supported key type.
    KeyTemplate key_template;
    key_template.set_type_url(key_type_1);
    key_template.set_value("test value 42");
    auto new_key_data_result = Registry::NewKeyData(key_template);
    EXPECT_TRUE(new_key_data_result.ok()) << new_key_data_result.status();
    EXPECT_EQ(key_type_1, new_key_data_result.value()->type_url());
    EXPECT_EQ(key_template.value(), new_key_data_result.value()->value());
  }

  {  // Another supported key type.
    KeyTemplate key_template;
    key_template.set_type_url(key_type_2);
    key_template.set_value("yet another test value 42");
    auto new_key_data_result = Registry::NewKeyData(key_template);
    EXPECT_TRUE(new_key_data_result.ok()) << new_key_data_result.status();
    EXPECT_EQ(key_type_2, new_key_data_result.value()->type_url());
    EXPECT_EQ(key_template.value(), new_key_data_result.value()->value());
  }

  {  // A key type that does not allow NewKey-operations.
    KeyTemplate key_template;
    key_template.set_type_url(key_type_3);
    key_template.set_value("some other value 72");
    auto new_key_data_result = Registry::NewKeyData(key_template);
    EXPECT_FALSE(new_key_data_result.ok());
    EXPECT_EQ(absl::StatusCode::kInvalidArgument,
              new_key_data_result.status().code());
    EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type_3,
                        std::string(new_key_data_result.status().message()));
    EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow",
                        std::string(new_key_data_result.status().message()));
  }

  {  // A key type that is not supported.
    KeyTemplate key_template;
    std::string bad_type_url = "some key type that is not supported";
    key_template.set_type_url(bad_type_url);
    key_template.set_value("some totally other value 42");
    auto new_key_data_result = Registry::NewKeyData(key_template);
    EXPECT_FALSE(new_key_data_result.ok());
    EXPECT_EQ(absl::StatusCode::kNotFound,
              new_key_data_result.status().code());
    EXPECT_PRED_FORMAT2(testing::IsSubstring, bad_type_url,
                        std::string(new_key_data_result.status().message()));
  }
}

TEST_F(RegistryTest, testGetPublicKeyData) {
  // Setup the registry.
  Registry::Reset();
  auto private_key_type_manager =
      absl::make_unique<EciesAeadHkdfPrivateKeyManager>();
  auto public_key_type_manager =
      absl::make_unique<EciesAeadHkdfPublicKeyManager>();

  auto status = Registry::RegisterKeyManager(
      internal::MakePrivateKeyManager<HybridDecrypt>(
          private_key_type_manager.get(), public_key_type_manager.get()),
      true);
  ASSERT_TRUE(status.ok()) << status;
  AesGcmKeyManager key_type_manager;
  status = Registry::RegisterKeyManager(
      crypto::tink::internal::MakeKeyManager<Aead>(&key_type_manager), true);
  ASSERT_TRUE(status.ok()) << status;

  // Get a test private key.
  auto ecies_key = test::GetEciesAesGcmHkdfTestKey(
      EllipticCurveType::NIST_P256, EcPointFormat::UNCOMPRESSED,
      HashType::SHA256, /* aes_gcm_key_size= */ 24);

  // Extract public key data and check.
  auto public_key_data_result = Registry::GetPublicKeyData(
      EciesAeadHkdfPrivateKeyManager().get_key_type(),
      ecies_key.SerializeAsString());
  EXPECT_TRUE(public_key_data_result.ok()) << public_key_data_result.status();
  auto public_key_data = std::move(public_key_data_result.value());
  EXPECT_EQ(EciesAeadHkdfPublicKeyManager().get_key_type(),
            public_key_data->type_url());
  EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_key_data->key_material_type());
  EXPECT_EQ(ecies_key.public_key().SerializeAsString(),
            public_key_data->value());

  // Try with a wrong key type.
  auto wrong_key_type_result = Registry::GetPublicKeyData(
      AesGcmKeyManager().get_key_type(), ecies_key.SerializeAsString());
  EXPECT_FALSE(wrong_key_type_result.ok());
  EXPECT_EQ(absl::StatusCode::kInvalidArgument,
            wrong_key_type_result.status().code());
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "PrivateKeyFactory",
                      std::string(wrong_key_type_result.status().message()));

  // Try with a bad serialized key.
  auto bad_key_result = Registry::GetPublicKeyData(
      EciesAeadHkdfPrivateKeyManager().get_key_type(),
      "some bad serialized key");
  EXPECT_FALSE(bad_key_result.ok());
  EXPECT_EQ(absl::StatusCode::kInvalidArgument, bad_key_result.status().code());
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "Could not parse",
                      std::string(bad_key_result.status().message()));
}

// Tests that if we register the same type of wrapper twice, the second call
// succeeds.
TEST_F(RegistryTest, RegisterWrapperTwice) {
  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<AeadWrapper>())
          .ok());
  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<AeadWrapper>())
          .ok());
}

// Tests that if we register the same type of wrapper twice, the second call
// succeeds.
TEST_F(RegistryTest, RegisterTransformingWrapperTwice) {
  EXPECT_TRUE(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<AeadVariantToStringWrapper>())
                  .ok());
  EXPECT_TRUE(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<AeadVariantToStringWrapper>())
                  .ok());
}

// Test that if we register a second wrapper, wrapping to the same type as a
// previous wrapper it will fail.
TEST_F(RegistryTest, RegisterTransformingWrapperTwiceMixing) {
  EXPECT_TRUE(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<AeadVariantToStringWrapper>())
                  .ok());
  // We cannot register a different wrapper creating a std::string.
  EXPECT_THAT(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<TestWrapper<std::string>>()),
              Not(IsOk()));
  // But one creating an Aead.
  EXPECT_THAT(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<TestWrapper<AeadVariant>>()),
              IsOk());
}

// Test that if we register a second wrapper, wrapping to the same type as a
// previous wrapper it will fail (order swapped).
TEST_F(RegistryTest, RegisterTransformingWrapperTwiceMixingBackwards) {
  EXPECT_THAT(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<TestWrapper<std::string>>()),
              IsOk());
  // We cannot register another wrapper producing strings.
  EXPECT_THAT(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<AeadVariantToStringWrapper>()),
              Not(IsOk()));
}

// Tests that if we register different wrappers for the same primitive twice,
// the second call fails.
TEST_F(RegistryTest, RegisterDifferentWrappers) {
  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<AeadWrapper>())
          .ok());
  util::Status result = Registry::RegisterPrimitiveWrapper(
      absl::make_unique<TestWrapper<Aead>>());
  EXPECT_FALSE(result.ok());
  EXPECT_EQ(absl::StatusCode::kAlreadyExists, result.code());
}

// Tests that if we register different wrappers for different primitives, this
// returns ok.
TEST_F(RegistryTest, RegisterDifferentWrappersDifferentPrimitives) {
  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<TestWrapper<Aead>>())
          .ok());
  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<TestWrapper<Mac>>())
          .ok());
}

// Tests that if we do not register a wrapper, then calls to Wrap
// fail with "No wrapper registered" -- even if there is a wrapper for a
// different primitive registered.
TEST_F(RegistryTest, NoWrapperRegistered) {
  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<TestWrapper<Mac>>())
          .ok());

  crypto::tink::util::StatusOr<std::unique_ptr<Aead>> result =
      Registry::Wrap<Aead>(absl::make_unique<PrimitiveSet<Aead>>());
  EXPECT_FALSE(result.ok());
  EXPECT_EQ(absl::StatusCode::kNotFound, result.status().code());
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "No wrapper registered",
                      std::string(result.status().message()));
}

// Tests that if the wrapper fails, the error of the wrapped is forwarded
// in GetWrappedPrimitive.
TEST_F(RegistryTest, WrapperFails) {
  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<TestWrapper<Aead>>())
          .ok());

  crypto::tink::util::StatusOr<std::unique_ptr<Aead>> result =
      Registry::Wrap<Aead>(absl::make_unique<PrimitiveSet<Aead>>());
  EXPECT_FALSE(result.ok());
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "This is a test wrapper",
                      std::string(result.status().message()));
}

// Tests that wrapping works as expected in the usual case.
TEST_F(RegistryTest, UsualWrappingTest) {
  KeysetInfo keyset_info;

  keyset_info.add_key_info();
  keyset_info.mutable_key_info(0)->set_output_prefix_type(
      OutputPrefixType::TINK);
  keyset_info.mutable_key_info(0)->set_key_id(1234543);
  keyset_info.mutable_key_info(0)->set_status(KeyStatusType::ENABLED);
  keyset_info.add_key_info();
  keyset_info.mutable_key_info(1)->set_output_prefix_type(
      OutputPrefixType::LEGACY);
  keyset_info.mutable_key_info(1)->set_key_id(726329);
  keyset_info.mutable_key_info(1)->set_status(KeyStatusType::ENABLED);
  keyset_info.add_key_info();
  keyset_info.mutable_key_info(2)->set_output_prefix_type(
      OutputPrefixType::TINK);
  keyset_info.mutable_key_info(2)->set_key_id(7213743);
  keyset_info.mutable_key_info(2)->set_status(KeyStatusType::ENABLED);

  auto primitive_set = absl::make_unique<PrimitiveSet<Aead>>();
  ASSERT_TRUE(primitive_set
                  ->AddPrimitive(absl::make_unique<DummyAead>("aead0"),
                                 keyset_info.key_info(0))
                  .ok());
  ASSERT_TRUE(primitive_set
                  ->AddPrimitive(absl::make_unique<DummyAead>("aead1"),
                                 keyset_info.key_info(1))
                  .ok());
  auto entry_result = primitive_set->AddPrimitive(
      absl::make_unique<DummyAead>("primary_aead"), keyset_info.key_info(2));
  ASSERT_THAT(primitive_set->set_primary(entry_result.value()), IsOk());

  EXPECT_TRUE(
      Registry::RegisterPrimitiveWrapper(absl::make_unique<AeadWrapper>())
          .ok());

  auto aead_result = Registry::Wrap<Aead>(std::move(primitive_set));
  EXPECT_TRUE(aead_result.ok()) << aead_result.status();
  std::unique_ptr<Aead> aead = std::move(aead_result.value());
  std::string plaintext = "some_plaintext";
  std::string aad = "some_aad";

  auto encrypt_result = aead->Encrypt(plaintext, aad);
  EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status();
  std::string ciphertext = encrypt_result.value();
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "primary_aead", ciphertext);

  auto decrypt_result = aead->Decrypt(ciphertext, aad);
  EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status();
  EXPECT_EQ(plaintext, decrypt_result.value());

  decrypt_result = aead->Decrypt("some bad ciphertext", aad);
  EXPECT_FALSE(decrypt_result.ok());
  EXPECT_EQ(absl::StatusCode::kInvalidArgument, decrypt_result.status().code());
  EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed",
                      std::string(decrypt_result.status().message()));
}

std::string AddAesGcmKey(uint32_t key_id, OutputPrefixType output_prefix_type,
                         KeyStatusType key_status_type,
                         Keyset& modified_keyset) {
  AesGcmKey key;
  key.set_version(0);
  key.set_key_value(subtle::Random::GetRandomBytes(16));
  KeyData key_data;
  key_data.set_value(key.SerializeAsString());
  key_data.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
  test::AddKeyData(key_data, key_id, output_prefix_type, key_status_type,
                   &modified_keyset);
  return key.key_value();
}

// Tests that wrapping of a keyset works in the usual case.
TEST_F(RegistryTest, KeysetWrappingTest) {
  if (!FIPS_mode()) {
    GTEST_SKIP() << "Not supported when BoringSSL is not built in FIPS-mode.";
  }

  Keyset keyset;
  std::string raw_key =
      AddAesGcmKey(13, OutputPrefixType::TINK, KeyStatusType::ENABLED, keyset);
  keyset.set_primary_key_id(13);

  auto fips_key_manager = absl::make_unique<ExampleKeyTypeManager>();

  ON_CALL(*fips_key_manager, FipsStatus())
      .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto));

  ASSERT_THAT(Registry::RegisterKeyTypeManager(
                  std::move(fips_key_manager), true),
              IsOk());
  ASSERT_THAT(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<AeadVariantWrapper>()),
              IsOk());

  crypto::tink::util::StatusOr<std::unique_ptr<AeadVariant>> aead_variant =
      RegistryImpl::GlobalInstance().WrapKeyset<AeadVariant>(
          keyset, /*annotations=*/{});
  EXPECT_THAT(aead_variant, IsOk());
  EXPECT_THAT(aead_variant.value()->get(), Eq(raw_key));
}

// Tests that wrapping of a keyset works.
TEST_F(RegistryTest, TransformingKeysetWrappingTest) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  Keyset keyset;
  std::string raw_key =
      AddAesGcmKey(13, OutputPrefixType::TINK, KeyStatusType::ENABLED, keyset);
  keyset.set_primary_key_id(13);

  ASSERT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  ASSERT_THAT(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<AeadVariantToStringWrapper>()),
              IsOk());

  crypto::tink::util::StatusOr<std::unique_ptr<std::string>> string_primitive =
      RegistryImpl::GlobalInstance().WrapKeyset<std::string>(
          keyset, /*annotations=*/{});
  EXPECT_THAT(string_primitive, IsOk());
  EXPECT_THAT(*string_primitive.value(), Eq(raw_key));
}

// Tests that when we ask the registry to wrap a PrimitiveSet<Aead> into an
// Aead, but the wrapper is in fact from something else into Aead, we give a
// correct error message.
TEST_F(RegistryTest, TransformingPrimitiveWrapperCustomKeyManager) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  ASSERT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  // Register a transforming wrapper taking strings and making Aeads.
  ASSERT_THAT(Registry::RegisterPrimitiveWrapper(
                  absl::make_unique<TestWrapper<std::string, Aead>>()),
              IsOk());

  KeysetInfo keyset_info;
  keyset_info.add_key_info();
  keyset_info.mutable_key_info(0)->set_output_prefix_type(
      OutputPrefixType::TINK);
  keyset_info.mutable_key_info(0)->set_key_id(1234543);
  keyset_info.mutable_key_info(0)->set_status(KeyStatusType::ENABLED);
  keyset_info.set_primary_key_id(1234543);

  auto primitive_set = absl::make_unique<PrimitiveSet<Aead>>();
  ASSERT_TRUE(primitive_set
                  ->AddPrimitive(absl::make_unique<DummyAead>("aead0"),
                                 keyset_info.key_info(0))
                  .ok());

  EXPECT_THAT(Registry::Wrap<Aead>(std::move(primitive_set)).status(),
              StatusIs(absl::StatusCode::kFailedPrecondition,
                       HasSubstr("custom key manager")));
}

// Tests that the error message in GetKeyManager contains the type_id.name() of
// the primitive for which the key manager was actually registered.
TEST_F(RegistryTest, GetKeyManagerErrorMessage) {
  AesGcmKeyManager key_type_manager;
  EXPECT_TRUE(
      Registry::RegisterKeyManager(
          crypto::tink::internal::MakeKeyManager<Aead>(&key_type_manager), true)
          .ok());
  auto result =
      Registry::get_key_manager<int>(AesGcmKeyManager().get_key_type());
  EXPECT_FALSE(result.ok());
  EXPECT_THAT(std::string(result.status().message()),
              HasSubstr(AesGcmKeyManager().get_key_type()));
  // Note: The C++ standard does not guarantee the next line.  If some toolchain
  // update fails it, one can delete it.
  EXPECT_THAT(std::string(result.status().message()),
              HasSubstr(typeid(Aead).name()));
}

TEST_F(RegistryTest, RegisterKeyTypeManager) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
}

TEST_F(RegistryTest, RegisterFipsKeyTypeManager) {
  if (!kUseOnlyFips || !FIPS_mode()) {
    GTEST_SKIP() << "Only supported in FIPS-mode with BoringCrypto available.";
  }

  auto fips_key_manager = absl::make_unique<ExampleKeyTypeManager>();

  ON_CALL(*fips_key_manager, FipsStatus())
      .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto));

  EXPECT_THAT(
      Registry::RegisterKeyTypeManager(std::move(fips_key_manager), true),
      IsOk());
}

TEST_F(RegistryTest, RegisterFipsKeyTypeManagerNoBoringCrypto) {
  if (!kUseOnlyFips || FIPS_mode()) {
    GTEST_SKIP()
        << "Only supported in FIPS-mode with BoringCrypto not available.";
  }

  auto fips_key_manager = absl::make_unique<ExampleKeyTypeManager>();

  ON_CALL(*fips_key_manager, FipsStatus())
      .WillByDefault(testing::Return(FipsCompatibility::kNotFips));

  EXPECT_THAT(
      Registry::RegisterKeyTypeManager(std::move(fips_key_manager), true),
      StatusIs(absl::StatusCode::kInternal));
}

TEST_F(RegistryTest, KeyTypeManagerGetFirstKeyManager) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  AesGcmKeyFormat format;
  format.set_key_size(16);
  AesGcmKey key = ExampleKeyTypeManager().CreateKey(format).value();
  auto aead = Registry::get_key_manager<Aead>(
                  "type.googleapis.com/google.crypto.tink.AesGcmKey")
                  .value()
                  ->GetPrimitive(key)
                  .value();
  std::string encryption = aead->Encrypt("TESTMESSAGE", "").value();
  std::string decryption = aead->Decrypt(encryption, "").value();
  EXPECT_THAT(decryption, Eq("TESTMESSAGE"));
}

TEST_F(RegistryTest, KeyTypeManagerGetSecondKeyManager) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  AesGcmKeyFormat format;
  format.set_key_size(16);
  AesGcmKey key = ExampleKeyTypeManager().CreateKey(format).value();
  auto aead_variant = Registry::get_key_manager<AeadVariant>(
                          "type.googleapis.com/google.crypto.tink.AesGcmKey")
                          .value()
                          ->GetPrimitive(key)
                          .value();
  EXPECT_THAT(aead_variant->get(), Eq(key.key_value()));
}

TEST_F(RegistryTest, KeyTypeManagerNotSupportedPrimitive) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  EXPECT_THAT(Registry::get_key_manager<Mac>(
                  "type.googleapis.com/google.crypto.tink.AesGcmKey")
                  .status(),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("not among supported primitives")));
}

// Tests that if we register a key manager once more after a call to
// get_key_manager, the key manager previously obtained with "get_key_manager()"
// remains valid.
TEST_F(RegistryTest, GetKeyManagerRemainsValidForKeyTypeManagers) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());

  crypto::tink::util::StatusOr<const KeyManager<Aead>*> key_manager =
      Registry::get_key_manager<Aead>(ExampleKeyTypeManager().get_key_type());
  ASSERT_THAT(key_manager, IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  EXPECT_THAT(key_manager.value()->get_key_type(),
              Eq(ExampleKeyTypeManager().get_key_type()));
}

TEST_F(RegistryTest, KeyTypeManagerNewKey) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());

  AesGcmKeyFormat format;
  format.set_key_size(32);
  KeyTemplate key_template;
  key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
  key_template.set_value(format.SerializeAsString());

  KeyData key_data = *Registry::NewKeyData(key_template).value();
  EXPECT_THAT(key_data.type_url(),
              Eq("type.googleapis.com/google.crypto.tink.AesGcmKey"));
  EXPECT_THAT(key_data.key_material_type(),
              Eq(google::crypto::tink::KeyData::SYMMETRIC));
  AesGcmKey key;
  key.ParseFromString(key_data.value());
  EXPECT_THAT(key.key_value(), SizeIs(32));
}

TEST_F(RegistryTest, KeyTypeManagerNewKeyInvalidSize) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());

  AesGcmKeyFormat format;
  format.set_key_size(33);
  KeyTemplate key_template;
  key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
  key_template.set_value(format.SerializeAsString());

  EXPECT_THAT(Registry::NewKeyData(key_template), IsOk());
}

TEST_F(RegistryTest, KeyTypeManagerDeriveKey) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());

  AesGcmKeyFormat format;
  format.set_key_size(32);
  KeyTemplate key_template;
  key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
  key_template.set_value(format.SerializeAsString());

  crypto::tink::util::IstreamInputStream input_stream{
      absl::make_unique<std::stringstream>(
          "0123456789012345678901234567890123456789")};

  auto key_data_or =
      RegistryImpl::GlobalInstance().DeriveKey(key_template, &input_stream);
  ASSERT_THAT(key_data_or, IsOk());
  EXPECT_THAT(key_data_or.value().type_url(), Eq(key_template.type_url()));
  AesGcmKey key;
  EXPECT_TRUE(key.ParseFromString(key_data_or.value().value()));
  // 32 byte prefix of above string.
  EXPECT_THAT(key.key_value(), Eq("01234567890123456789012345678901"));
}

// The same, but we register the key manager twice. This should catch some of
// the possible lifetime issues.
TEST_F(RegistryTest, KeyTypeManagerDeriveKeyRegisterTwice) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());

  AesGcmKeyFormat format;
  format.set_key_size(32);
  KeyTemplate key_template;
  key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
  key_template.set_value(format.SerializeAsString());

  crypto::tink::util::IstreamInputStream input_stream{
      absl::make_unique<std::stringstream>(
          "0123456789012345678901234567890123456789")};

  auto key_data_or =
      RegistryImpl::GlobalInstance().DeriveKey(key_template, &input_stream);
  ASSERT_THAT(key_data_or, IsOk());
  EXPECT_THAT(key_data_or.value().type_url(), Eq(key_template.type_url()));
  AesGcmKey key;
  EXPECT_TRUE(key.ParseFromString(key_data_or.value().value()));
  // 32 byte prefix of above string.
  EXPECT_THAT(key.key_value(), Eq("01234567890123456789012345678901"));
}

// Tests that if we register a KeyManager instead of a KeyTypeManager, DeriveKey
// fails properly.
TEST_F(RegistryTest, KeyManagerDeriveKeyFail) {
  std::string key_type = "type.googleapis.com/google.crypto.tink.AesGcmKey";
  ASSERT_THAT(Registry::RegisterKeyManager(
      absl::make_unique<TestAeadKeyManager>(key_type),
      /* new_key_allowed= */ true), IsOk());

  KeyTemplate key_template;
  key_template.set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");

  EXPECT_THAT(
      RegistryImpl::GlobalInstance().DeriveKey(key_template, nullptr).status(),
      StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("cannot derive")));
}

TEST_F(RegistryTest, KeyManagerDeriveNotRegistered) {
  KeyTemplate key_template;
  key_template.set_type_url("some_inexistent_keytype");

  EXPECT_THAT(
      RegistryImpl::GlobalInstance().DeriveKey(key_template, nullptr).status(),
      StatusIs(absl::StatusCode::kNotFound, HasSubstr("No manager")));
}

TEST_F(RegistryTest, RegisterKeyTypeManagerTwiceMoreRestrictive) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), false),
              IsOk());
}

TEST_F(RegistryTest, RegisterKeyTypeManagerTwice) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), false),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), false),
              IsOk());
}

TEST_F(RegistryTest, RegisterKeyTypeManagerLessRestrictive) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), false),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              StatusIs(absl::StatusCode::kAlreadyExists));
}

TEST_F(RegistryTest, RegisterKeyTypeManagerBeforeKeyManager) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyManager(
                  absl::make_unique<TestAeadKeyManager>(
                      "type.googleapis.com/google.crypto.tink.AesGcmKey"),
                  true),
              StatusIs(absl::StatusCode::kAlreadyExists));
}

TEST_F(RegistryTest, RegisterKeyTypeManagerAfterKeyManager) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  EXPECT_THAT(Registry::RegisterKeyManager(
                  absl::make_unique<TestAeadKeyManager>(
                      "type.googleapis.com/google.crypto.tink.AesGcmKey"),
                  true),
              IsOk());
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<ExampleKeyTypeManager>(), true),
              StatusIs(absl::StatusCode::kAlreadyExists));
}

class PrivatePrimitiveA {};
class PrivatePrimitiveB {};

class TestPrivateKeyTypeManager
    : public PrivateKeyTypeManager<EcdsaPrivateKey, EcdsaKeyFormat,
                                   EcdsaPublicKey,
                                   List<PrivatePrimitiveA, PrivatePrimitiveB>> {
 public:
  class PrivatePrimitiveAFactory : public PrimitiveFactory<PrivatePrimitiveA> {
   public:
    crypto::tink::util::StatusOr<std::unique_ptr<PrivatePrimitiveA>> Create(
        const EcdsaPrivateKey& key) const override {
      return util::Status(absl::StatusCode::kUnimplemented, "Not implemented");
    }
  };
  class PrivatePrimitiveBFactory : public PrimitiveFactory<PrivatePrimitiveB> {
   public:
    crypto::tink::util::StatusOr<std::unique_ptr<PrivatePrimitiveB>> Create(
        const EcdsaPrivateKey& key) const override {
      return util::Status(absl::StatusCode::kUnimplemented, "Not implemented");
    }
  };

  TestPrivateKeyTypeManager()
      : PrivateKeyTypeManager(absl::make_unique<PrivatePrimitiveAFactory>(),
                              absl::make_unique<PrivatePrimitiveBFactory>()) {}

  google::crypto::tink::KeyData::KeyMaterialType key_material_type()
      const override {
    return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE;
  }

  uint32_t get_version() const override { return 0; }
  crypto::tink::util::Status ValidateKey(
      const EcdsaPrivateKey& key) const override {
    return crypto::tink::util::OkStatus();
  }
  crypto::tink::util::Status ValidateKeyFormat(
      const EcdsaKeyFormat& key) const override {
    return crypto::tink::util::OkStatus();
  }

  const std::string& get_key_type() const override { return kKeyType; }

  crypto::tink::util::StatusOr<EcdsaPrivateKey> CreateKey(
      const EcdsaKeyFormat& key_format) const override {
    EcdsaPublicKey public_key;
    *public_key.mutable_params() = key_format.params();
    EcdsaPrivateKey result;
    *result.mutable_public_key() = public_key;
    return result;
  }

  crypto::tink::util::StatusOr<EcdsaPublicKey> GetPublicKey(
      const EcdsaPrivateKey& private_key) const override {
    return private_key.public_key();
  }

  MOCK_METHOD(FipsCompatibility, FipsStatus, (), (const, override));

 private:
  const std::string kKeyType =
      "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey";
};

class PublicPrimitiveA {};
class PublicPrimitiveB {};

class TestPublicKeyTypeManager
    : public KeyTypeManager<EcdsaPublicKey, void,
                            List<PublicPrimitiveA, PublicPrimitiveB>> {
 public:
  class PublicPrimitiveAFactory : public PrimitiveFactory<PublicPrimitiveA> {
   public:
    crypto::tink::util::StatusOr<std::unique_ptr<PublicPrimitiveA>> Create(
        const EcdsaPublicKey& key) const override {
      return util::Status(absl::StatusCode::kUnimplemented, "Not implemented");
    }
  };
  class PublicPrimitiveBFactory : public PrimitiveFactory<PublicPrimitiveB> {
   public:
    crypto::tink::util::StatusOr<std::unique_ptr<PublicPrimitiveB>> Create(
        const EcdsaPublicKey& key) const override {
      return util::Status(absl::StatusCode::kUnimplemented, "Not implemented");
    }
  };

  TestPublicKeyTypeManager()
      : KeyTypeManager(absl::make_unique<PublicPrimitiveAFactory>(),
                       absl::make_unique<PublicPrimitiveBFactory>()) {}

  google::crypto::tink::KeyData::KeyMaterialType key_material_type()
      const override {
    return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE;
  }

  uint32_t get_version() const override { return 0; }
  crypto::tink::util::Status ValidateKey(
      const EcdsaPublicKey& key) const override {
    return crypto::tink::util::OkStatus();
  }

  const std::string& get_key_type() const override { return kKeyType; }

  MOCK_METHOD(FipsCompatibility, FipsStatus, (), (const, override));

 private:
  const std::string kKeyType =
      "type.googleapis.com/google.crypto.tink.EcdsaPublicKey";
};

std::unique_ptr<TestPrivateKeyTypeManager>
CreateTestPrivateKeyManagerFipsCompatible() {
  auto private_key_manager = absl::make_unique<TestPrivateKeyTypeManager>();
  ON_CALL(*private_key_manager, FipsStatus())
      .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto));
  return private_key_manager;
}

std::unique_ptr<TestPublicKeyTypeManager>
CreateTestPublicKeyManagerFipsCompatible() {
  auto public_key_manager = absl::make_unique<TestPublicKeyTypeManager>();
  ON_CALL(*public_key_manager, FipsStatus())
      .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto));
  return public_key_manager;
}

TEST_F(RegistryTest, RegisterAsymmetricKeyManagers) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
      CreateTestPrivateKeyManagerFipsCompatible(),
      CreateTestPublicKeyManagerFipsCompatible(), true);
  ASSERT_TRUE(status.ok()) << status;
}

TEST_F(RegistryTest, AsymmetricMoreRestrictiveNewKey) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());

  crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
      CreateTestPrivateKeyManagerFipsCompatible(),
      CreateTestPublicKeyManagerFipsCompatible(), false);
  ASSERT_TRUE(status.ok()) << status;
}

TEST_F(RegistryTest, AsymmetricSameNewKey) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
      CreateTestPrivateKeyManagerFipsCompatible(),
      CreateTestPublicKeyManagerFipsCompatible(), true);
  ASSERT_TRUE(status.ok()) << status;

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), false)
                  .ok());
  status = Registry::RegisterAsymmetricKeyManagers(
      CreateTestPrivateKeyManagerFipsCompatible(),
      CreateTestPublicKeyManagerFipsCompatible(), false);
  ASSERT_TRUE(status.ok()) << status;
}

TEST_F(RegistryTest, AsymmetricLessRestrictiveGivesError) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
      CreateTestPrivateKeyManagerFipsCompatible(),
      CreateTestPublicKeyManagerFipsCompatible(), false);
  ASSERT_TRUE(status.ok()) << status;
  EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true),
              StatusIs(absl::StatusCode::kAlreadyExists,
                       HasSubstr("forbidden new key operation")));
}

// Tests that if we register asymmetric key managers once more after a call to
// get_key_manager, the key manager previously obtained with "get_key_manager()"
// remains valid.

TEST_F(RegistryTest, RegisterAsymmetricKeyManagersGetKeyManagerStaysValid) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_THAT(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true),
              IsOk());

  crypto::tink::util::StatusOr<const KeyManager<PrivatePrimitiveA>*>
      private_key_manager = Registry::get_key_manager<PrivatePrimitiveA>(
          TestPrivateKeyTypeManager().get_key_type());
  crypto::tink::util::StatusOr<const KeyManager<PublicPrimitiveA>*>
      public_key_manager = Registry::get_key_manager<PublicPrimitiveA>(
          TestPublicKeyTypeManager().get_key_type());

  ASSERT_THAT(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true),
              IsOk());

  EXPECT_THAT(private_key_manager.value()->get_key_type(),
              Eq(TestPrivateKeyTypeManager().get_key_type()));
  EXPECT_THAT(public_key_manager.value()->get_key_type(),
              Eq(TestPublicKeyTypeManager().get_key_type()));
}


TEST_F(RegistryTest, AsymmetricPrivateRegisterAlone) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterKeyTypeManager(
                  CreateTestPrivateKeyManagerFipsCompatible(), true)
                  .ok());
  ASSERT_TRUE(Registry::RegisterKeyTypeManager(
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  // Registering the same as asymmetric key managers must fail, because doing so
  // would mean we invalidate key managers previously obtained with
  // get_key_manager().
  ASSERT_FALSE(Registry::RegisterAsymmetricKeyManagers(
                   CreateTestPrivateKeyManagerFipsCompatible(),
                   CreateTestPublicKeyManagerFipsCompatible(), true)
                   .ok());
  ASSERT_TRUE(Registry::RegisterKeyTypeManager(
                  CreateTestPrivateKeyManagerFipsCompatible(), true)
                  .ok());
  ASSERT_TRUE(Registry::RegisterKeyTypeManager(
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
}

TEST_F(RegistryTest, AsymmetricGetPrimitiveA) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  crypto::tink::util::StatusOr<const KeyManager<PrivatePrimitiveA>*> km =
      Registry::get_key_manager<PrivatePrimitiveA>(
          TestPrivateKeyTypeManager().get_key_type());
  ASSERT_TRUE(km.ok()) << km.status();
  EXPECT_THAT(km.value()->get_key_type(),
              Eq(TestPrivateKeyTypeManager().get_key_type()));
}

TEST_F(RegistryTest, AsymmetricGetPrimitiveB) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  crypto::tink::util::StatusOr<const KeyManager<PrivatePrimitiveB>*> km =
      Registry::get_key_manager<PrivatePrimitiveB>(
          TestPrivateKeyTypeManager().get_key_type());
  ASSERT_TRUE(km.ok()) << km.status();
  EXPECT_THAT(km.value()->get_key_type(),
              Eq(TestPrivateKeyTypeManager().get_key_type()));
}

TEST_F(RegistryTest, AsymmetricGetPublicPrimitiveA) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  crypto::tink::util::StatusOr<const KeyManager<PublicPrimitiveA>*> km =
      Registry::get_key_manager<PublicPrimitiveA>(
          TestPublicKeyTypeManager().get_key_type());
  ASSERT_TRUE(km.ok()) << km.status();
  EXPECT_THAT(km.value()->get_key_type(),
              Eq(TestPublicKeyTypeManager().get_key_type()));
}

TEST_F(RegistryTest, AsymmetricGetPublicPrimitiveB) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  crypto::tink::util::StatusOr<const KeyManager<PublicPrimitiveB>*> km =
      Registry::get_key_manager<PublicPrimitiveB>(
          TestPublicKeyTypeManager().get_key_type());
  ASSERT_TRUE(km.ok()) << km.status();
  EXPECT_THAT(km.value()->get_key_type(),
              Eq(TestPublicKeyTypeManager().get_key_type()));
}

TEST_F(RegistryTest, AsymmetricGetWrongPrimitiveError) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  crypto::tink::util::StatusOr<const KeyManager<PublicPrimitiveA>*> km =
      Registry::get_key_manager<PublicPrimitiveA>(
          TestPrivateKeyTypeManager().get_key_type());
  EXPECT_THAT(km.status(),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("not among supported primitives")));
}

class PrivateKeyManagerImplTest : public testing::Test {
  void SetUp() override {
    Registry::Reset();
  }

  void TearDown() override {
    // Reset is needed here to ensure Mock objects get deleted and do not leak.
    Registry::Reset();
  }
};

TEST_F(PrivateKeyManagerImplTest, AsymmetricFactoryNewKeyFromMessage) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());

  EcdsaKeyFormat key_format;
  key_format.mutable_params()->set_encoding(EcdsaSignatureEncoding::DER);
  KeyTemplate key_template;
  key_template.set_type_url(TestPrivateKeyTypeManager().get_key_type());
  key_template.set_value(key_format.SerializeAsString());
  key_template.set_output_prefix_type(OutputPrefixType::TINK);
  std::unique_ptr<KeyData> key_data =
      Registry::NewKeyData(key_template).value();
  EXPECT_THAT(key_data->type_url(),
              Eq(TestPrivateKeyTypeManager().get_key_type()));
  EcdsaPrivateKey private_key;
  private_key.ParseFromString(key_data->value());
  EXPECT_THAT(private_key.public_key().params().encoding(),
              Eq(EcdsaSignatureEncoding::DER));
}

TEST_F(PrivateKeyManagerImplTest, AsymmetricNewKeyDisallowed) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), true)
                  .ok());
  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  CreateTestPrivateKeyManagerFipsCompatible(),
                  CreateTestPublicKeyManagerFipsCompatible(), false)
                  .ok());

  KeyTemplate key_template;
  key_template.set_type_url(TestPrivateKeyTypeManager().get_key_type());
  EXPECT_THAT(
      Registry::NewKeyData(key_template).status(),
      StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("not allow")));
}

TEST_F(RegistryTest, AsymmetricGetPublicKeyData) {
  if (kUseOnlyFips && !FIPS_mode()) {
    GTEST_SKIP() << "Not supported if FIPS-mode is used and BoringCrypto is "
                    "not available";
  }

  crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
      CreateTestPrivateKeyManagerFipsCompatible(),
      CreateTestPublicKeyManagerFipsCompatible(), true);
  EcdsaPrivateKey private_key;
  private_key.mutable_public_key()->mutable_params()->set_encoding(
      EcdsaSignatureEncoding::DER);

  std::unique_ptr<KeyData> key_data =
      Registry::GetPublicKeyData(TestPrivateKeyTypeManager().get_key_type(),
                                 private_key.SerializeAsString())
          .value();
  ASSERT_THAT(key_data->type_url(),
              Eq(TestPublicKeyTypeManager().get_key_type()));
  EcdsaPublicKey public_key;
  public_key.ParseFromString(key_data->value());
  EXPECT_THAT(public_key.params().encoding(), Eq(EcdsaSignatureEncoding::DER));
}

class TestPrivateKeyTypeManager2 : public TestPrivateKeyTypeManager {};
class TestPublicKeyTypeManager2 : public TestPublicKeyTypeManager {};

TEST_F(RegistryTest, RegisterAssymmetricReregistrationWithWrongClasses) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  absl::make_unique<TestPrivateKeyTypeManager>(),
                  absl::make_unique<TestPublicKeyTypeManager>(), true)
                  .ok());
  EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers(
                  absl::make_unique<TestPrivateKeyTypeManager2>(),
                  absl::make_unique<TestPublicKeyTypeManager>(), true),
              StatusIs(absl::StatusCode::kAlreadyExists,
                       HasSubstr("already registered")));
  EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers(
                  absl::make_unique<TestPrivateKeyTypeManager>(),
                  absl::make_unique<TestPublicKeyTypeManager2>(), true),
              StatusIs(absl::StatusCode::kAlreadyExists,
                       HasSubstr("already registered")));
  EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers(
                  absl::make_unique<TestPrivateKeyTypeManager2>(),
                  absl::make_unique<TestPublicKeyTypeManager2>(), true),
              StatusIs(absl::StatusCode::kAlreadyExists,
                       HasSubstr("already registered")));
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<TestPrivateKeyTypeManager2>(), true),
              StatusIs(absl::StatusCode::kAlreadyExists,
                       HasSubstr("already registered")));
  EXPECT_THAT(Registry::RegisterKeyTypeManager(
                  absl::make_unique<TestPublicKeyTypeManager2>(), true),
              StatusIs(absl::StatusCode::kAlreadyExists,
                       HasSubstr("already registered")));
}

class TestPublicKeyTypeManagerWithDifferentKeyType
    : public TestPublicKeyTypeManager {
  const std::string& get_key_type() const override { return kKeyType; }

 private:
  const std::string kKeyType = "bla";
};

TEST_F(RegistryTest, RegisterAssymmetricReregistrationWithNewKeyType) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
                  absl::make_unique<TestPrivateKeyTypeManager>(),
                  absl::make_unique<TestPublicKeyTypeManager>(), true)
                  .ok());
  EXPECT_THAT(
      Registry::RegisterAsymmetricKeyManagers(
          absl::make_unique<TestPrivateKeyTypeManager>(),
          absl::make_unique<TestPublicKeyTypeManagerWithDifferentKeyType>(),
          true),
      StatusIs(absl::StatusCode::kInvalidArgument,
               HasSubstr("impossible to register")));
}

// The DelegatingKeyTypeManager calls the registry
class DelegatingKeyTypeManager
    : public PrivateKeyTypeManager<EcdsaPrivateKey, EcdsaKeyFormat,
                                   EcdsaPublicKey, List<>> {
 public:
  DelegatingKeyTypeManager() : PrivateKeyTypeManager() {}

  void set_registry(RegistryImpl* registry) { registry_ = registry; }

  google::crypto::tink::KeyData::KeyMaterialType key_material_type()
      const override {
    return google::crypto::tink::KeyData::SYMMETRIC;
  }

  uint32_t get_version() const override { return kVersion; }

  const std::string& get_key_type() const override { return kKeyType; }

  crypto::tink::util::Status ValidateKey(
      const EcdsaPrivateKey& key) const override {
    return util::OkStatus();
  }

  crypto::tink::util::Status ValidateKeyFormat(
      const EcdsaKeyFormat& key_format) const override {
    return util::OkStatus();
  }

  crypto::tink::util::StatusOr<EcdsaPrivateKey> CreateKey(
      const EcdsaKeyFormat& key_format) const override {
    AesGcmKeyFormat format;
    KeyTemplate key_template;
    key_template.set_type_url(
        "type.googleapis.com/google.crypto.tink.AesGcmKey");
    key_template.set_value(format.SerializeAsString());
    auto result = registry_->NewKeyData(key_template);
    if (!result.ok()) return result.status();
    // Return a string we can check for.
    return util::Status(absl::StatusCode::kDeadlineExceeded,
                        "CreateKey worked");
  }

  crypto::tink::util::StatusOr<EcdsaPrivateKey> DeriveKey(
      const EcdsaKeyFormat& key_format,
      InputStream* input_stream) const override {
    AesGcmKeyFormat format;
    KeyTemplate key_template;
    key_template.set_type_url(
        "type.googleapis.com/google.crypto.tink.AesGcmKey");
    key_template.set_value(format.SerializeAsString());

    auto result = registry_->DeriveKey(key_template, input_stream);
    if (!result.ok()) return result.status();
    // Return a string we can check for.
    return util::Status(absl::StatusCode::kDeadlineExceeded,
                        "DeriveKey worked");
  }

  crypto::tink::util::StatusOr<EcdsaPublicKey> GetPublicKey(
      const EcdsaPrivateKey& private_key) const override {
    AesGcmKeyFormat format;
    KeyTemplate key_template;
    key_template.set_type_url(
        "type.googleapis.com/google.crypto.tink.AesGcmKey");
    key_template.set_value(format.SerializeAsString());
    auto result = registry_->NewKeyData(key_template);
    if (!result.ok()) return result.status();
    // Return a string we can check for.
    return util::Status(absl::StatusCode::kDeadlineExceeded,
                        "GetPublicKey worked");
  }

 private:
  RegistryImpl* registry_;

  static constexpr int kVersion = 0;
  const std::string kKeyType =
      "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey";
};

class RegistryImplTest : public ::testing::Test {
 protected:
  void TearDown() override {
    // Calling RestrictToFipsIfEmpty() may call SetFipsRestricted(), which
    // set a global variable to true. We have to reset that after the test.
    UnSetFipsRestricted();
  }
};

// Check that we can call the registry again from within NewKeyData
TEST_F(RegistryImplTest, CanDelegateCreateKey) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  RegistryImpl registry_impl;
  auto delegating_key_manager = absl::make_unique<DelegatingKeyTypeManager>();
  delegating_key_manager->set_registry(&registry_impl);
  auto status =
      registry_impl
          .RegisterKeyTypeManager<EcdsaPrivateKey, EcdsaKeyFormat, List<>>(
              std::move(delegating_key_manager), true);
  EXPECT_THAT(status, IsOk());
  status = registry_impl.RegisterKeyTypeManager<AesGcmKey, AesGcmKeyFormat,
                                                   List<Aead, AeadVariant>>(
                  absl::make_unique<ExampleKeyTypeManager>(), true);
  EXPECT_THAT(status, IsOk());

  EcdsaKeyFormat format;
  KeyTemplate key_template;
  key_template.set_type_url(
      "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey");
  key_template.set_value(format.SerializeAsString());
  EXPECT_THAT(registry_impl.NewKeyData(key_template).status(),
              StatusIs(absl::StatusCode::kDeadlineExceeded,
                       HasSubstr("CreateKey worked")));
}

// Check that we can call the registry again from within NewKeyData
TEST_F(RegistryImplTest, CanDelegateDeriveKey) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  RegistryImpl registry_impl;
  auto delegating_key_manager = absl::make_unique<DelegatingKeyTypeManager>();
  delegating_key_manager->set_registry(&registry_impl);
  auto status =
      registry_impl
          .RegisterKeyTypeManager<EcdsaPrivateKey, EcdsaKeyFormat, List<>>(
              std::move(delegating_key_manager), true);
  EXPECT_THAT(status, IsOk());
  status = registry_impl.RegisterKeyTypeManager<AesGcmKey, AesGcmKeyFormat,
                                                   List<Aead, AeadVariant>>(
                  absl::make_unique<ExampleKeyTypeManager>(), true);
  EXPECT_THAT(status, IsOk());

  EcdsaKeyFormat format;
  KeyTemplate key_template;
  key_template.set_type_url(
      "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey");
  key_template.set_value(format.SerializeAsString());
  EXPECT_THAT(registry_impl.DeriveKey(key_template, nullptr).status(),
              StatusIs(absl::StatusCode::kDeadlineExceeded,
                       HasSubstr("DeriveKey worked")));
}

TEST_F(RegistryImplTest, CanDelegateGetPublicKey) {
  if (kUseOnlyFips) {
    GTEST_SKIP() << "Not supported in FIPS-only mode";
  }

  RegistryImpl registry_impl;
  auto delegating_key_manager = absl::make_unique<DelegatingKeyTypeManager>();
  delegating_key_manager->set_registry(&registry_impl);
  auto status = registry_impl.RegisterAsymmetricKeyManagers(
      delegating_key_manager.release(),
      absl::make_unique<TestPublicKeyTypeManager>().release(), true);
  EXPECT_THAT(status, IsOk());
  status = registry_impl.RegisterKeyTypeManager<AesGcmKey, AesGcmKeyFormat,
                                                   List<Aead, AeadVariant>>(
                  absl::make_unique<ExampleKeyTypeManager>(), true);
  EXPECT_THAT(status, IsOk());

  EcdsaPrivateKey private_key;
  private_key.mutable_public_key()->mutable_params()->set_encoding(
      EcdsaSignatureEncoding::DER);

  EXPECT_THAT(registry_impl
                  .GetPublicKeyData(DelegatingKeyTypeManager().get_key_type(),
                                    private_key.SerializeAsString())
                  .status(),
              StatusIs(absl::StatusCode::kDeadlineExceeded,
                       HasSubstr("GetPublicKey worked")));
}

TEST_F(RegistryImplTest, FipsSucceedsOnEmptyRegistry) {
  RegistryImpl registry_impl;
  EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(), IsOk());
}

TEST_F(RegistryImplTest, FipsFailsIfNotEmpty) {
  if (!FIPS_mode()) {
    GTEST_SKIP() << "Not supported when BoringSSL is not built in FIPS-mode.";
  }

  auto fips_key_manager = absl::make_unique<ExampleKeyTypeManager>();
  ON_CALL(*fips_key_manager, FipsStatus())
      .WillByDefault(testing::Return(FipsCompatibility::kRequiresBoringCrypto));

  RegistryImpl registry_impl;
  auto status = registry_impl.RegisterKeyTypeManager<AesGcmKey, AesGcmKeyFormat,
                                                   List<Aead, AeadVariant>>(
                  std::move(fips_key_manager), true);
  EXPECT_THAT(status, IsOk());
  EXPECT_THAT(registry_impl.RestrictToFipsIfEmpty(),
              StatusIs(absl::StatusCode::kInternal));
}

TEST_F(RegistryImplTest, CanRegisterOnlyOneMonitoringFactory) {
  auto monitoring_client_factory =
      absl::make_unique<MockMonitoringClientFactory>();

  RegistryImpl registry_impl;
  EXPECT_THAT(registry_impl.RegisterMonitoringClientFactory(
                  std::move(monitoring_client_factory)),
              IsOk());
  ASSERT_THAT(registry_impl.GetMonitoringClientFactory(), Not(IsNull()));
  EXPECT_THAT(registry_impl.RegisterMonitoringClientFactory(
                  std::move(monitoring_client_factory)),
              StatusIs(absl::StatusCode::kAlreadyExists));
}

}  // namespace
}  // namespace internal
}  // namespace tink
}  // namespace crypto
