Merge "Fix Android Compiler Warning in system/keymaster"
am: d34d9f7a52

Change-Id: If92d8f6fc1d129fcf55b33b3d9879252f61c77c4
diff --git a/Makefile b/Makefile
index 656c4e5..51f8db3 100644
--- a/Makefile
+++ b/Makefile
@@ -28,11 +28,11 @@
 	external/gtest \
 	system/security/softkeymaster \
 	system/security/keystore
-GTEST=$(BASE)/external/gtest
+GTEST=$(BASE)/external/googletest/googletest
 
 INCLUDES=$(foreach dir,$(SUBS),-I $(BASE)/$(dir)/include) \
 	-I $(BASE)/libnativehelper/include/nativehelper \
-	-I $(GTEST) -Iinclude -I$(BASE)/../boringssl/include
+	-I $(GTEST)/include -isystem $(GTEST) -Iinclude -I$(BASE)/../boringssl/include
 
 ifdef FORCE_32_BIT
 ARCH_FLAGS = -m32
diff --git a/android_keymaster.cpp b/android_keymaster.cpp
index 47ebb16..0a62ff4 100644
--- a/android_keymaster.cpp
+++ b/android_keymaster.cpp
@@ -402,6 +402,12 @@
     if (response->error != KM_ERROR_OK)
         return;
 
+    keymaster_blob_t attestation_application_id;
+    if (request.attest_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID,
+                                          &attestation_application_id)) {
+        sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, attestation_application_id);
+    }
+
     response->error = key->GenerateAttestation(*context_, request.attest_params, tee_enforced,
                                                sw_enforced, &response->certificate_chain);
 }
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index ce85316..33bb58f 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -29,6 +29,7 @@
 
 #include "android_keymaster_test_utils.h"
 #include "attestation_record.h"
+#include "hmac_key.h"
 #include "keymaster0_engine.h"
 #include "openssl_utils.h"
 
@@ -84,7 +85,8 @@
 class TestKeymasterContext : public SoftKeymasterContext {
   public:
     TestKeymasterContext() {}
-    explicit TestKeymasterContext(const string& root_of_trust) : SoftKeymasterContext(root_of_trust) {}
+    explicit TestKeymasterContext(const string& root_of_trust)
+        : SoftKeymasterContext(root_of_trust) {}
 
     KeymasterEnforcement* enforcement_policy() override { return &test_policy_; }
 
@@ -112,13 +114,14 @@
     int keymaster0_calls() const override { return 0; }
     bool is_keymaster1_hw() const override { return false; }
     KeymasterContext* keymaster_context() const override { return context_; }
+    string name() const override { return "Soft Keymaster2"; }
 
   private:
     mutable TestKeymasterContext* context_;
 };
 
 /**
- * Test instance creator that builds keymaster1 instances which wrap a faked hardware keymaster0
+ * Test instance creator that builds keymaster2 instances which wrap a faked hardware keymaster0
  * instance, with or without EC support.
  */
 class Keymaster0AdapterTestInstanceCreator : public Keymaster2TestInstanceCreator {
@@ -166,6 +169,10 @@
     int keymaster0_calls() const override { return counting_keymaster0_device_->count(); }
     bool is_keymaster1_hw() const override { return false; }
     KeymasterContext* keymaster_context() const override { return context_; }
+    string name() const override {
+        return string("Wrapped fake keymaster0 ") + (support_ec_ ? "with" : "without") +
+               " EC support";
+    }
 
   private:
     mutable TestKeymasterContext* context_;
@@ -177,7 +184,7 @@
  * Test instance creator that builds a SoftKeymasterDevice which wraps a fake hardware keymaster1
  * instance, with minimal digest support.
  */
-class Sha256OnlyKeymaster2TestInstanceCreator : public Keymaster2TestInstanceCreator {
+class Sha256OnlyKeymaster1TestInstanceCreator : public Keymaster2TestInstanceCreator {
     keymaster2_device_t* CreateDevice() const {
         std::cerr << "Creating keymaster1-backed device that supports only SHA256";
 
@@ -202,6 +209,42 @@
     int minimal_digest_set() const override { return true; }
     bool is_keymaster1_hw() const override { return true; }
     KeymasterContext* keymaster_context() const override { return context_; }
+    string name() const override { return "Wrapped fake keymaster1 w/minimal digests"; }
+
+  private:
+    mutable TestKeymasterContext* context_;
+};
+
+/**
+ * Test instance creator that builds a SoftKeymasterDevice which wraps a fake hardware keymaster1
+ * instance, with full digest support
+ */
+class Keymaster1TestInstanceCreator : public Keymaster2TestInstanceCreator {
+    keymaster2_device_t* CreateDevice() const {
+        std::cerr << "Creating keymaster1-backed device";
+
+        // fake_device doesn't leak because device (below) takes ownership of it.
+        keymaster1_device_t* fake_device =
+            (new SoftKeymasterDevice(new TestKeymasterContext("PseudoHW")))->keymaster_device();
+
+        // device doesn't leak; it's cleaned up by device->keymaster_device()->common.close().
+        context_ = new TestKeymasterContext;
+        SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
+        device->SetHardwareDevice(fake_device);
+
+        AuthorizationSet version_info(AuthorizationSetBuilder()
+                                          .Authorization(TAG_OS_VERSION, kOsVersion)
+                                          .Authorization(TAG_OS_PATCHLEVEL, kOsPatchLevel));
+        device->keymaster2_device()->configure(device->keymaster2_device(), &version_info);
+        return device->keymaster2_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 false; }
+    bool is_keymaster1_hw() const override { return true; }
+    KeymasterContext* keymaster_context() const override { return context_; }
+    string name() const override { return "Wrapped fake keymaster1 w/full digests"; }
 
   private:
     mutable TestKeymasterContext* context_;
@@ -211,7 +254,8 @@
     InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
     InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
     InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)),
-    InstanceCreatorPtr(new Sha256OnlyKeymaster2TestInstanceCreator));
+    InstanceCreatorPtr(new Keymaster1TestInstanceCreator),
+    InstanceCreatorPtr(new Sha256OnlyKeymaster1TestInstanceCreator));
 
 class NewKeyGeneration : public Keymaster2Test {
   protected:
@@ -368,6 +412,26 @@
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
+TEST_P(NewKeyGeneration, CheckKeySizes) {
+    for (size_t key_size = 0; key_size <= kMaxHmacKeyLengthBits + 10; ++key_size) {
+        if (key_size < kMinHmacKeyLengthBits || key_size > kMaxHmacKeyLengthBits ||
+            key_size % 8 != 0) {
+            EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE,
+                      GenerateKey(AuthorizationSetBuilder()
+                                      .HmacKey(key_size)
+                                      .Digest(KM_DIGEST_SHA_2_256)
+                                      .Authorization(TAG_MIN_MAC_LENGTH, 256)))
+                << "HMAC key size " << key_size << " invalid.";
+        } else {
+            EXPECT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                                   .HmacKey(key_size)
+                                                   .Digest(KM_DIGEST_SHA_2_256)
+                                                   .Authorization(TAG_MIN_MAC_LENGTH, 256)));
+        }
+    }
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
+}
+
 TEST_P(NewKeyGeneration, HmacMultipleDigests) {
     ASSERT_EQ(KM_ERROR_UNSUPPORTED_DIGEST,
               GenerateKey(AuthorizationSetBuilder()
@@ -521,10 +585,8 @@
     begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
     EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
     string result;
-    size_t input_consumed;
-    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
     string signature;
-    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&signature));
+    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(message, "", &signature));
 
     if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
@@ -757,10 +819,6 @@
 }
 
 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)
@@ -774,10 +832,6 @@
 }
 
 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)
@@ -791,10 +845,6 @@
 }
 
 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)
@@ -808,10 +858,6 @@
 }
 
 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)
@@ -826,10 +872,6 @@
 }
 
 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)
