blob: 5aa7ae67c8cd5e3dd93b797d4f35249e6732cde1 [file] [log] [blame]
// 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 "tink/registry.h"
#include <thread> // NOLINT(build/c++11)
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "absl/strings/string_view.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/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/subtle/aes_gcm_boringssl.h"
#include "tink/subtle/random.h"
#include "tink/util/protobuf_helper.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 {
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::KeyStatusType;
using ::google::crypto::tink::KeyTemplate;
using ::google::crypto::tink::OutputPrefixType;
using ::portable_proto::MessageLite;
using ::testing::Eq;
using ::testing::HasSubstr;
using ::testing::SizeIs;
class RegistryTest : public ::testing::Test {
protected:
void SetUp() override {
Registry::Reset();
}
void TearDown() override {
}
};
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::UNKNOWN;
}
util::StatusOr<std::unique_ptr<portable_proto::MessageLite>> NewKey(
absl::string_view serialized_key_format) const override {
return util::Status::UNKNOWN;
}
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::UNKNOWN;
}
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_;
};
template <typename P>
class TestWrapper : public PrimitiveWrapper<P> {
public:
TestWrapper() {}
crypto::tink::util::StatusOr<std::unique_ptr<P>> Wrap(
std::unique_ptr<PrimitiveSet<P>> primitive_set) const override {
return util::Status(util::error::UNIMPLEMENTED, "This is a test wrapper.");
}
};
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.ValueOrDie();
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(util::error::INVALID_ARGUMENT, result_after.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type,
result_after.status().error_message());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow",
result_after.status().error_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(util::error::ALREADY_EXISTS, status.error_code()) << status;
EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type,
status.error_message()) << status;
EXPECT_PRED_FORMAT2(testing::IsSubstring, "forbidden new key operation" ,
status.error_message()) << status;
auto result_after = Registry::NewKeyData(key_template);
EXPECT_FALSE(result_after.ok());
EXPECT_EQ(util::error::INVALID_ARGUMENT, result_after.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type,
result_after.status().error_message());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow",
result_after.status().error_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.
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();
// 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.ValueOrDie()->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(util::error::NOT_FOUND, manager_result.status().error_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(util::error::NOT_FOUND,
manager_result.status().error_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.ValueOrDie();
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.ValueOrDie();
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(util::error::INVALID_ARGUMENT, status.error_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(util::error::ALREADY_EXISTS, status.error_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.ValueOrDie();
EXPECT_TRUE(manager->DoesSupport(key_type_1));
}
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(util::error::UNIMPLEMENTED,
"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(util::error::INVALID_ARGUMENT, status.error_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(util::error::ALREADY_EXISTS, status.error_code()) << status;
// Check the catalogue is still present.
EXPECT_THAT(Registry::get_catalogue<Aead>(catalogue_name).status(), 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.ValueOrDie());
EXPECT_EQ(DummyAead(key_type_1).Encrypt(plaintext, aad).ValueOrDie(),
aead->Encrypt(plaintext, aad).ValueOrDie());
}
// Key #3.
{
auto result = Registry::GetPrimitive<Aead>(keyset.key(2).key_data());
EXPECT_TRUE(result.ok()) << result.status();
auto aead = std::move(result.ValueOrDie());
EXPECT_EQ(DummyAead(key_type_2).Encrypt(plaintext, aad).ValueOrDie(),
aead->Encrypt(plaintext, aad).ValueOrDie());
}
}
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.ValueOrDie()->type_url());
EXPECT_EQ(key_template.value(), new_key_data_result.ValueOrDie()->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.ValueOrDie()->type_url());
EXPECT_EQ(key_template.value(), new_key_data_result.ValueOrDie()->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(util::error::INVALID_ARGUMENT,
new_key_data_result.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, key_type_3,
new_key_data_result.status().error_message());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "does not allow",
new_key_data_result.status().error_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(util::error::NOT_FOUND,
new_key_data_result.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, bad_type_url,
new_key_data_result.status().error_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.ValueOrDie());
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(util::error::INVALID_ARGUMENT,
wrong_key_type_result.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "PrivateKeyFactory",
wrong_key_type_result.status().error_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(util::error::INVALID_ARGUMENT,
bad_key_result.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "Could not parse",
bad_key_result.status().error_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 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(util::error::ALREADY_EXISTS, result.error_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(util::error::INVALID_ARGUMENT, result.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "No wrapper registered",
result.status().error_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",
result.status().error_message());
}
// Tests that wrapping works as expected in the usual case.
TEST_F(RegistryTest, UsualWrappingTest) {
Keyset keyset;
keyset.add_key();
keyset.mutable_key(0)->set_output_prefix_type(OutputPrefixType::TINK);
keyset.mutable_key(0)->set_key_id(1234543);
keyset.mutable_key(0)->set_status(KeyStatusType::ENABLED);
keyset.add_key();
keyset.mutable_key(1)->set_output_prefix_type(OutputPrefixType::LEGACY);
keyset.mutable_key(1)->set_key_id(726329);
keyset.mutable_key(1)->set_status(KeyStatusType::ENABLED);
keyset.add_key();
keyset.mutable_key(2)->set_output_prefix_type(OutputPrefixType::TINK);
keyset.mutable_key(2)->set_key_id(7213743);
keyset.mutable_key(2)->set_status(KeyStatusType::ENABLED);
auto primitive_set = absl::make_unique<PrimitiveSet<Aead>>();
ASSERT_TRUE(
primitive_set
->AddPrimitive(absl::make_unique<DummyAead>("aead0"), keyset.key(0))
.ok());
ASSERT_TRUE(
primitive_set
->AddPrimitive(absl::make_unique<DummyAead>("aead1"), keyset.key(1))
.ok());
auto entry_result = primitive_set->AddPrimitive(
absl::make_unique<DummyAead>("primary_aead"), keyset.key(2));
ASSERT_THAT(primitive_set->set_primary(entry_result.ValueOrDie()), 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.ValueOrDie());
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.ValueOrDie();
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.ValueOrDie());
decrypt_result = aead->Decrypt("some bad ciphertext", aad);
EXPECT_FALSE(decrypt_result.ok());
EXPECT_EQ(util::error::INVALID_ARGUMENT,
decrypt_result.status().error_code());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "decryption failed",
decrypt_result.status().error_message());
}
// 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(result.status().error_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(result.status().error_message(), HasSubstr(typeid(Aead).name()));
}
// 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(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;
}
private:
static const int kVersion = 0;
const std::string kKeyType = "type.googleapis.com/google.crypto.tink.AesGcmKey";
};
TEST_F(RegistryTest, RegisterKeyTypeManager) {
EXPECT_THAT(Registry::RegisterKeyTypeManager(
absl::make_unique<ExampleKeyTypeManager>(), true),
IsOk());
}
TEST_F(RegistryTest, KeyTypeManagerGetFirstKeyManager) {
EXPECT_THAT(Registry::RegisterKeyTypeManager(
absl::make_unique<ExampleKeyTypeManager>(), true),
IsOk());
AesGcmKeyFormat format;
format.set_key_size(16);
AesGcmKey key = ExampleKeyTypeManager().CreateKey(format).ValueOrDie();
auto aead = Registry::get_key_manager<Aead>(
"type.googleapis.com/google.crypto.tink.AesGcmKey")
.ValueOrDie()
->GetPrimitive(key)
.ValueOrDie();
std::string encryption = aead->Encrypt("TESTMESSAGE", "").ValueOrDie();
std::string decryption = aead->Decrypt(encryption, "").ValueOrDie();
EXPECT_THAT(decryption, Eq("TESTMESSAGE"));
}
TEST_F(RegistryTest, KeyTypeManagerGetSecondKeyManager) {
EXPECT_THAT(Registry::RegisterKeyTypeManager(
absl::make_unique<ExampleKeyTypeManager>(), true),
IsOk());
AesGcmKeyFormat format;
format.set_key_size(16);
AesGcmKey key = ExampleKeyTypeManager().CreateKey(format).ValueOrDie();
auto aead_variant = Registry::get_key_manager<AeadVariant>(
"type.googleapis.com/google.crypto.tink.AesGcmKey")
.ValueOrDie()
->GetPrimitive(key)
.ValueOrDie();
EXPECT_THAT(aead_variant->get(), Eq(key.key_value()));
}
TEST_F(RegistryTest, KeyTypeManagerNotSupportedPrimitive) {
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(util::error::INVALID_ARGUMENT,
HasSubstr("not among supported primitives")));
}
TEST_F(RegistryTest, KeyTypeManagerNewKey) {
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).ValueOrDie();
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) {
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).status(), IsOk());
}
TEST_F(RegistryTest, RegisterKeyTypeManagerTwiceMoreRestrictive) {
EXPECT_THAT(Registry::RegisterKeyTypeManager(
absl::make_unique<ExampleKeyTypeManager>(), true),
IsOk());
EXPECT_THAT(Registry::RegisterKeyTypeManager(
absl::make_unique<ExampleKeyTypeManager>(), false),
IsOk());
}
TEST_F(RegistryTest, RegisterKeyTypeManagerTwice) {
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) {
EXPECT_THAT(Registry::RegisterKeyTypeManager(
absl::make_unique<ExampleKeyTypeManager>(), false),
IsOk());
EXPECT_THAT(Registry::RegisterKeyTypeManager(
absl::make_unique<ExampleKeyTypeManager>(), true),
StatusIs(util::error::ALREADY_EXISTS));
}
TEST_F(RegistryTest, RegisterKeyTypeManagerBeforeKeyManager) {
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(util::error::ALREADY_EXISTS));
}
TEST_F(RegistryTest, RegisterKeyTypeManagerAfterKeyManager) {
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(util::error::ALREADY_EXISTS));
}
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(util::error::UNIMPLEMENTED, "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(util::error::UNIMPLEMENTED, "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::Status::OK;
}
crypto::tink::util::Status ValidateKeyFormat(
const EcdsaKeyFormat& key) const override {
return crypto::tink::util::Status::OK;
}
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();
}
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(util::error::UNIMPLEMENTED, "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(util::error::UNIMPLEMENTED, "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::Status::OK;
}
const std::string& get_key_type() const override { return kKeyType; }
private:
const std::string kKeyType =
"type.googleapis.com/google.crypto.tink.EcdsaPublicKey";
};
TEST_F(RegistryTest, RegisterAsymmetricKeyManagers) {
crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true);
ASSERT_TRUE(status.ok()) << status;
}
TEST_F(RegistryTest, AsymmetricMoreRestrictiveNewKey) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true)
.ok());
crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), false);
ASSERT_TRUE(status.ok()) << status;
}
TEST_F(RegistryTest, AsymmetricSameNewKey) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true)
.ok());
crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true);
ASSERT_TRUE(status.ok()) << status;
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), false)
.ok());
status = Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), false);
ASSERT_TRUE(status.ok()) << status;
}
TEST_F(RegistryTest, AsymmetricLessRestrictiveGivesError) {
crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), false);
ASSERT_TRUE(status.ok()) << status;
EXPECT_THAT(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true),
StatusIs(util::error::ALREADY_EXISTS,
HasSubstr("forbidden new key operation")));
}
TEST_F(RegistryTest, AsymmetricPrivateRegisterAlone) {
ASSERT_TRUE(Registry::RegisterKeyTypeManager(
absl::make_unique<TestPrivateKeyTypeManager>(), true)
.ok());
ASSERT_TRUE(Registry::RegisterKeyTypeManager(
absl::make_unique<TestPublicKeyTypeManager>(), true)
.ok());
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true)
.ok());
ASSERT_TRUE(Registry::RegisterKeyTypeManager(
absl::make_unique<TestPrivateKeyTypeManager>(), true)
.ok());
ASSERT_TRUE(Registry::RegisterKeyTypeManager(
absl::make_unique<TestPublicKeyTypeManager>(), true)
.ok());
}
TEST_F(RegistryTest, AsymmetricGetPrimitiveA) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), 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.ValueOrDie()->get_key_type(),
Eq(TestPrivateKeyTypeManager().get_key_type()));
}
TEST_F(RegistryTest, AsymmetricGetPrimitiveB) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), 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.ValueOrDie()->get_key_type(),
Eq(TestPrivateKeyTypeManager().get_key_type()));
}
TEST_F(RegistryTest, AsymmetricGetPublicPrimitiveA) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), 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.ValueOrDie()->get_key_type(),
Eq(TestPublicKeyTypeManager().get_key_type()));
}
TEST_F(RegistryTest, AsymmetricGetPublicPrimitiveB) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), 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.ValueOrDie()->get_key_type(),
Eq(TestPublicKeyTypeManager().get_key_type()));
}
TEST_F(RegistryTest, AsymmetricGetWrongPrimitiveError) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true)
.ok());
crypto::tink::util::StatusOr<const KeyManager<PublicPrimitiveA>*> km =
Registry::get_key_manager<PublicPrimitiveA>(
TestPrivateKeyTypeManager().get_key_type());
EXPECT_THAT(km.status(),
StatusIs(util::error::INVALID_ARGUMENT,
HasSubstr("not among supported primitives")));
}
TEST(PrivateKeyManagerImplTest, AsymmetricFactoryNewKeyFromMessage) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), 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).ValueOrDie();
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(PrivateKeyManagerImplTest, AsymmetricNewKeyDisallowed) {
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), true)
.ok());
ASSERT_TRUE(Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), false)
.ok());
KeyTemplate key_template;
key_template.set_type_url(TestPrivateKeyTypeManager().get_key_type());
EXPECT_THAT(Registry::NewKeyData(key_template).status(),
StatusIs(util::error::INVALID_ARGUMENT, HasSubstr("not allow")));
}
TEST_F(RegistryTest, AsymmetricGetPublicKeyData) {
crypto::tink::util::Status status = Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager>(), 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())
.ValueOrDie();
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) {
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(util::error::ALREADY_EXISTS, HasSubstr("already registered")));
EXPECT_THAT(
Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager>(),
absl::make_unique<TestPublicKeyTypeManager2>(), true),
StatusIs(util::error::ALREADY_EXISTS, HasSubstr("already registered")));
EXPECT_THAT(
Registry::RegisterAsymmetricKeyManagers(
absl::make_unique<TestPrivateKeyTypeManager2>(),
absl::make_unique<TestPublicKeyTypeManager2>(), true),
StatusIs(util::error::ALREADY_EXISTS, HasSubstr("already registered")));
EXPECT_THAT(
Registry::RegisterKeyTypeManager(
absl::make_unique<TestPrivateKeyTypeManager2>(), true),
StatusIs(util::error::ALREADY_EXISTS, HasSubstr("already registered")));
EXPECT_THAT(
Registry::RegisterKeyTypeManager(
absl::make_unique<TestPublicKeyTypeManager2>(), true),
StatusIs(util::error::ALREADY_EXISTS, 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) {
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(util::error::INVALID_ARGUMENT,
HasSubstr("cannot be re-registered")));
}
} // namespace
} // namespace tink
} // namespace crypto