[automerger skipped] Add permission check on onKeyguardVisibilityChanged am: 3cac4c660a -s ours am: 092ed74fbd -s ours am: 7033e889be -s ours

am skip reason: Change-Id Idb8a200dc2963e1085e9fddd0c565c5172465e65 with SHA-1 ed9a255fc6 is in history

Change-Id: I454e27a7acbfdd5f43608df0f35871079d4cb3ac
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index c8dbf77..dcf92be 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -3,3 +3,6 @@
 
 [Builtin Hooks Options]
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+
+[Hook Scripts]
+aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
diff --git a/fsverity_init/Android.bp b/fsverity_init/Android.bp
new file mode 100644
index 0000000..3c9ade0
--- /dev/null
+++ b/fsverity_init/Android.bp
@@ -0,0 +1,17 @@
+cc_binary {
+    name: "fsverity_init",
+    srcs: [
+        "fsverity_init.cpp",
+    ],
+    static_libs: [
+        "libc++fs",
+        "libmini_keyctl_static",
+    ],
+    shared_libs: [
+        "libbase",
+        "libkeyutils",
+        "liblog",
+        "liblogwrap",
+    ],
+    cflags: ["-Werror", "-Wall", "-Wextra"],
+}
diff --git a/fsverity_init/fsverity_init.cpp b/fsverity_init/fsverity_init.cpp
new file mode 100644
index 0000000..e2a8bf7
--- /dev/null
+++ b/fsverity_init/fsverity_init.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 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 "fsverity_init"
+
+#include <sys/types.h>
+
+#include <filesystem>
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <log/log.h>
+#include <mini_keyctl_utils.h>
+
+bool LoadKeyToKeyring(key_serial_t keyring_id, const char* desc, const char* data, size_t size) {
+    key_serial_t key = add_key("asymmetric", desc, data, size, keyring_id);
+    if (key < 0) {
+        PLOG(ERROR) << "Failed to add key";
+        return false;
+    }
+    return true;
+}
+
+void LoadKeyFromVerifiedPartitions(key_serial_t keyring_id) {
+    const char* dir = "/product/etc/security/fsverity";
+    if (!std::filesystem::exists(dir)) {
+        LOG(ERROR) << "no such dir: " << dir;
+        return;
+    }
+    for (const auto& entry : std::filesystem::directory_iterator(dir)) {
+        if (!android::base::EndsWithIgnoreCase(entry.path().c_str(), ".der")) continue;
+        std::string content;
+        if (!android::base::ReadFileToString(entry.path(), &content)) {
+            continue;
+        }
+        if (!LoadKeyToKeyring(keyring_id, "fsv_system", content.c_str(), content.size())) {
+            LOG(ERROR) << "Failed to load key from " << entry.path();
+        }
+    }
+}
+
+int main(int /*argc*/, const char** /*argv*/) {
+    key_serial_t keyring_id = android::GetKeyringId(".fs-verity");
+    if (keyring_id < 0) {
+        LOG(ERROR) << "Failed to find .fs-verity keyring id";
+        return -1;
+    }
+
+    // Requires files backed by fs-verity to be verified with a key in .fs-verity
+    // keyring.
+    if (!android::base::WriteStringToFile("1", "/proc/sys/fs/verity/require_signatures")) {
+        PLOG(ERROR) << "Failed to enforce fs-verity signature";
+    }
+
+    LoadKeyFromVerifiedPartitions(keyring_id);
+
+    if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+        if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) {
+            PLOG(ERROR) << "Cannot restrict .fs-verity keyring";
+        }
+    }
+    return 0;
+}
diff --git a/identity/Android.bp b/identity/Android.bp
new file mode 100644
index 0000000..c0f1635
--- /dev/null
+++ b/identity/Android.bp
@@ -0,0 +1,87 @@
+cc_defaults {
+    name: "identity_defaults",
+    cflags: [
+        "-Wall",
+        // "-Werror",
+        "-Wextra",
+        "-Wunused",
+    ],
+    sanitize: {
+        misc_undefined : ["integer"],
+    },
+    clang : true,
+}
+
+cc_binary {
+    name: "credstore",
+    defaults: ["identity_defaults"],
+
+    srcs: [
+        "main.cpp",
+        "CredentialStore.cpp",
+        "CredentialStoreFactory.cpp",
+        "WritableCredential.cpp",
+        "Credential.cpp",
+        "CredentialData.cpp",
+        "Util.cpp",
+    ],
+    init_rc: ["credstore.rc"],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libkeystore_aidl",
+        "libcredstore_aidl",
+        "libutils",
+        "libhidlbase",
+        "android.hardware.identity-support-lib",
+        "libkeymaster4support",
+        "libkeystore-attestation-application-id",
+    ],
+    static_libs: [
+        "android.hardware.identity-cpp",
+        "android.hardware.keymaster-cpp",
+        "libcppbor",
+    ]
+}
+
+filegroup {
+    name: "credstore_aidl",
+    srcs: [
+        "binder/android/security/identity/ICredential.aidl",
+        "binder/android/security/identity/IWritableCredential.aidl",
+        "binder/android/security/identity/ICredentialStore.aidl",
+        "binder/android/security/identity/AccessControlProfileParcel.aidl",
+        "binder/android/security/identity/EntryNamespaceParcel.aidl",
+        "binder/android/security/identity/EntryParcel.aidl",
+        "binder/android/security/identity/RequestNamespaceParcel.aidl",
+        "binder/android/security/identity/RequestEntryParcel.aidl",
+        "binder/android/security/identity/ResultNamespaceParcel.aidl",
+        "binder/android/security/identity/ResultEntryParcel.aidl",
+        "binder/android/security/identity/GetEntriesResultParcel.aidl",
+        "binder/android/security/identity/AuthKeyParcel.aidl",
+        "binder/android/security/identity/SecurityHardwareInfoParcel.aidl",
+        "binder/android/security/identity/ICredentialStoreFactory.aidl",
+    ],
+    path: "binder",
+}
+
+cc_library_shared {
+    name: "libcredstore_aidl",
+    srcs: [
+        ":credstore_aidl",
+        ],
+    aidl: {
+        export_aidl_headers: true,
+        include_dirs: [
+            "system/security/identity/binder",
+        ],
+    },
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "libkeymaster4support",
+    ],
+    export_shared_lib_headers: [
+        "libbinder",
+    ],
+}
diff --git a/identity/Credential.cpp b/identity/Credential.cpp
new file mode 100644
index 0000000..05c31d3
--- /dev/null
+++ b/identity/Credential.cpp
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 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 "Credential"
+
+#include <android-base/logging.h>
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <android/security/identity/ICredentialStore.h>
+
+#include <android/security/keystore/IKeystoreService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <keymasterV4_0/keymaster_utils.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include "Credential.h"
+#include "CredentialData.h"
+#include "Util.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+using std::optional;
+
+using android::security::keystore::IKeystoreService;
+
+using ::android::hardware::identity::support::ecKeyPairGetPkcs12;
+using ::android::hardware::identity::support::ecKeyPairGetPrivateKey;
+using ::android::hardware::identity::support::ecKeyPairGetPublicKey;
+using ::android::hardware::identity::support::sha256;
+
+using android::hardware::keymaster::V4_0::HardwareAuthToken;
+using AidlHardwareAuthToken = android::hardware::keymaster::HardwareAuthToken;
+
+Credential::Credential(CipherSuite cipherSuite, const std::string& dataPath,
+                       const std::string& credentialName)
+    : cipherSuite_(cipherSuite), dataPath_(dataPath), credentialName_(credentialName) {}
+
+Credential::~Credential() {}
+
+Status Credential::loadCredential(sp<IIdentityCredentialStore> halStoreBinder) {
+    uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+    sp<CredentialData> data = new CredentialData(dataPath_, callingUid, credentialName_);
+    if (!data->loadFromDisk()) {
+        LOG(ERROR) << "Error loading data for credential";
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error loading data for credential");
+    }
+
+    data_ = data;
+
+    sp<IIdentityCredential> halBinder;
+    Status status =
+        halStoreBinder->getCredential(cipherSuite_, data_->getCredentialData(), &halBinder);
+    if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
+        int code = status.serviceSpecificErrorCode();
+        if (code == IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED) {
+            return halStatusToError(status, ICredentialStore::ERROR_CIPHER_SUITE_NOT_SUPPORTED);
+        }
+    }
+    if (!status.isOk()) {
+        LOG(ERROR) << "Error getting HAL binder";
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC);
+    }
+
+    halBinder_ = halBinder;
+
+    return Status::ok();
+}
+
+Status Credential::getCredentialKeyCertificateChain(std::vector<uint8_t>* _aidl_return) {
+    *_aidl_return = data_->getAttestationCertificate();
+    return Status::ok();
+}
+
+// Returns operation handle
+Status Credential::selectAuthKey(bool allowUsingExhaustedKeys, int64_t* _aidl_return) {
+
+    selectedAuthKey_ = data_->selectAuthKey(allowUsingExhaustedKeys);
+    if (selectedAuthKey_ == nullptr) {
+        return Status::fromServiceSpecificError(
+            ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
+            "No suitable authentication key available");
+    }
+
+    int64_t challenge;
+    Status status = halBinder_->createAuthChallenge(&challenge);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+    if (challenge == 0) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Returned challenge is 0 (bug in HAL or TA)");
+    }
+
+    selectedChallenge_ = challenge;
+    *_aidl_return = challenge;
+    return Status::ok();
+}
+
+// Returns false if an error occurred communicating with keystore.
+//
+// Sets |authToken| to the empty vector if an auth token couldn't be obtained.
+//
+bool getAuthTokenFromKeystore(uint64_t challenge, uint64_t secureUserId,
+                              unsigned int authTokenMaxAgeMillis, vector<uint8_t>& authToken) {
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> keystore = interface_cast<IKeystoreService>(binder);
+    if (keystore == nullptr) {
+        return false;
+    }
+
+    vector<uint8_t> returnedAuthToken;
+    Status ret = keystore->getAuthTokenForCredstore(challenge, secureUserId, authTokenMaxAgeMillis,
+                                                    &returnedAuthToken);
+    if (!ret.isOk()) {
+        return false;
+    }
+    authToken = returnedAuthToken;
+    return true;
+}
+
+Status Credential::getEntries(const vector<uint8_t>& requestMessage,
+                              const vector<RequestNamespaceParcel>& requestNamespaces,
+                              const vector<uint8_t>& sessionTranscript,
+                              const vector<uint8_t>& readerSignature, bool allowUsingExhaustedKeys,
+                              GetEntriesResultParcel* _aidl_return) {
+    GetEntriesResultParcel ret;
+
+    // Calculate requestCounts ahead of time and be careful not to include
+    // elements that don't exist.
+    //
+    // Also go through and figure out which access control profiles to include
+    // in the startRetrieval() call.
+    vector<int32_t> requestCounts;
+    const vector<SecureAccessControlProfile>& allProfiles = data_->getSecureAccessControlProfiles();
+    vector<bool> includeProfile(allProfiles.size());
+    for (const RequestNamespaceParcel& rns : requestNamespaces) {
+        size_t numEntriesInNsToRequest = 0;
+        for (const RequestEntryParcel& rep : rns.entries) {
+            if (data_->hasEntryData(rns.namespaceName, rep.name)) {
+                numEntriesInNsToRequest++;
+            }
+
+            optional<EntryData> data = data_->getEntryData(rns.namespaceName, rep.name);
+            if (data) {
+                for (int32_t id : data.value().accessControlProfileIds) {
+                    if (id >= int32_t(includeProfile.size())) {
+                        LOG(ERROR) << "Invalid accessControlProfileId " << id << " for "
+                                   << rns.namespaceName << ": " << rep.name;
+                        return Status::fromServiceSpecificError(
+                            ICredentialStore::ERROR_GENERIC, "Invalid accessProfileId for entry");
+                    }
+                    includeProfile[id] = true;
+                }
+            }
+        }
+        requestCounts.push_back(numEntriesInNsToRequest);
+    }
+
+    // Now that we know which profiles are needed, send only those to the
+    // HAL.
+    vector<SecureAccessControlProfile> selectedProfiles;
+    for (size_t n = 0; n < allProfiles.size(); n++) {
+        if (includeProfile[n]) {
+            selectedProfiles.push_back(allProfiles[n]);
+        }
+    }
+
+    // Calculate the highest [1] non-zero timeout and if user-auth is needed
+    // ... we need this to select an appropriate authToken.
+    //
+    // [1] : Why do we request the highest timeout and not the lowest? Well, we
+    //       return partial results in getEntries e.g. if some data elements
+    //       fail to authorize we'll still return the ones that did not fail. So
+    //       e.g. consider data elements A and B where A has an ACP with 60
+    //       seconds and B has an ACP with 3600 seconds. In this case we'll be
+    //       fine with getting an authToken for e.g. 2400 seconds which would
+    //       mean returning only B.
+    //
+    bool userAuthNeeded = false;
+    unsigned int authTokenMaxAgeMillis = 0;
+    for (auto& profile : selectedProfiles) {
+        if (profile.userAuthenticationRequired) {
+            userAuthNeeded = true;
+            if (profile.timeoutMillis > 0) {
+                if (profile.timeoutMillis > authTokenMaxAgeMillis) {
+                    authTokenMaxAgeMillis = profile.timeoutMillis;
+                }
+            }
+        }
+    }
+
+    // If requesting a challenge-based authToken the idea is that authentication
+    // happens as part of the transaction. As such, authTokenMaxAgeMillis should
+    // be nearly zero. We'll use 10 seconds for this.
+    if (userAuthNeeded && selectedChallenge_ != 0) {
+        authTokenMaxAgeMillis = 10 * 1000;
+    }
+
+    // Only get an authToken if it's actually needed.
+    AidlHardwareAuthToken aidlAuthToken;
+    if (userAuthNeeded) {
+        vector<uint8_t> authTokenBytes;
+        if (!getAuthTokenFromKeystore(selectedChallenge_, data_->getSecureUserId(),
+                                      authTokenMaxAgeMillis, authTokenBytes)) {
+            LOG(ERROR) << "Error getting auth token from keystore";
+            return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                    "Error getting auth token from keystore");
+        }
+        if (authTokenBytes.size() > 0) {
+            HardwareAuthToken authToken =
+                android::hardware::keymaster::V4_0::support::hidlVec2AuthToken(authTokenBytes);
+            // Convert from HIDL to AIDL...
+            aidlAuthToken.challenge = int64_t(authToken.challenge);
+            aidlAuthToken.userId = int64_t(authToken.userId);
+            aidlAuthToken.authenticatorId = int64_t(authToken.authenticatorId);
+            aidlAuthToken.authenticatorType =
+                ::android::hardware::keymaster::HardwareAuthenticatorType(
+                    int32_t(authToken.authenticatorType));
+            aidlAuthToken.timestamp.milliSeconds = int64_t(authToken.timestamp);
+            aidlAuthToken.mac = authToken.mac;
+        }
+    }
+
+    // Note that the selectAuthKey() method is only called if a CryptoObject is involved at
+    // the Java layer. So we could end up with no previously selected auth key and we may
+    // need one.
+    const AuthKeyData* authKey = selectedAuthKey_;
+    if (sessionTranscript.size() > 0) {
+        if (authKey == nullptr) {
+            authKey = data_->selectAuthKey(allowUsingExhaustedKeys);
+            if (authKey == nullptr) {
+                return Status::fromServiceSpecificError(
+                    ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
+                    "No suitable authentication key available");
+            }
+        }
+    }
+    vector<uint8_t> signingKeyBlob;
+    if (authKey != nullptr) {
+        signingKeyBlob = authKey->keyBlob;
+    }
+
+    Status status =
+        halBinder_->startRetrieval(selectedProfiles, aidlAuthToken, requestMessage, signingKeyBlob,
+                                   sessionTranscript, readerSignature, requestCounts);
+    if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
+        int code = status.serviceSpecificErrorCode();
+        if (code == IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND) {
+            return halStatusToError(status, ICredentialStore::ERROR_EPHEMERAL_PUBLIC_KEY_NOT_FOUND);
+        } else if (code == IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED) {
+            return halStatusToError(status, ICredentialStore::ERROR_INVALID_READER_SIGNATURE);
+        } else if (code == IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE) {
+            return halStatusToError(status, ICredentialStore::ERROR_INVALID_ITEMS_REQUEST_MESSAGE);
+        } else if (code == IIdentityCredentialStore::STATUS_SESSION_TRANSCRIPT_MISMATCH) {
+            return halStatusToError(status, ICredentialStore::ERROR_SESSION_TRANSCRIPT_MISMATCH);
+        }
+    }
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+
+    for (const RequestNamespaceParcel& rns : requestNamespaces) {
+        ResultNamespaceParcel resultNamespaceParcel;
+        resultNamespaceParcel.namespaceName = rns.namespaceName;
+
+        for (const RequestEntryParcel& rep : rns.entries) {
+            ResultEntryParcel resultEntryParcel;
+            resultEntryParcel.name = rep.name;
+
+            optional<EntryData> data = data_->getEntryData(rns.namespaceName, rep.name);
+            if (!data) {
+                resultEntryParcel.status = STATUS_NO_SUCH_ENTRY;
+                resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                continue;
+            }
+
+            status =
+                halBinder_->startRetrieveEntryValue(rns.namespaceName, rep.name, data.value().size,
+                                                    data.value().accessControlProfileIds);
+            if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
+                int code = status.serviceSpecificErrorCode();
+                if (code == IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED) {
+                    resultEntryParcel.status = STATUS_USER_AUTHENTICATION_FAILED;
+                    resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                    continue;
+                } else if (code == IIdentityCredentialStore::STATUS_READER_AUTHENTICATION_FAILED) {
+                    resultEntryParcel.status = STATUS_READER_AUTHENTICATION_FAILED;
+                    resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                    continue;
+                } else if (code == IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE) {
+                    resultEntryParcel.status = STATUS_NOT_IN_REQUEST_MESSAGE;
+                    resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                    continue;
+                } else if (code == IIdentityCredentialStore::STATUS_NO_ACCESS_CONTROL_PROFILES) {
+                    resultEntryParcel.status = STATUS_NO_ACCESS_CONTROL_PROFILES;
+                    resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                    continue;
+                }
+            }
+            if (!status.isOk()) {
+                return halStatusToGenericError(status);
+            }
+
+            vector<uint8_t> value;
+            for (const auto& encryptedChunk : data.value().encryptedChunks) {
+                vector<uint8_t> chunk;
+                status = halBinder_->retrieveEntryValue(encryptedChunk, &chunk);
+                if (!status.isOk()) {
+                    return halStatusToGenericError(status);
+                }
+                value.insert(value.end(), chunk.begin(), chunk.end());
+            }
+
+            resultEntryParcel.status = STATUS_OK;
+            resultEntryParcel.value = value;
+            resultNamespaceParcel.entries.push_back(resultEntryParcel);
+        }
+        ret.resultNamespaces.push_back(resultNamespaceParcel);
+    }
+
+    status = halBinder_->finishRetrieval(&ret.mac, &ret.deviceNameSpaces);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+    if (authKey != nullptr) {
+        ret.staticAuthenticationData = authKey->staticAuthenticationData;
+    }
+
+    // Ensure useCount is updated on disk.
+    if (authKey != nullptr) {
+        if (!data_->saveToDisk()) {
+            return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                    "Error saving data");
+        }
+    }
+
+    *_aidl_return = ret;
+    return Status::ok();
+}
+
+Status Credential::deleteCredential(vector<uint8_t>* _aidl_return) {
+    vector<uint8_t> proofOfDeletionSignature;
+    Status status = halBinder_->deleteCredential(&proofOfDeletionSignature);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+    if (!data_->deleteCredential()) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error deleting credential data on disk");
+    }
+    *_aidl_return = proofOfDeletionSignature;
+    return Status::ok();
+}
+
+Status Credential::createEphemeralKeyPair(vector<uint8_t>* _aidl_return) {
+    vector<uint8_t> keyPair;
+    Status status = halBinder_->createEphemeralKeyPair(&keyPair);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+
+    optional<vector<uint8_t>> pkcs12Bytes = ecKeyPairGetPkcs12(keyPair,
+                                                               "ephemeralKey",  // Alias for key
+                                                               "0",  // Serial, as a decimal number
+                                                               "Credstore",      // Issuer
+                                                               "Ephemeral Key",  // Subject
+                                                               0,  // Validity Not Before
+                                                               24 * 60 * 60);  // Validity Not After
+    if (!pkcs12Bytes) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error creating PKCS#12 structure for key pair");
+    }
+    *_aidl_return = pkcs12Bytes.value();
+    return Status::ok();
+}
+
+Status Credential::setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) {
+    Status status = halBinder_->setReaderEphemeralPublicKey(publicKey);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+    return Status::ok();
+}
+
+Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey) {
+    data_->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey);
+    if (!data_->saveToDisk()) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error saving data");
+    }
+    return Status::ok();
+}
+
+Status Credential::getAuthKeysNeedingCertification(vector<AuthKeyParcel>* _aidl_return) {
+    optional<vector<vector<uint8_t>>> keysNeedingCert =
+        data_->getAuthKeysNeedingCertification(halBinder_);
+    if (!keysNeedingCert) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error getting auth keys neededing certification");
+    }
+    vector<AuthKeyParcel> authKeyParcels;
+    for (const vector<uint8_t>& key : keysNeedingCert.value()) {
+        AuthKeyParcel authKeyParcel;
+        authKeyParcel.x509cert = key;
+        authKeyParcels.push_back(authKeyParcel);
+    }
+    if (!data_->saveToDisk()) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error saving data");
+    }
+    *_aidl_return = authKeyParcels;
+    return Status::ok();
+}
+
+Status Credential::storeStaticAuthenticationData(const AuthKeyParcel& authenticationKey,
+                                                 const vector<uint8_t>& staticAuthData) {
+    if (!data_->storeStaticAuthenticationData(authenticationKey.x509cert, staticAuthData)) {
+        return Status::fromServiceSpecificError(
+            ICredentialStore::ERROR_AUTHENTICATION_KEY_NOT_FOUND,
+            "Error finding authentication key to store static "
+            "authentication data for");
+    }
+    if (!data_->saveToDisk()) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error saving data");
+    }
+    return Status::ok();
+}
+
+Status Credential::getAuthenticationDataUsageCount(vector<int32_t>* _aidl_return) {
+    const vector<AuthKeyData>& authKeyDatas = data_->getAuthKeyDatas();
+    vector<int32_t> ret;
+    for (const AuthKeyData& authKeyData : authKeyDatas) {
+        ret.push_back(authKeyData.useCount);
+    }
+    *_aidl_return = ret;
+    return Status::ok();
+}
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/identity/Credential.h b/identity/Credential.h
new file mode 100644
index 0000000..a0d9063
--- /dev/null
+++ b/identity/Credential.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 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 SYSTEM_SECURITY_CREDENTIAL_H_
+#define SYSTEM_SECURITY_CREDENTIAL_H_
+
+#include <string>
+#include <vector>
+
+#include <android/security/identity/BnCredential.h>
+
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+
+#include "CredentialData.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::sp;
+using ::android::binder::Status;
+using ::std::string;
+using ::std::vector;
+
+using ::android::hardware::identity::CipherSuite;
+using ::android::hardware::identity::IIdentityCredential;
+using ::android::hardware::identity::IIdentityCredentialStore;
+
+class Credential : public BnCredential {
+  public:
+    Credential(CipherSuite cipherSuite, const string& dataPath, const string& credentialName);
+    ~Credential();
+
+    Status loadCredential(sp<IIdentityCredentialStore> halStoreBinder);
+
+    // ICredential overrides
+    Status createEphemeralKeyPair(vector<uint8_t>* _aidl_return) override;
+
+    Status setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) override;
+
+    Status deleteCredential(vector<uint8_t>* _aidl_return) override;
+
+    Status getCredentialKeyCertificateChain(vector<uint8_t>* _aidl_return) override;
+
+    Status selectAuthKey(bool allowUsingExhaustedKeys, int64_t* _aidl_return) override;
+
+    Status getEntries(const vector<uint8_t>& requestMessage,
+                      const vector<RequestNamespaceParcel>& requestNamespaces,
+                      const vector<uint8_t>& sessionTranscript,
+                      const vector<uint8_t>& readerSignature, bool allowUsingExhaustedKeys,
+                      GetEntriesResultParcel* _aidl_return) override;
+
+    Status setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey) override;
+    Status getAuthKeysNeedingCertification(vector<AuthKeyParcel>* _aidl_return) override;
+    Status storeStaticAuthenticationData(const AuthKeyParcel& authenticationKey,
+                                         const vector<uint8_t>& staticAuthData) override;
+    Status getAuthenticationDataUsageCount(vector<int32_t>* _aidl_return) override;
+
+  private:
+    CipherSuite cipherSuite_;
+    string dataPath_;
+    string credentialName_;
+
+    const AuthKeyData* selectedAuthKey_ = nullptr;
+    uint64_t selectedChallenge_ = 0;
+
+    sp<CredentialData> data_;
+
+    sp<IIdentityCredential> halBinder_;
+};
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_IDENTITY_CREDENTIAL_H_
diff --git a/identity/CredentialData.cpp b/identity/CredentialData.cpp
new file mode 100644
index 0000000..b4e6641
--- /dev/null
+++ b/identity/CredentialData.cpp
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 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 "CredentialData"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include "CredentialData.h"
+#include "Util.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+using std::optional;
+
+string CredentialData::calculateCredentialFileName(const string& dataPath, uid_t ownerUid,
+                                                   const string& name) {
+    return android::base::StringPrintf(
+        "%s/%d-%s", dataPath.c_str(), (int)ownerUid,
+        android::hardware::identity::support::encodeHex(name).c_str());
+}
+
+CredentialData::CredentialData(const string& dataPath, uid_t ownerUid, const string& name)
+    : dataPath_(dataPath), ownerUid_(ownerUid), name_(name), secureUserId_(0) {
+    fileName_ = calculateCredentialFileName(dataPath_, ownerUid_, name_);
+}
+
+void CredentialData::setSecureUserId(int64_t secureUserId) {
+    secureUserId_ = secureUserId;
+}
+
+void CredentialData::setCredentialData(const vector<uint8_t>& credentialData) {
+    credentialData_ = credentialData;
+}
+
+void CredentialData::setAttestationCertificate(const vector<uint8_t>& attestationCertificate) {
+    attestationCertificate_ = attestationCertificate;
+}
+
+void CredentialData::addSecureAccessControlProfile(
+    const SecureAccessControlProfile& secureAccessControlProfile) {
+    secureAccessControlProfiles_.push_back(secureAccessControlProfile);
+}
+
+void CredentialData::addEntryData(const string& namespaceName, const string& entryName,
+                                  const EntryData& data) {
+    idToEncryptedChunks_[namespaceName + ":" + entryName] = data;
+}
+
+bool CredentialData::saveToDisk() const {
+    cppbor::Map map;
+
+    map.add("secureUserId", secureUserId_);
+
+    map.add("credentialData", credentialData_);
+
+    map.add("attestationCertificate", attestationCertificate_);
+
+    cppbor::Array sacpArray;
+    for (const SecureAccessControlProfile& sacp : secureAccessControlProfiles_) {
+        cppbor::Array array;
+        array.add(sacp.id);
+        array.add(sacp.readerCertificate.encodedCertificate);
+        array.add(sacp.userAuthenticationRequired);
+        array.add(sacp.timeoutMillis);
+        array.add(sacp.secureUserId);
+        vector<uint8_t> mac = sacp.mac;
+        array.add(mac);
+        sacpArray.add(std::move(array));
+    }
+    map.add("secureAccessControlProfiles", std::move(sacpArray));
+
+    cppbor::Map encryptedBlobsMap;
+    for (auto const& [nsAndName, entryData] : idToEncryptedChunks_) {
+        cppbor::Array encryptedChunkArray;
+        for (const vector<uint8_t>& encryptedChunk : entryData.encryptedChunks) {
+            encryptedChunkArray.add(encryptedChunk);
+        }
+        cppbor::Array entryDataArray;
+        entryDataArray.add(entryData.size);
+        cppbor::Array idsArray;
+        for (int32_t id : entryData.accessControlProfileIds) {
+            idsArray.add(id);
+        }
+        entryDataArray.add(std::move(idsArray));
+        entryDataArray.add(std::move(encryptedChunkArray));
+        encryptedBlobsMap.add(nsAndName, std::move(entryDataArray));
+    }
+    map.add("entryData", std::move(encryptedBlobsMap));
+    map.add("authKeyCount", keyCount_);
+    map.add("maxUsesPerAuthKey", maxUsesPerKey_);
+
+    cppbor::Array authKeyDatasArray;
+    for (const AuthKeyData& data : authKeyDatas_) {
+        cppbor::Array array;
+        array.add(data.certificate);
+        array.add(data.keyBlob);
+        array.add(data.staticAuthenticationData);
+        array.add(data.pendingCertificate);
+        array.add(data.pendingKeyBlob);
+        array.add(data.useCount);
+        authKeyDatasArray.add(std::move(array));
+    }
+    map.add("authKeyData", std::move(authKeyDatasArray));
+
+    vector<uint8_t> credentialData = map.encode();
+
+    return fileSetContents(fileName_, credentialData);
+}
+
+optional<SecureAccessControlProfile> parseSacp(const cppbor::Item& item) {
+    const cppbor::Array* array = item.asArray();
+    if (array == nullptr || array->size() < 6) {
+        LOG(ERROR) << "The SACP CBOR is not an array with at least six elements (size="
+                   << (array != nullptr ? array->size() : -1) << ")";
+        return {};
+    }
+    const cppbor::Int* itemId = ((*array)[0])->asInt();
+    const cppbor::Bstr* itemReaderCertificate = ((*array)[1])->asBstr();
+    const cppbor::Simple* simple = ((*array)[2])->asSimple();
+    const cppbor::Bool* itemUserAuthenticationRequired =
+        (simple != nullptr ? (simple->asBool()) : nullptr);
+    const cppbor::Int* itemTimeoutMillis = ((*array)[3])->asInt();
+    const cppbor::Int* itesecureUserId_ = ((*array)[4])->asInt();
+    const cppbor::Bstr* itemMac = ((*array)[5])->asBstr();
+    if (itemId == nullptr || itemReaderCertificate == nullptr ||
+        itemUserAuthenticationRequired == nullptr || itemTimeoutMillis == nullptr ||
+        itesecureUserId_ == nullptr || itemMac == nullptr) {
+        LOG(ERROR) << "One or more items SACP array in CBOR is of wrong type";
+        return {};
+    }
+    SecureAccessControlProfile sacp;
+    sacp.id = itemId->value();
+    sacp.readerCertificate.encodedCertificate = itemReaderCertificate->value();
+    sacp.userAuthenticationRequired = itemUserAuthenticationRequired->value();
+    sacp.timeoutMillis = itemTimeoutMillis->value();
+    sacp.secureUserId = itesecureUserId_->value();
+    sacp.mac = itemMac->value();
+    return sacp;
+}
+
+optional<AuthKeyData> parseAuthKeyData(const cppbor::Item& item) {
+    const cppbor::Array* array = item.asArray();
+    if (array == nullptr || array->size() < 6) {
+        LOG(ERROR) << "The AuthKeyData CBOR is not an array with at least six elements";
+        return {};
+    }
+    const cppbor::Bstr* itemCertificate = ((*array)[0])->asBstr();
+    const cppbor::Bstr* itemKeyBlob = ((*array)[1])->asBstr();
+    const cppbor::Bstr* itemStaticAuthenticationData = ((*array)[2])->asBstr();
+    const cppbor::Bstr* itemPendingCertificate = ((*array)[3])->asBstr();
+    const cppbor::Bstr* itemPendingKeyBlob = ((*array)[4])->asBstr();
+    const cppbor::Int* itemUseCount = ((*array)[5])->asInt();
+    if (itemCertificate == nullptr || itemKeyBlob == nullptr ||
+        itemStaticAuthenticationData == nullptr || itemPendingCertificate == nullptr ||
+        itemPendingKeyBlob == nullptr || itemUseCount == nullptr) {
+        LOG(ERROR) << "One or more items in AuthKeyData array in CBOR is of wrong type";
+        return {};
+    }
+    AuthKeyData authKeyData;
+    authKeyData.certificate = itemCertificate->value();
+    authKeyData.keyBlob = itemKeyBlob->value();
+    authKeyData.staticAuthenticationData = itemStaticAuthenticationData->value();
+    authKeyData.pendingCertificate = itemPendingCertificate->value();
+    authKeyData.pendingKeyBlob = itemPendingKeyBlob->value();
+    authKeyData.useCount = itemUseCount->value();
+    return authKeyData;
+}
+
+vector<int32_t> parseAccessControlProfileIds(const cppbor::Item& item) {
+    const cppbor::Array* array = item.asArray();
+    if (array == nullptr) {
+        LOG(ERROR) << "The accessControlProfileIds member is not an array";
+        return {};
+    }
+
+    vector<int32_t> accessControlProfileIds;
+    for (size_t n = 0; n < array->size(); n++) {
+        const cppbor::Int* itemInt = ((*array)[n])->asInt();
+        if (itemInt == nullptr) {
+            LOG(ERROR) << "An item in the accessControlProfileIds array is not a bstr";
+            return {};
+        }
+        accessControlProfileIds.push_back(itemInt->value());
+    }
+    return accessControlProfileIds;
+}
+
+optional<vector<vector<uint8_t>>> parseEncryptedChunks(const cppbor::Item& item) {
+    const cppbor::Array* array = item.asArray();
+    if (array == nullptr) {
+        LOG(ERROR) << "The encryptedChunks member is not an array";
+        return {};
+    }
+
+    vector<vector<uint8_t>> encryptedChunks;
+    for (size_t n = 0; n < array->size(); n++) {
+        const cppbor::Bstr* itemBstr = ((*array)[n])->asBstr();
+        if (itemBstr == nullptr) {
+            LOG(ERROR) << "An item in the encryptedChunks array is not a bstr";
+            return {};
+        }
+        encryptedChunks.push_back(itemBstr->value());
+    }
+    return encryptedChunks;
+}
+
+bool CredentialData::loadFromDisk() {
+
+    // Reset all data.
+    credentialData_.clear();
+    attestationCertificate_.clear();
+    secureAccessControlProfiles_.clear();
+    idToEncryptedChunks_.clear();
+    authKeyDatas_.clear();
+    keyCount_ = 0;
+    maxUsesPerKey_ = 1;
+
+    optional<vector<uint8_t>> data = fileGetContents(fileName_);
+    if (!data) {
+        LOG(ERROR) << "Error loading data";
+        return false;
+    }
+
+    auto [item, _ /* newPos */, message] = cppbor::parse(data.value());
+    if (item == nullptr) {
+        LOG(ERROR) << "Data loaded from " << fileName_ << " is not valid CBOR: " << message;
+        return false;
+    }
+
+    const cppbor::Map* map = item->asMap();
+    if (map == nullptr) {
+        LOG(ERROR) << "Top-level item is not a map";
+        return false;
+    }
+
+    for (size_t n = 0; n < map->size(); n++) {
+        auto [keyItem, valueItem] = (*map)[n];
+        const cppbor::Tstr* tstr = keyItem->asTstr();
+        if (tstr == nullptr) {
+            LOG(ERROR) << "Key item in top-level map is not a tstr";
+            return false;
+        }
+        const string& key = tstr->value();
+
+        if (key == "secureUserId") {
+            const cppbor::Int* number = valueItem->asInt();
+            if (number == nullptr) {
+                LOG(ERROR) << "Value for secureUserId is not a number";
+                return false;
+            }
+            secureUserId_ = number->value();
+        } else if (key == "credentialData") {
+            const cppbor::Bstr* valueBstr = valueItem->asBstr();
+            if (valueBstr == nullptr) {
+                LOG(ERROR) << "Value for credentialData is not a bstr";
+                return false;
+            }
+            credentialData_ = valueBstr->value();
+        } else if (key == "attestationCertificate") {
+            const cppbor::Bstr* valueBstr = valueItem->asBstr();
+            if (valueBstr == nullptr) {
+                LOG(ERROR) << "Value for attestationCertificate is not a bstr";
+                return false;
+            }
+            attestationCertificate_ = valueBstr->value();
+        } else if (key == "secureAccessControlProfiles") {
+            const cppbor::Array* array = valueItem->asArray();
+            if (array == nullptr) {
+                LOG(ERROR) << "Value for attestationCertificate is not an array";
+                return false;
+            }
+            for (size_t m = 0; m < array->size(); m++) {
+                const std::unique_ptr<cppbor::Item>& item = (*array)[m];
+                optional<SecureAccessControlProfile> sacp = parseSacp(*item);
+                if (!sacp) {
+                    LOG(ERROR) << "Error parsing SecureAccessControlProfile";
+                    return false;
+                }
+                secureAccessControlProfiles_.push_back(sacp.value());
+            }
+
+        } else if (key == "entryData") {
+            const cppbor::Map* map = valueItem->asMap();
+            if (map == nullptr) {
+                LOG(ERROR) << "Value for encryptedChunks is not an map";
+                return false;
+            }
+            for (size_t m = 0; m < map->size(); m++) {
+                auto [ecKeyItem, ecValueItem] = (*map)[m];
+                const cppbor::Tstr* ecTstr = ecKeyItem->asTstr();
+                if (ecTstr == nullptr) {
+                    LOG(ERROR) << "Key item in encryptedChunks map is not a tstr";
+                    return false;
+                }
+                const string& ecId = ecTstr->value();
+
+                const cppbor::Array* ecEntryArrayItem = ecValueItem->asArray();
+                if (ecEntryArrayItem == nullptr || ecEntryArrayItem->size() < 3) {
+                    LOG(ERROR) << "Value item in encryptedChunks map is an array with at least two "
+                                  "elements";
+                    return false;
+                }
+                const cppbor::Int* ecEntrySizeItem = (*ecEntryArrayItem)[0]->asInt();
+                if (ecEntrySizeItem == nullptr) {
+                    LOG(ERROR) << "Entry size not a number";
+                    return false;
+                }
+                uint64_t entrySize = ecEntrySizeItem->value();
+
+                optional<vector<int32_t>> accessControlProfileIds =
+                    parseAccessControlProfileIds(*(*ecEntryArrayItem)[1]);
+                if (!accessControlProfileIds) {
+                    LOG(ERROR) << "Error parsing access control profile ids";
+                    return false;
+                }
+
+                optional<vector<vector<uint8_t>>> encryptedChunks =
+                    parseEncryptedChunks(*(*ecEntryArrayItem)[2]);
+                if (!encryptedChunks) {
+                    LOG(ERROR) << "Error parsing encrypted chunks";
+                    return false;
+                }
+
+                EntryData data;
+                data.size = entrySize;
+                data.accessControlProfileIds = accessControlProfileIds.value();
+                data.encryptedChunks = encryptedChunks.value();
+                idToEncryptedChunks_[ecId] = data;
+            }
+
+        } else if (key == "authKeyData") {
+            const cppbor::Array* array = valueItem->asArray();
+            if (array == nullptr) {
+                LOG(ERROR) << "Value for authData is not an array";
+                return false;
+            }
+            for (size_t m = 0; m < array->size(); m++) {
+                const std::unique_ptr<cppbor::Item>& item = (*array)[m];
+                optional<AuthKeyData> authKeyData = parseAuthKeyData(*item);
+                if (!authKeyData) {
+                    LOG(ERROR) << "Error parsing AuthKeyData";
+                    return false;
+                }
+                authKeyDatas_.push_back(authKeyData.value());
+            }
+
+        } else if (key == "authKeyCount") {
+            const cppbor::Int* number = valueItem->asInt();
+            if (number == nullptr) {
+                LOG(ERROR) << "Value for authKeyCount is not a number";
+                return false;
+            }
+            keyCount_ = number->value();
+
+        } else if (key == "maxUsesPerAuthKey") {
+            const cppbor::Int* number = valueItem->asInt();
+            if (number == nullptr) {
+                LOG(ERROR) << "Value for maxUsesPerAuthKey is not a number";
+                return false;
+            }
+            maxUsesPerKey_ = number->value();
+        }
+    }
+
+    if (credentialData_.size() == 0) {
+        LOG(ERROR) << "Missing credentialData";
+        return false;
+    }
+
+    if (attestationCertificate_.size() == 0) {
+        LOG(ERROR) << "Missing attestationCertificate";
+        return false;
+    }
+
+    if (size_t(keyCount_) != authKeyDatas_.size()) {
+        LOG(ERROR) << "keyCount_=" << keyCount_
+                   << " != authKeyDatas_.size()=" << authKeyDatas_.size();
+        return false;
+    }
+
+    return true;
+}
+
+const vector<uint8_t>& CredentialData::getCredentialData() const {
+    return credentialData_;
+}
+
+int64_t CredentialData::getSecureUserId() {
+    return secureUserId_;
+}
+
+const vector<uint8_t>& CredentialData::getAttestationCertificate() const {
+    return attestationCertificate_;
+}
+
+const vector<SecureAccessControlProfile>& CredentialData::getSecureAccessControlProfiles() const {
+    return secureAccessControlProfiles_;
+}
+
+bool CredentialData::hasEntryData(const string& namespaceName, const string& entryName) const {
+    string id = namespaceName + ":" + entryName;
+    auto iter = idToEncryptedChunks_.find(id);
+    if (iter == idToEncryptedChunks_.end()) {
+        return false;
+    }
+    return true;
+}
+
+optional<EntryData> CredentialData::getEntryData(const string& namespaceName,
+                                                 const string& entryName) const {
+    string id = namespaceName + ":" + entryName;
+    auto iter = idToEncryptedChunks_.find(id);
+    if (iter == idToEncryptedChunks_.end()) {
+        return {};
+    }
+    return iter->second;
+}
+
+bool CredentialData::deleteCredential() {
+    if (unlink(fileName_.c_str()) != 0) {
+        PLOG(ERROR) << "Error deleting " << fileName_;
+        return false;
+    }
+    return true;
+}
+
+optional<bool> CredentialData::credentialExists(const string& dataPath, uid_t ownerUid,
+                                                const string& name) {
+    struct stat statbuf;
+    string filename = calculateCredentialFileName(dataPath, ownerUid, name);
+    if (stat(filename.c_str(), &statbuf) != 0) {
+        if (errno == ENOENT) {
+            return false;
+        }
+        PLOG(ERROR) << "Error getting information about " << filename;
+        return {};
+    }
+    return true;
+}
+
+// ---
+
+void CredentialData::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey) {
+    keyCount_ = keyCount;
+    maxUsesPerKey_ = maxUsesPerKey;
+
+    // If growing the number of auth keys (prevKeyCount < keyCount_ case) we'll add
+    // new AuthKeyData structs to |authKeyDatas_| and each struct will have empty |certificate|
+    // and |pendingCertificate| fields. Those will be filled out when the
+    // getAuthKeysNeedingCertification() is called.
+    //
+    // If shrinking, we'll just delete the AuthKeyData structs at the end. There's nothing
+    // else to do, the HAL doesn't need to know we're nuking these authentication keys.
+    //
+    // Therefore, in either case it's as simple as just resizing the vector.
+    authKeyDatas_.resize(keyCount_);
+}
+
+const vector<AuthKeyData>& CredentialData::getAuthKeyDatas() const {
+    return authKeyDatas_;
+}
+
+const AuthKeyData* CredentialData::selectAuthKey(bool allowUsingExhaustedKeys) {
+    AuthKeyData* candidate = nullptr;
+
+    int n = 0;
+    int candidateNum = -1;
+    for (AuthKeyData& data : authKeyDatas_) {
+        if (data.certificate.size() != 0) {
+            if (candidate == nullptr || data.useCount < candidate->useCount) {
+                candidate = &data;
+                candidateNum = n;
+            }
+        }
+        n++;
+    }
+
+    if (candidate == nullptr) {
+        return nullptr;
+    }
+
+    if (candidate->useCount >= maxUsesPerKey_ && !allowUsingExhaustedKeys) {
+        return nullptr;
+    }
+
+    candidate->useCount += 1;
+    return candidate;
+}
+
+optional<vector<vector<uint8_t>>>
+CredentialData::getAuthKeysNeedingCertification(const sp<IIdentityCredential>& halBinder) {
+
+    vector<vector<uint8_t>> keysNeedingCert;
+
+    for (AuthKeyData& data : authKeyDatas_) {
+        bool newKeyNeeded = (data.certificate.size() == 0) || (data.useCount >= maxUsesPerKey_);
+        bool certificationPending = (data.pendingCertificate.size() > 0);
+        if (newKeyNeeded && !certificationPending) {
+            vector<uint8_t> signingKeyBlob;
+            Certificate signingKeyCertificate;
+            if (!halBinder->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate)
+                     .isOk()) {
+                LOG(ERROR) << "Error generating signing key-pair";
+                return {};
+            }
+            data.pendingCertificate = signingKeyCertificate.encodedCertificate;
+            data.pendingKeyBlob = signingKeyBlob;
+            certificationPending = true;
+        }
+
+        if (certificationPending) {
+            keysNeedingCert.push_back(data.pendingCertificate);
+        }
+    }
+    return keysNeedingCert;
+}
+
+bool CredentialData::storeStaticAuthenticationData(const vector<uint8_t>& authenticationKey,
+                                                   const vector<uint8_t>& staticAuthData) {
+    for (AuthKeyData& data : authKeyDatas_) {
+        if (data.pendingCertificate == authenticationKey) {
+            data.certificate = data.pendingCertificate;
+            data.keyBlob = data.pendingKeyBlob;
+            data.staticAuthenticationData = staticAuthData;
+            data.pendingCertificate.clear();
+            data.pendingKeyBlob.clear();
+            data.useCount = 0;
+            return true;
+        }
+    }
+    return false;
+}
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/identity/CredentialData.h b/identity/CredentialData.h
new file mode 100644
index 0000000..7995828
--- /dev/null
+++ b/identity/CredentialData.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 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 SYSTEM_SECURITY_CREDENTIAL_DATA_H_
+#define SYSTEM_SECURITY_CREDENTIAL_DATA_H_
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <android/hardware/identity/IIdentityCredential.h>
+#include <android/hardware/identity/SecureAccessControlProfile.h>
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::hardware::identity::Certificate;
+using ::android::hardware::identity::IIdentityCredential;
+using ::android::hardware::identity::SecureAccessControlProfile;
+using ::std::map;
+using ::std::optional;
+using ::std::pair;
+using ::std::string;
+using ::std::tuple;
+using ::std::vector;
+
+struct EntryData {
+    EntryData() {}
+
+    uint64_t size = 0;
+    vector<int32_t> accessControlProfileIds;
+    vector<vector<uint8_t>> encryptedChunks;
+};
+
+struct AuthKeyData {
+    AuthKeyData() {}
+
+    vector<uint8_t> certificate;
+    vector<uint8_t> keyBlob;
+    vector<uint8_t> staticAuthenticationData;
+    vector<uint8_t> pendingCertificate;
+    vector<uint8_t> pendingKeyBlob;
+    int useCount = 0;
+};
+
+class CredentialData : public RefBase {
+  public:
+    CredentialData(const string& dataPath, uid_t ownerUid, const string& name);
+
+    static string calculateCredentialFileName(const string& dataPath, uid_t ownerUid,
+                                              const string& name);
+
+    static optional<bool> credentialExists(const string& dataPath, uid_t ownerUid,
+                                           const string& name);
+
+    void setSecureUserId(int64_t secureUserId);
+
+    void setCredentialData(const vector<uint8_t>& credentialData);
+
+    void setAttestationCertificate(const vector<uint8_t>& attestationCertificate);
+
+    void
+    addSecureAccessControlProfile(const SecureAccessControlProfile& secureAccessControlProfile);
+
+    void addEntryData(const string& namespaceName, const string& entryName, const EntryData& data);
+
+    bool saveToDisk() const;
+
+    bool loadFromDisk();
+
+    bool deleteCredential();
+
+    void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey);
+
+    // Getters
+
+    int64_t getSecureUserId();
+
+    const vector<uint8_t>& getCredentialData() const;
+
+    const vector<uint8_t>& getAttestationCertificate() const;
+
+    const vector<SecureAccessControlProfile>& getSecureAccessControlProfiles() const;
+
+    bool hasEntryData(const string& namespaceName, const string& entryName) const;
+
+    optional<EntryData> getEntryData(const string& namespaceName, const string& entryName) const;
+
+    const vector<AuthKeyData>& getAuthKeyDatas() const;
+
+    // Returns |nullptr| if a suitable key cannot be found. Otherwise returns
+    // the authentication and increases its use-count.
+    const AuthKeyData* selectAuthKey(bool allowUsingExhaustedKeys);
+
+    optional<vector<vector<uint8_t>>>
+    getAuthKeysNeedingCertification(const sp<IIdentityCredential>& halBinder);
+
+    bool storeStaticAuthenticationData(const vector<uint8_t>& authenticationKey,
+                                       const vector<uint8_t>& staticAuthData);
+
+  private:
+    // Set by constructor.
+    //
+    string dataPath_;
+    uid_t ownerUid_;
+    string name_;
+
+    // Calculated at construction time, from |dataPath_|, |ownerUid_|, |name_|.
+    string fileName_;
+
+    // Data serialized in CBOR from here:
+    //
+    int64_t secureUserId_;
+    vector<uint8_t> credentialData_;
+    vector<uint8_t> attestationCertificate_;
+    vector<SecureAccessControlProfile> secureAccessControlProfiles_;
+    map<string, EntryData> idToEncryptedChunks_;
+
+    int keyCount_ = 0;
+    int maxUsesPerKey_ = 1;
+    vector<AuthKeyData> authKeyDatas_;  // Always |keyCount_| long.
+};
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_CREDENTIAL_DATA_H_
diff --git a/identity/CredentialStore.cpp b/identity/CredentialStore.cpp
new file mode 100644
index 0000000..e3a825b
--- /dev/null
+++ b/identity/CredentialStore.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 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 "CredentialStore"
+
+#include <algorithm>
+
+#include <android-base/logging.h>
+
+#include <binder/IPCThreadState.h>
+
+#include "Credential.h"
+#include "CredentialData.h"
+#include "CredentialStore.h"
+#include "Util.h"
+#include "WritableCredential.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal)
+    : dataPath_(dataPath), hal_(hal) {}
+
+bool CredentialStore::init() {
+    Status status = hal_->getHardwareInformation(&hwInfo_);
+    if (!status.isOk()) {
+        LOG(ERROR) << "Error getting hardware information: " << status.toString8();
+        return false;
+    }
+
+    LOG(INFO) << "Connected to Identity Credential HAL with name '" << hwInfo_.credentialStoreName
+              << "' authored by '" << hwInfo_.credentialStoreAuthorName << "' with chunk size "
+              << hwInfo_.dataChunkSize << " and directoAccess set to "
+              << (hwInfo_.isDirectAccess ? "true" : "false");
+    return true;
+}
+
+CredentialStore::~CredentialStore() {}
+
+Status CredentialStore::getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) {
+    SecurityHardwareInfoParcel info;
+    info.directAccess = hwInfo_.isDirectAccess;
+    info.supportedDocTypes = hwInfo_.supportedDocTypes;
+    *_aidl_return = info;
+    return Status::ok();
+};
+
+Status CredentialStore::createCredential(const std::string& credentialName,
+                                         const std::string& docType,
+                                         sp<IWritableCredential>* _aidl_return) {
+    uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+    optional<bool> credentialExists =
+        CredentialData::credentialExists(dataPath_, callingUid, credentialName);
+    if (!credentialExists.has_value()) {
+        return Status::fromServiceSpecificError(
+            ERROR_GENERIC, "Error determining if credential with given name exists");
+    }
+    if (credentialExists.value()) {
+        return Status::fromServiceSpecificError(ERROR_ALREADY_PERSONALIZED,
+                                                "Credential with given name already exists");
+    }
+
+    if (hwInfo_.supportedDocTypes.size() > 0) {
+        if (std::find(hwInfo_.supportedDocTypes.begin(), hwInfo_.supportedDocTypes.end(),
+                      docType) == hwInfo_.supportedDocTypes.end()) {
+            return Status::fromServiceSpecificError(ERROR_DOCUMENT_TYPE_NOT_SUPPORTED,
+                                                    "No support for given document type");
+        }
+    }
+
+    sp<IWritableIdentityCredential> halWritableCredential;
+    Status status = hal_->createCredential(docType, false, &halWritableCredential);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+
+    sp<IWritableCredential> writableCredential = new WritableCredential(
+        dataPath_, credentialName, docType, hwInfo_.dataChunkSize, halWritableCredential);
+    *_aidl_return = writableCredential;
+    return Status::ok();
+}
+
+Status CredentialStore::getCredentialByName(const std::string& credentialName, int32_t cipherSuite,
+                                            sp<ICredential>* _aidl_return) {
+    *_aidl_return = nullptr;
+
+    uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+    optional<bool> credentialExists =
+        CredentialData::credentialExists(dataPath_, callingUid, credentialName);
+    if (!credentialExists.has_value()) {
+        return Status::fromServiceSpecificError(
+            ERROR_GENERIC, "Error determining if credential with given name exists");
+    }
+    if (!credentialExists.value()) {
+        return Status::fromServiceSpecificError(ERROR_NO_SUCH_CREDENTIAL,
+                                                "Credential with given name doesn't exist");
+    }
+
+    // Note: IdentityCredentialStore.java's CipherSuite enumeration and CipherSuite from the
+    // HAL is manually kept in sync. So this cast is safe.
+    sp<Credential> credential = new Credential(CipherSuite(cipherSuite), dataPath_, credentialName);
+
+    Status loadStatus = credential->loadCredential(hal_);
+    if (!loadStatus.isOk()) {
+        LOG(ERROR) << "Error loading credential";
+    } else {
+        *_aidl_return = credential;
+    }
+    return loadStatus;
+}
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/identity/CredentialStore.h b/identity/CredentialStore.h
new file mode 100644
index 0000000..24b2b4d
--- /dev/null
+++ b/identity/CredentialStore.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 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 SYSTEM_SECURITY_CREDENTIAL_STORE_H_
+#define SYSTEM_SECURITY_CREDENTIAL_STORE_H_
+
+#include <string>
+#include <vector>
+
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+
+#include <android/security/identity/BnCredentialStore.h>
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::sp;
+using ::android::binder::Status;
+using ::std::string;
+using ::std::unique_ptr;
+using ::std::vector;
+
+using ::android::hardware::identity::HardwareInformation;
+using ::android::hardware::identity::IIdentityCredentialStore;
+
+class CredentialStore : public BnCredentialStore {
+  public:
+    CredentialStore(const string& dataPath, sp<IIdentityCredentialStore> hal);
+    ~CredentialStore();
+
+    bool init();
+
+    // ICredentialStore overrides
+    Status getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) override;
+
+    Status createCredential(const string& credentialName, const string& docType,
+                            sp<IWritableCredential>* _aidl_return) override;
+
+    Status getCredentialByName(const string& credentialName, int32_t cipherSuite,
+                               sp<ICredential>* _aidl_return) override;
+
+  private:
+    string dataPath_;
+
+    sp<IIdentityCredentialStore> hal_;
+
+    HardwareInformation hwInfo_;
+};
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_CREDENTIAL_STORE_H_
diff --git a/identity/CredentialStoreFactory.cpp b/identity/CredentialStoreFactory.cpp
new file mode 100644
index 0000000..5c3bf36
--- /dev/null
+++ b/identity/CredentialStoreFactory.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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 "CredentialStoreFactory"
+
+#include <android-base/logging.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+//#include "CredentialStore.h"
+#include "CredentialStoreFactory.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::hardware::identity::IIdentityCredentialStore;
+
+CredentialStoreFactory::CredentialStoreFactory(const std::string& dataPath) : dataPath_(dataPath) {}
+
+CredentialStoreFactory::~CredentialStoreFactory() {}
+
+CredentialStore* CredentialStoreFactory::createCredentialStore(const string& instanceName) {
+    String16 serviceName =
+        IIdentityCredentialStore::descriptor + String16("/") + String16(instanceName.c_str());
+    sp<IIdentityCredentialStore> hal =
+        android::waitForDeclaredService<IIdentityCredentialStore>(serviceName);
+    if (hal.get() == nullptr) {
+        LOG(ERROR) << "Error getting HAL for IdentityCredentialStore store with service name '"
+                   << serviceName << "'";
+        return nullptr;
+    }
+
+    CredentialStore* store = new CredentialStore(dataPath_, hal);
+    if (!store->init()) {
+        LOG(ERROR) << "Error initializing CredentialStore with service name '" << serviceName
+                   << "'";
+        delete store;
+        return nullptr;
+    }
+    return store;
+}
+
+Status CredentialStoreFactory::getCredentialStore(int32_t credentialStoreType,
+                                                  sp<ICredentialStore>* _aidl_return) {
+    switch (credentialStoreType) {
+    case CREDENTIAL_STORE_TYPE_DEFAULT:
+        if (defaultStore_.get() == nullptr) {
+            defaultStore_ = createCredentialStore("default");
+        }
+        if (defaultStore_.get() == nullptr) {
+            return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                    "Error creating default store");
+        }
+        *_aidl_return = defaultStore_.get();
+        return Status::ok();
+
+    case CREDENTIAL_STORE_TYPE_DIRECT_ACCESS:
+        if (directAccessStore_.get() == nullptr) {
+            directAccessStore_ = createCredentialStore("directAccess");
+        }
+        if (directAccessStore_.get() == nullptr) {
+            return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                    "Error creating direct access store");
+        }
+        *_aidl_return = directAccessStore_.get();
+        return Status::ok();
+        break;
+    }
+
+    return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                            "Unknown credential store type");
+}
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/identity/CredentialStoreFactory.h b/identity/CredentialStoreFactory.h
new file mode 100644
index 0000000..b944b26
--- /dev/null
+++ b/identity/CredentialStoreFactory.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 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 SYSTEM_SECURITY_CREDENTIAL_STORE_FACTORY_H_
+#define SYSTEM_SECURITY_CREDENTIAL_STORE_FACTORY_H_
+
+#include <android/security/identity/BnCredentialStoreFactory.h>
+
+#include "CredentialStore.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::sp;
+using ::android::binder::Status;
+using ::std::string;
+
+class CredentialStoreFactory : public BnCredentialStoreFactory {
+  public:
+    explicit CredentialStoreFactory(const string& dataPath);
+    ~CredentialStoreFactory();
+
+    Status getCredentialStore(int32_t credentialStoreType,
+                              sp<ICredentialStore>* _aidl_return) override;
+
+  private:
+    CredentialStore* createCredentialStore(const string& instanceName);
+
+    string dataPath_;
+
+    sp<CredentialStore> defaultStore_;
+    sp<CredentialStore> directAccessStore_;
+};
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_CREDENTIAL_STORE_FACTORY_H_
diff --git a/identity/Util.cpp b/identity/Util.cpp
new file mode 100644
index 0000000..a962dc3
--- /dev/null
+++ b/identity/Util.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 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 "Util"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+#include <android/security/identity/ICredentialStore.h>
+
+#include "Util.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::base::StringPrintf;
+
+Status halStatusToError(const Status& halStatus, int credStoreError) {
+    string message = StringPrintf(
+        "HAL failed with exception code %d (%s), service-specific error code %d, message '%s'",
+        halStatus.exceptionCode(), Status::exceptionToString(halStatus.exceptionCode()).c_str(),
+        halStatus.serviceSpecificErrorCode(), halStatus.exceptionMessage().c_str());
+    return Status::fromServiceSpecificError(credStoreError, message.c_str());
+}
+
+Status halStatusToGenericError(const Status& halStatus) {
+    return halStatusToError(halStatus, ICredentialStore::ERROR_GENERIC);
+}
+
+optional<vector<uint8_t>> fileGetContents(const string& path) {
+    int fd = open(path.c_str(), O_RDONLY);
+    if (fd == -1) {
+        PLOG(ERROR) << "Error opening " << path;
+        return {};
+    }
+
+    struct stat statbuf;
+    if (fstat(fd, &statbuf) != 0) {
+        PLOG(ERROR) << "Error statting " << path;
+        close(fd);
+        return {};
+    }
+    vector<uint8_t> data;
+    data.resize(statbuf.st_size);
+
+    uint8_t* p = data.data();
+    size_t remaining = data.size();
+    while (remaining > 0) {
+        ssize_t numRead = TEMP_FAILURE_RETRY(read(fd, p, remaining));
+        if (numRead <= 0) {
+            PLOG(ERROR) << "Failed reading from '" << path << "'";
+            close(fd);
+            return {};
+        }
+        p += numRead;
+        remaining -= numRead;
+    }
+    close(fd);
+
+    return data;
+}
+
+bool fileSetContents(const string& path, const vector<uint8_t>& data) {
+    char tempName[4096];
+    int fd;
+
+    string tempNameStr = path + ".XXXXXX";
+    if (tempNameStr.size() >= sizeof tempName - 1) {
+        LOG(ERROR) << "Path name too long";
+        return false;
+    }
+    strncpy(tempName, tempNameStr.c_str(), sizeof tempName);
+
+    fd = mkstemp(tempName);
+    if (fd == -1) {
+        PLOG(ERROR) << "Error creating temp file for '" << path << "'";
+        return false;
+    }
+
+    const uint8_t* p = data.data();
+    size_t remaining = data.size();
+    while (remaining > 0) {
+        ssize_t numWritten = TEMP_FAILURE_RETRY(write(fd, p, remaining));
+        if (numWritten <= 0) {
+            PLOG(ERROR) << "Failed writing into temp file for '" << path << "'";
+            close(fd);
+            return false;
+        }
+        p += numWritten;
+        remaining -= numWritten;
+    }
+
+    if (TEMP_FAILURE_RETRY(fsync(fd) == -1)) {
+        PLOG(ERROR) << "Failed fsyncing temp file for '" << path << "'";
+        close(fd);
+        return false;
+    }
+    close(fd);
+
+    if (rename(tempName, path.c_str()) != 0) {
+        PLOG(ERROR) << "Error renaming temp file for '" << path << "'";
+        close(fd);
+        return false;
+    }
+
+    return true;
+}
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/identity/Util.h b/identity/Util.h
new file mode 100644
index 0000000..12953f7
--- /dev/null
+++ b/identity/Util.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 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 SYSTEM_SECURITY_IDENTITY_UTIL_H_
+#define SYSTEM_SECURITY_IDENTITY_UTIL_H_
+
+#include <string>
+#include <vector>
+
+#include <binder/Status.h>
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::std::optional;
+using ::std::string;
+using ::std::vector;
+
+using ::android::binder::Status;
+
+// Converts a HAL status to a credstore service-specific error with code
+// ICredentialStore::ERROR_GENERIC.
+Status halStatusToGenericError(const Status& halStatus);
+
+// Converts a HAL status to a credstore service-specific error of a given value
+Status halStatusToError(const Status& halStatus, int credStoreError);
+
+// Helper function to atomically write |data| into file at |path|.
+//
+// Returns true on success, false on error.
+//
+bool fileSetContents(const string& path, const vector<uint8_t>& data);
+
+// Helper function which reads contents offile at |path| into |data|.
+//
+// Returns nothing on error, the content on success.
+//
+optional<vector<uint8_t>> fileGetContents(const string& path);
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_IDENTITY_UTIL_H_
diff --git a/identity/WritableCredential.cpp b/identity/WritableCredential.cpp
new file mode 100644
index 0000000..dec95a6
--- /dev/null
+++ b/identity/WritableCredential.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 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 "WritableCredential"
+
+#include <android-base/logging.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <android/security/identity/ICredentialStore.h>
+#include <binder/IPCThreadState.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+#include <keystore/keystore_attestation_id.h>
+
+#include "CredentialData.h"
+#include "Util.h"
+#include "WritableCredential.h"
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::std::pair;
+
+using ::android::hardware::identity::SecureAccessControlProfile;
+
+using ::android::hardware::identity::support::chunkVector;
+
+WritableCredential::WritableCredential(const string& dataPath, const string& credentialName,
+                                       const string& /*docType*/, size_t dataChunkSize,
+                                       sp<IWritableIdentityCredential> halBinder)
+    : dataPath_(dataPath), credentialName_(credentialName), dataChunkSize_(dataChunkSize),
+      halBinder_(halBinder) {}
+
+WritableCredential::~WritableCredential() {}
+
+Status WritableCredential::ensureAttestationCertificateExists(const vector<uint8_t>& challenge) {
+    if (!attestationCertificate_.empty()) {
+        return Status::ok();
+    }
+
+    const int32_t callingUid = IPCThreadState::self()->getCallingUid();
+    auto asn1AttestationId = android::security::gather_attestation_application_id(callingUid);
+    if (!asn1AttestationId.isOk()) {
+        LOG(ERROR) << "Failed gathering AttestionApplicationId";
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Failed gathering AttestionApplicationId");
+    }
+
+    vector<Certificate> certificateChain;
+    Status status = halBinder_->getAttestationCertificate(asn1AttestationId.value(), challenge,
+                                                          &certificateChain);
+    if (!status.isOk()) {
+        LOG(ERROR) << "Error calling getAttestationCertificate()";
+        return halStatusToGenericError(status);
+    }
+
+    vector<vector<uint8_t>> splitCerts;
+    for (const auto& cert : certificateChain) {
+        splitCerts.push_back(cert.encodedCertificate);
+    }
+    attestationCertificate_ =
+        ::android::hardware::identity::support::certificateChainJoin(splitCerts);
+
+    return Status::ok();
+}
+
+Status WritableCredential::getCredentialKeyCertificateChain(const vector<uint8_t>& challenge,
+                                                            vector<uint8_t>* _aidl_return) {
+
+    Status ensureStatus = ensureAttestationCertificateExists(challenge);
+    if (!ensureStatus.isOk()) {
+        return ensureStatus;
+    }
+
+    *_aidl_return = attestationCertificate_;
+    return Status::ok();
+}
+
+Status
+WritableCredential::personalize(const vector<AccessControlProfileParcel>& accessControlProfiles,
+                                const vector<EntryNamespaceParcel>& entryNamespaces,
+                                int64_t secureUserId, vector<uint8_t>* _aidl_return) {
+    Status ensureStatus = ensureAttestationCertificateExists({});
+    if (!ensureStatus.isOk()) {
+        return ensureStatus;
+    }
+
+    uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+    CredentialData data = CredentialData(dataPath_, callingUid, credentialName_);
+
+    // Note: The value 0 is used to convey that no user-authentication is needed for this
+    // credential. This is to allow creating credentials w/o user authentication on devices
+    // where Secure lock screen is not enabled.
+    data.setSecureUserId(secureUserId);
+
+    data.setAttestationCertificate(attestationCertificate_);
+
+    vector<int32_t> entryCounts;
+    for (const EntryNamespaceParcel& ensParcel : entryNamespaces) {
+        entryCounts.push_back(ensParcel.entries.size());
+    }
+
+    Status status = halBinder_->startPersonalization(accessControlProfiles.size(), entryCounts);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+
+    for (const AccessControlProfileParcel& acpParcel : accessControlProfiles) {
+        Certificate certificate;
+        certificate.encodedCertificate = acpParcel.readerCertificate;
+        SecureAccessControlProfile profile;
+        status = halBinder_->addAccessControlProfile(
+            acpParcel.id, certificate, acpParcel.userAuthenticationRequired,
+            acpParcel.userAuthenticationTimeoutMillis, secureUserId, &profile);
+        if (!status.isOk()) {
+            return halStatusToGenericError(status);
+        }
+        data.addSecureAccessControlProfile(profile);
+    }
+
+    for (const EntryNamespaceParcel& ensParcel : entryNamespaces) {
+        for (const EntryParcel& eParcel : ensParcel.entries) {
+            vector<vector<uint8_t>> chunks = chunkVector(eParcel.value, dataChunkSize_);
+
+            vector<int32_t> ids;
+            std::copy(eParcel.accessControlProfileIds.begin(),
+                      eParcel.accessControlProfileIds.end(), std::back_inserter(ids));
+
+            status = halBinder_->beginAddEntry(ids, ensParcel.namespaceName, eParcel.name,
+                                               eParcel.value.size());
+            if (!status.isOk()) {
+                return halStatusToGenericError(status);
+            }
+
+            vector<vector<uint8_t>> encryptedChunks;
+            for (const auto& chunk : chunks) {
+                vector<uint8_t> encryptedChunk;
+                status = halBinder_->addEntryValue(chunk, &encryptedChunk);
+                if (!status.isOk()) {
+                    return halStatusToGenericError(status);
+                }
+                encryptedChunks.push_back(encryptedChunk);
+            }
+            EntryData eData;
+            eData.size = eParcel.value.size();
+            eData.accessControlProfileIds = std::move(ids);
+            eData.encryptedChunks = std::move(encryptedChunks);
+            data.addEntryData(ensParcel.namespaceName, eParcel.name, eData);
+        }
+    }
+
+    vector<uint8_t> credentialData;
+    vector<uint8_t> proofOfProvisioningSignature;
+    status = halBinder_->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
+    if (!status.isOk()) {
+        return halStatusToGenericError(status);
+    }
+    data.setCredentialData(credentialData);
+
+    if (!data.saveToDisk()) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error saving credential data to disk");
+    }
+
+    *_aidl_return = proofOfProvisioningSignature;
+    return Status::ok();
+}
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/identity/WritableCredential.h b/identity/WritableCredential.h
new file mode 100644
index 0000000..8b5e19e
--- /dev/null
+++ b/identity/WritableCredential.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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 SYSTEM_SECURITY_WRITABLE_CREDENTIAL_H_
+#define SYSTEM_SECURITY_WRITABLE_CREDENTIAL_H_
+
+#include <string>
+#include <vector>
+
+#include <android/security/identity/BnWritableCredential.h>
+
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::binder::Status;
+using ::android::hardware::identity::IWritableIdentityCredential;
+using ::std::string;
+using ::std::vector;
+
+class WritableCredential : public BnWritableCredential {
+  public:
+    WritableCredential(const string& dataPath, const string& credentialName, const string& docType,
+                       size_t dataChunkSize, sp<IWritableIdentityCredential> halBinder);
+    ~WritableCredential();
+
+    // IWritableCredential overrides
+    Status getCredentialKeyCertificateChain(const vector<uint8_t>& challenge,
+                                            vector<uint8_t>* _aidl_return) override;
+
+    Status personalize(const vector<AccessControlProfileParcel>& accessControlProfiles,
+                       const vector<EntryNamespaceParcel>& entryNamespaces, int64_t secureUserId,
+                       vector<uint8_t>* _aidl_return) override;
+
+  private:
+    string dataPath_;
+    string credentialName_;
+    size_t dataChunkSize_;
+    sp<IWritableIdentityCredential> halBinder_;
+    vector<uint8_t> attestationCertificate_;
+
+    Status ensureAttestationCertificateExists(const vector<uint8_t>& challenge);
+};
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_WRITABLE_CREDENTIAL_H_
diff --git a/identity/binder/android/security/identity/AccessControlProfileParcel.aidl b/identity/binder/android/security/identity/AccessControlProfileParcel.aidl
new file mode 100644
index 0000000..4bb85a9
--- /dev/null
+++ b/identity/binder/android/security/identity/AccessControlProfileParcel.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+/**
+ * @hide
+ */
+parcelable AccessControlProfileParcel {
+    int id;
+    byte[] readerCertificate;
+    boolean userAuthenticationRequired;
+    long userAuthenticationTimeoutMillis;
+}
diff --git a/identity/binder/android/security/identity/AuthKeyParcel.aidl b/identity/binder/android/security/identity/AuthKeyParcel.aidl
new file mode 100644
index 0000000..9374b8e
--- /dev/null
+++ b/identity/binder/android/security/identity/AuthKeyParcel.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+/**
+ * @hide
+ */
+parcelable AuthKeyParcel {
+    byte[] x509cert;
+}
diff --git a/identity/binder/android/security/identity/EntryNamespaceParcel.aidl b/identity/binder/android/security/identity/EntryNamespaceParcel.aidl
new file mode 100644
index 0000000..50758c8
--- /dev/null
+++ b/identity/binder/android/security/identity/EntryNamespaceParcel.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.EntryParcel;
+
+/**
+ * @hide
+ */
+parcelable EntryNamespaceParcel {
+    @utf8InCpp String namespaceName;
+    EntryParcel[] entries;
+}
diff --git a/identity/binder/android/security/identity/EntryParcel.aidl b/identity/binder/android/security/identity/EntryParcel.aidl
new file mode 100644
index 0000000..8d236d4
--- /dev/null
+++ b/identity/binder/android/security/identity/EntryParcel.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+/**
+ * @hide
+ */
+parcelable EntryParcel {
+    @utf8InCpp String name;
+    byte[] value;
+    int[] accessControlProfileIds;
+}
diff --git a/identity/binder/android/security/identity/GetEntriesResultParcel.aidl b/identity/binder/android/security/identity/GetEntriesResultParcel.aidl
new file mode 100644
index 0000000..03b363c
--- /dev/null
+++ b/identity/binder/android/security/identity/GetEntriesResultParcel.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.ResultNamespaceParcel;
+
+/**
+ * @hide
+ */
+parcelable GetEntriesResultParcel {
+    ResultNamespaceParcel[] resultNamespaces;
+    byte[] deviceNameSpaces;
+    byte[] mac;
+    byte[] staticAuthenticationData;
+}
diff --git a/identity/binder/android/security/identity/ICredential.aidl b/identity/binder/android/security/identity/ICredential.aidl
new file mode 100644
index 0000000..7bd0df7
--- /dev/null
+++ b/identity/binder/android/security/identity/ICredential.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.RequestNamespaceParcel;
+import android.security.identity.GetEntriesResultParcel;
+import android.security.identity.AuthKeyParcel;
+
+/**
+ * @hide
+ */
+interface ICredential {
+    /* The STATUS_* constants are used in the status field in ResultEntryParcel.
+     * Keep in sync with ResultNamespace.java.
+     */
+    const int STATUS_OK = 0;
+    const int STATUS_NO_SUCH_ENTRY = 1;
+    const int STATUS_NOT_REQUESTED = 2;
+    const int STATUS_NOT_IN_REQUEST_MESSAGE = 3;
+    const int STATUS_USER_AUTHENTICATION_FAILED = 4;
+    const int STATUS_READER_AUTHENTICATION_FAILED = 5;
+    const int STATUS_NO_ACCESS_CONTROL_PROFILES = 6;
+
+    byte[] createEphemeralKeyPair();
+
+    void setReaderEphemeralPublicKey(in byte[] publicKey);
+
+    byte[] deleteCredential();
+
+    byte[] getCredentialKeyCertificateChain();
+
+    long selectAuthKey(in boolean allowUsingExhaustedKeys);
+
+    GetEntriesResultParcel getEntries(in byte[] requestMessage,
+                                      in RequestNamespaceParcel[] requestNamespaces,
+                                      in byte[] sessionTranscript,
+                                      in byte[] readerSignature,
+                                      in boolean allowUsingExhaustedKeys);
+
+    void setAvailableAuthenticationKeys(in int keyCount, in int maxUsesPerKey);
+
+    AuthKeyParcel[] getAuthKeysNeedingCertification();
+
+    void storeStaticAuthenticationData(in AuthKeyParcel authenticationKey, in byte[] staticAuthData);
+
+    int[] getAuthenticationDataUsageCount();
+}
+
diff --git a/identity/binder/android/security/identity/ICredentialStore.aidl b/identity/binder/android/security/identity/ICredentialStore.aidl
new file mode 100644
index 0000000..1039831
--- /dev/null
+++ b/identity/binder/android/security/identity/ICredentialStore.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.IWritableCredential;
+import android.security.identity.ICredential;
+import android.security.identity.SecurityHardwareInfoParcel;
+
+/**
+ * @hide
+ */
+interface ICredentialStore {
+    /* All binder calls may return a ServiceSpecificException
+     * with the following error codes:
+     */
+    const int ERROR_NONE = 0;
+    const int ERROR_GENERIC = 1;
+    const int ERROR_ALREADY_PERSONALIZED = 2;
+    const int ERROR_NO_SUCH_CREDENTIAL = 3;
+    const int ERROR_CIPHER_SUITE_NOT_SUPPORTED = 4;
+    const int ERROR_EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 5;
+    const int ERROR_NO_AUTHENTICATION_KEY_AVAILABLE = 6;
+    const int ERROR_INVALID_READER_SIGNATURE = 7;
+    const int ERROR_DOCUMENT_TYPE_NOT_SUPPORTED = 8;
+    const int ERROR_AUTHENTICATION_KEY_NOT_FOUND = 9;
+    const int ERROR_INVALID_ITEMS_REQUEST_MESSAGE = 10;
+    const int ERROR_SESSION_TRANSCRIPT_MISMATCH = 11;
+
+    SecurityHardwareInfoParcel getSecurityHardwareInfo();
+
+    IWritableCredential createCredential(in @utf8InCpp String credentialName,
+                                         in @utf8InCpp String docType);
+    ICredential getCredentialByName(in @utf8InCpp String credentialName,
+                                    in int cipherSuite);
+}
diff --git a/identity/binder/android/security/identity/ICredentialStoreFactory.aidl b/identity/binder/android/security/identity/ICredentialStoreFactory.aidl
new file mode 100644
index 0000000..3164f28
--- /dev/null
+++ b/identity/binder/android/security/identity/ICredentialStoreFactory.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.ICredentialStore;
+
+/**
+ * @hide
+ */
+interface ICredentialStoreFactory {
+    const int CREDENTIAL_STORE_TYPE_DEFAULT = 0;
+    const int CREDENTIAL_STORE_TYPE_DIRECT_ACCESS = 1;
+
+    ICredentialStore getCredentialStore(int credentialStoreType);
+}
diff --git a/identity/binder/android/security/identity/IWritableCredential.aidl b/identity/binder/android/security/identity/IWritableCredential.aidl
new file mode 100644
index 0000000..0e7ca4c
--- /dev/null
+++ b/identity/binder/android/security/identity/IWritableCredential.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.AccessControlProfileParcel;
+import android.security.identity.EntryNamespaceParcel;
+
+/**
+ * @hide
+ */
+interface IWritableCredential {
+    byte[] getCredentialKeyCertificateChain(in byte[] challenge);
+    byte[] personalize(in AccessControlProfileParcel[] accessControlProfiles,
+                       in EntryNamespaceParcel[] entryNamespaces,
+                       in long secureUserId);
+}
diff --git a/identity/binder/android/security/identity/RequestEntryParcel.aidl b/identity/binder/android/security/identity/RequestEntryParcel.aidl
new file mode 100644
index 0000000..77d80c1
--- /dev/null
+++ b/identity/binder/android/security/identity/RequestEntryParcel.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+/**
+ * @hide
+ */
+parcelable RequestEntryParcel {
+    @utf8InCpp String name;
+}
diff --git a/identity/binder/android/security/identity/RequestNamespaceParcel.aidl b/identity/binder/android/security/identity/RequestNamespaceParcel.aidl
new file mode 100644
index 0000000..a4fb624
--- /dev/null
+++ b/identity/binder/android/security/identity/RequestNamespaceParcel.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.RequestEntryParcel;
+
+/**
+ * @hide
+ */
+parcelable RequestNamespaceParcel {
+    @utf8InCpp String namespaceName;
+    RequestEntryParcel[] entries;
+}
diff --git a/identity/binder/android/security/identity/ResultEntryParcel.aidl b/identity/binder/android/security/identity/ResultEntryParcel.aidl
new file mode 100644
index 0000000..fb4f9ef
--- /dev/null
+++ b/identity/binder/android/security/identity/ResultEntryParcel.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+/**
+ * @hide
+ */
+parcelable ResultEntryParcel {
+    int status;
+    @utf8InCpp String name;
+    byte[] value;
+}
diff --git a/identity/binder/android/security/identity/ResultNamespaceParcel.aidl b/identity/binder/android/security/identity/ResultNamespaceParcel.aidl
new file mode 100644
index 0000000..c9543d9
--- /dev/null
+++ b/identity/binder/android/security/identity/ResultNamespaceParcel.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+import android.security.identity.ResultEntryParcel;
+
+/**
+ * @hide
+ */
+parcelable ResultNamespaceParcel {
+    @utf8InCpp String namespaceName;
+    ResultEntryParcel[] entries;
+}
diff --git a/identity/binder/android/security/identity/SecurityHardwareInfoParcel.aidl b/identity/binder/android/security/identity/SecurityHardwareInfoParcel.aidl
new file mode 100644
index 0000000..cabaf21
--- /dev/null
+++ b/identity/binder/android/security/identity/SecurityHardwareInfoParcel.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package android.security.identity;
+
+/**
+ * @hide
+ */
+parcelable SecurityHardwareInfoParcel {
+    boolean directAccess;
+    @utf8InCpp String[] supportedDocTypes;
+}
diff --git a/identity/credstore.rc b/identity/credstore.rc
new file mode 100644
index 0000000..d9e989a
--- /dev/null
+++ b/identity/credstore.rc
@@ -0,0 +1,4 @@
+service credstore /system/bin/credstore /data/misc/credstore
+    class core
+    user credstore
+    group credstore
diff --git a/identity/main.cpp b/identity/main.cpp
new file mode 100644
index 0000000..af03a30
--- /dev/null
+++ b/identity/main.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 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.security.identity"
+
+#include <filesystem>
+
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include "CredentialStoreFactory.h"
+
+#include <cppbor.h>
+
+using ::std::string;
+
+using ::android::IPCThreadState;
+using ::android::IServiceManager;
+using ::android::sp;
+using ::android::String16;
+using ::android::base::InitLogging;
+using ::android::base::StderrLogger;
+
+using ::android::security::identity::CredentialStoreFactory;
+
+int main(int argc, char* argv[]) {
+    InitLogging(argv, StderrLogger);
+
+    CHECK(argc == 2) << "A directory must be specified";
+    string data_dir = string(argv[1]);
+    CHECK(chdir(data_dir.c_str()) != -1) << "chdir: " << data_dir << ": " << strerror(errno);
+
+    sp<IServiceManager> sm = ::android::defaultServiceManager();
+    sp<CredentialStoreFactory> factory = new CredentialStoreFactory(data_dir);
+
+    auto ret = sm->addService(String16("android.security.identity"), factory);
+    CHECK(ret == ::android::OK) << "Couldn't register binder service";
+    LOG(ERROR) << "Registered binder service";
+
+    IPCThreadState::self()->joinThreadPool();
+
+    return 0;
+}
diff --git a/keystore-engine/Android.bp b/keystore-engine/Android.bp
index 60f5940..6512c66 100644
--- a/keystore-engine/Android.bp
+++ b/keystore-engine/Android.bp
@@ -63,7 +63,6 @@
         "libcrypto",
         "liblog",
         "libhidlbase",