@@ -856,84 +898,6 @@
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase1) {
-    uint8_t key_data[] = {
-        0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-        0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-    };
-    string message = "Hi There";
-    uint8_t sha_224_expected[] = {
-        0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d,
-        0xf3, 0x3f, 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22,
-    };
-    uint8_t sha_256_expected[] = {
-        0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf,
-        0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83,
-        0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
-    };
-    uint8_t sha_384_expected[] = {
-        0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4,
-        0xab, 0x46, 0x90, 0x7f, 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
-        0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, 0xfa, 0xea, 0x9e, 0xa9,
-        0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6,
-    };
-    uint8_t sha_512_expected[] = {
-        0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a,
-        0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0,
-        0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7,
-        0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d, 0x91, 0x4e,
-        0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54,
-    };
-
-    string key = make_string(key_data);
-
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_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());
-}
-
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase2) {
-    string key = "Jefe";
-    string message = "what do ya want for nothing?";
-    uint8_t sha_224_expected[] = {
-        0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e,
-        0x6d, 0x0f, 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44,
-    };
-    uint8_t sha_256_expected[] = {
-        0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24,
-        0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27,
-        0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
-    };
-    uint8_t sha_384_expected[] = {
-        0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2,
-        0xb5, 0x8a, 0x6b, 0x1b, 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
-        0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, 0x8e, 0x22, 0x40, 0xca,
-        0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49,
-    };
-    uint8_t sha_512_expected[] = {
-        0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b,
-        0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27,
-        0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99,
-        0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 0xca, 0xea, 0xb1, 0xa3,
-        0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37,
-    };
-
-    CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_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());
-}
-
 TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) {
     string key(20, 0xaa);
     string message(50, 0xdd);
@@ -960,13 +924,10 @@
         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));
-    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));
-    }
+    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());
 }
@@ -1001,13 +962,10 @@
         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));
-    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));
-    }
+    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());
 }
@@ -1033,12 +991,10 @@
         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));
-    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));
-    }
+    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());
 }
@@ -1070,12 +1026,10 @@
         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));
-    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));
-    }
+    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());
 }
@@ -1109,12 +1063,10 @@
         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));
-    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));
-    }
+    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());
 }
@@ -1233,10 +1185,7 @@
     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));
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
 
     if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1259,10 +1208,7 @@
     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));
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
 
     if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1333,10 +1279,7 @@
     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));
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
 
     if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1359,10 +1302,7 @@
     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));
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
 
     if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1520,10 +1460,7 @@
     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));
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
 }
 
 TEST_P(VerificationOperationsTest, EcdsaSha224Success) {
@@ -1544,10 +1481,7 @@
     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));
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
 }
 
 TEST_P(VerificationOperationsTest, EcdsaAllDigestsAndKeySizes) {
@@ -1579,10 +1513,6 @@
 }
 
 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)
@@ -1596,10 +1526,6 @@
 }
 
 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)
@@ -1644,18 +1570,12 @@
     AuthorizationSet begin_params(client_params());
     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(KM_ERROR_INVALID_MAC_LENGTH, FinishOperation(signature, &result));
+    EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH, FinishOperation(message, signature, &result));
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
 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)
@@ -1669,10 +1589,6 @@
 }
 
 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)
@@ -2033,8 +1949,7 @@
     BN_bn2bin(rsa->n, modulus_buf.get());
     message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
     EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
-    EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(message, "", &result));
 
     if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -2425,10 +2340,7 @@
     begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
     EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
     string ciphertext;
-    size_t input_consumed;
-    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &ciphertext, &input_consumed));
-    EXPECT_EQ(message.size(), input_consumed);
-    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&ciphertext));
+    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(message, "", &ciphertext));
 
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
@@ -3603,6 +3515,9 @@
     expected_tee_enforced.Sort();
     EXPECT_EQ(expected_tee_enforced, att_tee_enforced);
 
+    delete[] att_challenge.data;
+    delete[] att_unique_id.data;
+
     return true;
 }
 
diff --git a/android_keymaster_test_utils.cpp b/android_keymaster_test_utils.cpp
index ecaee62..41135f3 100644
--- a/android_keymaster_test_utils.cpp
+++ b/android_keymaster_test_utils.cpp
@@ -169,6 +169,10 @@
 
 namespace test {
 
+std::ostream& operator<<(std::ostream& os, const InstanceCreatorPtr& instance_creator) {
+    return os << instance_creator->name();
+}
+
 Keymaster2Test::Keymaster2Test() : op_handle_(OP_HANDLE_SENTINEL) {
     memset(&characteristics_, 0, sizeof(characteristics_));
     blob_.key_material = nullptr;
@@ -291,24 +295,26 @@
 }
 
 keymaster_error_t Keymaster2Test::FinishOperation(string* output) {
-    return FinishOperation("", output);
+    return FinishOperation("", "", output);
 }
 
-keymaster_error_t Keymaster2Test::FinishOperation(const string& signature, string* output) {
+keymaster_error_t Keymaster2Test::FinishOperation(const string& input, const string& signature,
+                                                  string* output) {
     AuthorizationSet additional_params;
     AuthorizationSet output_params;
-    return FinishOperation(additional_params, signature, &output_params, output);
+    return FinishOperation(additional_params, input, signature, &output_params, output);
 }
 
 keymaster_error_t Keymaster2Test::FinishOperation(const AuthorizationSet& additional_params,
-                                                  const string& signature,
+                                                  const string& input, const string& signature,
                                                   AuthorizationSet* output_params, string* output) {
+    keymaster_blob_t inp = {reinterpret_cast<const uint8_t*>(input.c_str()), input.length()};
     keymaster_blob_t sig = {reinterpret_cast<const uint8_t*>(signature.c_str()),
                             signature.length()};
     keymaster_blob_t out_tmp;
     keymaster_key_param_set_t out_params;
-    keymaster_error_t error = device()->finish(device(), op_handle_, &additional_params,
-                                               nullptr /* input */, &sig, &out_params, &out_tmp);
+    keymaster_error_t error = device()->finish(device(), op_handle_, &additional_params, &inp, &sig,
+                                               &out_params, &out_tmp);
     if (error != KM_ERROR_OK) {
         EXPECT_TRUE(out_tmp.data == nullptr);
         EXPECT_TRUE(out_params.params == nullptr);
@@ -353,10 +359,7 @@
     EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, client_params(), NULL /* output_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_OK, FinishOperation(&result));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(message, "" /* signature */, &result));
     return result;
 }
 
@@ -367,11 +370,7 @@
     EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, begin_params, begin_out_params));
 
     string result;
-    size_t input_consumed;
-    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, nullptr /* output_params */,
-                                           &result, &input_consumed));
-    EXPECT_EQ(message.size(), input_consumed);
-    EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, "", &result));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, message, "" /* signature */, &result));
     return result;
 }
 
@@ -382,11 +381,7 @@
     EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, begin_params, output_params));
 
     string result;
-    size_t input_consumed;
-    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, nullptr /* output_params */,
-                                           &result, &input_consumed));
-    EXPECT_EQ(message.size(), input_consumed);
-    EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, signature, &result));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, message, signature, &result));
     return result;
 }
 
@@ -395,10 +390,7 @@
     EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, client_params(), NULL /* output_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_OK, FinishOperation(signature, &result));
+    EXPECT_EQ(KM_ERROR_OK, FinishOperation(message, signature, &result));
     return result;
 }
 
@@ -622,8 +614,8 @@
     return error;
 }
 
-void Keymaster2Test::CheckHmacTestVector(const string& key, const string& message, keymaster_digest_t digest,
-                                         string expected_mac) {
+void Keymaster2Test::CheckHmacTestVector(const string& key, const string& message,
+                                         keymaster_digest_t digest, string expected_mac) {
     ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
                                          .HmacKey(key.size() * 8)
                                          .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
@@ -678,7 +670,8 @@
 
 class Sha256OnlyWrapper {
   public:
-    explicit Sha256OnlyWrapper(const keymaster1_device_t* wrapped_device) : wrapped_device_(wrapped_device) {
+    explicit 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;
diff --git a/android_keymaster_test_utils.h b/android_keymaster_test_utils.h
index 5dd0f76..13832bb 100644
--- a/android_keymaster_test_utils.h
+++ b/android_keymaster_test_utils.h
@@ -166,11 +166,15 @@
     virtual int minimal_digest_set() const { return false; }
     virtual bool is_keymaster1_hw() const = 0;
     virtual KeymasterContext* keymaster_context() const = 0;
+
+    virtual std::string name() const = 0;
 };
 
 // Use a shared_ptr because it's copyable.
 typedef std::shared_ptr<Keymaster2TestInstanceCreator> InstanceCreatorPtr;
 
+std::ostream& operator<<(std::ostream& os, const InstanceCreatorPtr& instance_creator);
+
 const uint64_t OP_HANDLE_SENTINEL = 0xFFFFFFFFFFFFFFFF;
 class Keymaster2Test : public testing::TestWithParam<InstanceCreatorPtr> {
   protected:
@@ -201,14 +205,17 @@
                                       std::string* output, size_t* input_consumed);
 
     keymaster_error_t FinishOperation(std::string* output);
-    keymaster_error_t FinishOperation(const std::string& signature, std::string* output);
+    keymaster_error_t FinishOperation(const std::string& input, const std::string& signature,
+                                      std::string* output);
     keymaster_error_t FinishOperation(const AuthorizationSet& additional_params,
-                                      const std::string& signature, std::string* output) {
-        return FinishOperation(additional_params, signature, nullptr /* output_params */, output);
+                                      const std::string& input, const std::string& signature,
+                                      std::string* output) {
+        return FinishOperation(additional_params, input, signature, nullptr /* output_params */,
+                               output);
     }
     keymaster_error_t FinishOperation(const AuthorizationSet& additional_params,
-                                      const std::string& signature, AuthorizationSet* output_params,
-                                      std::string* output);
+                                      const std::string& input, const std::string& signature,
+                                      AuthorizationSet* output_params, std::string* output);
 
     keymaster_error_t AbortOperation();
 
