Do digesting, and sometimes padding, in SW when HW doesnt.

The keymaster1 specification only requires HW modules to implement
SHA256 out of the list of keymaster1 digest modes.  That would force
many keys to be software only, and would break legacy scenarios.  This
change uses SoftKeymasterDevice to front keymaster modules that don't
implement the full suite of digests, quietly inserting KM_DIGEST_NONE
and KM_PAD_NONE into key generation/import requests when necessary, then
performing the digesting, and sometimes padding, in software, then
delegating crypto operations to the hardware.

This is only done for RSA and EC keys.  Software digesting isn't
possible for HMAC or AES-GCM keys.

Note that this is not the complete fix for the bug.  Some changes in
keystore are also required, coming in another CL.

Bug: 22529223
Change-Id: I740572eb11341fb0659085309da01d5cbcd3854d
diff --git a/Android.mk b/Android.mk
index ed1a06e..8aba49a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -93,8 +93,13 @@
 LOCAL_MODULE := libsoftkeymasterdevice
 LOCAL_SRC_FILES := \
 	ec_keymaster0_key.cpp \
+	ec_keymaster1_key.cpp \
+	ecdsa_keymaster1_operation.cpp \
 	keymaster0_engine.cpp \
+	keymaster1_engine.cpp \
 	rsa_keymaster0_key.cpp \
+	rsa_keymaster1_key.cpp \
+	rsa_keymaster1_operation.cpp \
 	soft_keymaster_context.cpp \
 	soft_keymaster_device.cpp \
 	soft_keymaster_logger.cpp
diff --git a/Makefile b/Makefile
index 83acdae..a90b0a0 100644
--- a/Makefile
+++ b/Makefile
@@ -44,14 +44,14 @@
 CXXFLAGS +=-std=c++11 -DKEYMASTER_CLANG_TEST_BUILD
 CFLAGS += -DKEYMASTER_CLANG_TEST_BUILD
 else
-CXXFLAGS +=-std=c++0x -fprofile-arcs
-CFLAGS += -fprofile-arcs
+CXXFLAGS +=-std=c++0x -fprofile-arcs -ftest-coverage
+CFLAGS += -fprofile-arcs -ftest-coverage
 endif
 
 LDFLAGS += $(ARCH_FLAGS)
 CPPFLAGS = $(INCLUDES) -g -O0 -MD -MP
 CXXFLAGS += -Wall -Werror -Wno-unused -Winit-self -Wpointer-arith	-Wunused-parameter \
-	-Werror=sign-compare -ftest-coverage -fno-permissive \
+	-Werror=sign-compare -Werror=return-type -fno-permissive \
 	-Wno-deprecated-declarations -fno-exceptions -DKEYMASTER_NAME_TAGS $(ARCH_FLAGS)
 CFLAGS += $(ARCH_FLAGS)
 
@@ -61,7 +61,6 @@
 LDLIBS=-L$(BASE)/../boringssl/build/crypto -lcrypto -lpthread -lstdc++ -lgcov
 
 CPPSRCS=\
-	aead_mode_operation.cpp \
 	aes_key.cpp \
 	aes_operation.cpp \
 	android_keymaster.cpp \
@@ -78,6 +77,8 @@
 	ec_key.cpp \
 	ec_key_factory.cpp \
 	ec_keymaster0_key.cpp \
+	ec_keymaster1_key.cpp \
+	ecdsa_keymaster1_operation.cpp \
 	ecdsa_operation.cpp \
 	gtest_main.cpp \
 	hkdf.cpp \
@@ -90,6 +91,7 @@
 	key.cpp \
 	key_blob_test.cpp \
 	keymaster0_engine.cpp \
+	keymaster1_engine.cpp \
 	keymaster_enforcement.cpp \
 	keymaster_enforcement_test.cpp \
 	logger.cpp \
@@ -101,6 +103,8 @@
 	rsa_key.cpp \
 	rsa_key_factory.cpp \
 	rsa_keymaster0_key.cpp \
+	rsa_keymaster1_key.cpp \
+	rsa_keymaster1_operation.cpp \
 	rsa_operation.cpp \
 	serializable.cpp \
 	soft_keymaster_context.cpp \
@@ -231,12 +235,15 @@
 	ec_key.o \
 	ec_key_factory.o \
 	ec_keymaster0_key.o \
+	ec_keymaster1_key.o \
+	ecdsa_keymaster1_operation.o \
 	ecdsa_operation.o \
 	hmac_key.o \
 	hmac_operation.o \
 	integrity_assured_key_blob.o \
 	key.o \
 	keymaster0_engine.o \
+	keymaster1_engine.o \
 	keymaster_enforcement.o \
 	logger.o \
 	ocb.o \
@@ -248,6 +255,8 @@
 	rsa_key.o \
 	rsa_key_factory.o \
 	rsa_keymaster0_key.o \
+	rsa_keymaster1_key.o \
+	rsa_keymaster1_operation.o \
 	rsa_operation.o \
 	serializable.o \
 	soft_keymaster_context.o \
diff --git a/aes_key.cpp b/aes_key.cpp
index 92ea66e..6b784b7 100644
--- a/aes_key.cpp
+++ b/aes_key.cpp
@@ -42,6 +42,7 @@
 }
 
 keymaster_error_t AesKeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                         const AuthorizationSet& /* additional_params */,
                                          const AuthorizationSet& hw_enforced,
                                          const AuthorizationSet& sw_enforced,
                                          UniquePtr<Key>* key) const {
diff --git a/aes_key.h b/aes_key.h
index 9c58647..fad4569 100644
--- a/aes_key.h
+++ b/aes_key.h
@@ -33,6 +33,7 @@
     keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_AES; }
 
     keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& additional_params,
                               const AuthorizationSet& hw_enforced,
                               const AuthorizationSet& sw_enforced,
                               UniquePtr<Key>* key) const override;
diff --git a/android_keymaster.cpp b/android_keymaster.cpp
index 2bc6ea7..f60d6ee 100644
--- a/android_keymaster.cpp
+++ b/android_keymaster.cpp
@@ -275,8 +275,10 @@
         response->error = context_->enforcement_policy()->AuthorizeOperation(
             operation->purpose(), operation->key_id(), operation->authorizations(),
             request.additional_params, request.op_handle, false /* is_begin_operation */);
-        if (response->error != KM_ERROR_OK)
+        if (response->error != KM_ERROR_OK) {
+            operation_table_->Delete(request.op_handle);
             return;
+        }
     }
 
     response->error =
@@ -302,8 +304,10 @@
         response->error = context_->enforcement_policy()->AuthorizeOperation(
             operation->purpose(), operation->key_id(), operation->authorizations(),
             request.additional_params, request.op_handle, false /* is_begin_operation */);
-        if (response->error != KM_ERROR_OK)
+        if (response->error != KM_ERROR_OK) {
+            operation_table_->Delete(request.op_handle);
             return;
+        }
     }
 
     response->error = operation->Finish(request.additional_params, request.signature,
@@ -346,7 +350,8 @@
         return;
 
     UniquePtr<Key> key;
-    response->error = key_factory->LoadKey(key_material, hw_enforced, sw_enforced, &key);
+    response->error = key_factory->LoadKey(key_material, request.additional_params, hw_enforced,
+                                           sw_enforced, &key);
     if (response->error != KM_ERROR_OK)
         return;
 
@@ -392,6 +397,10 @@
     response->error = context_->DeleteAllKeys();
 }
 
+bool AndroidKeymaster::has_operation(keymaster_operation_handle_t op_handle) const {
+    return operation_table_->Find(op_handle) != nullptr;
+}
+
 keymaster_error_t AndroidKeymaster::LoadKey(const keymaster_key_blob_t& key_blob,
                                             const AuthorizationSet& additional_params,
                                             AuthorizationSet* hw_enforced,
@@ -408,7 +417,7 @@
     if (error != KM_ERROR_OK)
         return error;
 
-    return (*factory)->LoadKey(key_material, *hw_enforced, *sw_enforced, key);
+    return (*factory)->LoadKey(key_material, additional_params, *hw_enforced, *sw_enforced, key);
 }
 
 }  // namespace keymaster
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index af829e6..f0ae2f1 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -18,6 +18,9 @@
 #include <string>
 #include <vector>
 
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
 #include <hardware/keymaster0.h>
 #include <keymaster/key_factory.h>
 #include <keymaster/soft_keymaster_context.h>
@@ -51,6 +54,11 @@
     return vector<T>(array, array + len);
 }
 
+/**
+ * KeymasterEnforcement class for use in testing.  It's permissive in the sense that it doesn't
+ * check cryptoperiods, but restrictive in the sense that the clock never advances (so rate-limited
+ * keys will only work once).
+ */
 class TestKeymasterEnforcement : public KeymasterEnforcement {
   public:
     TestKeymasterEnforcement() : KeymasterEnforcement(3, 3) {}
@@ -65,10 +73,13 @@
     virtual bool ValidateTokenSignature(const hw_auth_token_t& /* token */) const { return true; }
 };
 
+/**
+ * Variant of SoftKeymasterContext that provides a TestKeymasterEnforcement.
+ */
 class TestKeymasterContext : public SoftKeymasterContext {
   public:
-    TestKeymasterContext(keymaster0_device_t* keymaster0 = nullptr)
-        : SoftKeymasterContext(keymaster0) {}
+    TestKeymasterContext() {}
+    TestKeymasterContext(const string& root_of_trust) : SoftKeymasterContext(root_of_trust) {}
 
     KeymasterEnforcement* enforcement_policy() override { return &test_policy_; }
 
@@ -76,6 +87,9 @@
     TestKeymasterEnforcement test_policy_;
 };
 
+/**
+ * Test instance creator that builds a pure software keymaster1 implementations.
+ */
 class SoftKeymasterTestInstanceCreator : public Keymaster1TestInstanceCreator {
   public:
     keymaster1_device_t* CreateDevice() const override {
@@ -84,10 +98,14 @@
         return device->keymaster_device();
     }
 
-    bool algorithm_in_hardware(keymaster_algorithm_t) const override { return false; }
+    bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
     int keymaster0_calls() const override { return 0; }
 };
 
+/**
+ * Test instance creator that builds keymaster1 instances which wrap a faked hardware keymaster0
+ * instance, with or without EC support.
+ */
 class Keymaster0AdapterTestInstanceCreator : public Keymaster1TestInstanceCreator {
   public:
     Keymaster0AdapterTestInstanceCreator(bool support_ec) : support_ec_(support_ec) {}
@@ -110,12 +128,12 @@
 
         counting_keymaster0_device_ = new Keymaster0CountingWrapper(keymaster0_device);
 
-        SoftKeymasterDevice* keymaster =
-            new SoftKeymasterDevice(new TestKeymasterContext(counting_keymaster0_device_));
+        SoftKeymasterDevice* keymaster = new SoftKeymasterDevice(new TestKeymasterContext);
+        keymaster->SetHardwareDevice(counting_keymaster0_device_);
         return keymaster->keymaster_device();
     }
 
-    bool algorithm_in_hardware(keymaster_algorithm_t algorithm) const override {
+    bool algorithm_in_km0_hardware(keymaster_algorithm_t algorithm) const override {
         switch (algorithm) {
         case KM_ALGORITHM_RSA:
             return true;
@@ -132,10 +150,35 @@
     bool support_ec_;
 };
 
+/**
+ * Test instance creator that builds a SoftKeymasterDevice which wraps a fake hardware keymaster1
+ * instance, with minimal digest support.
+ */
+class Sha256OnlyKeymaster1TestInstanceCreator : public Keymaster1TestInstanceCreator {
+    keymaster1_device_t* CreateDevice() const {
+        std::cerr << "Creating keymaster1-backed device that supports only SHA256";
+
+        // fake_device doesn't leak because device (below) takes ownership of it.
+        keymaster1_device_t* fake_device = make_device_sha256_only(
+            (new SoftKeymasterDevice(new TestKeymasterContext("PseudoHW")))->keymaster_device());
+
+        // device doesn't leak; it's cleaned up by device->keymaster_device()->common.close().
+        SoftKeymasterDevice* device = new SoftKeymasterDevice(new TestKeymasterContext);
+        device->SetHardwareDevice(fake_device);
+
+        return device->keymaster_device();
+    }
+
+    bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
+    int keymaster0_calls() const override { return 0; }
+    int minimal_digest_set() const override { return true; }
+};
+
 static auto test_params = testing::Values(
     InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
     InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
-    InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)));
+    InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)),
+    InstanceCreatorPtr(new Sha256OnlyKeymaster1TestInstanceCreator));
 
 typedef Keymaster1Test CheckSupported;
 INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, CheckSupported, test_params);
@@ -218,17 +261,38 @@
     keymaster_digest_t* digests;
     ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_RSA,
                                                            KM_PURPOSE_SIGN, &digests, &len));
-    EXPECT_TRUE(
-        ResponseContains({KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
-                          KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
-                         digests, len));
+    if (GetParam()->minimal_digest_set()) {
+        EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA_2_256}, digests, len));
+    } else {
+        EXPECT_TRUE(
+            ResponseContains({KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+                              KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
+                             digests, len));
+    }
+    free(digests);
+
+    ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_RSA,
+                                                           KM_PURPOSE_ENCRYPT, &digests, &len));
+    if (GetParam()->minimal_digest_set()) {
+        EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA_2_256}, digests, len));
+    } else {
+        EXPECT_TRUE(
+            ResponseContains({KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+                              KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
+                             digests, len));
+    }
     free(digests);
 
     ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_EC,
                                                            KM_PURPOSE_SIGN, &digests, &len));
-    EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
-                                  KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
-                                 digests, len));
+    if (GetParam()->minimal_digest_set()) {
+        EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA_2_256}, digests, len));
+    } else {
+        EXPECT_TRUE(
+            ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+                              KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
+                             digests, len));
+    }
     free(digests);
 
     EXPECT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE,
@@ -237,9 +301,13 @@
 
     ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_HMAC,
                                                            KM_PURPOSE_SIGN, &digests, &len));
-    EXPECT_TRUE(ResponseContains({KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384,
-                                  KM_DIGEST_SHA_2_512, KM_DIGEST_SHA1},
-                                 digests, len));
+    if (GetParam()->minimal_digest_set()) {
+        EXPECT_TRUE(ResponseContains({KM_DIGEST_SHA_2_256}, digests, len));
+    } else {
+        EXPECT_TRUE(ResponseContains({KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384,
+                                      KM_DIGEST_SHA_2_512, KM_DIGEST_SHA1},
+                                     digests, len));
+    }
     free(digests);
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
@@ -341,7 +409,7 @@
     // Check specified tags are all present, and in the right set.
     AuthorizationSet crypto_params;
     AuthorizationSet non_crypto_params;
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA)) {
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA)) {
         EXPECT_NE(0U, hw_enforced().size());
         EXPECT_NE(0U, sw_enforced().size());
         crypto_params.push_back(hw_enforced());
@@ -359,7 +427,7 @@
     EXPECT_TRUE(contains(crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
     EXPECT_FALSE(contains(non_crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
@@ -381,7 +449,7 @@
     // Check specified tags are all present, and in the right set.
     AuthorizationSet crypto_params;
     AuthorizationSet non_crypto_params;
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC)) {
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC)) {
         EXPECT_NE(0U, hw_enforced().size());
         EXPECT_NE(0U, sw_enforced().size());
         crypto_params.push_back(hw_enforced());
@@ -397,7 +465,7 @@
     EXPECT_TRUE(contains(crypto_params, TAG_KEY_SIZE, 224));
     EXPECT_FALSE(contains(non_crypto_params, TAG_KEY_SIZE, 224));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
@@ -412,7 +480,7 @@
 }
 
 TEST_P(NewKeyGeneration, EcdsaInvalidSize) {
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         ASSERT_EQ(
             KM_ERROR_UNKNOWN_ERROR,
             GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
@@ -421,7 +489,7 @@
             KM_ERROR_UNSUPPORTED_KEY_SIZE,
             GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
@@ -433,7 +501,7 @@
             << "Failed to generate size: " << size;
     }
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -510,7 +578,7 @@
     ASSERT_EQ(KM_ERROR_OK, GetCharacteristics());
     EXPECT_EQ(original, sw_enforced());
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
@@ -526,7 +594,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -540,7 +608,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -556,6 +624,9 @@
     begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
     begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
     EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+        EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, RsaPkcs1Sha256Success) {
@@ -567,7 +638,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -580,7 +651,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -601,7 +672,7 @@
     string signature;
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&signature));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -636,7 +707,7 @@
     size_t input_consumed;
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -653,7 +724,7 @@
     // Another abort should fail
     EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, AbortOperation());
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -666,7 +737,7 @@
     begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -681,7 +752,7 @@
     begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PSS);
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_SIGN, begin_params));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -693,7 +764,7 @@
     begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -706,7 +777,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -720,7 +791,7 @@
     begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -731,7 +802,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -742,7 +813,18 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(3, GetParam()->keymaster0_calls());
+}
+
+TEST_P(SigningOperationsTest, EcdsaSha384Success) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(
+                               KM_DIGEST_SHA_2_384)));
+    string message(1024, 'a');
+    string signature;
+    SignMessage(message, &signature, KM_DIGEST_SHA_2_384);
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -756,9 +838,9 @@
     ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
     string result;
     size_t input_consumed;
-    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
+    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -785,7 +867,7 @@
         }
     }
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(digests.size() * key_sizes.size() * 3,
                   static_cast<size_t>(GetParam()->keymaster0_calls()));
 }
@@ -801,6 +883,10 @@
 }
 
 TEST_P(SigningOperationsTest, HmacSha1Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate other digests for HMAC.
+        return;
+
     GenerateKey(AuthorizationSetBuilder()
                     .HmacKey(128)
                     .Digest(KM_DIGEST_SHA1)
@@ -814,6 +900,10 @@
 }
 
 TEST_P(SigningOperationsTest, HmacSha224Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate other digests for HMAC.
+        return;
+
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
                                            .HmacKey(128)
                                            .Digest(KM_DIGEST_SHA_2_224)
@@ -827,6 +917,10 @@
 }
 
 TEST_P(SigningOperationsTest, HmacSha256Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate other digests for HMAC.
+        return;
+
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
                                            .HmacKey(128)
                                            .Digest(KM_DIGEST_SHA_2_256)
@@ -840,6 +934,10 @@
 }
 
 TEST_P(SigningOperationsTest, HmacSha384Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate other digests for HMAC.
+        return;
+
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
                                            .HmacKey(128)
                                            .Digest(KM_DIGEST_SHA_2_384)
@@ -854,6 +952,10 @@
 }
 
 TEST_P(SigningOperationsTest, HmacSha512Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate other digests for HMAC.
+        return;
+
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
                                            .HmacKey(128)
                                            .Digest(KM_DIGEST_SHA_2_512)
@@ -870,12 +972,12 @@
     // TODO(swillden): unified API should generate an error on key generation.
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
                                            .HmacKey(128)
-                                           .Digest(KM_DIGEST_SHA_2_512)
-                                           .Authorization(TAG_MIN_MAC_LENGTH, 512)));
+                                           .Digest(KM_DIGEST_SHA_2_256)
+                                           .Authorization(TAG_MIN_MAC_LENGTH, 128)));
     string message = "12345678901234567890123456789012";
     string signature;
