Delegate ECDSA keys to keymaster0 in SoftKeymasterDevice.

Cherry-picked from internal

Bug: 20912868
Change-Id: Idd4057481fbec975d5d59e2b31c912f8edad1ed9
diff --git a/Android.mk b/Android.mk
index 3e16449..de43d86 100644
--- a/Android.mk
+++ b/Android.mk
@@ -87,6 +87,7 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libsoftkeymasterdevice
 LOCAL_SRC_FILES := \
+	ec_keymaster0_key.cpp \
 	keymaster0_engine.cpp \
 	rsa_keymaster0_key.cpp \
 	soft_keymaster_context.cpp \
diff --git a/Makefile b/Makefile
index bdbd2c7..c0b6500 100644
--- a/Makefile
+++ b/Makefile
@@ -70,6 +70,7 @@
 	authorization_set.cpp \
 	authorization_set_test.cpp \
 	ec_key.cpp \
+	ec_keymaster0_key.cpp \
 	ecdsa_operation.cpp \
 	gtest_main.cpp \
 	hkdf.cpp \
@@ -215,6 +216,7 @@
 	auth_encrypted_key_blob.o \
 	authorization_set.o \
 	ec_key.o \
+	ec_keymaster0_key.o \
 	ecdsa_operation.o \
 	hmac_key.o \
 	hmac_operation.o \
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index f68733b..5a4cba7 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -51,22 +51,29 @@
         return device->keymaster_device();
     }
 
-    bool crypto_params_in_hardware(keymaster_algorithm_t) const override { return false; }
-    bool expect_keymaster0_calls() const override { return false; }
+    bool algorithm_in_hardware(keymaster_algorithm_t) const override { return false; }
     int keymaster0_calls() const override { return 0; }
 };
 
 class Keymaster0AdapterTestInstanceCreator : public Keymaster1TestInstanceCreator {
   public:
+    Keymaster0AdapterTestInstanceCreator(bool support_ec) : support_ec_(support_ec) {}
+
     keymaster1_device_t* CreateDevice() const {
-        std::cerr << "Creating keymaster0-backed device" << std::endl;
+        std::cerr << "Creating keymaster0-backed device (with ec: " << std::boolalpha << support_ec_
+                  << ")." << std::endl;
         hw_device_t* softkeymaster_device;
         EXPECT_EQ(0, openssl_open(&softkeymaster_module.common, KEYSTORE_KEYMASTER,
                                   &softkeymaster_device));
         // Make the software device pretend to be hardware
         keymaster0_device_t* keymaster0_device =
             reinterpret_cast<keymaster0_device_t*>(softkeymaster_device);
-        keymaster0_device->flags = KEYMASTER_SUPPORTS_EC;
+        keymaster0_device->flags &= ~KEYMASTER_SOFTWARE_ONLY;
+
+        if (!support_ec_) {
+            // Make the software device pretend not to support EC
+            keymaster0_device->flags &= ~KEYMASTER_SUPPORTS_EC;
+        }
 
         counting_keymaster0_device_ = new Keymaster0CountingWrapper(keymaster0_device);
 
@@ -74,19 +81,27 @@
         return keymaster->keymaster_device();
     }
 
-    bool crypto_params_in_hardware(keymaster_algorithm_t algorithm) const override {
-        return algorithm == KM_ALGORITHM_RSA;
+    bool algorithm_in_hardware(keymaster_algorithm_t algorithm) const override {
+        switch (algorithm) {
+        case KM_ALGORITHM_RSA:
+            return true;
+        case KM_ALGORITHM_EC:
+            return support_ec_;
+        default:
+            return false;
+        }
     }
-    bool expect_keymaster0_calls() const override { return true; }
     int keymaster0_calls() const override { return counting_keymaster0_device_->count(); }
 
   private:
     mutable Keymaster0CountingWrapper* counting_keymaster0_device_;
+    bool support_ec_;
 };
 
-static auto test_params =
-    testing::Values(InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
-                    InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator));
+static auto test_params = testing::Values(
+    InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
+    InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
+    InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)));
 
 typedef Keymaster1Test CheckSupported;
 INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, CheckSupported, test_params);
