diff --git a/identity/Credential.cpp b/identity/Credential.cpp
new file mode 100644
index 0000000..6b03309
--- /dev/null
+++ b/identity/Credential.cpp
@@ -0,0 +1,494 @@
+/*
+ * 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::hidl_vec;
+
+using ::android::hardware::identity::V1_0::Result;
+using ::android::hardware::identity::V1_0::ResultCode;
+using ::android::hardware::identity::V1_0::SecureAccessControlProfile;
+
+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;
+
+Credential::Credential(const std::string& dataPath, const std::string& credentialName)
+    : 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;
+
+    Result result;
+    sp<IIdentityCredential> halBinder;
+    halStoreBinder->getCredential(
+        data_->getCredentialData(),
+        [&](const Result& _result, const sp<IIdentityCredential>& _halBinder) {
+            result = _result;
+            halBinder = _halBinder;
+        });
+    if (result.code != ResultCode::OK) {
+        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");
+    }
+
+    Result result;
+    uint64_t challenge;
+    halBinder_->createAuthChallenge([&](const Result& _result, uint64_t _challenge) {
+        result = _result;
+        challenge = _challenge;
+    });
+    if (result.code != ResultCode::OK) {
+        LOG(ERROR) << "createAuthChallenge() failed " << ((int)result.code) << ": "
+                   << result.message;
+        return halResultToGenericError(result);
+    }
+    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<uint16_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 (uint16_t id : data.value().accessControlProfileIds) {
+                    if (id >= 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.
+    HardwareAuthToken authToken;
+    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) {
+            authToken =
+                android::hardware::keymaster::V4_0::support::hidlVec2AuthToken(authTokenBytes);
+        }
+    }
+
+    Result result;
+    halBinder_->startRetrieval(selectedProfiles, authToken, requestMessage, sessionTranscript,
+                               readerSignature, requestCounts,
+                               [&](const Result& _result) { result = _result; });
+    if (result.code == ResultCode::EPHEMERAL_PUBLIC_KEY_NOT_FOUND) {
+        LOG(ERROR) << "startRetrieval() failed " << ((int)result.code) << ": " << result.message;
+        return Status::fromServiceSpecificError(
+            ICredentialStore::ERROR_EPHEMERAL_PUBLIC_KEY_NOT_FOUND, result.message.c_str());
+    } else if (result.code == ResultCode::READER_SIGNATURE_CHECK_FAILED) {
+        LOG(ERROR) << "startRetrieval() failed " << ((int)result.code) << ": " << result.message;
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_INVALID_READER_SIGNATURE,
+                                                result.message.c_str());
+    } else if (result.code == ResultCode::INVALID_ITEMS_REQUEST_MESSAGE) {
+        LOG(ERROR) << "startRetrieval() failed " << ((int)result.code) << ": " << result.message;
+        return Status::fromServiceSpecificError(
+            ICredentialStore::ERROR_INVALID_ITEMS_REQUEST_MESSAGE, result.message.c_str());
+    } else if (result.code == ResultCode::SESSION_TRANSCRIPT_MISMATCH) {
+        LOG(ERROR) << "startRetrieval() failed " << ((int)result.code) << ": " << result.message;
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_SESSION_TRANSCRIPT_MISMATCH,
+                                                result.message.c_str());
+    } else if (result.code != ResultCode::OK) {
+        LOG(ERROR) << "startRetrieval() failed " << ((int)result.code) << ": " << result.message;
+        return halResultToGenericError(result);
+    }
+
+    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;
+            }
+
+            halBinder_->startRetrieveEntryValue(rns.namespaceName, rep.name, data.value().size,
+                                                data.value().accessControlProfileIds,
+                                                [&](const Result& _result) { result = _result; });
+            if (result.code == ResultCode::USER_AUTHENTICATION_FAILED) {
+                resultEntryParcel.status = STATUS_USER_AUTHENTICATION_FAILED;
+                resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                continue;
+            } else if (result.code == ResultCode::READER_AUTHENTICATION_FAILED) {
+                resultEntryParcel.status = STATUS_READER_AUTHENTICATION_FAILED;
+                resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                continue;
+            } else if (result.code == ResultCode::NOT_IN_REQUEST_MESSAGE) {
+                resultEntryParcel.status = STATUS_NOT_IN_REQUEST_MESSAGE;
+                resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                continue;
+            } else if (result.code == ResultCode::NO_ACCESS_CONTROL_PROFILES) {
+                resultEntryParcel.status = STATUS_NO_ACCESS_CONTROL_PROFILES;
+                resultNamespaceParcel.entries.push_back(resultEntryParcel);
+                continue;
+            } else if (result.code != ResultCode::OK) {
+                LOG(ERROR) << "startRetrieveEntryValue() failed " << ((int)result.code) << ": "
+                           << result.message;
+                return halResultToGenericError(result);
+            }
+
+            vector<uint8_t> value;
+            for (const auto& encryptedChunk : data.value().encryptedChunks) {
+                halBinder_->retrieveEntryValue(
+                    encryptedChunk, [&](const Result& _result, const hidl_vec<uint8_t>& chunk) {
+                        result = _result;
+                        value.insert(value.end(), chunk.begin(), chunk.end());
+                    });
+                if (result.code != ResultCode::OK) {
+                    LOG(ERROR) << "retrieveEntryValue failed() " << ((int)result.code) << ": "
+                               << result.message;
+                    return halResultToGenericError(result);
+                }
+            }
+
+            resultEntryParcel.status = STATUS_OK;
+            resultEntryParcel.value = value;
+            resultNamespaceParcel.entries.push_back(resultEntryParcel);
+        }
+        ret.resultNamespaces.push_back(resultNamespaceParcel);
+    }
+
+    // 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;
+    }
+    halBinder_->finishRetrieval(signingKeyBlob, [&](const Result& _result,
+                                                    const hidl_vec<uint8_t>& _mac,
+                                                    const hidl_vec<uint8_t>& _deviceNameSpaces) {
+        result = _result;
+        ret.mac = _mac;
+        ret.deviceNameSpaces = _deviceNameSpaces;
+        if (authKey != nullptr) {
+            ret.staticAuthenticationData = authKey->staticAuthenticationData;
+        }
+    });
+    if (result.code != ResultCode::OK) {
+        LOG(ERROR) << "finishRetrieval failed() " << ((int)result.code) << ": " << result.message;
+        return halResultToGenericError(result);
+    }
+
+    // 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) {
+    Result result;
+    halBinder_->deleteCredential(
+        [&](const Result& _result, const hidl_vec<uint8_t>& _proofOfDeletionSignature) {
+            result = _result;
+            *_aidl_return = _proofOfDeletionSignature;
+        });
+    if (result.code != ResultCode::OK) {
+        LOG(ERROR) << "deleteCredential failed() " << ((int)result.code) << ": " << result.message;
+        return halResultToGenericError(result);
+    }
+    if (!data_->deleteCredential()) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error deleting credential data on disk");
+    }
+    return Status::ok();
+}
+
+Status Credential::createEphemeralKeyPair(vector<uint8_t>* _aidl_return) {
+    Result result;
+
+    vector<uint8_t> keyPair;
+    halBinder_->createEphemeralKeyPair(
+        [&](const Result& _result, const hidl_vec<uint8_t>& _keyPair) {
+            result = _result;
+            keyPair = _keyPair;
+        });
+    if (result.code != ResultCode::OK) {
+        LOG(ERROR) << "createEphemeralKeyPair failed() " << ((int)result.code) << ": "
+                   << result.message;
+        return halResultToGenericError(result);
+    }
+
+    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) {
+    Result result;
+    halBinder_->setReaderEphemeralPublicKey(publicKey,
+                                            [&](const Result& _result) { result = _result; });
+    if (result.code != ResultCode::OK) {
+        LOG(ERROR) << "setReaderEphemeralPublicKey failed() " << ((int)result.code) << ": "
+                   << result.message;
+        return halResultToGenericError(result);
+    }
+    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