-    MacMessage(message, &signature, 512);
-    ASSERT_EQ(64U, signature.size());
+    MacMessage(message, &signature, 160);
+    ASSERT_EQ(20U, signature.size());
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -911,10 +1013,12 @@
 
     string key = make_string(key_data);
 
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
     CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    if (!GetParam()->minimal_digest_set()) {
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    }
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -945,10 +1049,13 @@
         0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37,
     };
 
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
     CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    if (!GetParam()->minimal_digest_set()) {
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    }
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -979,10 +1086,13 @@
         0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb,
     };
 
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
     CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    if (!GetParam()->minimal_digest_set()) {
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    }
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -1017,10 +1127,13 @@
         0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd,
     };
 
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
     CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    if (!GetParam()->minimal_digest_set()) {
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    }
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -1046,10 +1159,12 @@
         0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6,
     };
 
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
     CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    if (!GetParam()->minimal_digest_set()) {
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    }
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -1081,10 +1196,12 @@
         0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98,
     };
 
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
     CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    if (!GetParam()->minimal_digest_set()) {
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    }
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -1118,10 +1235,12 @@
         0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58,
     };
 
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
     CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    if (!GetParam()->minimal_digest_set()) {
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+        CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+    }
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -1169,7 +1288,7 @@
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1184,10 +1303,46 @@
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
+TEST_P(VerificationOperationsTest, RsaPssSha224Success) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .RsaSigningKey(512, 3)
+                                           .Digest(KM_DIGEST_SHA_2_224)
+                                           .Padding(KM_PAD_RSA_PSS)));
+    // Use large message, which won't work without digesting.
+    string message(1024, 'a');
+    string signature;
+    SignMessage(message, &signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PSS);
+    VerifyMessage(message, signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PSS);
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
+
+    // Verify with OpenSSL.
+    string pubkey;
+    EXPECT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &pubkey));
+
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(pubkey.data());
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+        d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
+    ASSERT_TRUE(pkey.get());
+
+    EVP_MD_CTX digest_ctx;
+    EVP_MD_CTX_init(&digest_ctx);
+    EVP_PKEY_CTX* pkey_ctx;
+    EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, EVP_sha224(), nullptr /* engine */,
+                                      pkey.get()));
+    EXPECT_EQ(1, EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
+    EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()));
+    EXPECT_EQ(1,
+              EVP_DigestVerifyFinal(&digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
+                                    signature.size()));
+    EVP_MD_CTX_cleanup(&digest_ctx);
+}
+
 TEST_P(VerificationOperationsTest, RsaPssSha256CorruptSignature) {
     GenerateKey(AuthorizationSetBuilder()
                     .RsaSigningKey(512, 3)
@@ -1209,7 +1364,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1235,7 +1390,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1249,10 +1404,45 @@
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
+TEST_P(VerificationOperationsTest, RsaPks1Sha224Success) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .RsaSigningKey(512, 3)
+                                           .Digest(KM_DIGEST_SHA_2_224)
+                                           .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
+    // Use large message, which won't work without digesting.
+    string message(1024, 'a');
+    string signature;
+    SignMessage(message, &signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PKCS1_1_5_SIGN);
+    VerifyMessage(message, signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PKCS1_1_5_SIGN);
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
+
+    // Verify with OpenSSL.
+    string pubkey;
+    EXPECT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &pubkey));
+
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(pubkey.data());
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+        d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
+    ASSERT_TRUE(pkey.get());
+
+    EVP_MD_CTX digest_ctx;
+    EVP_MD_CTX_init(&digest_ctx);
+    EVP_PKEY_CTX* pkey_ctx;
+    EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, EVP_sha224(), nullptr /* engine */,
+                                      pkey.get()));
+    EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()));
+    EXPECT_EQ(1,
+              EVP_DigestVerifyFinal(&digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
+                                    signature.size()));
+    EVP_MD_CTX_cleanup(&digest_ctx);
+}
+
 TEST_P(VerificationOperationsTest, RsaPkcs1Sha256CorruptSignature) {
     GenerateKey(AuthorizationSetBuilder()
                     .RsaSigningKey(512, 3)
@@ -1274,7 +1464,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1300,28 +1490,23 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
 TEST_P(VerificationOperationsTest, RsaAllDigestAndPadCombinations) {
-    // Get all supported digests and padding modes.
-    size_t digests_len;
-    keymaster_digest_t* digests;
-    ASSERT_EQ(KM_ERROR_OK,
-              device()->get_supported_digests(device(), KM_ALGORITHM_RSA, KM_PURPOSE_SIGN, &digests,
-                                              &digests_len));
+    vector<keymaster_digest_t> digests = {
+        KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,      KM_DIGEST_SHA_2_224,
+        KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
+    };
 
-    size_t padding_modes_len;
-    keymaster_padding_t* padding_modes;
-    ASSERT_EQ(KM_ERROR_OK,
-              device()->get_supported_padding_modes(device(), KM_ALGORITHM_RSA, KM_PURPOSE_SIGN,
-                                                    &padding_modes, &padding_modes_len));
+    vector<keymaster_padding_t> padding_modes{
+        KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_PAD_RSA_PSS,
+    };
 
-    // Try them.
     int trial_count = 0;
-    for (keymaster_padding_t padding_mode : make_vector(padding_modes, padding_modes_len)) {
-        for (keymaster_digest_t digest : make_vector(digests, digests_len)) {
+    for (keymaster_padding_t padding_mode : padding_modes) {
+        for (keymaster_digest_t digest : digests) {
             if (digest != KM_DIGEST_NONE && padding_mode == KM_PAD_NONE)
                 // Digesting requires padding
                 continue;
@@ -1397,10 +1582,7 @@
         }
     }
 
-    free(padding_modes);
-    free(digests);
-
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(trial_count * 4, GetParam()->keymaster0_calls());
 }
 
@@ -1412,7 +1594,7 @@
     SignMessage(message, &signature, KM_DIGEST_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1424,27 +1606,10 @@
     SignMessage(message, &signature, KM_DIGEST_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
-TEST_P(VerificationOperationsTest, EcdsaTooLong) {
-    ASSERT_EQ(KM_ERROR_OK,
-              GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(KM_DIGEST_NONE)));
-    string message = "1234567890123456789012345678901234";
-    string signature;
-
-    AuthorizationSet begin_params(client_params());
-    begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
-    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
-    string output;
-    size_t input_consumed;
-    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &output, &input_consumed));
-
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
-        EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
 TEST_P(VerificationOperationsTest, EcdsaSlightlyTooLong) {
     ASSERT_EQ(KM_ERROR_OK,
               GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(521).Digest(KM_DIGEST_NONE)));
@@ -1458,7 +1623,7 @@
     message[65] ^= 7;
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(5, GetParam()->keymaster0_calls());
 }
 
@@ -1472,7 +1637,7 @@
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 
     // Just for giggles, try verifying with the wrong digest.
@@ -1487,7 +1652,63 @@
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 }
 
+TEST_P(VerificationOperationsTest, EcdsaSha224Success) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(
+                               KM_DIGEST_SHA_2_224)));
+
+    string message = "12345678901234567890123456789012";
+    string signature;
+    SignMessage(message, &signature, KM_DIGEST_SHA_2_224);
+    VerifyMessage(message, signature, KM_DIGEST_SHA_2_224);
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
+
+    // Just for giggles, try verifying with the wrong digest.
+    AuthorizationSet begin_params(client_params());
+    begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
+    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
+
+    string result;
+    size_t input_consumed;
+    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
+    EXPECT_EQ(message.size(), input_consumed);
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+}
+
+TEST_P(VerificationOperationsTest, EcdsaAllDigestsAndKeySizes) {
+    keymaster_digest_t digests[] = {
+        KM_DIGEST_SHA1,      KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256,
+        KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
+    };
+    size_t key_sizes[] = {224, 256, 384, 521};
+
+    string message = "1234567890";
+    string signature;
+
+    for (auto key_size : key_sizes) {
+        AuthorizationSetBuilder builder;
+        builder.EcdsaSigningKey(key_size);
+        for (auto digest : digests)
+            builder.Digest(digest);
+        ASSERT_EQ(KM_ERROR_OK, GenerateKey(builder));
+
+        for (auto digest : digests) {
+            SignMessage(message, &signature, digest);
+            VerifyMessage(message, signature, digest);
+        }
+    }
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(static_cast<int>(array_length(key_sizes) * (1 + 3 * array_length(digests))),
+                  GetParam()->keymaster0_calls());
+}
+
 TEST_P(VerificationOperationsTest, HmacSha1Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate missing digests for HMAC.
+        return;
+
     GenerateKey(AuthorizationSetBuilder()
                     .HmacKey(128)
                     .Digest(KM_DIGEST_SHA1)
@@ -1501,6 +1722,10 @@
 }
 
 TEST_P(VerificationOperationsTest, HmacSha224Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate missing digests for HMAC.
+        return;
+
     GenerateKey(AuthorizationSetBuilder()
                     .HmacKey(128)
                     .Digest(KM_DIGEST_SHA_2_224)
@@ -1553,6 +1778,10 @@
 }
 
 TEST_P(VerificationOperationsTest, HmacSha384Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate missing digests for HMAC.
+        return;
+
     GenerateKey(AuthorizationSetBuilder()
                     .HmacKey(128)
                     .Digest(KM_DIGEST_SHA_2_384)
@@ -1566,6 +1795,10 @@
 }
 
 TEST_P(VerificationOperationsTest, HmacSha512Success) {
+    if (GetParam()->minimal_digest_set())
+        // Can't emulate missing digests for HMAC.
+        return;
+
     GenerateKey(AuthorizationSetBuilder()
                     .HmacKey(128)
                     .Digest(KM_DIGEST_SHA_2_512)
@@ -1592,7 +1825,7 @@
 
     // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1605,7 +1838,7 @@
 
     // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1617,7 +1850,7 @@
     string export_data;
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1630,7 +1863,7 @@
     string export_data;
     ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, ExportKey(KM_KEY_FORMAT_X509, &export_data));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1666,18 +1899,18 @@
                                      KM_KEY_FORMAT_PKCS8, pk8_key));
 
     // Check values derived from the key.
-    EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
-                                                                             : sw_enforced(),
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+                                                                                 : sw_enforced(),
                          TAG_ALGORITHM, KM_ALGORITHM_RSA));
-    EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
-                                                                             : sw_enforced(),
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+                                                                                 : sw_enforced(),
                          TAG_KEY_SIZE, 1024));
-    EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
-                                                                             : sw_enforced(),
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+                                                                                 : sw_enforced(),
                          TAG_RSA_PUBLIC_EXPONENT, 65537U));
 
     // And values provided by AndroidKeymaster
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_UNKNOWN));
     else
         EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1688,35 +1921,7 @@
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
-        EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(ImportKeyTest, OldApiRsaSuccess) {
-    string pk8_key = read_file("rsa_privkey_pk8.der");
-    ASSERT_EQ(633U, pk8_key.size());
-
-    // NOTE: This will break when the keymaster0 APIs are removed from keymaster1.  But at that
-    // point softkeymaster will no longer support keymaster0 APIs anyway.
-    uint8_t* key_blob;
-    size_t key_blob_length;
-    ASSERT_EQ(0,
-              device()->import_keypair(device(), reinterpret_cast<const uint8_t*>(pk8_key.data()),
-                                       pk8_key.size(), &key_blob, &key_blob_length));
-    set_key_blob(key_blob, key_blob_length);
-
-    string message(1024 / 8, 'a');
-    AuthorizationSet begin_params;  // Don't use client data.
-    begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
-    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
-    AuthorizationSet update_params;
-    AuthorizationSet output_params;
-    string signature =
-        ProcessMessage(KM_PURPOSE_SIGN, message, begin_params, update_params, &output_params);
-    ProcessMessage(KM_PURPOSE_VERIFY, message, signature, begin_params, update_params,
-                   &output_params);
-
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1755,15 +1960,15 @@
                         KM_KEY_FORMAT_PKCS8, pk8_key));
 
     // Check values derived from the key.
-    EXPECT_TRUE(
-        contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
-                 TAG_ALGORITHM, KM_ALGORITHM_EC));
-    EXPECT_TRUE(
-        contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
-                 TAG_KEY_SIZE, 256));
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+                                                                                : sw_enforced(),
+                         TAG_ALGORITHM, KM_ALGORITHM_EC));
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+                                                                                : sw_enforced(),
+                         TAG_KEY_SIZE, 256));
 
     // And values provided by AndroidKeymaster
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_UNKNOWN));
     else
         EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1774,7 +1979,7 @@
     SignMessage(message, &signature, KM_DIGEST_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1787,15 +1992,15 @@
                         KM_KEY_FORMAT_PKCS8, pk8_key));
 
     // Check values derived from the key.
-    EXPECT_TRUE(
-        contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
-                 TAG_ALGORITHM, KM_ALGORITHM_EC));
-    EXPECT_TRUE(
-        contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
-                 TAG_KEY_SIZE, 256));
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+                                                                                : sw_enforced(),
+                         TAG_ALGORITHM, KM_ALGORITHM_EC));
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+                                                                                : sw_enforced(),
+                         TAG_KEY_SIZE, 256));
 
     // And values provided by AndroidKeymaster
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_UNKNOWN));
     else
         EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1806,7 +2011,7 @@
     SignMessage(message, &signature, KM_DIGEST_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1856,7 +2061,7 @@
     string message = "Hello World!";
     string signature;
     MacMessage(message, &signature, 256);
-    VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
+    VerifyMac(message, signature);
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -1878,7 +2083,7 @@
     // Unpadded RSA is deterministic
     EXPECT_EQ(ciphertext1, ciphertext2);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -1896,7 +2101,7 @@
 
     EXPECT_EQ(expected_plaintext, plaintext);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1914,7 +2119,7 @@
     size_t input_consumed;
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1957,7 +2162,7 @@
     EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
     EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1978,7 +2183,28 @@
     // OAEP randomizes padding so every result should be different.
     EXPECT_NE(ciphertext1, ciphertext2);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+        EXPECT_EQ(3, GetParam()->keymaster0_calls());
+}
+
+TEST_P(EncryptionOperationsTest, RsaOaepSha224Success) {
+    size_t key_size = 768;
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .RsaEncryptionKey(key_size, 3)
+                                           .Padding(KM_PAD_RSA_OAEP)
+                                           .Digest(KM_DIGEST_SHA_2_224)));
+
+    string message = "Hello";
+    string ciphertext1 = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+    EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+    string ciphertext2 = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+    EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+    // OAEP randomizes padding so every result should be different.
+    EXPECT_NE(ciphertext1, ciphertext2);
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -1995,7 +2221,24 @@
     string plaintext = DecryptMessage(ciphertext, KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
+}
+
+TEST_P(EncryptionOperationsTest, RsaOaepSha224RoundTrip) {
+    size_t key_size = 768;
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .RsaEncryptionKey(key_size, 3)
+                                           .Padding(KM_PAD_RSA_OAEP)
+                                           .Digest(KM_DIGEST_SHA_2_224)));
+    string message = "Hello World!";
+    string ciphertext = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+    EXPECT_EQ(key_size / 8, ciphertext.size());
+
+    string plaintext = DecryptMessage(ciphertext, KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+    EXPECT_EQ(message, plaintext);
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -2011,11 +2254,15 @@
     begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
     EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, RsaOaepUnauthorizedDigest) {
+    if (GetParam()->minimal_digest_set())
+        // We don't have two supported digests, so we can't try authorizing one and using another.
+        return;
+
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
                                            .RsaEncryptionKey(512, 3)
                                            .Padding(KM_PAD_RSA_OAEP)
@@ -2029,11 +2276,16 @@
     begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA1);
     EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
+    if (GetParam()->minimal_digest_set())
+        // We don't have two supported digests, so we can't try encrypting with one and decrypting
+        // with another.
+        return;
+
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
                                            .RsaEncryptionKey(768, 3)
                                            .Padding(KM_PAD_RSA_OAEP)
@@ -2052,7 +2304,7 @@
     EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -2073,7 +2325,7 @@
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -2100,7 +2352,7 @@
     EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -2108,16 +2360,16 @@
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
                                KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
     string message = "Hello World!";
-    string ciphertext1 = EncryptMessage(string(message), KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+    string ciphertext1 = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
     EXPECT_EQ(512U / 8, ciphertext1.size());
 
-    string ciphertext2 = EncryptMessage(string(message), KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+    string ciphertext2 = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
     EXPECT_EQ(512U / 8, ciphertext2.size());
 
     // PKCS1 v1.5 randomizes padding so every result should be different.
     EXPECT_NE(ciphertext1, ciphertext2);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -2125,16 +2377,55 @@
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
                                KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
     string message = "Hello World!";
-    string ciphertext = EncryptMessage(string(message), KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+    string ciphertext = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
     EXPECT_EQ(512U / 8, ciphertext.size());
 
     string plaintext = DecryptMessage(ciphertext, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
+TEST_P(EncryptionOperationsTest, RsaRoundTripAllCombinations) {
+    size_t key_size = 2048;
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .RsaEncryptionKey(key_size, 3)
+                                           .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
+                                           .Padding(KM_PAD_RSA_OAEP)
+                                           .Digest(KM_DIGEST_NONE)
+                                           .Digest(KM_DIGEST_MD5)
+                                           .Digest(KM_DIGEST_SHA1)
+                                           .Digest(KM_DIGEST_SHA_2_224)
+                                           .Digest(KM_DIGEST_SHA_2_256)
+                                           .Digest(KM_DIGEST_SHA_2_384)
+                                           .Digest(KM_DIGEST_SHA_2_512)));
+
+    string message = "Hello World!";
+
+    keymaster_padding_t padding_modes[] = {KM_PAD_RSA_OAEP, KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
+    keymaster_digest_t digests[] = {
+        KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,      KM_DIGEST_SHA_2_224,
+        KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
+    };
+
+    for (auto padding : padding_modes)
+        for (auto digest : digests) {
+            if (padding == KM_PAD_RSA_OAEP && digest == KM_DIGEST_NONE)
+                // OAEP requires a digest.
+                continue;
+
+            string ciphertext = EncryptMessage(message, digest, padding);
+            EXPECT_EQ(key_size / 8, ciphertext.size());
+
+            string plaintext = DecryptMessage(ciphertext, digest, padding);
+            EXPECT_EQ(message, plaintext);
+        }
+
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+        EXPECT_EQ(40, GetParam()->keymaster0_calls());
+}
+
 TEST_P(EncryptionOperationsTest, RsaPkcs1TooLarge) {
     ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
                                KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
@@ -2149,24 +2440,7 @@
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
-        EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaPkcs1InvalidDigest) {
-    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
-                                           .RsaEncryptionKey(512, 3)
-                                           .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
-                                           .Digest(KM_DIGEST_NONE)));
-    string message = "Hello World!";
-    string result;
-
-    AuthorizationSet begin_params(client_params());
-    begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
-    begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);  // Any digest is invalid
-    EXPECT_EQ(KM_ERROR_UNSUPPORTED_DIGEST, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -2189,7 +2463,7 @@
     EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -2201,7 +2475,7 @@
     begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -2211,7 +2485,7 @@
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
 
-    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+    if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -3339,5 +3613,32 @@
     EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
+TEST(SoftKeymasterWrapperTest, CheckKeymaster1Device) {
+    // Make a good fake device, and wrap it.
+    SoftKeymasterDevice* good_fake(new SoftKeymasterDevice(new TestKeymasterContext));
+
+    // Wrap it and check it.
+    SoftKeymasterDevice* good_fake_wrapper(new SoftKeymasterDevice(new TestKeymasterContext));
+    good_fake_wrapper->SetHardwareDevice(good_fake->keymaster_device());
+    EXPECT_TRUE(good_fake_wrapper->Keymaster1DeviceIsGood());
+
+    // Close and clean up wrapper and wrapped
+    good_fake_wrapper->keymaster_device()->common.close(good_fake_wrapper->hw_device());
+
+    // Make a "bad" (doesn't support all digests) device;
+    keymaster1_device_t* sha256_only_fake = make_device_sha256_only(
+        (new SoftKeymasterDevice(new TestKeymasterContext("256")))->keymaster_device());
+
+    // Wrap it and check it.
+    SoftKeymasterDevice* sha256_only_fake_wrapper(
+        (new SoftKeymasterDevice(new TestKeymasterContext)));
+    sha256_only_fake_wrapper->SetHardwareDevice(sha256_only_fake);
+    EXPECT_FALSE(sha256_only_fake_wrapper->Keymaster1DeviceIsGood());
+
+    // Close and clean up wrapper and wrapped
+    sha256_only_fake_wrapper->keymaster_device()->common.close(
+        sha256_only_fake_wrapper->hw_device());
+}
+
 }  // namespace test
 }  // namespace keymaster
diff --git a/android_keymaster_test_utils.cpp b/android_keymaster_test_utils.cpp
index dacc413..3f058c5 100644
--- a/android_keymaster_test_utils.cpp
+++ b/android_keymaster_test_utils.cpp
@@ -23,6 +23,8 @@
 #include <keymaster/android_keymaster_messages.h>
 #include <keymaster/android_keymaster_utils.h>
 
+using std::copy_if;
+using std::find_if;
 using std::is_permutation;
 using std::ostream;
 using std::string;
@@ -636,5 +638,227 @@
     ++tmp[blob_.key_material_size / 2];
 }
 
+class Sha256OnlyWrapper {
+  public:
+    Sha256OnlyWrapper(const keymaster1_device_t* wrapped_device) : wrapped_device_(wrapped_device) {
+
+        new_module = *wrapped_device_->common.module;
+        new_module_name = std::string("SHA 256-only ") + wrapped_device_->common.module->name;
+        new_module.name = new_module_name.c_str();
+
+        memset(&device_, 0, sizeof(device_));
+        device_.common.module = &new_module;
+
+        device_.common.close = close_device;
+        device_.get_supported_algorithms = get_supported_algorithms;
+        device_.get_supported_block_modes = get_supported_block_modes;
+        device_.get_supported_padding_modes = get_supported_padding_modes;
+        device_.get_supported_digests = get_supported_digests;
+        device_.get_supported_import_formats = get_supported_import_formats;
+        device_.get_supported_export_formats = get_supported_export_formats;
+        device_.add_rng_entropy = add_rng_entropy;
+        device_.generate_key = generate_key;
+        device_.get_key_characteristics = get_key_characteristics;
+        device_.import_key = import_key;
+        device_.export_key = export_key;
+        device_.begin = begin;
+        device_.update = update;
+        device_.finish = finish;
+        device_.abort = abort;
+    }
+
+    keymaster1_device_t* keymaster_device() { return &device_; }
+
+    static bool is_supported(keymaster_digest_t digest) {
+        return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
+    }
+
+    static bool all_digests_supported(const keymaster_key_param_set_t* params) {
+        for (size_t i = 0; i < params->length; ++i)
+            if (params->params[i].tag == TAG_DIGEST)
+                if (!is_supported(static_cast<keymaster_digest_t>(params->params[i].enumerated)))
+                    return false;
+        return true;
+    }
+
+    static const keymaster_key_param_t*
+    get_algorithm_param(const keymaster_key_param_set_t* params) {
+        keymaster_key_param_t* end = params->params + params->length;
+        auto alg_ptr = std::find_if(params->params, end, [](keymaster_key_param_t& p) {
+            return p.tag == KM_TAG_ALGORITHM;
+        });
+        if (alg_ptr == end)
+            return nullptr;
+        return alg_ptr;
+    }
+
+    static int close_device(hw_device_t* dev) {
+        Sha256OnlyWrapper* wrapper = reinterpret_cast<Sha256OnlyWrapper*>(dev);
+        const keymaster1_device_t* wrapped_device = wrapper->wrapped_device_;
+        delete wrapper;
+        return wrapped_device->common.close(const_cast<hw_device_t*>(&wrapped_device->common));
+    }
+
+    static const keymaster1_device_t* unwrap(const keymaster1_device_t* dev) {
+        return reinterpret_cast<const Sha256OnlyWrapper*>(dev)->wrapped_device_;
+    }
+
+    static keymaster_error_t get_supported_algorithms(const struct keymaster1_device* dev,
+                                                      keymaster_algorithm_t** algorithms,
+                                                      size_t* algorithms_length) {
+        return unwrap(dev)->get_supported_algorithms(unwrap(dev), algorithms, algorithms_length);
+    }
+    static keymaster_error_t get_supported_block_modes(const struct keymaster1_device* dev,
+                                                       keymaster_algorithm_t algorithm,
+                                                       keymaster_purpose_t purpose,
+                                                       keymaster_block_mode_t** modes,
+                                                       size_t* modes_length) {
+        return unwrap(dev)
+            ->get_supported_block_modes(unwrap(dev), algorithm, purpose, modes, modes_length);
+    }
+    static keymaster_error_t get_supported_padding_modes(const struct keymaster1_device* dev,
+                                                         keymaster_algorithm_t algorithm,
+                                                         keymaster_purpose_t purpose,
+                                                         keymaster_padding_t** modes,
+                                                         size_t* modes_length) {
+        return unwrap(dev)
+            ->get_supported_padding_modes(unwrap(dev), algorithm, purpose, modes, modes_length);
+    }
+
+    static keymaster_error_t get_supported_digests(const keymaster1_device_t* dev,
+                                                   keymaster_algorithm_t algorithm,
+                                                   keymaster_purpose_t purpose,
+                                                   keymaster_digest_t** digests,
+                                                   size_t* digests_length) {
+        keymaster_error_t error = unwrap(dev)->get_supported_digests(
+            unwrap(dev), algorithm, purpose, digests, digests_length);
+        if (error != KM_ERROR_OK)
+            return error;
+
+        std::vector<keymaster_digest_t> filtered_digests;
+        std::copy_if(*digests, *digests + *digests_length, std::back_inserter(filtered_digests),
+                     [](keymaster_digest_t digest) { return is_supported(digest); });
+
+        free(*digests);
+        *digests_length = filtered_digests.size();
+        *digests = reinterpret_cast<keymaster_digest_t*>(
+            malloc(*digests_length * sizeof(keymaster_digest_t)));
+        std::copy(filtered_digests.begin(), filtered_digests.end(), *digests);
+
+        return KM_ERROR_OK;
+    }
+
+    static keymaster_error_t get_supported_import_formats(const struct keymaster1_device* dev,
+                                                          keymaster_algorithm_t algorithm,
+                                                          keymaster_key_format_t** formats,
+                                                          size_t* formats_length) {
+        return unwrap(dev)
+            ->get_supported_import_formats(unwrap(dev), algorithm, formats, formats_length);
+    }
+    static keymaster_error_t get_supported_export_formats(const struct keymaster1_device* dev,
+                                                          keymaster_algorithm_t algorithm,
+                                                          keymaster_key_format_t** formats,
+                                                          size_t* formats_length) {
+        return unwrap(dev)
+            ->get_supported_export_formats(unwrap(dev), algorithm, formats, formats_length);
+    }
+    static keymaster_error_t add_rng_entropy(const struct keymaster1_device* dev,
+                                             const uint8_t* data, size_t data_length) {
+        return unwrap(dev)->add_rng_entropy(unwrap(dev), data, data_length);
+    }
+
+    static keymaster_error_t generate_key(const keymaster1_device_t* dev,
+                                          const keymaster_key_param_set_t* params,
+                                          keymaster_key_blob_t* key_blob,
+                                          keymaster_key_characteristics_t** characteristics) {
+        auto alg_ptr = get_algorithm_param(params);
+        if (!alg_ptr)
+            return KM_ERROR_UNSUPPORTED_ALGORITHM;
+        if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
+            return KM_ERROR_UNSUPPORTED_DIGEST;
+
+        return unwrap(dev)->generate_key(unwrap(dev), params, key_blob, characteristics);
+    }
+
+    static keymaster_error_t
+    get_key_characteristics(const struct keymaster1_device* dev,
+                            const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id,
+                            const keymaster_blob_t* app_data,
+                            keymaster_key_characteristics_t** characteristics) {
+        return unwrap(dev)
+            ->get_key_characteristics(unwrap(dev), key_blob, client_id, app_data, characteristics);
+    }
+
+    static keymaster_error_t
+    import_key(const keymaster1_device_t* dev, const keymaster_key_param_set_t* params,
+               keymaster_key_format_t key_format, const keymaster_blob_t* key_data,
+               keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t** characteristics) {
+        auto alg_ptr = get_algorithm_param(params);
+        if (!alg_ptr)
+            return KM_ERROR_UNSUPPORTED_ALGORITHM;
+        if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
+            return KM_ERROR_UNSUPPORTED_DIGEST;
+
+        return unwrap(dev)
+            ->import_key(unwrap(dev), params, key_format, key_data, key_blob, characteristics);
+    }
+
+    static keymaster_error_t export_key(const struct keymaster1_device* dev,  //
+                                        keymaster_key_format_t export_format,
+                                        const keymaster_key_blob_t* key_to_export,
+                                        const keymaster_blob_t* client_id,
+                                        const keymaster_blob_t* app_data,
+                                        keymaster_blob_t* export_data) {
+        return unwrap(dev)->export_key(unwrap(dev), export_format, key_to_export, client_id,
+                                       app_data, export_data);
+    }
+
+    static keymaster_error_t begin(const keymaster1_device_t* dev,  //
+                                   keymaster_purpose_t purpose, const keymaster_key_blob_t* key,
+                                   const keymaster_key_param_set_t* in_params,
+                                   keymaster_key_param_set_t* out_params,
+                                   keymaster_operation_handle_t* operation_handle) {
+        if (!all_digests_supported(in_params))
+            return KM_ERROR_UNSUPPORTED_DIGEST;
+        return unwrap(dev)
+            ->begin(unwrap(dev), purpose, key, in_params, out_params, operation_handle);
+    }
+
+    static keymaster_error_t update(const keymaster1_device_t* dev,
+                                    keymaster_operation_handle_t operation_handle,
+                                    const keymaster_key_param_set_t* in_params,
+                                    const keymaster_blob_t* input, size_t* input_consumed,
+                                    keymaster_key_param_set_t* out_params,
+                                    keymaster_blob_t* output) {
+        return unwrap(dev)->update(unwrap(dev), operation_handle, in_params, input, input_consumed,
+                                   out_params, output);
+    }
+
+    static keymaster_error_t finish(const struct keymaster1_device* dev,  //
+                                    keymaster_operation_handle_t operation_handle,
+                                    const keymaster_key_param_set_t* in_params,
+                                    const keymaster_blob_t* signature,
+                                    keymaster_key_param_set_t* out_params,
+                                    keymaster_blob_t* output) {
+        return unwrap(dev)
+            ->finish(unwrap(dev), operation_handle, in_params, signature, out_params, output);
+    }
+
+    static keymaster_error_t abort(const struct keymaster1_device* dev,
+                                   keymaster_operation_handle_t operation_handle) {
+        return unwrap(dev)->abort(unwrap(dev), operation_handle);
+    }
+
+  private:
+    keymaster1_device_t device_;
+    const keymaster1_device_t* wrapped_device_;
+    hw_module_t new_module;
+    string new_module_name;
+};
+
+keymaster1_device_t* make_device_sha256_only(keymaster1_device_t* device) {
+    return (new Sha256OnlyWrapper(device))->keymaster_device();
+}
+
 }  // namespace test
 }  // namespace keymaster
