/*
 * 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 "credstore"

#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/hardware/identity/support/IdentityCredentialSupport.h>

#include <android/security/identity/ICredentialStore.h>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <keymasterV4_0/keymaster_utils.h>

#include <cppbor.h>
#include <cppbor_parse.h>
#include <future>
#include <tuple>

#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
#include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
#include <aidl/android/security/authorization/AuthorizationTokens.h>
#include <aidl/android/security/authorization/IKeystoreAuthorization.h>

#include "Credential.h"
#include "CredentialData.h"
#include "Util.h"
#include "WritableCredential.h"

namespace android {
namespace security {
namespace identity {

using std::optional;
using std::promise;
using std::tuple;

using ::android::hardware::identity::IWritableIdentityCredential;

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::SecurityLevel;
using android::hardware::keymaster::V4_0::HardwareAuthToken;
using android::hardware::keymaster::V4_0::VerificationToken;
using AidlHardwareAuthToken = android::hardware::keymaster::HardwareAuthToken;
using AidlVerificationToken = android::hardware::keymaster::VerificationToken;

using KeyMintAuthToken = ::aidl::android::hardware::security::keymint::HardwareAuthToken;
using ::aidl::android::hardware::security::secureclock::TimeStampToken;
using ::aidl::android::security::authorization::AuthorizationTokens;
using ::aidl::android::security::authorization::IKeystoreAuthorization;

Credential::Credential(CipherSuite cipherSuite, const std::string& dataPath,
                       const std::string& credentialName, uid_t callingUid,
                       HardwareInformation hwInfo, sp<IIdentityCredentialStore> halStoreBinder,
                       sp<IPresentationSession> halSessionBinder, int halApiVersion)
    : cipherSuite_(cipherSuite), dataPath_(dataPath), credentialName_(credentialName),
      callingUid_(callingUid), hwInfo_(std::move(hwInfo)), halStoreBinder_(halStoreBinder),
      halSessionBinder_(halSessionBinder), halApiVersion_(halApiVersion) {}

Credential::~Credential() {}

Status Credential::ensureOrReplaceHalBinder() {
    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");
    }

    // If we're in a session we explicitly don't get the binder to IIdentityCredential until
    // it's used in getEntries() which is the only method call allowed for sessions.
    //
    // Why? This is because we want to throw the IIdentityCredential object away as soon as it's
    // used because the HAL only guarantees a single IIdentityCredential object alive at a time
    // and in a session there may be multiple credentials in play and we want to do multiple
    // getEntries() calls on all of them.
    //

    if (!halSessionBinder_) {
        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) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }
    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");
    }
    *_aidl_return = data->getAttestationCertificate();
    return Status::ok();
}

// Returns operation handle
Status Credential::selectAuthKey(bool allowUsingExhaustedKeys, bool allowUsingExpiredKeys,
                                 bool incrementUsageCount, int64_t* _aidl_return) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }
    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");
    }

    // We just check if a key is available, we actually don't store it since we
    // don't keep CredentialData around between binder calls.
    const AuthKeyData* authKey =
        data->selectAuthKey(allowUsingExhaustedKeys, allowUsingExpiredKeys, incrementUsageCount);
    if (authKey == nullptr) {
        return Status::fromServiceSpecificError(
            ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
            "No suitable authentication key available");
    }

    if (!ensureChallenge()) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Error getting challenge (bug in HAL or TA)");
    }
    *_aidl_return = selectedChallenge_;
    return Status::ok();
}

bool Credential::ensureChallenge() {
    if (selectedChallenge_ != 0) {
        return true;
    }

    int64_t challenge;
    // If we're in a session, the challenge is selected by the session
    if (halSessionBinder_) {
        Status status = halSessionBinder_->getAuthChallenge(&challenge);
        if (!status.isOk()) {
            LOG(ERROR) << "Error getting challenge from session: " << status.exceptionMessage();
            return false;
        }
    } else {
        Status status = halBinder_->createAuthChallenge(&challenge);
        if (!status.isOk()) {
            LOG(ERROR) << "Error getting challenge: " << status.exceptionMessage();
            return false;
        }
    }
    if (challenge == 0) {
        LOG(ERROR) << "Returned challenge is 0 (bug in HAL or TA)";
        return false;
    }

    selectedChallenge_ = challenge;
    return true;
}

// Returns false if an error occurred communicating with keystore.
//
bool getTokensFromKeystore2(uint64_t challenge, uint64_t secureUserId,
                            unsigned int authTokenMaxAgeMillis,
                            AidlHardwareAuthToken& aidlAuthToken,
                            AidlVerificationToken& aidlVerificationToken) {
    // try to connect to IKeystoreAuthorization AIDL service first.
    AIBinder* authzAIBinder = AServiceManager_checkService("android.security.authorization");
    ::ndk::SpAIBinder authzBinder(authzAIBinder);
    auto authzService = IKeystoreAuthorization::fromBinder(authzBinder);
    if (authzService) {
        AuthorizationTokens authzTokens;
        auto result = authzService->getAuthTokensForCredStore(challenge, secureUserId,
                                                              authTokenMaxAgeMillis, &authzTokens);
        // Convert KeyMint auth token to KeyMaster authtoken, only if tokens are
        // returned
        if (result.isOk()) {
            KeyMintAuthToken keymintAuthToken = authzTokens.authToken;
            aidlAuthToken.challenge = keymintAuthToken.challenge;
            aidlAuthToken.userId = keymintAuthToken.userId;
            aidlAuthToken.authenticatorId = keymintAuthToken.authenticatorId;
            aidlAuthToken.authenticatorType =
                ::android::hardware::keymaster::HardwareAuthenticatorType(
                    int32_t(keymintAuthToken.authenticatorType));
            aidlAuthToken.timestamp.milliSeconds = keymintAuthToken.timestamp.milliSeconds;
            aidlAuthToken.mac = keymintAuthToken.mac;

            // Convert timestamp token to KeyMaster verification token
            TimeStampToken timestampToken = authzTokens.timestampToken;
            aidlVerificationToken.challenge = timestampToken.challenge;
            aidlVerificationToken.timestamp.milliSeconds = timestampToken.timestamp.milliSeconds;
            // Legacy verification tokens were always minted by TEE.
            aidlVerificationToken.securityLevel = SecurityLevel::TRUSTED_ENVIRONMENT;
            aidlVerificationToken.mac = timestampToken.mac;
        } else {
            if (result.getServiceSpecificError() == 0) {
                // Here we differentiate the errors occurred during communication
                // from the service specific errors.
                LOG(ERROR) << "Error getting tokens from keystore2: " << result.getDescription();
                return false;
            } else {
                // Log the reason for not receiving auth tokens from keystore2.
                LOG(INFO) << "Auth tokens were not received due to: " << result.getDescription();
            }
        }
        return true;
    } else {
        LOG(ERROR) << "Error connecting to IKeystoreAuthorization service";
        return false;
    }
}

Status Credential::getEntries(const vector<uint8_t>& requestMessage,
                              const vector<RequestNamespaceParcel>& requestNamespaces,
                              const vector<uint8_t>& sessionTranscript,
                              const vector<uint8_t>& readerSignature, bool allowUsingExhaustedKeys,
                              bool allowUsingExpiredKeys, bool incrementUsageCount,
                              GetEntriesResultParcel* _aidl_return) {
    GetEntriesResultParcel ret;

    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");
    }

    // If used in a session, get the binder on demand...
    //
    sp<IIdentityCredential> halBinder = halBinder_;
    if (halSessionBinder_) {
        if (halBinder) {
            LOG(ERROR) << "Unexpected HAL binder for session";
            return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                    "Unexpected HAL binder for session");
        }
        Status status = halSessionBinder_->getCredential(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);
        }
    }

    // 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();

    // We don't support ACP identifiers which isn't in the range 0 to 31. This
    // guarantee exists so it's feasible to implement the TA part of an Identity
    // Credential HAL implementation where the TA uses a 32-bit word to indicate
    // which profiles are authorized.
    for (const SecureAccessControlProfile& profile : allProfiles) {
        if (profile.id < 0 || profile.id >= 32) {
            return Status::fromServiceSpecificError(
                ICredentialStore::ERROR_GENERIC,
                "Invalid accessProfileId in profile (must be between 0 and 31)");
        }
    }

    vector<bool> includeProfile(32);

    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> eData = data->getEntryData(rns.namespaceName, rep.name);
            if (eData) {
                for (int32_t id : eData.value().accessControlProfileIds) {
                    if (id < 0 || id >= 32) {
                        LOG(ERROR) << "Invalid accessControlProfileId " << id << " for "
                                   << rns.namespaceName << ": " << rep.name;
                        return Status::fromServiceSpecificError(
                            ICredentialStore::ERROR_GENERIC,
                            "Invalid accessProfileId in entry (must be between 0 and 31)");
                    }
                    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[allProfiles[n].id]) {
            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;
                }
            }
        }
    }

    // Reset tokens and only get them if they're actually needed, e.g. if user authentication
    // is needed in any of the access control profiles for data items being requested.
    //
    AidlHardwareAuthToken aidlAuthToken;
    AidlVerificationToken aidlVerificationToken;
    aidlAuthToken.challenge = 0;
    aidlAuthToken.userId = 0;
    aidlAuthToken.authenticatorId = 0;
    aidlAuthToken.authenticatorType =
        ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
    aidlAuthToken.timestamp.milliSeconds = 0;
    aidlAuthToken.mac.clear();
    aidlVerificationToken.challenge = 0;
    aidlVerificationToken.timestamp.milliSeconds = 0;
    aidlVerificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
    aidlVerificationToken.mac.clear();
    if (userAuthNeeded) {
        // If user authentication is needed, always get a challenge from the
        // HAL/TA since it'll need it to check the returned VerificationToken
        // for freshness.
        if (!ensureChallenge()) {
            return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                    "Error getting challenge (bug in HAL or TA)");
        }

        // Note: if all selected profiles require auth-on-every-presentation
        // then authTokenMaxAgeMillis will be 0 (because timeoutMillis for each
        // profile is 0). Which means that keystore will only return an
        // AuthToken if its challenge matches what we pass, regardless of its
        // age. This is intended b/c the HAL/TA will check not care about
        // the age in this case, it only cares that the challenge matches.
        //
        // Otherwise, if one or more of the profiles is auth-with-a-timeout then
        // authTokenMaxAgeMillis will be set to the largest of those
        // timeouts. We'll get an AuthToken which satisfies this deadline if it
        // exists. This authToken _may_ have the requested challenge but it's
        // not a guarantee and it's also not required.
        //

        if (!getTokensFromKeystore2(selectedChallenge_, data->getSecureUserId(),
                                    authTokenMaxAgeMillis, aidlAuthToken, aidlVerificationToken)) {
            LOG(ERROR) << "Error getting tokens from keystore2";
            return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                    "Error getting tokens from keystore2");
        }
    }

    // Reuse the same AuthKey over multiple getEntries() calls.
    //
    bool updateUseCountOnDisk = false;
    if (!selectedAuthKey_) {
        // 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 = data->selectAuthKey(
            allowUsingExhaustedKeys, allowUsingExpiredKeys, incrementUsageCount);
        if (authKey == nullptr) {
            // If no authKey is available, consider it an error only when a
            // SessionTranscript was provided.
            //
            // We allow no SessionTranscript to be provided because it makes
            // the API simpler to deal with insofar it can be used without having
            // to generate any authentication keys.
            //
            // In this "no SessionTranscript is provided" mode we don't return
            // DeviceNameSpaces nor a MAC over DeviceAuthentication so we don't
            // need a device key.
            //
            if (sessionTranscript.size() > 0) {
                return Status::fromServiceSpecificError(
                    ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
                    "No suitable authentication key available and one is needed");
            }
        } else {
            // We did find an authKey. Store its contents for future getEntries() calls.
            updateUseCountOnDisk = true;
            selectedAuthKeySigningKeyBlob_ = authKey->keyBlob;
            selectedAuthKeyStaticAuthData_ = authKey->staticAuthenticationData;
        }
        selectedAuthKey_ = true;
    }

    // Pass the HAL enough information to allow calculating the size of
    // DeviceNameSpaces ahead of time.
    vector<RequestNamespace> halRequestNamespaces;
    for (const RequestNamespaceParcel& rns : requestNamespaces) {
        RequestNamespace ns;
        ns.namespaceName = rns.namespaceName;
        for (const RequestEntryParcel& rep : rns.entries) {
            optional<EntryData> entryData = data->getEntryData(rns.namespaceName, rep.name);
            if (entryData) {
                RequestDataItem di;
                di.name = rep.name;
                di.size = entryData.value().size;
                di.accessControlProfileIds = entryData.value().accessControlProfileIds;
                ns.items.push_back(di);
            }
        }
        if (ns.items.size() > 0) {
            halRequestNamespaces.push_back(ns);
        }
    }
    // This is not catastrophic, we might be dealing with a version 1 implementation which
    // doesn't have this method.
    Status status = halBinder->setRequestedNamespaces(halRequestNamespaces);
    if (!status.isOk()) {
        LOG(INFO) << "Failed setting expected requested namespaces, assuming V1 HAL "
                  << "and continuing";
    }

    // Pass the verification token. Failure is OK, this method isn't in the V1 HAL.
    status = halBinder->setVerificationToken(aidlVerificationToken);
    if (!status.isOk()) {
        LOG(INFO) << "Failed setting verification token, assuming V1 HAL "
                  << "and continuing";
    }

    status = halBinder->startRetrieval(selectedProfiles, aidlAuthToken, requestMessage,
                                       selectedAuthKeySigningKeyBlob_, 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> eData = data->getEntryData(rns.namespaceName, rep.name);
            if (!eData) {
                resultEntryParcel.status = STATUS_NO_SUCH_ENTRY;
                resultNamespaceParcel.entries.push_back(resultEntryParcel);
                continue;
            }

            status =
                halBinder->startRetrieveEntryValue(rns.namespaceName, rep.name, eData.value().size,
                                                   eData.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 : eData.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);
    }

    // API version 5 (feature version 202301) supports both MAC and ECDSA signature.
    if (halApiVersion_ >= 5) {
        status = halBinder->finishRetrievalWithSignature(&ret.mac, &ret.deviceNameSpaces,
                                                         &ret.signature);
        if (!status.isOk()) {
            return halStatusToGenericError(status);
        }
    } else {
        status = halBinder->finishRetrieval(&ret.mac, &ret.deviceNameSpaces);
        if (!status.isOk()) {
            return halStatusToGenericError(status);
        }
    }
    ret.staticAuthenticationData = selectedAuthKeyStaticAuthData_;

    // Ensure useCount is updated on disk.
    if (updateUseCountOnDisk) {
        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) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    vector<uint8_t> proofOfDeletionSignature;

    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");
    }

    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::deleteWithChallenge(const vector<uint8_t>& challenge,
                                       vector<uint8_t>* _aidl_return) {
    if (halApiVersion_ < 3) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_NOT_SUPPORTED,
                                                "Not implemented by HAL");
    }

    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    vector<uint8_t> proofOfDeletionSignature;

    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");
    }

    Status status = halBinder_->deleteCredentialWithChallenge(challenge, &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::proveOwnership(const vector<uint8_t>& challenge, vector<uint8_t>* _aidl_return) {
    if (halApiVersion_ < 3) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_NOT_SUPPORTED,
                                                "Not implemented by HAL");
    }

    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    vector<uint8_t> proofOfOwnershipSignature;
    Status status = halBinder_->proveOwnership(challenge, &proofOfOwnershipSignature);
    if (!status.isOk()) {
        return halStatusToGenericError(status);
    }
    *_aidl_return = proofOfOwnershipSignature;
    return Status::ok();
}

Status Credential::createEphemeralKeyPair(vector<uint8_t>* _aidl_return) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    vector<uint8_t> keyPair;
    Status status = halBinder_->createEphemeralKeyPair(&keyPair);
    if (!status.isOk()) {
        return halStatusToGenericError(status);
    }

    time_t nowSeconds = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    time_t validityNotBefore = nowSeconds;
    time_t validityNotAfter = nowSeconds + 24 * 60 * 60;
    optional<vector<uint8_t>> pkcs12Bytes = ecKeyPairGetPkcs12(keyPair,
                                                               "ephemeralKey",  // Alias for key
                                                               "0",  // Serial, as a decimal number
                                                               "Credstore",      // Issuer
                                                               "Ephemeral Key",  // Subject
                                                               validityNotBefore, validityNotAfter);
    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) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    Status status = halBinder_->setReaderEphemeralPublicKey(publicKey);
    if (!status.isOk()) {
        return halStatusToGenericError(status);
    }
    return Status::ok();
}

Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey,
                                                  int64_t minValidTimeMillis) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    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->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey, minValidTimeMillis);
    if (!data->saveToDisk()) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Error saving data");
    }
    return Status::ok();
}

Status Credential::getAuthKeysNeedingCertification(vector<AuthKeyParcel>* _aidl_return) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    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");
    }
    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 (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    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");
    }
    if (!data->storeStaticAuthenticationData(authenticationKey.x509cert,
                                             std::numeric_limits<int64_t>::max(), 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::storeStaticAuthenticationDataWithExpiration(const AuthKeyParcel& authenticationKey,
                                                        int64_t expirationDateMillisSinceEpoch,
                                                        const vector<uint8_t>& staticAuthData) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    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");
    }
    if (!data->storeStaticAuthenticationData(authenticationKey.x509cert,
                                             expirationDateMillisSinceEpoch, 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) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    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");
    }
    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();
}

Status Credential::getAuthenticationDataExpirations(vector<int64_t>* _aidl_return) {
    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    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");
    }
    const vector<AuthKeyData>& authKeyDatas = data->getAuthKeyDatas();
    vector<int64_t> ret;
    ret.reserve(authKeyDatas.size());
    for (const AuthKeyData& authKeyData : authKeyDatas) {
        // Note: value is INT64_MAX if expiration date is not set.
        ret.push_back(authKeyData.expirationDateMillisSinceEpoch);
    }
    *_aidl_return = ret;
    return Status::ok();
}

optional<string> extractDocType(const vector<uint8_t>& credentialData) {
    auto [item, _ /* newPos */, message] = cppbor::parse(credentialData);
    if (item == nullptr) {
        LOG(ERROR) << "CredentialData is not valid CBOR: " << message;
        return {};
    }
    const cppbor::Array* array = item->asArray();
    if (array == nullptr || array->size() < 1) {
        LOG(ERROR) << "CredentialData array with at least one element";
        return {};
    }
    const cppbor::Tstr* tstr = ((*array)[0])->asTstr();
    if (tstr == nullptr) {
        LOG(ERROR) << "First item in CredentialData is not a string";
        return {};
    }
    return tstr->value();
}