@@ -217,7 +224,6 @@
     keymaster_error_t UpgradeKey(const AuthorizationSet& upgrade_params);
 
     keymaster_error_t GetVersion(uint8_t* major, uint8_t* minor, uint8_t* subminor);
-
     std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message);
     std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message,
                                const AuthorizationSet& begin_params,
@@ -274,8 +280,8 @@
                                keymaster_block_mode_t block_mode, keymaster_padding_t padding,
                                const std::string& nonce);
 
-    void CheckHmacTestVector(const std::string& key, const std::string& message, keymaster_digest_t digest,
-                             std::string expected_mac);
+    void CheckHmacTestVector(const std::string& key, const std::string& message,
+                             keymaster_digest_t digest, std::string expected_mac);
     void CheckAesOcbTestVector(const std::string& key, const std::string& nonce,
                                const std::string& associated_data, const std::string& message,
                                const std::string& expected_ciphertext);
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp
index 782e87b..35406e6 100644
--- a/asymmetric_key.cpp
+++ b/asymmetric_key.cpp
@@ -290,19 +290,10 @@
         !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
         return TranslateLastOpenSslError();
 
-    // TODO(swillden): Find useful values (if possible) for issuerName and subjectName.
-    X509_NAME_Ptr issuerName(X509_NAME_new());
-    if (!issuerName.get() ||
-        !X509_NAME_add_entry_by_txt(issuerName.get(), "CN", MBSTRING_ASC,
-                                    reinterpret_cast<const uint8_t*>("Android Keymaster"),
-                                    -1 /* len */, -1 /* loc */, 0 /* set */) ||
-        !X509_set_issuer_name(certificate.get(), issuerName.get() /* Don't release; copied  */))
-        return TranslateLastOpenSslError();
-
     X509_NAME_Ptr subjectName(X509_NAME_new());
     if (!subjectName.get() ||
         !X509_NAME_add_entry_by_txt(subjectName.get(), "CN", MBSTRING_ASC,
-                                    reinterpret_cast<const uint8_t*>("A Keymaster Key"),
+                                    reinterpret_cast<const uint8_t*>("Android Keystore Key"),
                                     -1 /* len */, -1 /* loc */, 0 /* set */) ||
         !X509_set_subject_name(certificate.get(), subjectName.get() /* Don't release; copied */))
         return TranslateLastOpenSslError();
@@ -354,6 +345,15 @@
         return TranslateLastOpenSslError();
     }
 
+    // Set issuer to subject of batch certificate.
+    X509_NAME* issuerSubject = X509_get_subject_name(signing_cert.get());
+    if (!issuerSubject) {
+        return KM_ERROR_UNKNOWN_ERROR;
+    }
+    if (!X509_set_issuer_name(certificate.get(), issuerSubject)) {
+        return TranslateLastOpenSslError();
+    }
+
     UniquePtr<X509V3_CTX> x509v3_ctx(new X509V3_CTX);
     *x509v3_ctx = {};
     X509V3_set_ctx(x509v3_ctx.get(), signing_cert.get(), certificate.get(), nullptr /* req */,
diff --git a/attestation_record.cpp b/attestation_record.cpp
index 8417c55..0f7f05f 100644
--- a/attestation_record.cpp
+++ b/attestation_record.cpp
@@ -28,6 +28,9 @@
 
 namespace keymaster {
 
+constexpr uint kCurrentKeymasterVersion = 3;
+constexpr uint kCurrentAttestationVersion = 2;
+
 struct stack_st_ASN1_TYPE_Delete {
     void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
 };
@@ -79,6 +82,15 @@
     KM_ROOT_OF_TRUST* root_of_trust;
     ASN1_INTEGER* os_version;
     ASN1_INTEGER* os_patchlevel;
+    ASN1_OCTET_STRING* attestation_application_id;
+    ASN1_OCTET_STRING* attestation_id_brand;
+    ASN1_OCTET_STRING* attestation_id_device;
+    ASN1_OCTET_STRING* attestation_id_product;
+    ASN1_OCTET_STRING* attestation_id_serial;
+    ASN1_OCTET_STRING* attestation_id_imei;
+    ASN1_OCTET_STRING* attestation_id_meid;
+    ASN1_OCTET_STRING* attestation_id_manufacturer;
+    ASN1_OCTET_STRING* attestation_id_model;
 } KM_AUTH_LIST;
 
 ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -110,6 +122,24 @@
     ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.masked_tag()),
     ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.masked_tag()),
     ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_APPLICATION_ID.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_BRAND.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_DEVICE.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_PRODUCT.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_SERIAL.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_IMEI.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_MEID.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_MANUFACTURER.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_ID_MODEL.masked_tag()),
 } ASN1_SEQUENCE_END(KM_AUTH_LIST);
 IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
 
@@ -136,6 +166,17 @@
 } ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
 IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
 
+static const keymaster_tag_t kDeviceAttestationTags[] = {
+    KM_TAG_ATTESTATION_ID_BRAND,
+    KM_TAG_ATTESTATION_ID_DEVICE,
+    KM_TAG_ATTESTATION_ID_PRODUCT,
+    KM_TAG_ATTESTATION_ID_SERIAL,
+    KM_TAG_ATTESTATION_ID_IMEI,
+    KM_TAG_ATTESTATION_ID_MEID,
+    KM_TAG_ATTESTATION_ID_MANUFACTURER,
+    KM_TAG_ATTESTATION_ID_MODEL,
+};
+
 struct KM_AUTH_LIST_Delete {
     void operator()(KM_AUTH_LIST* p) { KM_AUTH_LIST_free(p); }
 };
@@ -306,6 +347,33 @@
         case KM_TAG_APPLICATION_ID:
             string_ptr = &record->application_id;
             break;
+        case KM_TAG_ATTESTATION_APPLICATION_ID:
+            string_ptr = &record->attestation_application_id;
+            break;
+        case KM_TAG_ATTESTATION_ID_BRAND:
+            string_ptr = &record->attestation_id_brand;
+            break;
+        case KM_TAG_ATTESTATION_ID_DEVICE:
+            string_ptr = &record->attestation_id_device;
+            break;
+        case KM_TAG_ATTESTATION_ID_PRODUCT:
+            string_ptr = &record->attestation_id_product;
+            break;
+        case KM_TAG_ATTESTATION_ID_SERIAL:
+            string_ptr = &record->attestation_id_serial;
+            break;
+        case KM_TAG_ATTESTATION_ID_IMEI:
+            string_ptr = &record->attestation_id_imei;
+            break;
+        case KM_TAG_ATTESTATION_ID_MEID:
+            string_ptr = &record->attestation_id_meid;
+            break;
+        case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+            string_ptr = &record->attestation_id_manufacturer;
+            break;
+        case KM_TAG_ATTESTATION_ID_MODEL:
+            string_ptr = &record->attestation_id_model;
+            break;
         }
 
         keymaster_tag_type_t type = keymaster_tag_get_type(entry.tag);
@@ -407,8 +475,8 @@
 // Construct an ASN1.1 DER-encoded attestation record containing the values from sw_enforced and
 // tee_enforced.
 keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