diff --git a/android_keymaster_test_utils.h b/android_keymaster_test_utils.h
index 3d9e26a..c7177ea 100644
--- a/android_keymaster_test_utils.h
+++ b/android_keymaster_test_utils.h
@@ -158,8 +158,9 @@
     virtual ~Keymaster1TestInstanceCreator(){};
     virtual keymaster1_device_t* CreateDevice() const = 0;
 
-    virtual bool algorithm_in_hardware(keymaster_algorithm_t algorithm) const = 0;
+    virtual bool algorithm_in_km0_hardware(keymaster_algorithm_t algorithm) const = 0;
     virtual int keymaster0_calls() const = 0;
+    virtual int minimal_digest_set() const { return false; }
 };
 
 // Use a shared_ptr because it's copyable.
@@ -444,6 +445,13 @@
     int counter_;
 };
 
+
+/**
+ * This function takes a keymaster1_device_t and wraps it in an adapter that supports only
+ * KM_DIGEST_SHA_2_256.
+ */
+keymaster1_device_t* make_device_sha256_only(keymaster1_device_t* device);
+
 }  // namespace test
 }  // namespace keymaster
 
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp
index 74751f7..2ead3c5 100644
--- a/asymmetric_key.cpp
+++ b/asymmetric_key.cpp
@@ -25,28 +25,6 @@
 
 namespace keymaster {
 
-keymaster_error_t AsymmetricKey::key_material(UniquePtr<uint8_t[]>* material, size_t* size) const {
-    if (material == NULL || size == NULL)
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
-    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
-    if (pkey.get() == NULL)
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
-    if (!InternalToEvp(pkey.get()))
-        return TranslateLastOpenSslError();
-
-    *size = i2d_PrivateKey(pkey.get(), NULL /* key_data*/);
-    if (*size <= 0)
-        return TranslateLastOpenSslError();
-
-    material->reset(new (std::nothrow) uint8_t[*size]);
-    uint8_t* tmp = material->get();
-    i2d_PrivateKey(pkey.get(), &tmp);
-
-    return KM_ERROR_OK;
-}
-
 keymaster_error_t AsymmetricKey::formatted_key_material(keymaster_key_format_t format,
                                                         UniquePtr<uint8_t[]>* material,
                                                         size_t* size) const {
diff --git a/asymmetric_key.h b/asymmetric_key.h
index d8606dc..1a3b09f 100644
--- a/asymmetric_key.h
+++ b/asymmetric_key.h
@@ -29,7 +29,6 @@
                   keymaster_error_t* error)
         : Key(hw_enforced, sw_enforced, error) {}
 
-    keymaster_error_t key_material(UniquePtr<uint8_t[]>* material, size_t* size) const override;
     keymaster_error_t formatted_key_material(keymaster_key_format_t format,
                                              UniquePtr<uint8_t[]>* material,
                                              size_t* size) const override;
diff --git a/asymmetric_key_factory.cpp b/asymmetric_key_factory.cpp
index 05b69e4..b06d0d8 100644
--- a/asymmetric_key_factory.cpp
+++ b/asymmetric_key_factory.cpp
@@ -39,6 +39,7 @@
 }
 
 keymaster_error_t AsymmetricKeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                                const AuthorizationSet& /* additional_params */,
                                                 const AuthorizationSet& hw_enforced,
                                                 const AuthorizationSet& sw_enforced,
                                                 UniquePtr<Key>* key) const {
diff --git a/auth_encrypted_key_blob.cpp b/auth_encrypted_key_blob.cpp
index e7511d1..655bc12 100644
--- a/auth_encrypted_key_blob.cpp
+++ b/auth_encrypted_key_blob.cpp
@@ -71,7 +71,7 @@
         !copy_from_buf(buf_ptr, end, tag->peek_write(), OCB_TAG_LENGTH) ||
         !hw_enforced->Deserialize(buf_ptr, end) ||  //
         !sw_enforced->Deserialize(buf_ptr, end)) {
-        LOG_I("Failed to deserialize unversioned blob (may be a HW-backed key)", 0);
+        LOG_D("Failed to deserialize unversioned blob (may be a HW-backed key)", 0);
         return KM_ERROR_INVALID_KEY_BLOB;
     }
     if (!nonce->advance_write(OCB_NONCE_LENGTH) || !tag->advance_write(OCB_TAG_LENGTH))
@@ -127,7 +127,7 @@
         // Based on those two checks alone, the probability of interpreting an unversioned blob as a
         // version 0 blob is 1/2^40.  That's small enough to be negligible, but there are additional
         // checks which lower it further.
-        LOG_I("Failed to deserialize versioned key blob.  Assuming unversioned.", 0);
+        LOG_D("Failed to deserialize versioned key blob.  Assuming unversioned.", 0);
         return DeserializeUnversionedBlob(key_blob, encrypted_key_material, hw_enforced,
                                           sw_enforced, nonce, tag);
     }
diff --git a/authorization_set.cpp b/authorization_set.cpp
index 7ddb524..9a2b36a 100644
--- a/authorization_set.cpp
+++ b/authorization_set.cpp
@@ -191,6 +191,15 @@
 }
 
 keymaster_key_param_t empty;
+keymaster_key_param_t& AuthorizationSet::operator[](int at) {
+    if (is_valid() == OK && at < (int)elems_size_) {
+        return elems_[at];
+    }
+    memset(&empty, 0, sizeof(empty));
+    return empty;
+}
+
+
 keymaster_key_param_t AuthorizationSet::operator[](int at) const {
     if (is_valid() == OK && at < (int)elems_size_) {
         return elems_[at];
diff --git a/ec_key.h b/ec_key.h
index 2f66eb1..96c2635 100644
--- a/ec_key.h
+++ b/ec_key.h
@@ -35,7 +35,7 @@
     bool InternalToEvp(EVP_PKEY* pkey) const override;
     bool EvpToInternal(const EVP_PKEY* pkey) override;
 
-    EC_KEY* key() const { return EC_KEY_dup(ec_key_.get()); }
+    EC_KEY* key() const { return ec_key_.get(); }
 
   protected:
     EcKey(EC_KEY* ec_key, const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced,
diff --git a/ec_keymaster0_key.cpp b/ec_keymaster0_key.cpp
index 8cea462..c10a014 100644
--- a/ec_keymaster0_key.cpp
+++ b/ec_keymaster0_key.cpp
@@ -31,8 +31,7 @@
 
 EcdsaKeymaster0KeyFactory::EcdsaKeymaster0KeyFactory(const SoftKeymasterContext* context,
                                                      const Keymaster0Engine* engine)
-    : EcKeyFactory(context), engine_(engine), soft_context_(context) {
-}
+    : EcKeyFactory(context), engine_(engine) {}
 
 keymaster_error_t EcdsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
                                                          KeymasterKeyBlob* key_blob,
@@ -97,6 +96,7 @@
 }
 
 keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                                     const AuthorizationSet& additional_params,
                                                      const AuthorizationSet& hw_enforced,
                                                      const AuthorizationSet& sw_enforced,
                                                      UniquePtr<Key>* key) const {
@@ -104,7 +104,7 @@
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
     if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
-        return super::LoadKey(key_material, hw_enforced, sw_enforced, key);
+        return super::LoadKey(key_material, additional_params, hw_enforced, sw_enforced, key);
 
     unique_ptr<EC_KEY, EC_Delete> ec_key(engine_->BlobToEcKey(key_material));
     if (!ec_key)
@@ -122,23 +122,6 @@
 EcKeymaster0Key::EcKeymaster0Key(EC_KEY* ec_key, const AuthorizationSet& hw_enforced,
                                  const AuthorizationSet& sw_enforced,
                                  const Keymaster0Engine* engine, keymaster_error_t* error)
-    : EcKey(ec_key, hw_enforced, sw_enforced, error), engine_(engine) {
-}
-
-keymaster_error_t EcKeymaster0Key::key_material(UniquePtr<uint8_t[]>* material,
-                                                size_t* size) const {
-    if (!engine_)
-        return super::key_material(material, size);
-
-    const keymaster_key_blob_t* blob = engine_->EcKeyToBlob(key());
-    if (!blob)
-        return KM_ERROR_UNKNOWN_ERROR;
-
-    *size = blob->key_material_size;
-    material->reset(dup_buffer(blob->key_material, *size));
-    if (!material->get())
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    return KM_ERROR_OK;
-}
+    : EcKey(ec_key, hw_enforced, sw_enforced, error), engine_(engine) {}
 
 }  // namespace keymaster
diff --git a/ec_keymaster0_key.h b/ec_keymaster0_key.h
index 428c2b5..1d5cfe2 100644
--- a/ec_keymaster0_key.h
+++ b/ec_keymaster0_key.h
@@ -49,13 +49,13 @@
                                 AuthorizationSet* sw_enforced) const override;
 
     keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& additional_params,
                               const AuthorizationSet& hw_enforced,
                               const AuthorizationSet& sw_enforced,
                               UniquePtr<Key>* key) const override;
 
   private:
     const Keymaster0Engine* engine_;
-    const SoftKeymasterContext* soft_context_;
 };
 
 class EcKeymaster0Key : public EcKey {
@@ -66,8 +66,6 @@
                     const AuthorizationSet& sw_enforced, const Keymaster0Engine* engine,
                     keymaster_error_t* error);
 
-    keymaster_error_t key_material(UniquePtr<uint8_t[]>* material, size_t* size) const override;
-
   private:
     const Keymaster0Engine* engine_;
 };
diff --git a/ec_keymaster1_key.cpp b/ec_keymaster1_key.cpp
new file mode 100644
index 0000000..3958c5c
--- /dev/null
+++ b/ec_keymaster1_key.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 "ec_keymaster1_key.h"
+
+#include <memory>
+
+#include <keymaster/logger.h>
+
+#include "ecdsa_keymaster1_operation.h"
+#include "ecdsa_operation.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+EcdsaKeymaster1KeyFactory::EcdsaKeymaster1KeyFactory(const SoftKeymasterContext* context,
+                                                     const Keymaster1Engine* engine)
+    : EcKeyFactory(context), engine_(engine),
+      sign_factory_(new EcdsaKeymaster1OperationFactory(KM_PURPOSE_SIGN, engine)),
+      // For pubkey ops we can use the normal operation factories.
+      verify_factory_(new EcdsaVerifyOperationFactory) {}
+
+static bool is_supported(uint32_t digest) {
+    return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
+}
+
+static void UpdateToWorkAroundUnsupportedDigests(const AuthorizationSet& key_description,
+                                                 AuthorizationSet* new_description) {
+    bool have_unsupported_digests = false;
+    bool have_digest_none = false;
+    for (const keymaster_key_param_t& entry : key_description) {
+        new_description->push_back(entry);
+
+        if (entry.tag == TAG_DIGEST) {
+            if (entry.enumerated == KM_DIGEST_NONE) {
+                have_digest_none = true;
+            } else if (!is_supported(entry.enumerated)) {
+                LOG_D("Found request for unsupported digest %u", entry.enumerated);
+                have_unsupported_digests = true;
+            }
+        }
+    }
+
+    if (have_unsupported_digests && !have_digest_none) {
+        LOG_I("Adding KM_DIGEST_NONE to key authorization, to enable software digesting", 0);
+        new_description->push_back(TAG_DIGEST, KM_DIGEST_NONE);
+    }
+}
+
+keymaster_error_t EcdsaKeymaster1KeyFactory::GenerateKey(const AuthorizationSet& key_description,
+                                                         KeymasterKeyBlob* key_blob,
+                                                         AuthorizationSet* hw_enforced,
+                                                         AuthorizationSet* sw_enforced) const {
+    AuthorizationSet key_params_copy;
+    UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+    return engine_->GenerateKey(key_params_copy, key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t EcdsaKeymaster1KeyFactory::ImportKey(
+    const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format,
+    const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob,
+    AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
+    AuthorizationSet key_params_copy;
+    UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+    return engine_->ImportKey(key_params_copy, input_key_material_format, input_key_material,
+                              output_key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t EcdsaKeymaster1KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                                     const AuthorizationSet& additional_params,
+                                                     const AuthorizationSet& hw_enforced,
+                                                     const AuthorizationSet& sw_enforced,
+                                                     UniquePtr<Key>* key) const {
+    if (!key)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    keymaster_error_t error;
+    unique_ptr<EC_KEY, EC_Delete> ecdsa(
+        engine_->BuildEcKey(key_material, additional_params, &error));
+    if (!ecdsa)
+        return error;
+
+    key->reset(new (std::nothrow)
+                   EcdsaKeymaster1Key(ecdsa.release(), hw_enforced, sw_enforced, engine_, &error));
+    if (!key->get())
+        error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    if (error != KM_ERROR_OK)
+        return error;
+
+    return KM_ERROR_OK;
+}
+
+OperationFactory*
+EcdsaKeymaster1KeyFactory::GetOperationFactory(keymaster_purpose_t purpose) const {
+    switch (purpose) {
+    case KM_PURPOSE_SIGN:
+        return sign_factory_.get();
+    case KM_PURPOSE_VERIFY:
+        return verify_factory_.get();
+    default:
+        return nullptr;
+    }
+}
+
+EcdsaKeymaster1Key::EcdsaKeymaster1Key(EC_KEY* ecdsa_key, const AuthorizationSet& hw_enforced,
+                                       const AuthorizationSet& sw_enforced,
+                                       const Keymaster1Engine* engine, keymaster_error_t* error)
+    : EcKey(ecdsa_key, hw_enforced, sw_enforced, error), engine_(engine) {}
+
+}  // namespace keymaster
diff --git a/ec_keymaster1_key.h b/ec_keymaster1_key.h
new file mode 100644
index 0000000..b4c347a
--- /dev/null
+++ b/ec_keymaster1_key.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_KEYMASTER_EC_KEYMASTER1_KEY_H_
+#define SYSTEM_KEYMASTER_EC_KEYMASTER1_KEY_H_
+
+#include <openssl/ecdsa.h>
+
+#include <hardware/keymaster1.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/logger.h>
+#include <keymaster/ec_key_factory.h>
+#include <keymaster/soft_keymaster_context.h>
+
+#include "ec_key.h"
+#include "keymaster1_engine.h"
+
+namespace keymaster {
+
+class SoftKeymasterContext;
+
+/**
+ * EcdsaKeymaster1KeyFactory is a KeyFactory that creates and loads keys which are actually backed
+ * by a hardware keymaster1 module, but which does not support all keymaster1 digests.  During
+ * generation or import any unsupported digests in the key description are silently replaced with
+ * KM_DIGEST_NONE.
+ */
+class EcdsaKeymaster1KeyFactory : public EcKeyFactory {
+  public:
+    EcdsaKeymaster1KeyFactory(const SoftKeymasterContext* context, const Keymaster1Engine* engine);
+
+    keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+                                  KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
+                                  AuthorizationSet* sw_enforced) const override;
+
+    keymaster_error_t ImportKey(const AuthorizationSet& key_description,
+                                keymaster_key_format_t input_key_material_format,
+                                const KeymasterKeyBlob& input_key_material,
+                                KeymasterKeyBlob* output_key_blob, AuthorizationSet* hw_enforced,
+                                AuthorizationSet* sw_enforced) const override;
+
+    keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& additional_params,
+                              const AuthorizationSet& hw_enforced,
+                              const AuthorizationSet& sw_enforced,
+                              UniquePtr<Key>* key) const override;
+
+    OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
+
+  private:
+    const Keymaster1Engine* engine_;
+
+    std::unique_ptr<OperationFactory> sign_factory_;
+    std::unique_ptr<OperationFactory> verify_factory_;
+};
+
+class EcdsaKeymaster1Key : public EcKey {
+  public:
+    EcdsaKeymaster1Key(EC_KEY* ecdsa_key, const AuthorizationSet& hw_enforced,
+                       const AuthorizationSet& sw_enforced, const Keymaster1Engine* engine,
+                       keymaster_error_t* error);
+
+  private:
+    const Keymaster1Engine* engine_;
+};
+
+}  // namespace keymaster
+
+#endif  // SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_KEY_H_
diff --git a/ecdsa_keymaster1_operation.cpp b/ecdsa_keymaster1_operation.cpp
new file mode 100644
index 0000000..7e1a4f5
--- /dev/null
+++ b/ecdsa_keymaster1_operation.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 "ecdsa_keymaster1_operation.h"
+
+#include <memory>
+
+#include <keymaster/android_keymaster_utils.h>
+
+#include "openssl_err.h"
+#include "openssl_utils.h"
+#include "ec_keymaster1_key.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+keymaster_error_t EcdsaKeymaster1WrappedOperation::Begin(EVP_PKEY* ecdsa_key,
+                                                         const AuthorizationSet& input_params) {
+    Keymaster1Engine::KeyData* key_data = engine_->GetData(ecdsa_key);
+    if (!key_data)
+        return KM_ERROR_UNKNOWN_ERROR;
+
+    // Copy the input params and substitute KM_DIGEST_NONE for whatever was specified.  Also change
+    // KM_PAD_ECDSA_PSS and KM_PAD_OAEP to KM_PAD_NONE, if necessary. These are the params we'll
+    // pass
+    // to the hardware module.  The regular Ecdsa*Operation classes will do software digesting and
+    // padding where we've told the HW not to.
+    //
+    // The reason we don't change KM_PAD_ECDSA_PKCS1_1_5_SIGN or KM_PAD_ECDSA_PKCS1_1_5_ENCRYPT to
+    // KM_PAD_NONE is because the hardware can to those padding modes, since they don't involve
+    // digesting.
+    //
+    // We also cache in the key the padding value that we expect to be passed to the engine crypto
+    // operation.  This just allows us to double-check that the correct padding value is reaching
+    // that layer.
+    AuthorizationSet begin_params(input_params);
+    int pos = begin_params.find(TAG_DIGEST);
+    if (pos == -1)
+        return KM_ERROR_UNSUPPORTED_DIGEST;
+    begin_params[pos].enumerated = KM_DIGEST_NONE;
+
+    return engine_->device()->begin(engine_->device(), purpose_, &key_data->key_material,
+                                    &begin_params, nullptr /* out_params */, &operation_handle_);
+}
+
+keymaster_error_t
+EcdsaKeymaster1WrappedOperation::PrepareFinish(EVP_PKEY* ecdsa_key,
+                                               const AuthorizationSet& input_params) {
+    Keymaster1Engine::KeyData* key_data = engine_->GetData(ecdsa_key);
+    if (!key_data) {
+        LOG_E("Could not get extended key data... not a Keymaster1Engine key?", 0);
+        return KM_ERROR_UNKNOWN_ERROR;
+    }
+    key_data->op_handle = operation_handle_;
+    key_data->finish_params.Reinitialize(input_params);
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t EcdsaKeymaster1WrappedOperation::Abort() {
+    return engine_->device()->abort(engine_->device(), operation_handle_);
+}
+
+keymaster_error_t EcdsaKeymaster1WrappedOperation::GetError(EVP_PKEY* ecdsa_key) {
+    Keymaster1Engine::KeyData* key_data = engine_->GetData(ecdsa_key);
+    if (!key_data)
+        return KM_ERROR_UNKNOWN_ERROR;
+    return key_data->error;
+}
+
+static EVP_PKEY* GetEvpKey(const EcdsaKeymaster1Key& key, keymaster_error_t* error) {
+    if (!key.key()) {
+        *error = KM_ERROR_UNKNOWN_ERROR;
+        return nullptr;
+    }
+
+    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
+    if (!key.InternalToEvp(pkey.get())) {
+        *error = KM_ERROR_UNKNOWN_ERROR;
+        return nullptr;
+    }
+    return pkey.release();
+}
+
+Operation* EcdsaKeymaster1OperationFactory::CreateOperation(const Key& key,
+                                                            const AuthorizationSet& begin_params,
+                                                            keymaster_error_t* error) {
+    keymaster_digest_t digest;
+    if (!GetAndValidateDigest(begin_params, key, &digest, error))
+        return nullptr;
+
+    const EcdsaKeymaster1Key& ecdsa_km1_key(static_cast<const EcdsaKeymaster1Key&>(key));
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> ecdsa(GetEvpKey(ecdsa_km1_key, error));
+    if (!ecdsa)
+        return nullptr;
+
+    switch (purpose_) {
+    case KM_PURPOSE_SIGN:
+        return new EcdsaKeymaster1Operation<EcdsaSignOperation>(digest, ecdsa.release(), engine_);
+    default:
+        LOG_E(
+            "Bug: Pubkey operation requested.  Those should be handled by normal ECDSA operations.",
+            0);
+        *error = KM_ERROR_UNSUPPORTED_PURPOSE;
+        return nullptr;
+    }
+}
+
+static const keymaster_digest_t supported_digests[] = {
+    KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,     KM_DIGEST_SHA_2_224,
+    KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+
+const keymaster_digest_t*
+EcdsaKeymaster1OperationFactory::SupportedDigests(size_t* digest_count) const {
+    *digest_count = array_length(supported_digests);
+    return supported_digests;
+}
+
+const keymaster_padding_t*
+EcdsaKeymaster1OperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
+    *padding_mode_count = 0;
+    return nullptr;
+}
+
+}  // namespace keymaster
diff --git a/ecdsa_keymaster1_operation.h b/ecdsa_keymaster1_operation.h
new file mode 100644
index 0000000..7530fbb
--- /dev/null
+++ b/ecdsa_keymaster1_operation.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_
+#define SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_
+
+#include <openssl/evp.h>
+
+#include <hardware/keymaster1.h>
+#include <keymaster/android_keymaster_utils.h>
+
+#include "ecdsa_operation.h"
+#include "keymaster1_engine.h"
+
+namespace keymaster {
+
+class EcdsaKeymaster1WrappedOperation {
+  public:
+    EcdsaKeymaster1WrappedOperation(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+        : purpose_(purpose), operation_handle_(0), engine_(engine) {}
+    ~EcdsaKeymaster1WrappedOperation() {
+        if (operation_handle_)
+            Abort();
+    }
+
+    keymaster_error_t Begin(EVP_PKEY* ecdsa_key, const AuthorizationSet& input_params);
+    keymaster_error_t PrepareFinish(EVP_PKEY* ecdsa_key, const AuthorizationSet& input_params);
+    void Finish() { operation_handle_ = 0; }
+    keymaster_error_t Abort();
+
+    keymaster_error_t GetError(EVP_PKEY* ecdsa_key);
+
+  protected:
+    keymaster_purpose_t purpose_;
+    keymaster_operation_handle_t operation_handle_;
+    const Keymaster1Engine* engine_;
+};
+
+template <typename BaseOperation> class EcdsaKeymaster1Operation : public BaseOperation {
+    typedef BaseOperation super;
+
+  public:
+    EcdsaKeymaster1Operation(keymaster_digest_t digest, EVP_PKEY* key,
+                             const Keymaster1Engine* engine)
+        : BaseOperation(digest, key), wrapped_operation_(super::purpose(), engine) {
+        // Shouldn't be instantiated for public key operations.
+        assert(super::purpose() != KM_PURPOSE_VERIFY);
+        assert(super::purpose() != KM_PURPOSE_ENCRYPT);
+    }
+
+    keymaster_error_t Begin(const AuthorizationSet& input_params,
+                            AuthorizationSet* output_params) override {
+        keymaster_error_t error = wrapped_operation_.Begin(super::ecdsa_key_, input_params);
+        if (error != KM_ERROR_OK)
+            return error;
+        return super::Begin(input_params, output_params);
+    }
+
+    keymaster_error_t Finish(const AuthorizationSet& input_params, const Buffer& signature,
+                             AuthorizationSet* output_params, Buffer* output) override {
+        keymaster_error_t error = wrapped_operation_.PrepareFinish(super::ecdsa_key_, input_params);
+        if (error != KM_ERROR_OK)
+            return error;
+        error = super::Finish(input_params, signature, output_params, output);
+        if (wrapped_operation_.GetError(super::ecdsa_key_) != KM_ERROR_OK)
+            error = wrapped_operation_.GetError(super::ecdsa_key_);
+        if (error == KM_ERROR_OK)
+            wrapped_operation_.Finish();
+        return error;
+    }
+
+    keymaster_error_t Abort() override {
+        keymaster_error_t error = wrapped_operation_.Abort();
+        if (error != KM_ERROR_OK)
+            return error;
+        return super::Abort();
+    }
+
+  private:
+    EcdsaKeymaster1WrappedOperation wrapped_operation_;
+};
+
+/**
+ * Factory that produces EcdsaKeymaster1Operations.  This is instantiated and
+ * provided by EcdsaKeymaster1KeyFactory.
+ */
+class EcdsaKeymaster1OperationFactory : public OperationFactory {
+  public:
+    EcdsaKeymaster1OperationFactory(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+        : purpose_(purpose), engine_(engine) {}
+    KeyType registry_key() const override { return KeyType(KM_ALGORITHM_EC, purpose_); }
+
+    Operation* CreateOperation(const Key& key, const AuthorizationSet& begin_params,
+                               keymaster_error_t* error) override;
+
+    const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;
+    const keymaster_padding_t* SupportedPaddingModes(size_t* padding_mode_count) const override;
+
+  private:
+    keymaster_purpose_t purpose_;
+    const Keymaster1Engine* engine_;
+};
+
+}  // namespace keymaster
+
+#endif  // SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_
diff --git a/ecdsa_operation.cpp b/ecdsa_operation.cpp
index 54af6b2..6da23f5 100644
--- a/ecdsa_operation.cpp
+++ b/ecdsa_operation.cpp
@@ -91,16 +91,17 @@
     }
 }
 