@@ -102,8 +117,7 @@
         {KM_ALGORITHM_RSA, KM_ALGORITHM_EC, KM_ALGORITHM_AES, KM_ALGORITHM_HMAC}, algorithms, len));
     free(algorithms);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(CheckSupported, SupportedBlockModes) {
@@ -127,8 +141,7 @@
     EXPECT_TRUE(ResponseContains({KM_MODE_ECB, KM_MODE_CBC, KM_MODE_CTR}, modes, len));
     free(modes);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(CheckSupported, SupportedPaddingModes) {
@@ -158,8 +171,7 @@
               device()->get_supported_padding_modes(device(), KM_ALGORITHM_AES, KM_PURPOSE_SIGN,
                                                     &modes, &len));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(CheckSupported, SupportedDigests) {
@@ -190,8 +202,7 @@
                                  digests, len));
     free(digests);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(CheckSupported, SupportedImportFormats) {
@@ -215,8 +226,7 @@
     EXPECT_TRUE(ResponseContains(KM_KEY_FORMAT_RAW, formats, len));
     free(formats);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(CheckSupported, SupportedExportFormats) {
@@ -250,8 +260,7 @@
     EXPECT_EQ(0U, len);
     free(formats);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 class NewKeyGeneration : public Keymaster1Test {
@@ -293,7 +302,7 @@
     // Check specified tags are all present, and in the right set.
     AuthorizationSet crypto_params;
     AuthorizationSet non_crypto_params;
-    if (GetParam()->crypto_params_in_hardware(KM_ALGORITHM_RSA)) {
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA)) {
         EXPECT_NE(0U, hw_enforced().size());
         EXPECT_NE(0U, sw_enforced().size());
         crypto_params.push_back(hw_enforced());
@@ -311,7 +320,7 @@
     EXPECT_TRUE(contains(crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
     EXPECT_FALSE(contains(non_crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
@@ -322,8 +331,7 @@
                               .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3)
                               .SigningKey()));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(NewKeyGeneration, Ecdsa) {
@@ -331,12 +339,27 @@
               GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(KM_DIGEST_NONE)));
     CheckBaseParams();
 
-    // Check specified tags are all present in unenforced characteristics
-    EXPECT_TRUE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_EC));
-    EXPECT_TRUE(contains(sw_enforced(), TAG_KEY_SIZE, 224));
+    // 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)) {
+        EXPECT_NE(0U, hw_enforced().size());
+        EXPECT_NE(0U, sw_enforced().size());
+        crypto_params.push_back(hw_enforced());
+        non_crypto_params.push_back(sw_enforced());
+    } else {
+        EXPECT_EQ(0U, hw_enforced().size());
+        EXPECT_NE(0U, sw_enforced().size());
+        crypto_params.push_back(sw_enforced());
+    }
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_TRUE(contains(crypto_params, TAG_ALGORITHM, KM_ALGORITHM_EC));
+    EXPECT_FALSE(contains(non_crypto_params, TAG_ALGORITHM, KM_ALGORITHM_EC));
+    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))
+        EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
 TEST_P(NewKeyGeneration, EcdsaDefaultSize) {
@@ -346,16 +369,21 @@
                               .SigningKey()
                               .Digest(KM_DIGEST_NONE)));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(NewKeyGeneration, EcdsaInvalidSize) {
-    ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE,
-              GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        ASSERT_EQ(
+            KM_ERROR_UNKNOWN_ERROR,
+            GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
+    else
+        ASSERT_EQ(
+            KM_ERROR_UNSUPPORTED_KEY_SIZE,
+            GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
 TEST_P(NewKeyGeneration, EcdsaAllValidSizes) {
@@ -367,16 +395,15 @@
             << size;
     }
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
 TEST_P(NewKeyGeneration, HmacSha256) {
     ASSERT_EQ(KM_ERROR_OK,
               GenerateKey(AuthorizationSetBuilder().HmacKey(128).Digest(KM_DIGEST_SHA_2_256)));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 typedef Keymaster1Test GetKeyCharacteristics;
@@ -392,7 +419,7 @@
     ASSERT_EQ(KM_ERROR_OK, GetCharacteristics());
     EXPECT_EQ(original, sw_enforced());
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(1, GetParam()->keymaster0_calls());
 }
 
@@ -408,7 +435,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -421,7 +448,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -435,7 +462,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -448,7 +475,7 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -473,7 +500,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, FinishOperation(signature, &result));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -490,7 +517,7 @@
     // Another abort should fail
     EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, AbortOperation());
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -501,7 +528,7 @@
                     .Padding(KM_PAD_RSA_PSS /* supported padding */));
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_DIGEST, BeginOperation(KM_PURPOSE_SIGN));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -514,7 +541,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()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -529,7 +556,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()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -541,7 +568,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()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -566,7 +593,7 @@
     ASSERT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&signature));
     EXPECT_EQ(0U, signature.length());
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -578,7 +605,7 @@
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_SIGN));
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_VERIFY));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -589,8 +616,8 @@
     string signature;
     SignMessage(message, &signature, KM_DIGEST_NONE);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, AesEcbSign) {
@@ -600,8 +627,7 @@
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_SIGN));
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_VERIFY));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacSha1Success) {
@@ -611,8 +637,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA1, 160);
     ASSERT_EQ(20U, signature.size());
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacSha224Success) {
@@ -623,8 +648,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_224, 224);
     ASSERT_EQ(28U, signature.size());
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacSha256Success) {
@@ -635,8 +659,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_256, 256);
     ASSERT_EQ(32U, signature.size());
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacSha384Success) {
@@ -648,8 +671,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_384, 384);
     ASSERT_EQ(48U, signature.size());
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacSha512Success) {
@@ -660,8 +682,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_512, 512);
     ASSERT_EQ(64U, signature.size());
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacLengthInKey) {
@@ -676,8 +697,7 @@
     // Size in key was ignored.
     ASSERT_EQ(30U, signature.size());
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase1) {
@@ -716,8 +736,7 @@
     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()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase2) {
@@ -751,8 +770,7 @@
     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()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) {
@@ -786,8 +804,7 @@
     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()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase4) {
@@ -825,8 +842,7 @@
     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()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase5) {
@@ -855,8 +871,7 @@
     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()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase6) {
@@ -891,8 +906,7 @@
     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()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase7) {
@@ -929,8 +943,7 @@
     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()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(SigningOperationsTest, HmacSha256TooLargeMacLength) {
@@ -947,8 +960,7 @@
     ASSERT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_MAC_LENGTH, FinishOperation(&result));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 // TODO(swillden): Add more verification failure tests.
@@ -966,7 +978,7 @@
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -980,7 +992,7 @@
     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()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1005,7 +1017,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1020,7 +1032,7 @@
     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()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1045,7 +1057,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1071,7 +1083,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1085,7 +1097,7 @@
     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()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1110,7 +1122,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1136,7 +1148,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1217,7 +1229,7 @@
     free(padding_modes);
     free(digests);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(16, GetParam()->keymaster0_calls());
 }
 