-        "libhidltransport",
         "libcutils",
         "libutils",
     ],
diff --git a/keystore-engine/android_engine.cpp b/keystore-engine/android_engine.cpp
index 856194d..e3525b2 100644
--- a/keystore-engine/android_engine.cpp
+++ b/keystore-engine/android_engine.cpp
@@ -251,32 +251,11 @@
       EC_KEY_get_ex_data(ec_key, g_keystore_engine->ec_key_ex_index()));
 }
 
-struct EVP_PKEY_Delete {
-    void operator()(EVP_PKEY* p) const {
-        EVP_PKEY_free(p);
-    }
-};
-typedef std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
-
-struct RSA_Delete {
-    void operator()(RSA* p) const {
-        RSA_free(p);
-    }
-};
-typedef std::unique_ptr<RSA, RSA_Delete> Unique_RSA;
-
-struct EC_KEY_Delete {
-    void operator()(EC_KEY* ec) const {
-        EC_KEY_free(ec);
-    }
-};
-typedef std::unique_ptr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
-
 /* wrap_rsa returns an |EVP_PKEY| that contains an RSA key where the public
  * part is taken from |public_rsa| and the private operations are forwarded to
  * KeyStore and operate on the key named |key_id|. */
 static EVP_PKEY *wrap_rsa(const char *key_id, const RSA *public_rsa) {
-    Unique_RSA rsa(RSA_new_method(g_keystore_engine->engine()));
+    bssl::UniquePtr<RSA> rsa(RSA_new_method(g_keystore_engine->engine()));
     if (rsa.get() == nullptr) {
         return nullptr;
     }
@@ -298,7 +277,7 @@
         return nullptr;
     }
 