+inline size_t min(size_t a, size_t b) {
+    return (a < b) ? a : b;
+}
+
 keymaster_error_t EcdsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
     if (!data_.reserve((EVP_PKEY_bits(ecdsa_key_) + 7) / 8))
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
 
-    // If the write fails, it's because input length exceeds key size.
-    if (!data_.write(input.peek_read(), input.available_read())) {
-        LOG_E("Input too long: cannot sign %u bytes of data with %u-bit ECDSA key",
-              input.available_read() + data_.available_read(), EVP_PKEY_bits(ecdsa_key_));
-        return KM_ERROR_INVALID_INPUT_LENGTH;
-    }
+    if (!data_.write(input.peek_read(), min(data_.available_write(), input.available_read())))
+        return KM_ERROR_UNKNOWN_ERROR;
+
     *input_consumed = input.available_read();
     return KM_ERROR_OK;
 }
diff --git a/ecdsa_operation.h b/ecdsa_operation.h
index fdca143..fba743f 100644
--- a/ecdsa_operation.h
+++ b/ecdsa_operation.h
@@ -49,8 +49,8 @@
 
 class EcdsaSignOperation : public EcdsaOperation {
   public:
-    EcdsaSignOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
-        : EcdsaOperation(purpose, digest, key) {}
+    EcdsaSignOperation(keymaster_digest_t digest, EVP_PKEY* key)
+        : EcdsaOperation(KM_PURPOSE_SIGN, digest, key) {}
     keymaster_error_t Begin(const AuthorizationSet& input_params,
                             AuthorizationSet* output_params) override;
     keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
@@ -62,8 +62,8 @@
 
 class EcdsaVerifyOperation : public EcdsaOperation {
   public:
-    EcdsaVerifyOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
-        : EcdsaOperation(purpose, digest, key) {}
+    EcdsaVerifyOperation(keymaster_digest_t digest, EVP_PKEY* key)
+        : EcdsaOperation(KM_PURPOSE_VERIFY, digest, key) {}
     keymaster_error_t Begin(const AuthorizationSet& input_params,
                             AuthorizationSet* output_params) override;
     keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
@@ -88,7 +88,7 @@
   private:
     keymaster_purpose_t purpose() const override { return KM_PURPOSE_SIGN; }
     Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
-        return new (std::nothrow) EcdsaSignOperation(purpose(), digest, key);
+        return new (std::nothrow) EcdsaSignOperation(digest, key);
     }
 };
 
@@ -96,7 +96,7 @@
   public:
     keymaster_purpose_t purpose() const override { return KM_PURPOSE_VERIFY; }
     Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
-        return new (std::nothrow) EcdsaVerifyOperation(KM_PURPOSE_VERIFY, digest, key);
+        return new (std::nothrow) EcdsaVerifyOperation(digest, key);
     }
 };
 
diff --git a/hmac_key.cpp b/hmac_key.cpp
index 91455e3..40a8906 100644
--- a/hmac_key.cpp
+++ b/hmac_key.cpp
@@ -40,6 +40,7 @@
 }
 
 keymaster_error_t HmacKeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                          const AuthorizationSet& /* additional_params */,
                                           const AuthorizationSet& hw_enforced,
                                           const AuthorizationSet& sw_enforced,
                                           UniquePtr<Key>* key) const {
diff --git a/hmac_key.h b/hmac_key.h
index c877a12..69d5331 100644
--- a/hmac_key.h
+++ b/hmac_key.h
@@ -28,6 +28,7 @@
     HmacKeyFactory(const KeymasterContext* context) : SymmetricKeyFactory(context) {}
 
     keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& additional_params,
                               const AuthorizationSet& hw_enforced,
                               const AuthorizationSet& sw_enforced,
                               UniquePtr<Key>* key) const override;
diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h
index e85ba25..24954d9 100644
--- a/include/keymaster/android_keymaster.h
+++ b/include/keymaster/android_keymaster.h
@@ -77,6 +77,8 @@
     void AbortOperation(const AbortOperationRequest& request, AbortOperationResponse* response);
     void GetVersion(const GetVersionRequest& request, GetVersionResponse* response);
 
+    bool has_operation(keymaster_operation_handle_t op_handle) const;
+
   private:
     keymaster_error_t LoadKey(const keymaster_key_blob_t& key_blob,
                               const AuthorizationSet& additional_params,
diff --git a/include/keymaster/android_keymaster_utils.h b/include/keymaster/android_keymaster_utils.h
index b957dd1..1964f1f 100644
--- a/include/keymaster/android_keymaster_utils.h
+++ b/include/keymaster/android_keymaster_utils.h
@@ -301,6 +301,17 @@
     }
 };
 
+struct Characteristics_Delete {
+    void operator()(keymaster_key_characteristics_t* p) {
+        keymaster_free_characteristics(p);
+        free(p);
+    }
+};
+
+struct Malloc_Delete {
+    void operator()(void* p) { free(p); }
+};
+
 }  // namespace keymaster
 
 #endif  // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
diff --git a/include/keymaster/asymmetric_key_factory.h b/include/keymaster/asymmetric_key_factory.h
index 22dfcde..a306d20 100644
--- a/include/keymaster/asymmetric_key_factory.h
+++ b/include/keymaster/asymmetric_key_factory.h
@@ -30,6 +30,7 @@
     AsymmetricKeyFactory(const KeymasterContext* context) : KeyFactory(context) {}
 
     keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& additional_params,
                               const AuthorizationSet& hw_enforced,
                               const AuthorizationSet& sw_enforced,
                               UniquePtr<Key>* key) const override;
diff --git a/include/keymaster/authorization_set.h b/include/keymaster/authorization_set.h
index 360e532..c638b7d 100644
--- a/include/keymaster/authorization_set.h
+++ b/include/keymaster/authorization_set.h
@@ -159,6 +159,11 @@
     /**
      * Returns the nth element of the set.
      */
+    keymaster_key_param_t& operator[](int n);
+
+    /**
+     * Returns the nth element of the set.
+     */
     keymaster_key_param_t operator[](int n) const;
 
     /**
diff --git a/include/keymaster/key_factory.h b/include/keymaster/key_factory.h
index 4ce3ddb..c77275a 100644
--- a/include/keymaster/key_factory.h
+++ b/include/keymaster/key_factory.h
@@ -49,6 +49,7 @@
                                         AuthorizationSet* sw_enforced) const = 0;
 
     virtual keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                                      const AuthorizationSet& additional_params,
                                       const AuthorizationSet& hw_enforced,
                                       const AuthorizationSet& sw_enforced,
                                       UniquePtr<Key>* key) const = 0;
diff --git a/include/keymaster/logger.h b/include/keymaster/logger.h
index 7b9e6d5..a4fdea3 100644
--- a/include/keymaster/logger.h
+++ b/include/keymaster/logger.h
@@ -59,23 +59,8 @@
 #define STRINGIFY(x) STR(x)
 #define FILE_LINE __FILE__ ", Line " STRINGIFY(__LINE__) ": "
 
-#ifdef DEBUG
-#define DEBUG_LOGS 1
-#else
-#define DEBUG_LOGS 0
-#endif
-
-#define LOG_D(fmt, ...)                                                                            \
-    do {                                                                                           \
-        if (DEBUG_LOGS)                                                                            \
-            Logger::Debug(FILE_LINE fmt, __VA_ARGS__);                                             \
-    } while (0)
-#define LOG_I(fmt, ...)                                                                            \
-    do {                                                                                           \
-        if (DEBUG_LOGS)                                                                            \
-            Logger::Info(FILE_LINE fmt, __VA_ARGS__);                                              \
-    } while (0)
-
+#define LOG_D(fmt, ...) Logger::Debug(FILE_LINE fmt, __VA_ARGS__)
+#define LOG_I(fmt, ...) Logger::Info(FILE_LINE fmt, __VA_ARGS__)
 #define LOG_W(fmt, ...) Logger::Warning(FILE_LINE fmt, __VA_ARGS__)
 #define LOG_E(fmt, ...) Logger::Error(FILE_LINE fmt, __VA_ARGS__)
 #define LOG_S(fmt, ...) Logger::Severe(FILE_LINE fmt, __VA_ARGS__)
diff --git a/include/keymaster/soft_keymaster_context.h b/include/keymaster/soft_keymaster_context.h
index 8f6fe2d..dac376a 100644
--- a/include/keymaster/soft_keymaster_context.h
+++ b/include/keymaster/soft_keymaster_context.h
@@ -18,23 +18,40 @@
 #define SYSTEM_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_
 
 #include <memory>
+#include <string>
 
 #include <openssl/evp.h>
 
 #include <hardware/keymaster0.h>
+#include <hardware/keymaster1.h>
 #include <keymaster/keymaster_context.h>
 
 namespace keymaster {
 
 class SoftKeymasterKeyRegistrations;
 class Keymaster0Engine;
+class Keymaster1Engine;
 
 /**
  * SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster.
  */
 class SoftKeymasterContext : public KeymasterContext {
   public:
-    SoftKeymasterContext(keymaster0_device_t* keymaster0_device);
+    SoftKeymasterContext(const std::string& root_of_trust = "SW");
+    ~SoftKeymasterContext() override;
+
+    /**
+     * Use the specified HW keymaster0 device for the operations it supports.  Takes ownership of
+     * the specified device (will call keymaster0_device->common.close());
+     */
+    keymaster_error_t SetHardwareDevice(keymaster0_device_t* keymaster0_device);
+
+    /**
+     * Use the specified HW keymaster1 device for performing undigested RSA and EC operations after
+     * digesting has been done in software.  Takes ownership of the specified device (will call
+     * keymaster1_device->common.close());
+     */
+    keymaster_error_t SetHardwareDevice(keymaster1_device_t* keymaster1_device);
 
     KeyFactory* GetKeyFactory(keymaster_algorithm_t algorithm) const override;
     OperationFactory* GetOperationFactory(keymaster_algorithm_t algorithm,
@@ -62,14 +79,28 @@
                                                 KeymasterKeyBlob* key_material,
                                                 AuthorizationSet* hw_enforced,
                                                 AuthorizationSet* sw_enforced) const;
+    keymaster_error_t ParseKeymaster1HwBlob(const KeymasterKeyBlob& blob,
+                                            const AuthorizationSet& additional_params,
+                                            KeymasterKeyBlob* key_material,
+                                            AuthorizationSet* hw_enforced,
+                                            AuthorizationSet* sw_enforced) const;
+    keymaster_error_t ParseKeymaster0HwBlob(const KeymasterKeyBlob& blob,
+                                            KeymasterKeyBlob* key_material,
+                                            AuthorizationSet* hw_enforced,
+                                            AuthorizationSet* sw_enforced) const;
     keymaster_error_t FakeKeyAuthorizations(EVP_PKEY* pubkey, AuthorizationSet* hw_enforced,
                                             AuthorizationSet* sw_enforced) const;
+    keymaster_error_t BuildHiddenAuthorizations(const AuthorizationSet& input_set,
+                                                AuthorizationSet* hidden) const;
 
-    std::unique_ptr<Keymaster0Engine> engine_;
+    std::unique_ptr<Keymaster0Engine> km0_engine_;
+    std::unique_ptr<Keymaster1Engine> km1_engine_;
     std::unique_ptr<KeyFactory> rsa_factory_;
     std::unique_ptr<KeyFactory> ec_factory_;
     std::unique_ptr<KeyFactory> aes_factory_;
     std::unique_ptr<KeyFactory> hmac_factory_;
+    keymaster1_device* km1_dev_;
+    const std::string root_of_trust_;
 };
 
 }  // namespace keymaster
diff --git a/include/keymaster/soft_keymaster_device.h b/include/keymaster/soft_keymaster_device.h
index 86ad260..5d7b83b 100644
--- a/include/keymaster/soft_keymaster_device.h
+++ b/include/keymaster/soft_keymaster_device.h
@@ -17,14 +17,15 @@
 #ifndef SYSTEM_KEYMASTER_SOFT_KEYMASTER_DEVICE_H_
 #define SYSTEM_KEYMASTER_SOFT_KEYMASTER_DEVICE_H_
 
-#include <stdlib.h>
+#include <cstdlib>
+#include <map>
+#include <vector>
 
 #include <hardware/keymaster0.h>
 #include <hardware/keymaster1.h>
 
 #include <keymaster/android_keymaster.h>
-#include <keymaster/keymaster_context.h>
-#include <keymaster/logger.h>
+#include <keymaster/soft_keymaster_context.h>
 
 #include <UniquePtr.h>
 
@@ -45,19 +46,28 @@
  */
 class SoftKeymasterDevice {
   public:
-    /**
-     * Create a SoftKeymasterDevice wrapping the specified HW keymaster0 device, which may be NULL.
-     *
-     * Uses SoftKeymaserContext.
-     */
-    SoftKeymasterDevice(keymaster0_device_t* keymaster0_device = nullptr);
+    SoftKeymasterDevice();
+
+    // Public only for testing.
+    SoftKeymasterDevice(SoftKeymasterContext* context);
 
     /**
-     * Create a SoftKeymasterDevice that uses the specified KeymasterContext.
-     *
-     * TODO(swillden): Refactor SoftKeymasterDevice construction to make all components injectable.
+     * Set SoftKeymasterDevice to wrap the speicified HW keymaster0 device.  Takes ownership of the
+     * specified device (will call keymaster0_device->common.close());
      */
-    SoftKeymasterDevice(KeymasterContext* context);
+    keymaster_error_t SetHardwareDevice(keymaster0_device_t* keymaster0_device);
+
+    /**
+     * Set SoftKeymasterDevice to wrap specified HW keymaster1 device.  Takes ownership of the
+     * specified device (will call keymaster1_device->common.close());
+     */
+    keymaster_error_t SetHardwareDevice(keymaster1_device_t* keymaster1_device);
+
+    /**
+     * Returns true if a keymaster1_device_t has been set as the hardware device, and if that
+     * hardware device should be used directly.
+     */
+    bool Keymaster1DeviceIsGood();
 
     hw_device_t* hw_device();
     keymaster1_device_t* keymaster_device();
@@ -68,7 +78,13 @@
     }
 
   private:
-    void initialize(keymaster0_device_t* keymaster0_device);
+    void initialize_device_struct();
+    bool FindUnsupportedDigest(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
+                               const AuthorizationSet& params,
+                               keymaster_digest_t* unsupported) const;
+    bool RequiresSoftwareDigesting(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
+                                   const AuthorizationSet& params) const;
+    bool KeyRequiresSoftwareDigesting(const AuthorizationSet& key_description) const;
 
     static void StoreDefaultNewKeyParams(keymaster_algorithm_t algorithm,
                                          AuthorizationSet* auth_set);
@@ -81,28 +97,6 @@
      * These static methods are the functions referenced through the function pointers in
      * keymaster_device.
      */
-
-    // keymaster0 APIs
-    static int generate_keypair(const keymaster1_device_t* dev, const keymaster_keypair_t key_type,
-                                const void* key_params, uint8_t** keyBlob, size_t* keyBlobLength);
-    static int import_keypair(const struct keymaster1_device* dev, const uint8_t* key,
-                              const size_t key_length, uint8_t** key_blob, size_t* key_blob_length);
-    static int get_keypair_public(const keymaster1_device_t* dev, const uint8_t* key_blob,
-                                  const size_t key_blob_length, uint8_t** x509_data,
-                                  size_t* x509_data_length);
-    static int delete_keypair(const struct keymaster1_device* dev, const uint8_t* key_blob,
-                              const size_t key_blob_length);
-    static int delete_all(const struct keymaster1_device* dev);
-    static int sign_data(const keymaster1_device_t* dev, const void* signing_params,
-                         const uint8_t* key_blob, const size_t key_blob_length, const uint8_t* data,
-                         const size_t data_length, uint8_t** signed_data,
-                         size_t* signed_data_length);
-    static int verify_data(const keymaster1_device_t* dev, const void* signing_params,
-                           const uint8_t* key_blob, const size_t key_blob_length,
-                           const uint8_t* signed_data, const size_t signed_data_length,
-                           const uint8_t* signature, const size_t signature_length);
-
-    // keymaster1 APIs.
     static keymaster_error_t get_supported_algorithms(const keymaster1_device_t* dev,
                                                       keymaster_algorithm_t** algorithms,
                                                       size_t* algorithms_length);
@@ -160,20 +154,33 @@
                                    const keymaster_key_param_set_t* in_params,
                                    keymaster_key_param_set_t* out_params,
                                    keymaster_operation_handle_t* operation_handle);
-    static keymaster_error_t
-    update(const keymaster1_device_t* dev, keymaster_operation_handle_t operation_handle,
-           const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input,
-           size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
-    static keymaster_error_t
-    finish(const keymaster1_device_t* dev, keymaster_operation_handle_t operation_handle,
-           const keymaster_key_param_set_t* in_params, const keymaster_blob_t* signature,
-           keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
+    static keymaster_error_t update(const keymaster1_device_t* dev,  //
+                                    keymaster_operation_handle_t operation_handle,
+                                    const keymaster_key_param_set_t* in_params,
+                                    const keymaster_blob_t* input, size_t* input_consumed,
+                                    keymaster_key_param_set_t* out_params,
+                                    keymaster_blob_t* output);
+    static keymaster_error_t finish(const keymaster1_device_t* dev,  //
+                                    keymaster_operation_handle_t operation_handle,
+                                    const keymaster_key_param_set_t* in_params,
+                                    const keymaster_blob_t* signature,
+                                    keymaster_key_param_set_t* out_params,
+                                    keymaster_blob_t* output);
+
     static keymaster_error_t abort(const keymaster1_device_t* dev,
                                    keymaster_operation_handle_t operation_handle);
 
+    typedef std::map<std::pair<keymaster_algorithm_t, keymaster_purpose_t>,
+                     std::vector<keymaster_digest_t>> DigestMap;
+
     keymaster1_device_t device_;
-    keymaster0_device_t* wrapped_device_;
+    keymaster0_device_t* wrapped_km0_device_;
+    keymaster1_device_t* wrapped_km1_device_;
+    DigestMap km1_device_digests_;
+    SoftKeymasterContext* context_;
     UniquePtr<AndroidKeymaster> impl_;
+    std::string module_name_;
+    hw_module_t updated_module_;
 };
 
 }  // namespace keymaster
