Merge "Don't call ERR_error_string in keymaster"
diff --git a/Android.bp b/Android.bp
index c3ab924..0cccde3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,12 +14,30 @@
 
 // libkeymaster_messages contains just the code necessary to communicate with a
 // AndroidKeymaster implementation, e.g. one running in TrustZone.
+cc_defaults {
+    name: "keymaster_defaults",
+    vendor_available: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+    ],
+    clang: true,
+    clang_cflags: [
+        "-Wno-error=unused-const-variable",
+        "-Wno-error=unused-private-field",
+        "-Wimplicit-fallthrough",
+        // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
+        // Currently, if enabled, these flags will cause an internal error in Clang.
+        "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
+    ],
+    sanitize: {
+        integer_overflow: false,
+    },
+}
+
 cc_library_shared {
     name: "libkeymaster_messages",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "android_keymaster/android_keymaster_messages.cpp",
         "android_keymaster/android_keymaster_utils.cpp",
@@ -30,24 +48,19 @@
         "android_keymaster/keymaster_stl.cpp",
     ],
     header_libs: ["libhardware_headers"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused",
+    defaults: ["keymaster_defaults" ],
+    clang_cflags: [
         "-DKEYMASTER_NAME_TAGS",
     ],
     stl: "none",
-    clang: true,
-    clang_cflags: [
-        "-Wimplicit-fallthrough",
-        // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
-        // Currently, if enabled, these flags will cause an internal error in Clang.
-        "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
-    ],
-
     export_include_dirs: ["include"],
-    sanitize: {
-        integer_overflow: false,
+    host_supported: true,
+    target: {
+        host: {
+            clang_cflags: [
+                "-fno-rtti", // TODO(b/156427382): Remove workaround when possible.
+            ],
+        },
     },
 }
 
@@ -57,10 +70,6 @@
 // the function-based keymaster HAL API to the message-based AndroidKeymaster API.
 cc_library {
     name: "libkeymaster_portable",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "android_keymaster/android_keymaster.cpp",
         "android_keymaster/android_keymaster_messages.cpp",
@@ -114,10 +123,8 @@
     ],
     header_libs: ["libhardware_headers"],
     export_header_lib_headers: ["libhardware_headers"],
+    defaults: ["keymaster_defaults" ],
     cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused",
         "-DBORINGSSL_NO_CXX",
     ],
     // NOTE: libkeymaster_portable must run unchanged in the trusty runtime environment.
@@ -125,19 +132,14 @@
     // weakly defines the subset of stl symbols required for this library to work
     // and which are also available in the trusty context.
     stl: "none",
-    clang: true,
-    clang_cflags: [
-        "-Wno-error=unused-const-variable",
-        "-Wno-error=unused-private-field",
-        "-Wimplicit-fallthrough",
-        // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
-        // Currently, if enabled, these flags will cause an internal error in Clang.
-        "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
-    ],
-
+    host_supported: true,
     export_include_dirs: ["include"],
-    sanitize: {
-        integer_overflow: false,
+    target: {
+        host: {
+            clang_cflags: [
+                "-fno-rtti", // TODO(b/156427382): Remove workaround when possible.
+            ],
+        },
     },
 }
 
@@ -146,10 +148,6 @@
 // not support the request.
 cc_library {
     name: "libsoftkeymasterdevice",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "android_keymaster/keymaster_configuration.cpp",
         "legacy_support/ec_keymaster0_key.cpp",
@@ -161,81 +159,88 @@
         "legacy_support/rsa_keymaster1_key.cpp",
         "legacy_support/rsa_keymaster1_operation.cpp",
         "legacy_support/keymaster1_legacy_support.cpp",
-        "contexts/soft_attestation_cert.cpp",
         "contexts/soft_keymaster_context.cpp",
         "contexts/pure_soft_keymaster_context.cpp",
         "contexts/soft_keymaster_device.cpp",
         "km_openssl/soft_keymaster_enforcement.cpp",
         "contexts/soft_keymaster_logger.cpp",
     ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused",
-    ],
-    clang: true,
-    clang_cflags: [
-        "-Wno-error=unused-const-variable",
-        "-Wno-error=unused-private-field",
-        // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
-        // Currently, if enabled, these flags will cause an internal error in Clang.
-        "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
-    ],
-
+    defaults: ["keymaster_defaults"],
     shared_libs: [
         "libkeymaster_messages",
         "libkeymaster_portable",
+        "libsoft_attestation_cert",
         "liblog",
         "libbase",
         "libcrypto",
         "libcutils",
     ],
+    export_include_dirs: ["include"],
+}
 
+cc_library {
+    name: "libsoft_attestation_cert",
+    srcs: [
+        "contexts/soft_attestation_cert.cpp",
+    ],
+    defaults: ["keymaster_defaults"],
+    shared_libs: [
+        "libkeymaster_portable",
+    ],
+
+    host_supported: true,
     export_include_dirs: ["include"],
 }
 
 cc_library {
     name: "libpuresoftkeymasterdevice",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "android_keymaster/keymaster_configuration.cpp",
-        "contexts/soft_attestation_cert.cpp",
         "contexts/pure_soft_keymaster_context.cpp",
         "contexts/soft_keymaster_logger.cpp",
         "km_openssl/soft_keymaster_enforcement.cpp",
     ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused",
-    ],
-    clang: true,
-    clang_cflags: [
-        "-Wno-error=unused-const-variable",
-        "-Wno-error=unused-private-field",
-        // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
-        // Currently, if enabled, these flags will cause an internal error in Clang.
-        "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
-    ],
-
+    defaults: ["keymaster_defaults"],
     shared_libs: [
         "libkeymaster_messages",
         "libkeymaster_portable",
+        "libsoft_attestation_cert",
         "liblog",
         "libcrypto",
         "libcutils",
         "libbase",
     ],
+    export_include_dirs: ["include"],
+}
 
+cc_library {
+    name: "libpuresoftkeymasterdevice_host",
+    srcs: [
+        "contexts/pure_soft_keymaster_context.cpp",
+        "contexts/soft_keymaster_logger.cpp",
+        "km_openssl/soft_keymaster_enforcement.cpp",
+    ],
+    defaults: ["keymaster_defaults"],
+    host_supported: true,
+    device_supported: false,
+    shared_libs: [
+        "libkeymaster_messages",
+        "libkeymaster_portable",
+        "libsoft_attestation_cert",
+        "liblog",
+        "libcrypto",
+        "libcutils",
+        "libbase",
+    ],
+    clang_cflags: [
+        "-DKEYMASTER_NAME_TAGS",
+        "-fno-rtti", // TODO(b/156427382): Remove workaround when possible.
+    ],
     export_include_dirs: ["include"],
 }
 
 cc_library_shared {
     name: "libkeymaster3device",
-    vendor: true,
     srcs: [
         "legacy_support/keymaster_passthrough_key.cpp",
         "legacy_support/keymaster_passthrough_engine.cpp",
@@ -254,20 +259,7 @@
         "legacy_support/rsa_keymaster1_key.cpp",
         "legacy_support/rsa_keymaster1_operation.cpp",
     ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused",
-    ],
-    clang: true,
-    clang_cflags: [
-        "-Wno-error=unused-const-variable",
-        "-Wno-error=unused-private-field",
-        // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
-        // Currently, if enabled, these flags will cause an internal error in Clang.
-        "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
-    ],
-
+    defaults: ["keymaster_defaults"],
     shared_libs: [
         "libkeymaster_messages",
         "android.hardware.keymaster@3.0",
@@ -276,17 +268,16 @@
         "libbase",
         "libhidlbase",
         "libkeymaster_portable",
-        "libpuresoftkeymasterdevice",
         "liblog",
+        "libpuresoftkeymasterdevice",
+        "libsoft_attestation_cert",
         "libutils",
     ],
-
     export_include_dirs: ["include", "ng/include"],
 }
 
 cc_library_shared {
     name: "libkeymaster4",
-    vendor_available: true,
     srcs: [
         "legacy_support/keymaster_passthrough_key.cpp",
         "legacy_support/keymaster_passthrough_engine.cpp",
@@ -294,20 +285,7 @@
         "ng/AndroidKeymaster4Device.cpp",
         "android_keymaster/keymaster_configuration.cpp",
     ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused",
-    ],
-    clang: true,
-    clang_cflags: [
-        "-Wno-error=unused-const-variable",
-        "-Wno-error=unused-private-field",
-        // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released.
-        // Currently, if enabled, these flags will cause an internal error in Clang.
-        "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
-    ],
-
+    defaults: ["keymaster_defaults"],
     shared_libs: [
         "libkeymaster_messages",
         "android.hardware.keymaster@4.0",
@@ -321,7 +299,32 @@
         "libutils",
         "libkeymaster4support",
     ],
+    export_include_dirs: ["ng/include"],
+}
 
+cc_library_shared {
+    name: "libkeymaster41",
+    vendor_available: true,
+    srcs: [
+        "ng/AndroidKeymaster41Device.cpp",
+    ],
+    defaults: ["keymaster_defaults"],
+    shared_libs: [
+        "android.hardware.keymaster@4.0",
+        "android.hardware.keymaster@4.1",
+        "libbase",
+        "libcrypto",
+        "libcutils",
+        "libhidlbase",
+        "libkeymaster4",
+        "libkeymaster4_1support",
+        "libkeymaster4support",
+        "libkeymaster_messages",
+        "libkeymaster_portable",
+        "liblog",
+        "libpuresoftkeymasterdevice",
+        "libutils",
+    ],
     export_include_dirs: ["ng/include"],
 }
 
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: NOTICE
+}
diff --git a/Makefile b/Makefile
index 6d87e06..6b4aa54 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,6 @@
 GTEST=$(BASE)/external/googletest/googletest
 
 INCLUDES=$(foreach dir,$(SUBS),-I $(BASE)/$(dir)/include) \
-	-I $(BASE)/libnativehelper/include/nativehelper \
 	-I $(GTEST)/include -isystem $(GTEST) -Iinclude -I$(BASE)/../boringssl/include
 
 ifdef FORCE_32_BIT
@@ -42,8 +41,8 @@
 CXXFLAGS +=-std=c++14 -fprofile-arcs -ftest-coverage
 CFLAGS += -fprofile-arcs -ftest-coverage
 else
-CC=$(BASE)/prebuilts/clang/host/linux-x86/clang-r353983d/bin/clang
-CXX=$(BASE)/prebuilts/clang/host/linux-x86/clang-r353983d/bin/clang++
+CC=$(BASE)/prebuilts/clang/host/linux-x86/clang-r370808/bin/clang
+CXX=$(BASE)/prebuilts/clang/host/linux-x86/clang-r370808/bin/clang++
 CXXFLAGS +=-std=c++14 -DKEYMASTER_CLANG_TEST_BUILD
 CFLAGS += -DKEYMASTER_CLANG_TEST_BUILD
 endif
diff --git a/android_keymaster/android_keymaster.cpp b/android_keymaster/android_keymaster.cpp
index 195a797..045e04f 100644
--- a/android_keymaster/android_keymaster.cpp
+++ b/android_keymaster/android_keymaster.cpp
@@ -224,7 +224,11 @@
     if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm) ||
         !(factory = context_->GetKeyFactory(algorithm)))
         response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
-    else {
+    else if (context_->enforcement_policy() &&
+             request.key_description.GetTagValue(TAG_EARLY_BOOT_ONLY) &&
+             !context_->enforcement_policy()->in_early_boot()) {
+        response->error = KM_ERROR_EARLY_BOOT_ENDED;
+    } else {
         KeymasterKeyBlob key_blob;
         response->enforced.Clear();
         response->unenforced.Clear();
@@ -529,4 +533,18 @@
     }
 }
 
