From b9615a3dde8207df3c28f01d986073636ea73ab5 Mon Sep 17 00:00:00 2001
From: tholenst <tholenst@google.com>
Date: Tue, 6 Aug 2019 08:47:31 -0700
Subject: [PATCH] Migrate the AesGcmKeyManager to a KeyTypeManager.

PiperOrigin-RevId: 261922099
---
 cc/BUILD.bazel                                |   2 +
 cc/CMakeLists.txt                             |   2 +
 cc/aead/BUILD.bazel                           |   9 +-
 cc/aead/CMakeLists.txt                        |   4 +-
 cc/aead/aead_config.cc                        |   4 +-
 cc/aead/aead_factory_test.cc                  |  25 +-
 cc/aead/aead_key_templates_test.cc            | 100 +++--
 cc/aead/aes_gcm_key_manager.cc                |  99 -----
 cc/aead/aes_gcm_key_manager.h                 |  64 +++-
 cc/aead/aes_gcm_key_manager_test.cc           | 359 +++++++-----------
 cc/core/keyset_handle_test.cc                 |  27 +-
 cc/core/keyset_manager_test.cc                |  10 +-
 cc/core/registry_test.cc                      |  19 +-
 .../ecies_aead_hkdf_hybrid_decrypt_test.cc    |   9 +-
 .../ecies_aead_hkdf_hybrid_encrypt_test.cc    |   9 +-
 ...cies_aead_hkdf_private_key_manager_test.cc |   4 +-
 ...ecies_aead_hkdf_public_key_manager_test.cc |   4 +-
 cc/signature/ecdsa_sign_key_manager_test.cc   |  13 +-
 cc/signature/ed25519_sign_key_manager_test.cc |  13 +-
 .../rsa_ssa_pkcs1_sign_key_manager_test.cc    |  15 +-
 .../rsa_ssa_pss_sign_key_manager_test.cc      |  15 +-
 .../UnitTests/aead/TINKAeadFactoryTest.mm     |  22 +-
 22 files changed, 344 insertions(+), 484 deletions(-)
 delete mode 100644 cc/aead/aes_gcm_key_manager.cc