diff --git a/key.h b/key.h
index ca0ceb9..959729e 100644
--- a/key.h
+++ b/key.h
@@ -29,11 +29,6 @@
     virtual ~Key() {}
 
     /**
-     * Return a copy of raw key material, in the key's preferred binary format.
-     */
-    virtual keymaster_error_t key_material(UniquePtr<uint8_t[]>*, size_t* size) const = 0;
-
-    /**
      * Return a copy of raw key material, in the specified format.
      */
     virtual keymaster_error_t formatted_key_material(keymaster_key_format_t format,
diff --git a/keymaster0_engine.cpp b/keymaster0_engine.cpp
index d7ad709..995bc0b 100644
--- a/keymaster0_engine.cpp
+++ b/keymaster0_engine.cpp
@@ -36,52 +36,7 @@
 
 namespace keymaster {
 
-// int Keymaster0Engine::rsa_index_ = -1;
-// int Keymaster0Engine::ec_key_index_ = -1;
 Keymaster0Engine* Keymaster0Engine::instance_ = nullptr;
-const RSA_METHOD Keymaster0Engine::rsa_method_ = {
-    .common =
-        {
-            0,  // references
-            1   // is_static
-        },
-    .app_data = nullptr,
-    .init = nullptr,
-    .finish = nullptr,
-    .size = nullptr,
-    .sign = nullptr,
-    .verify = nullptr,
-
-    .encrypt = nullptr,
-    .sign_raw = nullptr,
-    .decrypt = nullptr,
-    .verify_raw = nullptr,
-
-    .private_transform = Keymaster0Engine::rsa_private_transform,
-
-    .mod_exp = nullptr,
-    .bn_mod_exp = BN_mod_exp_mont,
-
-    .flags = RSA_FLAG_OPAQUE,
-
-    .keygen = nullptr,
-    .supports_digest = nullptr,
-};
-
-const ECDSA_METHOD Keymaster0Engine::ecdsa_method_ = {
-    .common =
-        {
-            0,  // references
-            1   // is_static
-        },
-    .app_data = nullptr,
-    .init = nullptr,
-    .finish = nullptr,
-    .group_order_size = nullptr,
-    .sign = Keymaster0Engine::ecdsa_sign,
-    .verify = nullptr,
-    .flags = ECDSA_FLAG_OPAQUE,
-};
 
 Keymaster0Engine::Keymaster0Engine(const keymaster0_device_t* keymaster0_device)
     : keymaster0_device_(keymaster0_device), engine_(ENGINE_new()), supports_ec_(false) {
@@ -93,10 +48,40 @@
     ec_key_index_ = EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
                                             keyblob_dup, keyblob_free);
 
+    rsa_method_.common.references = 0;
+    rsa_method_.common.is_static = 1;
+    rsa_method_.app_data = nullptr;
+    rsa_method_.init = nullptr;
+    rsa_method_.finish = nullptr;
+    rsa_method_.size = nullptr;
+    rsa_method_.sign = nullptr;
+    rsa_method_.verify = nullptr;
+    rsa_method_.encrypt = nullptr;
+    rsa_method_.sign_raw = nullptr;
+    rsa_method_.decrypt = nullptr;
+    rsa_method_.verify_raw = nullptr;
+    rsa_method_.private_transform = Keymaster0Engine::rsa_private_transform;
+    rsa_method_.mod_exp = nullptr;
+    rsa_method_.bn_mod_exp = BN_mod_exp_mont;
+    rsa_method_.flags = RSA_FLAG_OPAQUE;
+    rsa_method_.keygen = nullptr;
+    rsa_method_.supports_digest = nullptr;
+
     ENGINE_set_RSA_method(engine_, &rsa_method_, sizeof(rsa_method_));
 
     if ((keymaster0_device_->flags & KEYMASTER_SUPPORTS_EC) != 0) {
         supports_ec_ = true;
+
+        ecdsa_method_.common.references = 0;
+        ecdsa_method_.common.is_static = 1;
+        ecdsa_method_.app_data = nullptr;
+        ecdsa_method_.init = nullptr;
+        ecdsa_method_.finish = nullptr;
+        ecdsa_method_.group_order_size = nullptr;
+        ecdsa_method_.sign = Keymaster0Engine::ecdsa_sign;
+        ecdsa_method_.verify = nullptr;
+        ecdsa_method_.flags = ECDSA_FLAG_OPAQUE;
+
         ENGINE_set_ECDSA_method(engine_, &ecdsa_method_, sizeof(ecdsa_method_));
     }
 }
@@ -346,17 +331,6 @@
     return 1;
 }
 
-static size_t ec_group_size_bits(EC_KEY* ec_key) {
-    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
-    unique_ptr<BN_CTX, BN_CTX_Delete> bn_ctx(BN_CTX_new());
-    unique_ptr<BIGNUM, BIGNUM_Delete> order(BN_new());
-    if (!EC_GROUP_get_order(group, order.get(), bn_ctx.get())) {
-        ALOGE("Failed to get EC group order");
-        return 0;
-    }
-    return BN_num_bits(order.get());
-}
-
 int Keymaster0Engine::EcdsaSign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
                                 unsigned int* sig_len, EC_KEY* ec_key) const {
     const keymaster_key_blob_t* key_blob = EcKeyToBlob(ec_key);
diff --git a/keymaster0_engine.h b/keymaster0_engine.h
index 90aec93..71f550b 100644
--- a/keymaster0_engine.h
+++ b/keymaster0_engine.h
@@ -31,7 +31,7 @@
 
 struct KeymasterKeyBlob;
 
-/* Keymaster0Engine is a BoringSSL ENGINE that implements RSA by forwarding the requested
+/* Keymaster0Engine is a BoringSSL ENGINE that implements RSA & EC by forwarding the requested
  * operations to a keymaster0 module. */
 class Keymaster0Engine {
   public:
@@ -57,6 +57,8 @@
     const keymaster_key_blob_t* RsaKeyToBlob(const RSA* rsa) const;
     const keymaster_key_blob_t* EcKeyToBlob(const EC_KEY* rsa) const;
 
+    const keymaster0_device_t* device() { return keymaster0_device_; }
+
     EVP_PKEY* GetKeymaster0PublicKey(const KeymasterKeyBlob& blob) const;
 
   private:
@@ -88,9 +90,9 @@
     ENGINE* const engine_;
     int rsa_index_, ec_key_index_;
     bool supports_ec_;
+    RSA_METHOD rsa_method_;
+    ECDSA_METHOD ecdsa_method_;
 
-    static const RSA_METHOD rsa_method_;
-    static const ECDSA_METHOD ecdsa_method_;
     static Keymaster0Engine* instance_;
 };
 
diff --git a/keymaster1_engine.cpp b/keymaster1_engine.cpp
new file mode 100644
index 0000000..866a255
--- /dev/null
+++ b/keymaster1_engine.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 "keymaster1_engine.h"
+
+#include <assert.h>
+
+#include <algorithm>
+#include <memory>
+
+#define LOG_TAG "Keymaster1Engine"
+#include <cutils/log.h>
+
+#include "keymaster/android_keymaster_utils.h"
+
+#include <openssl/bn.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+
+#include "openssl_err.h"
+#include "openssl_utils.h"
+
+using std::shared_ptr;
+using std::unique_ptr;
+
+namespace keymaster {
+
+Keymaster1Engine* Keymaster1Engine::instance_ = nullptr;
+
+Keymaster1Engine::Keymaster1Engine(const keymaster1_device_t* keymaster1_device)
+    : keymaster1_device_(keymaster1_device), engine_(ENGINE_new()),
+      rsa_index_(RSA_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
+                                      Keymaster1Engine::duplicate_key_data,
+                                      Keymaster1Engine::free_key_data)),
+      ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
+                                            Keymaster1Engine::duplicate_key_data,
+                                            Keymaster1Engine::free_key_data)),
+      rsa_method_(BuildRsaMethod()), ecdsa_method_(BuildEcdsaMethod()) {
+    assert(rsa_index_ != -1);
+    assert(ec_key_index_ != -1);
+    assert(keymaster1_device);
+    assert(!instance_);
+
+    instance_ = this;
+
+    ENGINE_set_RSA_method(engine_.get(), &rsa_method_, sizeof(rsa_method_));
+    ENGINE_set_ECDSA_method(engine_.get(), &ecdsa_method_, sizeof(ecdsa_method_));
+}
+
+Keymaster1Engine::~Keymaster1Engine() {
+    keymaster1_device_->common.close(
+        reinterpret_cast<hw_device_t*>(const_cast<keymaster1_device_t*>(keymaster1_device_)));
+    instance_ = nullptr;
+}
+
+static void ConvertCharacteristics(keymaster_key_characteristics_t* characteristics,
+                                   AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) {
+    unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete> characteristics_deleter(
+        characteristics);
+    if (hw_enforced)
+        hw_enforced->Reinitialize(characteristics->hw_enforced);
+    if (sw_enforced)
+        sw_enforced->Reinitialize(characteristics->sw_enforced);
+}
+
+keymaster_error_t Keymaster1Engine::GenerateKey(const AuthorizationSet& key_description,
+                                                KeymasterKeyBlob* key_blob,
+                                                AuthorizationSet* hw_enforced,
+                                                AuthorizationSet* sw_enforced) const {
+    assert(key_blob);
+
+    keymaster_key_characteristics_t* characteristics;
+    keymaster_key_blob_t blob;
+    keymaster_error_t error = keymaster1_device_->generate_key(keymaster1_device_, &key_description,
+                                                               &blob, &characteristics);
+    if (error != KM_ERROR_OK)
+        return error;
+    unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
+    key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
+    key_blob->key_material_size = blob.key_material_size;
+
+    ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
+    return error;
+}
+
+keymaster_error_t Keymaster1Engine::ImportKey(const AuthorizationSet& key_description,
+                                              keymaster_key_format_t input_key_material_format,
+                                              const KeymasterKeyBlob& input_key_material,
+                                              KeymasterKeyBlob* output_key_blob,
+                                              AuthorizationSet* hw_enforced,
+                                              AuthorizationSet* sw_enforced) const {
+    assert(output_key_blob);
+
+    keymaster_key_characteristics_t* characteristics;
+    const keymaster_blob_t input_key = {input_key_material.key_material,
+                                        input_key_material.key_material_size};
+    keymaster_key_blob_t blob;
+    keymaster_error_t error = keymaster1_device_->import_key(keymaster1_device_, &key_description,
+                                                             input_key_material_format, &input_key,
+                                                             &blob, &characteristics);
+    if (error != KM_ERROR_OK)
+        return error;
+    unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
+    output_key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
+    output_key_blob->key_material_size = blob.key_material_size;
+
+    ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
+    return error;
+}
+
+RSA* Keymaster1Engine::BuildRsaKey(const KeymasterKeyBlob& blob,
+                                   const AuthorizationSet& additional_params,
+                                   keymaster_error_t* error) const {
+    // Create new RSA key (with engine methods) and add metadata
+    unique_ptr<RSA, RSA_Delete> rsa(RSA_new_method(engine_.get()));
+    if (!rsa) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    KeyData* key_data = new KeyData(blob, additional_params);
+    if (!RSA_set_ex_data(rsa.get(), rsa_index_, key_data)) {
+        *error = TranslateLastOpenSslError();
+        delete key_data;
+        return nullptr;
+    }
+
+    // Copy public key into new RSA key
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+        GetKeymaster1PublicKey(key_data->key_material, key_data->begin_params, error));
+    if (!pkey) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
+    if (!public_rsa) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    rsa->n = BN_dup(public_rsa->n);
+    rsa->e = BN_dup(public_rsa->e);
+    if (!rsa->n || !rsa->e) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    *error = KM_ERROR_OK;
+    return rsa.release();
+}
+
+EC_KEY* Keymaster1Engine::BuildEcKey(const KeymasterKeyBlob& blob,
+                                     const AuthorizationSet& additional_params,
+                                     keymaster_error_t* error) const {
+    // Create new EC key (with engine methods) and insert blob
+    unique_ptr<EC_KEY, EC_Delete> ec_key(EC_KEY_new_method(engine_.get()));
+    if (!ec_key) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    KeyData* key_data = new KeyData(blob, additional_params);
+    if (!EC_KEY_set_ex_data(ec_key.get(), ec_key_index_, key_data)) {
+        *error = TranslateLastOpenSslError();
+        delete key_data;
+        return nullptr;
+    }
+
+    // Copy public key into new EC key
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+        GetKeymaster1PublicKey(blob, additional_params, error));
+    if (!pkey) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    unique_ptr<EC_KEY, EC_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
+    if (!public_ec_key) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    if (!EC_KEY_set_group(ec_key.get(), EC_KEY_get0_group(public_ec_key.get())) ||
+        !EC_KEY_set_public_key(ec_key.get(), EC_KEY_get0_public_key(public_ec_key.get()))) {
+        *error = TranslateLastOpenSslError();
+        return nullptr;
+    }
+
+    *error = KM_ERROR_OK;
+    return ec_key.release();
+}
+
+Keymaster1Engine::KeyData* Keymaster1Engine::GetData(EVP_PKEY* key) const {
+    switch (EVP_PKEY_type(key->type)) {
+    case EVP_PKEY_RSA: {
+        unique_ptr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(key));
+        return GetData(rsa.get());
+    }
+
+    case EVP_PKEY_EC: {
+        unique_ptr<EC_KEY, EC_Delete> ec_key(EVP_PKEY_get1_EC_KEY(key));
+        return GetData(ec_key.get());
+    }
+
+    default:
+        return nullptr;
+    };
+}
+
+Keymaster1Engine::KeyData* Keymaster1Engine::GetData(const RSA* rsa) const {
+    if (!rsa)
+        return nullptr;
+    return reinterpret_cast<KeyData*>(RSA_get_ex_data(rsa, rsa_index_));
+}
+
+Keymaster1Engine::KeyData* Keymaster1Engine::GetData(const EC_KEY* ec_key) const {
+    if (!ec_key)
+        return nullptr;
+    return reinterpret_cast<KeyData*>(EC_KEY_get_ex_data(ec_key, ec_key_index_));
+}
+
+/* static */
+int Keymaster1Engine::duplicate_key_data(CRYPTO_EX_DATA* /* to */, const CRYPTO_EX_DATA* /* from */,
+                                         void** from_d, int /* index */, long /* argl */,
+                                         void* /* argp */) {
+    KeyData* data = reinterpret_cast<KeyData*>(*from_d);
+    if (!data)
+        return 1;
+
+    // Default copy ctor is good.
+    *from_d = new KeyData(*data);
+    if (*from_d)
+        return 1;
+    return 0;
+}
+
+/* static */
+void Keymaster1Engine::free_key_data(void* /* parent */, void* ptr, CRYPTO_EX_DATA* /* data */,
+                                     int /* index*/, long /* argl */, void* /* argp */) {
+    delete reinterpret_cast<KeyData*>(ptr);
+}
+
+keymaster_error_t Keymaster1Engine::Keymaster1Finish(const KeyData* key_data,
+                                                     const keymaster_blob_t& input,
+                                                     keymaster_blob_t* output) {
+    if (key_data->op_handle == 0)
+        return KM_ERROR_UNKNOWN_ERROR;
+
+    size_t input_consumed;
+    // Note: devices are required to consume all input in a single update call for undigested
+    // signing operations and encryption operations.  No need to loop here.
+    keymaster_error_t error =
+        device()->update(device(), key_data->op_handle, &key_data->finish_params, &input,
+                         &input_consumed, nullptr /* out_params */, nullptr /* output */);
+    if (error != KM_ERROR_OK)
+        return error;
+
+    return device()->finish(device(), key_data->op_handle, &key_data->finish_params,
+                            nullptr /* signature */, nullptr /* out_params */, output);
+}
+
+/* static */
+int Keymaster1Engine::rsa_sign_raw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+                                   const uint8_t* in, size_t in_len, int padding) {
+    KeyData* key_data = instance_->GetData(rsa);
+    if (!key_data)
+        return 0;
+
+    if (padding != key_data->expected_openssl_padding) {
+        LOG_E("Expected sign_raw with padding %d but got padding %d",
+              key_data->expected_openssl_padding, padding);
+        return KM_ERROR_UNKNOWN_ERROR;
+    }
+
+    keymaster_blob_t input = {in, in_len};
+    keymaster_blob_t output;
+    key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
+    if (key_data->error != KM_ERROR_OK)
+        return 0;
+    unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));
+
+    *out_len = std::min(output.data_length, max_out);
+    memcpy(out, output.data, *out_len);
+    return 1;
+}
+
+/* static */
+int Keymaster1Engine::rsa_decrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+                                  const uint8_t* in, size_t in_len, int padding) {
+    KeyData* key_data = instance_->GetData(rsa);
+    if (!key_data)
+        return 0;
+
+    if (padding != key_data->expected_openssl_padding) {
+        LOG_E("Expected sign_raw with padding %d but got padding %d",
+              key_data->expected_openssl_padding, padding);
+        return KM_ERROR_UNKNOWN_ERROR;
+    }
+
+    keymaster_blob_t input = {in, in_len};
+    keymaster_blob_t output;
+    key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
+    if (key_data->error != KM_ERROR_OK)
+        return 0;
+    unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));
+
+    *out_len = std::min(output.data_length, max_out);
+    memcpy(out, output.data, *out_len);
+    return 1;
+}
+
+/* static */
+int Keymaster1Engine::ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+                                 unsigned int* sig_len, EC_KEY* ec_key) {
+    KeyData* key_data = instance_->GetData(ec_key);
+    if (!key_data)
+        return 0;
+
+    // Truncate digest if it's too long
+    size_t max_input_len = (ec_group_size_bits(ec_key) + 7) / 8;
+    if (digest_len > max_input_len)
+        digest_len = max_input_len;
+
+    keymaster_blob_t input = {digest, digest_len};
+    keymaster_blob_t output;
+    key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
+    if (key_data->error != KM_ERROR_OK)
+        return 0;
+    unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));
+
+    *sig_len = std::min(output.data_length, ECDSA_size(ec_key));
+    memcpy(sig, output.data, *sig_len);
+    return 1;
+}
+
+EVP_PKEY* Keymaster1Engine::GetKeymaster1PublicKey(const KeymasterKeyBlob& blob,
+                                                   const AuthorizationSet& additional_params,
+                                                   keymaster_error_t* error) const {
+    keymaster_blob_t client_id = {nullptr, 0};
+    keymaster_blob_t app_data = {nullptr, 0};
+    keymaster_blob_t* client_id_ptr = nullptr;
+    keymaster_blob_t* app_data_ptr = nullptr;
+    if (additional_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
+        client_id_ptr = &client_id;
+    if (additional_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
+        app_data_ptr = &app_data;
+
+    keymaster_blob_t export_data = {nullptr, 0};
+    *error = keymaster1_device_->export_key(keymaster1_device_, KM_KEY_FORMAT_X509, &blob,
+                                            client_id_ptr, app_data_ptr, &export_data);
+    if (*error != KM_ERROR_OK)
+        return nullptr;
+
+    unique_ptr<uint8_t, Malloc_Delete> pub_key(const_cast<uint8_t*>(export_data.data));
+
+    const uint8_t* p = export_data.data;
+    return d2i_PUBKEY(nullptr /* allocate new struct */, &p, export_data.data_length);
+}
+
+RSA_METHOD Keymaster1Engine::BuildRsaMethod() {
+    RSA_METHOD method;
+
+    method.common.references = 0;
+    method.common.is_static = 1;
+    method.app_data = nullptr;
+    method.init = nullptr;
+    method.finish = nullptr;
+    method.size = nullptr;
+    method.sign = nullptr;
+    method.verify = nullptr;
+    method.encrypt = nullptr;
+    method.sign_raw = Keymaster1Engine::rsa_sign_raw;
+    method.decrypt = Keymaster1Engine::rsa_decrypt;
+    method.verify_raw = nullptr;
+    method.private_transform = nullptr;
+    method.mod_exp = nullptr;
+    method.bn_mod_exp = BN_mod_exp_mont;
+    method.flags = RSA_FLAG_OPAQUE;
+    method.keygen = nullptr;
+    method.supports_digest = nullptr;
+
+    return method;
+}
+
+ECDSA_METHOD Keymaster1Engine::BuildEcdsaMethod() {
+    ECDSA_METHOD method;
+
+    method.common.references = 0;
+    method.common.is_static = 1;
+    method.app_data = nullptr;
+    method.init = nullptr;
+    method.finish = nullptr;
+    method.group_order_size = nullptr;
+    method.sign = Keymaster1Engine::ecdsa_sign;
+    method.verify = nullptr;
+    method.flags = ECDSA_FLAG_OPAQUE;
+
+    return method;
+}
+
+}  // namespace keymaster
diff --git a/keymaster1_engine.h b/keymaster1_engine.h
new file mode 100644
index 0000000..9d696df
--- /dev/null
+++ b/keymaster1_engine.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
+#define SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
+
+#include <memory>
+
+#include <openssl/ec.h>
+#include <openssl/engine.h>
+#include <openssl/ex_data.h>
+#include <openssl/rsa.h>
+
+#include <hardware/keymaster1.h>
+#include <hardware/keymaster_defs.h>
+
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
+
+#include "openssl_utils.h"
+
+namespace keymaster {
+
+class Keymaster1Engine {
+  public:
+    /**
+     * Create a Keymaster1Engine, wrapping the provided keymaster1_device.  The engine takes
+     * ownership of the device, and will close it during destruction.
+     */
+    Keymaster1Engine(const keymaster1_device_t* keymaster1_device);
+    ~Keymaster1Engine();
+
+    keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+                                  KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
+                                  AuthorizationSet* sw_enforced) const;
+
+    keymaster_error_t ImportKey(const AuthorizationSet& key_description,
+                                keymaster_key_format_t input_key_material_format,
+                                const KeymasterKeyBlob& input_key_material,
+                                KeymasterKeyBlob* output_key_blob, AuthorizationSet* hw_enforced,
+                                AuthorizationSet* sw_enforced) const;
+
+    struct KeyData {
+        KeyData(const KeymasterKeyBlob& blob, const AuthorizationSet& params)
+            : op_handle(0), begin_params(params), key_material(blob), error(KM_ERROR_OK),
+              expected_openssl_padding(-1) {}
+
+        keymaster_operation_handle_t op_handle;
+        AuthorizationSet begin_params;
+        AuthorizationSet finish_params;
+        KeymasterKeyBlob key_material;
+        keymaster_error_t error;
+        int expected_openssl_padding;
+    };
+
+    RSA* BuildRsaKey(const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
+                     keymaster_error_t* error) const;
+    EC_KEY* BuildEcKey(const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
+                       keymaster_error_t* error) const;
+
+    KeyData* GetData(EVP_PKEY* key) const;
+    KeyData* GetData(const RSA* rsa) const;
+    KeyData* GetData(const EC_KEY* rsa) const;
+
+    const keymaster1_device_t* device() const { return keymaster1_device_; }
+
+    EVP_PKEY* GetKeymaster1PublicKey(const KeymasterKeyBlob& blob,
+                                     const AuthorizationSet& additional_params,
+                                     keymaster_error_t* error) const;
+
+  private:
+    Keymaster1Engine(const Keymaster1Engine&);  // Uncopyable
+    void operator=(const Keymaster1Engine&);    // Unassignable
+
+    RSA_METHOD BuildRsaMethod();
+    ECDSA_METHOD BuildEcdsaMethod();
+    void ConfigureEngineForRsa();
+    void ConfigureEngineForEcdsa();
+
+    keymaster_error_t Keymaster1Finish(const KeyData* key_data, const keymaster_blob_t& input,
+                                       keymaster_blob_t* output);
+
+    static int duplicate_key_data(CRYPTO_EX_DATA* to, const CRYPTO_EX_DATA* from, void** from_d,
+                                  int index, long argl, void* argp);
+    static void free_key_data(void* parent, void* ptr, CRYPTO_EX_DATA* data, int index, long argl,
+                              void* argp);
+
+    static int rsa_sign_raw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+                            const uint8_t* in, size_t in_len, int padding);
+    static int rsa_decrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+                           const uint8_t* in, size_t in_len, int padding);
+    static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+                          unsigned int* sig_len, EC_KEY* ec_key);
+
+    const keymaster1_device_t* const keymaster1_device_;
+    const std::unique_ptr<ENGINE, ENGINE_Delete> engine_;
+    const int rsa_index_;
+    const int ec_key_index_;
+
+    const RSA_METHOD rsa_method_;
+    const ECDSA_METHOD ecdsa_method_;
+
+    static Keymaster1Engine* instance_;
+};
+
+}  // namespace keymaster
+
+#endif  // SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
diff --git a/openssl_utils.cpp b/openssl_utils.cpp
index 3d29c86..1e25ca5 100644
--- a/openssl_utils.cpp
+++ b/openssl_utils.cpp
@@ -82,4 +82,15 @@
     return KM_ERROR_OK;
 }
 