@@ -1229,8 +1241,8 @@
     SignMessage(message, &signature, KM_DIGEST_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
 TEST_P(VerificationOperationsTest, HmacSha1Success) {
@@ -1240,8 +1252,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA1, 160);
     VerifyMessage(message, signature, KM_DIGEST_SHA1);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(VerificationOperationsTest, HmacSha224Success) {
@@ -1251,8 +1262,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_224, 224);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_224);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(VerificationOperationsTest, HmacSha256Success) {
@@ -1262,8 +1272,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_256, 256);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(VerificationOperationsTest, HmacSha384Success) {
@@ -1273,8 +1282,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_384, 384);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_384);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(VerificationOperationsTest, HmacSha512Success) {
@@ -1284,8 +1292,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_512, 512);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_512);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 typedef Keymaster1Test ExportKeyTest;
@@ -1302,7 +1309,7 @@
 
     // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1315,8 +1322,8 @@
 
     // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
 TEST_P(ExportKeyTest, RsaUnsupportedKeyFormat) {
@@ -1327,7 +1334,7 @@
     string export_data;
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1340,7 +1347,7 @@
     string export_data;
     ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, ExportKey(KM_KEY_FORMAT_X509, &export_data));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1352,8 +1359,7 @@
     EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
     EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_RAW, &export_data));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 static string read_file(const string& file_name) {
@@ -1377,14 +1383,14 @@
                                      KM_KEY_FORMAT_PKCS8, pk8_key));
 
     // Check values derived from the key.
-    EXPECT_TRUE(contains(GetParam()->crypto_params_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
-                                                                                 : sw_enforced(),
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+                                                                             : sw_enforced(),
                          TAG_ALGORITHM, KM_ALGORITHM_RSA));
-    EXPECT_TRUE(contains(GetParam()->crypto_params_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
-                                                                                 : sw_enforced(),
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+                                                                             : sw_enforced(),
                          TAG_KEY_SIZE, 1024));
-    EXPECT_TRUE(contains(GetParam()->crypto_params_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
-                                                                                 : sw_enforced(),
+    EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+                                                                             : sw_enforced(),
                          TAG_RSA_PUBLIC_EXPONENT, 65537U));
 
     // And values provided by AndroidKeymaster
@@ -1396,7 +1402,7 @@
     SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1424,7 +1430,7 @@
     ProcessMessage(KM_PURPOSE_VERIFY, message, signature, begin_params, update_params,
                    &output_params);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1438,8 +1444,7 @@
                             .Padding(KM_PAD_NONE),
                         KM_KEY_FORMAT_PKCS8, pk8_key));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(ImportKeyTest, RsaPublicExponenMismatch) {
@@ -1452,8 +1457,7 @@
                             .Padding(KM_PAD_NONE),
                         KM_KEY_FORMAT_PKCS8, pk8_key));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(ImportKeyTest, EcdsaSuccess) {
@@ -1465,8 +1469,12 @@
                         KM_KEY_FORMAT_PKCS8, pk8_key));
 
     // Check values derived from the key.
-    EXPECT_TRUE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_EC));
-    EXPECT_TRUE(contains(sw_enforced(), TAG_KEY_SIZE, 256));
+    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));
 
     // And values provided by AndroidKeymaster
     EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1477,8 +1485,8 @@
     SignMessage(message, &signature, KM_DIGEST_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
 TEST_P(ImportKeyTest, EcdsaSizeSpecified) {
@@ -1490,8 +1498,12 @@
                         KM_KEY_FORMAT_PKCS8, pk8_key));
 
     // Check values derived from the key.
-    EXPECT_TRUE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_EC));
-    EXPECT_TRUE(contains(sw_enforced(), TAG_KEY_SIZE, 256));
+    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));
 
     // And values provided by AndroidKeymaster
     EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1502,8 +1514,8 @@
     SignMessage(message, &signature, KM_DIGEST_NONE);
     VerifyMessage(message, signature, KM_DIGEST_NONE);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
 TEST_P(ImportKeyTest, EcdsaSizeMismatch) {
@@ -1515,8 +1527,7 @@
                             .Digest(KM_DIGEST_NONE),
                         KM_KEY_FORMAT_PKCS8, pk8_key));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(ImportKeyTest, AesKeySuccess) {
@@ -1535,8 +1546,7 @@
     string plaintext = DecryptMessage(ciphertext, KM_MODE_ECB, KM_PAD_PKCS7);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(ImportKeyTest, HmacSha256KeySuccess) {
@@ -1556,8 +1566,7 @@
     MacMessage(message, &signature, KM_DIGEST_SHA_2_256, 32);
     VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 typedef Keymaster1Test EncryptionOperationsTest;
@@ -1577,7 +1586,7 @@
     // OAEP randomizes padding so every result should be different.
     EXPECT_NE(ciphertext1, ciphertext2);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -1591,7 +1600,7 @@
     string plaintext = DecryptMessage(ciphertext, KM_PAD_RSA_OAEP);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1609,7 +1618,7 @@
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1632,7 +1641,7 @@
     EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1649,7 +1658,7 @@
     // PKCS1 v1.5 randomizes padding so every result should be different.
     EXPECT_NE(ciphertext1, ciphertext2);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -1663,7 +1672,7 @@
     string plaintext = DecryptMessage(ciphertext, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1681,7 +1690,7 @@
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
 }
 
@@ -1704,7 +1713,7 @@
     EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
     EXPECT_EQ(0U, result.size());
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
@@ -1716,7 +1725,7 @@
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
 
-    if (GetParam()->expect_keymaster0_calls())
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
@@ -1726,8 +1735,8 @@
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, HmacEncrypt) {
@@ -1738,8 +1747,7 @@
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
     ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesEcbRoundTripSuccess) {
@@ -1761,8 +1769,7 @@
     string plaintext = DecryptMessage(ciphertext1, KM_MODE_ECB, KM_PAD_NONE);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesEcbNoPaddingWrongInputSize) {
@@ -1783,8 +1790,7 @@
     EXPECT_EQ(message.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&ciphertext));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesEcbPkcs7Padding) {
@@ -1802,8 +1808,7 @@
         EXPECT_EQ(message, plaintext);
     }
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesEcbPkcs7PaddingCorrupted) {
@@ -1828,8 +1833,7 @@
     EXPECT_EQ(ciphertext.size(), input_consumed);
     EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&plaintext));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