+EarlyBootEndedResponse AndroidKeymaster::EarlyBootEnded() {
+    if (context_->enforcement_policy()) {
+        context_->enforcement_policy()->early_boot_ended();
+    }
+    return EarlyBootEndedResponse(KM_ERROR_OK);
+}
+
+DeviceLockedResponse AndroidKeymaster::DeviceLocked(const DeviceLockedRequest& request) {
+    if (context_->enforcement_policy()) {
+        context_->enforcement_policy()->device_locked(request.passwordOnly);
+    }
+    return DeviceLockedResponse(KM_ERROR_OK);
+}
+
 }  // namespace keymaster
diff --git a/android_keymaster/android_keymaster_utils.cpp b/android_keymaster/android_keymaster_utils.cpp
index 31fdbf3..fb45fc9 100644
--- a/android_keymaster/android_keymaster_utils.cpp
+++ b/android_keymaster/android_keymaster_utils.cpp
@@ -16,7 +16,7 @@
 
 #include <keymaster/android_keymaster_utils.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 namespace keymaster {
 
diff --git a/android_keymaster/authorization_set.cpp b/android_keymaster/authorization_set.cpp
index 8c09a12..e09b73c 100644
--- a/android_keymaster/authorization_set.cpp
+++ b/android_keymaster/authorization_set.cpp
@@ -21,7 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <keymaster/android_keymaster_utils.h>
 #include <keymaster/logger.h>
diff --git a/android_keymaster/keymaster_enforcement.cpp b/android_keymaster/keymaster_enforcement.cpp
index dc533a0..bfaaf08 100644
--- a/android_keymaster/keymaster_enforcement.cpp
+++ b/android_keymaster/keymaster_enforcement.cpp
@@ -292,6 +292,22 @@
             }
             break;
 
+        case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+            if (device_locked_at_ > 0) {
+                const hw_auth_token_t* auth_token;
+                uint32_t token_auth_type;
+                if (!GetAndValidateAuthToken(operation_params, &auth_token, &token_auth_type)) {
+                    return KM_ERROR_DEVICE_LOCKED;
+                }
+
+                uint64_t token_timestamp_millis = ntoh(auth_token->timestamp);
+                if (token_timestamp_millis <= device_locked_at_ ||
+                    (password_unlock_only_ && !(token_auth_type & HW_AUTH_PASSWORD))) {
+                    return KM_ERROR_DEVICE_LOCKED;
+                }
+            }
+            break;
+
         case KM_TAG_CALLER_NONCE:
             caller_nonce_authorized_by_key = true;
             break;
@@ -311,6 +327,7 @@
         case KM_TAG_ATTESTATION_ID_MEID:
         case KM_TAG_ATTESTATION_ID_MANUFACTURER:
         case KM_TAG_ATTESTATION_ID_MODEL:
+        case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
             return KM_ERROR_INVALID_KEY_BLOB;
 
         /* Tags used for cryptographic parameters in keygen.  Nothing to enforce. */
@@ -337,7 +354,9 @@
         /* Informational tags. */
         case KM_TAG_CREATION_DATETIME:
         case KM_TAG_ORIGIN:
+        case KM_TAG_ROLLBACK_RESISTANCE:
         case KM_TAG_ROLLBACK_RESISTANT:
+        case KM_TAG_USER_ID:
 
         /* Tags handled when KM_TAG_USER_SECURE_ID is handled */
         case KM_TAG_NO_AUTH_REQUIRED:
@@ -364,14 +383,13 @@
         case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
             break;
 
-        /* TODO(bcyoung): This is currently handled in keystore, but may move to keymaster in the
-         * future */
-        case KM_TAG_USER_ID:
-        case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
-            break;
-
+        case KM_TAG_IDENTITY_CREDENTIAL_KEY:
         case KM_TAG_BOOTLOADER_ONLY:
             return KM_ERROR_INVALID_KEY_BLOB;
+
+        case KM_TAG_EARLY_BOOT_ONLY:
+            if (!in_early_boot()) return KM_ERROR_EARLY_BOOT_ENDED;
+            break;
         }
     }
 
@@ -398,7 +416,7 @@
 
     if (update_access_count) {
         if (!access_count_map_) {
-            LOG_S("Usage-count limited keys tabel not allocated.  Count-limited keys disabled", 0);
+            LOG_S("Usage-count limited keys table not allocated.  Count-limited keys disabled", 0);
             return KM_ERROR_MEMORY_ALLOCATION_FAILED;
         }
 
@@ -431,6 +449,38 @@
     return key_access_count < max_uses;
 }
 
+bool KeymasterEnforcement::GetAndValidateAuthToken(const AuthorizationSet& operation_params,
+                                                   const hw_auth_token_t** auth_token,
+                                                   uint32_t* token_auth_type) const {
+    keymaster_blob_t auth_token_blob;
+    if (!operation_params.GetTagValue(TAG_AUTH_TOKEN, &auth_token_blob)) {
+        LOG_E("Authentication required, but auth token not provided", 0);
+        return false;
+    }
+
+    if (auth_token_blob.data_length != sizeof(**auth_token)) {
+        LOG_E("Bug: Auth token is the wrong size (%d expected, %d found)", sizeof(hw_auth_token_t),
+              auth_token_blob.data_length);
+        return false;
+    }
+
+    *auth_token = reinterpret_cast<const hw_auth_token_t*>(auth_token_blob.data);
+    if ((*auth_token)->version != HW_AUTH_TOKEN_VERSION) {
+        LOG_E("Bug: Auth token is the version %d (or is not an auth token). Expected %d",
+              (*auth_token)->version, HW_AUTH_TOKEN_VERSION);
+        return false;
+    }
+
+    if (!ValidateTokenSignature(**auth_token)) {
+        LOG_E("Auth token signature invalid", 0);
+        return false;
+    }
+
+    *token_auth_type = ntoh((*auth_token)->authenticator_type);
+
+    return true;
+}
+
 bool KeymasterEnforcement::AuthTokenMatches(const AuthProxy& auth_set,
                                             const AuthorizationSet& operation_params,
                                             const uint64_t user_secure_id,
@@ -440,39 +490,18 @@
     assert(auth_type_index < static_cast<int>(auth_set.size()));
     assert(auth_timeout_index < static_cast<int>(auth_set.size()));
 
-    keymaster_blob_t auth_token_blob;
-    if (!operation_params.GetTagValue(TAG_AUTH_TOKEN, &auth_token_blob)) {
-        LOG_E("Authentication required, but auth token not provided", 0);
+    const hw_auth_token_t* auth_token;
+    uint32_t token_auth_type;
+    if (!GetAndValidateAuthToken(operation_params, &auth_token, &token_auth_type)) return false;
+
+    if (auth_timeout_index == -1 && op_handle && op_handle != auth_token->challenge) {
+        LOG_E("Auth token has the challenge %llu, need %llu", auth_token->challenge, op_handle);
         return false;
     }
 
-    if (auth_token_blob.data_length != sizeof(hw_auth_token_t)) {
-        LOG_E("Bug: Auth token is the wrong size (%d expected, %d found)", sizeof(hw_auth_token_t),
-              auth_token_blob.data_length);
-        return false;
-    }
-
-    hw_auth_token_t auth_token;
-    memcpy(&auth_token, auth_token_blob.data, sizeof(hw_auth_token_t));
-    if (auth_token.version != HW_AUTH_TOKEN_VERSION) {
-        LOG_E("Bug: Auth token is the version %d (or is not an auth token). Expected %d",
-              auth_token.version, HW_AUTH_TOKEN_VERSION);
-        return false;
-    }
-
-    if (!ValidateTokenSignature(auth_token)) {
-        LOG_E("Auth token signature invalid", 0);
-        return false;
-    }
-
-    if (auth_timeout_index == -1 && op_handle && op_handle != auth_token.challenge) {
-        LOG_E("Auth token has the challenge %llu, need %llu", auth_token.challenge, op_handle);
-        return false;
-    }
-
-    if (user_secure_id != auth_token.user_id && user_secure_id != auth_token.authenticator_id) {
-        LOG_I("Auth token SIDs %llu and %llu do not match key SID %llu", auth_token.user_id,
-              auth_token.authenticator_id, user_secure_id);
+    if (user_secure_id != auth_token->user_id && user_secure_id != auth_token->authenticator_id) {
+        LOG_I("Auth token SIDs %llu and %llu do not match key SID %llu", auth_token->user_id,
+              auth_token->authenticator_id, user_secure_id);
         return false;
     }
 
@@ -486,7 +515,6 @@
         return false;
 
     uint32_t key_auth_type_mask = auth_set[auth_type_index].integer;
-    uint32_t token_auth_type = ntoh(auth_token.authenticator_type);
     if ((key_auth_type_mask & token_auth_type) == 0) {
         LOG_E("Key requires match of auth type mask 0%uo, but token contained 0%uo",
               key_auth_type_mask, token_auth_type);
@@ -498,7 +526,7 @@
         if (auth_set[auth_timeout_index].tag != KM_TAG_AUTH_TIMEOUT)
             return false;
 
-        if (auth_token_timed_out(auth_token, auth_set[auth_timeout_index].integer)) {
+        if (auth_token_timed_out(*auth_token, auth_set[auth_timeout_index].integer)) {
             LOG_E("Auth token has timed out", 0);
             return false;
         }
diff --git a/android_keymaster/keymaster_stl.cpp b/android_keymaster/keymaster_stl.cpp
index 56296b4..5ca9ed5 100644
--- a/android_keymaster/keymaster_stl.cpp
+++ b/android_keymaster/keymaster_stl.cpp
@@ -15,7 +15,7 @@
 ** limitations under the License.
 */
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 #include <stdlib.h>
 
 namespace std {
@@ -24,10 +24,10 @@
 
 extern const std::nothrow_t __attribute__((weak)) std::nothrow = {};
 
-void* __attribute__((weak)) operator new(size_t __sz, const std::nothrow_t&) {
+void* __attribute__((weak)) operator new(size_t __sz, const std::nothrow_t&) _NOEXCEPT {
     return malloc(__sz);
 }
-void* __attribute__((weak)) operator new[](size_t __sz, const std::nothrow_t&) {
+void* __attribute__((weak)) operator new[](size_t __sz, const std::nothrow_t&) _NOEXCEPT {
     return malloc(__sz);
 }
 
diff --git a/android_keymaster/keymaster_tags.cpp b/android_keymaster/keymaster_tags.cpp
index b26d0ee..a92698d 100644
--- a/android_keymaster/keymaster_tags.cpp
+++ b/android_keymaster/keymaster_tags.cpp
@@ -77,6 +77,8 @@
         return "KM_TAG_CREATION_DATETIME";
     case KM_TAG_ORIGIN:
         return "KM_TAG_ORIGIN";
+    case KM_TAG_ROLLBACK_RESISTANCE:
+        return "KM_TAG_ROLLBACK_RESISTANCE";
     case KM_TAG_ROLLBACK_RESISTANT:
         return "KM_TAG_ROLLBACK_RESISTANT";
     case KM_TAG_ROOT_OF_TRUST:
@@ -133,6 +135,12 @@
         return "KM_TAG_ATTESTATION_ID_MANUFACTURER";
     case KM_TAG_ATTESTATION_ID_MODEL:
         return "KM_TAG_ATTESTATION_ID_MODEL";
+    case KM_TAG_EARLY_BOOT_ONLY:
+        return "KM_TAG_EARLY_BOOT_ONLY";
+    case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+        return "KM_TAG_DEVICE_UNIQUE_ATTESTATION";
+    case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+        return "KM_TAG_IDENTITY_CREDENTIAL_KEY";
     }
     return "<Unknown>";
 }
@@ -164,6 +172,7 @@
 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_ID);
 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_DATA);
 DEFINE_KEYMASTER_TAG(KM_DATE, TAG_CREATION_DATETIME);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANCE);
 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANT);
 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ROOT_OF_TRUST);
 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ASSOCIATED_DATA);