+size_t ec_group_size_bits(EC_KEY* ec_key) {
+    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
+    UniquePtr<BN_CTX, BN_CTX_Delete> bn_ctx(BN_CTX_new());
+    UniquePtr<BIGNUM, BIGNUM_Delete> order(BN_new());
+    if (!EC_GROUP_get_order(group, order.get(), bn_ctx.get())) {
+        LOG_E("Failed to get EC group order", 0);
+        return 0;
+    }
+    return BN_num_bits(order.get());
+}
+
 }  // namespace keymaster
diff --git a/openssl_utils.h b/openssl_utils.h
index 97c2b5a..a66ef43 100644
--- a/openssl_utils.h
+++ b/openssl_utils.h
@@ -20,6 +20,7 @@
 #include <openssl/bn.h>
 #include <openssl/evp.h>
 #include <openssl/ec.h>
+#include <openssl/engine.h>
 #include <openssl/rsa.h>
 #include <openssl/x509.h>
 
@@ -59,6 +60,10 @@
     void operator()(EC_KEY* p) { EC_KEY_free(p); }
 };
 
+struct ENGINE_Delete {
+    void operator()(ENGINE* p) { ENGINE_free(p); }
+};
+
 /**
  * Many OpenSSL APIs take ownership of an argument on success but don't free the argument on
  * failure. This means we need to tell our scoped pointers when we've transferred ownership, without
@@ -80,6 +85,8 @@
 
 keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* evp_pkey, KeymasterKeyBlob* key_blob);
 
+size_t ec_group_size_bits(EC_KEY* ec_key);
+
 }  // namespace keymaster
 
 #endif  // SYSTEM_KEYMASTER_OPENSSL_UTILS_H_
diff --git a/rsa_keymaster0_key.cpp b/rsa_keymaster0_key.cpp
index 3afd024..8df05ae 100644
--- a/rsa_keymaster0_key.cpp
+++ b/rsa_keymaster0_key.cpp
@@ -18,9 +18,6 @@
 
 #include <memory>
 
-#define LOG_TAG "RsaKeymaster0Key"
-#include <cutils/log.h>
-
 #include <keymaster/android_keymaster_utils.h>
 #include <keymaster/logger.h>
 #include <keymaster/soft_keymaster_context.h>
@@ -34,7 +31,7 @@
 
 RsaKeymaster0KeyFactory::RsaKeymaster0KeyFactory(const SoftKeymasterContext* context,
                                                  const Keymaster0Engine* engine)
-    : RsaKeyFactory(context), engine_(engine), soft_context_(context) {}
+    : RsaKeyFactory(context), engine_(engine) {}
 
 keymaster_error_t RsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
                                                        KeymasterKeyBlob* key_blob,
@@ -43,9 +40,6 @@
     if (!key_blob || !hw_enforced || !sw_enforced)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
-    if (!engine_)
-        return super::GenerateKey(key_description, key_blob, hw_enforced, sw_enforced);
-
     uint64_t public_exponent;
     if (!key_description.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
         LOG_E("%s", "No public exponent specified for RSA key generation");
@@ -80,10 +74,6 @@
     if (!output_key_blob || !hw_enforced || !sw_enforced)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
-    if (!engine_)
-        return super::ImportKey(key_description, input_key_material_format, input_key_material,
-                                output_key_blob, hw_enforced, sw_enforced);
-
     AuthorizationSet authorizations;
     uint64_t public_exponent;
     uint32_t key_size;
@@ -109,6 +99,7 @@
 }
 
 keymaster_error_t RsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                                   const AuthorizationSet& additional_params,
                                                    const AuthorizationSet& hw_enforced,
                                                    const AuthorizationSet& sw_enforced,
                                                    UniquePtr<Key>* key) const {
@@ -116,7 +107,7 @@
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
     if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
-        return super::LoadKey(key_material, hw_enforced, sw_enforced, key);
+        return super::LoadKey(key_material, additional_params, hw_enforced, sw_enforced, key);
 
     unique_ptr<RSA, RSA_Delete> rsa(engine_->BlobToRsaKey(key_material));
     if (!rsa)
@@ -139,20 +130,4 @@
                                    const Keymaster0Engine* engine, keymaster_error_t* error)
     : RsaKey(rsa_key, hw_enforced, sw_enforced, error), engine_(engine) {}
 
-keymaster_error_t RsaKeymaster0Key::key_material(UniquePtr<uint8_t[]>* material,
-                                                 size_t* size) const {
-    if (!engine_)
-        return super::key_material(material, size);
-
-    const keymaster_key_blob_t* blob = engine_->RsaKeyToBlob(key());
-    if (!blob)
-        return KM_ERROR_UNKNOWN_ERROR;
-
-    *size = blob->key_material_size;
-    material->reset(dup_buffer(blob->key_material, *size));
-    if (!material->get())
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    return KM_ERROR_OK;
-}
-
 }  // namespace keymaster
diff --git a/rsa_keymaster0_key.h b/rsa_keymaster0_key.h
index 2090d04..9fd9fac 100644
--- a/rsa_keymaster0_key.h
+++ b/rsa_keymaster0_key.h
@@ -49,13 +49,13 @@
                                 AuthorizationSet* sw_enforced) const override;
 
     keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& additional_params,
                               const AuthorizationSet& hw_enforced,
                               const AuthorizationSet& sw_enforced,
                               UniquePtr<Key>* key) const override;
 
   private:
     const Keymaster0Engine* engine_;
-    const SoftKeymasterContext* soft_context_;
 };
 
 class RsaKeymaster0Key : public RsaKey {
@@ -66,8 +66,6 @@
                      const AuthorizationSet& sw_enforced, const Keymaster0Engine* engine,
                      keymaster_error_t* error);
 
-    keymaster_error_t key_material(UniquePtr<uint8_t[]>* material, size_t* size) const override;
-
   private:
     const Keymaster0Engine* engine_;
 };
diff --git a/rsa_keymaster1_key.cpp b/rsa_keymaster1_key.cpp
new file mode 100644
index 0000000..94f3cab
--- /dev/null
+++ b/rsa_keymaster1_key.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 "rsa_keymaster1_key.h"
+
+#include <memory>
+
+#include <keymaster/logger.h>
+#include <keymaster/soft_keymaster_context.h>
+
+#include "rsa_keymaster1_operation.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+RsaKeymaster1KeyFactory::RsaKeymaster1KeyFactory(const SoftKeymasterContext* context,
+                                                 const Keymaster1Engine* engine)
+    : RsaKeyFactory(context), engine_(engine),
+      sign_factory_(new RsaKeymaster1OperationFactory(KM_PURPOSE_SIGN, engine)),
+      decrypt_factory_(new RsaKeymaster1OperationFactory(KM_PURPOSE_DECRYPT, engine)),
+      // For pubkey ops we can use the normal operation factories.
+      verify_factory_(new RsaVerificationOperationFactory),
+      encrypt_factory_(new RsaEncryptionOperationFactory) {}
+
+static bool is_supported(uint32_t digest) {
+    return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
+}
+
+static void UpdateToWorkAroundUnsupportedDigests(const AuthorizationSet& key_description,
+                                                 AuthorizationSet* new_description) {
+    bool have_unsupported_digests = false;
+    bool have_digest_none = false;
+    bool have_pad_none = false;
+    bool have_padding_requiring_digest = false;
+    for (const keymaster_key_param_t& entry : key_description) {
+        new_description->push_back(entry);
+
+        if (entry.tag == TAG_DIGEST) {
+            if (entry.enumerated == KM_DIGEST_NONE) {
+                have_digest_none = true;
+            } else if (!is_supported(entry.enumerated)) {
+                LOG_D("Found request for unsupported digest %u", entry.enumerated);
+                have_unsupported_digests = true;
+            }
+        }
+
+        if (entry.tag == TAG_PADDING) {
+            switch (entry.enumerated) {
+            case KM_PAD_RSA_PSS:
+            case KM_PAD_RSA_OAEP:
+                have_padding_requiring_digest = true;
+                break;
+            case KM_PAD_NONE:
+                have_pad_none = true;
+                break;
+            }
+        }
+    }
+
+    if (have_unsupported_digests && !have_digest_none) {
+        LOG_I("Adding KM_DIGEST_NONE to key authorization, to enable software digesting", 0);
+        new_description->push_back(TAG_DIGEST, KM_DIGEST_NONE);
+    }
+
+    if (have_unsupported_digests && have_padding_requiring_digest && !have_pad_none) {
+        LOG_I("Adding KM_PAD_NONE to key authorization, to enable PSS or OAEP software padding", 0);
+        new_description->push_back(TAG_PADDING, KM_PAD_NONE);
+    }
+}
+
+keymaster_error_t RsaKeymaster1KeyFactory::GenerateKey(const AuthorizationSet& key_description,
+                                                       KeymasterKeyBlob* key_blob,
+                                                       AuthorizationSet* hw_enforced,
+                                                       AuthorizationSet* sw_enforced) const {
+    AuthorizationSet key_params_copy;
+    UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+    return engine_->GenerateKey(key_params_copy, key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t RsaKeymaster1KeyFactory::ImportKey(
+    const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format,
+    const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob,
+    AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
+    AuthorizationSet key_params_copy;
+    UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+    return engine_->ImportKey(key_params_copy, input_key_material_format, input_key_material,
+                              output_key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t RsaKeymaster1KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                                   const AuthorizationSet& additional_params,
+                                                   const AuthorizationSet& hw_enforced,
+                                                   const AuthorizationSet& sw_enforced,
+                                                   UniquePtr<Key>* key) const {
+    if (!key)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    keymaster_error_t error;
+    unique_ptr<RSA, RSA_Delete> rsa(engine_->BuildRsaKey(key_material, additional_params, &error));
+    if (!rsa)
+        return error;
+
+    key->reset(new (std::nothrow)
+                   RsaKeymaster1Key(rsa.release(), hw_enforced, sw_enforced, engine_, &error));
+    if (!key->get())
+        error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    if (error != KM_ERROR_OK)
+        return error;
+
+    return KM_ERROR_OK;
+}
+
+OperationFactory* RsaKeymaster1KeyFactory::GetOperationFactory(keymaster_purpose_t purpose) const {
+    switch (purpose) {
+    case KM_PURPOSE_SIGN:
+        return sign_factory_.get();
+    case KM_PURPOSE_VERIFY:
+        return verify_factory_.get();
+    case KM_PURPOSE_ENCRYPT:
+        return encrypt_factory_.get();
+    case KM_PURPOSE_DECRYPT:
+        return decrypt_factory_.get();
+    }
+    return nullptr;
+}
+
+RsaKeymaster1Key::RsaKeymaster1Key(RSA* rsa_key, const AuthorizationSet& hw_enforced,
+                                   const AuthorizationSet& sw_enforced,
+                                   const Keymaster1Engine* engine, keymaster_error_t* error)
+    : RsaKey(rsa_key, hw_enforced, sw_enforced, error), engine_(engine) {}
+
+}  // namespace keymaster
diff --git a/rsa_keymaster1_key.h b/rsa_keymaster1_key.h
new file mode 100644
index 0000000..4d5a3bd
--- /dev/null
+++ b/rsa_keymaster1_key.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
+#define SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
+
+#include <openssl/rsa.h>
+
+#include <keymaster/rsa_key_factory.h>
+
+#include "keymaster1_engine.h"
+#include "rsa_key.h"
+
+namespace keymaster {
+
+class SoftKeymasterContext;
+
+/**
+ * RsaKeymaster1KeyFactory is a KeyFactory that creates and loads keys which are actually backed by
+ * a hardware keymaster1 module, but which does not support all keymaster1 digests.  If unsupported
+ * digests are found during generation or import, KM_DIGEST_NONE is added to the key description,
+ * then the operations handle the unsupported digests in software.
+ *
+ * If unsupported digests are requested and KM_PAD_RSA_PSS or KM_PAD_RSA_OAEP is also requested, but
+ * KM_PAD_NONE is not present KM_PAD_NONE will be added to the description, to allow for
+ * software padding as well as software digesting.
+ */
+class RsaKeymaster1KeyFactory : public RsaKeyFactory {
+  public:
+    RsaKeymaster1KeyFactory(const SoftKeymasterContext* context, const Keymaster1Engine* engine);
+
+    keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+                                  KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
+                                  AuthorizationSet* sw_enforced) const override;
+
+    keymaster_error_t ImportKey(const AuthorizationSet& key_description,
+                                keymaster_key_format_t input_key_material_format,
+                                const KeymasterKeyBlob& input_key_material,
+                                KeymasterKeyBlob* output_key_blob, AuthorizationSet* hw_enforced,
+                                AuthorizationSet* sw_enforced) const override;
+
+    keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& additional_params,
+                              const AuthorizationSet& hw_enforced,
+                              const AuthorizationSet& sw_enforced,
+                              UniquePtr<Key>* key) const override;
+
+    OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
+
+  private:
+    const Keymaster1Engine* engine_;
+
+    std::unique_ptr<OperationFactory> sign_factory_;
+    std::unique_ptr<OperationFactory> decrypt_factory_;
+    std::unique_ptr<OperationFactory> verify_factory_;
+    std::unique_ptr<OperationFactory> encrypt_factory_;
+};
+
+class RsaKeymaster1Key : public RsaKey {
+  public:
+    RsaKeymaster1Key(RSA* rsa_key, const AuthorizationSet& hw_enforced,
+                     const AuthorizationSet& sw_enforced, const Keymaster1Engine* engine,
+                     keymaster_error_t* error);
+
+  private:
+    const Keymaster1Engine* engine_;
+};
+
+}  // namespace keymaster
+
+#endif  // SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
diff --git a/rsa_keymaster1_operation.cpp b/rsa_keymaster1_operation.cpp
new file mode 100644
index 0000000..002930e
--- /dev/null
+++ b/rsa_keymaster1_operation.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 "rsa_keymaster1_operation.h"
+
+#include <memory>
+
+#include <keymaster/android_keymaster_utils.h>
+
+#include "openssl_err.h"
+#include "openssl_utils.h"
+#include "rsa_keymaster1_key.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+keymaster_error_t RsaKeymaster1WrappedOperation::Begin(EVP_PKEY* rsa_key,
+                                                       const AuthorizationSet& input_params) {
+    Keymaster1Engine::KeyData* key_data = engine_->GetData(rsa_key);
+    if (!key_data)
+        return KM_ERROR_UNKNOWN_ERROR;
+
+    // Copy the input params and substitute KM_DIGEST_NONE for whatever was specified.  Also change
+    // KM_PAD_RSA_PSS and KM_PAD_OAEP to KM_PAD_NONE, if necessary. These are the params we'll pass
+    // to the hardware module.  The regular Rsa*Operation classes will do software digesting and
+    // padding where we've told the HW not to.
+    //
+    // The reason we don't change KM_PAD_RSA_PKCS1_1_5_SIGN or KM_PAD_RSA_PKCS1_1_5_ENCRYPT to
+    // KM_PAD_NONE is because the hardware can perform those padding modes, since they don't involve
+    // digesting.
+    //
+    // We also cache in the key the padding value that we expect to be passed to the engine crypto
+    // operation.  This just allows us to double-check that the correct padding value is reaching
+    // that layer.
+    AuthorizationSet begin_params(input_params);
+    int pos = begin_params.find(TAG_DIGEST);
+    if (pos == -1)
+        return KM_ERROR_UNSUPPORTED_DIGEST;
+    begin_params[pos].enumerated = KM_DIGEST_NONE;
+
+    pos = begin_params.find(TAG_PADDING);
+    if (pos == -1)
+        return KM_ERROR_UNSUPPORTED_PADDING_MODE;
+    switch (begin_params[pos].enumerated) {
+
+    case KM_PAD_RSA_PSS:
+    case KM_PAD_RSA_OAEP:
+        key_data->expected_openssl_padding = RSA_NO_PADDING;
+        begin_params[pos].enumerated = KM_PAD_NONE;
+        break;
+
+    case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
+    case KM_PAD_RSA_PKCS1_1_5_SIGN:
+        key_data->expected_openssl_padding = RSA_PKCS1_PADDING;
+        break;
+    }
+
+    return engine_->device()->begin(engine_->device(), purpose_, &key_data->key_material,
+                                    &begin_params, nullptr /* out_params */, &operation_handle_);
+}
+
+keymaster_error_t
+RsaKeymaster1WrappedOperation::PrepareFinish(EVP_PKEY* rsa_key,
+                                             const AuthorizationSet& input_params) {
+    Keymaster1Engine::KeyData* key_data = engine_->GetData(rsa_key);
+    if (!key_data) {
+        LOG_E("Could not get extended key data... not a Keymaster1Engine key?", 0);
+        return KM_ERROR_UNKNOWN_ERROR;
+    }
+    key_data->op_handle = operation_handle_;
+    key_data->finish_params.Reinitialize(input_params);
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t RsaKeymaster1WrappedOperation::Abort() {
+    return engine_->device()->abort(engine_->device(), operation_handle_);
+}
+
+keymaster_error_t RsaKeymaster1WrappedOperation::GetError(EVP_PKEY* rsa_key) {
+    Keymaster1Engine::KeyData* key_data = engine_->GetData(rsa_key);  // key_data is owned by rsa
+    if (!key_data)
+        return KM_ERROR_UNKNOWN_ERROR;
+    return key_data->error;
+}
+
+static EVP_PKEY* GetEvpKey(const RsaKeymaster1Key& key, keymaster_error_t* error) {
+    if (!key.key()) {
+        *error = KM_ERROR_UNKNOWN_ERROR;
+        return nullptr;
+    }
+
+    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
+    if (!key.InternalToEvp(pkey.get())) {
+        *error = KM_ERROR_UNKNOWN_ERROR;
+        return nullptr;
+    }
+    return pkey.release();
+}
+
+Operation* RsaKeymaster1OperationFactory::CreateOperation(const Key& key,
+                                                          const AuthorizationSet& begin_params,
+                                                          keymaster_error_t* error) {
+    keymaster_digest_t digest;
+    if (!GetAndValidateDigest(begin_params, key, &digest, error))
+        return nullptr;
+
+    keymaster_padding_t padding;
+    if (!GetAndValidatePadding(begin_params, key, &padding, error))
+        return nullptr;
+
+    const RsaKeymaster1Key& rsa_km1_key(static_cast<const RsaKeymaster1Key&>(key));
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetEvpKey(rsa_km1_key, error));
+    if (!rsa)
+        return nullptr;
+
+    switch (purpose_) {
+    case KM_PURPOSE_SIGN:
+        return new RsaKeymaster1Operation<RsaSignOperation>(digest, padding, rsa.release(),
+                                                            engine_);
+    case KM_PURPOSE_DECRYPT:
+        return new RsaKeymaster1Operation<RsaDecryptOperation>(digest, padding, rsa.release(),
+                                                               engine_);
+    default:
+        LOG_E("Bug: Pubkey operation requested.  Those should be handled by normal RSA operations.",
+              0);
+        *error = KM_ERROR_UNSUPPORTED_PURPOSE;
+        return nullptr;
+    }
+}
+
+static const keymaster_digest_t supported_digests[] = {
+    KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,     KM_DIGEST_SHA_2_224,
+    KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+
+const keymaster_digest_t*
+RsaKeymaster1OperationFactory::SupportedDigests(size_t* digest_count) const {
+    *digest_count = array_length(supported_digests);
+    return supported_digests;
+}
+
+static const keymaster_padding_t supported_sig_padding[] = {
+    KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_PAD_RSA_PSS,
+};
+static const keymaster_padding_t supported_crypt_padding[] = {
+    KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_ENCRYPT, KM_PAD_RSA_OAEP,
+};
+
+const keymaster_padding_t*
+RsaKeymaster1OperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
+    switch (purpose_) {
+    case KM_PURPOSE_SIGN:
+    case KM_PURPOSE_VERIFY:
+        *padding_mode_count = array_length(supported_sig_padding);
+        return supported_sig_padding;
+    case KM_PURPOSE_ENCRYPT:
+    case KM_PURPOSE_DECRYPT:
+        *padding_mode_count = array_length(supported_crypt_padding);
+        return supported_crypt_padding;
+    default:
+        *padding_mode_count = 0;
+        return nullptr;
+    }
+}
+
+}  // namespace keymaster
diff --git a/rsa_keymaster1_operation.h b/rsa_keymaster1_operation.h
new file mode 100644
index 0000000..bdf1a4e
--- /dev/null
+++ b/rsa_keymaster1_operation.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
+#define SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
+
+#include <openssl/evp.h>
+
+#include <hardware/keymaster1.h>
+#include <keymaster/android_keymaster_utils.h>
+
+#include "rsa_operation.h"
+#include "keymaster1_engine.h"
+
+namespace keymaster {
+
+class RsaKeymaster1WrappedOperation {
+  public:
+    RsaKeymaster1WrappedOperation(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+        : purpose_(purpose), operation_handle_(0), engine_(engine) {}
+    ~RsaKeymaster1WrappedOperation() {
+        if (operation_handle_)
+            Abort();
+    }
+
+    keymaster_error_t Begin(EVP_PKEY* rsa_key, const AuthorizationSet& input_params);
+    keymaster_error_t PrepareFinish(EVP_PKEY* rsa_key, const AuthorizationSet& input_params);
+    void Finish() { operation_handle_ = 0; }
+    keymaster_error_t Abort();
+
+    keymaster_error_t GetError(EVP_PKEY* rsa_key);
+
+  protected:
+    keymaster_purpose_t purpose_;
+    keymaster_operation_handle_t operation_handle_;
+    const Keymaster1Engine* engine_;
+};
+
+template <typename BaseOperation> class RsaKeymaster1Operation : public BaseOperation {
+    typedef BaseOperation super;
+
+  public:
+    RsaKeymaster1Operation(keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key,
+                           const Keymaster1Engine* engine)
+        : BaseOperation(digest, padding, key), wrapped_operation_(super::purpose(), engine) {
+        // Shouldn't be instantiated for public key operations.
+        assert(super::purpose() != KM_PURPOSE_VERIFY);
+        assert(super::purpose() != KM_PURPOSE_ENCRYPT);
+    }
+
+    keymaster_error_t Begin(const AuthorizationSet& input_params,
+                            AuthorizationSet* output_params) override {
+        keymaster_error_t error = wrapped_operation_.Begin(super::rsa_key_, input_params);
+        if (error != KM_ERROR_OK)
+            return error;
+        return super::Begin(input_params, output_params);
+    }
+
+    keymaster_error_t Finish(const AuthorizationSet& input_params, const Buffer& signature,
+                             AuthorizationSet* output_params, Buffer* output) override {
+        keymaster_error_t error = wrapped_operation_.PrepareFinish(super::rsa_key_, input_params);
+        if (error != KM_ERROR_OK)
+            return error;
+        error = super::Finish(input_params, signature, output_params, output);
+        if (wrapped_operation_.GetError(super::rsa_key_) != KM_ERROR_OK)
+            error = wrapped_operation_.GetError(super::rsa_key_);
+        if (error == KM_ERROR_OK)
+            wrapped_operation_.Finish();
+        return error;
+    }
+
+    keymaster_error_t Abort() override {
+        keymaster_error_t error = wrapped_operation_.Abort();
+        if (error != KM_ERROR_OK)
+            return error;
+        return super::Abort();
+    }
+
+  private:
+    RsaKeymaster1WrappedOperation wrapped_operation_;
+};
+
+/**
+ * Factory that produces RsaKeymaster1Operations.  This is instantiated and
+ * provided by RsaKeymaster1KeyFactory.
+ */
+class RsaKeymaster1OperationFactory : public OperationFactory {
+  public:
+    RsaKeymaster1OperationFactory(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+        : purpose_(purpose), engine_(engine) {}
+    KeyType registry_key() const override { return KeyType(KM_ALGORITHM_RSA, purpose_); }
+
+    Operation* CreateOperation(const Key& key, const AuthorizationSet& begin_params,
+                               keymaster_error_t* error) override;
+
+    const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;
+    const keymaster_padding_t* SupportedPaddingModes(size_t* padding_mode_count) const override;
+
+  private:
+    keymaster_purpose_t purpose_;
+    const Keymaster1Engine* engine_;
+};
+
+}  // namespace keymaster
+
+#endif  // SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
diff --git a/rsa_operation.cpp b/rsa_operation.cpp
index 076f333..7b6514c 100644
--- a/rsa_operation.cpp
+++ b/rsa_operation.cpp
@@ -76,10 +76,6 @@
     keymaster_digest_t digest = KM_DIGEST_NONE;
     if (require_digest && !GetAndValidateDigest(begin_params, key, &digest, error))
         return nullptr;
-    if (!require_digest && begin_params.find(TAG_DIGEST) != -1) {
-        *error = KM_ERROR_UNSUPPORTED_DIGEST;
-        return nullptr;
-    }
 
     UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
     if (!rsa.get())
diff --git a/rsa_operation.h b/rsa_operation.h
index 30ea3c5..3ad4f0d 100644
--- a/rsa_operation.h
+++ b/rsa_operation.h
@@ -58,7 +58,7 @@
     keymaster_error_t InitDigest();
 
     EVP_PKEY* rsa_key_;
-    keymaster_padding_t padding_;
+    const keymaster_padding_t padding_;
     Buffer data_;
     const keymaster_digest_t digest_;
     const EVP_MD* digest_algorithm_;
@@ -129,9 +129,9 @@
  */
 class RsaCryptOperation : public RsaOperation {
   public:
-    RsaCryptOperation(keymaster_purpose_t, keymaster_digest_t digest, keymaster_padding_t padding,
-                      EVP_PKEY* key)
-        : RsaOperation(KM_PURPOSE_ENCRYPT, digest, padding, key) {}
+    RsaCryptOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
+                      keymaster_padding_t padding, EVP_PKEY* key)
+        : RsaOperation(purpose, digest, padding, key) {}
 
   protected:
     keymaster_error_t SetOaepDigestIfRequired(EVP_PKEY_CTX* pkey_ctx);
@@ -189,9 +189,7 @@
 };
 
 /**
- * Abstract base for RSA operations that digest their input (signing and verification).  This class
- * does most of the work of creation of RSA digesting operations, delegating only the actual
- * operation instantiation.
+ * Abstract base for RSA operations that digest their input (signing and verification).
  */
 class RsaDigestingOperationFactory : public RsaOperationFactory {
   public:
diff --git a/soft_keymaster_context.cpp b/soft_keymaster_context.cpp
index 3e5fc35..288a350 100644
--- a/soft_keymaster_context.cpp
+++ b/soft_keymaster_context.cpp
@@ -29,12 +29,14 @@
 #include "aes_key.h"
 #include "auth_encrypted_key_blob.h"
 #include "ec_keymaster0_key.h"
+#include "ec_keymaster1_key.h"
 #include "hmac_key.h"
 #include "integrity_assured_key_blob.h"
 #include "keymaster0_engine.h"
 #include "ocb_utils.h"
 #include "openssl_err.h"
 #include "rsa_keymaster0_key.h"
+#include "rsa_keymaster1_key.h"
 
 using std::unique_ptr;
 
@@ -47,13 +49,47 @@
 const KeymasterKeyBlob MASTER_KEY(master_key_bytes, array_length(master_key_bytes));
 }  // anonymous namespace
 
-SoftKeymasterContext::SoftKeymasterContext(keymaster0_device_t* keymaster0_device) {
-    if (keymaster0_device && (keymaster0_device->flags & KEYMASTER_SOFTWARE_ONLY) == 0)
-        engine_.reset(new Keymaster0Engine(keymaster0_device));
-    rsa_factory_.reset(new RsaKeymaster0KeyFactory(this, engine_.get()));
-    ec_factory_.reset(new EcdsaKeymaster0KeyFactory(this, engine_.get()));
-    aes_factory_.reset(new AesKeyFactory(this));
-    hmac_factory_.reset(new HmacKeyFactory(this));
+SoftKeymasterContext::SoftKeymasterContext(const std::string& root_of_trust)
+    : rsa_factory_(new RsaKeyFactory(this)), ec_factory_(new EcKeyFactory(this)),
+      aes_factory_(new AesKeyFactory(this)), hmac_factory_(new HmacKeyFactory(this)),
+      km1_dev_(nullptr), root_of_trust_(root_of_trust) {}
+
+SoftKeymasterContext::~SoftKeymasterContext() {}
+
+keymaster_error_t SoftKeymasterContext::SetHardwareDevice(keymaster0_device_t* keymaster0_device) {
+    if (!keymaster0_device)
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+    if ((keymaster0_device->flags & KEYMASTER_SOFTWARE_ONLY) != 0) {
+        LOG_E("SoftKeymasterContext only wraps hardware keymaster0 devices", 0);
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+
+    km0_engine_.reset(new Keymaster0Engine(keymaster0_device));
+    rsa_factory_.reset(new RsaKeymaster0KeyFactory(this, km0_engine_.get()));
+    ec_factory_.reset(new EcdsaKeymaster0KeyFactory(this, km0_engine_.get()));
+    // Keep AES and HMAC factories.
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::SetHardwareDevice(keymaster1_device_t* keymaster1_device) {
+    if (!keymaster1_device)
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+    km1_dev_ = keymaster1_device;
+
+    km1_engine_.reset(new Keymaster1Engine(keymaster1_device));
+    rsa_factory_.reset(new RsaKeymaster1KeyFactory(this, km1_engine_.get()));
+    ec_factory_.reset(new EcdsaKeymaster1KeyFactory(this, km1_engine_.get()));
+
+    // All AES and HMAC operations should be passed directly to the keymaster1 device.  Explicitly
+    // do not handle them, to provoke errors in case the higher layers fail to send them to the
+    // device.
+    aes_factory_.reset(nullptr);
+    hmac_factory_.reset(nullptr);
+
+    return KM_ERROR_OK;
 }
 
 KeyFactory* SoftKeymasterContext::GetKeyFactory(keymaster_algorithm_t algorithm) const {
@@ -100,23 +136,6 @@
     return KM_ERROR_OK;
 }
 
-static keymaster_error_t BuildHiddenAuthorizations(const AuthorizationSet& input_set,
-                                                   AuthorizationSet* hidden) {
-    keymaster_blob_t entry;
-    if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
-        hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
-    if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
-        hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
-
-    keymaster_key_param_t root_of_trust;
-    root_of_trust.tag = KM_TAG_ROOT_OF_TRUST;
-    root_of_trust.blob.data = reinterpret_cast<const uint8_t*>("SW");
-    root_of_trust.blob.data_length = 2;
-    hidden->push_back(root_of_trust);
-
-    return TranslateAuthorizationSetError(hidden->is_valid());
-}
-
 static keymaster_error_t SetAuthorizations(const AuthorizationSet& key_description,
                                            keymaster_key_origin_t origin,
                                            AuthorizationSet* hw_enforced,
@@ -293,7 +312,10 @@
     //     they're protected by the keymaster0 hardware implementation).  The keymaster0 key blob
     //     and auth sets should be extracted and returned.
     //
-    // 5.  Old keymaster0 hardware key blobs.  These are raw hardware key blobs.  They don't have
+    // 5.  Keymaster1 hardware key blobs.  These are raw hardware key blobs.  They contain auth
+    //     sets, which we retrieve from the hardware module.
+    //
+    // 6.  Old keymaster0 hardware key blobs.  These are raw hardware key blobs.  They don't have
     //     auth sets so reasonable defaults are generated and returned along with the key blob.
     //
     // Determining what kind of blob has arrived is somewhat tricky.  What helps is that
@@ -328,17 +350,72 @@
     if (error != KM_ERROR_INVALID_KEY_BLOB)
         return error;
 
-    // Not an old softkeymaster blob, either.  The only remaining option is old HW keymaster0.
-    if (!engine_)
-        return KM_ERROR_INVALID_KEY_BLOB;
+    if (km1_dev_)
+        return ParseKeymaster1HwBlob(blob, additional_params, key_material, hw_enforced,
+                                     sw_enforced);
+    else if (km0_engine_)
+        return ParseKeymaster0HwBlob(blob, key_material, hw_enforced, sw_enforced);
 
-    // See if the HW thinks it's valid.
-    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> tmp_key(engine_->GetKeymaster0PublicKey(blob));
+    LOG_E("Failed to parse key; not a valid software blob, no hardware module configured", 0);
+    return KM_ERROR_INVALID_KEY_BLOB;
+}
+
+keymaster_error_t SoftKeymasterContext::AddRngEntropy(const uint8_t* buf, size_t length) const {
+    RAND_add(buf, length, 0 /* Don't assume any entropy is added to the pool. */);
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::GenerateRandom(uint8_t* buf, size_t length) const {
+    if (RAND_bytes(buf, length) != 1)
+        return KM_ERROR_UNKNOWN_ERROR;
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::ParseKeymaster1HwBlob(
+    const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
+    KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
+    AuthorizationSet* sw_enforced) const {
+    assert(km1_dev_);
+
+    keymaster_blob_t client_id = {nullptr, 0};
+    keymaster_blob_t app_data = {nullptr, 0};
+    keymaster_blob_t* client_id_ptr = nullptr;
+    keymaster_blob_t* app_data_ptr = nullptr;
+    if (additional_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
+        client_id_ptr = &client_id;
+    if (additional_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
+        app_data_ptr = &app_data;
+
+    // Get key characteristics, which incidentally verifies that the HW recognizes the key.
+    keymaster_key_characteristics_t* characteristics;
+    keymaster_error_t error = km1_dev_->get_key_characteristics(km1_dev_, &blob, client_id_ptr,
+                                                                app_data_ptr, &characteristics);
+    if (error != KM_ERROR_OK)
+        return error;
+    unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete> characteristics_deleter(
+        characteristics);
+
+    LOG_D("Module \"%s\" accepted key", km1_dev_->common.module->name);
+
+    hw_enforced->Reinitialize(characteristics->hw_enforced);
+    sw_enforced->Reinitialize(characteristics->sw_enforced);
+    *key_material = blob;
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::ParseKeymaster0HwBlob(const KeymasterKeyBlob& blob,
+                                                              KeymasterKeyBlob* key_material,
+                                                              AuthorizationSet* hw_enforced,
+                                                              AuthorizationSet* sw_enforced) const {
+    assert(km0_engine_);
+
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> tmp_key(km0_engine_->GetKeymaster0PublicKey(blob));
+
     if (!tmp_key)
         return KM_ERROR_INVALID_KEY_BLOB;
-    else
-        error = FakeKeyAuthorizations(tmp_key.get(), hw_enforced, sw_enforced);
 
+    LOG_D("Module \"%s\" accepted key", km0_engine_->device()->common.module->name);
+    keymaster_error_t error = FakeKeyAuthorizations(tmp_key.get(), hw_enforced, sw_enforced);
     if (error == KM_ERROR_OK)
         *key_material = blob;
 
@@ -418,15 +495,18 @@
     return KM_ERROR_OK;
 }
 
-keymaster_error_t SoftKeymasterContext::AddRngEntropy(const uint8_t* buf, size_t length) const {
-    RAND_add(buf, length, 0 /* Don't assume any entropy is added to the pool. */);
-    return KM_ERROR_OK;
-}
+keymaster_error_t SoftKeymasterContext::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
+                                                                  AuthorizationSet* hidden) const {
+    keymaster_blob_t entry;
+    if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
+        hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
+    if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
+        hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
 
-keymaster_error_t SoftKeymasterContext::GenerateRandom(uint8_t* buf, size_t length) const {
-    if (RAND_bytes(buf, length) != 1)
-        return KM_ERROR_UNKNOWN_ERROR;
-    return KM_ERROR_OK;
+    hidden->push_back(TAG_ROOT_OF_TRUST, reinterpret_cast<const uint8_t*>(root_of_trust_.data()),
+                      root_of_trust_.size());
+
+    return TranslateAuthorizationSetError(hidden->is_valid());
 }
 
 }  // namespace keymaster
diff --git a/soft_keymaster_device.cpp b/soft_keymaster_device.cpp
index e1d9090..9f3418e 100644
--- a/soft_keymaster_device.cpp
+++ b/soft_keymaster_device.cpp
@@ -48,7 +48,7 @@
             .module_api_version = KEYMASTER_MODULE_API_VERSION_1_0,
             .hal_api_version = HARDWARE_HAL_API_VERSION,
             .id = KEYSTORE_HARDWARE_MODULE_ID,
-            .name = "Keymaster OpenSSL HAL",
+            .name = "OpenSSL-based SoftKeymaster HAL",
             .author = "The Android Open Source Project",
             .methods = NULL,
             .dso = 0,
@@ -58,18 +58,61 @@
 
 namespace keymaster {
 
-SoftKeymasterDevice::SoftKeymasterDevice(keymaster0_device_t* keymaster0_device)
-    : wrapped_device_(keymaster0_device),
-      impl_(new AndroidKeymaster(new SoftKeymasterContext(keymaster0_device), 16)) {
-    initialize(keymaster0_device);
+const size_t kOperationTableSize = 16;
+
+typedef std::map<std::pair<keymaster_algorithm_t, keymaster_purpose_t>,
+                 std::vector<keymaster_digest_t>> DigestMap;
+
+template <typename T> std::vector<T> make_vector(const T* array, size_t len) {
+    return std::vector<T>(array, array + len);
 }
 
-SoftKeymasterDevice::SoftKeymasterDevice(KeymasterContext* context)
-    : impl_(new AndroidKeymaster(context, 16)) {
-    initialize(nullptr);
+static keymaster_error_t add_digests(keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
+                                     keymaster_purpose_t purpose, DigestMap* map) {
+    auto key = std::make_pair(algorithm, purpose);
+
+    keymaster_digest_t* digests;
+    size_t digests_length;
+    keymaster_error_t error =
+        dev->get_supported_digests(dev, algorithm, purpose, &digests, &digests_length);
+    if (error != KM_ERROR_OK) {
+        LOG_E("Error %d getting supported digests from keymaster1 device", error);
+        return error;
+    }
+    std::unique_ptr<keymaster_digest_t, Malloc_Delete> digests_deleter(digests);
+
+    (*map)[key] = make_vector(digests, digests_length);
+    return KM_ERROR_OK;
 }
 
-void SoftKeymasterDevice::initialize(keymaster0_device_t* keymaster0_device) {
+static keymaster_error_t map_digests(keymaster1_device_t* dev, DigestMap* map) {
+    map->clear();
+
+    keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC};
+    keymaster_purpose_t sig_purposes[] = {KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY};
+    for (auto algorithm : sig_algorithms)
+        for (auto purpose : sig_purposes) {
+            keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
+            if (error != KM_ERROR_OK)
+                return error;
+        }
+
+    keymaster_algorithm_t crypt_algorithms[] = {KM_ALGORITHM_RSA};
+    keymaster_purpose_t crypt_purposes[] = {KM_PURPOSE_ENCRYPT, KM_PURPOSE_DECRYPT};
+    for (auto algorithm : crypt_algorithms)
+        for (auto purpose : crypt_purposes) {
+            keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
+            if (error != KM_ERROR_OK)
+                return error;
+        }
+
+    return KM_ERROR_OK;
+}
+
+SoftKeymasterDevice::SoftKeymasterDevice()
+    : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr),
+      context_(new SoftKeymasterContext),
+      impl_(new AndroidKeymaster(context_, kOperationTableSize)) {
     static_assert(std::is_standard_layout<SoftKeymasterDevice>::value,
                   "SoftKeymasterDevice must be standard layout");
     static_assert(offsetof(SoftKeymasterDevice, device_) == 0,
@@ -79,6 +122,106 @@
     LOG_I("Creating device", 0);
     LOG_D("Device address: %p", this);
 
+    initialize_device_struct();
+}
+
+SoftKeymasterDevice::SoftKeymasterDevice(SoftKeymasterContext* context)
+    : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr), context_(context),
+      impl_(new AndroidKeymaster(context_, kOperationTableSize)) {
+    static_assert(std::is_standard_layout<SoftKeymasterDevice>::value,
+                  "SoftKeymasterDevice must be standard layout");
+    static_assert(offsetof(SoftKeymasterDevice, device_) == 0,
+                  "device_ must be the first member of SoftKeymasterDevice");
+    static_assert(offsetof(SoftKeymasterDevice, device_.common) == 0,
+                  "common must be the first member of keymaster_device");
+    LOG_I("Creating test device", 0);
+    LOG_D("Device address: %p", this);
+
+    initialize_device_struct();
+}
+
+keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster0_device_t* keymaster0_device) {
+    assert(keymaster0_device);
+    LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster0", 0);
+
+    if (!context_)
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+    keymaster_error_t error = context_->SetHardwareDevice(keymaster0_device);
+    if (error != KM_ERROR_OK)
+        return error;
+
+    initialize_device_struct();
+
+    module_name_ = device_.common.module->name;
+    module_name_.append("(Wrapping ");
+    module_name_.append(keymaster0_device->common.module->name);
+    module_name_.append(")");
+
+    updated_module_ = *device_.common.module;
+    updated_module_.name = module_name_.c_str();
+
+    device_.common.module = &updated_module_;
+
+    wrapped_km0_device_ = keymaster0_device;
+    wrapped_km1_device_ = nullptr;
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster1_device_t* keymaster1_device) {
+    assert(keymaster1_device);
+    LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster1", 0);
+
+    if (!context_)
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+    keymaster_error_t error = map_digests(keymaster1_device, &km1_device_digests_);
+    if (error != KM_ERROR_OK)
+        return error;
+
+    error = context_->SetHardwareDevice(keymaster1_device);
+    if (error != KM_ERROR_OK)
+        return error;
+
+    initialize_device_struct();
+
+    module_name_ = device_.common.module->name;
+    module_name_.append(" (Wrapping ");
+    module_name_.append(keymaster1_device->common.module->name);
+    module_name_.append(")");
+
+    updated_module_ = *device_.common.module;
+    updated_module_.name = module_name_.c_str();
+
+    device_.common.module = &updated_module_;
+
+    wrapped_km0_device_ = nullptr;
+    wrapped_km1_device_ = keymaster1_device;
+    return KM_ERROR_OK;
+}
+
+bool SoftKeymasterDevice::Keymaster1DeviceIsGood() {
+    std::vector<keymaster_digest_t> expected_rsa_digests = {
+        KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,     KM_DIGEST_SHA_2_224,
+        KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+    std::vector<keymaster_digest_t> expected_ec_digests = {
+        KM_DIGEST_NONE,      KM_DIGEST_SHA1,      KM_DIGEST_SHA_2_224,
+        KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+
+    for (auto& entry : km1_device_digests_) {
+        if (entry.first.first == KM_ALGORITHM_RSA)
+            if (!std::is_permutation(entry.second.begin(), entry.second.end(),
+                                     expected_rsa_digests.begin()))
+                return false;
+        if (entry.first.first == KM_ALGORITHM_EC)
+            if (!std::is_permutation(entry.second.begin(), entry.second.end(),
+                                     expected_ec_digests.begin()))
+                return false;
+    }
+    return true;
+}
+
+void SoftKeymasterDevice::initialize_device_struct() {
     memset(&device_, 0, sizeof(device_));
 
     device_.common.tag = HARDWARE_DEVICE_TAG;
@@ -87,28 +230,15 @@
     device_.common.close = &close_device;
 
     device_.flags = KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_EC;
-    if (keymaster0_device) {
-        device_.flags |= keymaster0_device->flags & KEYMASTER_SOFTWARE_ONLY;
-    } else {
-        device_.flags |= KEYMASTER_SOFTWARE_ONLY;
-    }
 
     // keymaster0 APIs
-    device_.generate_keypair = generate_keypair;
-    device_.import_keypair = import_keypair;
-    device_.get_keypair_public = get_keypair_public;
-    if (keymaster0_device && keymaster0_device->delete_keypair) {
-        device_.delete_keypair = delete_keypair;
-    } else {
-        device_.delete_keypair = nullptr;
-    }
-    if (keymaster0_device && keymaster0_device->delete_all) {
-        device_.delete_all = delete_all;
-    } else {
-        device_.delete_all = nullptr;
-    }
-    device_.sign_data = sign_data;
-    device_.verify_data = verify_data;
+    device_.generate_keypair = nullptr;
+    device_.import_keypair = nullptr;
+    device_.get_keypair_public = nullptr;
+    device_.delete_keypair = nullptr;
+    device_.delete_all = nullptr;
+    device_.sign_data = nullptr;
+    device_.verify_data = nullptr;
 
     // keymaster1 APIs
     device_.get_supported_algorithms = get_supported_algorithms;
@@ -175,295 +305,6 @@
 }
 
 /* static */
-int SoftKeymasterDevice::generate_keypair(const keymaster1_device_t* dev,
-                                          const keymaster_keypair_t key_type,
-                                          const void* key_params, uint8_t** key_blob,
-                                          size_t* key_blob_length) {
-    LOG_D("%s", "Device received generate_keypair");
-    if (!dev || !key_params)
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
-    if (!key_blob || !key_blob_length)
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
-    GenerateKeyRequest req;
-
-    switch (key_type) {
-    case TYPE_RSA: {
-        req.key_description.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
-        StoreDefaultNewKeyParams(KM_ALGORITHM_RSA, &req.key_description);
-        const keymaster_rsa_keygen_params_t* rsa_params =
-            static_cast<const keymaster_rsa_keygen_params_t*>(key_params);
-        LOG_D("Generating RSA pair, modulus size: %u, public exponent: %lu",
-              rsa_params->modulus_size, rsa_params->public_exponent);
-        req.key_description.push_back(TAG_KEY_SIZE, rsa_params->modulus_size);
-        req.key_description.push_back(TAG_RSA_PUBLIC_EXPONENT, rsa_params->public_exponent);
-        break;
-    }
-
-    case TYPE_EC: {
-        req.key_description.push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
-        StoreDefaultNewKeyParams(KM_ALGORITHM_EC, &req.key_description);
-        const keymaster_ec_keygen_params_t* ec_params =
-            static_cast<const keymaster_ec_keygen_params_t*>(key_params);
-        LOG_D("Generating ECDSA pair, key size: %u", ec_params->field_size);
-        req.key_description.push_back(TAG_KEY_SIZE, ec_params->field_size);
-        break;
-    }
-
-    default:
-        LOG_D("Received request for unsuported key type %d", key_type);
-        return KM_ERROR_UNSUPPORTED_ALGORITHM;
-    }
-
-    GenerateKeyResponse rsp;
-    convert_device(dev)->impl_->GenerateKey(req, &rsp);
-    if (rsp.error != KM_ERROR_OK) {
-        LOG_E("Key generation failed with error: %d", rsp.error);
-        return rsp.error;
-    }
-
-    *key_blob_length = rsp.key_blob.key_material_size;
-    *key_blob = static_cast<uint8_t*>(malloc(*key_blob_length));
-    if (!*key_blob) {
-        LOG_E("Failed to allocate %d bytes", *key_blob_length);
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-    memcpy(*key_blob, rsp.key_blob.key_material, *key_blob_length);
-    LOG_D("Returning %d bytes in key blob\n", (int)*key_blob_length);
-
-    return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::import_keypair(const keymaster1_device_t* dev, const uint8_t* key,
-                                        const size_t key_length, uint8_t** key_blob,
-                                        size_t* key_blob_length) {
-    LOG_D("Device received import_keypair", 0);
-
-    if (!dev || !key)
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
-    if (!key_blob || !key_blob_length)
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
-    ImportKeyRequest request;
-    keymaster_algorithm_t algorithm;
-    keymaster_error_t err = GetPkcs8KeyAlgorithm(key, key_length, &algorithm);
-    if (err != KM_ERROR_OK)
-        return err;
-    request.key_description.push_back(TAG_ALGORITHM, algorithm);
-    StoreDefaultNewKeyParams(algorithm, &request.key_description);
-    request.SetKeyMaterial(key, key_length);
-    request.key_format = KM_KEY_FORMAT_PKCS8;
-
-    ImportKeyResponse response;
-    convert_device(dev)->impl_->ImportKey(request, &response);
-    if (response.error != KM_ERROR_OK) {
-        LOG_E("Key import failed with error: %d", response.error);
-        return response.error;
-    }
-
-    *key_blob_length = response.key_blob.key_material_size;
-    *key_blob = static_cast<uint8_t*>(malloc(*key_blob_length));
-    if (!*key_blob) {
-        LOG_E("Failed to allocate %d bytes", *key_blob_length);
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-    memcpy(*key_blob, response.key_blob.key_material, *key_blob_length);
-    LOG_D("Returning %d bytes in key blob\n", (int)*key_blob_length);
-
-    return KM_ERROR_OK;
-}
-
-/* static */
-keymaster_error_t SoftKeymasterDevice::GetPkcs8KeyAlgorithm(const uint8_t* key, size_t key_length,
-                                                            keymaster_algorithm_t* algorithm) {
-    if (key == NULL) {
-        LOG_E("No key specified for import", 0);
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-
-    UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8(
-        d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
-    if (pkcs8.get() == NULL) {
-        LOG_E("Could not parse PKCS8 key blob", 0);
-        return KM_ERROR_INVALID_KEY_BLOB;
-    }
-
-    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKCS82PKEY(pkcs8.get()));
-    if (pkey.get() == NULL) {
-        LOG_E("Could not extract key from PKCS8 key blob", 0);
-        return KM_ERROR_INVALID_KEY_BLOB;
-    }
-
-    switch (EVP_PKEY_type(pkey->type)) {
-    case EVP_PKEY_RSA:
-        *algorithm = KM_ALGORITHM_RSA;
-        break;
-    case EVP_PKEY_EC:
-        *algorithm = KM_ALGORITHM_EC;
-        break;
-    default:
-        LOG_E("Unsupported algorithm %d", EVP_PKEY_type(pkey->type));
-        return KM_ERROR_UNSUPPORTED_ALGORITHM;
-    }
-
-    return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::get_keypair_public(const struct keymaster1_device* dev,
-                                            const uint8_t* key_blob, const size_t key_blob_length,
-                                            uint8_t** x509_data, size_t* x509_data_length) {
-    LOG_D("Device received get_keypair_public", 0);
-
-    if (!dev || !key_blob)
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
-    if (!x509_data || !x509_data_length)
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
-    ExportKeyRequest req;
-    req.SetKeyMaterial(key_blob, key_blob_length);
-    req.key_format = KM_KEY_FORMAT_X509;
-
-    ExportKeyResponse rsp;
-    convert_device(dev)->impl_->ExportKey(req, &rsp);
-    if (rsp.error != KM_ERROR_OK) {
-        LOG_E("get_keypair_public failed with error: %d", rsp.error);
-        return rsp.error;
-    }
-
-    *x509_data_length = rsp.key_data_length;
-    *x509_data = static_cast<uint8_t*>(malloc(*x509_data_length));
-    if (!*x509_data)
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    memcpy(*x509_data, rsp.key_data, *x509_data_length);
-    LOG_D("Returning %d bytes in x509 key\n", (int)*x509_data_length);
-
-    return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::delete_keypair(const struct keymaster1_device* dev,
-                                        const uint8_t* key_blob, const size_t key_blob_length) {
-    if (!dev || !dev->delete_keypair) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    return dev->delete_keypair(dev, key_blob, key_blob_length);
-}
-
-/* static */
-int SoftKeymasterDevice::delete_all(const struct keymaster1_device* dev) {
-    if (!dev || !dev->delete_all) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    return dev->delete_all(dev);
-}
-
-/* static */
-int SoftKeymasterDevice::sign_data(const keymaster1_device_t* dev, const void* params,
-                                   const uint8_t* key_blob, const size_t key_blob_length,
-                                   const uint8_t* data, const size_t data_length,
-                                   uint8_t** signed_data, size_t* signed_data_length) {
-    LOG_D("Device received sign_data", 0);
-
-    if (!dev || !params || !key_blob)
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
-    if (!signed_data || !signed_data_length)
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
-    *signed_data_length = 0;
-
-    BeginOperationRequest begin_request;
-    begin_request.purpose = KM_PURPOSE_SIGN;
-    begin_request.SetKeyMaterial(key_blob, key_blob_length);
-    begin_request.additional_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
-    begin_request.additional_params.push_back(TAG_PADDING, KM_PAD_NONE);
-
-    BeginOperationResponse begin_response;
-    convert_device(dev)->impl_->BeginOperation(begin_request, &begin_response);
-    if (begin_response.error != KM_ERROR_OK) {
-        LOG_E("sign_data begin operation failed with error: %d", begin_response.error);
-        return begin_response.error;
-    }
-
-    UpdateOperationRequest update_request;
-    update_request.op_handle = begin_response.op_handle;
-    update_request.input.Reinitialize(data, data_length);
-    UpdateOperationResponse update_response;
-    convert_device(dev)->impl_->UpdateOperation(update_request, &update_response);
-    if (update_response.error != KM_ERROR_OK) {
-        LOG_E("sign_data update operation failed with error: %d", update_response.error);
-        return update_response.error;
-    }
-
-    FinishOperationRequest finish_request;
-    finish_request.op_handle = begin_response.op_handle;
-    FinishOperationResponse finish_response;
-    convert_device(dev)->impl_->FinishOperation(finish_request, &finish_response);
-    if (finish_response.error != KM_ERROR_OK) {
-        LOG_E("sign_data finish operation failed with error: %d", finish_response.error);
-        return finish_response.error;
-    }
-
-    *signed_data_length = finish_response.output.available_read();
-    *signed_data = static_cast<uint8_t*>(malloc(*signed_data_length));
-    if (!*signed_data)
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    if (!finish_response.output.read(*signed_data, *signed_data_length))
-        return KM_ERROR_UNKNOWN_ERROR;
-    return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::verify_data(const keymaster1_device_t* dev, const void* params,
-                                     const uint8_t* key_blob, const size_t key_blob_length,
-                                     const uint8_t* signed_data, const size_t signed_data_length,
-                                     const uint8_t* signature, const size_t signature_length) {
-    LOG_D("Device received verify_data", 0);
-
-    if (!dev || !params || !key_blob || !signed_data || !signature)
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
-    BeginOperationRequest begin_request;
-    begin_request.purpose = KM_PURPOSE_VERIFY;
-    begin_request.SetKeyMaterial(key_blob, key_blob_length);
-    begin_request.additional_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
-    begin_request.additional_params.push_back(TAG_PADDING, KM_PAD_NONE);
-
-    BeginOperationResponse begin_response;
-    convert_device(dev)->impl_->BeginOperation(begin_request, &begin_response);
-    if (begin_response.error != KM_ERROR_OK) {
-        LOG_E("verify_data begin operation failed with error: %d", begin_response.error);
-        return begin_response.error;
-    }
-
-    UpdateOperationRequest update_request;
-    update_request.op_handle = begin_response.op_handle;
-    update_request.input.Reinitialize(signed_data, signed_data_length);
-    UpdateOperationResponse update_response;
-    convert_device(dev)->impl_->UpdateOperation(update_request, &update_response);
-    if (update_response.error != KM_ERROR_OK) {
-        LOG_E("verify_data update operation failed with error: %d", update_response.error);
-        return update_response.error;
-    }
-
-    FinishOperationRequest finish_request;
-    finish_request.op_handle = begin_response.op_handle;
-    finish_request.signature.Reinitialize(signature, signature_length);
-    FinishOperationResponse finish_response;
-    convert_device(dev)->impl_->FinishOperation(finish_request, &finish_response);
-    if (finish_response.error != KM_ERROR_OK) {
-        LOG_E("verify_data finish operation failed with error: %d", finish_response.error);
-        return finish_response.error;
-    }
-    return KM_ERROR_OK;
-}
-
-/* static */
 keymaster_error_t SoftKeymasterDevice::get_supported_algorithms(const keymaster1_device_t* dev,
                                                                 keymaster_algorithm_t** algorithms,
                                                                 size_t* algorithms_length) {
@@ -473,6 +314,10 @@
     if (!algorithms || !algorithms_length)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->get_supported_algorithms(km1_dev, algorithms, algorithms_length);
+
     SupportedAlgorithmsRequest request;
     SupportedAlgorithmsResponse response;
     convert_device(dev)->impl_->SupportedAlgorithms(request, &response);
@@ -503,6 +348,10 @@
     if (!modes || !modes_length)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->get_supported_block_modes(km1_dev, algorithm, purpose, modes, modes_length);
+
     SupportedBlockModesRequest request;
     request.algorithm = algorithm;
     request.purpose = purpose;
@@ -535,6 +384,11 @@
     if (!modes || !modes_length)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->get_supported_padding_modes(km1_dev, algorithm, purpose, modes,
+                                                    modes_length);
+
     SupportedPaddingModesRequest request;
     request.algorithm = algorithm;
     request.purpose = purpose;
@@ -566,6 +420,10 @@
     if (!digests || !digests_length)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->get_supported_digests(km1_dev, algorithm, purpose, digests, digests_length);
+
     SupportedDigestsRequest request;
     request.algorithm = algorithm;
     request.purpose = purpose;
@@ -595,6 +453,10 @@
     if (!formats || !formats_length)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->get_supported_import_formats(km1_dev, algorithm, formats, formats_length);
+
     SupportedImportFormatsRequest request;
     request.algorithm = algorithm;
     SupportedImportFormatsResponse response;
@@ -624,6 +486,10 @@
     if (!formats || !formats_length)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->get_supported_export_formats(km1_dev, algorithm, formats, formats_length);
+
     SupportedExportFormatsRequest request;
     request.algorithm = algorithm;
     SupportedExportFormatsResponse response;
@@ -649,6 +515,10 @@
     if (!dev)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->add_rng_entropy(km1_dev, data, data_length);
+
     AddEntropyRequest request;
     request.random_data.Reinitialize(data, data_length);
     AddEntropyResponse response;
@@ -658,6 +528,80 @@
     return response.error;
 }
 
+template <typename Collection, typename Value> bool contains(const Collection& c, const Value& v) {
+    return std::find(c.begin(), c.end(), v) != c.end();
+}
+
+bool SoftKeymasterDevice::FindUnsupportedDigest(keymaster_algorithm_t algorithm,
+                                                keymaster_purpose_t purpose,
+                                                const AuthorizationSet& params,
+                                                keymaster_digest_t* unsupported) const {
+    assert(wrapped_km1_device_);
+
+    auto supported_digests = km1_device_digests_.find(std::make_pair(algorithm, purpose));
+    if (supported_digests == km1_device_digests_.end())
+        // Invalid algorith/purpose pair (e.g. EC encrypt).  Let the error be handled by HW module.
+        return false;
+
+    for (auto& entry : params)
+        if (entry.tag == TAG_DIGEST)
+            if (!contains(supported_digests->second, entry.enumerated)) {
+                LOG_I("Digest %d requested but not supported by module %s", entry.enumerated,
+                      wrapped_km1_device_->common.module->name);
+                *unsupported = static_cast<keymaster_digest_t>(entry.enumerated);
+                return true;
+            }
+    return false;
+}
+
+bool SoftKeymasterDevice::RequiresSoftwareDigesting(keymaster_algorithm_t algorithm,
+                                                    keymaster_purpose_t purpose,
+                                                    const AuthorizationSet& params) const {
+    assert(wrapped_km1_device_);
+    if (!wrapped_km1_device_)
+        return true;
+
+    switch (algorithm) {
+    case KM_ALGORITHM_AES:
+    case KM_ALGORITHM_HMAC:
+        LOG_D("Not performing software digesting for algorithm %d", algorithm);
+        return false;
+    case KM_ALGORITHM_RSA:
+    case KM_ALGORITHM_EC:
+        break;
+    }
+
+    keymaster_digest_t unsupported;
+    if (!FindUnsupportedDigest(algorithm, purpose, params, &unsupported)) {
+        LOG_D("Requested digest(s) supported for algorithm %d and purpose %d", algorithm, purpose);
+        return false;
+    }
+
+    return true;
+}
+
+bool SoftKeymasterDevice::KeyRequiresSoftwareDigesting(
+    const AuthorizationSet& key_description) const {
+    assert(wrapped_km1_device_);
+    if (!wrapped_km1_device_)
+        return true;
+
+    keymaster_algorithm_t algorithm;
+    if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
+        // The hardware module will return an error during keygen.
+        return false;
+    }
+
+    for (auto& entry : key_description)
+        if (entry.tag == TAG_PURPOSE) {
+            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(entry.enumerated);
+            if (RequiresSoftwareDigesting(algorithm, purpose, key_description))
+                return true;
+        }
+
+    return false;
+}
+
 /* static */
 keymaster_error_t SoftKeymasterDevice::generate_key(
     const keymaster1_device_t* dev, const keymaster_key_param_set_t* params,
@@ -668,11 +612,17 @@
     if (!key_blob)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    SoftKeymasterDevice* sk_dev = convert_device(dev);
+
     GenerateKeyRequest request;
     request.key_description.Reinitialize(*params);
 
+    keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
+    if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description))
+        return km1_dev->generate_key(km1_dev, params, key_blob, characteristics);
+
     GenerateKeyResponse response;
-    convert_device(dev)->impl_->GenerateKey(request, &response);
+    sk_dev->impl_->GenerateKey(request, &response);
     if (response.error != KM_ERROR_OK)
         return response.error;
 
@@ -703,6 +653,11 @@
     if (!characteristics)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->get_key_characteristics(km1_dev, key_blob, client_id, app_data,
+                                                characteristics);
+
     GetKeyCharacteristicsRequest request;
     request.SetKeyMaterial(*key_blob);
     AddClientAndAppData(client_id, app_data, &request);
@@ -729,10 +684,18 @@
     if (!key_blob)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
-    *characteristics = nullptr;
+    SoftKeymasterDevice* sk_dev = convert_device(dev);
 
     ImportKeyRequest request;
     request.key_description.Reinitialize(*params);
+
+    keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
+    if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description))
+        return km1_dev->import_key(km1_dev, params, key_format, key_data, key_blob,
+                                   characteristics);
+
+    *characteristics = nullptr;
+
     request.key_format = key_format;
     request.SetKeyMaterial(key_data->data, key_data->data_length);
 
@@ -769,6 +732,11 @@
     if (!export_data)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev)
+        return km1_dev->export_key(km1_dev, export_format, key_to_export, client_id, app_data,
+                                   export_data);
+
     export_data->data = nullptr;
     export_data->data_length = 0;
 
@@ -797,11 +765,15 @@
     if (!dev || !key || !key->key_material)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
-    keymaster0_device_t* wrapped = convert_device(dev)->wrapped_device_;
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev && km1_dev->delete_key)
+        return km1_dev->delete_key(km1_dev, key);
 
-    if (wrapped && wrapped->delete_keypair)
-        if (wrapped->delete_keypair(wrapped, key->key_material, key->key_material_size) < 0)
+    const keymaster0_device_t* km0_dev = convert_device(dev)->wrapped_km0_device_;
+    if (km0_dev && km0_dev->delete_keypair)
+        if (km0_dev->delete_keypair(km0_dev, key->key_material, key->key_material_size) < 0)
             return KM_ERROR_UNKNOWN_ERROR;
+
     return KM_ERROR_OK;
 }
 
@@ -810,14 +782,58 @@
     if (!dev)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
-    keymaster0_device_t* wrapped = convert_device(dev)->wrapped_device_;
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev && km1_dev->delete_all_keys)
+        return km1_dev->delete_all_keys(km1_dev);
 
-    if (wrapped && wrapped->delete_all)
-        if (wrapped->delete_all(wrapped) < 0)
+    const keymaster0_device_t* km0_dev = convert_device(dev)->wrapped_km0_device_;
+    if (km0_dev && km0_dev->delete_all)
+        if (km0_dev->delete_all(km0_dev) < 0)
             return KM_ERROR_UNKNOWN_ERROR;
+
     return KM_ERROR_OK;
 }
 
+static bool FindAlgorithm(const keymaster_key_param_set_t& params,
+                          keymaster_algorithm_t* algorithm) {
+    for (size_t i = 0; i < params.length; ++i)
+        if (params.params[i].tag == KM_TAG_ALGORITHM) {
+            *algorithm = static_cast<keymaster_algorithm_t>(params.params[i].enumerated);
+            return true;
+        }
+    return false;
+}
+
+static keymaster_error_t GetAlgorithm(const keymaster1_device_t* dev,
+                                      const keymaster_key_blob_t& key,
+                                      const AuthorizationSet& in_params,
+                                      keymaster_algorithm_t* algorithm) {
+    keymaster_blob_t client_id = {nullptr, 0};
+    keymaster_blob_t app_data = {nullptr, 0};
+    keymaster_blob_t* client_id_ptr = nullptr;
+    keymaster_blob_t* app_data_ptr = nullptr;
+    if (in_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
+        client_id_ptr = &client_id;
+    if (in_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
+        app_data_ptr = &app_data;
+
+    keymaster_key_characteristics_t* characteristics;
+    keymaster_error_t error =
+        dev->get_key_characteristics(dev, &key, client_id_ptr, app_data_ptr, &characteristics);
+    if (error != KM_ERROR_OK)
+        return error;
+    std::unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete>
+        characteristics_deleter(characteristics);
+
+    if (FindAlgorithm(characteristics->hw_enforced, algorithm))
+        return KM_ERROR_OK;
+
+    if (FindAlgorithm(characteristics->sw_enforced, algorithm))
+        return KM_ERROR_OK;
+
+    return KM_ERROR_INVALID_KEY_BLOB;
+}
+
 /* static */
 keymaster_error_t SoftKeymasterDevice::begin(const keymaster1_device_t* dev,
                                              keymaster_purpose_t purpose,
@@ -828,11 +844,30 @@
     if (!key || !key->key_material)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
-    if (!operation_handle || !out_params)
+    if (!operation_handle)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
-    out_params->params = nullptr;
-    out_params->length = 0;
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev) {
+        AuthorizationSet in_params_set(*in_params);
+
+        keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+        keymaster_error_t error = GetAlgorithm(km1_dev, *key, in_params_set, &algorithm);
+        if (error != KM_ERROR_OK)
+            return error;
+
+        if (!convert_device(dev)->RequiresSoftwareDigesting(algorithm, purpose, in_params_set)) {
+            LOG_D("Operation supported by %s, passing through to keymaster1 module",
+                  km1_dev->common.module->name);
+            return km1_dev->begin(km1_dev, purpose, key, in_params, out_params, operation_handle);
+        }
+        LOG_I("Doing software digesting for keymaster1 module %s", km1_dev->common.module->name);
+    }
+
+    if (out_params) {
+        out_params->params = nullptr;
+        out_params->length = 0;
+    }
 
     BeginOperationRequest request;
     request.purpose = purpose;
@@ -844,8 +879,12 @@
     if (response.error != KM_ERROR_OK)
         return response.error;
 
-    if (response.output_params.size() > 0)
-        response.output_params.CopyToParamSet(out_params);
+    if (response.output_params.size() > 0) {
+        if (out_params)
+            response.output_params.CopyToParamSet(out_params);
+        else
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
 
     *operation_handle = response.op_handle;
     return KM_ERROR_OK;
@@ -861,13 +900,26 @@
     if (!input)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
-    if (!input_consumed || !output || !out_params)
+    if (!input_consumed)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
-    out_params->params = nullptr;
-    out_params->length = 0;
-    output->data = nullptr;
-    output->data_length = 0;
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
+        // This operation is being handled by km1_dev (or doesn't exist).  Pass it through to
+        // km1_dev.  Otherwise, we'll use the software AndroidKeymaster, which may delegate to
+        // km1_dev after doing necessary digesting.
+        return km1_dev->update(km1_dev, operation_handle, in_params, input, input_consumed,
+                               out_params, output);
+    }
+
+    if (out_params) {
+        out_params->params = nullptr;
+        out_params->length = 0;
+    }
+    if (output) {
+        output->data = nullptr;
+        output->data_length = 0;
+    }
 
     UpdateOperationRequest request;
     request.op_handle = operation_handle;
@@ -881,16 +933,24 @@
     if (response.error != KM_ERROR_OK)
         return response.error;
 
-    if (response.output_params.size() > 0)
-        response.output_params.CopyToParamSet(out_params);
+    if (response.output_params.size() > 0) {
+        if (out_params)
+            response.output_params.CopyToParamSet(out_params);
+        else
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
 
     *input_consumed = response.input_consumed;
-    output->data_length = response.output.available_read();
-    uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
-    if (!tmp)
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    memcpy(tmp, response.output.peek_read(), output->data_length);
-    output->data = tmp;
+    if (output) {
+        output->data_length = response.output.available_read();
+        uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
+        if (!tmp)
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        memcpy(tmp, response.output.peek_read(), output->data_length);
+        output->data = tmp;
+    } else if (response.output.available_read() > 0) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
     return KM_ERROR_OK;
 }
 
@@ -901,17 +961,27 @@
                                               const keymaster_blob_t* signature,
                                               keymaster_key_param_set_t* out_params,
                                               keymaster_blob_t* output) {
-    if (!output || !out_params)
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
+        // This operation is being handled by km1_dev (or doesn't exist).  Pass it through to
+        // km1_dev.  Otherwise, we'll use the software AndroidKeymaster, which may delegate to
+        // km1_dev after doing necessary digesting.
+        return km1_dev->finish(km1_dev, operation_handle, params, signature, out_params, output);
+    }
 
-    out_params->params = nullptr;
-    out_params->length = 0;
-    output->data = nullptr;
-    output->data_length = 0;
+    if (out_params) {
+        out_params->params = nullptr;
+        out_params->length = 0;
+    }
+
+    if (output) {
+        output->data = nullptr;
+        output->data_length = 0;
+    }
 
     FinishOperationRequest request;
     request.op_handle = operation_handle;
-    if (signature)
+    if (signature && signature->data_length > 0)
         request.signature.Reinitialize(signature->data, signature->data_length);
     request.additional_params.Reinitialize(*params);
 
@@ -920,22 +990,37 @@
     if (response.error != KM_ERROR_OK)
         return response.error;
 
-    if (response.output_params.size() > 0)
-        response.output_params.CopyToParamSet(out_params);
-    else
-
+    if (response.output_params.size() > 0) {
+        if (out_params)
+            response.output_params.CopyToParamSet(out_params);
+        else
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+    if (output) {
         output->data_length = response.output.available_read();
-    uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
-    if (!tmp)
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    memcpy(tmp, response.output.peek_read(), output->data_length);
-    output->data = tmp;
+        uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
+        if (!tmp)
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        memcpy(tmp, response.output.peek_read(), output->data_length);
+        output->data = tmp;
+    } else if (response.output.available_read() > 0) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
     return KM_ERROR_OK;
 }
 
 /* static */
 keymaster_error_t SoftKeymasterDevice::abort(const keymaster1_device_t* dev,
                                              keymaster_operation_handle_t operation_handle) {
+    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
+        // This operation is being handled by km1_dev (or doesn't exist).  Pass it through to
+        // km1_dev.  Otherwise, we'll use the software AndroidKeymaster, which may delegate to
+        // km1_dev.
+        return km1_dev->abort(km1_dev, operation_handle);
+    }
+
     AbortOperationRequest request;
     request.op_handle = operation_handle;
     AbortOperationResponse response;