@@ -1855,8 +1859,7 @@
     string plaintext = DecryptMessage(ciphertext1, KM_MODE_CTR, KM_PAD_NONE, iv1);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
@@ -1897,8 +1900,7 @@
     EXPECT_EQ(ciphertext.size(), plaintext.size());
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 struct AesCtrSp80038aTestVector {
@@ -1948,8 +1950,7 @@
         CheckAesCtrTestVector(key, nonce, plaintext, ciphertext);
     }
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCtrInvalidPaddingMode) {
@@ -1962,8 +1963,7 @@
     begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
     EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCtrInvalidCallerNonce) {
@@ -1979,8 +1979,7 @@
     input_params.push_back(TAG_NONCE, "123", 3);
     EXPECT_EQ(KM_ERROR_INVALID_NONCE, BeginOperation(KM_PURPOSE_ENCRYPT, input_params));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCbcRoundTripSuccess) {
@@ -2005,8 +2004,7 @@
     string plaintext = DecryptMessage(ciphertext1, KM_MODE_CBC, KM_PAD_NONE, iv1);
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCallerNonce) {
@@ -2049,8 +2047,7 @@
                                &output_params);
     EXPECT_NE(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCallerNonceProhibited) {
@@ -2080,8 +2077,7 @@
     EXPECT_EQ(KM_ERROR_CALLER_NONCE_PROHIBITED,
               BeginOperation(KM_PURPOSE_ENCRYPT, input_params, &output_params));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCbcIncrementalNoPadding) {
@@ -2122,8 +2118,7 @@
     EXPECT_EQ(ciphertext.size(), plaintext.size());
     EXPECT_EQ(message, plaintext);
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 TEST_P(EncryptionOperationsTest, AesCbcPkcs7Padding) {
@@ -2142,8 +2137,7 @@
         EXPECT_EQ(message, plaintext);
     }
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 typedef Keymaster1Test AddEntropyTest;
@@ -2155,16 +2149,17 @@
     EXPECT_EQ(KM_ERROR_OK,
               device()->add_rng_entropy(device(), reinterpret_cast<const uint8_t*>("foo"), 3));
 
-    if (GetParam()->expect_keymaster0_calls())
-        EXPECT_EQ(0, GetParam()->keymaster0_calls());
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 typedef Keymaster1Test Keymaster0AdapterTest;
 INSTANTIATE_TEST_CASE_P(
     AndroidKeymasterTest, Keymaster0AdapterTest,
-    ::testing::Values(InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator)));
+    ::testing::Values(
+        InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
+        InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */))));
 
-TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster1Blob) {
+TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster1RsaBlob) {
     // Load and use an old-style Keymaster1 software key blob.  These blobs contain OCB-encrypted
     // key data.
     string km1_sw = read_file("km1_sw_rsa_512.blob");
@@ -2181,11 +2176,28 @@
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
+TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster1EcdsaBlob) {
+    // Load and use an old-style Keymaster1 software key blob.  These blobs contain OCB-encrypted
+    // key data.
+    string km1_sw = read_file("km1_sw_ecdsa_256.blob");
+    EXPECT_EQ(270U, km1_sw.length());
+
+    uint8_t* key_data = reinterpret_cast<uint8_t*>(malloc(km1_sw.length()));
+    memcpy(key_data, km1_sw.data(), km1_sw.length());
+    set_key_blob(key_data, km1_sw.length());
+
+    string message(64, 'a');
+    string signature;
+    SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
+
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
+}
+
 struct Malloc_Delete {
     void operator()(void* p) { free(p); }
 };
 
-TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster0Blob) {
+TEST_P(Keymaster0AdapterTest, OldSoftwareKeymaster0RsaBlob) {
     // Load and use an old softkeymaster blob.  These blobs contain PKCS#8 key data.
     string km0_sw = read_file("km0_sw_rsa_512.blob");
     EXPECT_EQ(333U, km0_sw.length());
diff --git a/android_keymaster_test_utils.h b/android_keymaster_test_utils.h
index 19b272a..ede14f5 100644
--- a/android_keymaster_test_utils.h
+++ b/android_keymaster_test_utils.h
@@ -157,8 +157,7 @@
     virtual ~Keymaster1TestInstanceCreator(){};
     virtual keymaster1_device_t* CreateDevice() const = 0;
 
-    virtual bool crypto_params_in_hardware(keymaster_algorithm_t algorithm) const = 0;
-    virtual bool expect_keymaster0_calls() const = 0;
+    virtual bool algorithm_in_hardware(keymaster_algorithm_t algorithm) const = 0;
     virtual int keymaster0_calls() const = 0;
 };
 
diff --git a/ec_key.cpp b/ec_key.cpp
index 4deb1c0..0cd3fa0 100644
--- a/ec_key.cpp
+++ b/ec_key.cpp
@@ -44,7 +44,7 @@
         return KM_ERROR_UNSUPPORTED_KEY_SIZE;
     }
 
-    UniquePtr<EC_KEY, EcKey::EC_Delete> ec_key(EC_KEY_new());
+    UniquePtr<EC_KEY, EC_Delete> ec_key(EC_KEY_new());
     UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
     if (ec_key.get() == NULL || pkey.get() == NULL)
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
@@ -86,43 +86,54 @@
     if (!output_key_blob || !hw_enforced || !sw_enforced)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
-    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey;
-    keymaster_error_t error =
-        KeyMaterialToEvpKey(input_key_material_format, input_key_material, &pkey);
+    AuthorizationSet authorizations;
+    uint32_t key_size;
+    keymaster_error_t error = UpdateImportKeyDescription(
+        key_description, input_key_material_format, input_key_material, &authorizations, &key_size);
     if (error != KM_ERROR_OK)
         return error;
 
