diff --git a/cc/aead/BUILD.bazel b/cc/aead/BUILD.bazel
index fbde5a037a735269490e0e60436c9918a52e1a2c..17ec7b639dd02c35d0663bac25717292bb2440b7 100644
--- a/cc/aead/BUILD.bazel
+++ b/cc/aead/BUILD.bazel
@@ -86,25 +86,22 @@ cc_library(
 
 cc_library(
     name = "aes_eax_key_manager",
-    srcs = ["aes_eax_key_manager.cc"],
     hdrs = ["aes_eax_key_manager.h"],
     include_prefix = "tink",
     strip_include_prefix = "/cc",
     deps = [
         "//cc:aead",
-        "//cc:key_manager",
-        "//cc:key_manager_base",
+        "//cc:core/key_type_manager",
         "//cc/subtle:aes_eax_boringssl",
         "//cc/subtle:random",
+        "//cc/util:constants",
         "//cc/util:errors",
         "//cc/util:protobuf_helper",
         "//cc/util:status",
         "//cc/util:statusor",
         "//cc/util:validation",
         "//proto:aes_eax_cc_proto",
-        "//proto:common_cc_proto",
-        "//proto:tink_cc_proto",
-        "@com_google_absl//absl/base",
+        "@com_google_absl//absl/strings",
     ],
 )
 
@@ -367,6 +364,7 @@ cc_test(
     deps = [
         ":aes_eax_key_manager",
         "//cc:aead",
+        "//cc:core/key_manager_impl",
         "//cc/util:status",
         "//cc/util:statusor",
         "//proto:aes_eax_cc_proto",
@@ -385,9 +383,9 @@ cc_test(
     deps = [
         ":aes_gcm_key_manager",
         "//cc:aead",
+        "//cc/subtle:aead_test_util",
         "//cc/util:status",
         "//cc/util:statusor",
-        "//cc/subtle:aead_test_util",
         "//cc/util:test_matchers",
         "//proto:aes_eax_cc_proto",
         "//proto:aes_gcm_cc_proto",
diff --git a/cc/aead/CMakeLists.txt b/cc/aead/CMakeLists.txt
index 42bf336f4aadfb50cf52194a4965c77cce600176..f42ef49800ea767d89809e56dec76d9329483ed7 100644
--- a/cc/aead/CMakeLists.txt
+++ b/cc/aead/CMakeLists.txt
@@ -75,23 +75,20 @@ tink_cc_library(
 tink_cc_library(
   NAME aes_eax_key_manager
   SRCS
-    aes_eax_key_manager.cc
     aes_eax_key_manager.h
   DEPS
     tink::core::aead
-    tink::core::key_manager
-    tink::core::key_manager_base
+    tink::core::key_type_manager
     tink::subtle::aes_eax_boringssl
     tink::subtle::random
+    tink::util::constants
     tink::util::errors
     tink::util::protobuf_helper
     tink::util::status
     tink::util::statusor
     tink::util::validation
     tink::proto::aes_eax_cc_proto
-    tink::proto::common_cc_proto
-    tink::proto::tink_cc_proto
-    absl::base
+    absl::strings
 )
 
 tink_cc_library(
@@ -321,6 +318,7 @@ tink_cc_test(
   DEPS
     tink::aead::aes_eax_key_manager
     tink::core::aead
+    tink::core::key_manager_impl
     tink::util::status
     tink::util::statusor
     tink::proto::aes_eax_cc_proto
diff --git a/cc/aead/aead_config.cc b/cc/aead/aead_config.cc
index 2369ca6bacea91bb3479495b22ff819f18a54f5e..836a223134acfbd5c9950583ccaa287fc1bf4a45 100644
--- a/cc/aead/aead_config.cc
+++ b/cc/aead/aead_config.cc
@@ -57,7 +57,7 @@ util::Status AeadConfig::Register() {
   status = Registry::RegisterKeyManager(
       absl::make_unique<AesGcmSivKeyManager>(), true);
   if (!status.ok()) return status;
-  status = Registry::RegisterKeyManager(
+  status = Registry::RegisterKeyTypeManager(
       absl::make_unique<AesEaxKeyManager>(), true);
   if (!status.ok()) return status;
   status = Registry::RegisterKeyManager(
diff --git a/cc/aead/aead_key_templates_test.cc b/cc/aead/aead_key_templates_test.cc
index ca16ebba066deff22dbd95265ec66401969cbff1..6220208bc7c9d63da401188ec84d4f89326ac822 100644
--- a/cc/aead/aead_key_templates_test.cc
+++ b/cc/aead/aead_key_templates_test.cc
@@ -23,6 +23,7 @@
 #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/core/key_manager_impl.h"
 #include "tink/util/test_matchers.h"
 #include "proto/aes_ctr_hmac_aead.pb.h"
 #include "proto/aes_eax.pb.h"
@@ -66,10 +67,11 @@ TEST(AeadKeyTemplatesTest, testAesEaxKeyTemplates) {
     EXPECT_EQ(&key_template, &key_template_2);
 
     // Check that the template works with the key manager.
-    AesEaxKeyManager key_manager;
-    EXPECT_EQ(key_manager.get_key_type(), key_template.type_url());
+    AesEaxKeyManager key_type_manager;
+    auto key_manager = internal::MakeKeyManager<Aead>(&key_type_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());
+        key_manager->get_key_factory().NewKey(key_template.value());
     EXPECT_TRUE(new_key_result.ok()) << new_key_result.status();
   }
 
@@ -88,10 +90,11 @@ TEST(AeadKeyTemplatesTest, testAesEaxKeyTemplates) {
     EXPECT_EQ(&key_template, &key_template_2);
 
     // Check that the template works with the key manager.
-    AesEaxKeyManager key_manager;
-    EXPECT_EQ(key_manager.get_key_type(), key_template.type_url());
+    AesEaxKeyManager key_type_manager;
+    auto key_manager = internal::MakeKeyManager<Aead>(&key_type_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());
+        key_manager->get_key_factory().NewKey(key_template.value());
     EXPECT_TRUE(new_key_result.ok()) << new_key_result.status();
   }
 }
diff --git a/cc/aead/aes_eax_key_manager.cc b/cc/aead/aes_eax_key_manager.cc
deleted file mode 100644
index 210455f0523939b26b46c8f4fff2e16df050dc5f..0000000000000000000000000000000000000000
--- a/cc/aead/aes_eax_key_manager.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// 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_eax_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_eax_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_eax.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::AesEaxKey;
-using google::crypto::tink::AesEaxKeyFormat;
-using google::crypto::tink::KeyData;
-
-class AesEaxKeyFactory : public KeyFactoryBase<AesEaxKey, AesEaxKeyFormat> {
- public:
-  AesEaxKeyFactory() {}
-
-  KeyData::KeyMaterialType key_material_type() const override {
-    return KeyData::SYMMETRIC;
-  }
-
- protected:
-  StatusOr<std::unique_ptr<AesEaxKey>> NewKeyFromFormat(
-      const AesEaxKeyFormat& aes_eax_key_format) const override {
-    Status status = AesEaxKeyManager::Validate(aes_eax_key_format);
-    if (!status.ok()) return status;
-
-    auto aes_eax_key = absl::make_unique<AesEaxKey>();
-    aes_eax_key->set_version(AesEaxKeyManager::kVersion);
-    aes_eax_key->set_key_value(
-        subtle::Random::GetRandomBytes(aes_eax_key_format.key_size()));
-    aes_eax_key->mutable_params()->set_iv_size(
-        aes_eax_key_format.params().iv_size());
-    return absl::implicit_cast<StatusOr<std::unique_ptr<AesEaxKey>>>(
-        std::move(aes_eax_key));
-  }
-};
-
-constexpr uint32_t AesEaxKeyManager::kVersion;
-
-AesEaxKeyManager::AesEaxKeyManager()
-    : key_factory_(absl::make_unique<AesEaxKeyFactory>()) {}
-
-uint32_t AesEaxKeyManager::get_version() const {
-  return kVersion;
-}
-
-const KeyFactory& AesEaxKeyManager::get_key_factory() const {
-  return *key_factory_;
-}
-
-StatusOr<std::unique_ptr<Aead>> AesEaxKeyManager::GetPrimitiveFromKey(
-    const AesEaxKey& aes_eax_key) const {
-  Status status = Validate(aes_eax_key);
-  if (!status.ok()) return status;
-  auto aes_eax_result = subtle::AesEaxBoringSsl::New(
-      aes_eax_key.key_value(), aes_eax_key.params().iv_size());
-  if (!aes_eax_result.ok()) return aes_eax_result.status();
-  return std::move(aes_eax_result.ValueOrDie());
-}
-
-// static
-Status AesEaxKeyManager::Validate(const AesEaxKey& key) {
-  Status status = ValidateVersion(key.version(), kVersion);
-  if (!status.ok()) return status;
-  uint32_t key_size = key.key_value().size();
-  if (key_size != 16 && key_size != 32) {
-      return ToStatusF(util::error::INVALID_ARGUMENT,
-                       "Invalid AesEaxKey: key_value has %d bytes; "
-                       "supported sizes: 16 or 32 bytes.", key_size);
-  }
-  uint32_t iv_size = key.params().iv_size();
-  if (iv_size != 12 && iv_size != 16) {
-      return ToStatusF(util::error::INVALID_ARGUMENT,
-                       "Invalid AesEaxKey: iv_size is %d bytes; "
-                       "supported sizes: 12 or 16 bytes.", iv_size);
-  }
-  return Status::OK;
-}
-
-// static
-Status AesEaxKeyManager::Validate(const AesEaxKeyFormat& key_format) {
-  uint32_t key_size = key_format.key_size();
-  if (key_size != 16 && key_size != 32) {
-      return ToStatusF(util::error::INVALID_ARGUMENT,
-                       "Invalid AesEaxKeyFormat: key_size is %d bytes; "
-                       "supported sizes: 16 or 32 bytes.", key_size);
-  }
-  uint32_t iv_size = key_format.params().iv_size();
-  if (iv_size != 12 && iv_size != 16) {
-      return ToStatusF(util::error::INVALID_ARGUMENT,
-                       "Invalid AesEaxKeyFormat: iv_size is %d bytes; "
-                       "supported sizes: 12 or 16 bytes.", iv_size);
-  }
-  return Status::OK;
-}
-
-}  // namespace tink
-}  // namespace crypto
diff --git a/cc/aead/aes_eax_key_manager.h b/cc/aead/aes_eax_key_manager.h
index 0d442a78c82da1eb958d38c63e5ce850a4b8bd18..dbbf8b3a034af801b1d15b948281156217661c0e 100644
--- a/cc/aead/aes_eax_key_manager.h
+++ b/cc/aead/aes_eax_key_manager.h
@@ -19,47 +19,94 @@
 
 #include "absl/strings/string_view.h"
 #include "tink/aead.h"
-#include "tink/core/key_manager_base.h"
-#include "tink/key_manager.h"
+#include "tink/core/key_type_manager.h"
+#include "tink/subtle/aes_eax_boringssl.h"
+#include "tink/subtle/random.h"
+#include "tink/util/constants.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_eax.pb.h"
-#include "proto/tink.pb.h"
 
 namespace crypto {
 namespace tink {
 
 class AesEaxKeyManager
-    : public KeyManagerBase<Aead, google::crypto::tink::AesEaxKey> {
+    : public KeyTypeManager<google::crypto::tink::AesEaxKey,
+                            google::crypto::tink::AesEaxKeyFormat, 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::AesEaxKey& key) const override {
+      return subtle::AesEaxBoringSsl::New(key.key_value(),
+                                          key.params().iv_size());
+    }
+  };
 
-  AesEaxKeyManager();
+  AesEaxKeyManager() : KeyTypeManager(absl::make_unique<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 ~AesEaxKeyManager() {}
+  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::AesEaxKey& aes_eax_key) const override;
+  crypto::tink::util::Status ValidateKey(
+      const google::crypto::tink::AesEaxKey& key) const override {
+    crypto::tink::util::Status status =
+        ValidateVersion(key.version(), get_version());
+    if (!status.ok()) return status;
+    status = ValidateKeySize(key.key_value().size());
+    if (!status.ok()) return status;
+    return ValidateIvSize(key.params().iv_size());
+  }
+
+  crypto::tink::util::Status ValidateKeyFormat(
+      const google::crypto::tink::AesEaxKeyFormat& key_format) const override {
+    crypto::tink::util::Status status = ValidateKeySize(key_format.key_size());
+    if (!status.ok()) return status;
+    return ValidateIvSize(key_format.params().iv_size());
+  }
+
+  crypto::tink::util::StatusOr<google::crypto::tink::AesEaxKey> CreateKey(
+      const google::crypto::tink::AesEaxKeyFormat& key_format) const override {
+    google::crypto::tink::AesEaxKey aes_eax_key;
+    aes_eax_key.set_version(get_version());
+    aes_eax_key.set_key_value(
+        subtle::Random::GetRandomBytes(key_format.key_size()));
+    aes_eax_key.mutable_params()->set_iv_size(
+        key_format.params().iv_size());
+    return aes_eax_key;
+  }
 
  private:
-  friend class AesEaxKeyFactory;
+  crypto::tink::util::Status ValidateKeySize(uint32_t key_size) const {
+    if (key_size != 16 && key_size != 32) {
+      return crypto::tink::util::Status(
+          util::error::INVALID_ARGUMENT,
+          absl::StrCat("Invalid key size: ", key_size,
+                       " bytes, expected 16 or 32 bytes."));
+    }
+    return crypto::tink::util::OkStatus();
+  }
 
-  std::unique_ptr<KeyFactory> key_factory_;
+  crypto::tink::util::Status ValidateIvSize(uint32_t iv_size) const {
+    if (iv_size != 12 && iv_size != 16) {
+      return crypto::tink::util::Status(
+          util::error::INVALID_ARGUMENT,
+          absl::StrCat("Invalid IV size: ", iv_size,
+                       " bytes, expected 12 or 16 bytes."));
+    }
+    return crypto::tink::util::OkStatus();
+  }
 
-  static crypto::tink::util::Status Validate(
-      const google::crypto::tink::AesEaxKey& key);
-  static crypto::tink::util::Status Validate(
-      const google::crypto::tink::AesEaxKeyFormat& key_format);
+  const std::string key_type_ = absl::StrCat(
+      kTypeGoogleapisCom, google::crypto::tink::AesEaxKey().GetTypeName());
 };
 
 }  // namespace tink
diff --git a/cc/aead/aes_eax_key_manager_test.cc b/cc/aead/aes_eax_key_manager_test.cc
index 28684fb7343314d46cf43871a74ef925efac7504..7878a1469c85a3c5e89b040e28c7e661f98a0629 100644
--- a/cc/aead/aes_eax_key_manager_test.cc
+++ b/cc/aead/aes_eax_key_manager_test.cc
@@ -14,12 +14,13 @@
 
 #include "tink/aead/aes_eax_key_manager.h"
 
+#include "gtest/gtest.h"
 #include "tink/aead.h"
+#include "tink/core/key_manager_impl.h"
 #include "tink/util/status.h"
 #include "tink/util/statusor.h"
-#include "gtest/gtest.h"
-#include "proto/aes_gcm.pb.h"
 #include "proto/aes_eax.pb.h"
+#include "proto/aes_gcm.pb.h"
 #include "proto/common.pb.h"
 #include "proto/tink.pb.h"
 
@@ -37,28 +38,28 @@ namespace {
 class AesEaxKeyManagerTest : public ::testing::Test {
  protected:
   std::string key_type_prefix = "type.googleapis.com/";
-  std::string aes_eax_key_type =
-      "type.googleapis.com/google.crypto.tink.AesEaxKey";
+  std::string aes_eax_key_type = "type.googleapis.com/google.crypto.tink.AesEaxKey";
 };
 
 TEST_F(AesEaxKeyManagerTest, testBasic) {
-  AesEaxKeyManager key_manager;
+  AesEaxKeyManager key_type_manager;
+  auto key_manager = internal::MakeKeyManager<Aead>(&key_type_manager);
 
-  EXPECT_EQ(0, key_manager.get_version());
+  EXPECT_EQ(0, key_manager->get_version());
   EXPECT_EQ("type.googleapis.com/google.crypto.tink.AesEaxKey",
-            key_manager.get_key_type());
-  EXPECT_TRUE(key_manager.DoesSupport(key_manager.get_key_type()));
+            key_manager->get_key_type());
+  EXPECT_TRUE(key_manager->DoesSupport(key_manager->get_key_type()));
 }
 
 TEST_F(AesEaxKeyManagerTest, testKeyDataErrors) {
-  AesEaxKeyManager key_manager;
+  AesEaxKeyManager key_type_manager;
+  auto key_manager = internal::MakeKeyManager<Aead>(&key_type_manager);
 
   {  // Bad key type.
     KeyData key_data;
-    std::string bad_key_type =
-        "type.googleapis.com/google.crypto.tink.SomeOtherKey";
+    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);
+    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",
@@ -71,7 +72,7 @@ TEST_F(AesEaxKeyManagerTest, testKeyDataErrors) {
     KeyData key_data;
     key_data.set_type_url(aes_eax_key_type);
     key_data.set_value("some bad serialized proto");
-    auto result = key_manager.GetPrimitive(key_data);
+    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",
@@ -84,7 +85,7 @@ TEST_F(AesEaxKeyManagerTest, testKeyDataErrors) {
     key.set_version(1);
     key_data.set_type_url(aes_eax_key_type);
     key_data.set_value(key.SerializeAsString());
-    auto result = key_manager.GetPrimitive(key_data);
+    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",
@@ -100,17 +101,16 @@ TEST_F(AesEaxKeyManagerTest, testKeyDataErrors) {
       KeyData key_data;
       key_data.set_type_url(aes_eax_key_type);
       key_data.set_value(key.SerializeAsString());
-      auto result = key_manager.GetPrimitive(key_data);
+      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_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",
+        EXPECT_PRED_FORMAT2(testing::IsSubstring, "Invalid key size",
                             result.status().error_message());
       }
     }
@@ -126,17 +126,16 @@ TEST_F(AesEaxKeyManagerTest, testKeyDataErrors) {
       KeyData key_data;
       key_data.set_type_url(aes_eax_key_type);
       key_data.set_value(key.SerializeAsString());
-      auto result = key_manager.GetPrimitive(key_data);
+      auto result = key_manager->GetPrimitive(key_data);
       if (iv_size == 12 || iv_size == 16) {
         EXPECT_TRUE(result.ok()) << result.status();
       } else {
         EXPECT_FALSE(result.ok());
-        EXPECT_EQ(util::error::INVALID_ARGUMENT,
-                  result.status().error_code());
+        EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
         EXPECT_PRED_FORMAT2(testing::IsSubstring,
                             std::to_string(iv_size) + " bytes",
                             result.status().error_message());
-        EXPECT_PRED_FORMAT2(testing::IsSubstring, "supported sizes",
+        EXPECT_PRED_FORMAT2(testing::IsSubstring, "Invalid IV size",
                             result.status().error_message());
       }
     }
@@ -144,11 +143,12 @@ TEST_F(AesEaxKeyManagerTest, testKeyDataErrors) {
 }
 
 TEST_F(AesEaxKeyManagerTest, testKeyMessageErrors) {
-  AesEaxKeyManager key_manager;
+  AesEaxKeyManager key_type_manager;
+  auto key_manager = internal::MakeKeyManager<Aead>(&key_type_manager);
 
   {  // Bad protobuffer.
     AesGcmKey key;
-    auto result = key_manager.GetPrimitive(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, "AesGcmKey",
@@ -163,17 +163,16 @@ TEST_F(AesEaxKeyManagerTest, testKeyMessageErrors) {
       key.set_version(0);
       key.set_key_value(std::string(len, 'a'));
       key.mutable_params()->set_iv_size(16);
-      auto result = key_manager.GetPrimitive(key);
+      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_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",
+        EXPECT_PRED_FORMAT2(testing::IsSubstring, "Invalid key size",
                             result.status().error_message());
       }
     }
@@ -186,17 +185,16 @@ TEST_F(AesEaxKeyManagerTest, testKeyMessageErrors) {
       key.set_version(0);
       key.set_key_value(std::string(key_size, 'a'));
       key.mutable_params()->set_iv_size(iv_size);
-      auto result = key_manager.GetPrimitive(key);
+      auto result = key_manager->GetPrimitive(key);
       if (iv_size == 12 || iv_size == 16) {
         EXPECT_TRUE(result.ok()) << result.status();
       } else {
         EXPECT_FALSE(result.ok());
-        EXPECT_EQ(util::error::INVALID_ARGUMENT,
-                  result.status().error_code());
+        EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
         EXPECT_PRED_FORMAT2(testing::IsSubstring,
                             std::to_string(iv_size) + " bytes",
                             result.status().error_message());
-        EXPECT_PRED_FORMAT2(testing::IsSubstring, "supported sizes",
+        EXPECT_PRED_FORMAT2(testing::IsSubstring, "Invalid IV size",
                             result.status().error_message());
       }
     }
@@ -206,7 +204,8 @@ TEST_F(AesEaxKeyManagerTest, testKeyMessageErrors) {
 TEST_F(AesEaxKeyManagerTest, testPrimitives) {
   std::string plaintext = "some plaintext";
   std::string aad = "some aad";
-  AesEaxKeyManager key_manager;
+  AesEaxKeyManager key_type_manager;
+  auto key_manager = internal::MakeKeyManager<Aead>(&key_type_manager);
   AesEaxKey key;
 
   key.set_version(0);
@@ -214,7 +213,7 @@ TEST_F(AesEaxKeyManagerTest, testPrimitives) {
   key.mutable_params()->set_iv_size(16);
 
   {  // Using key message only.
-    auto result = key_manager.GetPrimitive(key);
+    auto result = key_manager->GetPrimitive(key);
     EXPECT_TRUE(result.ok()) << result.status();
     auto aes_eax = std::move(result.ValueOrDie());
     auto encrypt_result = aes_eax->Encrypt(plaintext, aad);
@@ -228,7 +227,7 @@ TEST_F(AesEaxKeyManagerTest, testPrimitives) {
     KeyData key_data;
     key_data.set_type_url(aes_eax_key_type);
     key_data.set_value(key.SerializeAsString());
-    auto result = key_manager.GetPrimitive(key_data);
+    auto result = key_manager->GetPrimitive(key_data);
     EXPECT_TRUE(result.ok()) << result.status();
     auto aes_eax = std::move(result.ValueOrDie());
     auto encrypt_result = aes_eax->Encrypt(plaintext, aad);
@@ -240,8 +239,9 @@ TEST_F(AesEaxKeyManagerTest, testPrimitives) {
 }
 
 TEST_F(AesEaxKeyManagerTest, testNewKeyErrors) {
-  AesEaxKeyManager key_manager;
-  const KeyFactory& key_factory = key_manager.get_key_factory();
+  AesEaxKeyManager key_type_manager;
+  auto key_manager = internal::MakeKeyManager<Aead>(&key_type_manager);
+  const KeyFactory& key_factory = key_manager->get_key_factory();
 
   {  // Bad key format.
     AesGcmKeyFormat key_format;
@@ -268,19 +268,20 @@ TEST_F(AesEaxKeyManagerTest, testNewKeyErrors) {
     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, "key_size",
+    EXPECT_PRED_FORMAT2(testing::IsSubstring, "Invalid key size",
                         result.status().error_message());
   }
 }
 
 TEST_F(AesEaxKeyManagerTest, testNewKeyBasic) {
-  AesEaxKeyManager key_manager;
-  const KeyFactory& key_factory = key_manager.get_key_factory();
+  AesEaxKeyManager key_type_manager;
+  auto key_manager = internal::MakeKeyManager<Aead>(&key_type_manager);
+  const KeyFactory& key_factory = key_manager->get_key_factory();
   AesEaxKeyFormat key_format;
   key_format.set_key_size(16);
   key_format.mutable_params()->set_iv_size(12);
 
-  { // Via NewKey(format_proto).
+  {  // Via NewKey(format_proto).
     auto result = key_factory.NewKey(key_format);
     EXPECT_TRUE(result.ok()) << result.status();
     auto key = std::move(result.ValueOrDie());
@@ -292,7 +293,7 @@ TEST_F(AesEaxKeyManagerTest, testNewKeyBasic) {
     EXPECT_EQ(key_format.params().iv_size(), aes_eax_key->params().iv_size());
   }
 
-  { // Via NewKey(serialized_format_proto).
+  {  // 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());
@@ -304,7 +305,7 @@ TEST_F(AesEaxKeyManagerTest, testNewKeyBasic) {
     EXPECT_EQ(key_format.params().iv_size(), aes_eax_key->params().iv_size());
   }
 
-  { // Via NewKeyData(serialized_format_proto).
+  {  // 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());
diff --git a/python/aead/aead_key_manager_test.py b/python/aead/aead_key_manager_test.py
index 6a1a9b481f59084dc8c64938c27b422dbeabd2d8..c7e43ccedbb899e952be75a3134124f87e0d64fd 100644
--- a/python/aead/aead_key_manager_test.py
+++ b/python/aead/aead_key_manager_test.py
@@ -93,7 +93,7 @@ class AeadKeyManagerTest(absltest.TestCase):
   def test_invalid_params_throw_exception(self):
     key_template = self.new_aes_eax_key_template(9, 16)
     with self.assertRaisesRegex(tink_error.TinkError,
-                                'Invalid AesEaxKeyFormat'):
+                                'Invalid IV size'):
       self.key_manager_eax.new_key_data(key_template)
 
     key_template = self.new_aes_gcm_key_template(17)