-                                           const AuthorizationSet& sw_enforced,
-                                           const AuthorizationSet& tee_enforced,
+                                           AuthorizationSet sw_enforced,
+                                           AuthorizationSet tee_enforced,
                                            const KeymasterContext& context,
                                            UniquePtr<uint8_t[]>* asn1_key_desc,
                                            size_t* asn1_key_desc_len) {
@@ -423,34 +491,14 @@
     if (tee_enforced.empty()) {
         // Software key.
         keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
-        keymaster_version = 2;
+        keymaster_version = kCurrentKeymasterVersion;
     } else {
         keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
         switch (context.GetSecurityLevel()) {
-        case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT: {
-            // We're running in a TEE, so the key is KM2.
-            keymaster_version = 2;
-
-            // Root of trust is only available in TEE
-            KM_AUTH_LIST* tee_record = key_desc->tee_enforced;
-            tee_record->root_of_trust = KM_ROOT_OF_TRUST_new();
-            keymaster_blob_t verified_boot_key;
-            keymaster_verified_boot_t verified_boot_state;
-            bool device_locked;
-            keymaster_error_t error = context.GetVerifiedBootParams(
-                &verified_boot_key, &verified_boot_state, &device_locked);
-            if (error != KM_ERROR_OK)
-                return error;
-            if (verified_boot_key.data_length &&
-                !ASN1_OCTET_STRING_set(tee_record->root_of_trust->verified_boot_key,
-                                       verified_boot_key.data, verified_boot_key.data_length))
-                return TranslateLastOpenSslError();
-            tee_record->root_of_trust->device_locked = (int*)device_locked;
-            if (!ASN1_ENUMERATED_set(tee_record->root_of_trust->verified_boot_state,
-                                     verified_boot_state))
-                return TranslateLastOpenSslError();
+        case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT:
+            keymaster_version = kCurrentKeymasterVersion;
             break;
-        }
+
         case KM_SECURITY_LEVEL_SOFTWARE:
             // We're running in software, wrapping some KM hardware.  Is it KM0 or KM1?  KM1 keys
             // have the purpose in the tee_enforced list.  It's possible that a key could be created
@@ -465,7 +513,7 @@
             return KM_ERROR_UNKNOWN_ERROR;
     }
 
-    if (!ASN1_INTEGER_set(key_desc->attestation_version, 1) ||
+    if (!ASN1_INTEGER_set(key_desc->attestation_version, kCurrentAttestationVersion) ||
         !ASN1_ENUMERATED_set(key_desc->attestation_security_level, context.GetSecurityLevel()) ||
         !ASN1_INTEGER_set(key_desc->keymaster_version, keymaster_version) ||
         !ASN1_ENUMERATED_set(key_desc->keymaster_security_level, keymaster_security_level))
@@ -478,7 +526,26 @@
                                attestation_challenge.data_length))
         return TranslateLastOpenSslError();
 
-    keymaster_error_t error = build_auth_list(sw_enforced, key_desc->software_enforced);
+    keymaster_blob_t attestation_app_id;
+    if (!attestation_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID, &attestation_app_id))
+        return KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING;
+    sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, attestation_app_id);
+
+    keymaster_error_t error = context.VerifyAndCopyDeviceIds(attestation_params,
+            keymaster_security_level == KM_SECURITY_LEVEL_SOFTWARE ? &sw_enforced : &tee_enforced);
+    if (error == KM_ERROR_UNIMPLEMENTED) {
+        // The KeymasterContext implementation does not support device ID attestation. Bail out if
+        // device ID attestation is being attempted.
+        for (const auto& tag : kDeviceAttestationTags) {
+            if (attestation_params.find(tag) != -1) {
+                return KM_ERROR_CANNOT_ATTEST_IDS;
+            }
+        }
+    } else if (error != KM_ERROR_OK) {
+        return error;
+    }
+
+    error = build_auth_list(sw_enforced, key_desc->software_enforced);
     if (error != KM_ERROR_OK)
         return error;
 
@@ -663,6 +730,55 @@
         !auth_list->push_back(TAG_OS_PATCHLEVEL, ASN1_INTEGER_get(record->os_patchlevel)))
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
 
+    // Brand name
+    if (record->attestation_id_brand &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_BRAND, record->attestation_id_brand->data,
+                              record->attestation_id_brand->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    // Device name
+    if (record->attestation_id_device &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_DEVICE, record->attestation_id_device->data,
+                              record->attestation_id_device->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    // Product name
+    if (record->attestation_id_product &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_PRODUCT, record->attestation_id_product->data,
+                              record->attestation_id_product->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    // Serial number
+    if (record->attestation_id_serial &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_SERIAL, record->attestation_id_serial->data,
+                              record->attestation_id_serial->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    // IMEI
+    if (record->attestation_id_imei &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_IMEI, record->attestation_id_imei->data,
+                              record->attestation_id_imei->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    // MEID
+    if (record->attestation_id_meid &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_MEID, record->attestation_id_meid->data,
+                              record->attestation_id_meid->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    // Manufacturer name
+    if (record->attestation_id_manufacturer &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_MANUFACTURER,
+                              record->attestation_id_manufacturer->data,
+                              record->attestation_id_manufacturer->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+    // Model name
+    if (record->attestation_id_model &&
+        !auth_list->push_back(TAG_ATTESTATION_ID_MODEL, record->attestation_id_model->data,
+                              record->attestation_id_model->length))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
     return KM_ERROR_OK;
 }
 
@@ -704,4 +820,4 @@
     return extract_auth_list(record->tee_enforced, tee_enforced);
 }
 
-}  // namepace keymaster
+}  // namespace keymaster
diff --git a/attestation_record.h b/attestation_record.h
index 64acabc..116f82b 100644
--- a/attestation_record.h
+++ b/attestation_record.h
@@ -42,8 +42,8 @@
 static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
 
 keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
-                                           const AuthorizationSet& software_enforced,
-                                           const AuthorizationSet& tee_enforced,
+                                           AuthorizationSet software_enforced,
+                                           AuthorizationSet tee_enforced,
                                            const KeymasterContext& context,
                                            UniquePtr<uint8_t[]>* asn1_key_desc,
                                            size_t* asn1_key_desc_len);
@@ -57,6 +57,6 @@
                                            AuthorizationSet* software_enforced,
                                            AuthorizationSet* tee_enforced,
                                            keymaster_blob_t* unique_id);
-}
+}  // namespace keymaster
 
 #endif  // SYSTEM_KEYMASTER_ATTESTATION_RECORD_H_
diff --git a/attestation_record_test.cpp b/attestation_record_test.cpp
index 1cf8630..e7c1906 100644
--- a/attestation_record_test.cpp
+++ b/attestation_record_test.cpp
@@ -133,6 +133,9 @@
                                        &keymaster_security_level, &attestation_challenge,
                                        &parsed_sw_set, &parsed_hw_set, &unique_id));
 
+    delete[] attestation_challenge.data;
+    delete[] unique_id.data;
+
     hw_set.Sort();
     sw_set.Sort();
     parsed_hw_set.Sort();
diff --git a/authorization_set.cpp b/authorization_set.cpp
index 4cf070c..3f02109 100644
--- a/authorization_set.cpp
+++ b/authorization_set.cpp
@@ -65,7 +65,7 @@
     if (is_valid() != OK)
         return false;
 