-    UniquePtr<EC_KEY, EcKey::EC_Delete> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
+    return context_->CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, input_key_material,
+                                   output_key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t EcKeyFactory::UpdateImportKeyDescription(const AuthorizationSet& key_description,
+                                                           keymaster_key_format_t key_format,
+                                                           const KeymasterKeyBlob& key_material,
+                                                           AuthorizationSet* updated_description,
+                                                           uint32_t* key_size_bits) {
+    if (!updated_description || !key_size_bits)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey;
+    keymaster_error_t error = KeyMaterialToEvpKey(key_format, key_material, &pkey);
+    if (error != KM_ERROR_OK)
+        return error;
+
+    UniquePtr<EC_KEY, EC_Delete> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
     if (!ec_key.get())
         return TranslateLastOpenSslError();
 
-    AuthorizationSet authorizations(key_description);
+    updated_description->Reinitialize(key_description);
 
     size_t extracted_key_size_bits;
     error = get_group_size(*EC_KEY_get0_group(ec_key.get()), &extracted_key_size_bits);
     if (error != KM_ERROR_OK)
         return error;
 
-    uint32_t key_size_bits;
-    if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size_bits)) {
-        // key_size_bits specified, make sure it matches the key.
-        if (key_size_bits != extracted_key_size_bits)
-            return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
-    } else {
-        // key_size_bits not specified, add it.
-        authorizations.push_back(TAG_KEY_SIZE, extracted_key_size_bits);
-    }
+    *key_size_bits = extracted_key_size_bits;
+    if (!updated_description->GetTagValue(TAG_KEY_SIZE, key_size_bits))
+        updated_description->push_back(TAG_KEY_SIZE, extracted_key_size_bits);
+    if (*key_size_bits != extracted_key_size_bits)
+        return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
 
-    keymaster_algorithm_t algorithm;
-    if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
-        if (algorithm != registry_key())
-            return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
-    } else {
-        authorizations.push_back(TAG_ALGORITHM, registry_key());
-    }
+    keymaster_algorithm_t algorithm = KM_ALGORITHM_EC;
+    if (!updated_description->GetTagValue(TAG_ALGORITHM, &algorithm))
+        updated_description->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
+    if (algorithm != KM_ALGORITHM_EC)
+        return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
 
-    return context_->CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, input_key_material,
-                                   output_key_blob, hw_enforced, sw_enforced);
+    return KM_ERROR_OK;
 }
 
 /* static */
diff --git a/ec_key.h b/ec_key.h
index e3e15f6..f6a53f8 100644
--- a/ec_key.h
+++ b/ec_key.h
@@ -40,13 +40,15 @@
                                      const AuthorizationSet& sw_enforced,
                                      UniquePtr<AsymmetricKey>* key) override;
 
+    keymaster_error_t UpdateImportKeyDescription(const AuthorizationSet& key_description,
+                                                 keymaster_key_format_t key_format,
+                                                 const KeymasterKeyBlob& key_material,
+                                                 AuthorizationSet* updated_description,
+                                                 uint32_t* key_size);
+
   private:
     static EC_GROUP* choose_group(size_t key_size_bits);
     static keymaster_error_t get_group_size(const EC_GROUP& group, size_t* key_size_bits);
-
-    struct EC_GROUP_Delete {
-        void operator()(EC_GROUP* p) { EC_GROUP_free(p); }
-    };
 };
 
 class EcdsaKeyFactory : public EcKeyFactory {
@@ -68,12 +70,14 @@
     bool InternalToEvp(EVP_PKEY* pkey) const override;
     bool EvpToInternal(const EVP_PKEY* pkey) override;
 
-    struct EC_Delete {
-        void operator()(EC_KEY* p) { EC_KEY_free(p); }
-    };
-
     EC_KEY* key() const { return EC_KEY_dup(ec_key_.get()); }
 
+  protected:
+    EcKey(EC_KEY* ec_key, const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced,
+          keymaster_error_t* error)
+        : AsymmetricKey(hw_enforced, sw_enforced, error), ec_key_(ec_key) {}
+
+  private:
     UniquePtr<EC_KEY, EC_Delete> ec_key_;
 };
 