diff --git a/cc/BUILD.bazel b/cc/BUILD.bazel
index a70df9153..4323bd464 100644
--- a/cc/BUILD.bazel
+++ b/cc/BUILD.bazel
@@ -812,6 +812,7 @@ cc_test(
     deps = [
         ":aead",
         ":catalogue",
+        ":core/key_manager_impl",
         ":core/key_type_manager",
         ":crypto_format",
         ":keyset_manager",
@@ -945,6 +946,7 @@ cc_test(
         ":binary_keyset_reader",
         ":cleartext_keyset_handle",
         ":config",
+        ":core/key_manager_impl",
         ":json_keyset_reader",
         ":json_keyset_writer",
         ":keyset_handle",
diff --git a/cc/CMakeLists.txt b/cc/CMakeLists.txt
index 6448c8e1f..4dcf7bdb9 100644
--- a/cc/CMakeLists.txt
+++ b/cc/CMakeLists.txt
@@ -615,6 +615,7 @@ tink_cc_test(
     tink::core::aead
     tink::core::catalogue
     tink::core::crypto_format
+    tink::core::key_manager_impl
     tink::core::key_type_manager
     tink::core::keyset_manager
     tink::core::registry
@@ -717,6 +718,7 @@ tink_cc_test(
     tink::core::config
     tink::core::json_keyset_reader
     tink::core::json_keyset_writer
+    tink::core::key_manager_impl
     tink::core::keyset_handle
     tink::static
     tink::aead::aead_key_templates
diff --git a/cc/aead/BUILD.bazel b/cc/aead/BUILD.bazel
index 24e745c6c..1110445d9 100644
--- a/cc/aead/BUILD.bazel
+++ b/cc/aead/BUILD.bazel
@@ -30,6 +30,7 @@ cc_library(
     strip_include_prefix = "/cc",
     visibility = ["//visibility:public"],
     deps = [
+        ":aead_wrapper",
         ":aes_ctr_hmac_aead_key_manager",
         ":aes_eax_key_manager",
         ":aes_gcm_key_manager",
@@ -37,7 +38,6 @@ cc_library(
         ":kms_aead_key_manager",
         ":kms_envelope_aead_key_manager",
         ":xchacha20_poly1305_key_manager",
-        ":aead_wrapper",
         "//cc/config:config_util",
         "//cc/mac:mac_config",
         "//cc/util:status",
@@ -109,12 +109,12 @@ cc_library(
 
 cc_library(
     name = "aes_gcm_key_manager",
-    srcs = ["aes_gcm_key_manager.cc"],
     hdrs = ["aes_gcm_key_manager.h"],
     include_prefix = "tink",
     strip_include_prefix = "/cc",
     deps = [
         "//cc:aead",
+        "//cc:core/key_type_manager",
         "//cc:key_manager",
         "//cc:key_manager_base",
         "//cc/subtle:aes_gcm_boringssl",
@@ -346,6 +346,7 @@ cc_test(
         ":aes_gcm_key_manager",
         ":aes_gcm_siv_key_manager",
         ":xchacha20_poly1305_key_manager",
+        "//cc/util:test_matchers",
         "//proto:aes_ctr_hmac_aead_cc_proto",
         "//proto:aes_eax_cc_proto",
         "//proto:aes_gcm_cc_proto",
@@ -385,6 +386,7 @@ cc_test(
         "//cc:aead",
         "//cc/util:status",
         "//cc/util:statusor",
+        "//cc/util:test_matchers",
         "//proto:aes_eax_cc_proto",
         "//proto:aes_gcm_cc_proto",
         "//proto:common_cc_proto",
@@ -463,8 +465,8 @@ cc_test(
         "//cc/util:test_matchers",
         "//cc/util:test_util",
         "//proto:aes_eax_cc_proto",
-        "//proto:kms_aead_cc_proto",
         "//proto:common_cc_proto",
+        "//proto:kms_aead_cc_proto",
         "//proto:tink_cc_proto",
         "@com_google_absl//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -518,4 +520,3 @@ cc_test(
         "@com_google_googletest//:gtest_main",
     ],
 )
-
diff --git a/cc/aead/CMakeLists.txt b/cc/aead/CMakeLists.txt
index cd1e289f4..d4ecbfc20 100644
--- a/cc/aead/CMakeLists.txt
+++ b/cc/aead/CMakeLists.txt
@@ -96,11 +96,11 @@ tink_cc_library(
 tink_cc_library(
   NAME aes_gcm_key_manager
   SRCS
-    aes_gcm_key_manager.cc
     aes_gcm_key_manager.h
   DEPS
     tink::core::aead
     tink::core::key_manager
+    tink::core::key_type_manager
     tink::core::key_manager_base
     tink::subtle::aes_gcm_boringssl
     tink::subtle::random
@@ -304,6 +304,7 @@ tink_cc_test(
     tink::aead::aes_gcm_key_manager
     tink::aead::aes_gcm_siv_key_manager
     tink::aead::xchacha20_poly1305_key_manager
+    tink::util::test_matchers
     tink::proto::aes_ctr_hmac_aead_cc_proto
     tink::proto::aes_eax_cc_proto
     tink::proto::aes_gcm_cc_proto
@@ -335,6 +336,7 @@ tink_cc_test(
     tink::core::aead
     tink::util::status
     tink::util::statusor
+    tink::util::test_matchers
     tink::proto::aes_eax_cc_proto
     tink::proto::aes_gcm_cc_proto
     tink::proto::common_cc_proto
diff --git a/cc/aead/aead_config.cc b/cc/aead/aead_config.cc
index bcef29100..a33e72dab 100644
--- a/cc/aead/aead_config.cc
+++ b/cc/aead/aead_config.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -54,7 +54,7 @@ util::Status AeadConfig::Register() {
   status = Registry::RegisterKeyManager(
       absl::make_unique<AesCtrHmacAeadKeyManager>(), true);
   if (!status.ok()) return status;
-  status = Registry::RegisterKeyManager(
+  status = Registry::RegisterKeyTypeManager(
       absl::make_unique<AesGcmKeyManager>(), true);
   if (!status.ok()) return status;
   status = Registry::RegisterKeyManager(
diff --git a/cc/aead/aead_factory_test.cc b/cc/aead/aead_factory_test.cc
index d6abf83ee..1cc2d3cfd 100644
--- a/cc/aead/aead_factory_test.cc
+++ b/cc/aead/aead_factory_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
 using crypto::tink::TestKeysetHandle;
 using crypto::tink::test::AddRawKey;
 using crypto::tink::test::AddTinkKey;
+using google::crypto::tink::AesGcmKey;
 using google::crypto::tink::AesGcmKeyFormat;
 using google::crypto::tink::KeyData;
 using google::crypto::tink::Keyset;
@@ -55,9 +56,7 @@ TEST_F(AeadFactoryTest, testBasic) {
 
 TEST_F(AeadFactoryTest, testPrimitive) {
   // Prepare a template for generating keys for a Keyset.
-  AesGcmKeyManager key_manager;
-  const KeyFactory& key_factory = key_manager.get_key_factory();
-  std::string key_type = key_manager.get_key_type();
+  std::string key_type = AesGcmKeyManager().get_key_type();
 
   AesGcmKeyFormat key_format;
   key_format.set_key_size(16);
@@ -65,18 +64,18 @@ TEST_F(AeadFactoryTest, testPrimitive) {
   // Prepare a Keyset.
   Keyset keyset;
   uint32_t key_id_1 = 1234543;
-  auto new_key = std::move(key_factory.NewKey(key_format).ValueOrDie());
-  AddTinkKey(key_type, key_id_1, *new_key, KeyStatusType::ENABLED,
+  AesGcmKey new_key = AesGcmKeyManager().CreateKey(key_format).ValueOrDie();
+  AddTinkKey(key_type, key_id_1, new_key, KeyStatusType::ENABLED,
              KeyData::SYMMETRIC, &keyset);
 
   uint32_t key_id_2 = 726329;
-  new_key = std::move(key_factory.NewKey(key_format).ValueOrDie());
-  AddRawKey(key_type, key_id_2, *new_key, KeyStatusType::ENABLED,
+  new_key = AesGcmKeyManager().CreateKey(key_format).ValueOrDie();
+  AddRawKey(key_type, key_id_2, new_key, KeyStatusType::ENABLED,
             KeyData::SYMMETRIC, &keyset);
 
   uint32_t key_id_3 = 7213743;
-  new_key = std::move(key_factory.NewKey(key_format).ValueOrDie());
-  AddTinkKey(key_type, key_id_3, *new_key, KeyStatusType::ENABLED,
+  new_key = AesGcmKeyManager().CreateKey(key_format).ValueOrDie();
+  AddTinkKey(key_type, key_id_3, new_key, KeyStatusType::ENABLED,
              KeyData::SYMMETRIC, &keyset);
 
   keyset.set_primary_key_id(key_id_3);
@@ -113,8 +112,10 @@ TEST_F(AeadFactoryTest, testPrimitive) {
                       decrypt_result.status().error_message());
 
   // Create raw ciphertext with 2nd key, and decrypt with Aead-instance.
-  auto raw_aead = std::move(
-      key_manager.GetPrimitive(keyset.key(1).key_data()).ValueOrDie());
+  AesGcmKey raw_key;
+  EXPECT_TRUE(raw_key.ParseFromString(keyset.key(1).key_data().value()));
+  auto raw_aead =
+      std::move(AesGcmKeyManager().GetPrimitive<Aead>(raw_key).ValueOrDie());
   std::string raw_ciphertext = raw_aead->Encrypt(plaintext, aad).ValueOrDie();
   decrypt_result = aead->Decrypt(ciphertext, aad);
   EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status();
diff --git a/cc/aead/aead_key_templates_test.cc b/cc/aead/aead_key_templates_test.cc
index 0efff4469..ca16ebba0 100644
--- a/cc/aead/aead_key_templates_test.cc
+++ b/cc/aead/aead_key_templates_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 Google Inc.
+// Copyright 2018 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,12 +16,14 @@
 
 #include "tink/aead/aead_key_templates.h"
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "tink/aead/aes_ctr_hmac_aead_key_manager.h"
 #include "tink/aead/aes_eax_key_manager.h"
 #include "tink/aead/aes_gcm_key_manager.h"
 #include "tink/aead/aes_gcm_siv_key_manager.h"
 #include "tink/aead/xchacha20_poly1305_key_manager.h"
+#include "tink/util/test_matchers.h"
 #include "proto/aes_ctr_hmac_aead.pb.h"
 #include "proto/aes_eax.pb.h"
 #include "proto/aes_gcm.pb.h"
@@ -42,6 +44,10 @@ namespace crypto {
 namespace tink {
 namespace {
 
+using ::crypto::tink::test::IsOk;
+using ::testing::Eq;
+using ::testing::Ref;
+
 TEST(AeadKeyTemplatesTest, testAesEaxKeyTemplates) {
   std::string type_url = "type.googleapis.com/google.crypto.tink.AesEaxKey";
 
@@ -90,50 +96,66 @@ TEST(AeadKeyTemplatesTest, testAesEaxKeyTemplates) {
   }
 }
 
-TEST(AeadKeyTemplatesTest, testAesGcmKeyTemplates) {
-  std::string type_url = "type.googleapis.com/google.crypto.tink.AesGcmKey";
+TEST(Aes256Gcm, Basics) {
+  EXPECT_THAT(AeadKeyTemplates::Aes256Gcm().type_url(),
+              Eq("type.googleapis.com/google.crypto.tink.AesGcmKey"));
+  EXPECT_THAT(AeadKeyTemplates::Aes256Gcm().type_url(),
+              Eq(AesGcmKeyManager().get_key_type()));
+}
 
-  {  // Test Aes128Gcm().
-    // Check that returned template is correct.
-    const KeyTemplate& key_template = AeadKeyTemplates::Aes128Gcm();
-    EXPECT_EQ(type_url, key_template.type_url());
-    EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type());
-    AesGcmKeyFormat key_format;
-    EXPECT_TRUE(key_format.ParseFromString(key_template.value()));
-    EXPECT_EQ(16, key_format.key_size());
+TEST(Aes256Gcm, OutputPrefixType) {
+  EXPECT_THAT(AeadKeyTemplates::Aes256Gcm().output_prefix_type(),
+              Eq(OutputPrefixType::TINK));
+}
 
-    // Check that reference to the same object is returned.
-    const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes128Gcm();
-    EXPECT_EQ(&key_template, &key_template_2);
+TEST(Aes256Gcm, MultipleCallsSameReference) {
+  EXPECT_THAT(AeadKeyTemplates::Aes256Gcm(),
+              Ref(AeadKeyTemplates::Aes256Gcm()));
+}
 
-    // Check that the template works with the key manager.
-    AesGcmKeyManager key_manager;
-    EXPECT_EQ(key_manager.get_key_type(), key_template.type_url());
-    auto new_key_result =
-        key_manager.get_key_factory().NewKey(key_template.value());
-    EXPECT_TRUE(new_key_result.ok()) << new_key_result.status();
-  }
+TEST(Aes256Gcm, WorksWithKeyTypeManager) {
+  const KeyTemplate& key_template = AeadKeyTemplates::Aes256Gcm();
+  AesGcmKeyFormat key_format;
+  EXPECT_TRUE(key_format.ParseFromString(key_template.value()));
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(key_format), IsOk());
+}
 
-  {  // Test Aes256Gcm().
-    // Check that returned template is correct.
-    const KeyTemplate& key_template = AeadKeyTemplates::Aes256Gcm();
-    EXPECT_EQ(type_url, key_template.type_url());
-    EXPECT_EQ(OutputPrefixType::TINK, key_template.output_prefix_type());
-    AesGcmKeyFormat key_format;
-    EXPECT_TRUE(key_format.ParseFromString(key_template.value()));
-    EXPECT_EQ(32, key_format.key_size());
+TEST(Aes256Gcm, CheckValues) {
+  const KeyTemplate& key_template = AeadKeyTemplates::Aes256Gcm();
+  AesGcmKeyFormat key_format;
+  EXPECT_TRUE(key_format.ParseFromString(key_template.value()));
+  EXPECT_THAT(key_format.key_size(), Eq(32));
+}
 
-    // Check that reference to the same object is returned.
-    const KeyTemplate& key_template_2 = AeadKeyTemplates::Aes256Gcm();
-    EXPECT_EQ(&key_template, &key_template_2);
+TEST(Aes128Gcm, Basics) {
+  EXPECT_THAT(AeadKeyTemplates::Aes128Gcm().type_url(),
+              Eq("type.googleapis.com/google.crypto.tink.AesGcmKey"));
+  EXPECT_THAT(AeadKeyTemplates::Aes128Gcm().type_url(),
+              Eq(AesGcmKeyManager().get_key_type()));
+}
 
-    // Check that the template works with the key manager.
-    AesGcmKeyManager key_manager;
-    EXPECT_EQ(key_manager.get_key_type(), key_template.type_url());
-    auto new_key_result =
-        key_manager.get_key_factory().NewKey(key_template.value());
-    EXPECT_TRUE(new_key_result.ok()) << new_key_result.status();
-  }
+TEST(Aes128Gcm, OutputPrefixType) {
+  EXPECT_THAT(AeadKeyTemplates::Aes128Gcm().output_prefix_type(),
+              Eq(OutputPrefixType::TINK));
+}
+
+TEST(Aes128Gcm, MultipleCallsSameReference) {
+  EXPECT_THAT(AeadKeyTemplates::Aes128Gcm(),
+              Ref(AeadKeyTemplates::Aes128Gcm()));
+}
+
+TEST(Aes128Gcm, WorksWithKeyTypeManager) {
+  const KeyTemplate& key_template = AeadKeyTemplates::Aes128Gcm();
+  AesGcmKeyFormat key_format;
+  EXPECT_TRUE(key_format.ParseFromString(key_template.value()));
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(key_format), IsOk());
+}
+
+TEST(Aes128Gcm, CheckValues) {
+  const KeyTemplate& key_template = AeadKeyTemplates::Aes128Gcm();
+  AesGcmKeyFormat key_format;
+  EXPECT_TRUE(key_format.ParseFromString(key_template.value()));
+  EXPECT_THAT(key_format.key_size(), Eq(16));
 }
 
 TEST(AeadKeyTemplatesTest, testAesGcmSivKeyTemplates) {
diff --git a/cc/aead/aes_gcm_key_manager.cc b/cc/aead/aes_gcm_key_manager.cc
deleted file mode 100644
index cc98c4273..000000000
--- a/cc/aead/aes_gcm_key_manager.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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/aead/aes_gcm_key_manager.h"
-
-#include "absl/base/casts.h"
-#include "absl/strings/string_view.h"
-#include "tink/aead.h"
-#include "tink/key_manager.h"
-#include "tink/subtle/aes_gcm_boringssl.h"
-#include "tink/subtle/random.h"
-#include "tink/util/errors.h"
-#include "tink/util/protobuf_helper.h"
-#include "tink/util/status.h"
-#include "tink/util/statusor.h"
-#include "tink/util/validation.h"
-#include "proto/aes_gcm.pb.h"
-#include "proto/tink.pb.h"
-
-namespace crypto {
-namespace tink {
-
-using ::crypto::tink::util::Status;
-using ::crypto::tink::util::StatusOr;
-using ::google::crypto::tink::AesGcmKey;
-using ::google::crypto::tink::AesGcmKeyFormat;
-using ::google::crypto::tink::KeyData;
-
-class AesGcmKeyFactory : public KeyFactoryBase<AesGcmKey, AesGcmKeyFormat> {
- public:
-  AesGcmKeyFactory() {}
-
-  KeyData::KeyMaterialType key_material_type() const override {
-    return KeyData::SYMMETRIC;
-  }
-
- protected:
-  StatusOr<std::unique_ptr<AesGcmKey>> NewKeyFromFormat(
-      const AesGcmKeyFormat& aes_gcm_key_format) const override {
-    Status status = AesGcmKeyManager::Validate(aes_gcm_key_format);
-    if (!status.ok()) return status;
-    std::unique_ptr<AesGcmKey> aes_gcm_key(new AesGcmKey());
-    aes_gcm_key->set_version(AesGcmKeyManager::kVersion);
-    aes_gcm_key->set_key_value(
-        subtle::Random::GetRandomBytes(aes_gcm_key_format.key_size()));
-    return absl::implicit_cast<StatusOr<std::unique_ptr<AesGcmKey>>>(
-        std::move(aes_gcm_key));
-  }
-};
-
-constexpr uint32_t AesGcmKeyManager::kVersion;
-
-AesGcmKeyManager::AesGcmKeyManager()
-    : key_factory_(absl::make_unique<AesGcmKeyFactory>()) {}
-
-uint32_t AesGcmKeyManager::get_version() const {
-  return kVersion;
-}
-
-const KeyFactory& AesGcmKeyManager::get_key_factory() const {
-  return *key_factory_;
-}
-
-StatusOr<std::unique_ptr<Aead>> AesGcmKeyManager::GetPrimitiveFromKey(
-    const AesGcmKey& aes_gcm_key) const {
-  Status status = Validate(aes_gcm_key);
-  if (!status.ok()) return status;
-  auto aes_gcm_result = subtle::AesGcmBoringSsl::New(aes_gcm_key.key_value());
-  if (!aes_gcm_result.ok()) return aes_gcm_result.status();
-  return std::move(aes_gcm_result.ValueOrDie());
-}
-
-// static
-Status AesGcmKeyManager::Validate(const AesGcmKey& key) {
-  Status status = ValidateVersion(key.version(), kVersion);
-  if (!status.ok()) return status;
-  return ValidateAesKeySize(key.key_value().size());
-}
-
-// static
-Status AesGcmKeyManager::Validate(const AesGcmKeyFormat& key_format) {
-  return ValidateAesKeySize(key_format.key_size());
-}
-
-}  // namespace tink
-}  // namespace crypto
diff --git a/cc/aead/aes_gcm_key_manager.h b/cc/aead/aes_gcm_key_manager.h
index 5bb41d45f..7e27eade3 100644
--- a/cc/aead/aes_gcm_key_manager.h
+++ b/cc/aead/aes_gcm_key_manager.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -22,11 +22,15 @@
 #include "absl/strings/string_view.h"
 #include "tink/aead.h"
 #include "tink/core/key_manager_base.h"
+#include "tink/core/key_type_manager.h"
 #include "tink/key_manager.h"
+#include "tink/subtle/aes_gcm_boringssl.h"
+#include "tink/subtle/random.h"
 #include "tink/util/errors.h"
 #include "tink/util/protobuf_helper.h"
 #include "tink/util/status.h"
 #include "tink/util/statusor.h"
+#include "tink/util/validation.h"
 #include "proto/aes_gcm.pb.h"
 #include "proto/tink.pb.h"
 
@@ -34,34 +38,56 @@ namespace crypto {
 namespace tink {
 
 class AesGcmKeyManager
-    : public KeyManagerBase<Aead, google::crypto::tink::AesGcmKey> {
+    : public KeyTypeManager<google::crypto::tink::AesGcmKey,
+                            google::crypto::tink::AesGcmKeyFormat, List<Aead>> {
  public:
-  static constexpr uint32_t kVersion = 0;
+  class AeadFactory : public PrimitiveFactory<Aead> {
+    crypto::tink::util::StatusOr<std::unique_ptr<Aead>> Create(
+        const google::crypto::tink::AesGcmKey& key) const override {
+      auto aes_gcm_result = subtle::AesGcmBoringSsl::New(key.key_value());
+      if (!aes_gcm_result.ok()) return aes_gcm_result.status();
+      return {std::move(aes_gcm_result.ValueOrDie())};
+    }
+  };
 
-  AesGcmKeyManager();
+  AesGcmKeyManager()
+      : KeyTypeManager(absl::make_unique<AesGcmKeyManager::AeadFactory>()) {}
 
   // Returns the version of this key manager.
-  uint32_t get_version() const override;
+  uint32_t get_version() const override { return 0; }
 
-  // Returns a factory that generates keys of the key type
-  // handled by this manager.
-  const KeyFactory& get_key_factory() const override;
+  google::crypto::tink::KeyData::KeyMaterialType key_material_type()
+      const override {
+    return google::crypto::tink::KeyData::SYMMETRIC;
+  }
 
-  virtual ~AesGcmKeyManager() {}
+  const std::string& get_key_type() const override { return key_type_; }
 
- protected:
-  crypto::tink::util::StatusOr<std::unique_ptr<Aead>> GetPrimitiveFromKey(
-      const google::crypto::tink::AesGcmKey& key) const override;
+  crypto::tink::util::Status ValidateKey(
+      const google::crypto::tink::AesGcmKey& key) const override {
+    crypto::tink::util::Status status =
+        ValidateVersion(key.version(), get_version());
+    if (!status.ok()) return status;
+    return ValidateAesKeySize(key.key_value().size());
+  }
 
- private:
-  friend class AesGcmKeyFactory;
+  crypto::tink::util::Status ValidateKeyFormat(
+      const google::crypto::tink::AesGcmKeyFormat& key_format) const override {
+    return ValidateAesKeySize(key_format.key_size());
+  }
 
-  std::unique_ptr<KeyFactory> key_factory_;
+  crypto::tink::util::StatusOr<google::crypto::tink::AesGcmKey> CreateKey(
+      const google::crypto::tink::AesGcmKeyFormat& key_format) const override {
+    google::crypto::tink::AesGcmKey key;
+    key.set_version(get_version());
+    key.set_key_value(
+        crypto::tink::subtle::Random::GetRandomBytes(key_format.key_size()));
+    return key;
+  }
 
-  static crypto::tink::util::Status Validate(
-      const google::crypto::tink::AesGcmKey& key);
-  static crypto::tink::util::Status Validate(
-      const google::crypto::tink::AesGcmKeyFormat& key_format);
+ private:
+  const std::string key_type_ = absl::StrCat(
+      kTypeGoogleapisCom, google::crypto::tink::AesGcmKey().GetTypeName());
 };
 
 }  // namespace tink
diff --git a/cc/aead/aes_gcm_key_manager_test.cc b/cc/aead/aes_gcm_key_manager_test.cc
index e069b44a1..0783bd3e8 100644
--- a/cc/aead/aes_gcm_key_manager_test.cc
+++ b/cc/aead/aes_gcm_key_manager_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,255 +16,184 @@
 
 #include "tink/aead/aes_gcm_key_manager.h"
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "tink/aead.h"
 #include "tink/util/status.h"
 #include "tink/util/statusor.h"
-#include "gtest/gtest.h"
-#include "proto/aes_eax.pb.h"
+#include "tink/util/test_matchers.h"
 #include "proto/aes_gcm.pb.h"
-#include "proto/common.pb.h"
-#include "proto/tink.pb.h"
 
 namespace crypto {
 namespace tink {
 
-using google::crypto::tink::AesEaxKey;
-using google::crypto::tink::AesEaxKeyFormat;
-using google::crypto::tink::AesGcmKey;
-using google::crypto::tink::AesGcmKeyFormat;
-using google::crypto::tink::KeyData;
-
 namespace {
 
-class AesGcmKeyManagerTest : public ::testing::Test {
- protected:
-  std::string key_type_prefix = "type.googleapis.com/";
-  std::string aes_gcm_key_type =
-      "type.googleapis.com/google.crypto.tink.AesGcmKey";
-};
-
-TEST_F(AesGcmKeyManagerTest, testBasic) {
-  AesGcmKeyManager key_manager;
-
-  EXPECT_EQ(0, key_manager.get_version());
-  EXPECT_EQ("type.googleapis.com/google.crypto.tink.AesGcmKey",
-            key_manager.get_key_type());
-  EXPECT_TRUE(key_manager.DoesSupport(key_manager.get_key_type()));
+using ::crypto::tink::test::IsOk;
+using ::crypto::tink::test::StatusIs;
+using ::crypto::tink::util::StatusOr;
+using ::google::crypto::tink::AesGcmKey;
+using ::google::crypto::tink::AesGcmKeyFormat;
+using ::testing::Eq;
+
+TEST(AesGcmKeyManagerTest, Basics) {
+  EXPECT_THAT(AesGcmKeyManager().get_version(), Eq(0));
+  EXPECT_THAT(AesGcmKeyManager().get_key_type(),
+              Eq("type.googleapis.com/google.crypto.tink.AesGcmKey"));
+  EXPECT_THAT(AesGcmKeyManager().key_material_type(),
+              Eq(google::crypto::tink::KeyData::SYMMETRIC));
 }
 
-TEST_F(AesGcmKeyManagerTest, testKeyDataErrors) {
-  AesGcmKeyManager key_manager;
-
-  {  // Bad key type.
-    KeyData key_data;
-    std::string bad_key_type =
-        "type.googleapis.com/google.crypto.tink.SomeOtherKey";
-    key_data.set_type_url(bad_key_type);
-    auto result = key_manager.GetPrimitive(key_data);
-    EXPECT_FALSE(result.ok());
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported",
-                        result.status().error_message());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, bad_key_type,
-                        result.status().error_message());
-  }
+TEST(AesGcmKeyManagerTest, ValidateEmptyKey) {
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(AesGcmKey()),
+              StatusIs(util::error::INVALID_ARGUMENT));
+}
 
-  {  // Bad key value.
-    KeyData key_data;
-    key_data.set_type_url(aes_gcm_key_type);
-    key_data.set_value("some bad serialized proto");
-    auto result = key_manager.GetPrimitive(key_data);
-    EXPECT_FALSE(result.ok());
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "not parse",
-                        result.status().error_message());
-  }
+TEST(AesGcmKeyManagerTest, ValidateValid16ByteKey) {
+  AesGcmKey key;
+  key.set_version(0);
+  key.set_key_value("0123456789abcdef");
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), IsOk());
+}
 
-  {  // Bad version.
-    KeyData key_data;
-    AesGcmKey key;
-    key.set_version(1);
-    key_data.set_type_url(aes_gcm_key_type);
-    key_data.set_value(key.SerializeAsString());
-    auto result = key_manager.GetPrimitive(key_data);
-    EXPECT_FALSE(result.ok());
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "version",
-                        result.status().error_message());
-  }
+TEST(AesGcmKeyManagerTest, ValidateValid32ByteKey) {
+  AesGcmKey key;
+  key.set_version(0);
+  key.set_key_value("01234567890123456789012345678901");
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(key), IsOk());
+}
 
-  {  // Bad key_value size (supported sizes: 16, 32).
-    for (int len = 0; len < 42; len++) {
-      AesGcmKey key;
-      key.set_version(0);
-      key.set_key_value(std::string(len, 'a'));
-      KeyData key_data;
-      key_data.set_type_url(aes_gcm_key_type);
-      key_data.set_value(key.SerializeAsString());
-      auto result = key_manager.GetPrimitive(key_data);
-      if (len == 16 || len == 32) {
-        EXPECT_TRUE(result.ok()) << result.status();
-      } else {
-        EXPECT_FALSE(result.ok());
-        EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-        EXPECT_PRED_FORMAT2(testing::IsSubstring,
-                            std::to_string(len) + " bytes",
-                            result.status().error_message());
-        EXPECT_PRED_FORMAT2(testing::IsSubstring, "supported sizes",
-                            result.status().error_message());
-      }
-    }
-  }
+TEST(AesGcmKeyManagerTest, InvalidKeySizes15Bytes) {
+  AesGcmKey key;
+  key.set_version(0);
+  key.set_key_value("0123456789abcde");
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(key),
+              StatusIs(util::error::INVALID_ARGUMENT));
 }
 
-TEST_F(AesGcmKeyManagerTest, testKeyMessageErrors) {
-  AesGcmKeyManager key_manager;
-
-  {  // Bad protobuffer.
-    AesEaxKey key;
-    auto result = key_manager.GetPrimitive(key);
-    EXPECT_FALSE(result.ok());
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "AesEaxKey",
-                        result.status().error_message());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported",
-                        result.status().error_message());
-  }
+TEST(AesGcmKeyManagerTest, InvalidKeySizes17Bytes) {
+  AesGcmKey key;
+  key.set_version(0);
+  key.set_key_value("0123456789abcdefg");
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(key),
+              StatusIs(util::error::INVALID_ARGUMENT));
+}
 
-  {  // Bad key_value size (supported sizes: 16, 32).
-    for (int len = 0; len < 42; len++) {
-      AesGcmKey key;
-      key.set_version(0);
-      key.set_key_value(std::string(len, 'a'));
-      auto result = key_manager.GetPrimitive(key);
-      if (len == 16 || len == 32) {
-        EXPECT_TRUE(result.ok()) << result.status();
-      } else {
-          EXPECT_FALSE(result.ok());
-          EXPECT_EQ(util::error::INVALID_ARGUMENT,
-                    result.status().error_code());
-          EXPECT_PRED_FORMAT2(testing::IsSubstring,
-                              std::to_string(len) + " bytes",
-                              result.status().error_message());
-          EXPECT_PRED_FORMAT2(testing::IsSubstring, "supported sizes",
-                              result.status().error_message());
-      }
-    }
-  }
+TEST(AesGcmKeyManagerTest, InvalidKeySizes24Bytes) {
+  AesGcmKey key;
+  key.set_version(0);
+  key.set_key_value("01234567890123");
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(key),
+              StatusIs(util::error::INVALID_ARGUMENT));
 }
 
-TEST_F(AesGcmKeyManagerTest, testPrimitives) {
-  std::string plaintext = "some plaintext";
-  std::string aad = "some aad";
-  AesGcmKeyManager key_manager;
+TEST(AesGcmKeyManagerTest, InvalidKeySizes31Bytes) {
   AesGcmKey key;
+  key.set_version(0);
+  key.set_key_value("0123456789012345678901234567890");
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(key),
+              StatusIs(util::error::INVALID_ARGUMENT));
+}
 
+TEST(AesGcmKeyManagerTest, InvalidKeySizes33Bytes) {
+  AesGcmKey key;
   key.set_version(0);
-  key.set_key_value("16 bytes of key ");
-
-  {  // Using key message only.
-    auto result = key_manager.GetPrimitive(key);
-    EXPECT_TRUE(result.ok()) << result.status();
-    auto aes_gcm = std::move(result.ValueOrDie());
-    auto encrypt_result = aes_gcm->Encrypt(plaintext, aad);
-    EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status();
-    auto decrypt_result = aes_gcm->Decrypt(encrypt_result.ValueOrDie(), aad);
-    EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status();
-    EXPECT_EQ(plaintext, decrypt_result.ValueOrDie());
-  }
+  key.set_key_value("012345678901234567890123456789012");
+  EXPECT_THAT(AesGcmKeyManager().ValidateKey(key),
+              StatusIs(util::error::INVALID_ARGUMENT));
+}
 
-  {  // Using KeyData proto.
-    KeyData key_data;
-    key_data.set_type_url(aes_gcm_key_type);
-    key_data.set_value(key.SerializeAsString());
-    auto result = key_manager.GetPrimitive(key_data);
-    EXPECT_TRUE(result.ok()) << result.status();
-    auto aes_gcm = std::move(result.ValueOrDie());
-    auto encrypt_result = aes_gcm->Encrypt(plaintext, aad);
-    EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status();
-    auto decrypt_result = aes_gcm->Decrypt(encrypt_result.ValueOrDie(), aad);
-    EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status();
-    EXPECT_EQ(plaintext, decrypt_result.ValueOrDie());
-  }
+TEST(AesGcmKeyManagerTest, ValidateKeyFormat) {
+  AesGcmKeyFormat format;
+
+  format.set_key_size(0);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format),
+              StatusIs(util::error::INVALID_ARGUMENT));
+
+  format.set_key_size(1);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format),
+              StatusIs(util::error::INVALID_ARGUMENT));
+
+  format.set_key_size(15);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format),
+              StatusIs(util::error::INVALID_ARGUMENT));
+
+  format.set_key_size(16);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), IsOk());
+
+  format.set_key_size(17);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format),
+              StatusIs(util::error::INVALID_ARGUMENT));
+
+  format.set_key_size(31);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format),
+              StatusIs(util::error::INVALID_ARGUMENT));
+
+  format.set_key_size(32);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format), IsOk());
+
+  format.set_key_size(33);
+  EXPECT_THAT(AesGcmKeyManager().ValidateKeyFormat(format),
+              StatusIs(util::error::INVALID_ARGUMENT));
 }
 
-TEST_F(AesGcmKeyManagerTest, testNewKeyErrors) {
-  AesGcmKeyManager key_manager;
-  const KeyFactory& key_factory = key_manager.get_key_factory();
-
-  {  // Bad key format.
-    AesEaxKeyFormat key_format;
-    auto result = key_factory.NewKey(key_format);
-    EXPECT_FALSE(result.ok());
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported",
-                        result.status().error_message());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "AesEaxKeyFormat",
-                        result.status().error_message());
-  }
+TEST(AesGcmKeyManagerTest, Create16ByteKey) {
+  AesGcmKeyFormat format;
+  format.set_key_size(16);
 
-  {  // Bad serialized key format.
-    auto result = key_factory.NewKey("some bad serialized proto");
-    EXPECT_FALSE(result.ok());
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "not parse",
-                        result.status().error_message());
-  }
+  StatusOr<AesGcmKey> key_or = AesGcmKeyManager().CreateKey(format);
 
-  {  // Bad AesGcmKeyFormat: small key_size.
-    AesGcmKeyFormat key_format;
-    key_format.set_key_size(8);
-    auto result = key_factory.NewKey(key_format);
-    EXPECT_FALSE(result.ok());
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "8 bytes",
-                        result.status().error_message());
-    EXPECT_PRED_FORMAT2(testing::IsSubstring, "supported sizes",
-                        result.status().error_message());
-  }
+  ASSERT_THAT(key_or.status(), IsOk());
+  EXPECT_THAT(key_or.ValueOrDie().key_value().size(), Eq(format.key_size()));
 }
 
-TEST_F(AesGcmKeyManagerTest, testNewKeyBasic) {
-  AesGcmKeyManager key_manager;
-  const KeyFactory& key_factory = key_manager.get_key_factory();
-  AesGcmKeyFormat key_format;
-  key_format.set_key_size(16);
-
-  { // Via NewKey(format_proto).
-    auto result = key_factory.NewKey(key_format);
-    EXPECT_TRUE(result.ok()) << result.status();
-    auto key = std::move(result.ValueOrDie());
-    EXPECT_EQ(key_type_prefix + key->GetTypeName(), aes_gcm_key_type);
-    std::unique_ptr<AesGcmKey> aes_gcm_key(
-        reinterpret_cast<AesGcmKey*>(key.release()));
-    EXPECT_EQ(0, aes_gcm_key->version());
-    EXPECT_EQ(key_format.key_size(), aes_gcm_key->key_value().size());
-  }
+TEST(AesGcmKeyManagerTest, Create32ByteKey) {
+  AesGcmKeyFormat format;
+  format.set_key_size(32);
 
-  { // Via NewKey(serialized_format_proto).
-    auto result = key_factory.NewKey(key_format.SerializeAsString());
-    EXPECT_TRUE(result.ok()) << result.status();
-    auto key = std::move(result.ValueOrDie());
-    EXPECT_EQ(key_type_prefix + key->GetTypeName(), aes_gcm_key_type);
-    std::unique_ptr<AesGcmKey> aes_gcm_key(
-        reinterpret_cast<AesGcmKey*>(key.release()));
-    EXPECT_EQ(0, aes_gcm_key->version());
-    EXPECT_EQ(key_format.key_size(), aes_gcm_key->key_value().size());
-  }
+  StatusOr<AesGcmKey> key_or = AesGcmKeyManager().CreateKey(format);
 
-  { // Via NewKeyData(serialized_format_proto).
-    auto result = key_factory.NewKeyData(key_format.SerializeAsString());
-    EXPECT_TRUE(result.ok()) << result.status();
-    auto key_data = std::move(result.ValueOrDie());
-    EXPECT_EQ(aes_gcm_key_type, key_data->type_url());
-    EXPECT_EQ(KeyData::SYMMETRIC, key_data->key_material_type());
-    AesGcmKey aes_gcm_key;
-    EXPECT_TRUE(aes_gcm_key.ParseFromString(key_data->value()));
-    EXPECT_EQ(0, aes_gcm_key.version());
-    EXPECT_EQ(key_format.key_size(), aes_gcm_key.key_value().size());
+  ASSERT_THAT(key_or.status(), IsOk());
+  EXPECT_THAT(key_or.ValueOrDie().key_value().size(), Eq(format.key_size()));
+}
+
+crypto::tink::util::Status EncryptThenDecrypt(Aead* encrypter, Aead* decrypter,
+                                              absl::string_view message,
+                                              absl::string_view aad) {
+  StatusOr<std::string> encryption_or = encrypter->Encrypt(message, aad);
+  if (!encryption_or.status().ok()) return encryption_or.status();
+  StatusOr<std::string> decryption_or =
+      decrypter->Decrypt(encryption_or.ValueOrDie(), aad);
+  if (!decryption_or.status().ok()) return decryption_or.status();
+  if (decryption_or.ValueOrDie() != message) {
+    return crypto::tink::util::Status(crypto::tink::util::error::INTERNAL,
+                                      "Message/Decryption mismatch");
   }
+  return util::OkStatus();
 }
 
+TEST(AesGcmKeyManagerTest, CreateAead) {
+  AesGcmKeyFormat format;
+  format.set_key_size(32);
+  StatusOr<AesGcmKey> key_or = AesGcmKeyManager().CreateKey(format);
+  ASSERT_THAT(key_or.status(), IsOk());
+
+  StatusOr<std::unique_ptr<Aead>> aead_or =
+      AesGcmKeyManager().GetPrimitive<Aead>(key_or.ValueOrDie());
+
+  ASSERT_THAT(aead_or.status(), IsOk());
+
+  StatusOr<std::unique_ptr<Aead>> boring_ssl_aead_or =
+      subtle::AesGcmBoringSsl::New(key_or.ValueOrDie().key_value());
+  ASSERT_THAT(boring_ssl_aead_or.status(), IsOk());
+
+  ASSERT_THAT(EncryptThenDecrypt(aead_or.ValueOrDie().get(),
+                                 boring_ssl_aead_or.ValueOrDie().get(),
+                                 "message", "aad"),
+              IsOk());
+}
+
+
 }  // namespace
 }  // namespace tink
 }  // namespace crypto
diff --git a/cc/core/keyset_handle_test.cc b/cc/core/keyset_handle_test.cc
index cad4f417e..0cde41647 100644
--- a/cc/core/keyset_handle_test.cc
+++ b/cc/core/keyset_handle_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
+#include "tink/core/key_manager_impl.h"
 #include "tink/keyset_handle.h"
 
 #include "gtest/gtest.h"
@@ -353,10 +354,10 @@ TEST_F(KeysetHandleTest, GetPublicKeysetHandleErrors) {
   { // A keyset with multiple keys.
     EcdsaSignKeyManager key_manager;
     const KeyFactory& key_factory = key_manager.get_key_factory();
-    AesGcmKeyManager aead_key_manager;
-    const KeyFactory& aead_key_factory = aead_key_manager.get_key_factory();
     Keyset keyset;
 
+    google::crypto::tink::AesGcmKeyFormat aead_key_format;
+    aead_key_format.set_key_size(16);
     AddTinkKey(EcdsaSignKeyManager::static_key_type(),
                /* key_id= */ 623628,
                *(key_factory.NewKey(
@@ -364,14 +365,12 @@ TEST_F(KeysetHandleTest, GetPublicKeysetHandleErrors) {
                KeyStatusType::ENABLED,
                KeyData::ASYMMETRIC_PRIVATE,
                &keyset);
-    AddLegacyKey(
-        AesGcmKeyManager::static_key_type(),
-        /* key_id= */ 42,
-        *(aead_key_factory.NewKey(AeadKeyTemplates::Aes128Gcm().value())
-              .ValueOrDie()),
-        KeyStatusType::ENABLED,
-        KeyData::ASYMMETRIC_PRIVATE,  // Intentionally wrong setting.
-        &keyset);
+    AddLegacyKey(AesGcmKeyManager().get_key_type(),
+                 /* key_id= */ 42,
+                 AesGcmKeyManager().CreateKey(aead_key_format).ValueOrDie(),
+                 KeyStatusType::ENABLED,
+                 KeyData::ASYMMETRIC_PRIVATE,  // Intentionally wrong setting.
+                 &keyset);
     keyset.set_primary_key_id(42);
     auto handle = TestKeysetHandle::GetKeysetHandle(keyset);
     auto public_handle_result = handle->GetPublicKeysetHandle();
@@ -445,9 +444,11 @@ TEST_F(KeysetHandleTest, GetPrimitiveCustomKeyManager) {
           .ok());
   // Without custom key manager it now fails.
   ASSERT_FALSE(handle->GetPrimitive<Aead>().ok());
-  AesGcmKeyManager key_manager;
+  AesGcmKeyManager key_type_manager;
+  std::unique_ptr<KeyManager<Aead>> key_manager =
+      crypto::tink::internal::MakeKeyManager<Aead>(&key_type_manager);
   // With custom key manager it works ok.
-  ASSERT_TRUE(handle->GetPrimitive<Aead>(&key_manager).ok());
+  ASSERT_TRUE(handle->GetPrimitive<Aead>(key_manager.get()).ok());
 }
 
 // Compile time check: ensures that the KeysetHandle can be copied.
diff --git a/cc/core/keyset_manager_test.cc b/cc/core/keyset_manager_test.cc
index a09612571..3c99bbf41 100644
--- a/cc/core/keyset_manager_test.cc
+++ b/cc/core/keyset_manager_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ TEST_F(KeysetManagerTest, testBasicOperations) {
   AesGcmKeyFormat key_format;
   key_format.set_key_size(16);
   KeyTemplate key_template;
-  key_template.set_type_url(AesGcmKeyManager::static_key_type());
+  key_template.set_type_url(AesGcmKeyManager().get_key_type());
   key_template.set_output_prefix_type(OutputPrefixType::TINK);
   key_template.set_value(key_format.SerializeAsString());
 
@@ -66,7 +66,7 @@ TEST_F(KeysetManagerTest, testBasicOperations) {
   EXPECT_EQ(key_id_0, keyset.primary_key_id());
   EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(0).status());
   EXPECT_EQ(OutputPrefixType::TINK, keyset.key(0).output_prefix_type());
-  EXPECT_EQ(AesGcmKeyManager::static_key_type(),
+  EXPECT_EQ(AesGcmKeyManager().get_key_type(),
             keyset.key(0).key_data().type_url());
   EXPECT_EQ(KeyData::SYMMETRIC, keyset.key(0).key_data().key_material_type());
 
@@ -83,7 +83,7 @@ TEST_F(KeysetManagerTest, testBasicOperations) {
                keyset.key(1).key_data().value());
   EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(1).status());
   EXPECT_EQ(OutputPrefixType::RAW, keyset.key(1).output_prefix_type());
-  EXPECT_EQ(AesGcmKeyManager::static_key_type(),
+  EXPECT_EQ(AesGcmKeyManager().get_key_type(),
             keyset.key(1).key_data().type_url());
   EXPECT_EQ(KeyData::SYMMETRIC, keyset.key(1).key_data().key_material_type());
 
@@ -102,7 +102,7 @@ TEST_F(KeysetManagerTest, testBasicOperations) {
                keyset.key(2).key_data().value());
   EXPECT_EQ(KeyStatusType::ENABLED, keyset.key(2).status());
   EXPECT_EQ(OutputPrefixType::LEGACY, keyset.key(2).output_prefix_type());
-  EXPECT_EQ(AesGcmKeyManager::static_key_type(),
+  EXPECT_EQ(AesGcmKeyManager().get_key_type(),
             keyset.key(2).key_data().type_url());
   EXPECT_EQ(KeyData::SYMMETRIC, keyset.key(2).key_data().key_material_type());
 
diff --git a/cc/core/registry_test.cc b/cc/core/registry_test.cc
index 97cf6bbde..451c37a6e 100644
--- a/cc/core/registry_test.cc
+++ b/cc/core/registry_test.cc
@@ -27,6 +27,7 @@
 #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"
@@ -307,7 +308,7 @@ TEST_F(RegistryTest, testBasic) {
 }
 
 TEST_F(RegistryTest, testRegisterKeyManager) {
-  std::string key_type_1 = AesGcmKeyManager::static_key_type();
+  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);
@@ -325,8 +326,9 @@ TEST_F(RegistryTest, testRegisterKeyManager) {
   EXPECT_TRUE(status.ok()) << status;
 
   // Try overriding a key manager.
-  status =
-      Registry::RegisterKeyManager(absl::make_unique<AesGcmKeyManager>(), true);
+  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;
 
@@ -518,8 +520,9 @@ TEST_F(RegistryTest, testGetPublicKeyData) {
   auto status = Registry::RegisterKeyManager(
       absl::make_unique<EciesAeadHkdfPrivateKeyManager>(), true);
   ASSERT_TRUE(status.ok()) << status;
-  status =
-      Registry::RegisterKeyManager(absl::make_unique<AesGcmKeyManager>(), true);
+  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.
@@ -541,7 +544,7 @@ TEST_F(RegistryTest, testGetPublicKeyData) {
 
   // Try with a wrong key type.
   auto wrong_key_type_result = Registry::GetPublicKeyData(
-      AesGcmKeyManager::static_key_type(), ecies_key.SerializeAsString());
+      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());
@@ -683,8 +686,10 @@ TEST_F(RegistryTest, UsualWrappingTest) {
 // 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(absl::make_unique<AesGcmKeyManager>(), true)
+      Registry::RegisterKeyManager(
+          crypto::tink::internal::MakeKeyManager<Aead>(&key_type_manager), true)
           .ok());
   auto result =
       Registry::get_key_manager<int>(AesGcmKeyManager().get_key_type());
diff --git a/cc/hybrid/ecies_aead_hkdf_hybrid_decrypt_test.cc b/cc/hybrid/ecies_aead_hkdf_hybrid_decrypt_test.cc
index cb57199f8..2b232688a 100644
--- a/cc/hybrid/ecies_aead_hkdf_hybrid_decrypt_test.cc
+++ b/cc/hybrid/ecies_aead_hkdf_hybrid_decrypt_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -124,9 +124,10 @@ TEST_F(EciesAeadHkdfHybridDecryptTest, testBasic) {
                       bad_result.status().error_message());
 
   // Register DEM key manager.
-  auto key_manager = absl::make_unique<AesGcmKeyManager>();
-  std::string dem_key_type = key_manager->get_key_type();
-  ASSERT_TRUE(Registry::RegisterKeyManager(std::move(key_manager), true).ok());
+  std::string dem_key_type = AesGcmKeyManager().get_key_type();
+  ASSERT_TRUE(Registry::RegisterKeyTypeManager(
+                  absl::make_unique<AesGcmKeyManager>(), true)
+                  .ok());
 
   // Generate and test many keys with various parameters.
   std::string context_info = "some context info";
diff --git a/cc/hybrid/ecies_aead_hkdf_hybrid_encrypt_test.cc b/cc/hybrid/ecies_aead_hkdf_hybrid_encrypt_test.cc
index 12f5bad5c..3c8fb749b 100644
--- a/cc/hybrid/ecies_aead_hkdf_hybrid_encrypt_test.cc
+++ b/cc/hybrid/ecies_aead_hkdf_hybrid_encrypt_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -118,9 +118,10 @@ TEST_F(EciesAeadHkdfHybridEncryptTest, testBasic) {
                       bad_result.status().error_message());
 
   // Register DEM key manager.
-  auto key_manager = absl::make_unique<AesGcmKeyManager>();
-  std::string dem_key_type = key_manager->get_key_type();
-  ASSERT_TRUE(Registry::RegisterKeyManager(std::move(key_manager), true).ok());
+  ASSERT_TRUE(Registry::RegisterKeyTypeManager(
+                  absl::make_unique<AesGcmKeyManager>(), true)
+                  .ok());
+  std::string dem_key_type = AesGcmKeyManager().get_key_type();
 
   // Generate and test many keys with various parameters.
   std::string plaintext = "some plaintext";
diff --git a/cc/hybrid/ecies_aead_hkdf_private_key_manager_test.cc b/cc/hybrid/ecies_aead_hkdf_private_key_manager_test.cc
index 0b9df0531..5b93760e5 100644
--- a/cc/hybrid/ecies_aead_hkdf_private_key_manager_test.cc
+++ b/cc/hybrid/ecies_aead_hkdf_private_key_manager_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ namespace {
 class EciesAeadHkdfPrivateKeyManagerTest : public ::testing::Test {
  protected:
   static void SetUpTestSuite() {
-    ASSERT_TRUE(Registry::RegisterKeyManager(
+    ASSERT_TRUE(Registry::RegisterKeyTypeManager(
                     absl::make_unique<AesGcmKeyManager>(), true)
                     .ok());
     ASSERT_TRUE(Registry::RegisterKeyManager(
diff --git a/cc/hybrid/ecies_aead_hkdf_public_key_manager_test.cc b/cc/hybrid/ecies_aead_hkdf_public_key_manager_test.cc
index 104a09276..fce2be31b 100644
--- a/cc/hybrid/ecies_aead_hkdf_public_key_manager_test.cc
+++ b/cc/hybrid/ecies_aead_hkdf_public_key_manager_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ namespace {
 class EciesAeadHkdfPublicKeyManagerTest : public ::testing::Test {
  protected:
   static void SetUpTestSuite() {
-    ASSERT_TRUE(Registry::RegisterKeyManager(
+    ASSERT_TRUE(Registry::RegisterKeyTypeManager(
                     absl::make_unique<AesGcmKeyManager>(), true)
                     .ok());
   }
diff --git a/cc/signature/ecdsa_sign_key_manager_test.cc b/cc/signature/ecdsa_sign_key_manager_test.cc
index ffe8236e2..dcb8cb126 100644
--- a/cc/signature/ecdsa_sign_key_manager_test.cc
+++ b/cc/signature/ecdsa_sign_key_manager_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -288,17 +288,8 @@ TEST_F(EcdsaSignKeyManagerTest, testPublicKeyExtractionErrors) {
       &(key_manager.get_key_factory()));
   ASSERT_NE(private_key_factory, nullptr);
 
-  AesGcmKeyManager aead_key_manager;
-  auto aead_private_key_factory = dynamic_cast<const PrivateKeyFactory*>(
-      &(aead_key_manager.get_key_factory()));
-  ASSERT_EQ(nullptr, aead_private_key_factory);
-
-  auto aead_key_result = aead_key_manager.get_key_factory().NewKey(
-      AeadKeyTemplates::Aes128Gcm().value());
-  ASSERT_TRUE(aead_key_result.ok()) << aead_key_result.status();
-  auto aead_key = std::move(aead_key_result.ValueOrDie());
   auto public_key_data_result = private_key_factory->GetPublicKeyData(
-      aead_key->SerializeAsString());
+      google::crypto::tink::AesGcmKey().SerializeAsString());
   EXPECT_FALSE(public_key_data_result.ok());
   EXPECT_EQ(util::error::INVALID_ARGUMENT,
             public_key_data_result.status().error_code());
diff --git a/cc/signature/ed25519_sign_key_manager_test.cc b/cc/signature/ed25519_sign_key_manager_test.cc
index 602a7000b..5c1ccf6c1 100644
--- a/cc/signature/ed25519_sign_key_manager_test.cc
+++ b/cc/signature/ed25519_sign_key_manager_test.cc
@@ -168,17 +168,8 @@ TEST_F(Ed25519SignKeyManagerTest, testPublicKeyExtractionErrors) {
       dynamic_cast<const PrivateKeyFactory*>(&(key_manager.get_key_factory()));
   ASSERT_NE(private_key_factory, nullptr);
 
-  AesGcmKeyManager aead_key_manager;
-  auto aead_private_key_factory = dynamic_cast<const PrivateKeyFactory*>(
-      &(aead_key_manager.get_key_factory()));
-  ASSERT_EQ(nullptr, aead_private_key_factory);
-
-  auto aead_key_result = aead_key_manager.get_key_factory().NewKey(
-      AeadKeyTemplates::Aes128Gcm().value());
-  ASSERT_TRUE(aead_key_result.ok()) << aead_key_result.status();
-  auto aead_key = std::move(aead_key_result.ValueOrDie());
-  auto public_key_data_result =
-      private_key_factory->GetPublicKeyData(aead_key->SerializeAsString());
+  auto public_key_data_result = private_key_factory->GetPublicKeyData(
+      google::crypto::tink::AesGcmKey().SerializeAsString());
   EXPECT_FALSE(public_key_data_result.ok());
   EXPECT_EQ(util::error::INVALID_ARGUMENT,
             public_key_data_result.status().error_code());
diff --git a/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc b/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc
index 0277e809a..f8ae4dc39 100644
--- a/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc
+++ b/cc/signature/rsa_ssa_pkcs1_sign_key_manager_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 Google Inc.
+// Copyright 2018 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -332,17 +332,8 @@ TEST_F(RsaSsaPkcs1SignKeyManagerTest, PublicKeyExtractionErrors) {
       dynamic_cast<const PrivateKeyFactory*>(&(key_manager.get_key_factory()));
   ASSERT_NE(private_key_factory, nullptr);
 
-  AesGcmKeyManager aead_key_manager;
-  auto aead_private_key_factory = dynamic_cast<const PrivateKeyFactory*>(
-      &(aead_key_manager.get_key_factory()));
-  ASSERT_EQ(nullptr, aead_private_key_factory);
-
-  auto aead_key_result = aead_key_manager.get_key_factory().NewKey(
-      AeadKeyTemplates::Aes128Gcm().value());
-  ASSERT_TRUE(aead_key_result.ok()) << aead_key_result.status();
-  auto aead_key = std::move(aead_key_result.ValueOrDie());
-  auto public_key_data_result =
-      private_key_factory->GetPublicKeyData(aead_key->SerializeAsString());
+  auto public_key_data_result = private_key_factory->GetPublicKeyData(
+      google::crypto::tink::AesGcmKey().SerializeAsString());
   EXPECT_FALSE(public_key_data_result.ok());
   EXPECT_EQ(util::error::INVALID_ARGUMENT,
             public_key_data_result.status().error_code());
diff --git a/cc/signature/rsa_ssa_pss_sign_key_manager_test.cc b/cc/signature/rsa_ssa_pss_sign_key_manager_test.cc
index 210aff095..adf25cf6a 100644
--- a/cc/signature/rsa_ssa_pss_sign_key_manager_test.cc
+++ b/cc/signature/rsa_ssa_pss_sign_key_manager_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 Google Inc.
+// Copyright 2018 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -360,17 +360,8 @@ TEST_F(RsaSsaPssSignKeyManagerTest, PublicKeyExtractionErrors) {
       dynamic_cast<const PrivateKeyFactory*>(&(key_manager.get_key_factory()));
   ASSERT_NE(private_key_factory, nullptr);
 
-  AesGcmKeyManager aead_key_manager;
-  auto aead_private_key_factory = dynamic_cast<const PrivateKeyFactory*>(
-      &(aead_key_manager.get_key_factory()));
-  ASSERT_EQ(nullptr, aead_private_key_factory);
-
-  auto aead_key_result = aead_key_manager.get_key_factory().NewKey(
-      AeadKeyTemplates::Aes128Gcm().value());
-  ASSERT_TRUE(aead_key_result.ok()) << aead_key_result.status();
-  auto aead_key = std::move(aead_key_result.ValueOrDie());
-  auto public_key_data_result =
-      private_key_factory->GetPublicKeyData(aead_key->SerializeAsString());
+  auto public_key_data_result = private_key_factory->GetPublicKeyData(
+      google::crypto::tink::AesGcmKey().SerializeAsString());
   EXPECT_FALSE(public_key_data_result.ok());
   EXPECT_EQ(util::error::INVALID_ARGUMENT,
             public_key_data_result.status().error_code());
diff --git a/objc/Tests/UnitTests/aead/TINKAeadFactoryTest.mm b/objc/Tests/UnitTests/aead/TINKAeadFactoryTest.mm
index 5bf093b52..3e2a6d77f 100644
--- a/objc/Tests/UnitTests/aead/TINKAeadFactoryTest.mm
+++ b/objc/Tests/UnitTests/aead/TINKAeadFactoryTest.mm
@@ -43,6 +43,7 @@ using crypto::tink::KeyFactory;
 using crypto::tink::TestKeysetHandle;
 using crypto::tink::test::AddRawKey;
 using crypto::tink::test::AddTinkKey;
+using google::crypto::tink::AesGcmKey;
 using google::crypto::tink::AesGcmKeyFormat;
 using google::crypto::tink::KeyData;
 using google::crypto::tink::Keyset;
@@ -69,9 +70,7 @@ using google::crypto::tink::KeyStatusType;
 
 - (void)testPrimitive {
   // Prepare a template for generating keys for a Keyset.
-  AesGcmKeyManager key_manager;
-  const KeyFactory &key_factory = key_manager.get_key_factory();
-  std::string key_type = key_manager.get_key_type();
+  std::string key_type = AesGcmKeyManager().get_key_type();
 
   AesGcmKeyFormat key_format;
   key_format.set_key_size(16);
@@ -79,16 +78,16 @@ using google::crypto::tink::KeyStatusType;
   // Prepare a Keyset.
   Keyset keyset;
   uint32_t key_id_1 = 1234543;
-  auto new_key = std::move(key_factory.NewKey(key_format).ValueOrDie());
-  AddTinkKey(key_type, key_id_1, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset);
+  AesGcmKey new_key = AesGcmKeyManager().CreateKey(key_format).ValueOrDie();
+  AddTinkKey(key_type, key_id_1, new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset);
 
   uint32_t key_id_2 = 726329;
-  new_key = std::move(key_factory.NewKey(key_format).ValueOrDie());
-  AddRawKey(key_type, key_id_2, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset);
+  new_key = AesGcmKeyManager().CreateKey(key_format).ValueOrDie();
+  AddRawKey(key_type, key_id_2, new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset);
 
   uint32_t key_id_3 = 7213743;
-  new_key = std::move(key_factory.NewKey(key_format).ValueOrDie());
-  AddTinkKey(key_type, key_id_3, *new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset);
+  new_key = AesGcmKeyManager().CreateKey(key_format).ValueOrDie();
+  AddTinkKey(key_type, key_id_3, new_key, KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset);
 
   keyset.set_primary_key_id(key_id_3);
 
@@ -117,7 +116,10 @@ using google::crypto::tink::KeyStatusType;
   XCTAssertTrue([plaintext isEqual:decrypted]);
 
   // Create raw ciphertext with 2nd key, and decrypt with Aead-instance.
-  auto raw_aead = std::move(key_manager.GetPrimitive(keyset.key(1).key_data()).ValueOrDie());
+  AesGcmKey raw_key;
+  XCTAssertTrue(raw_key.ParseFromString(keyset.key(1).key_data().value()));
+  auto raw_aead =
+      std::move(AesGcmKeyManager().GetPrimitive<crypto::tink::Aead>(raw_key).ValueOrDie());
   std::string raw_ciphertext =
       raw_aead->Encrypt(absl::string_view("some_plaintext"), absl::string_view("some_aad"))
           .ValueOrDie();
-- 
GitLab