@@ -184,6 +193,9 @@
 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_UNLOCKED_DEVICE_REQUIRED);
 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_TRUSTED_CONFIRMATION_REQUIRED);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_EARLY_BOOT_ONLY);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_DEVICE_UNIQUE_ATTESTATION);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_IDENTITY_CREDENTIAL_KEY);
 
 // DEFINE_KEYMASTER_ENUM_TAG is used to create TypedEnumTag instances for each enum keymaster tag.
 
diff --git a/android_keymaster/operation_table.cpp b/android_keymaster/operation_table.cpp
index 2e630c8..ff9d2bb 100644
--- a/android_keymaster/operation_table.cpp
+++ b/android_keymaster/operation_table.cpp
@@ -18,7 +18,7 @@
 #include <keymaster/operation.h>
 #include <keymaster/android_keymaster_utils.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 namespace keymaster {
 
diff --git a/android_keymaster/serializable.cpp b/android_keymaster/serializable.cpp
index 794cdb1..1f795e2 100644
--- a/android_keymaster/serializable.cpp
+++ b/android_keymaster/serializable.cpp
@@ -18,7 +18,7 @@
 
 #include <assert.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <keymaster/android_keymaster_utils.h>
 
diff --git a/contexts/keymaster1_passthrough_context.cpp b/contexts/keymaster1_passthrough_context.cpp
index dab8f37..f0fe65d 100644
--- a/contexts/keymaster1_passthrough_context.cpp
+++ b/contexts/keymaster1_passthrough_context.cpp
@@ -17,19 +17,19 @@
 
 #include <keymaster/contexts/keymaster1_passthrough_context.h>
 
-#include <keymaster/legacy_support/keymaster_passthrough_key.h>
-#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
-#include <keymaster/legacy_support/keymaster1_legacy_support.h>
-#include <keymaster/legacy_support/keymaster1_engine.h>
-#include <keymaster/legacy_support/rsa_keymaster1_key.h>
-#include <keymaster/legacy_support/ec_keymaster1_key.h>
-#include <keymaster/key_blob_utils/software_keyblobs.h>
+#include <keymaster/contexts/soft_attestation_cert.h>
 #include <keymaster/key_blob_utils/integrity_assured_key_blob.h>
 #include <keymaster/key_blob_utils/ocb_utils.h>
+#include <keymaster/key_blob_utils/software_keyblobs.h>
 #include <keymaster/km_openssl/aes_key.h>
-#include <keymaster/km_openssl/hmac_key.h>
 #include <keymaster/km_openssl/attestation_utils.h>
-#include "soft_attestation_cert.h"
+#include <keymaster/km_openssl/hmac_key.h>
+#include <keymaster/legacy_support/ec_keymaster1_key.h>
+#include <keymaster/legacy_support/keymaster1_engine.h>
+#include <keymaster/legacy_support/keymaster1_legacy_support.h>
+#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
+#include <keymaster/legacy_support/keymaster_passthrough_key.h>
+#include <keymaster/legacy_support/rsa_keymaster1_key.h>
 
 namespace keymaster {
 
diff --git a/contexts/pure_soft_keymaster_context.cpp b/contexts/pure_soft_keymaster_context.cpp
index b4d1fb7..33dc6dc 100644
--- a/contexts/pure_soft_keymaster_context.cpp
+++ b/contexts/pure_soft_keymaster_context.cpp
@@ -44,18 +44,18 @@
 #include <keymaster/operation.h>
 #include <keymaster/wrapped_key.h>
 
-#include "soft_attestation_cert.h"
+#include <keymaster/contexts/soft_attestation_cert.h>
 
 using std::unique_ptr;
 
 namespace keymaster {
 
-PureSoftKeymasterContext::PureSoftKeymasterContext()
+PureSoftKeymasterContext::PureSoftKeymasterContext(keymaster_security_level_t security_level)
     : rsa_factory_(new RsaKeyFactory(this)), ec_factory_(new EcKeyFactory(this)),
       aes_factory_(new AesKeyFactory(this, this)),
       tdes_factory_(new TripleDesKeyFactory(this, this)),
       hmac_factory_(new HmacKeyFactory(this, this)), os_version_(0), os_patchlevel_(0),
-      soft_keymaster_enforcement_(64, 64) {}
+      soft_keymaster_enforcement_(64, 64), security_level_(security_level) {}
 
 PureSoftKeymasterContext::~PureSoftKeymasterContext() {}
 
@@ -106,20 +106,58 @@
 }
 
 keymaster_error_t PureSoftKeymasterContext::CreateKeyBlob(const AuthorizationSet& key_description,
-                                                      const keymaster_key_origin_t origin,
-                                                      const KeymasterKeyBlob& key_material,
-                                                      KeymasterKeyBlob* blob,
-                                                      AuthorizationSet* hw_enforced,
-                                                      AuthorizationSet* sw_enforced) const {
+                                                          const keymaster_key_origin_t origin,
+                                                          const KeymasterKeyBlob& key_material,
+                                                          KeymasterKeyBlob* blob,
+                                                          AuthorizationSet* hw_enforced,
+                                                          AuthorizationSet* sw_enforced) const {
+    if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) {
+        return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
+    }
+
+    if (GetSecurityLevel() != KM_SECURITY_LEVEL_SOFTWARE) {
+        // We're pretending to be some sort of secure hardware.  Put relevant tags in hw_enforced.
+        for (auto& entry : key_description) {
+            switch (entry.tag) {
+            case KM_TAG_PURPOSE:
+            case KM_TAG_ALGORITHM:
+            case KM_TAG_KEY_SIZE:
+            case KM_TAG_RSA_PUBLIC_EXPONENT:
+            case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+            case KM_TAG_DIGEST:
+            case KM_TAG_PADDING:
+            case KM_TAG_BLOCK_MODE:
+            case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+            case KM_TAG_MAX_USES_PER_BOOT:
+            case KM_TAG_USER_SECURE_ID:
+            case KM_TAG_NO_AUTH_REQUIRED:
+            case KM_TAG_AUTH_TIMEOUT:
+            case KM_TAG_CALLER_NONCE:
+            case KM_TAG_MIN_MAC_LENGTH:
+            case KM_TAG_KDF:
+            case KM_TAG_EC_CURVE:
+            case KM_TAG_ECIES_SINGLE_HASH_MODE:
+            case KM_TAG_USER_AUTH_TYPE:
+            case KM_TAG_ORIGIN:
+            case KM_TAG_OS_VERSION:
+            case KM_TAG_OS_PATCHLEVEL:
+            case KM_TAG_EARLY_BOOT_ONLY:
+            case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+                hw_enforced->push_back(entry);
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
     keymaster_error_t error = SetKeyBlobAuthorizations(key_description, origin, os_version_,
                                                        os_patchlevel_, hw_enforced, sw_enforced);
-    if (error != KM_ERROR_OK)
-        return error;
+    if (error != KM_ERROR_OK) return error;
 
     AuthorizationSet hidden;
     error = BuildHiddenAuthorizations(key_description, &hidden, softwareRootOfTrust);
-    if (error != KM_ERROR_OK)
-        return error;
+    if (error != KM_ERROR_OK) return error;
 
     return SerializeIntegrityAssuredBlob(key_material, hidden, *hw_enforced, *sw_enforced, blob);
 }
@@ -281,7 +319,7 @@
     UniquePtr<Key> key;
     auto wrapping_key_params = AuthorizationSetBuilder()
                                    .RsaEncryptionKey(2048, 65537)
-                                   .Digest(KM_DIGEST_SHA1)
+                                   .Digest(KM_DIGEST_SHA_2_256)
                                    .Padding(KM_PAD_RSA_OAEP)
                                    .Authorization(TAG_PURPOSE, KM_PURPOSE_WRAP)
                                    .build();
@@ -406,4 +444,16 @@
     return error;
 }
 
+keymaster_error_t PureSoftKeymasterContext::GetVerifiedBootParams(
+    keymaster_blob_t* verified_boot_key, keymaster_blob_t* verified_boot_hash,
+    keymaster_verified_boot_t* verified_boot_state, bool* device_locked) const {
+    // TODO(swillden): See if there might be some sort of vbmeta data in goldfish/cuttlefish.
+    static std::string fake_vb_key(32, 0);
+    *verified_boot_key = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
+    *verified_boot_hash = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
+    *verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
+    *device_locked = false;
+    return KM_ERROR_OK;
+}
+
 }  // namespace keymaster
diff --git a/contexts/soft_attestation_cert.cpp b/contexts/soft_attestation_cert.cpp
index cc9d104..c9142e3 100644
--- a/contexts/soft_attestation_cert.cpp
+++ b/contexts/soft_attestation_cert.cpp
@@ -15,12 +15,11 @@
 ** limitations under the License.
 */
 
-#include "soft_attestation_cert.h"
+#include <keymaster/contexts/soft_attestation_cert.h>
 
 #include <stdint.h>
 #include <hardware/keymaster_defs.h>
 #include <keymaster/android_keymaster_utils.h>
-#include <openssl/aes.h>
 
 namespace keymaster {
 
diff --git a/contexts/soft_keymaster_context.cpp b/contexts/soft_keymaster_context.cpp
index a0a42d3..5003c72 100644
--- a/contexts/soft_keymaster_context.cpp
+++ b/contexts/soft_keymaster_context.cpp
@@ -38,7 +38,7 @@
 #include <keymaster/legacy_support/rsa_keymaster1_key.h>
 #include <keymaster/logger.h>
 
-#include "soft_attestation_cert.h"
+#include <keymaster/contexts/soft_attestation_cert.h>
 
 using std::unique_ptr;
 
@@ -476,4 +476,16 @@
     return KM_ERROR_UNIMPLEMENTED;
 }
 
+keymaster_error_t SoftKeymasterContext::GetVerifiedBootParams(
+    keymaster_blob_t* verified_boot_key, keymaster_blob_t* verified_boot_hash,
+    keymaster_verified_boot_t* verified_boot_state, bool* device_locked) const {
+    // TODO(swillden): See if there might be some sort of vbmeta data in goldfish/cuttlefish.
+    static std::string fake_vb_key(32, 0);
+    *verified_boot_key = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
+    *verified_boot_hash = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
+    *verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
+    *device_locked = false;
+    return KM_ERROR_OK;
+}
+
 }  // namespace keymaster
diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h
index 2836464..383c9da 100644
--- a/include/keymaster/android_keymaster.h
+++ b/include/keymaster/android_keymaster.h
@@ -87,6 +87,9 @@
     void FinishOperation(const FinishOperationRequest& request, FinishOperationResponse* response);
     void AbortOperation(const AbortOperationRequest& request, AbortOperationResponse* response);
 
+    EarlyBootEndedResponse EarlyBootEnded();
+    DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
+
     bool has_operation(keymaster_operation_handle_t op_handle) const;
 
   private:
diff --git a/include/keymaster/android_keymaster_messages.h b/include/keymaster/android_keymaster_messages.h
index 116dfc2..4dbabd7 100644
--- a/include/keymaster/android_keymaster_messages.h
+++ b/include/keymaster/android_keymaster_messages.h
@@ -55,6 +55,8 @@
     DELETE_ALL_KEYS = 23,
     DESTROY_ATTESTATION_IDS = 24,
     IMPORT_WRAPPED_KEY = 25,