diff --git a/ec_keymaster0_key.cpp b/ec_keymaster0_key.cpp
new file mode 100644
index 0000000..d171d58
--- /dev/null
+++ b/ec_keymaster0_key.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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_keymaster0_key.h"
+
+#include <memory>
+
+#define LOG_TAG "EcKeymaster0Key"
+#include <cutils/log.h>
+
+#include <keymaster/soft_keymaster_context.h>
+
+#include "keymaster0_engine.h"
+#include "openssl_utils.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+EcdsaKeymaster0KeyFactory::EcdsaKeymaster0KeyFactory(const SoftKeymasterContext* context,
+                                                     const Keymaster0Engine* engine)
+    : EcdsaKeyFactory(context), engine_(engine), soft_context_(context) {
+}
+
+keymaster_error_t EcdsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
+                                                         KeymasterKeyBlob* key_blob,
+                                                         AuthorizationSet* hw_enforced,
+                                                         AuthorizationSet* sw_enforced) {
+    if (!key_blob || !hw_enforced || !sw_enforced)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    if (!engine_ || !engine_->supports_ec())
+        return super::GenerateKey(key_description, key_blob, hw_enforced, sw_enforced);
+
+    uint32_t key_size;
+    if (!key_description.GetTagValue(TAG_KEY_SIZE, &key_size)) {
+        LOG_E("%s", "No key size specified for EC key generation");
+        return KM_ERROR_UNSUPPORTED_KEY_SIZE;
+    }
+
+    KeymasterKeyBlob key_material;
+    if (!engine_->GenerateEcKey(key_size, &key_material))
+        return KM_ERROR_UNKNOWN_ERROR;
+
+    // These tags are hardware-enforced.  Putting them in the hw_enforced set here will ensure that
+    // context_->CreateKeyBlob doesn't put them in sw_enforced.
+    hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
+    hw_enforced->push_back(TAG_KEY_SIZE, key_size);
+
+    return context_->CreateKeyBlob(key_description, KM_ORIGIN_GENERATED, key_material, key_blob,
+                                   hw_enforced, sw_enforced);
+}
+
+keymaster_error_t EcdsaKeymaster0KeyFactory::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) {
+    if (!output_key_blob || !hw_enforced || !sw_enforced)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    if (!engine_ || !engine_->supports_ec())
+        return super::ImportKey(key_description, input_key_material_format, input_key_material,
+                                output_key_blob, hw_enforced, sw_enforced);
+
+    AuthorizationSet authorizations;
+    uint32_t key_size;
+    keymaster_error_t error = UpdateImportKeyDescription(
+        key_description, input_key_material_format, input_key_material, &authorizations, &key_size);
+    if (error != KM_ERROR_OK)
+        return error;
+
+    KeymasterKeyBlob imported_hw_key;
+    if (!engine_->ImportKey(input_key_material_format, input_key_material, &imported_hw_key))
+        return KM_ERROR_UNKNOWN_ERROR;
+
+    // These tags are hardware-enforced.  Putting them in the hw_enforced set here will ensure that
+    // context_->CreateKeyBlob doesn't put them in sw_enforced.
+    hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
+    hw_enforced->push_back(TAG_KEY_SIZE, key_size);
+
+    return context_->CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, imported_hw_key,
+                                   output_key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+                                                     const AuthorizationSet& hw_enforced,
+                                                     const AuthorizationSet& sw_enforced,
+                                                     UniquePtr<Key>* key) {
+    if (!key)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
+        return super::LoadKey(key_material, hw_enforced, sw_enforced, key);
+
+    unique_ptr<EC_KEY, EC_Delete> ec_key(engine_->BlobToEcKey(key_material));
+    if (!ec_key)
+        return KM_ERROR_UNKNOWN_ERROR;
+
+    keymaster_error_t error;
+    key->reset(new EcKeymaster0Key(ec_key.release(), hw_enforced, sw_enforced, engine_, &error));
+    if (error != KM_ERROR_OK)
+        return error;
+
+    return KM_ERROR_OK;
+}
+
+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(new uint8_t[*size]);
+    if (!material->get())
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    memcpy(material->get(), blob->key_material, *size);
+    return KM_ERROR_OK;
+}
+
+}  // namespace keymaster
diff --git a/ec_keymaster0_key.h b/ec_keymaster0_key.h
new file mode 100644
index 0000000..b2f8294
--- /dev/null
+++ b/ec_keymaster0_key.h
@@ -0,0 +1,74 @@
+/*
+ * 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_KEYMASTER0_KEY_H_
+#define SYSTEM_KEYMASTER_EC_KEYMASTER0_KEY_H_
+
+#include <openssl/ec_key.h>
+
+#include "ec_key.h"
+
+namespace keymaster {
+
+class Keymaster0Engine;
+class SoftKeymasterContext;
+
+/**
+ * An EcdsaKeyFactory which can delegate key generation, importing and loading operations to a
+ * keymaster0-backed OpenSSL engine.
+ */
+class EcdsaKeymaster0KeyFactory : public EcdsaKeyFactory {
+    typedef EcdsaKeyFactory super;
+
+  public:
+    EcdsaKeymaster0KeyFactory(const SoftKeymasterContext* context, const Keymaster0Engine* engine);
+
+    keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+                                  KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
+                                  AuthorizationSet* sw_enforced) 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) override;
+
+    keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+                              const AuthorizationSet& hw_enforced,
+                              const AuthorizationSet& sw_enforced, UniquePtr<Key>* key) override;
+
+  private:
+    const Keymaster0Engine* engine_;
+    const SoftKeymasterContext* soft_context_;
+};
+
+class EcKeymaster0Key : public EcKey {
+    typedef EcKey super;
+
+  public:
+    EcKeymaster0Key(EC_KEY* ec_key, const AuthorizationSet& hw_enforced,
+                    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_;
+};
+
+}  // namespace keymaster
+
+#endif  // SYSTEM_KEYMASTER_EC_KEYMASTER0_KEY_H_
diff --git a/keymaster0_engine.cpp b/keymaster0_engine.cpp
index 3b8f815..900bb7e 100644
--- a/keymaster0_engine.cpp
+++ b/keymaster0_engine.cpp
@@ -39,9 +39,11 @@
 // int Keymaster0Engine::ec_key_index_ = -1;
 Keymaster0Engine* Keymaster0Engine::instance_ = nullptr;
 const RSA_METHOD Keymaster0Engine::rsa_method_ = {
-    {
-        0 /* references */, 1 /* is_static */,
-    },
+    .common =
+        {
+            0,  // references
+            1   // is_static
+        },
     .app_data = nullptr,
     .init = nullptr,
     .finish = nullptr,
@@ -59,20 +61,43 @@
     .mod_exp = nullptr,
     .bn_mod_exp = BN_mod_exp_mont,
 
-    .flags = RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_OPAQUE | RSA_FLAG_EXT_PKEY,
+    .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()) {
+    : keymaster0_device_(keymaster0_device), engine_(ENGINE_new()), supports_ec_(false) {
     assert(!instance_);
     instance_ = this;
 
     rsa_index_ = RSA_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
                                       keyblob_dup, keyblob_free);
+    ec_key_index_ = EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
+                                            keyblob_dup, keyblob_free);
+
     ENGINE_set_RSA_method(engine_, &rsa_method_, sizeof(rsa_method_));