-    Unique_EVP_PKEY result(EVP_PKEY_new());
+    bssl::UniquePtr<EVP_PKEY> result(EVP_PKEY_new());
     if (result.get() == nullptr ||
         !EVP_PKEY_assign_RSA(result.get(), rsa.get())) {
         return nullptr;
@@ -312,7 +291,7 @@
  * part is taken from |public_rsa| and the private operations are forwarded to
  * KeyStore and operate on the key named |key_id|. */
 static EVP_PKEY *wrap_ecdsa(const char *key_id, const EC_KEY *public_ecdsa) {
-    Unique_EC_KEY ec(EC_KEY_new_method(g_keystore_engine->engine()));
+    bssl::UniquePtr<EC_KEY> ec(EC_KEY_new_method(g_keystore_engine->engine()));
     if (ec.get() == nullptr) {
         return nullptr;
     }
@@ -333,7 +312,7 @@
         return nullptr;
     }
 
-    Unique_EVP_PKEY result(EVP_PKEY_new());
+    bssl::UniquePtr<EVP_PKEY> result(EVP_PKEY_new());
     if (result.get() == nullptr ||
         !EVP_PKEY_assign_EC_KEY(result.get(), ec.get())) {
         return nullptr;
@@ -370,7 +349,7 @@
     }
 
     const uint8_t *inp = pubkey;
-    Unique_EVP_PKEY pkey(d2i_PUBKEY(nullptr, &inp, pubkey_len));
+    bssl::UniquePtr<EVP_PKEY> pkey(d2i_PUBKEY(nullptr, &inp, pubkey_len));
     if (pkey.get() == nullptr) {
         ALOGW("Cannot convert pubkey");
         return nullptr;
@@ -379,12 +358,12 @@
     EVP_PKEY *result;
     switch (EVP_PKEY_type(pkey->type)) {
     case EVP_PKEY_RSA: {
-        Unique_RSA public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
+        bssl::UniquePtr<RSA> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
         result = wrap_rsa(key_id, public_rsa.get());
         break;
     }
     case EVP_PKEY_EC: {
-        Unique_EC_KEY public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
+        bssl::UniquePtr<EC_KEY> public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
         result = wrap_ecdsa(key_id, public_ecdsa.get());
         break;
     }
diff --git a/keystore-engine/keystore_backend_binder.cpp b/keystore-engine/keystore_backend_binder.cpp
index 9a7c63e..8b5a584 100644
--- a/keystore-engine/keystore_backend_binder.cpp
+++ b/keystore-engine/keystore_backend_binder.cpp
@@ -211,9 +211,9 @@
     promise = new OperationResultPromise();
     future = promise->get_future();
 
-    binder_result = service->finish(promise, handle, KeymasterArguments(params),
-                                    std::vector<uint8_t>() /* signature */,
-                                    std::vector<uint8_t>() /* entropy */, &error_code);
+    binder_result = service->finish(
+        promise, handle, KeymasterArguments(params), std::vector<uint8_t>() /* input */,
+        std::vector<uint8_t>() /* signature */, std::vector<uint8_t>() /* entropy */, &error_code);
 
     if (!binder_result.isOk()) {
         LOG(ERROR) << AT << "communication error while calling keystore";
diff --git a/keystore-engine/methods.h b/keystore-engine/methods.h
index da54ce2..853bc57 100644
--- a/keystore-engine/methods.h
+++ b/keystore-engine/methods.h
@@ -29,28 +29,6 @@
 extern int dsa_key_handle;
 extern int rsa_key_handle;
 
-struct DSA_Delete {
-    void operator()(DSA* p) const {
-        DSA_free(p);
-    }
-};
-typedef std::unique_ptr<DSA, struct DSA_Delete> Unique_DSA;
-
-struct EC_KEY_Delete {
-    void operator()(EC_KEY* p) const {
-        EC_KEY_free(p);
-    }
-};
-typedef std::unique_ptr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
-
-struct RSA_Delete {
-    void operator()(RSA* p) const {
-        RSA_free(p);
-    }
-};
-typedef std::unique_ptr<RSA, struct RSA_Delete> Unique_RSA;
-
-
 /* Keyhandles for ENGINE metadata */
 int keyhandle_new(void*, void*, CRYPTO_EX_DATA* ad, int idx, long, void*);
 void keyhandle_free(void *, void *ptr, CRYPTO_EX_DATA*, int, long, void*);
diff --git a/keystore/Android.bp b/keystore/Android.bp
index 356ac1b..6145047 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -29,7 +29,6 @@
     defaults: ["keystore_defaults"],
 
     srcs: [
-        ":IKeyAttestationApplicationIdProvider.aidl",
         "KeyStore.cpp",
         "auth_token_table.cpp",
         "blob.cpp",
@@ -41,7 +40,6 @@
         "keyblob_utils.cpp",
         "keymaster_enforcement.cpp",
         "keymaster_worker.cpp",
-        "keystore_attestation_id.cpp",
         "keystore_main.cpp",
         "keystore_utils.cpp",
         "legacy_keymaster_device_wrapper.cpp",
@@ -55,18 +53,18 @@
         "android.hardware.confirmationui@1.0",
         "android.hardware.keymaster@3.0",
         "android.hardware.keymaster@4.0",
-        "android.system.wifi.keystore@1.0",
+        "android.hardware.keymaster@4.1",
         "libbase",
         "libbinder",
         "libcrypto",
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libkeymaster4support",
+        "libkeymaster4_1support",
         "libkeymaster_messages",
         "libkeymaster_portable",
+        "libkeystore-attestation-application-id",
         "libkeystore_aidl",
         "libkeystore_binder",
         "libkeystore_parcelables",
@@ -76,7 +74,6 @@
         "libservices",
         "libsoftkeymasterdevice",
         "libutils",
-        "libwifikeystorehal",
     ],
     init_rc: ["keystore.rc"],
     aidl: {
@@ -110,7 +107,6 @@
         "libcrypto",
         "libcutils",
         "libhidlbase",
-        "libhwbinder",
         "libkeystore_aidl", // for IKeyStoreService.asInterface()
         "libkeystore_binder",
         "libkeystore_parcelables",
@@ -135,7 +131,6 @@
         "libchrome",
         "libutils",
         "libhidlbase",
-        "libhwbinder",
         "libkeymaster4support",
         "libkeystore_aidl",
         "libkeystore_binder",
@@ -150,31 +145,30 @@
     defaults: ["keystore_defaults"],
     export_include_dirs: ["include"],
     srcs: [
-        "KeyAttestationApplicationId.cpp",
-        "KeyAttestationPackageInfo.cpp",
         "KeymasterArguments.cpp",
         "keystore_aidl_hidl_marshalling_utils.cpp",
         "KeystoreResponse.cpp",
         "OperationResult.cpp",
-        "Signature.cpp",
     ],
     shared_libs: [
         "android.hardware.keymaster@4.0",
+        "android.hardware.keymaster@4.1",
         "libbinder",
         "libhardware",
         "libhidlbase",
-        "libhwbinder",
         "libkeymaster4support",
+        "libkeymaster4_1support",
         "liblog",
         "libprotobuf-cpp-lite",
         "libutils",
+        "libkeystore-attestation-application-id",
     ],
     export_shared_lib_headers: [
         "android.hardware.keymaster@4.0",
+        "android.hardware.keymaster@4.1",
         "libbinder",
         "libhidlbase",
-        "libhwbinder",
-        "libkeymaster4support",
+        "libkeymaster4_1support",
     ],
 }
 // Library for keystore clients
@@ -192,7 +186,6 @@
         "android.hardware.keymaster@4.0",
         "libbinder",
         "libhidlbase",
-        "libhwbinder",
         "libkeymaster4support",
         "libkeystore_aidl",
         "libkeystore_parcelables",
@@ -214,12 +207,36 @@
         "android.hardware.keymaster@4.0",
         "libbinder",
         "libhidlbase",
-        "libhwbinder",
         "libkeystore_aidl",
         "libkeystore_parcelables",
     ],
 }
 
+// Library used by both keystore and credstore for generating the ASN.1 stored
+// in Tag::ATTESTATION_APPLICATION_ID
+cc_library_shared {
+    name: "libkeystore-attestation-application-id",
+    defaults: ["keystore_defaults"],
+
+    srcs: [
+        ":IKeyAttestationApplicationIdProvider.aidl",
+        "keystore_attestation_id.cpp",
+        "KeyAttestationApplicationId.cpp",
+        "KeyAttestationPackageInfo.cpp",
+        "Signature.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+        "libcrypto",
+    ],
+
+    export_include_dirs: ["include"],
+}
+
 // Library for keystore clients using the WiFi HIDL interface
 cc_library_shared {
     name: "libkeystore-wifi-hidl",
@@ -230,7 +247,6 @@
         "android.system.wifi.keystore@1.0",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -246,13 +262,8 @@
     defaults: ["keystore_defaults"],
 
     srcs: [
-        ":IKeyAttestationApplicationIdProvider.aidl",
         "auth_token_table.cpp",
         "blob.cpp",
-        "keystore_attestation_id.cpp",
-        "KeyAttestationApplicationId.cpp",
-        "KeyAttestationPackageInfo.cpp",
-        "Signature.cpp",
     ],
     cflags: [ "-O0", ],
     static_libs: ["libgtest_main"],
@@ -261,8 +272,8 @@
         "libbinder",
         "libcrypto",
         "libhidlbase",
-        "libhwbinder",
         "libkeymaster4support",
+        "libkeystore-attestation-application-id",
         "libutils",
         "libkeystore_aidl",
         "libkeystore_parcelables",
@@ -270,7 +281,6 @@
     export_shared_lib_headers: [
         "android.hardware.keymaster@4.0",
         "libhidlbase",
-        "libhwbinder",
         "libkeymaster4support",
     ],
 
@@ -308,8 +318,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libkeystore_parcelables",
         "liblog",
         "libselinux",
diff --git a/keystore/KeyStore.cpp b/keystore/KeyStore.cpp
index d4219bd..7545397 100644
--- a/keystore/KeyStore.cpp
+++ b/keystore/KeyStore.cpp
@@ -402,11 +402,6 @@
     return updated;
 }
 
-struct BIO_Delete {
-    void operator()(BIO* p) const { BIO_free(p); }
-};
-typedef std::unique_ptr<BIO, BIO_Delete> Unique_BIO;
-
 void KeyStore::readMetaData() {
     int in = TEMP_FAILURE_RETRY(open(kMetaDataFile, O_RDONLY));
     if (in < 0) {
diff --git a/keystore/KeyStore.h b/keystore/KeyStore.h
index a7fbab4..0027ec8 100644
--- a/keystore/KeyStore.h
+++ b/keystore/KeyStore.h
@@ -18,7 +18,7 @@
 #define KEYSTORE_KEYSTORE_H_
 
 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
 #include <utils/Vector.h>
 
 #include <keystore/keymaster_types.h>
diff --git a/keystore/OperationResult.cpp b/keystore/OperationResult.cpp
index 3ff8bc3..dec4d40 100644
--- a/keystore/OperationResult.cpp
+++ b/keystore/OperationResult.cpp
@@ -29,8 +29,8 @@
 namespace security {
 namespace keymaster {
 
-using keystore::keymaster::ErrorCode;
 using ::android::status_t;
+using ::keystore::ErrorCode;
 
 OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
 
diff --git a/keystore/auth_token_table.cpp b/keystore/auth_token_table.cpp
index 6bffa7c..5e6d572 100644
--- a/keystore/auth_token_table.cpp
+++ b/keystore/auth_token_table.cpp
@@ -173,6 +173,60 @@
     return {OK, newest_match->token()};
 }
 
+std::tuple<AuthTokenTable::Error, HardwareAuthToken>
+AuthTokenTable::FindAuthorizationForCredstore(uint64_t challenge, uint64_t secureUserId,
+                                              int64_t authTokenMaxAgeMillis) {
+    std::vector<uint64_t> sids = {secureUserId};
+    HardwareAuthenticatorType auth_type = HardwareAuthenticatorType::ANY;
+
+    time_t now = clock_function_();
+
+    // challenge-based - the authToken has to contain the given challenge.
+    if (challenge != 0) {
+        auto matching_op = find_if(
+            entries_, [&](Entry& e) { return e.token().challenge == challenge && !e.completed(); });
+        if (matching_op == entries_.end()) {
+            return {AUTH_TOKEN_NOT_FOUND, {}};
+        }
+
+        if (!matching_op->SatisfiesAuth(sids, auth_type)) {
+            return {AUTH_TOKEN_WRONG_SID, {}};
+        }
+
+        if (authTokenMaxAgeMillis > 0) {
+            if (static_cast<int64_t>(matching_op->time_received()) + authTokenMaxAgeMillis <
+                static_cast<int64_t>(now)) {
+                return {AUTH_TOKEN_EXPIRED, {}};
+            }
+        }
+
+        return {OK, matching_op->token()};
+    }
+
+    // Otherwise, no challenge - any authToken younger than the specified maximum
+    // age will do.
+    Entry* newest_match = nullptr;
+    for (auto& entry : entries_) {
+        if (entry.SatisfiesAuth(sids, auth_type) && entry.is_newer_than(newest_match)) {
+            newest_match = &entry;
+        }
+    }
+
+    if (newest_match == nullptr) {
+        return {AUTH_TOKEN_NOT_FOUND, {}};
+    }
+
+    if (authTokenMaxAgeMillis > 0) {
+        if (static_cast<int64_t>(newest_match->time_received()) + authTokenMaxAgeMillis <
+            static_cast<int64_t>(now)) {
+            return {AUTH_TOKEN_EXPIRED, {}};
+        }
+    }
+
+    newest_match->UpdateLastUse(now);
+    return {OK, newest_match->token()};
+}
+
 void AuthTokenTable::ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids) {
     assert(sids);
     for (auto& param : key_info)
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index 7b48a6c..787b9b1 100644
--- a/keystore/auth_token_table.h
+++ b/keystore/auth_token_table.h
@@ -25,8 +25,6 @@
 
 namespace keystore {
 
-using keymaster::HardwareAuthToken;
-
 namespace test {
 class AuthTokenTableTest;
 }  // namespace test
@@ -76,6 +74,10 @@
     std::tuple<Error, HardwareAuthToken> FindAuthorization(const AuthorizationSet& key_info,
                                                            KeyPurpose purpose, uint64_t op_handle);
 
+    std::tuple<Error, HardwareAuthToken>
+    FindAuthorizationForCredstore(uint64_t challenge, uint64_t secureUserId,
+                                  int64_t authTokenMaxAgeMillis);
+
     /**
      * Mark operation completed.  This allows tokens associated with the specified operation to be
      * superseded by new tokens.
diff --git a/keystore/binder/android/security/keystore/IKeystoreService.aidl b/keystore/binder/android/security/keystore/IKeystoreService.aidl
index 348964f..fcea115 100644
--- a/keystore/binder/android/security/keystore/IKeystoreService.aidl
+++ b/keystore/binder/android/security/keystore/IKeystoreService.aidl
@@ -29,21 +29,29 @@
  * @hide
  */
 interface IKeystoreService {
+    @UnsupportedAppUsage
     int getState(int userId);
+    @UnsupportedAppUsage
     byte[] get(String name, int uid);
+    @UnsupportedAppUsage
     int insert(String name, in byte[] item, int uid, int flags);
+    @UnsupportedAppUsage
     int del(String name, int uid);
+    @UnsupportedAppUsage
     int exist(String name, int uid);
+    @UnsupportedAppUsage
     String[] list(String namePrefix, int uid);
-    int reset();
     int onUserPasswordChanged(int userId, String newPassword);
     int lock(int userId);
     int unlock(int userId, String userPassword);
     int isEmpty(int userId);
     String grant(String name, int granteeUid);
+    @UnsupportedAppUsage
     int ungrant(String name, int granteeUid);
     long getmtime(String name, int uid);
+    @UnsupportedAppUsage
     int is_hardware_backed(String string);
+    @UnsupportedAppUsage
     int clear_uid(long uid);
 
     int addRngEntropy(IKeystoreResponseCallback cb, in byte[] data, int flags);
@@ -58,7 +66,7 @@
     int begin(in IKeystoreOperationResultCallback cb, IBinder appToken, String alias, int purpose, boolean pruneable,
         in KeymasterArguments params, in byte[] entropy, int uid);
     int update(in IKeystoreOperationResultCallback cb, IBinder token, in KeymasterArguments params, in byte[] input);
-    int finish(in IKeystoreOperationResultCallback cb, IBinder token, in KeymasterArguments params, in byte[] signature,
+    int finish(in IKeystoreOperationResultCallback cb, IBinder token, in KeymasterArguments params, in byte[] input, in byte[] signature,
         in byte[] entropy);
     int abort(in IKeystoreResponseCallback cb, IBinder token);
     int addAuthToken(in byte[] authToken);
@@ -76,4 +84,7 @@
     boolean isConfirmationPromptSupported();
     int onKeyguardVisibilityChanged(in boolean isShowing, in int userId);
     int listUidsOfAuthBoundKeys(out @utf8InCpp List<String> uids);
+
+    // Called by credstore (and only credstore).
+    byte[] getAuthTokenForCredstore(in long challenge, in long secureUserId, in int authTokenMaxAgeMillis);
 }
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 497f304..ffdb454 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -36,21 +36,12 @@
 #include <string>
 
 #include <android-base/logging.h>
+#include <android-base/unique_fd.h>
 
 namespace {
 
 constexpr size_t kGcmIvSizeBytes = 96 / 8;
 
-template <typename T, void (*FreeFunc)(T*)> struct OpenSslObjectDeleter {
-    void operator()(T* p) { FreeFunc(p); }
-};
-
-#define DEFINE_OPENSSL_OBJECT_POINTER(name)                                                        \
-    typedef OpenSslObjectDeleter<name, name##_free> name##_Delete;                                 \
-    typedef std::unique_ptr<name, name##_Delete> name##_Ptr;
-
-DEFINE_OPENSSL_OBJECT_POINTER(EVP_CIPHER_CTX);
-
 #if defined(__clang__)
 #define OPTNONE __attribute__((optnone))
 #elif defined(__GNUC__)
@@ -91,7 +82,7 @@
     // There can be 128-bit and 256-bit keys
     const EVP_CIPHER* cipher = getAesCipherForKey(key);
 
-    EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
+    bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
 
     EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
     EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
@@ -128,7 +119,7 @@
     // There can be 128-bit and 256-bit keys
     const EVP_CIPHER* cipher = getAesCipherForKey(key);
 
-    EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
+    bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
 
     EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
     EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
@@ -142,12 +133,12 @@
     EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
     out_pos += out_len;
     if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
-        ALOGD("Failed to decrypt blob; ciphertext or tag is likely corrupted");
+        ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted");
         return ResponseCode::VALUE_CORRUPTED;
     }
     out_pos += out_len;
     if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
-        ALOGD("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
+        ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
               out_pos - out_tmp.get());
         return ResponseCode::VALUE_CORRUPTED;
     }
@@ -341,22 +332,35 @@
 
     size_t fileLength = offsetof(blobv3, value) + dataLength + rawBlob->info;
 
-    int out =
-        TEMP_FAILURE_RETRY(open(filename.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
-    if (out < 0) {
-        ALOGW("could not open file: %s: %s", filename.c_str(), strerror(errno));
+    char tmpFileName[] = ".tmpXXXXXX";
+    {
+        android::base::unique_fd out(TEMP_FAILURE_RETRY(mkstemp(tmpFileName)));
+        if (out < 0) {
+            LOG(ERROR) << "could not open temp file: " << tmpFileName
+                       << " for writing blob file: " << filename.c_str()
+                       << " because: " << strerror(errno);
+            return ResponseCode::SYSTEM_ERROR;
+        }
+
+        const size_t writtenBytes =
+            writeFully(out, reinterpret_cast<uint8_t*>(rawBlob), fileLength);
+
+        if (writtenBytes != fileLength) {
+            LOG(ERROR) << "blob not fully written " << writtenBytes << " != " << fileLength;
+            unlink(tmpFileName);
+            return ResponseCode::SYSTEM_ERROR;
+        }
+    }
+
+    if (rename(tmpFileName, filename.c_str()) == -1) {
+        LOG(ERROR) << "could not rename blob file to " << filename
+                   << " because: " << strerror(errno);
+        unlink(tmpFileName);
         return ResponseCode::SYSTEM_ERROR;
     }
 
-    const size_t writtenBytes = writeFully(out, reinterpret_cast<uint8_t*>(rawBlob), fileLength);
-    if (close(out) != 0) {
-        return ResponseCode::SYSTEM_ERROR;
-    }
-    if (writtenBytes != fileLength) {
-        ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
-        unlink(filename.c_str());
-        return ResponseCode::SYSTEM_ERROR;
-    }
+    fsyncDirectory(getContainingDirectory(filename));
+
     return ResponseCode::NO_ERROR;
 }
 
@@ -401,6 +405,7 @@
     }
 
     if (fileLength == 0) {
+        LOG(ERROR) << __func__ << " VALUE_CORRUPTED file length == 0";
         return ResponseCode::VALUE_CORRUPTED;
     }
 
@@ -412,7 +417,10 @@
         if (state == STATE_UNINITIALIZED) return ResponseCode::UNINITIALIZED;
     }
 
-    if (fileLength < offsetof(blobv3, value)) return ResponseCode::VALUE_CORRUPTED;
+    if (fileLength < offsetof(blobv3, value)) {
+        LOG(ERROR) << __func__ << " VALUE_CORRUPTED blob file too short: " << fileLength;
+        return ResponseCode::VALUE_CORRUPTED;
+    }
 
     if (rawBlob->version == 3) {
         const ssize_t encryptedLength = ntohl(rawBlob->length);
@@ -428,6 +436,8 @@
                     (rc == ResponseCode::VALUE_CORRUPTED)) {
                     return ResponseCode::KEY_PERMANENTLY_INVALIDATED;
                 }
+                LOG(ERROR) << __func__ << " AES_gcm_decrypt returned: " << uint32_t(rc);
+
                 return rc;
             }
         }
@@ -435,10 +445,16 @@
         blobv2& v2blob = reinterpret_cast<blobv2&>(*rawBlob);
         const size_t headerLength = offsetof(blobv2, encrypted);
         const ssize_t encryptedLength = fileLength - headerLength - v2blob.info;
-        if (encryptedLength < 0) return ResponseCode::VALUE_CORRUPTED;
+        if (encryptedLength < 0) {
+            LOG(ERROR) << __func__ << " VALUE_CORRUPTED v2blob file too short";
+            return ResponseCode::VALUE_CORRUPTED;
+        }
 
         if (rawBlobIsEncrypted(*rawBlob)) {
             if (encryptedLength % AES_BLOCK_SIZE != 0) {
+                LOG(ERROR) << __func__
+                           << " VALUE_CORRUPTED encrypted length is not a multiple"
+                              " of the AES block size";
                 return ResponseCode::VALUE_CORRUPTED;
             }
 
@@ -452,6 +468,7 @@
             ssize_t digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
             MD5(v2blob.digested, digestedLength, computedDigest);
             if (memcmp(v2blob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
+                LOG(ERROR) << __func__ << " v2blob MD5 digest mismatch";
                 return ResponseCode::VALUE_CORRUPTED;
             }
         }
@@ -462,6 +479,7 @@
     if (rawBlob->length < 0 || rawBlob->length > maxValueLength ||
         rawBlob->length + rawBlob->info + AES_BLOCK_SIZE >
             static_cast<ssize_t>(sizeof(rawBlob->value))) {
+        LOG(ERROR) << __func__ << " raw blob length is out of bounds";
         return ResponseCode::VALUE_CORRUPTED;
     }
 
diff --git a/keystore/confirmation_manager.cpp b/keystore/confirmation_manager.cpp
index 3396359..76df1cc 100644
--- a/keystore/confirmation_manager.cpp
+++ b/keystore/confirmation_manager.cpp
@@ -116,12 +116,22 @@
     }
     mMutex.unlock();
 
-    finalizeTransaction(ConfirmationResponseCode::Aborted, {}, true);
+    cancelPrompt();
 
     *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
     return Status::ok();
 }
 
+void ConfirmationManager::cancelPrompt() {
+    mMutex.lock();
+    mRateLimiting.cancelPrompt();
+    sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
+    mMutex.unlock();
+    if (confirmationUI != nullptr) {
+        confirmationUI->abort();
+    }
+}
+
 // Called by keystore main thread.
 Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
     sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
@@ -136,13 +146,7 @@
 }
 
 void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseCode,
-                                              hidl_vec<uint8_t> dataThatWasConfirmed,
-                                              bool callAbortOnHal) {
-    // Note that confirmationUI->abort() may make the remote HAL process do an IPC call back
-    // into our process resulting in confirmationResultCallback() to be called... this in turn
-    // calls finalizeTransaction(). So we have to be careful a) not holding any locks;
-    // and b) ensure state has been cleared; before doing this...
-
+                                              hidl_vec<uint8_t> dataThatWasConfirmed) {
     mMutex.lock();
     mRateLimiting.processResult(responseCode);
     sp<IBinder> listener = mCurrentListener;
@@ -150,18 +154,12 @@
         mCurrentListener->unlinkToDeath(mDeathRecipient);
         mCurrentListener = nullptr;
     }
-    sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
     if (mCurrentConfirmationUI != nullptr) {
         mCurrentConfirmationUI->unlinkToDeath(this);
         mCurrentConfirmationUI = nullptr;
     }
     mMutex.unlock();
 
-    // Tell the HAL to shut down the confirmation dialog, if requested.
-    if (confirmationUI != nullptr && callAbortOnHal) {
-        confirmationUI->abort();
-    }
-
     // Deliver result to the application that started the operation.
     if (listener != nullptr) {
         sp<BpConfirmationPromptCallback> obj = new BpConfirmationPromptCallback(listener);
@@ -178,7 +176,7 @@
 Return<void> ConfirmationManager::result(ConfirmationResponseCode responseCode,
                                          const hidl_vec<uint8_t>& dataThatWasConfirmed,
                                          const hidl_vec<uint8_t>& confirmationToken) {
-    finalizeTransaction(responseCode, dataThatWasConfirmed, false);
+    finalizeTransaction(responseCode, dataThatWasConfirmed);
     lock_guard<mutex> lock(mMutex);
     mLatestConfirmationToken = confirmationToken;
     return Return<void>();
@@ -201,7 +199,7 @@
         mCurrentListener = nullptr;
         mMutex.unlock();
         ALOGW("The process which requested the confirmation dialog died.\n");
-        finalizeTransaction(ConfirmationResponseCode::SystemError, {}, true);
+        cancelPrompt();
     } else {
         mMutex.unlock();
     }
@@ -210,7 +208,7 @@
 void ConfirmationManager::serviceDied(uint64_t /* cookie */,
                                       const wp<android::hidl::base::V1_0::IBase>& /* who */) {
     ALOGW("The ConfirmationUI HAL died.\n");
-    finalizeTransaction(ConfirmationResponseCode::SystemError, {}, false);
+    finalizeTransaction(ConfirmationResponseCode::SystemError, {});
 }
 
 }  // namespace keystore
diff --git a/keystore/confirmation_manager.h b/keystore/confirmation_manager.h
index 46b623c..7f0a11d 100644
--- a/keystore/confirmation_manager.h
+++ b/keystore/confirmation_manager.h
@@ -84,8 +84,12 @@
   private:
     friend class ConfirmationResultCallback;
 
+    // Set rate limiting to not decrement on next abort and aborts
+    // confirmationui.
+    void cancelPrompt();
+
     void finalizeTransaction(ConfirmationResponseCode responseCode,
-                             hidl_vec<uint8_t> dataThatWasConfirmed, bool callAbortOnHal);
+                             hidl_vec<uint8_t> dataThatWasConfirmed);
 
     // This mutex protects all data below it.
     std::mutex mMutex;