+    EARLY_BOOT_ENDED = 26,
+    DEVICE_LOCKED = 27,
 };
 
 /**
@@ -423,6 +425,10 @@
 
 struct AbortOperationResponse : public KeymasterResponse {
     explicit AbortOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
+    explicit AbortOperationResponse(keymaster_error_t error_, int32_t ver = MAX_MESSAGE_VERSION)
+        : KeymasterResponse(ver) {
+        error = error_;
+    }
 
     size_t NonErrorSerializedSize() const override { return 0; }
     uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
@@ -902,6 +908,31 @@
     VerificationToken token;
 };
 
+// These return nothing but an error code, like AbortOperationResponse so might as well use that.
+using EarlyBootEndedResponse = AbortOperationResponse;
+using DeviceLockedResponse = AbortOperationResponse;
+
+struct DeviceLockedRequest : public KeymasterMessage {
+    explicit DeviceLockedRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+    explicit DeviceLockedRequest(bool passwordOnly_, VerificationToken&& token_,
+                                 int32_t ver = MAX_MESSAGE_VERSION)
+        : KeymasterMessage(ver), passwordOnly(passwordOnly_), token(move(token_)) {}
+
+    size_t SerializedSize() const override { return 1; }
+    uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+        if (buf < end) *buf++ = passwordOnly ? 1 : 0;
+        return token.Serialize(buf, end);
+    }
+    bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+        if (*buf_ptr >= end) return false;
+        passwordOnly = !!*(*buf_ptr)++;
+        return token.Deserialize(buf_ptr, end);
+    }
+
+    bool passwordOnly;
+    VerificationToken token;
+};
+
 }  // namespace keymaster
 
 #endif  // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_
diff --git a/include/keymaster/attestation_record.h b/include/keymaster/attestation_record.h
index 1f662d6..17a6429 100644
--- a/include/keymaster/attestation_record.h
+++ b/include/keymaster/attestation_record.h
@@ -25,6 +25,8 @@
 
 namespace keymaster {
 
+constexpr uint kCurrentKeymasterVersion = 41;
+
 struct stack_st_ASN1_TYPE_Delete {
     void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
 };
@@ -41,7 +43,7 @@
 
 typedef struct km_root_of_trust {
     ASN1_OCTET_STRING* verified_boot_key;
-    ASN1_BOOLEAN* device_locked;
+    ASN1_BOOLEAN device_locked;
     ASN1_ENUMERATED* verified_boot_state;
     ASN1_OCTET_STRING* verified_boot_hash;
 } KM_ROOT_OF_TRUST;
@@ -79,6 +81,7 @@
     ASN1_OCTET_STRING* application_id;
     ASN1_INTEGER* creation_date_time;
     ASN1_INTEGER* origin;
+    ASN1_NULL* rollback_resistance;
     ASN1_NULL* rollback_resistant;
     KM_ROOT_OF_TRUST* root_of_trust;
     ASN1_INTEGER* os_version;
@@ -92,6 +95,9 @@
     ASN1_OCTET_STRING* attestation_id_meid;
     ASN1_OCTET_STRING* attestation_id_manufacturer;
     ASN1_OCTET_STRING* attestation_id_model;
+    ASN1_NULL* early_boot_only;
+    ASN1_NULL* device_unique_attestation;
+    ASN1_NULL* identity_credential_key;
 } KM_AUTH_LIST;
 
 ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -124,6 +130,8 @@
     ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
                  TAG_CREATION_DATETIME.masked_tag()),
     ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
+                 TAG_ROLLBACK_RESISTANCE.masked_tag()),
     ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistant, ASN1_NULL, TAG_ROLLBACK_RESISTANT.masked_tag()),
     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()),
@@ -146,6 +154,11 @@
                  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_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
+                 TAG_DEVICE_UNIQUE_ATTESTATION.masked_tag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
+                 TAG_IDENTITY_CREDENTIAL_KEY.masked_tag()),
 } ASN1_SEQUENCE_END(KM_AUTH_LIST);
 DECLARE_ASN1_FUNCTIONS(KM_AUTH_LIST);
 
@@ -215,6 +228,7 @@
      */
     virtual keymaster_error_t
     GetVerifiedBootParams(keymaster_blob_t* /* verified_boot_key */,
+                          keymaster_blob_t* /* verified_boot_hash */,
                           keymaster_verified_boot_t* /* verified_boot_state */,
                           bool* /* device_locked */) const {
         return KM_ERROR_UNIMPLEMENTED;
@@ -237,6 +251,8 @@
  */
 static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
 
+// This build_attestation_record sets the keymaster version to the default
+// value.
 keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
                                            AuthorizationSet software_enforced,
                                            AuthorizationSet tee_enforced,
@@ -244,6 +260,14 @@
                                            UniquePtr<uint8_t[]>* asn1_key_desc,
                                            size_t* asn1_key_desc_len);
 
+// Builds attestation record, same as above, except this allows the keymaster
+// version to be set to different value than the default.
+keymaster_error_t
+build_attestation_record(const AuthorizationSet& attestation_params, AuthorizationSet sw_enforced,
+                         AuthorizationSet tee_enforced, const AttestationRecordContext& context,
+                         const uint keymaster_version, UniquePtr<uint8_t[]>* asn1_key_desc,
+                         size_t* asn1_key_desc_len);
+
 /**
  * Helper functions for attestation record tests. Caller takes ownership of
  * |attestation_challenge->data| and |unique_id->data|, deallocate using delete[].
diff --git a/include/keymaster/authorization_set.h b/include/keymaster/authorization_set.h
index 11ffc30..b4a3b27 100644
--- a/include/keymaster/authorization_set.h
+++ b/include/keymaster/authorization_set.h
@@ -82,6 +82,9 @@
     explicit AuthorizationSet(/* NOT const */ AuthorizationSetBuilder& builder);
 
     // Copy constructor.
+    // A copy constructor normal should call a base class copy constructor,
+    // but Serializable is special without copy constructor.
+    // NOLINTNEXTLINE(bugprone-copy-constructor-init)
     AuthorizationSet(const AuthorizationSet& set)
         : Serializable(), elems_capacity_(0), indirect_data_(nullptr), indirect_data_size_(0),
           indirect_data_capacity_(0), error_(OK) {
diff --git a/include/keymaster/contexts/pure_soft_keymaster_context.h b/include/keymaster/contexts/pure_soft_keymaster_context.h
index 3a1156d..66a7b49 100644
--- a/include/keymaster/contexts/pure_soft_keymaster_context.h
+++ b/include/keymaster/contexts/pure_soft_keymaster_context.h
@@ -38,12 +38,14 @@
 /**
  * SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster.
  */
-class PureSoftKeymasterContext: public KeymasterContext,
-        protected SoftwareKeyBlobMaker,
-        AttestationRecordContext,
-        SoftwareRandomSource {
+class PureSoftKeymasterContext : public KeymasterContext,
+                                 protected SoftwareKeyBlobMaker,
+                                 public AttestationRecordContext,
+                                 SoftwareRandomSource {
   public:
-    explicit PureSoftKeymasterContext();
+    // Security level must only be used for testing.
+    explicit PureSoftKeymasterContext(
+        keymaster_security_level_t security_level = KM_SECURITY_LEVEL_SOFTWARE);
     ~PureSoftKeymasterContext() override;
 
     /*********************************************************************************************
@@ -90,6 +92,17 @@
               AuthorizationSet* wrapped_key_params, keymaster_key_format_t* wrapped_key_format,
               KeymasterKeyBlob* wrapped_key_material) const override;
 
+    /*********************************************************************************************
+     * Implement AttestationRecordContext
+     */
+
+    keymaster_error_t GetVerifiedBootParams(keymaster_blob_t* verified_boot_key,
+                                            keymaster_blob_t* verified_boot_hash,
+                                            keymaster_verified_boot_t* verified_boot_state,
+                                            bool* device_locked) const override;
+
+    keymaster_security_level_t GetSecurityLevel() const override { return security_level_; }
+
   protected:
     std::unique_ptr<KeyFactory> rsa_factory_;
     std::unique_ptr<KeyFactory> ec_factory_;
@@ -99,6 +112,7 @@
     uint32_t os_version_;
     uint32_t os_patchlevel_;
     SoftKeymasterEnforcement soft_keymaster_enforcement_;
+    keymaster_security_level_t security_level_;
 };
 
 }  // namespace keymaster
diff --git a/contexts/soft_attestation_cert.h b/include/keymaster/contexts/soft_attestation_cert.h
similarity index 97%
rename from contexts/soft_attestation_cert.h
rename to include/keymaster/contexts/soft_attestation_cert.h
index a508ff8..597c90b 100644
--- a/contexts/soft_attestation_cert.h
+++ b/include/keymaster/contexts/soft_attestation_cert.h
@@ -27,5 +27,5 @@
 const keymaster_cert_chain_t* getAttestationChain(keymaster_algorithm_t algorithm,
                                                   keymaster_error_t* error);
 
-}
+}  // namespace keymaster
 #endif  // SOFTWARE_CONTEXT_SOFT_ATTESTATION_CERT_H_
diff --git a/include/keymaster/contexts/soft_keymaster_context.h b/include/keymaster/contexts/soft_keymaster_context.h
index 588e3db..20a10ac 100644
--- a/include/keymaster/contexts/soft_keymaster_context.h
+++ b/include/keymaster/contexts/soft_keymaster_context.h
@@ -104,6 +104,15 @@
                                     AuthorizationSet* sw_enforced) const override;
     /*********************************************************************************************/
 
+    /*********************************************************************************************
+     * Implement AttestationRecordContext
+     */
+
+    keymaster_error_t GetVerifiedBootParams(keymaster_blob_t* verified_boot_key,
+                                            keymaster_blob_t* verified_boot_hash,
+                                            keymaster_verified_boot_t* verified_boot_state,
+                                            bool* device_locked) const override;
+
   private:
     keymaster_error_t ParseKeymaster1HwBlob(const KeymasterKeyBlob& blob,
                                             const AuthorizationSet& additional_params,
diff --git a/include/keymaster/keymaster_enforcement.h b/include/keymaster/keymaster_enforcement.h
index 4e33aff..8aa9984 100644
--- a/include/keymaster/keymaster_enforcement.h
+++ b/include/keymaster/keymaster_enforcement.h
@@ -133,6 +133,11 @@
     virtual uint64_t get_current_time_ms() const = 0;
 
     /*
+     * Get whether or not we're in early boot.  See early_boot_ended() below.
+     */
+    bool in_early_boot() const { return in_early_boot_; }
+
+    /*
      * Get current time in seconds from some starting point.  This value is used to compute relative
      * times between events.  It must be monotonically increasing, and must not skip or lag.  It
      * need not have any relation to any external time standard (other than the duration of
@@ -179,6 +184,22 @@
      */
     virtual bool CreateKeyId(const keymaster_key_blob_t& key_blob, km_id_t* keyid) const = 0;
 
+    /*
+     * Inform the KeymasterEnforcement object that early boot stage has ended.
+     */
+    void early_boot_ended() { in_early_boot_ = false; }
+
+    /*
+     * Inform the KeymasterEnforcement object that the device is locked, so it knows not to permit
+     * UNLOCKED_DEVICE_REQUIRED keys to be used until a fresh (later than "now") auth token is
+     * provided.  If password_only is true, the fresh auth token must additionally be a password
+     * auth token.
+     */
+    void device_locked(bool password_only) {
+        device_locked_at_ = get_current_time_ms();
+        password_unlock_only_ = password_only;
+    }
+
   private:
     keymaster_error_t AuthorizeUpdateOrFinish(const AuthProxy& auth_set,
                                               const AuthorizationSet& operation_params,
@@ -186,6 +207,8 @@
 
     bool MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid);
     bool MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses);
+    bool GetAndValidateAuthToken(const AuthorizationSet& operation_params,
+                                 const hw_auth_token_t** token, uint32_t* token_auth_type) const;
     bool AuthTokenMatches(const AuthProxy& auth_set, const AuthorizationSet& operation_params,
                           const uint64_t user_secure_id, const int auth_type_index,
                           const int auth_timeout_index,
@@ -194,6 +217,9 @@
 
     AccessTimeMap* access_time_map_;
     AccessCountMap* access_count_map_;
+    bool in_early_boot_ = false;  // TODO(swillden): default to true when vold sends signal.
+    uint64_t device_locked_at_ = 0;
+    bool password_unlock_only_ = false;
 };
 
 }; /* namespace keymaster */