+
+    if ((keymaster0_device_->flags & KEYMASTER_SUPPORTS_EC) != 0) {
+        supports_ec_ = true;
+        ENGINE_set_ECDSA_method(engine_, &ecdsa_method_, sizeof(ecdsa_method_));
+    }
 }
 
 Keymaster0Engine::~Keymaster0Engine() {
@@ -101,9 +126,25 @@
     return true;
 }
 
-bool Keymaster0Engine::ImportRsaKey(keymaster_key_format_t key_format,
-                                    const KeymasterKeyBlob& to_import,
-                                    KeymasterKeyBlob* imported_key) const {
+bool Keymaster0Engine::GenerateEcKey(uint32_t key_size, KeymasterKeyBlob* key_material) const {
+    assert(key_material);
+    keymaster_ec_keygen_params_t params;
+    params.field_size = key_size;
+
+    uint8_t* key_blob = 0;
+    if (keymaster0_device_->generate_keypair(keymaster0_device_, TYPE_EC, &params, &key_blob,
+                                             &key_material->key_material_size) < 0) {
+        ALOGE("Error generating EC key pair with keymaster0 device");
+        return false;
+    }
+    unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
+    key_material->key_material = dup_buffer(key_blob, key_material->key_material_size);
+    return true;
+}
+
+bool Keymaster0Engine::ImportKey(keymaster_key_format_t key_format,
+                                 const KeymasterKeyBlob& to_import,
+                                 KeymasterKeyBlob* imported_key) const {
     assert(imported_key);
     if (key_format != KM_KEY_FORMAT_PKCS8)
         return false;
@@ -112,7 +153,7 @@
     if (keymaster0_device_->import_keypair(keymaster0_device_, to_import.key_material,
                                            to_import.key_material_size, &key_blob,
                                            &imported_key->key_material_size) < 0) {
-        ALOGW("Error importing RSA keypair with keymaster0 device");
+        ALOGW("Error importing keypair with keymaster0 device");
         return false;
     }
     unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
@@ -161,15 +202,47 @@
     return rsa.release();
 }
 
-const keymaster_key_blob_t* Keymaster0Engine::rsa_get_blob(const RSA* rsa) const {
+EC_KEY* Keymaster0Engine::BlobToEcKey(const KeymasterKeyBlob& blob) const {
+    // Create new EC key (with engine methods) and insert blob
+    unique_ptr<EC_KEY, EC_Delete> ec_key(EC_KEY_new_method(engine_));
+    if (!ec_key)
+        return nullptr;
+
+    keymaster_key_blob_t* blob_copy = duplicate_blob(blob);
+    if (!blob_copy->key_material || !EC_KEY_set_ex_data(ec_key.get(), ec_key_index_, blob_copy))
+        return nullptr;
+
+    // Copy public key into new EC key
+    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(GetKeymaster0PublicKey(blob));
+    if (!pkey)
+        return nullptr;
+
+    unique_ptr<EC_KEY, EC_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
+    if (!public_ec_key)
+        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())))
+        return nullptr;
+
+    return ec_key.release();
+}
+
+const keymaster_key_blob_t* Keymaster0Engine::RsaKeyToBlob(const RSA* rsa) const {
     return reinterpret_cast<keymaster_key_blob_t*>(RSA_get_ex_data(rsa, rsa_index_));
 }
 
+const keymaster_key_blob_t* Keymaster0Engine::EcKeyToBlob(const EC_KEY* ec_key) const {
+    return reinterpret_cast<keymaster_key_blob_t*>(EC_KEY_get_ex_data(ec_key, ec_key_index_));
+}
+
 /* static */
 int Keymaster0Engine::keyblob_dup(CRYPTO_EX_DATA* /* to */, const CRYPTO_EX_DATA* /* from */,
                                   void** from_d, int /* index */, long /* argl */,
                                   void* /* argp */) {
     keymaster_key_blob_t* blob = reinterpret_cast<keymaster_key_blob_t*>(*from_d);
+    if (!blob)
+        return 1;
     *from_d = duplicate_blob(*blob);
     if (*from_d)
         return 1;
@@ -194,6 +267,14 @@
     return instance_->RsaPrivateTransform(rsa, out, in, len);
 }
 
+/* static */
+int Keymaster0Engine::ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+                                 unsigned int* sig_len, EC_KEY* ec_key) {
+    ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned)digest_len, ec_key);
+    assert(instance_);
+    return instance_->EcdsaSign(digest, digest_len, sig, sig_len, ec_key);
+}
+
 bool Keymaster0Engine::Keymaster0Sign(const void* signing_params, const keymaster_key_blob_t& blob,
                                       const uint8_t* data, const size_t data_length,
                                       unique_ptr<uint8_t[], Malloc_Delete>* signature,
@@ -229,7 +310,7 @@
 
 int Keymaster0Engine::RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t* in,
                                           size_t len) const {
-    const keymaster_key_blob_t* key_blob = rsa_get_blob(rsa);
+    const keymaster_key_blob_t* key_blob = RsaKeyToBlob(rsa);
     if (key_blob == NULL) {
         ALOGE("key had no key_blob!");
         return 0;
@@ -263,4 +344,34 @@
     return 1;
 }
 
+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);
+    if (key_blob == NULL) {
+        ALOGE("key had no key_blob!");
+        return 0;
+    }
+
+    keymaster_ec_sign_params_t sign_params = {DIGEST_NONE};
+    unique_ptr<uint8_t[], Malloc_Delete> signature;
+    size_t signature_length;
+    if (!Keymaster0Sign(&sign_params, *key_blob, digest, digest_len, &signature, &signature_length))
+        return 0;
+    Eraser eraser(signature.get(), signature_length);
+
+    if (signature_length == 0) {
+        ALOGW("No valid signature returned");
+        return 0;
+    } else if (signature_length > ECDSA_size(ec_key)) {
+        ALOGW("Signature is too large");
+        return 0;
+    } else {
+        memcpy(sig, signature.get(), signature_length);
+        *sig_len = signature_length;
+    }
+
+    ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len, ec_key);
+    return 1;
+}
+
 }  // namespace keymaster