-    if (count >= elems_capacity_) {
+    if (count > elems_capacity_) {
         keymaster_key_param_t* new_elems = new (std::nothrow) keymaster_key_param_t[count];
         if (new_elems == NULL) {
             set_invalid(ALLOCATION_FAILURE);
diff --git a/ec_key_factory.cpp b/ec_key_factory.cpp
index 36ec433..3f7b3d2 100644
--- a/ec_key_factory.cpp
+++ b/ec_key_factory.cpp
@@ -170,16 +170,29 @@
         return error;
 
     *key_size_bits = extracted_key_size_bits;
-    if (!updated_description->GetTagValue(TAG_KEY_SIZE, 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)
+    } else if (*key_size_bits != extracted_key_size_bits) {
         return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+    }
+
+    keymaster_ec_curve_t curve_from_size;
+    error = EcKeySizeToCurve(*key_size_bits, &curve_from_size);
+    if (error != KM_ERROR_OK)
+        return error;
+    keymaster_ec_curve_t curve;
+    if (!updated_description->GetTagValue(TAG_EC_CURVE, &curve)) {
+        updated_description->push_back(TAG_EC_CURVE, curve_from_size);
+    } else if (curve_from_size != curve) {
+        return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+    }
 
     keymaster_algorithm_t algorithm = KM_ALGORITHM_EC;
-    if (!updated_description->GetTagValue(TAG_ALGORITHM, &algorithm))
+    if (!updated_description->GetTagValue(TAG_ALGORITHM, &algorithm)) {
         updated_description->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
-    if (algorithm != KM_ALGORITHM_EC)
+    } else if (algorithm != KM_ALGORITHM_EC) {
         return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+    }
 
     return KM_ERROR_OK;
 }
diff --git a/ec_keymaster1_key.cpp b/ec_keymaster1_key.cpp
index 5cc2539..4386250 100644
--- a/ec_keymaster1_key.cpp
+++ b/ec_keymaster1_key.cpp
@@ -67,6 +67,15 @@
                                                          AuthorizationSet* sw_enforced) const {
     AuthorizationSet key_params_copy;
     UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+
+    keymaster_ec_curve_t ec_curve;
+    uint32_t key_size;
+    keymaster_error_t error = GetCurveAndSize(key_description, &ec_curve, &key_size);
+    if (error != KM_ERROR_OK) {
+        return error;
+    } else if (!key_description.Contains(TAG_KEY_SIZE, key_size)) {
+        key_params_copy.push_back(TAG_KEY_SIZE, key_size);
+    }
     return engine_->GenerateKey(key_params_copy, key_blob, hw_enforced, sw_enforced);
 }
 
diff --git a/hmac_key.h b/hmac_key.h
index c05e6a3..61d86e0 100644
--- a/hmac_key.h
+++ b/hmac_key.h
@@ -22,6 +22,8 @@
 namespace keymaster {
 
 const size_t kMinHmacLengthBits = 64;
+const size_t kMinHmacKeyLengthBits = 64;
+const size_t kMaxHmacKeyLengthBits = 2048;  // Some RFC test cases require >1024-bit keys
 
 class HmacKeyFactory : public SymmetricKeyFactory {
   public:
@@ -38,7 +40,7 @@
   private:
     bool key_size_supported(size_t key_size_bits) const override {
         return key_size_bits > 0 && key_size_bits % 8 == 00 &&
-               key_size_bits <= 2048 /* Some RFC test cases require >1024-bit keys */;
+               key_size_bits >= kMinHmacKeyLengthBits && key_size_bits <= kMaxHmacKeyLengthBits;
     }
     keymaster_error_t validate_algorithm_specific_new_key_params(
         const AuthorizationSet& key_description) const override;
diff --git a/include/keymaster/android_keymaster_utils.h b/include/keymaster/android_keymaster_utils.h
index a1cbf51..699f731 100644
--- a/include/keymaster/android_keymaster_utils.h
+++ b/include/keymaster/android_keymaster_utils.h
@@ -175,10 +175,15 @@
     T* begin_;
     T* end_;
 };
+
 template <typename T> ArrayWrapper<T> array_range(T* begin, size_t length) {
     return ArrayWrapper<T>(begin, length);
 }
 
+template <typename T, size_t n> ArrayWrapper<T> array_range(T (&a)[n]) {
+    return ArrayWrapper<T>(a, n);
+}
+
 /**
  * Convert any unsigned integer from network to host order.  We implement this here rather than
  * using the functions from arpa/inet.h because the TEE doesn't have inet.h.  This isn't the most
diff --git a/include/keymaster/keymaster_configuration.h b/include/keymaster/keymaster_configuration.h
index 97b7fa5..69738fd 100644
--- a/include/keymaster/keymaster_configuration.h
+++ b/include/keymaster/keymaster_configuration.h
@@ -40,12 +40,24 @@
 uint32_t GetOsVersion(const char* version_string);
 
 /**
+ * Retrieves and parses OS version information from build properties. Returns 0 if the string
+ * doesn't contain a numeric version number.
+ */
+uint32_t GetOsVersion();
+
+/**
  * Parses OS patch level string, returning year and month in integer form. For example, "2016-03-25"
  * will be returned as 201603. Returns 0 if the string doesn't contain a date in the form
  * YYYY-MM-DD.
  */
 uint32_t GetOsPatchlevel(const char* patchlevel_string);
 
+/**
+ * Retrieves and parses OS patch level from build properties. Returns 0 if the string doesn't
+ * contain a date in the form YYYY-MM-DD.
+ */
+uint32_t GetOsPatchlevel();
+
 }  // namespace keymaster
 
 #endif  // SYSTEM_KEYMASTER_KEYMASTER_CONFIGURATION_H_
diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h
index fab170e..cf18869 100644
--- a/include/keymaster/keymaster_context.h
+++ b/include/keymaster/keymaster_context.h
@@ -182,14 +182,17 @@
                                                Buffer* unique_id) const = 0;
 
     /**
-     * Returns verified boot parameters for the Attestation Extension.  For hardware-based
-     * implementations, these will be the values reported by the bootloader. By default,  verified
-     * boot state is unknown, and KM_ERROR_UNIMPLEMENTED is returned.
+     * Verify that the device IDs provided in the attestation_params match the device's actual IDs
+     * and copy them to attestation. If *any* of the IDs do not match or verification is not
+     * possible, return KM_ERROR_CANNOT_ATTEST_IDS. If *all* IDs provided are successfully verified
+     * or no IDs were provided, return KM_ERROR_OK.
+     *
+     * If you do not support device ID attestation, ignore all arguments and return
+     * KM_ERROR_UNIMPLEMENTED.
      */
-    virtual keymaster_error_t
-    GetVerifiedBootParams(keymaster_blob_t* /* verified_boot_key */,
-                          keymaster_verified_boot_t* /* verified_boot_state */,
-                          bool* /* device_locked */) const {
+    virtual keymaster_error_t VerifyAndCopyDeviceIds(
+        const AuthorizationSet& /* attestation_params */,
+        AuthorizationSet* /* attestation */) const {
         return KM_ERROR_UNIMPLEMENTED;
     }
 
diff --git a/include/keymaster/keymaster_tags.h b/include/keymaster/keymaster_tags.h
index 2c7ac03..ad072ec 100644
--- a/include/keymaster/keymaster_tags.h
+++ b/include/keymaster/keymaster_tags.h
@@ -165,7 +165,16 @@
 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_CHALLENGE);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_APPLICATION_ID);
 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_RESET_SINCE_ID_ROTATION);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_BRAND);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
 
 // DECLARE_KEYMASTER_ENUM_TAG is used to declare TypedEnumTag instances for each enum keymaster tag.
 #define DECLARE_KEYMASTER_ENUM_TAG(type, name, enumtype)                                           \
diff --git a/include/keymaster/soft_keymaster_device.h b/include/keymaster/soft_keymaster_device.h
index a20454d..6663ac4 100644
--- a/include/keymaster/soft_keymaster_device.h
+++ b/include/keymaster/soft_keymaster_device.h
@@ -49,7 +49,6 @@
   public:
     SoftKeymasterDevice();
 
-    // Public only for testing.
     explicit SoftKeymasterDevice(SoftKeymasterContext* context);
 
     /**
@@ -81,6 +80,8 @@
 
     bool configured() const { return configured_; }
 
+    bool supports_all_digests() { return supports_all_digests_; }
+
     typedef std::pair<keymaster_algorithm_t, keymaster_purpose_t> AlgPurposePair;
     typedef std::map<AlgPurposePair, std::vector<keymaster_digest_t>> DigestMap;
 
@@ -105,7 +106,7 @@
      * keymaster_device.
      */
 
-    // Keymaster1 methods
+    // Keymaster1 methods -- needed for testing.
     static keymaster_error_t get_supported_algorithms(const keymaster1_device_t* dev,
                                                       keymaster_algorithm_t** algorithms,
                                                       size_t* algorithms_length);
@@ -247,6 +248,7 @@
     std::string module_name_;
     hw_module_t updated_module_;
     bool configured_;
+    bool supports_all_digests_;
 };
 
 }  // namespace keymaster
diff --git a/keymaster1_engine.cpp b/keymaster1_engine.cpp
index 8e11e91..2051363 100644
--- a/keymaster1_engine.cpp
+++ b/keymaster1_engine.cpp
@@ -153,10 +153,8 @@
     // 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();
+    if (*error != KM_ERROR_OK)
         return nullptr;
-    }
 
     unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
     if (!public_rsa) {
@@ -195,10 +193,8 @@
     // Copy public key into new EC key
     unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
         GetKeymaster1PublicKey(blob, additional_params, error));