diff --git a/include/keymaster/keymaster_tags.h b/include/keymaster/keymaster_tags.h
index daa7b19..321e92f 100644
--- a/include/keymaster/keymaster_tags.h
+++ b/include/keymaster/keymaster_tags.h
@@ -159,6 +159,7 @@
 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_ID);
 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_DATA);
 DECLARE_KEYMASTER_TAG(KM_DATE, TAG_CREATION_DATETIME);
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANCE);
 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANT);
 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ROOT_OF_TRUST);
 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ASSOCIATED_DATA);
@@ -179,6 +180,9 @@
 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_TAG(KM_BOOL, TAG_EARLY_BOOT_ONLY);
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_DEVICE_UNIQUE_ATTESTATION);
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_IDENTITY_CREDENTIAL_KEY);
 
 // 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/km_openssl/attestation_utils.h b/include/keymaster/km_openssl/attestation_utils.h
index 063fb2c..e30d90f 100644
--- a/include/keymaster/km_openssl/attestation_utils.h
+++ b/include/keymaster/km_openssl/attestation_utils.h
@@ -31,12 +31,39 @@
 class AttestationRecordContext;
 class AsymmetricKey;
 
-
+// Generate attestation certificate base on the AsymmetricKey key and other parameters
+// passed in.  In attest_params, we expect the challenge, active time and expiration
+// time, and app id.
+//
+// The active time and expiration time are expected in milliseconds.
+//
+// Hardware and software enforced AuthorizationSet are expected to be built into the AsymmetricKey
+// input. In hardware enforced AuthorizationSet, we expect hardware related tags such as
+// TAG_IDENTITY_CREDENTIAL_KEY.
 keymaster_error_t generate_attestation(const AsymmetricKey& key,
         const AuthorizationSet& attest_params, const keymaster_cert_chain_t& attestation_chain,
         const keymaster_key_blob_t& attestation_signing_key,
         const AttestationRecordContext& context, CertChainPtr* cert_chain_out);
 
+// Generate attestation certificate based on the EVP key and other parameters
+// passed in.  Note that due to sub sub sub call setup, there are 3 AuthorizationSet passed in,
+// hardware, software, and general.  In attest_params, we expect the challenge,
+// active time and expiration time, and app id.  In hw_enforced, we expect
+// hardware related tags such as TAG_IDENTITY_CREDENTIAL_KEY.
+//
+// The active time and expiration time are expected in milliseconds since Jan 1,
+// 1970.
+keymaster_error_t generate_attestation_from_EVP(
+    const EVP_PKEY* evp_key,                  // input
+    const AuthorizationSet& sw_enforced,      // input
+    const AuthorizationSet& hw_enforced,      // input
+    const AuthorizationSet& attest_params,    // input. Sub function require app id to be set here.
+    const AttestationRecordContext& context,  // input
+    const uint keymaster_version,             // input
+    const keymaster_cert_chain_t& attestation_chain,      // input
+    const keymaster_key_blob_t& attestation_signing_key,  // input
+    CertChainPtr* cert_chain_out);                        // Output.
+
 } // namespace keymaster
 
 #endif  // KM_OPENSSL_ATTESTATION_UTILS_H_
diff --git a/include/keymaster/new b/include/keymaster/new.h
similarity index 97%
rename from include/keymaster/new
rename to include/keymaster/new.h
index b4786db..17537e0 100644
--- a/include/keymaster/new
+++ b/include/keymaster/new.h
@@ -23,7 +23,7 @@
 namespace std {
 struct nothrow_t;
 extern const nothrow_t nothrow;
-}
+}  // namespace std
 
 #ifndef _NOEXCEPT
 #define _NOEXCEPT
diff --git a/include/keymaster/serializable.h b/include/keymaster/serializable.h
index 9f69f44..575b691 100644
--- a/include/keymaster/serializable.h
+++ b/include/keymaster/serializable.h
@@ -21,8 +21,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <keymaster/new.h>
 #include <stddef.h>
-#include <keymaster/new>
 // #include <new>
 
 #include <keymaster/UniquePtr.h>
diff --git a/key_blob_utils/integrity_assured_key_blob.cpp b/key_blob_utils/integrity_assured_key_blob.cpp
index 35b5390..014855e 100644
--- a/key_blob_utils/integrity_assured_key_blob.cpp
+++ b/key_blob_utils/integrity_assured_key_blob.cpp
@@ -24,8 +24,7 @@
 #include <keymaster/android_keymaster_utils.h>
 #include <keymaster/authorization_set.h>
 #include <keymaster/km_openssl/openssl_err.h>
-#include <keymaster/new>
-
+#include <keymaster/new.h>
 
 namespace keymaster {
 
diff --git a/key_blob_utils/ocb_utils.cpp b/key_blob_utils/ocb_utils.cpp
index 409029c..d58d2df 100644
--- a/key_blob_utils/ocb_utils.cpp
+++ b/key_blob_utils/ocb_utils.cpp
@@ -23,11 +23,10 @@
 
 #include <hardware/keymaster_defs.h>
 
-#include <keymaster/authorization_set.h>
 #include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
 #include <keymaster/km_openssl/openssl_err.h>
-#include <keymaster/new>
-
+#include <keymaster/new.h>
 
 namespace keymaster {
 
diff --git a/key_blob_utils/software_keyblobs.cpp b/key_blob_utils/software_keyblobs.cpp
index c490631..60719bb 100644
--- a/key_blob_utils/software_keyblobs.cpp
+++ b/key_blob_utils/software_keyblobs.cpp
@@ -292,10 +292,16 @@
         }
     }
 
-    sw_enforced->push_back(TAG_CREATION_DATETIME, java_time(time(nullptr)));
-    sw_enforced->push_back(TAG_ORIGIN, origin);
-    sw_enforced->push_back(TAG_OS_VERSION, os_version);
-    sw_enforced->push_back(TAG_OS_PATCHLEVEL, os_patchlevel);
+    // If hw_enforced is non-empty, we're pretending to be some sort of secure hardware.
+    AuthorizationSet* pseudo_hw_enforced = (hw_enforced->empty()) ? sw_enforced : hw_enforced;
+    pseudo_hw_enforced->push_back(TAG_ORIGIN, origin);
+    pseudo_hw_enforced->push_back(TAG_OS_VERSION, os_version);
+    pseudo_hw_enforced->push_back(TAG_OS_PATCHLEVEL, os_patchlevel);
+
+    // Honor caller creation, if provided.
+    if (!sw_enforced->Contains(TAG_CREATION_DATETIME)) {
+        sw_enforced->push_back(TAG_CREATION_DATETIME, java_time(time(nullptr)));
+    }
 
     return TranslateAuthorizationSetError(sw_enforced->is_valid());
 }
diff --git a/km_openssl/aes_key.cpp b/km_openssl/aes_key.cpp
index 5bb6a24..0e1a756 100644
--- a/km_openssl/aes_key.cpp
+++ b/km_openssl/aes_key.cpp
@@ -18,7 +18,7 @@
 
 #include <assert.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <openssl/err.h>
 #include <openssl/rand.h>
diff --git a/km_openssl/asymmetric_key.cpp b/km_openssl/asymmetric_key.cpp
index 7e459a0..511e43a 100644
--- a/km_openssl/asymmetric_key.cpp
+++ b/km_openssl/asymmetric_key.cpp
@@ -16,7 +16,7 @@
 
 #include <keymaster/km_openssl/asymmetric_key.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <openssl/asn1.h>
 #include <openssl/stack.h>
diff --git a/km_openssl/attestation_record.cpp b/km_openssl/attestation_record.cpp
index 35114ca..4f70138 100644
--- a/km_openssl/attestation_record.cpp
+++ b/km_openssl/attestation_record.cpp
@@ -26,8 +26,7 @@
 
 namespace keymaster {
 
-constexpr uint kCurrentKeymasterVersion = 4;
-constexpr uint kCurrentAttestationVersion = 3;
+constexpr uint kCurrentAttestationVersion = 4;
 constexpr size_t kMaximumAttestationChallengeLength = 128;
 
 IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
@@ -53,6 +52,10 @@
     void operator()(KM_KEY_DESCRIPTION* p) { KM_KEY_DESCRIPTION_free(p); }
 };
 
+struct KM_ROOT_OF_TRUST_Delete {
+    void operator()(KM_ROOT_OF_TRUST* p) { KM_ROOT_OF_TRUST_free(p); }
+};
+
 static uint32_t get_uint32_value(const keymaster_key_param_t& param) {
     switch (keymaster_tag_get_type(param.tag)) {
     case KM_ENUM:
@@ -220,6 +223,9 @@
         case KM_TAG_ROLLBACK_RESISTANT:
             bool_ptr = &record->rollback_resistant;
             break;
+        case KM_TAG_ROLLBACK_RESISTANCE:
+            bool_ptr = &record->rollback_resistance;
+            break;
         case KM_TAG_ALLOW_WHILE_ON_BODY:
             bool_ptr = &record->allow_while_on_body;
             break;
@@ -232,6 +238,15 @@
         case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
             bool_ptr = &record->trusted_confirmation_required;
             break;
+        case KM_TAG_EARLY_BOOT_ONLY:
+            bool_ptr = &record->early_boot_only;
+            break;
+        case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+            bool_ptr = &record->device_unique_attestation;
+            break;
+        case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+            bool_ptr = &record->identity_credential_key;
+            break;
 
         /* Byte arrays*/
         case KM_TAG_APPLICATION_ID:
@@ -364,69 +379,55 @@
 
 // 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,
-                                           AuthorizationSet sw_enforced,
-                                           AuthorizationSet tee_enforced,
-                                           const AttestationRecordContext& context,
-                                           UniquePtr<uint8_t[]>* asn1_key_desc,
-                                           size_t* asn1_key_desc_len) {
+keymaster_error_t
+build_attestation_record(const AuthorizationSet& attestation_params, AuthorizationSet sw_enforced,
+                         AuthorizationSet tee_enforced, const AttestationRecordContext& context,
+                         const uint keymaster_version, UniquePtr<uint8_t[]>* asn1_key_desc,
+                         size_t* asn1_key_desc_len) {
     assert(asn1_key_desc && asn1_key_desc_len);
 
     UniquePtr<KM_KEY_DESCRIPTION, KM_KEY_DESCRIPTION_Delete> key_desc(KM_KEY_DESCRIPTION_new());
     if (!key_desc.get())
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
 
-    keymaster_security_level_t keymaster_security_level;
-    uint32_t keymaster_version = UINT32_MAX;
-    if (tee_enforced.empty()) {
-        // Software key.
-        keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
-        keymaster_version = kCurrentKeymasterVersion;
+    KM_ROOT_OF_TRUST* root_of_trust = nullptr;
+    if (context.GetSecurityLevel() == KM_SECURITY_LEVEL_SOFTWARE) {
+        key_desc->software_enforced->root_of_trust = KM_ROOT_OF_TRUST_new();
+        root_of_trust = key_desc->software_enforced->root_of_trust;
     } else {
-        keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
-        switch (context.GetSecurityLevel()) {
-        case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT: {
-            keymaster_version = kCurrentKeymasterVersion;
+        key_desc->tee_enforced->root_of_trust = KM_ROOT_OF_TRUST_new();
+        root_of_trust = key_desc->tee_enforced->root_of_trust;
+    }
 
-            // 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();
-            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
-            // without a purpose, which would fool this test into reporting it's a KM0 key.  That
-            // corner case doesn't matter much, because purpose-less keys are not usable anyway.
-            // Also, KM1 TEEs should disappear rapidly.
-            keymaster_version = tee_enforced.Contains(TAG_PURPOSE) ? 1 : 0;
-            break;
-        }
+    keymaster_blob_t verified_boot_key;
+    keymaster_blob_t verified_boot_hash;
+    keymaster_verified_boot_t verified_boot_state;
+    bool device_locked;
+    keymaster_error_t error = context.GetVerifiedBootParams(&verified_boot_key, &verified_boot_hash,
+                                                            &verified_boot_state, &device_locked);
+    if (error != KM_ERROR_OK) return error;
+    if (verified_boot_key.data_length &&
+        !ASN1_OCTET_STRING_set(root_of_trust->verified_boot_key, verified_boot_key.data,
+                               verified_boot_key.data_length)) {
+        return TranslateLastOpenSslError();
+    }
+    if (verified_boot_hash.data_length &&
+        !ASN1_OCTET_STRING_set(root_of_trust->verified_boot_hash, verified_boot_hash.data,
+                               verified_boot_hash.data_length)) {
+        return TranslateLastOpenSslError();
+    }
 
-        if (keymaster_version == UINT32_MAX)
-            return KM_ERROR_UNKNOWN_ERROR;
+    root_of_trust->device_locked = device_locked ? 0xFF : 0x00;
+    if (!ASN1_ENUMERATED_set(root_of_trust->verified_boot_state, verified_boot_state)) {
+        return TranslateLastOpenSslError();
     }
 
     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))
+        !ASN1_ENUMERATED_set(key_desc->keymaster_security_level, context.GetSecurityLevel())) {
         return TranslateLastOpenSslError();
+    }
 
     keymaster_blob_t attestation_challenge = {nullptr, 0};
     if (!attestation_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge))
@@ -444,8 +445,9 @@
         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);