diff --git a/keymaster0_engine.h b/keymaster0_engine.h
index 93e805f..90aec93 100644
--- a/keymaster0_engine.h
+++ b/keymaster0_engine.h
@@ -42,14 +42,20 @@
     Keymaster0Engine(const keymaster0_device_t* keymaster0_device);
     ~Keymaster0Engine();
 
+    bool supports_ec() const { return supports_ec_; }
+
     bool GenerateRsaKey(uint64_t public_exponent, uint32_t public_modulus,
                         KeymasterKeyBlob* key_material) const;
-    bool ImportRsaKey(keymaster_key_format_t key_format, const KeymasterKeyBlob& to_import,
-                      KeymasterKeyBlob* imported_key_material) const;
+    bool GenerateEcKey(uint32_t key_size, KeymasterKeyBlob* key_material) const;
+
+    bool ImportKey(keymaster_key_format_t key_format, const KeymasterKeyBlob& to_import,
+                   KeymasterKeyBlob* imported_key_material) const;
 
     RSA* BlobToRsaKey(const KeymasterKeyBlob& blob) const;
+    EC_KEY* BlobToEcKey(const KeymasterKeyBlob& blob) const;
 
-    const keymaster_key_blob_t* rsa_get_blob(const RSA* rsa) const;
+    const keymaster_key_blob_t* RsaKeyToBlob(const RSA* rsa) const;
+    const keymaster_key_blob_t* EcKeyToBlob(const EC_KEY* rsa) const;
 
     EVP_PKEY* GetKeymaster0PublicKey(const KeymasterKeyBlob& blob) const;
 
@@ -62,6 +68,8 @@
     static void keyblob_free(void* parent, void* ptr, CRYPTO_EX_DATA* data, int index, long argl,
                              void* argp);
     static int rsa_private_transform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len);
+    static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+                          unsigned int* sig_len, EC_KEY* ec_key);
 
     struct Malloc_Delete {
         void operator()(void* p) { free(p); }
@@ -73,12 +81,16 @@
                         size_t* signature_length) const;
 
     int RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len) const;
+    int EcdsaSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
+                  EC_KEY* ec_key) const;
 
     const keymaster0_device_t* keymaster0_device_;
     ENGINE* const engine_;
-    int rsa_index_;
+    int rsa_index_, ec_key_index_;
+    bool supports_ec_;
 
     static const RSA_METHOD rsa_method_;
+    static const ECDSA_METHOD ecdsa_method_;
     static Keymaster0Engine* instance_;
 };
 
diff --git a/km1_sw_ecdsa_256.blob b/km1_sw_ecdsa_256.blob
new file mode 100644
index 0000000..5b9a6f4
--- /dev/null
+++ b/km1_sw_ecdsa_256.blob
Binary files differ
diff --git a/openssl_utils.h b/openssl_utils.h
index af7e381..8ec0442 100644
--- a/openssl_utils.h
+++ b/openssl_utils.h
@@ -45,6 +45,14 @@
     void operator()(RSA* p) { RSA_free(p); }
 };
 
+struct EC_GROUP_Delete {
+    void operator()(EC_GROUP* p) { EC_GROUP_free(p); }
+};
+
+struct EC_Delete {
+    void operator()(EC_KEY* p) { EC_KEY_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
diff --git a/rsa_keymaster0_key.cpp b/rsa_keymaster0_key.cpp
index c1fd2ad..25acbc3 100644
--- a/rsa_keymaster0_key.cpp
+++ b/rsa_keymaster0_key.cpp
@@ -92,7 +92,7 @@
         return error;
 
     KeymasterKeyBlob imported_hw_key;
-    if (!engine_->ImportRsaKey(input_key_material_format, input_key_material, &imported_hw_key))
+    if (!engine_->ImportKey(input_key_material_format, input_key_material, &imported_hw_key))
         return KM_ERROR_UNKNOWN_ERROR;
 
     // These tags are hardware-enforced.  Putting them in the hw_enforced set here will ensure that
@@ -138,7 +138,7 @@
     if (!engine_)
         return super::key_material(material, size);
 
-    const keymaster_key_blob_t* blob = engine_->rsa_get_blob(key());
+    const keymaster_key_blob_t* blob = engine_->RsaKeyToBlob(key());
     if (!blob)
         return KM_ERROR_UNKNOWN_ERROR;
 
diff --git a/soft_keymaster_context.cpp b/soft_keymaster_context.cpp
index 8469925..8751a27 100644
--- a/soft_keymaster_context.cpp
+++ b/soft_keymaster_context.cpp
@@ -28,13 +28,13 @@
 
 #include "aes_key.h"
 #include "auth_encrypted_key_blob.h"
-#include "ec_key.h"
+#include "ec_keymaster0_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 "integrity_assured_key_blob.h"
 
 using std::unique_ptr;
 
@@ -50,10 +50,10 @@
 class SoftKeymasterKeyRegistrations {
   public:
     SoftKeymasterKeyRegistrations(SoftKeymasterContext* context, Keymaster0Engine* engine)
-        : rsa_(context, engine), ec_(context), hmac_(context), aes_(context) {}
+        : rsa_(context, engine), ec_(context, engine), hmac_(context), aes_(context) {}
 
     KeyFactoryRegistry::Registration<RsaKeymaster0KeyFactory> rsa_;
-    KeyFactoryRegistry::Registration<EcdsaKeyFactory> ec_;
+    KeyFactoryRegistry::Registration<EcdsaKeymaster0KeyFactory> ec_;
     KeyFactoryRegistry::Registration<HmacKeyFactory> hmac_;
     KeyFactoryRegistry::Registration<AesKeyFactory> aes_;
 };