diff --git a/keystore/confirmationui_rate_limiting.h b/keystore/confirmationui_rate_limiting.h
index 12c20fa..658bf41 100644
--- a/keystore/confirmationui_rate_limiting.h
+++ b/keystore/confirmationui_rate_limiting.h
@@ -29,8 +29,8 @@
 
 using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
 
-using std::chrono::time_point;
 using std::chrono::duration;
+using std::chrono::time_point;
 
 template <typename Clock = std::chrono::steady_clock> class RateLimiting {
   private:
@@ -96,7 +96,17 @@
         return false;
     }
 
+    // The app is penalized for cancelling a request. Request are rolled back only if
+    // the prompt was cancelled by the system: e.g. a system error or asynchronous event.
+    // When the user cancels the prompt, it is subject to rate limiting.
+    static constexpr const uint_t kInvalidRequester = -1;
+
+    void cancelPrompt() { latest_requester_ = kInvalidRequester; }
+
     void processResult(ConfirmationResponseCode rc) {
+        if (latest_requester_ == kInvalidRequester) {
+            return;
+        }
         switch (rc) {
         case ConfirmationResponseCode::OK:
             // reset the counter slot
diff --git a/keystore/include/keystore/keymaster_types.h b/keystore/include/keystore/keymaster_types.h
index f3c6907..8da9682 100644
--- a/keystore/include/keystore/keymaster_types.h
+++ b/keystore/include/keystore/keymaster_types.h
@@ -16,11 +16,11 @@
 #define SECURITY_KEYSTORE_INCLUDE_KEYSTORE_KEYMASTER_TYPES_H_
 
 #include <android/hardware/keymaster/3.0/types.h>
-#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
-#include <android/hardware/keymaster/4.0/types.h>
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.1/types.h>
 
-#include <keymasterV4_0/authorization_set.h>
-#include <keymasterV4_0/keymaster_tags.h>
+#include <keymasterV4_1/authorization_set.h>
+#include <keymasterV4_1/keymaster_tags.h>
 
 /**
  * This header lifts the types from the current Keymaster version into the keystore namespace.
@@ -29,7 +29,7 @@
 namespace keystore {
 
 // Changing this namespace alias will change the keymaster version.
-namespace keymaster = ::android::hardware::keymaster::V4_0;
+namespace keymaster = ::android::hardware::keymaster::V4_1;
 
 using android::hardware::hidl_vec;
 using android::hardware::Return;
@@ -40,11 +40,17 @@
 using keymaster::AuthorizationSet;
 using keymaster::AuthorizationSetBuilder;
 
+// It's more convenient to use the V4.0 error and tag types by default.
+using ::android::hardware::keymaster::V4_0::ErrorCode;
+using ::android::hardware::keymaster::V4_0::Tag;
+
+using V4_1_ErrorCode = ::android::hardware::keymaster::V4_1::ErrorCode;
+using V4_1_Tag = ::android::hardware::keymaster::V4_1::Tag;
+
 using keymaster::Algorithm;
 using keymaster::BlockMode;
 using keymaster::Digest;
 using keymaster::EcCurve;
-using keymaster::ErrorCode;
 using keymaster::HardwareAuthenticatorType;
 using keymaster::HardwareAuthToken;
 using keymaster::HmacSharingParameters;
@@ -55,7 +61,6 @@
 using keymaster::OperationHandle;
 using keymaster::PaddingMode;
 using keymaster::SecurityLevel;
-using keymaster::Tag;
 using keymaster::TagType;
 using keymaster::VerificationToken;
 
diff --git a/keystore/keystore_attestation_id.h b/keystore/include/keystore/keystore_attestation_id.h
similarity index 98%
rename from keystore/keystore_attestation_id.h
rename to keystore/include/keystore/keystore_attestation_id.h
index 63015ee..238f4b1 100644
--- a/keystore/keystore_attestation_id.h
+++ b/keystore/include/keystore/keystore_attestation_id.h
@@ -51,7 +51,7 @@
 
     ::android::status_t status() const { return _status; }
 
-    const T& value() const & { return _value; }
+    const T& value() const& { return _value; }
     T& value() & { return _value; }
     T&& value() && { return std::move(_value); }
 
diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h
index d6a4807..cb27268 100644
--- a/keystore/include/keystore/keystore_client.h
+++ b/keystore/include/keystore/keystore_client.h
@@ -15,6 +15,8 @@
 #ifndef KEYSTORE_KEYSTORE_CLIENT_H_
 #define KEYSTORE_KEYSTORE_CLIENT_H_
 
+#include <memory>
+#include <optional>
 #include <set>
 #include <string>
 #include <vector>
@@ -158,7 +160,7 @@
     // keymaster_error_t on failure.
     virtual KeyStoreNativeReturnCode
     finishOperation(uint64_t handle, const keystore::AuthorizationSet& input_parameters,
-                    const std::string& signature_to_verify,
+                    const std::string& input_data, const std::string& signature_to_verify,
                     keystore::AuthorizationSet* output_parameters, std::string* output_data) = 0;
 
     // Aborts the operation associated with |handle|. Returns KM_ERROR_OK on
@@ -173,6 +175,13 @@
     // caller's key store starting with |prefix|. Returns true on success.
     virtual bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) = 0;
 
+    // Provides a |key_name_list| containing all existing key names in the
+    // caller's key store starting with |prefix|. Returns true on success.
+    virtual bool listKeysOfUid(const std::string& prefix, int uid,
+                               std::vector<std::string>* key_name_list) = 0;
+
+    virtual std::optional<std::vector<uint8_t>> getKey(const std::string& alias, int uid) = 0;
+
   private:
     DISALLOW_COPY_AND_ASSIGN(KeystoreClient);
 };
diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h
index 0bcef98..ed8ac44 100644
--- a/keystore/include/keystore/keystore_client_impl.h
+++ b/keystore/include/keystore/keystore_client_impl.h
@@ -19,6 +19,7 @@
 
 #include <future>
 #include <map>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -75,12 +76,16 @@
                                              std::string* output_data) override;
     KeyStoreNativeReturnCode finishOperation(uint64_t handle,
                                              const keystore::AuthorizationSet& input_parameters,
+                                             const std::string& input_data,
                                              const std::string& signature_to_verify,
                                              keystore::AuthorizationSet* output_parameters,
                                              std::string* output_data) override;
     KeyStoreNativeReturnCode abortOperation(uint64_t handle) override;
     bool doesKeyExist(const std::string& key_name) override;
     bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) override;
+    bool listKeysOfUid(const std::string& prefix, int uid,
+                       std::vector<std::string>* key_name_list) override;
+    std::optional<std::vector<uint8_t>> getKey(const std::string& alias, int uid) override;
 
   private:
     // Returns an available virtual operation handle.
diff --git a/keystore/include/keystore/keystore_return_types.h b/keystore/include/keystore/keystore_return_types.h
index f8cf1cc..2762f8d 100644
--- a/keystore/include/keystore/keystore_return_types.h
+++ b/keystore/include/keystore/keystore_return_types.h
@@ -23,8 +23,6 @@
 
 namespace keystore {
 
-using keymaster::ErrorCode;
-
 class KeyStoreServiceReturnCode;
 class KeyStoreNativeReturnCode;
 
diff --git a/keystore/key_proto_handler.cpp b/keystore/key_proto_handler.cpp
index a106213..f8400af 100644
--- a/keystore/key_proto_handler.cpp
+++ b/keystore/key_proto_handler.cpp
@@ -19,7 +19,7 @@
 
 #include <android/os/DropBoxManager.h>
 #include <google/protobuf/message_lite.h>
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
 #include <keystore/keymaster_types.h>
 #include <utils/String16.h>
 #include <utils/StrongPointer.h>
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index b6b7295..75fcbde 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -38,12 +38,13 @@
 
 #include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
 #include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
+#include <keymasterV4_0/keymaster_utils.h>
 
 #include "defaults.h"
 #include "key_proto_handler.h"
-#include "keystore_attestation_id.h"
 #include "keystore_keymaster_enforcement.h"
 #include "keystore_utils.h"
+#include <keystore/keystore_attestation_id.h>
 #include <keystore/keystore_hidl_support.h>
 #include <keystore/keystore_return_types.h>
 
@@ -70,11 +71,6 @@
 constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
 const char* kTimestampFilePath = "timestamp";
 
-struct BIGNUM_Delete {
-    void operator()(BIGNUM* p) const { BN_free(p); }
-};
-typedef std::unique_ptr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
-
 bool containsTag(const hidl_vec<KeyParameter>& params, Tag tag) {
     return params.end() !=
            std::find_if(params.begin(), params.end(),
@@ -82,7 +78,6 @@
 }
 
 #define AIDL_RETURN(rc) (*_aidl_return = KeyStoreServiceReturnCode(rc).getErrorCode(), Status::ok())
-#define KEYSTORE_SERVICE_LOCK std::lock_guard<std::mutex> keystore_lock(keystoreServiceMutex_)
 
 std::pair<KeyStoreServiceReturnCode, bool> hadFactoryResetSinceIdRotation() {
     struct stat sbuf;
@@ -123,7 +118,8 @@
     auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid);
     if (!asn1_attestation_id_result.isOk()) {
         ALOGE("failed to gather attestation_id");
-        return ErrorCode::ATTESTATION_APPLICATION_ID_MISSING;
+        // Couldn't get attestation ID; just use an empty one rather than failing.
+        asn1_attestation_id_result = std::vector<uint8_t>();
     }
     std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result;
 
@@ -146,7 +142,6 @@
 }  // anonymous namespace
 
 Status KeyStoreService::getState(int32_t userId, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkBinderPermission(P_GET_STATE)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
         return Status::ok();
@@ -156,7 +151,6 @@
 }
 
 Status KeyStoreService::get(const String16& name, int32_t uid, ::std::vector<uint8_t>* item) {
-    KEYSTORE_SERVICE_LOCK;
     uid_t targetUid = getEffectiveUid(uid);
     if (!checkBinderPermission(P_GET, targetUid)) {
         // see keystore/keystore.h
@@ -186,7 +180,6 @@
 
 Status KeyStoreService::insert(const String16& name, const ::std::vector<uint8_t>& item,
                                int targetUid, int32_t flags, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     targetUid = getEffectiveUid(targetUid);
     KeyStoreServiceReturnCode result =
         checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
@@ -212,7 +205,6 @@
 }
 
 Status KeyStoreService::del(const String16& name, int targetUid, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_DELETE, targetUid)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
@@ -233,7 +225,6 @@
 }
 
 Status KeyStoreService::exist(const String16& name, int targetUid, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_EXIST, targetUid)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
@@ -249,7 +240,6 @@
 
 Status KeyStoreService::list(const String16& prefix, int32_t targetUid,
                              ::std::vector<::android::String16>* matches) {
-    KEYSTORE_SERVICE_LOCK;
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_LIST, targetUid)) {
         return Status::fromServiceSpecificError(
@@ -288,7 +278,6 @@
  */
 Status KeyStoreService::listUidsOfAuthBoundKeys(std::vector<std::string>* uidsOut,
                                                 int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     const int32_t callingUid = IPCThreadState::self()->getCallingUid();
     const int32_t userId = get_user_id(callingUid);
     const int32_t appId = get_app_id(callingUid);
@@ -351,22 +340,8 @@
     return Status::ok();
 }
 
-Status KeyStoreService::reset(int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
-    if (!checkBinderPermission(P_RESET)) {
-        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
-        return Status::ok();
-    }
-
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    mKeyStore->resetUser(get_user_id(callingUid), false);
-    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
-    return Status::ok();
-}
-
 Status KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password,
                                               int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkBinderPermission(P_PASSWORD)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
         return Status::ok();
@@ -404,7 +379,6 @@
 }
 
 Status KeyStoreService::onUserAdded(int32_t userId, int32_t parentId, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkBinderPermission(P_USER_CHANGED)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
         return Status::ok();
@@ -430,7 +404,6 @@
 }
 
 Status KeyStoreService::onUserRemoved(int32_t userId, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkBinderPermission(P_USER_CHANGED)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
         return Status::ok();
@@ -442,7 +415,6 @@
 }
 
 Status KeyStoreService::lock(int32_t userId, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkBinderPermission(P_LOCK)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
         return Status::ok();
@@ -462,7 +434,6 @@
 }
 
 Status KeyStoreService::unlock(int32_t userId, const String16& pw, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkBinderPermission(P_UNLOCK)) {
         *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
         return Status::ok();
@@ -493,7 +464,6 @@
 }
 
 Status KeyStoreService::isEmpty(int32_t userId, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkBinderPermission(P_IS_EMPTY)) {
         *aidl_return = static_cast<int32_t>(false);
         return Status::ok();
@@ -505,7 +475,6 @@
 
 Status KeyStoreService::grant(const String16& name, int32_t granteeUid,
                               ::android::String16* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     auto result =
         checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
@@ -526,7 +495,6 @@
 }
 
 Status KeyStoreService::ungrant(const String16& name, int32_t granteeUid, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     KeyStoreServiceReturnCode result =
         checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
@@ -547,7 +515,6 @@
 }
 
 Status KeyStoreService::getmtime(const String16& name, int32_t uid, int64_t* time) {
-    KEYSTORE_SERVICE_LOCK;
     uid_t targetUid = getEffectiveUid(uid);
     if (!checkBinderPermission(P_GET, targetUid)) {
         ALOGW("permission denied for %d: getmtime", targetUid);
@@ -586,13 +553,11 @@
 }
 
 Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     *aidl_return = static_cast<int32_t>(mKeyStore->isHardwareBacked(keyType) ? 1 : 0);
     return Status::ok();
 }
 
 Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     uid_t targetUid = getEffectiveUid(targetUid64);
     if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
         return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
@@ -632,7 +597,6 @@
 Status KeyStoreService::addRngEntropy(
     const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb,
     const ::std::vector<uint8_t>& entropy, int32_t flags, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags));
     if (!device) {
         return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
@@ -649,9 +613,6 @@
     const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
     const String16& name, const KeymasterArguments& params, const ::std::vector<uint8_t>& entropy,
     int uid, int flags, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
-    // TODO(jbires): remove this getCallingUid call upon implementation of b/25646100
-    uid_t originalUid = IPCThreadState::self()->getCallingUid();
     uid = getEffectiveUid(uid);
     auto logOnScopeExit = android::base::make_scope_guard([&] {
         if (__android_log_security()) {
@@ -671,9 +632,7 @@
     }
 
     if (containsTag(params.getParameters(), Tag::INCLUDE_UNIQUE_ID)) {
-        // TODO(jbires): remove uid checking upon implementation of b/25646100
-        if (!checkBinderPermission(P_GEN_UNIQUE_ID) ||
-            originalUid != IPCThreadState::self()->getCallingUid()) {
+        if (!checkBinderPermission(P_GEN_UNIQUE_ID)) {
             return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
         }
     }
@@ -711,7 +670,6 @@
     const String16& name, const ::android::security::keymaster::KeymasterBlob& clientId,
     const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
     int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
 
     uid_t targetUid = getEffectiveUid(uid);
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -758,7 +716,6 @@
     const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
     const String16& name, const KeymasterArguments& params, int32_t format,
     const ::std::vector<uint8_t>& keyData, int uid, int flags, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     uid = getEffectiveUid(uid);
     auto logOnScopeExit = android::base::make_scope_guard([&] {
         if (__android_log_security()) {
@@ -815,7 +772,6 @@
     const ::android::security::keymaster::KeymasterBlob& clientId,
     const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
     int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
 
     uid_t targetUid = getEffectiveUid(uid);
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -851,7 +807,6 @@
                               bool pruneable, const KeymasterArguments& params,
                               const ::std::vector<uint8_t>& entropy, int32_t uid,
                               int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     uid_t targetUid = getEffectiveUid(uid);
     if (!is_granted_to(callingUid, targetUid)) {
@@ -900,7 +855,6 @@
                                const ::android::sp<::android::IBinder>& token,
                                const ::android::security::keymaster::KeymasterArguments& params,
                                const ::std::vector<uint8_t>& input, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkAllowedOperationParams(params.getParameters())) {
         return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
     }
@@ -923,9 +877,9 @@
 Status KeyStoreService::finish(const ::android::sp<IKeystoreOperationResultCallback>& cb,
                                const ::android::sp<::android::IBinder>& token,
                                const ::android::security::keymaster::KeymasterArguments& params,
+                               const ::std::vector<uint8_t>& input,
                                const ::std::vector<uint8_t>& signature,
                                const ::std::vector<uint8_t>& entropy, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (!checkAllowedOperationParams(params.getParameters())) {
         return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
     }
@@ -935,7 +889,7 @@
         return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
     }
 
-    dev->finish(token, params.getParameters(), {}, signature, entropy,
+    dev->finish(token, params.getParameters(), input, signature, entropy,
                 [this, cb, token](OperationResult result_) {
                     mKeyStore->removeOperationDevice(token);
                     cb->onFinished(result_);
@@ -947,7 +901,6 @@
 Status KeyStoreService::abort(const ::android::sp<IKeystoreResponseCallback>& cb,
                               const ::android::sp<::android::IBinder>& token,
                               int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     auto dev = mKeyStore->getOperationDevice(token);
     if (!dev) {
         return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
@@ -963,7 +916,6 @@
 
 Status KeyStoreService::addAuthToken(const ::std::vector<uint8_t>& authTokenAsVector,
                                      int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
 
     // TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to
     // receive a HardwareAuthToken, rather than an opaque byte array.
@@ -991,6 +943,24 @@
     return Status::ok();
 }
 
+Status KeyStoreService::getAuthTokenForCredstore(int64_t challenge, int64_t secureUserId,
+                                                 int32_t authTokenMaxAgeMillis,
+                                                 std::vector<uint8_t>* _aidl_return) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    if (callingUid != AID_CREDSTORE) {
+        return Status::fromServiceSpecificError(static_cast<int32_t>(0));
+    }
+
+    auto [err, authToken] = mKeyStore->getAuthTokenTable().FindAuthorizationForCredstore(
+        challenge, secureUserId, authTokenMaxAgeMillis);
+    std::vector<uint8_t> ret;
+    if (err == AuthTokenTable::OK) {
+        ret = android::hardware::keymaster::V4_0::support::authToken2HidlVec(authToken);
+    }
+    *_aidl_return = ret;
+    return Status::ok();
+}
+
 bool isDeviceIdAttestationRequested(const KeymasterArguments& params) {
     const hardware::hidl_vec<KeyParameter>& paramsVec = params.getParameters();
     for (size_t i = 0; i < paramsVec.size(); ++i) {
@@ -1014,7 +984,6 @@
 Status KeyStoreService::attestKey(
     const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb,
     const String16& name, const KeymasterArguments& params, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
     if (!checkAllowedOperationParams(params.getParameters())) {
         return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
@@ -1074,7 +1043,6 @@
 Status KeyStoreService::attestDeviceIds(
     const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb,
     const KeymasterArguments& params, int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
 
     if (!checkAllowedOperationParams(params.getParameters())) {
@@ -1167,7 +1135,6 @@
 }
 
 Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     // TODO(tuckeris): add permission check.  This should be callable from ClockworkHome only.
     mKeyStore->getAuthTokenTable().onDeviceOffBody();
     *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
@@ -1180,7 +1147,6 @@
     const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& maskingKey,
     const KeymasterArguments& params, int64_t rootSid, int64_t fingerprintSid,
     int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
 
@@ -1230,19 +1196,16 @@
                                                   const ::std::vector<uint8_t>& extraData,
                                                   const String16& locale, int32_t uiOptionsAsFlags,
                                                   int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     return mKeyStore->getConfirmationManager().presentConfirmationPrompt(
         listener, promptText, extraData, locale, uiOptionsAsFlags, aidl_return);
 }
 
 Status KeyStoreService::cancelConfirmationPrompt(const sp<IBinder>& listener,
                                                  int32_t* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     return mKeyStore->getConfirmationManager().cancelConfirmationPrompt(listener, aidl_return);
 }
 
 Status KeyStoreService::isConfirmationPromptSupported(bool* aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     return mKeyStore->getConfirmationManager().isConfirmationPromptSupported(aidl_return);
 }
 
@@ -1360,7 +1323,6 @@
 
 Status KeyStoreService::onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
                                                     int32_t* _aidl_return) {
-    KEYSTORE_SERVICE_LOCK;
     if (isShowing) {
         if (!checkBinderPermission(P_LOCK, UID_SELF)) {
             LOG(WARNING) << "onKeyguardVisibilityChanged called with isShowing == true but "
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
index 96d0c07..8c1d508 100644
--- a/keystore/key_store_service.h
+++ b/keystore/key_store_service.h
@@ -66,7 +66,6 @@
     ::android::binder::Status listUidsOfAuthBoundKeys(std::vector<::std::string>* uids,
                                                       int32_t* _aidl_return) override;
 
-    ::android::binder::Status reset(int32_t* _aidl_return) override;
     ::android::binder::Status onUserPasswordChanged(int32_t userId,
                                                     const ::android::String16& newPassword,
                                                     int32_t* _aidl_return) override;
@@ -126,13 +125,16 @@
     finish(const ::android::sp<::android::security::keystore::IKeystoreOperationResultCallback>& cb,
            const ::android::sp<::android::IBinder>& token,
            const ::android::security::keymaster::KeymasterArguments& params,
-           const ::std::vector<uint8_t>& signature, const ::std::vector<uint8_t>& entropy,
-           int32_t* _aidl_return) override;
+           const ::std::vector<uint8_t>& input, const ::std::vector<uint8_t>& signature,
+           const ::std::vector<uint8_t>& entropy, int32_t* _aidl_return) override;
     ::android::binder::Status
     abort(const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb,
           const ::android::sp<::android::IBinder>& token, int32_t* _aidl_return) override;
     ::android::binder::Status addAuthToken(const ::std::vector<uint8_t>& authToken,
                                            int32_t* _aidl_return) override;
+    ::android::binder::Status
+    getAuthTokenForCredstore(int64_t challenge, int64_t secureUserId, int32_t authTokenMaxAge,
+                             ::std::vector<uint8_t>* _aidl_return) override;
     ::android::binder::Status onUserAdded(int32_t userId, int32_t parentId,
                                           int32_t* _aidl_return) override;
     ::android::binder::Status onUserRemoved(int32_t userId, int32_t* _aidl_return) override;
@@ -231,18 +233,6 @@
                                          std::vector<KeyParameter>* params);
 
     sp<KeyStore> mKeyStore;
-
-    /**
-     * This mutex locks keystore operations from concurrent execution.
-     * The keystore service has always been conceptually single threaded. Even with the introduction
-     * of keymaster workers, it was assumed that the dispatcher thread executes exclusively on
-     * certain code paths. With the introduction of wifi Keystore service in the keystore process
-     * this assumption no longer holds as the hwbinder thread servicing this interface makes
-     * functions (rather than IPC) calls into keystore. This mutex protects the keystore logic
-     * from concurrent execution.
-     */
-    std::mutex keystoreServiceMutex_;
-
 };
 
 };  // namespace keystore
diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp
index 728e607..911815e 100644
--- a/keystore/keymaster_worker.cpp
+++ b/keystore/keymaster_worker.cpp
@@ -22,14 +22,22 @@
 
 #include <android-base/logging.h>
 
+#include <log/log_event_list.h>
+
+#include <private/android_logger.h>
+
 #include "KeyStore.h"
 #include "keymaster_enforcement.h"
 
 #include "key_proto_handler.h"
 #include "keystore_utils.h"
 
+#include <chrono>
+
 namespace keystore {
 
+using namespace std::chrono;
+
 constexpr size_t kMaxOperations = 15;
 
 using AndroidKeymasterArguments = android::security::keymaster::KeymasterArguments;
@@ -40,23 +48,34 @@
 Worker::Worker() {}
 Worker::~Worker() {
     std::unique_lock<std::mutex> lock(pending_requests_mutex_);
-    pending_requests_cond_var_.wait(lock, [this] { return pending_requests_.empty(); });
+    terminate_ = true;
+    pending_requests_cond_var_.notify_all();
+    pending_requests_cond_var_.wait(lock, [this] { return !running_; });
 }
 void Worker::addRequest(WorkerTask request) {
     std::unique_lock<std::mutex> lock(pending_requests_mutex_);
-    bool start_thread = pending_requests_.empty();
+    bool start_thread = !running_;
+    running_ = true;
     pending_requests_.push(std::move(request));
     lock.unlock();
+    pending_requests_cond_var_.notify_all();
     if (start_thread) {
         auto worker = std::thread([this] {
             std::unique_lock<std::mutex> lock(pending_requests_mutex_);
-            running_ = true;
-            while (!pending_requests_.empty()) {
-                auto request = std::move(pending_requests_.front());
-                lock.unlock();
-                request();
-                lock.lock();
-                pending_requests_.pop();
+            while (running_) {
+                // Wait for 30s if the request queue is empty, then kill die.
+                // Die immediately if termiate_ was set which happens in the destructor.
+                auto status = pending_requests_cond_var_.wait_for(
+                    lock, 30s, [this]() { return !pending_requests_.empty() || terminate_; });
+                if (status && !terminate_) {
+                    auto request = std::move(pending_requests_.front());
+                    lock.unlock();
+                    request();
+                    lock.lock();
+                    pending_requests_.pop();
+                } else {
+                    running_ = false;
+                }
                 pending_requests_cond_var_.notify_all();
             }
         });
@@ -74,6 +93,26 @@
     keymasterDevice_->logIfKeymasterVendorError(ec);
 }
 
+void KeymasterWorker::deleteOldKeyOnUpgrade(const LockedKeyBlobEntry& blobfile, Blob keyBlob) {
+    // if we got the blob successfully, we try and delete it from the keymaster device
+    auto& dev = keymasterDevice_;
+    uid_t uid = blobfile->uid();
+    const auto& alias = blobfile->alias();
+
+    if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
+        auto ret = KS_HANDLE_HIDL_ERROR(dev, dev->deleteKey(blob2hidlVec(keyBlob)));
+        // A device doesn't have to implement delete_key.
+        bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED;
+        if (__android_log_security()) {
+            android_log_event_list(SEC_TAG_KEY_DESTROYED)
+                << int32_t(success) << alias << int32_t(uid) << LOG_ID_SECURITY;
+        }
+        if (!success) {
+            LOG(ERROR) << "Keymaster delete for key " << alias << " of uid " << uid << " failed";
+        }
+    }
+}
+
 std::tuple<KeyStoreServiceReturnCode, Blob>
 KeymasterWorker::upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry,
                                 const AuthorizationSet& params) {
@@ -111,12 +150,6 @@
             return;
         }
 
-        error = keyStore_->del(lockedEntry);
-        if (!error.isOk()) {
-            ALOGI("upgradeKeyBlob keystore->del failed %d", error.getErrorCode());
-            return;
-        }
-
         Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
                      0 /* infoLength */, ::TYPE_KEYMASTER_10);
         newBlob.setSecurityLevel(blob.getSecurityLevel());
@@ -129,6 +162,8 @@
             ALOGI("upgradeKeyBlob keystore->put failed %d", error.getErrorCode());
             return;
         }
+
+        deleteOldKeyOnUpgrade(lockedEntry, std::move(blob));
         blob = std::move(newBlob);
     };
 
diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h
index e1a1c02..8e35c16 100644
--- a/keystore/keymaster_worker.h
+++ b/keystore/keymaster_worker.h
@@ -20,7 +20,7 @@
 
 #include <condition_variable>
 #include <functional>
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
 #include <memory>
 #include <mutex>
 #include <optional>
@@ -32,6 +32,7 @@
 #include <keystore/KeyCharacteristics.h>
 #include <keystore/KeymasterBlob.h>
 #include <keystore/OperationResult.h>
+#include <keystore/keymaster_types.h>
 #include <keystore/keystore_return_types.h>
 
 #include "blob.h"
@@ -43,16 +44,7 @@
 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::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::VerificationToken;
-using android::hardware::keymaster::V4_0::support::Keymaster;
-// using KeystoreCharacteristics = ::android::security::keymaster::KeyCharacteristics;
+using android::hardware::keymaster::V4_1::support::Keymaster;
 using ::android::security::keymaster::KeymasterBlob;
 
 class KeyStore;
@@ -115,6 +107,7 @@
     std::mutex pending_requests_mutex_;
     std::condition_variable pending_requests_cond_var_;
     bool running_ = false;
+    bool terminate_ = false;
 
   public:
     Worker();
@@ -175,6 +168,8 @@
             unwrap_tuple(kmfn, std::move(cb), tuple, std::index_sequence_for<Args...>{});
         });
     }
+
+    void deleteOldKeyOnUpgrade(const LockedKeyBlobEntry& blobfile, Blob keyBlob);
     std::tuple<KeyStoreServiceReturnCode, Blob>
     upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry, const AuthorizationSet& params);
     std::tuple<KeyStoreServiceReturnCode, KeyCharacteristics, Blob, Blob>
diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.cpp b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
index 49e18f0..823ca58 100644
--- a/keystore/keystore_aidl_hidl_marshalling_utils.cpp
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
@@ -205,7 +205,7 @@
 namespace keymaster {
 
 using ::android::status_t;
-using ::keystore::keymaster::ErrorCode;
+using ::keystore::ErrorCode;
 
 ExportResult::ExportResult() : resultCode() {}
 
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index b48639f..3d9e87e 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -13,7 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "keystore_attestation_id.h"
+
+#include <keystore/keystore_attestation_id.h>
 
 #define LOG_TAG "keystore_att_id"
 
diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp
index 2705a19..428a9bc 100644
--- a/keystore/keystore_cli.cpp
+++ b/keystore/keystore_cli.cpp
@@ -47,21 +47,6 @@
     /* [WRONG_PASSWORD + 3] = */ "Wrong password (4 tries left)",
 };
 
-#define NO_ARG_INT_RETURN(cmd) \
-    do { \
-        if (strcmp(argv[1], #cmd) == 0) { \
-            int32_t ret = -1; \
-            service->cmd(&ret); \
-            if (ret < 0) { \
-                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
-                return 1; \
-            } else { \
-                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
-                return 0; \
-            } \
-        } \
-    } while (0)
-
 #define SINGLE_ARG_INT_RETURN(cmd) \
     do { \
         if (strcmp(argv[1], #cmd) == 0) { \
@@ -242,8 +227,6 @@
                 argc < 4 ? -1 : atoi(argv[3]));
     }
 
-    NO_ARG_INT_RETURN(reset);
-
     // TODO: notifyUserPasswordChanged
 
     SINGLE_INT_ARG_INT_RETURN(lock);
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index b46b221..4f69eb0 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -416,16 +416,10 @@
         return result.getErrorCode();
     }
     AuthorizationSet empty_params;
-    size_t num_input_bytes_consumed;
     std::string output_data;
-    result = keystore->updateOperation(handle, empty_params, "data_to_sign",
-                                       &num_input_bytes_consumed, &output_params, &output_data);
-    if (!result.isOk()) {
-        printf("Sign: UpdateOperation failed: %d\n", result.getErrorCode());
-        return result.getErrorCode();
-    }
-    result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
-                                       &output_params, &output_data);
+    result = keystore->finishOperation(handle, empty_params, "data_to_sign",
+                                       std::string() /*signature_to_verify*/, &output_params,
+                                       &output_data);
     if (!result.isOk()) {
         printf("Sign: FinishOperation failed: %d\n", result.getErrorCode());
         return result.getErrorCode();
@@ -436,18 +430,8 @@
     output_data.clear();
     result =
         keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle);
-    if (!result.isOk()) {
-        printf("Verify: BeginOperation failed: %d\n", result.getErrorCode());
-        return result.getErrorCode();
-    }
-    result = keystore->updateOperation(handle, empty_params, "data_to_sign",
-                                       &num_input_bytes_consumed, &output_params, &output_data);
-    if (!result.isOk()) {
-        printf("Verify: UpdateOperation failed: %d\n", result.getErrorCode());
-        return result.getErrorCode();
-    }
-    result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
-                                       &output_data);
+    result = keystore->finishOperation(handle, empty_params, "data_to_sign", signature_to_verify,
+                                       &output_params, &output_data);
     if (result == ErrorCode::VERIFICATION_FAILED) {
         printf("Verify: Failed to verify signature.\n");
         return result.getErrorCode();
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
index b9a142e..f888683 100644
--- a/keystore/keystore_client_impl.cpp
+++ b/keystore/keystore_client_impl.cpp
@@ -17,6 +17,7 @@
 #include "keystore/keystore_client_impl.h"
 
 #include <future>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -165,16 +166,9 @@
         return false;
     }
     AuthorizationSet empty_params;
-    size_t num_input_bytes_consumed;
     AuthorizationSet ignored_params;
-    result = updateOperation(handle, empty_params, input_data, &num_input_bytes_consumed,
-                             &ignored_params, output_data);
-    if (!result.isOk()) {
-        ALOGE("UpdateOperation failed: %d", result.getErrorCode());
-        return false;
-    }
-    result =
-        finishOperation(handle, empty_params, signature_to_verify, &ignored_params, output_data);
+    result = finishOperation(handle, empty_params, input_data, signature_to_verify, &ignored_params,
+                             output_data);
     if (!result.isOk()) {
         ALOGE("FinishOperation failed: %d", result.getErrorCode());
         return false;
@@ -383,6 +377,7 @@
 
 KeyStoreNativeReturnCode
 KeystoreClientImpl::finishOperation(uint64_t handle, const AuthorizationSet& input_parameters,
+                                    const std::string& input_data,
                                     const std::string& signature_to_verify,
                                     AuthorizationSet* output_parameters, std::string* output_data) {
     if (active_operations_.count(handle) == 0) {
@@ -390,12 +385,14 @@
     }
     int32_t error_code;
     auto hidlSignature = blob2hidlVec(signature_to_verify);
+    auto hidlInput = blob2hidlVec(input_data);
     android::sp<OperationResultPromise> promise(new OperationResultPromise{});
     auto future = promise->get_future();
     auto binder_result = keystore_->finish(
         promise, active_operations_[handle],
         android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
-        (std::vector<uint8_t>)hidlSignature, hidl_vec<uint8_t>(), &error_code);
+        (std::vector<uint8_t>)hidlInput, (std::vector<uint8_t>)hidlSignature, hidl_vec<uint8_t>(),
+        &error_code);
     if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
     KeyStoreNativeReturnCode rc(error_code);
     if (!rc.isOk()) return rc;
@@ -441,9 +438,14 @@
 
 bool KeystoreClientImpl::listKeys(const std::string& prefix,
                                   std::vector<std::string>* key_name_list) {
+    return listKeysOfUid(prefix, kDefaultUID, key_name_list);
+}
+
+bool KeystoreClientImpl::listKeysOfUid(const std::string& prefix, int uid,
+                                       std::vector<std::string>* key_name_list) {
     String16 prefix16(prefix.data(), prefix.size());
     std::vector<::android::String16> matches;
-    auto binder_result = keystore_->list(prefix16, kDefaultUID, &matches);
+    auto binder_result = keystore_->list(prefix16, uid, &matches);
     if (!binder_result.isOk()) return false;
 
     for (const auto& match : matches) {
@@ -453,6 +455,14 @@
     return true;
 }
 
+std::optional<std::vector<uint8_t>> KeystoreClientImpl::getKey(const std::string& alias, int uid) {
+    String16 alias16(alias.data(), alias.size());
+    std::vector<uint8_t> output;
+    auto binder_result = keystore_->get(alias16, uid, &output);
+    if (!binder_result.isOk()) return std::nullopt;
+    return output;
+}
+
 uint64_t KeystoreClientImpl::getNextVirtualHandle() {
     return next_virtual_handle_++;
 }
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
index f3eadd7..02c2139 100644
--- a/keystore/keystore_main.cpp
+++ b/keystore/keystore_main.cpp
@@ -17,16 +17,13 @@
 #define LOG_TAG "keystore"
 
 #include <android-base/logging.h>
-#include <android/hidl/manager/1.1/IServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
 #include <android/security/keystore/IKeystoreService.h>
-#include <android/system/wifi/keystore/1.0/IKeystore.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
-#include <hidl/HidlTransportSupport.h>
-#include <keymasterV4_0/Keymaster3.h>
-#include <keymasterV4_0/Keymaster4.h>
+#include <keymasterV4_1/Keymaster3.h>
+#include <keymasterV4_1/Keymaster4.h>
 #include <utils/StrongPointer.h>
-#include <wifikeystorehal/keystore.h>
 
 #include <keystore/keystore_hidl_support.h>
 #include <keystore/keystore_return_types.h>
@@ -43,15 +40,12 @@
  * the maximum space we needed, so boundary checks on buffers are omitted. */
 
 using ::android::sp;
-using ::android::hardware::configureRpcThreadpool;
-using ::android::system::wifi::keystore::V1_0::IKeystore;
-using ::android::system::wifi::keystore::V1_0::implementation::Keystore;
-using ::android::hidl::manager::V1_1::IServiceManager;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
-using ::android::hardware::keymaster::V4_0::SecurityLevel;
-using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
 using ::android::hardware::keymaster::V4_0::ErrorCode;
+using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
+using ::android::hardware::keymaster::V4_0::SecurityLevel;
+using ::android::hidl::manager::V1_2::IServiceManager;
 
 using ::keystore::keymaster::support::Keymaster;
 using ::keystore::keymaster::support::Keymaster3;
@@ -62,7 +56,7 @@
 template <typename Wrapper>
 KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) {
     KeymasterDevices result;
-    serviceManager->listByInterface(
+    serviceManager->listManifestByInterface(
         Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
             auto try_get_device = [&](const auto& name, bool fail_silent) {
                 auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
@@ -108,7 +102,7 @@
 }
 
 KeymasterDevices initializeKeymasters() {
-    auto serviceManager = android::hidl::manager::V1_1::IServiceManager::getService();
+    auto serviceManager = IServiceManager::getService();
     CHECK(serviceManager.get()) << "Failed to get ServiceManager";
     auto result = enumerateKeymasterDevices<Keymaster4>(serviceManager.get());
     auto softKeymaster = result[SecurityLevel::SOFTWARE];
@@ -160,16 +154,6 @@
     android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
     CHECK(ret == android::OK) << "Couldn't register binder service!";
 
-    /**
-     * Register the wifi keystore HAL service to run in passthrough mode.
-     * This will spawn off a new thread which will service the HIDL
-     * transactions.
-     */
-    configureRpcThreadpool(1, false /* callerWillJoin */);
-    android::sp<IKeystore> wifiKeystoreHalService = new Keystore();
-    android::status_t err = wifiKeystoreHalService->registerAsService();
-    CHECK(ret == android::OK) << "Cannot register wifi keystore HAL service: " << err;
-
     /*
      * This thread is just going to process Binder transactions.
      */
diff --git a/keystore/keystore_utils.cpp b/keystore/keystore_utils.cpp
index 78056d6..f0f6098 100644
--- a/keystore/keystore_utils.cpp
+++ b/keystore/keystore_utils.cpp
@@ -31,6 +31,9 @@
 #include <keystore/keymaster_types.h>
 #include <keystore/keystore_client.h>
 
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+
 #include "blob.h"
 
 size_t readFully(int fd, uint8_t* data, size_t size) {
@@ -64,6 +67,44 @@
     return size;
 }
 
+std::string getContainingDirectory(const std::string& filename) {
+    std::string containing_dir;
+    size_t last_pos;
+    size_t pos = std::string::npos;
+
+    __builtin_add_overflow(filename.size(), -1, &last_pos);
+
+    // strip all trailing '/'
+    while ((pos = filename.find_last_of('/', last_pos)) == last_pos && pos != 0) {
+        --last_pos;
+    }
+
+    if (pos == 0) {
+        containing_dir = "/";
+    } else if (pos == std::string::npos) {
+        containing_dir = ".";
+    } else {
+        containing_dir = filename.substr(0, pos);
+    }
+
+    return containing_dir;
+}
+
+void fsyncDirectory(const std::string& path) {
+    android::base::unique_fd dir_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_DIRECTORY | O_RDONLY)));
+
+    if (dir_fd < 0) {
+        LOG(WARNING) << "Could not open dir: " << path << " error: " << strerror(errno);
+        return;
+    }
+
+    if (TEMP_FAILURE_RETRY(fsync(dir_fd)) == -1) {
+        LOG(WARNING) << "Failed to fsync the directory " << path << " error: " << strerror(errno);
+    }
+
+    return;
+}
+
 void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* params) {
     using namespace keystore;
     params->push_back(TAG_PURPOSE, KeyPurpose::SIGN);
diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h
index 3bc9c01..ce64d42 100644
--- a/keystore/keystore_utils.h
+++ b/keystore/keystore_utils.h
@@ -18,6 +18,7 @@
 #define KEYSTORE_KEYSTORE_UTILS_H_
 
 #include <cstdint>
+#include <string>
 #include <vector>
 
 #include <openssl/evp.h>
@@ -29,6 +30,8 @@
 
 size_t readFully(int fd, uint8_t* data, size_t size);
 size_t writeFully(int fd, uint8_t* data, size_t size);
+std::string getContainingDirectory(const std::string& filename);
+void fsyncDirectory(const std::string& path);
 
 void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* params);
 
@@ -44,16 +47,6 @@
  */
 uid_t get_user_id(uid_t uid);
 
-struct EVP_PKEY_Delete {
-    void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
-};
-typedef std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
-
-struct PKCS8_PRIV_KEY_INFO_Delete {
-    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
-};
-typedef std::unique_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
-
 class Blob;
 
 // Tags for audit logging. Be careful and don't log sensitive data.
diff --git a/keystore/operation.h b/keystore/operation.h
index e0865a4..ef880a7 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -26,7 +26,7 @@
 
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
 #include <utils/StrongPointer.h>
 
 #include <keystore/keymaster_types.h>
diff --git a/keystore/operation_proto_handler.cpp b/keystore/operation_proto_handler.cpp
index dfc0692..3b3d3fc 100644
--- a/keystore/operation_proto_handler.cpp
+++ b/keystore/operation_proto_handler.cpp
@@ -19,7 +19,7 @@
 
 #include <android/os/DropBoxManager.h>
 #include <google/protobuf/message_lite.h>
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
 #include <keystore/keymaster_types.h>
 #include <keystore/keystore_hidl_support.h>
 #include <utils/String16.h>
diff --git a/keystore/operation_struct.h b/keystore/operation_struct.h
index 84265b6..23e79fc 100644
--- a/keystore/operation_struct.h
+++ b/keystore/operation_struct.h
@@ -19,7 +19,7 @@
 
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
 #include <utils/StrongPointer.h>
 
 #include <keystore/keymaster_types.h>
diff --git a/keystore/permissions.cpp b/keystore/permissions.cpp
index 05454cb..2cd42cf 100644
--- a/keystore/permissions.cpp
+++ b/keystore/permissions.cpp
@@ -57,8 +57,6 @@
 user_euid user_euids[] = {{AID_VPN, AID_SYSTEM},
                           {AID_WIFI, AID_SYSTEM},
                           {AID_ROOT, AID_SYSTEM},
-                          {AID_WIFI, AID_KEYSTORE},
-                          {AID_KEYSTORE, AID_WIFI},
 
 #ifdef GRANT_ROOT_ALL_PERMISSIONS
                           // Allow VTS tests to act on behalf of the wifi user
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
index 25fa10b..eac6fe6 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -19,19 +19,21 @@
     static_libs: [
         "android.hardware.confirmationui@1.0",
         "libbase",
-        "libcrypto",
+        "libcrypto_static",
         "libcutils",
         "libgtest_main",
         "libhidlbase",
         "libkeymaster4support",
+        "libkeymaster4_1support",
         "libkeystore_test",
         "liblog",
         "libutils",
-        "libvndksupport",
     ],
     shared_libs: [
         "libbinder",
         "libkeymaster_messages",
+        "libkeystore-attestation-application-id",
+        "libvndksupport",
     ],
    sanitize: {
      cfi: false,
diff --git a/keystore/tests/aaid_truncation_test.cpp b/keystore/tests/aaid_truncation_test.cpp
index e5d5e9f..45c54df 100644
--- a/keystore/tests/aaid_truncation_test.cpp
+++ b/keystore/tests/aaid_truncation_test.cpp
@@ -19,8 +19,8 @@
 #include <string>
 #include <utils/String16.h>
 
-#include "../keystore_attestation_id.h"
 #include <keymaster/logger.h>
+#include <keystore/keystore_attestation_id.h>
 
 #include <keystore/KeyAttestationApplicationId.h>
 #include <keystore/KeyAttestationPackageInfo.h>
diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp
index 8d993e2..30dfe3c 100644
--- a/keystore/user_state.cpp
+++ b/keystore/user_state.cpp
@@ -37,7 +37,7 @@
 
 UserState::UserState(uid_t userId)
     : mMasterKeyEntry(".masterkey", "user_" + std::to_string(userId), userId, /* masterkey */ true),
-      mUserId(userId), mState(STATE_UNINITIALIZED), mRetry(MAX_RETRY) {}
+      mUserId(userId), mState(STATE_UNINITIALIZED) {}
 
 bool UserState::operator<(const UserState& rhs) const {
     return getUserId() < rhs.getUserId();
@@ -69,9 +69,6 @@
 
 void UserState::setState(State state) {
     mState = state;
-    if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
-        mRetry = MAX_RETRY;
-    }
 }
 
 void UserState::zeroizeMasterKeysInMemory() {
@@ -208,23 +205,9 @@
         }
         return response;
     }
-    if (mRetry <= 0) {
-        reset();
-        return ResponseCode::UNINITIALIZED;
-    }
-    --mRetry;
-    switch (mRetry) {
-    case 0:
-        return ResponseCode::WRONG_PASSWORD_0;
-    case 1:
-        return ResponseCode::WRONG_PASSWORD_1;
-    case 2:
-        return ResponseCode::WRONG_PASSWORD_2;
-    case 3:
-        return ResponseCode::WRONG_PASSWORD_3;
-    default:
-        return ResponseCode::WRONG_PASSWORD_3;
-    }
+
+    LOG(ERROR) << "Invalid password presented";
+    return ResponseCode::WRONG_PASSWORD_0;
 }
 
 bool UserState::reset() {
diff --git a/keystore/user_state.h b/keystore/user_state.h
index 620aaa5..75d99d9 100644
--- a/keystore/user_state.h
+++ b/keystore/user_state.h
@@ -55,8 +55,6 @@
     void setState(State state);
     State getState() const { return mState; }
 
-    int8_t getRetry() const { return mRetry; }
-
     void zeroizeMasterKeysInMemory();
     bool deleteMasterKey();
 
@@ -81,7 +79,6 @@
     static constexpr int MASTER_KEY_SIZE_BYTES = kAes256KeySizeBytes;
     static constexpr int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8;
 
-    static constexpr int MAX_RETRY = 4;
     static constexpr size_t SALT_SIZE = 16;
 
     void generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw,
@@ -94,7 +91,6 @@
 
     uid_t mUserId;
     State mState;
-    int8_t mRetry;
 
     std::vector<uint8_t> mMasterKey;
     uint8_t mSalt[SALT_SIZE];