-    if (!pkey) {
-        *error = TranslateLastOpenSslError();
+    if (*error != KM_ERROR_OK)
         return nullptr;
-    }
 
     unique_ptr<EC_KEY, EC_KEY_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
     if (!public_ec_key) {
@@ -380,7 +376,11 @@
     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);
+    auto result = d2i_PUBKEY(nullptr /* allocate new struct */, &p, export_data.data_length);
+    if (!result) {
+        *error = TranslateLastOpenSslError();
+    }
+    return result;
 }
 
 RSA_METHOD Keymaster1Engine::BuildRsaMethod() {
diff --git a/keymaster_configuration.cpp b/keymaster_configuration.cpp
index 428197c..ac6d3c1 100644
--- a/keymaster_configuration.cpp
+++ b/keymaster_configuration.cpp
@@ -70,15 +70,7 @@
 }
 
 keymaster_error_t ConfigureDevice(keymaster2_device_t* dev) {
-    char version_str[PROPERTY_VALUE_MAX];
-    property_get(kPlatformVersionProp, version_str, "" /* default */);
-    uint32_t version = GetOsVersion(version_str);
-
-    char patchlevel_str[PROPERTY_VALUE_MAX];
-    property_get(kPlatformPatchlevelProp, patchlevel_str, "" /* default */);
-    uint32_t patchlevel = GetOsPatchlevel(patchlevel_str);
-
-    return ConfigureDevice(dev, version, patchlevel);
+    return ConfigureDevice(dev, GetOsVersion(), GetOsPatchlevel());
 }
 
 uint32_t GetOsVersion(const char* version_str) {
@@ -89,7 +81,10 @@
     }
 
     regmatch_t matches[kPlatformVersionMatchCount];
-    if (regexec(&regex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */)) {
+    int not_match =
+        regexec(&regex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
+    regfree(&regex);
+    if (not_match) {
         ALOGI("Platform version string does not match expected format.  Using version 0.");
         return 0;
     }
@@ -101,6 +96,12 @@
     return (major * 100 + minor) * 100 + subminor;
 }
 
+uint32_t GetOsVersion() {
+    char version_str[PROPERTY_VALUE_MAX];
+    property_get(kPlatformVersionProp, version_str, "" /* default */);
+    return GetOsVersion(version_str);
+}
+
 uint32_t GetOsPatchlevel(const char* patchlevel_str) {
     regex_t regex;
     if (regcomp(&regex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
@@ -109,7 +110,10 @@
     }
 
     regmatch_t matches[kPlatformPatchlevelMatchCount];
-    if (regexec(&regex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */)) {
+    int not_match =
+        regexec(&regex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
+    regfree(&regex);
+    if (not_match) {
         ALOGI("Platform patchlevel string does not match expected format.  Using patchlevel 0");
         return 0;
     }
@@ -124,4 +128,10 @@
     return year * 100 + month;
 }
 
+uint32_t GetOsPatchlevel() {
+    char patchlevel_str[PROPERTY_VALUE_MAX];
+    property_get(kPlatformPatchlevelProp, patchlevel_str, "" /* default */);
+    return GetOsPatchlevel(patchlevel_str);
+}
+
 }  // namespace keymaster
diff --git a/keymaster_enforcement.cpp b/keymaster_enforcement.cpp
index 3f2e4f4..e49ab46 100644
--- a/keymaster_enforcement.cpp
+++ b/keymaster_enforcement.cpp
@@ -286,6 +286,15 @@
         case KM_TAG_ROOT_OF_TRUST:
         case KM_TAG_APPLICATION_DATA:
         case KM_TAG_ATTESTATION_CHALLENGE:
+        case KM_TAG_ATTESTATION_APPLICATION_ID:
+        case KM_TAG_ATTESTATION_ID_BRAND:
+        case KM_TAG_ATTESTATION_ID_DEVICE:
+        case KM_TAG_ATTESTATION_ID_PRODUCT:
+        case KM_TAG_ATTESTATION_ID_SERIAL:
+        case KM_TAG_ATTESTATION_ID_IMEI:
+        case KM_TAG_ATTESTATION_ID_MEID:
+        case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+        case KM_TAG_ATTESTATION_ID_MODEL:
             return KM_ERROR_INVALID_KEY_BLOB;
 
         /* Tags used for cryptographic parameters in keygen.  Nothing to enforce. */
diff --git a/keymaster_tags.cpp b/keymaster_tags.cpp
index 238bc33..2375389 100644
--- a/keymaster_tags.cpp
+++ b/keymaster_tags.cpp
@@ -111,6 +111,24 @@
         return "KM_TAG_ALLOW_WHILE_ON_BODY";
     case KM_TAG_ATTESTATION_CHALLENGE:
         return "KM_TAG_ATTESTATION_CHALLENGE";
+    case KM_TAG_ATTESTATION_APPLICATION_ID:
+        return "KM_TAG_ATTESTATION_APPLICATION_ID";
+    case KM_TAG_ATTESTATION_ID_BRAND:
+        return "KM_TAG_ATTESTATION_ID_BRAND";
+    case KM_TAG_ATTESTATION_ID_DEVICE:
+        return "KM_TAG_ATTESTATION_ID_DEVICE";
+    case KM_TAG_ATTESTATION_ID_PRODUCT:
+        return "KM_TAG_ATTESTATION_ID_PRODUCT";
+    case KM_TAG_ATTESTATION_ID_SERIAL:
+        return "KM_TAG_ATTESTATION_ID_SERIAL";
+    case KM_TAG_ATTESTATION_ID_IMEI:
+        return "KM_TAG_ATTESTATION_ID_IMEI";
+    case KM_TAG_ATTESTATION_ID_MEID:
+        return "KM_TAG_ATTESTATION_ID_MEID";
+    case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+        return "KM_TAG_ATTESTATION_ID_MANUFACTURER";
+    case KM_TAG_ATTESTATION_ID_MODEL:
+        return "KM_TAG_ATTESTATION_ID_MODEL";
     }
     return "<Unknown>";
 }
@@ -151,6 +169,15 @@
 DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_VERSION);
 DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_APPLICATION_ID);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_BRAND);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
 
 // DEFINE_KEYMASTER_ENUM_TAG is used to create TypedEnumTag instances for each enum keymaster tag.
 
diff --git a/rsa_key_factory.cpp b/rsa_key_factory.cpp
index e6c3f8c..4cae693 100644
--- a/rsa_key_factory.cpp
+++ b/rsa_key_factory.cpp
@@ -27,7 +27,9 @@
 
 namespace keymaster {
 
-const int kMaximumRsaKeySize = 16 * 1024;  // 16kbits should be enough for anyone.
+const int kMaximumRsaKeySize = 4096;  // OpenSSL fails above 4096.
+const int kMinimumRsaKeySize = 16;    // OpenSSL goes into an infinite loop if key size < 10
+const int kMinimumRsaExponent = 3;
 
 static RsaSigningOperationFactory sign_factory;
 static RsaVerificationOperationFactory verify_factory;
@@ -60,7 +62,11 @@
 
     uint64_t public_exponent;
     if (!authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
-        LOG_E("%s", "No public exponent specified for RSA key generation");
+        LOG_E("No public exponent specified for RSA key generation", 0);
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+    if (public_exponent < kMinimumRsaExponent || public_exponent % 2 != 1) {
+        LOG_E("Invalid public exponent specified for RSA key generation", 0);
         return KM_ERROR_INVALID_ARGUMENT;
     }
 
@@ -69,7 +75,7 @@
         LOG_E("No key size specified for RSA key generation", 0);
         return KM_ERROR_UNSUPPORTED_KEY_SIZE;
     }
-    if (key_size % 8 != 0 || key_size > kMaximumRsaKeySize) {
+    if (key_size % 8 != 0 || key_size > kMaximumRsaKeySize || key_size < kMinimumRsaKeySize) {
         LOG_E("Invalid key size of %u bits specified for RSA key generation", key_size);
         return KM_ERROR_UNSUPPORTED_KEY_SIZE;
     }
diff --git a/soft_keymaster_context.cpp b/soft_keymaster_context.cpp
index 5766117..c30dffb 100644
--- a/soft_keymaster_context.cpp
+++ b/soft_keymaster_context.cpp
@@ -17,6 +17,7 @@
 #include <keymaster/soft_keymaster_context.h>
 
 #include <memory>
+
 #include <time.h>
 
 #include <openssl/aes.h>
@@ -340,11 +341,8 @@
     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);
+    // Use default HMAC and AES key factories. Higher layers will pass HMAC/AES keys/ops that are
+    // supported by the hardware to it and other ones to the software-only factory.
 
     return KM_ERROR_OK;
 }