+    error = context.VerifyAndCopyDeviceIds(
+        attestation_params,
+        context.GetSecurityLevel() == 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.
@@ -458,6 +460,11 @@
         return error;
     }
 
+    if (attestation_params.Contains(TAG_DEVICE_UNIQUE_ATTESTATION) &&
+        context.GetSecurityLevel() == KM_SECURITY_LEVEL_STRONGBOX) {
+        tee_enforced.push_back(TAG_DEVICE_UNIQUE_ATTESTATION);
+    };
+
     error = build_auth_list(sw_enforced, key_desc->software_enforced);
     if (error != KM_ERROR_OK)
         return error;
@@ -509,6 +516,14 @@
     return KM_ERROR_OK;
 }
 
+keymaster_error_t
+build_attestation_record(const AuthorizationSet& attestation_params, AuthorizationSet sw_enforced,
+                         AuthorizationSet tee_enforced, const AttestationRecordContext& context,
+                         UniquePtr<uint8_t[]>* asn1_key_desc, size_t* asn1_key_desc_len) {
+    return build_attestation_record(attestation_params, sw_enforced, tee_enforced, context,
+                                    kCurrentKeymasterVersion, asn1_key_desc, asn1_key_desc_len);
+}
+
 // Copy all enumerated values with the specified tag from stack to auth_list.
 static bool get_repeated_enums(const ASN1_INTEGER_SET* stack, keymaster_tag_t tag,
                                AuthorizationSet* auth_list) {
@@ -630,6 +645,10 @@
                               record->attestation_application_id->length))
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
 
+    // identity credential key
+    if (record->identity_credential_key && !auth_list->push_back(TAG_IDENTITY_CREDENTIAL_KEY))
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
     // Creation date time
     if (!get_ulong(record->creation_date_time, TAG_CREATION_DATETIME, auth_list))
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
@@ -717,6 +736,13 @@
         }
     }
 
+    // Early boot only
+    if (record->early_boot_only) {
+        if (!auth_list->push_back(TAG_EARLY_BOOT_ONLY)) {
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+    }
+
     return KM_ERROR_OK;
 }
 
diff --git a/km_openssl/attestation_utils.cpp b/km_openssl/attestation_utils.cpp
index e6754a2..1ed523b 100644
--- a/km_openssl/attestation_utils.cpp
+++ b/km_openssl/attestation_utils.cpp
@@ -165,12 +165,12 @@
     return result;
 }
 
-
 keymaster_error_t build_attestation_extension(const AuthorizationSet& attest_params,
-                                                     const AuthorizationSet& tee_enforced,
-                                                     const AuthorizationSet& sw_enforced,
-                                                     const AttestationRecordContext& context,
-                                                     X509_EXTENSION_Ptr* extension) {
+                                              const AuthorizationSet& tee_enforced,
+                                              const AuthorizationSet& sw_enforced,
+                                              const uint keymaster_version,
+                                              const AttestationRecordContext& context,
+                                              X509_EXTENSION_Ptr* extension) {
     ASN1_OBJECT_Ptr oid(
         OBJ_txt2obj(kAttestionRecordOid, 1 /* accept numerical dotted string form only */));
     if (!oid.get())
@@ -178,8 +178,9 @@
 
     UniquePtr<uint8_t[]> attest_bytes;
     size_t attest_bytes_len;
-    keymaster_error_t error = build_attestation_record(attest_params, sw_enforced, tee_enforced,
-                                                       context, &attest_bytes, &attest_bytes_len);
+    keymaster_error_t error =
+        build_attestation_record(attest_params, sw_enforced, tee_enforced, context,
+                                 keymaster_version, &attest_bytes, &attest_bytes_len);
     if (error != KM_ERROR_OK)
         return error;
 
@@ -266,8 +267,8 @@
     return KM_ERROR_OK;
 }
 