Status Credential::update(sp<IWritableCredential>* _aidl_return) {
    if (halApiVersion_ < 3) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_NOT_SUPPORTED,
                                                "Not implemented by HAL");
    }

    if (halSessionBinder_) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Cannot be used with session");
    }

    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");
    }

    sp<IWritableIdentityCredential> halWritableCredential;
    Status status = halBinder_->updateCredential(&halWritableCredential);
    if (!status.isOk()) {
        return halStatusToGenericError(status);
    }

    optional<string> docType = extractDocType(data->getCredentialData());
    if (!docType) {
        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                "Unable to extract DocType from CredentialData");
    }

    // NOTE: The caller is expected to call WritableCredential::personalize() which will
    // write brand new data to disk, specifically it will overwrite any data already
    // have _including_ authentication keys.
    //
    // It is because of this we need to set the CredentialKey certificate chain,
    // keyCount, and maxUsesPerKey below.
    sp<WritableCredential> writableCredential = new WritableCredential(
        dataPath_, credentialName_, docType.value(), true, hwInfo_, halWritableCredential);

    writableCredential->setAttestationCertificate(data->getAttestationCertificate());
    auto [keyCount, maxUsesPerKey, minValidTimeMillis] = data->getAvailableAuthenticationKeys();
    writableCredential->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey, minValidTimeMillis);

    // Because its data has changed, we need to replace the binder for the
    // IIdentityCredential when the credential has been updated... otherwise the
    // remote object will have stale data for future calls, for example
    // getAuthKeysNeedingCertification().
    //
    // The way this is implemented is that setCredentialToReloadWhenUpdated()
    // instructs the WritableCredential to call writableCredentialPersonalized()
    // on |this|.
    //
    //
    writableCredential->setCredentialToReloadWhenUpdated(this);

    *_aidl_return = writableCredential;
    return Status::ok();
}

void Credential::writableCredentialPersonalized() {
    Status status = ensureOrReplaceHalBinder();
    if (!status.isOk()) {
        LOG(ERROR) << "Error reloading credential";
    }
}

}  // namespace identity
}  // namespace security
}  // namespace android