@@ -684,19 +682,23 @@
     else if (km0_engine_)
         return ParseKeymaster0HwBlob(blob, key_material, hw_enforced, sw_enforced);
 
-    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::DeleteKey(const KeymasterKeyBlob& blob) const {
     if (km1_engine_) {
-        keymaster_error_t error = km1_engine_->DeleteKey(blob);
-        if (error == KM_ERROR_INVALID_KEY_BLOB) {
-            // Note that we succeed on invalid blob, because it probably just indicates that the
-            // blob is a software blob, not a hardware blob.
-            error = KM_ERROR_OK;
+        // HACK. Due to a bug with Qualcomm's Keymaster implementation, which causes the device to
+        // reboot if we pass it a key blob it doesn't understand, we need to check for software
+        // keys.  If it looks like a software key there's nothing to do so we just return.
+        KeymasterKeyBlob key_material;
+        AuthorizationSet hw_enforced, sw_enforced;
+        keymaster_error_t error = DeserializeIntegrityAssuredBlob_NoHmacCheck(
+            blob, &key_material, &hw_enforced, &sw_enforced);
+        if (error == KM_ERROR_OK) {
+            return KM_ERROR_OK;
         }
-        return error;
+
+        return km1_engine_->DeleteKey(blob);
     }
 
     if (km0_engine_) {
diff --git a/soft_keymaster_device.cpp b/soft_keymaster_device.cpp
index 35523f7..f0d87ca 100644
--- a/soft_keymaster_device.cpp
+++ b/soft_keymaster_device.cpp
@@ -24,6 +24,7 @@
 #include <time.h>
 
 #include <algorithm>
+#include <vector>
 
 #include <type_traits>
 
@@ -35,6 +36,7 @@
 
 #include <keymaster/android_keymaster.h>
 #include <keymaster/android_keymaster_messages.h>
+#include <keymaster/android_keymaster_utils.h>
 #include <keymaster/authorization_set.h>
 #include <keymaster/soft_keymaster_context.h>
 #include <keymaster/soft_keymaster_logger.h>
@@ -80,9 +82,32 @@
     return std::vector<T>(array, array + len);
 }
 
+// This helper class implements just enough of the C++ standard collection interface to be able to
+// accept push_back calls, and it does nothing but count them.  It's useful when you want to count
+// insertions but not actually store anything.  It's used in digest_set_is_full below to count the
+// size of a set intersection.
+struct PushbackCounter {
+    struct value_type {
+        template <typename T> value_type(const T&) {}
+    };
+    void push_back(const value_type&) { ++count; }
+    size_t count = 0;
+};
+
+static std::vector<keymaster_digest_t> full_digest_list = {
+    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};
+
+template <typename Iter> static bool digest_set_is_full(Iter begin, Iter end) {
+    PushbackCounter counter;
+    std::set_intersection(begin, end, full_digest_list.begin(), full_digest_list.end(),
+                          std::back_inserter(counter));
+    return counter.count == full_digest_list.size();
+}
+
 static keymaster_error_t add_digests(keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
                                      keymaster_purpose_t purpose,
-                                     SoftKeymasterDevice::DigestMap* map) {
+                                     SoftKeymasterDevice::DigestMap* map, bool* supports_all) {
     auto key = std::make_pair(algorithm, purpose);
 
     keymaster_digest_t* digests;
@@ -95,30 +120,39 @@
     }
     std::unique_ptr<keymaster_digest_t, Malloc_Delete> digests_deleter(digests);
 
-    (*map)[key] = make_vector(digests, digests_length);
-    return KM_ERROR_OK;
+    auto digest_vec = make_vector(digests, digests_length);
+    *supports_all = digest_set_is_full(digest_vec.begin(), digest_vec.end());
+    (*map)[key] = std::move(digest_vec);
+    return error;
 }
 
-static keymaster_error_t map_digests(keymaster1_device_t* dev,
-                                     SoftKeymasterDevice::DigestMap* map) {
+static keymaster_error_t map_digests(keymaster1_device_t* dev, SoftKeymasterDevice::DigestMap* map,
+                                     bool* supports_all) {
     map->clear();
+    *supports_all = true;
 
-    keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC};
+    keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC, KM_ALGORITHM_HMAC};
     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);
+            bool alg_purpose_supports_all;
+            keymaster_error_t error =
+                add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
             if (error != KM_ERROR_OK)
                 return error;
+            *supports_all &= alg_purpose_supports_all;
         }
 
     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);
+            bool alg_purpose_supports_all;
+            keymaster_error_t error =
+                add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
             if (error != KM_ERROR_OK)
                 return error;
+            *supports_all &= alg_purpose_supports_all;
         }
 
     return KM_ERROR_OK;
@@ -152,6 +186,7 @@
     if (!context_)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
+    supports_all_digests_ = false;
     keymaster_error_t error = context_->SetHardwareDevice(keymaster0_device);
     if (error != KM_ERROR_OK)
         return error;
@@ -180,7 +215,8 @@
     if (!context_)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
-    keymaster_error_t error = map_digests(keymaster1_device, &km1_device_digests_);
+    keymaster_error_t error =
+        map_digests(keymaster1_device, &km1_device_digests_, &supports_all_digests_);
     if (error != KM_ERROR_OK)
         return error;
 
@@ -337,44 +373,17 @@
     return reinterpret_cast<SoftKeymasterDevice*>(dev->context);
 }
 
-bool FindAlgorithm(const keymaster_key_param_set_t& params, keymaster_algorithm_t* algorithm) {
+template <keymaster_tag_t Tag, keymaster_tag_type_t Type, typename KeymasterEnum>
+bool FindTagValue(const keymaster_key_param_set_t& params,
+                  TypedEnumTag<Type, Tag, KeymasterEnum> tag, KeymasterEnum* value) {
     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);
+        if (params.params[i].tag == tag) {
+            *value = static_cast<KeymasterEnum>(params.params[i].enumerated);
             return true;
         }
     return false;
 }
 
-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;
-}
-
 }  // unnamed namespaced
 
 /* static */
@@ -686,9 +695,9 @@
 
     switch (algorithm) {
     case KM_ALGORITHM_AES:
-    case KM_ALGORITHM_HMAC:
-        LOG_D("Not performing software digesting for algorithm %d", algorithm);
+        LOG_D("Not performing software digesting for AES keys", algorithm);
         return false;
+    case KM_ALGORITHM_HMAC:
     case KM_ALGORITHM_RSA:
     case KM_ALGORITHM_EC:
         break;
@@ -792,8 +801,28 @@
 
     keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
     if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description)) {
+        keymaster_ec_curve_t curve;
+        if (request.key_description.Contains(TAG_ALGORITHM, KM_ALGORITHM_EC) &&
+            request.key_description.GetTagValue(TAG_EC_CURVE, &curve)) {
+            // Keymaster1 doesn't know about EC curves. We need to translate to key size.
+            uint32_t key_size_from_curve;
+            keymaster_error_t error = EcCurveToKeySize(curve, &key_size_from_curve);
+            if (error != KM_ERROR_OK) {
+                return error;
+            }
+
+            uint32_t key_size_from_desc;
+            if (request.key_description.GetTagValue(TAG_KEY_SIZE, &key_size_from_desc)) {
+                if (key_size_from_desc != key_size_from_curve) {
+                    return KM_ERROR_INVALID_ARGUMENT;
+                }
+            } else {
+                request.key_description.push_back(TAG_KEY_SIZE, key_size_from_curve);
+            }
+        }
+
         keymaster_key_characteristics_t* chars_ptr;
-        keymaster_error_t error = km1_dev->generate_key(km1_dev, params, key_blob,
+        keymaster_error_t error = km1_dev->generate_key(km1_dev, &request.key_description, key_blob,
                                                         characteristics ? &chars_ptr : nullptr);
         if (error != KM_ERROR_OK)
             return error;
@@ -839,8 +868,13 @@
 
     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);
+        keymaster_error_t error = km1_dev->get_key_characteristics(km1_dev, key_blob, client_id,
+                                                                   app_data, characteristics);
+        if (error != KM_ERROR_INVALID_KEY_BLOB) {
+            return error;
+        }
+        // If we got "invalid blob", continue to try with the software device. This might be a
+        // software key blob.
     }
 
     GetKeyCharacteristicsRequest request;