-bool add_public_key(EVP_PKEY* key, X509* certificate, keymaster_error_t* error) {
-    if (!X509_set_pubkey(certificate, key)) {
+bool add_public_key(const EVP_PKEY* key, X509* certificate, keymaster_error_t* error) {
+    if (!X509_set_pubkey(certificate, (EVP_PKEY*)key)) {
         *error = TranslateLastOpenSslError();
         return false;
     }
@@ -275,14 +276,14 @@
 }
 
 bool add_attestation_extension(const AuthorizationSet& attest_params,
-                                      const AuthorizationSet& tee_enforced,
-                                      const AuthorizationSet& sw_enforced,
-                                      const AttestationRecordContext& context,
-                                      X509* certificate,
-                                      keymaster_error_t* error) {
+                               const AuthorizationSet& tee_enforced,
+                               const AuthorizationSet& sw_enforced,
+                               const AttestationRecordContext& context,
+                               const uint keymaster_version, X509* certificate,
+                               keymaster_error_t* error) {
     X509_EXTENSION_Ptr attest_extension;
-    *error = build_attestation_extension(attest_params, tee_enforced, sw_enforced, context,
-                                         &attest_extension);
+    *error = build_attestation_extension(attest_params, tee_enforced, sw_enforced,
+                                         keymaster_version, context, &attest_extension);
     if (*error != KM_ERROR_OK)
         return false;
 
@@ -297,26 +298,29 @@
 
 } // anonymous namespace
 
-keymaster_error_t generate_attestation(const AsymmetricKey& key,
-        const AuthorizationSet& attest_params, const keymaster_cert_chain_t& attestation_chain,
-        const keymaster_key_blob_t& attestation_signing_key,
-        const AttestationRecordContext& context, CertChainPtr* cert_chain_out) {
+keymaster_error_t generate_attestation_common(
+    const EVP_PKEY* evp_key,                // input
+    const AuthorizationSet& sw_enforced,    // input
+    const AuthorizationSet& hw_enforced,    // input
+    const AuthorizationSet& attest_params,  // input. Sub function require app id to be set here.
+    uint64_t
+        activeDateTimeMilliSeconds,  // input, certificate active time in milliseconds since epoch
+    uint64_t usageExpireDateTimeMilliSeconds,  // Input, certificate expire time in milliseconds
+                                               // since epoch
+    const uint keymaster_version,
+    const AttestationRecordContext& context,              // input
+    const keymaster_cert_chain_t& attestation_chain,      // input
+    const keymaster_key_blob_t& attestation_signing_key,  // input
+    CertChainPtr* cert_chain_out) {                       // Output.
 
-    if (!cert_chain_out)
+    if (!cert_chain_out) {
         return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
-    keymaster_algorithm_t sign_algorithm;
-    if ((!key.sw_enforced().GetTagValue(TAG_ALGORITHM, &sign_algorithm) &&
-         !key.hw_enforced().GetTagValue(TAG_ALGORITHM, &sign_algorithm)))
-        return KM_ERROR_UNKNOWN_ERROR;
-
-    EVP_PKEY_Ptr pkey(EVP_PKEY_new());
-    if (!key.InternalToEvp(pkey.get()))
-        return TranslateLastOpenSslError();
+    }
 
     X509_Ptr certificate(X509_new());
-    if (!certificate.get())
+    if (!certificate.get()) {
         return TranslateLastOpenSslError();
+    }
 
     if (!X509_set_version(certificate.get(), 2 /* version 3, but zero-based */))
         return TranslateLastOpenSslError();
@@ -328,53 +332,58 @@
 
     X509_NAME_Ptr subjectName(X509_NAME_new());
     if (!subjectName.get() ||
-        !X509_NAME_add_entry_by_txt(subjectName.get(), "CN", MBSTRING_ASC,
+        !X509_NAME_add_entry_by_txt(subjectName.get(),  //
+                                    "CN",               //
+                                    MBSTRING_ASC,
                                     reinterpret_cast<const uint8_t*>("Android Keystore Key"),
-                                    -1 /* len */, -1 /* loc */, 0 /* set */) ||
+                                    -1,  // len
+                                    -1,  // loc
+                                    0 /* set */) ||
         !X509_set_subject_name(certificate.get(), subjectName.get() /* Don't release; copied */))
         return TranslateLastOpenSslError();
 
     ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
-    uint64_t activeDateTime = 0;
-    key.authorizations().GetTagValue(TAG_ACTIVE_DATETIME, &activeDateTime);
-    if (!notBefore.get() || !ASN1_TIME_set(notBefore.get(), activeDateTime / 1000) ||
+
+    if (!notBefore.get() || !ASN1_TIME_set(notBefore.get(), activeDateTimeMilliSeconds / 1000) ||
         !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
         return TranslateLastOpenSslError();
 
     ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
-    uint64_t usageExpireDateTime = UINT64_MAX;
-    key.authorizations().GetTagValue(TAG_USAGE_EXPIRE_DATETIME, &usageExpireDateTime);
+
     // TODO(swillden): When trusty can use the C++ standard library change the calculation of
-    // notAfterTime to use std::numeric_limits<time_t>::max(), rather than assuming that time_t is
-    // 32 bits.
-    time_t notAfterTime =
-        (time_t)min(static_cast<uint64_t>(UINT32_MAX), usageExpireDateTime / 1000);
+    // notAfterTime to use std::numeric_limits<time_t>::max(), rather than assuming that time_t
+    // is 32 bits.
+    time_t notAfterTime;
+    notAfterTime =
+        (time_t)min(static_cast<uint64_t>(UINT32_MAX), usageExpireDateTimeMilliSeconds / 1000);
+
     if (!notAfter.get() || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
         !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */))
         return TranslateLastOpenSslError();
 
-    keymaster_error_t error = add_key_usage_extension(key.hw_enforced(), key.sw_enforced(), certificate.get());
+    keymaster_error_t error = add_key_usage_extension(hw_enforced, sw_enforced, certificate.get());
     if (error != KM_ERROR_OK) {
         return error;
     }
 
-    // We have established above that it is one of the two. So if it is not RSA its EC.
-    int evp_key_type = (sign_algorithm == KM_ALGORITHM_RSA) ? EVP_PKEY_RSA : EVP_PKEY_EC;
+    int evp_key_type = EVP_PKEY_type(evp_key->type);
 
     const uint8_t* key_material = attestation_signing_key.key_material;
-    EVP_PKEY_Ptr sign_key(
-            d2i_PrivateKey(evp_key_type, nullptr,
-                    const_cast<const uint8_t**>(&key_material),
-                    attestation_signing_key.key_material_size));
-    if (!sign_key.get()) return TranslateLastOpenSslError();
+    EVP_PKEY_Ptr sign_key(d2i_PrivateKey(evp_key_type, nullptr, &key_material,
+                                         attestation_signing_key.key_material_size));
 
-    if (!add_public_key(pkey.get(), certificate.get(), &error) ||
-        !add_attestation_extension(attest_params, key.hw_enforced(), key.sw_enforced(),
-                                   context, certificate.get(), &error))
+    if (!sign_key.get()) {
+        return TranslateLastOpenSslError();
+    }
+
+    if (!add_public_key(evp_key, certificate.get(), &error) ||
+        !add_attestation_extension(attest_params, hw_enforced, sw_enforced, context,
+                                   keymaster_version, certificate.get(), &error))
         return error;
 
     if (attestation_chain.entry_count < 1) {
-        // the attestation chain must have at least the cert for the key that signs the new cert.
+        // the attestation chain must have at least the cert for the key that signs the new
+        // cert.
         return KM_ERROR_UNKNOWN_ERROR;
     }
 
@@ -389,34 +398,100 @@
     if (!issuerSubject) {
         return KM_ERROR_UNKNOWN_ERROR;
     }
+
     if (!X509_set_issuer_name(certificate.get(), issuerSubject)) {
         return TranslateLastOpenSslError();
     }
 
-    UniquePtr<X509V3_CTX> x509v3_ctx(new(std::nothrow) X509V3_CTX);
-    if (!x509v3_ctx.get())
+    UniquePtr<X509V3_CTX> x509v3_ctx(new (std::nothrow) X509V3_CTX);
+    if (!x509v3_ctx.get()) {
         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    *x509v3_ctx = {};
-    X509V3_set_ctx(x509v3_ctx.get(), signing_cert.get(), certificate.get(), nullptr /* req */,
-                   nullptr /* crl */, 0 /* flags */);
-
-    X509_EXTENSION_Ptr auth_key_id(X509V3_EXT_nconf_nid(nullptr /* conf */, x509v3_ctx.get(),
-                                                        NID_authority_key_identifier,
-                                                        const_cast<char*>("keyid:always")));
-    if (!auth_key_id.get() ||
-        !X509_add_ext(certificate.get(), auth_key_id.get() /* Don't release; copied */,
-                      -1 /* insert at end */)) {
-        return TranslateLastOpenSslError();
     }
 
+    *x509v3_ctx = {};
+    X509V3_set_ctx(x509v3_ctx.get(),    //
+                   signing_cert.get(),  // signing certificate
+                   certificate.get(),   //
+                   nullptr,             // req
+                   nullptr,             // crl
+                   0 /* flags */);
+
     if (!X509_sign(certificate.get(), sign_key.get(), EVP_sha256()))
         return TranslateLastOpenSslError();
 
-    *cert_chain_out = makeCertChain(certificate.get(), attestation_chain);
-    if (!cert_chain_out->get())
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    if (attest_params.Contains(TAG_DEVICE_UNIQUE_ATTESTATION)) {
+        // When we're pretending to be a StrongBox doing device-unique attestation, we don't chain
+        // back to anything, but just return the plain certificate.
+        *cert_chain_out = makeCertChain(certificate.get());
+    } else {
+        *cert_chain_out = makeCertChain(certificate.get(), attestation_chain);
+    }
+    if (!cert_chain_out->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
     return KM_ERROR_OK;
 }
 
+// Generate attestation certificate base on the AsymmetricKey key and other parameters
+// passed in.  In attest_params, we expects the challenge, active time and expiration
+// time, and app id.
+//
+// The active time and expiration time are expected in milliseconds.
+//
+// Hardware and software enforced AuthorizationSet are expected to be built into the AsymmetricKey
+// input. In hardware enforced AuthorizationSet, we expects hardware related tags such as
+// TAG_IDENTITY_CREDENTIAL_KEY.
+keymaster_error_t generate_attestation(const AsymmetricKey& key,
+                                       const AuthorizationSet& attest_params,
+                                       const keymaster_cert_chain_t& attestation_chain,
+                                       const keymaster_key_blob_t& attestation_signing_key,
+                                       const AttestationRecordContext& context,
+                                       CertChainPtr* cert_chain_out) {
 
-} // namespace keymaster
+    // assume the conversion to EVP key correctly encodes the key type such
+    // that EVP_PKEY_type(evp_key->type) returns correctly.
+    EVP_PKEY_Ptr pkey(EVP_PKEY_new());
+    if (!key.InternalToEvp(pkey.get())) {
+        return TranslateLastOpenSslError();
+    }
+
+    uint64_t activeDateTime = 0;
+    key.authorizations().GetTagValue(TAG_ACTIVE_DATETIME, &activeDateTime);
+
+    uint64_t usageExpireDateTime = UINT64_MAX;
+    key.authorizations().GetTagValue(TAG_USAGE_EXPIRE_DATETIME, &usageExpireDateTime);
+
+    return generate_attestation_common(pkey.get(), key.sw_enforced(), key.hw_enforced(),
+                                       attest_params, activeDateTime, usageExpireDateTime,
+                                       kCurrentKeymasterVersion, context, attestation_chain,
+                                       attestation_signing_key, cert_chain_out);
+}
+
+// Generate attestation certificate base on the EVP key and other parameters
+// passed in.  Note that due to sub sub sub function call setup, there are 3 AuthorizationSet
+// passed in, hardware, software, and attest_params.  In attest_params, we expects the
+// challenge, active time and expiration time, and app id.  In hw_enforced, we expects
+// hardware related tags such as TAG_IDENTITY_CREDENTIAL_KEY.
+//
+// The active time and expiration time are expected in milliseconds.
+keymaster_error_t generate_attestation_from_EVP(
+    const EVP_PKEY* evp_key,                  // input
+    const AuthorizationSet& sw_enforced,      // input
+    const AuthorizationSet& hw_enforced,      // input
+    const AuthorizationSet& attest_params,    // input. Sub function require app id to be set here.
+    const AttestationRecordContext& context,  // input
+    const uint keymaster_version,             // input
+    const keymaster_cert_chain_t& attestation_chain,      // input
+    const keymaster_key_blob_t& attestation_signing_key,  // input
+    CertChainPtr* cert_chain_out) {                       // Output.
+
+    uint64_t activeDateTime = 0;
+    attest_params.GetTagValue(TAG_ACTIVE_DATETIME, &activeDateTime);
+
+    uint64_t usageExpireDateTime = UINT64_MAX;
+    attest_params.GetTagValue(TAG_USAGE_EXPIRE_DATETIME, &usageExpireDateTime);
+
+    return generate_attestation_common(
+        evp_key, sw_enforced, hw_enforced, attest_params, activeDateTime, usageExpireDateTime,
+        keymaster_version, context, attestation_chain, attestation_signing_key, cert_chain_out);
+}
+
+}  // namespace keymaster
diff --git a/km_openssl/block_cipher_operation.cpp b/km_openssl/block_cipher_operation.cpp
index 7ba3707..ba75785 100644
--- a/km_openssl/block_cipher_operation.cpp
+++ b/km_openssl/block_cipher_operation.cpp
@@ -18,7 +18,7 @@
 
 #include <stdio.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <keymaster/UniquePtr.h>
 
diff --git a/km_openssl/hkdf.cpp b/km_openssl/hkdf.cpp
index e7142d2..7ac49b9 100644
--- a/km_openssl/hkdf.cpp
+++ b/km_openssl/hkdf.cpp
@@ -18,7 +18,7 @@
 
 #include <keymaster/android_keymaster_utils.h>
 #include <keymaster/km_openssl/hmac.h>
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 namespace keymaster {
 
diff --git a/km_openssl/hmac_key.cpp b/km_openssl/hmac_key.cpp
index 3883274..b2757b6 100644
--- a/km_openssl/hmac_key.cpp
+++ b/km_openssl/hmac_key.cpp
@@ -16,7 +16,7 @@
 
 #include <keymaster/km_openssl/hmac_key.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <openssl/err.h>
 #include <openssl/rand.h>
diff --git a/km_openssl/hmac_operation.cpp b/km_openssl/hmac_operation.cpp
index 30edf36..ce80cfc 100644
--- a/km_openssl/hmac_operation.cpp
+++ b/km_openssl/hmac_operation.cpp
@@ -16,7 +16,7 @@
 
 #include "hmac_operation.h"
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
diff --git a/km_openssl/rsa_key_factory.cpp b/km_openssl/rsa_key_factory.cpp
index 30bb9fb..05029bb 100644
--- a/km_openssl/rsa_key_factory.cpp
+++ b/km_openssl/rsa_key_factory.cpp
@@ -21,7 +21,7 @@
 #include <keymaster/km_openssl/openssl_utils.h>
 #include <keymaster/km_openssl/rsa_key.h>
 #include <keymaster/km_openssl/rsa_operation.h>
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 namespace keymaster {
 
diff --git a/km_openssl/rsa_operation.cpp b/km_openssl/rsa_operation.cpp
index 7e9bae8..3e3e082 100644
--- a/km_openssl/rsa_operation.cpp
+++ b/km_openssl/rsa_operation.cpp
@@ -24,7 +24,7 @@
 #include <keymaster/km_openssl/openssl_utils.h>
 #include <keymaster/km_openssl/rsa_key.h>
 #include <keymaster/logger.h>
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 namespace keymaster {
 
diff --git a/km_openssl/triple_des_key.cpp b/km_openssl/triple_des_key.cpp
index d515d96..654e40e 100644
--- a/km_openssl/triple_des_key.cpp
+++ b/km_openssl/triple_des_key.cpp
@@ -18,7 +18,7 @@
 
 #include <assert.h>
 
-#include <keymaster/new>
+#include <keymaster/new.h>
 
 #include <openssl/err.h>
 #include <openssl/rand.h>
diff --git a/ng/AndroidKeymaster41Device.cpp b/ng/AndroidKeymaster41Device.cpp
new file mode 100644
index 0000000..8d57fd2
--- /dev/null
+++ b/ng/AndroidKeymaster41Device.cpp
@@ -0,0 +1,61 @@
+/*
+ **
+ ** Copyright 2019, 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.
+ */
+
+#define LOG_TAG "android.hardware.keymaster@4.1 ref impl"
+#include <log/log.h>
+
+#include "include/AndroidKeymaster41Device.h"
+
+#include <keymaster/android_keymaster.h>
+
+namespace keymaster::V4_1 {
+
+using V4_0::ng::hidlKeyParams2Km;
+
+namespace {
+
+inline V41ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+    return static_cast<V41ErrorCode>(value);
+}
+
+}  // namespace
+
+IKeymasterDevice* CreateKeymasterDevice(SecurityLevel securityLevel) {
+    return new AndroidKeymaster41Device(securityLevel);
+}
+
+Return<V41ErrorCode>
+AndroidKeymaster41Device::deviceLocked(bool passwordOnly,
+                                       const VerificationToken& verificationToken) {
+    keymaster::VerificationToken serializableToken;
+    serializableToken.challenge = verificationToken.challenge;
+    serializableToken.timestamp = verificationToken.timestamp;
+    serializableToken.parameters_verified.Reinitialize(
+        hidlKeyParams2Km(verificationToken.parametersVerified));
+    serializableToken.security_level =
+        static_cast<keymaster_security_level_t>(verificationToken.securityLevel);
+    serializableToken.mac =
+        KeymasterBlob(verificationToken.mac.data(), verificationToken.mac.size());
+    return legacy_enum_conversion(
+        impl_->DeviceLocked(DeviceLockedRequest(passwordOnly, std::move(serializableToken))).error);
+}
+
+Return<V41ErrorCode> AndroidKeymaster41Device::earlyBootEnded() {
+    return legacy_enum_conversion(impl_->EarlyBootEnded().error);
+}
+
+}  // namespace keymaster::V4_1
diff --git a/ng/AndroidKeymaster4Device.cpp b/ng/AndroidKeymaster4Device.cpp
index 70060d6..9a71360 100644
--- a/ng/AndroidKeymaster4Device.cpp
+++ b/ng/AndroidKeymaster4Device.cpp
@@ -21,6 +21,7 @@
 #include "include/AndroidKeymaster4Device.h"
 
 #include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/keymaster_utils.h>
 
 #include <keymaster/android_keymaster.h>
 #include <keymaster/android_keymaster_messages.h>
@@ -30,6 +31,8 @@
 #include <keymaster/keymaster_enforcement.h>
 #include <keymaster/km_openssl/soft_keymaster_enforcement.h>
 
+using android::hardware::keymaster::V4_0::support::authToken2HidlVec;
+
 namespace keymaster {
 namespace V4_0 {
 namespace ng {
@@ -72,46 +75,8 @@
 
 class KmParamSet : public keymaster_key_param_set_t {
   public:
-    explicit KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
-        params = new keymaster_key_param_t[keyParams.size()];
-        length = keyParams.size();
-        for (size_t i = 0; i < keyParams.size(); ++i) {
-            auto tag = legacy_enum_conversion(keyParams[i].tag);
-            switch (typeFromTag(tag)) {
-            case KM_ENUM:
-            case KM_ENUM_REP:
-                params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
-                break;
-            case KM_UINT:
-            case KM_UINT_REP:
-                params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
-                break;
-            case KM_ULONG:
-            case KM_ULONG_REP:
-                params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
-                break;
-            case KM_DATE:
-                params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
-                break;
-            case KM_BOOL:
-                if (keyParams[i].f.boolValue)
-                    params[i] = keymaster_param_bool(tag);
-                else
-                    params[i].tag = KM_TAG_INVALID;
-                break;
-            case KM_BIGNUM:
-            case KM_BYTES:
-                params[i] =
-                    keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
-                break;
-            case KM_INVALID:
-            default:
-                params[i].tag = KM_TAG_INVALID;
-                /* just skip */
-                break;
-            }
-        }
-    }
+    explicit KmParamSet(const hidl_vec<KeyParameter>& keyParams)
+        : keymaster_key_param_set_t(hidlKeyParams2Km(keyParams)) {}
     KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
         other.length = 0;
         other.params = nullptr;
@@ -209,14 +174,62 @@
 
 }  // anonymous namespace
 
+keymaster_key_param_set_t hidlKeyParams2Km(const hidl_vec<KeyParameter>& keyParams) {
+    keymaster_key_param_set_t set;
+
+    set.params = new keymaster_key_param_t[keyParams.size()];
+    set.length = keyParams.size();
+
+    for (size_t i = 0; i < keyParams.size(); ++i) {
+        auto tag = legacy_enum_conversion(keyParams[i].tag);
+        switch (typeFromTag(tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP:
+            set.params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+            break;
+        case KM_UINT:
+        case KM_UINT_REP:
+            set.params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+            break;
+        case KM_ULONG:
+        case KM_ULONG_REP:
+            set.params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+            break;
+        case KM_DATE:
+            set.params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+            break;
+        case KM_BOOL:
+            if (keyParams[i].f.boolValue)
+                set.params[i] = keymaster_param_bool(tag);
+            else
+                set.params[i].tag = KM_TAG_INVALID;
+            break;
+        case KM_BIGNUM:
+        case KM_BYTES:
+            set.params[i] =
+                keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
+            break;
+        case KM_INVALID:
+        default:
+            set.params[i].tag = KM_TAG_INVALID;
+            /* just skip */
+            break;
+        }
+    }
+
+    return set;
+}
+
 AndroidKeymaster4Device::AndroidKeymaster4Device(SecurityLevel securityLevel)
     : impl_(new ::keymaster::AndroidKeymaster(
-          []() -> auto {
-              auto context = new PureSoftKeymasterContext();
+          [&]() -> auto {
+              auto context = new PureSoftKeymasterContext(
+                  static_cast<keymaster_security_level_t>(securityLevel));
               context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
               return context;
           }(),
-          kOperationTableSize)), securityLevel_(securityLevel) {}
+          kOperationTableSize)),
+      securityLevel_(securityLevel) {}
 
 AndroidKeymaster4Device::~AndroidKeymaster4Device() {}
 
@@ -478,21 +491,22 @@
 
 Return<void> AndroidKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
                                             const hidl_vec<KeyParameter>& inParams,
-                                            const HardwareAuthToken& /* authToken */,
-                                            begin_cb _hidl_cb) {
+                                            const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
 
     BeginOperationRequest request;
     request.purpose = legacy_enum_conversion(purpose);
     request.SetKeyMaterial(key.data(), key.size());
     request.additional_params.Reinitialize(KmParamSet(inParams));
 
+    hidl_vec<uint8_t> hidl_vec_token = authToken2HidlVec(authToken);
+    request.additional_params.push_back(
+        TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(hidl_vec_token.data()), hidl_vec_token.size());
+
     BeginOperationResponse response;
     impl_->BeginOperation(request, &response);
 
     hidl_vec<KeyParameter> resultParams;
-    if (response.error == KM_ERROR_OK) {
-        resultParams = kmParamSet2Hidl(response.output_params);
-    }
+    if (response.error == KM_ERROR_OK) resultParams = kmParamSet2Hidl(response.output_params);
 
     _hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle);
     return Void();
diff --git a/ng/include/AndroidKeymaster41Device.h b/ng/include/AndroidKeymaster41Device.h
new file mode 100644
index 0000000..68bbcf6
--- /dev/null
+++ b/ng/include/AndroidKeymaster41Device.h
@@ -0,0 +1,183 @@
+/*
+ **
+ ** Copyright 2019, 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 HIDL_android_hardware_keymaster_V4_1_AndroidKeymaster4Device_H_
+#define HIDL_android_hardware_keymaster_V4_1_AndroidKeymaster4Device_H_
+
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.1/types.h>
+#include <hidl/Status.h>
+
+#include "AndroidKeymaster4Device.h"
+
+namespace keymaster {
+class AndroidKeymaster;
+class KeymasterContext;
+
+namespace V4_1 {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::hardware::keymaster::V4_0::ErrorCode;
+using ::android::hardware::keymaster::V4_0::HardwareAuthenticatorType;
+using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
+using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
+using ::android::hardware::keymaster::V4_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V4_0::KeyFormat;
+using ::android::hardware::keymaster::V4_0::KeyParameter;
+using ::android::hardware::keymaster::V4_0::KeyPurpose;
+using ::android::hardware::keymaster::V4_0::OperationHandle;
+using ::android::hardware::keymaster::V4_0::SecurityLevel;
+using ::android::hardware::keymaster::V4_0::VerificationToken;
+using ::android::hardware::keymaster::V4_1::IKeymasterDevice;
+using ::android::hardware::keymaster::V4_1::Tag;
+
+using V41ErrorCode = ::android::hardware::keymaster::V4_1::ErrorCode;
+
+V41ErrorCode convert(ErrorCode error_code) {
+    return static_cast<V41ErrorCode>(error_code);
+}
+
+ErrorCode convert(V41ErrorCode error_code) {
+    return static_cast<ErrorCode>(error_code);
+}
+
+class AndroidKeymaster41Device : public IKeymasterDevice, public V4_0::ng::AndroidKeymaster4Device {
+    using super = V4_0::ng::AndroidKeymaster4Device;
+
+  public:
+    explicit AndroidKeymaster41Device(SecurityLevel securityLevel) : super(securityLevel) {}
+    virtual ~AndroidKeymaster41Device() {}
+
+    Return<V41ErrorCode> deviceLocked(bool /* passwordOnly */,
+                                      const VerificationToken& /* verificationToken */) override;
+    Return<V41ErrorCode> earlyBootEnded() override;
+
+    Return<void> getHardwareInfo(super::getHardwareInfo_cb _hidl_cb) override {
+        return super::getHardwareInfo(_hidl_cb);
+    }
+
+    Return<void> getHmacSharingParameters(super::getHmacSharingParameters_cb _hidl_cb) override {
+        return super::getHmacSharingParameters(_hidl_cb);
+    }
+
+    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
+                                   super::computeSharedHmac_cb _hidl_cb) override {
+        return super::computeSharedHmac(params, _hidl_cb);
+    }
+
+    Return<void> verifyAuthorization(uint64_t challenge,
+                                     const hidl_vec<KeyParameter>& parametersToVerify,
+                                     const HardwareAuthToken& authToken,
+                                     super::verifyAuthorization_cb _hidl_cb) override {
+        return super::verifyAuthorization(challenge, parametersToVerify, authToken, _hidl_cb);
+    }
+
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override {
+        return super::addRngEntropy(data);
+    }
+
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             super::generateKey_cb _hidl_cb) override {
+        return super::generateKey(keyParams, _hidl_cb);
+    }
+
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       super::getKeyCharacteristics_cb _hidl_cb) override {
+        return super::getKeyCharacteristics(keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData,
+                           super::importKey_cb _hidl_cb) override {
+        return super::importKey(params, keyFormat, keyData, _hidl_cb);
+    }
+
+    Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
+                                  const hidl_vec<uint8_t>& wrappingKeyBlob,
+                                  const hidl_vec<uint8_t>& maskingKey,
+                                  const hidl_vec<KeyParameter>& unwrappingParams,
+                                  uint64_t passwordSid, uint64_t biometricSid,
+                                  super::importWrappedKey_cb _hidl_cb) override {
+        return super::importWrappedKey(wrappedKeyData, wrappingKeyBlob, maskingKey,
+                                       unwrappingParams, passwordSid, biometricSid, _hidl_cb);
+    }
+
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           super::exportKey_cb _hidl_cb) override {
+        return super::exportKey(exportFormat, keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           super::attestKey_cb _hidl_cb) override {
+        return super::attestKey(keyToAttest, attestParams, _hidl_cb);
+    }
+
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            super::upgradeKey_cb _hidl_cb) override {
+        return super::upgradeKey(keyBlobToUpgrade, upgradeParams, _hidl_cb);
+    }
+
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override {
+        return super::deleteKey(keyBlob);
+    }
+
+    Return<ErrorCode> deleteAllKeys() override { return super::deleteAllKeys(); }
+
+    Return<ErrorCode> destroyAttestationIds() override { return super::destroyAttestationIds(); }
+
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                       super::begin_cb _hidl_cb) override {
+        return super::begin(purpose, key, inParams, authToken, _hidl_cb);
+    }
+
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken,
+                        super::update_cb _hidl_cb) override {
+        return super::update(operationHandle, inParams, input, authToken, verificationToken,
+                             _hidl_cb);
+    }
+
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken,
+                        super::finish_cb _hidl_cb) override {
+        return super::finish(operationHandle, inParams, input, signature, authToken,
+                             verificationToken, _hidl_cb);
+    }
+
+    Return<ErrorCode> abort(uint64_t operationHandle) override {
+        return super::abort(operationHandle);
+    }
+};
+
+IKeymasterDevice* CreateKeymasterDevice(SecurityLevel securityLevel);
+
+}  // namespace V4_1
+}  // namespace keymaster
+
+#endif  // HIDL_android_hardware_keymaster_V4_1_AndroidKeymaster4Device_H_
diff --git a/ng/include/AndroidKeymaster4Device.h b/ng/include/AndroidKeymaster4Device.h
index 688d08a..8bf0914 100644
--- a/ng/include/AndroidKeymaster4Device.h
+++ b/ng/include/AndroidKeymaster4Device.h
@@ -20,6 +20,7 @@
 
 #include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
 
+#include <hardware/keymaster_defs.h>
 #include <hidl/Status.h>
 
 namespace keymaster {
@@ -98,11 +99,16 @@
                         const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
     Return<ErrorCode> abort(uint64_t operationHandle) override;
 
-  private:
+  protected:
     std::unique_ptr<::keymaster::AndroidKeymaster> impl_;
     SecurityLevel securityLevel_;
 };
 
+// Convert HIDL key parametes to old keymaster param set.  Note that this does *not* copy the blobs
+// from keyParams, only pointers to them.  The keyParams instance retains ownership and must
+// continue to exist.
+keymaster_key_param_set_t hidlKeyParams2Km(const hidl_vec<KeyParameter>& keyParams);
+
 IKeymasterDevice* CreateKeymasterDevice(SecurityLevel securityLevel);
 
 }  // namespace ng