@@ -881,18 +915,6 @@
 
     SoftKeymasterDevice* sk_dev = convert_device(dev);
 
-    const keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
-    if (km1_dev) {
-        keymaster_key_characteristics_t* tmp_characteristics;
-        keymaster_error_t error = km1_dev->get_key_characteristics(km1_dev, key_blob, client_id,
-                                                                   app_data, &tmp_characteristics);
-        if (error == KM_ERROR_OK) {
-            *characteristics = *tmp_characteristics;
-            free(tmp_characteristics);
-        }
-        return error;
-    }
-
     GetKeyCharacteristicsRequest request;
     request.SetKeyMaterial(*key_blob);
     AddClientAndAppData(client_id, app_data, &request);
@@ -1181,22 +1203,42 @@
                                              const keymaster_key_param_set_t* in_params,
                                              keymaster_key_param_set_t* out_params,
                                              keymaster_operation_handle_t* operation_handle) {
-    if (!key || !key->key_material)
+    if (!dev || !key || !key->key_material)
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
 
     if (!operation_handle)
         return KM_ERROR_OUTPUT_PARAMETER_NULL;
 
-    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+    SoftKeymasterDevice* skdev = convert_device(dev);
+    const keymaster1_device_t* km1_dev = skdev->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;
+        KeymasterKeyBlob key_material;
+        AuthorizationSet hw_enforced;
+        AuthorizationSet sw_enforced;
+        skdev->context_->ParseKeyBlob(KeymasterKeyBlob(*key), in_params_set, &key_material,
+                                      &hw_enforced, &sw_enforced);
 
-        if (!convert_device(dev)->RequiresSoftwareDigesting(algorithm, purpose, in_params_set)) {
+        keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+        if (!hw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm) &&
+            !sw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) {
+            return KM_ERROR_INVALID_KEY_BLOB;
+        }
+
+        if (algorithm == KM_ALGORITHM_HMAC) {
+            // Because HMAC keys can have only one digest, in_params_set doesn't contain it.  We
+            // need to get the digest from the key and add it to in_params_set.
+            keymaster_digest_t digest;
+            if (!hw_enforced.GetTagValue(TAG_DIGEST, &digest) &&
+                !sw_enforced.GetTagValue(TAG_DIGEST, &digest)) {
+                return KM_ERROR_INVALID_KEY_BLOB;
+            }
+            in_params_set.push_back(TAG_DIGEST, digest);
+        }
+
+        if (!skdev->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);
@@ -1215,7 +1257,7 @@
     request.additional_params.Reinitialize(*in_params);
 
     BeginOperationResponse response;
-    convert_device(dev)->impl_->BeginOperation(request, &response);
+    skdev->impl_->BeginOperation(request, &response);
     if (response.error != KM_ERROR_OK)
         return response.error;
 
@@ -1336,6 +1378,9 @@
                                               const keymaster_blob_t* signature,
                                               keymaster_key_param_set_t* out_params,
                                               keymaster_blob_t* output) {
+    if (!dev)
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
     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
@@ -1385,6 +1430,10 @@
     return KM_ERROR_OK;
 }
 
+struct KeyParamSetContents_Delete {
+    void operator()(keymaster_key_param_set_t* p) { keymaster_free_param_set(p); }
+};
+
 /* static */
 keymaster_error_t SoftKeymasterDevice::finish(const keymaster2_device_t* dev,
                                               keymaster_operation_handle_t operation_handle,
@@ -1399,11 +1448,144 @@
     if (!convert_device(dev)->configured())
         return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
 
-    if (input && input->data)
-        return KM_ERROR_UNIMPLEMENTED;  // TODO(swillden): Implement this
+    if (out_params)
+        *out_params = {};
 
-    SoftKeymasterDevice* sk_dev = convert_device(dev);
-    return finish(&sk_dev->km1_device_, operation_handle, params, signature, out_params, output);
+    if (output)
+        *output = {};
+
+    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.
+
+        std::vector<uint8_t> accumulated_output;
+        AuthorizationSet accumulated_out_params;
+        AuthorizationSet mutable_params(*params);
+        if (input && input->data && input->data_length) {
+            // Keymaster1 doesn't support input to finish().  Call update() to process input.
+
+            accumulated_output.reserve(input->data_length);  // Guess at output size
+            keymaster_blob_t mutable_input = *input;
+
+            while (mutable_input.data_length > 0) {
+                keymaster_key_param_set_t update_out_params = {};
+                keymaster_blob_t update_output = {};
+                size_t input_consumed = 0;
+                keymaster_error_t error =
+                    km1_dev->update(km1_dev, operation_handle, &mutable_params, &mutable_input,
+                                    &input_consumed, &update_out_params, &update_output);
+                if (error != KM_ERROR_OK) {
+                    return error;
+                }
+
+                accumulated_output.reserve(accumulated_output.size() + update_output.data_length);
+                std::copy(update_output.data, update_output.data + update_output.data_length,
+                          std::back_inserter(accumulated_output));
+                free(const_cast<uint8_t*>(update_output.data));
+
+                accumulated_out_params.push_back(update_out_params);
+                keymaster_free_param_set(&update_out_params);
+
+                mutable_input.data += input_consumed;
+                mutable_input.data_length -= input_consumed;
+
+                // AAD should only be sent once, so remove it if present.
+                int aad_pos = mutable_params.find(TAG_ASSOCIATED_DATA);
+                if (aad_pos != -1) {
+                    mutable_params.erase(aad_pos);
+                }
+
+                if (input_consumed == 0) {
+                    // Apparently we need more input than we have to complete an operation.
+                    km1_dev->abort(km1_dev, operation_handle);
+                    return KM_ERROR_INVALID_INPUT_LENGTH;
+                }
+            }
+        }
+
+        keymaster_key_param_set_t finish_out_params = {};
+        keymaster_blob_t finish_output = {};
+        keymaster_error_t error = km1_dev->finish(km1_dev, operation_handle, &mutable_params,
+                                                  signature, &finish_out_params, &finish_output);
+        if (error != KM_ERROR_OK) {
+            return error;
+        }
+
+        if (!accumulated_out_params.empty()) {
+            accumulated_out_params.push_back(finish_out_params);
+            keymaster_free_param_set(&finish_out_params);
+            accumulated_out_params.Deduplicate();
+            accumulated_out_params.CopyToParamSet(&finish_out_params);
+        }
+        std::unique_ptr<keymaster_key_param_set_t, KeyParamSetContents_Delete>
+            finish_out_params_deleter(&finish_out_params);
+
+        if (!accumulated_output.empty()) {
+            size_t finish_out_length = accumulated_output.size() + finish_output.data_length;
+            uint8_t* finish_out_buf = reinterpret_cast<uint8_t*>(malloc(finish_out_length));
+
+            std::copy(accumulated_output.begin(), accumulated_output.end(), finish_out_buf);
+            std::copy(finish_output.data, finish_output.data + finish_output.data_length,
+                      finish_out_buf + accumulated_output.size());
+
+            free(const_cast<uint8_t*>(finish_output.data));
+            finish_output.data_length = finish_out_length;
+            finish_output.data = finish_out_buf;
+        }
+        std::unique_ptr<uint8_t, Malloc_Delete> finish_output_deleter(
+            const_cast<uint8_t*>(finish_output.data));
+
+        if ((!out_params && finish_out_params.length) || (!output && finish_output.data_length)) {
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+        }
+
+        if (out_params) {
+            *out_params = finish_out_params;
+        }
+
+        if (output) {
+            *output = finish_output;
+        }
+
+        finish_out_params_deleter.release();
+        finish_output_deleter.release();
+
+        return KM_ERROR_OK;
+    }
+
+    FinishOperationRequest request;
+    request.op_handle = operation_handle;
+    if (signature && signature->data_length > 0)
+        request.signature.Reinitialize(signature->data, signature->data_length);
+    if (input && input->data_length > 0)
+        request.input.Reinitialize(input->data, input->data_length);
+    request.additional_params.Reinitialize(*params);
+
+    FinishOperationResponse response;
+    convert_device(dev)->impl_->FinishOperation(request, &response);
+    if (response.error != KM_ERROR_OK)
+        return response.error;
+
+    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;
+    } else if (response.output.available_read() > 0) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    return KM_ERROR_OK;
 }
 
 /* static */