/*
 * Copyright 2021, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "android.hardware.security.keymint-impl"
#include "MicrodroidKeyMintDevice.h"

#include <aidl/android/hardware/security/keymint/ErrorCode.h>
#include <android-base/logging.h>
#include <keymaster/android_keymaster.h>
#include <keymaster/contexts/pure_soft_keymaster_context.h>
#include <keymaster/keymaster_configuration.h>

#include "AndroidKeyMintOperation.h"
#include "KeyMintUtils.h"

namespace aidl::android::hardware::security::keymint {

using namespace keymaster; // NOLINT(google-build-using-namespace)

using km_utils::authToken2AidlVec;
using km_utils::kmBlob2vector;
using km_utils::kmError2ScopedAStatus;
using km_utils::kmParam2Aidl;
using km_utils::KmParamSet;
using km_utils::kmParamSet2Aidl;
using km_utils::legacy_enum_conversion;
using secureclock::TimeStampToken;

namespace {

vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecurityLevel,
                                                     const AuthorizationSet& requestParams,
                                                     const AuthorizationSet& sw_enforced,
                                                     const AuthorizationSet& hw_enforced,
                                                     bool include_keystore_enforced = true) {
    KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};

    if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
        // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
        keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
        if (include_keystore_enforced) {
            // Put all the software authorizations in the keystore list.
            KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
                                                kmParamSet2Aidl(sw_enforced)};
            return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
        } else {
            return {std::move(keyMintEnforced)};
        }
    }

    KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
    CHECK(hw_enforced.empty()) << "Hardware-enforced list is non-empty for pure SW KeyMint";

    // This is a pure software implementation, so all tags are in sw_enforced.
    // We need to walk through the SW-enforced list and figure out which tags to
    // return in the software list and which in the keystore list.

    for (auto& entry : sw_enforced) {
        switch (entry.tag) {
            /* Invalid and unused */
            case KM_TAG_ECIES_SINGLE_HASH_MODE:
            case KM_TAG_INVALID:
            case KM_TAG_KDF:
            case KM_TAG_ROLLBACK_RESISTANCE:
                CHECK(false) << "We shouldn't see tag " << entry.tag;
                break;

            /* Unimplemented */
            case KM_TAG_ALLOW_WHILE_ON_BODY:
            case KM_TAG_BOOTLOADER_ONLY:
            case KM_TAG_EARLY_BOOT_ONLY:
            case KM_TAG_ROLLBACK_RESISTANT:
            case KM_TAG_STORAGE_KEY:
            case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
            case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
                break;

            /* Keystore-enforced if not locally generated. */
            case KM_TAG_CREATION_DATETIME:
                // A KeyMaster implementation is required to add this tag to generated/imported
                // keys. A KeyMint implementation is not required to create this tag, only to echo
                // it back if it was included in the key generation/import request.
                if (requestParams.Contains(KM_TAG_CREATION_DATETIME)) {
                    keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
                }
                break;

            /* Disallowed in KeyCharacteristics */
            case KM_TAG_APPLICATION_DATA:
            case KM_TAG_ATTESTATION_APPLICATION_ID:
                break;

            /* Not key characteristics */
            case KM_TAG_ASSOCIATED_DATA:
            case KM_TAG_ATTESTATION_CHALLENGE:
            case KM_TAG_ATTESTATION_ID_BRAND:
            case KM_TAG_ATTESTATION_ID_DEVICE:
            case KM_TAG_ATTESTATION_ID_IMEI:
            case KM_TAG_ATTESTATION_ID_MANUFACTURER:
            case KM_TAG_ATTESTATION_ID_MEID:
            case KM_TAG_ATTESTATION_ID_MODEL:
            case KM_TAG_ATTESTATION_ID_PRODUCT:
            case KM_TAG_ATTESTATION_ID_SERIAL:
            case KM_TAG_AUTH_TOKEN:
            case KM_TAG_CERTIFICATE_SERIAL:
            case KM_TAG_CERTIFICATE_SUBJECT:
            case KM_TAG_CERTIFICATE_NOT_AFTER:
            case KM_TAG_CERTIFICATE_NOT_BEFORE:
            case KM_TAG_CONFIRMATION_TOKEN:
            case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
            case KM_TAG_IDENTITY_CREDENTIAL_KEY:
            case KM_TAG_MAC_LENGTH:
            case KM_TAG_NONCE:
            case KM_TAG_RESET_SINCE_ID_ROTATION:
            case KM_TAG_ROOT_OF_TRUST:
            case KM_TAG_UNIQUE_ID:
                break;

            /* KeyMint-enforced */
            case KM_TAG_ALGORITHM:
            case KM_TAG_APPLICATION_ID:
            case KM_TAG_AUTH_TIMEOUT:
            case KM_TAG_BLOB_USAGE_REQUIREMENTS:
            case KM_TAG_BLOCK_MODE:
            case KM_TAG_BOOT_PATCHLEVEL:
            case KM_TAG_CALLER_NONCE:
            case KM_TAG_DIGEST:
            case KM_TAG_EC_CURVE:
            case KM_TAG_EXPORTABLE:
            case KM_TAG_INCLUDE_UNIQUE_ID:
            case KM_TAG_KEY_SIZE:
            case KM_TAG_MAX_USES_PER_BOOT:
            case KM_TAG_MIN_MAC_LENGTH:
            case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
            case KM_TAG_NO_AUTH_REQUIRED:
            case KM_TAG_ORIGIN:
            case KM_TAG_OS_PATCHLEVEL:
            case KM_TAG_OS_VERSION:
            case KM_TAG_PADDING:
            case KM_TAG_PURPOSE:
            case KM_TAG_RSA_OAEP_MGF_DIGEST:
            case KM_TAG_RSA_PUBLIC_EXPONENT:
            case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
            case KM_TAG_USER_AUTH_TYPE:
            case KM_TAG_USER_SECURE_ID:
            case KM_TAG_VENDOR_PATCHLEVEL:
                keyMintEnforced.authorizations.push_back(kmParam2Aidl(entry));
                break;

            /* Keystore-enforced */
            case KM_TAG_ACTIVE_DATETIME:
            case KM_TAG_ALL_APPLICATIONS:
            case KM_TAG_ALL_USERS:
            case KM_TAG_MAX_BOOT_LEVEL:
            case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
            case KM_TAG_USAGE_EXPIRE_DATETIME:
            case KM_TAG_USER_ID:
            case KM_TAG_USAGE_COUNT_LIMIT:
                keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
                break;
        }
    }

    vector<KeyCharacteristics> retval;
    retval.reserve(2);
    if (!keyMintEnforced.authorizations.empty()) retval.push_back(std::move(keyMintEnforced));
    if (include_keystore_enforced && !keystoreEnforced.authorizations.empty()) {
        retval.push_back(std::move(keystoreEnforced));
    }

    return retval;
}

Certificate convertCertificate(const keymaster_blob_t& cert) {
    return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
}

vector<Certificate> convertCertificateChain(const CertificateChain& chain) {
    vector<Certificate> retval;
    retval.reserve(chain.entry_count);
    std::transform(chain.begin(), chain.end(), std::back_inserter(retval), convertCertificate);
    return retval;
}

void addClientAndAppData(const std::vector<uint8_t>& appId, const std::vector<uint8_t>& appData,
                         ::keymaster::AuthorizationSet* params) {
    params->Clear();
    if (appId.size()) {
        params->push_back(::keymaster::TAG_APPLICATION_ID, appId.data(), appId.size());
    }
    if (appData.size()) {
        params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
    }
}

} // namespace

constexpr size_t kOperationTableSize = 16;

MicrodroidKeyMintDevice::MicrodroidKeyMintDevice(SecurityLevel securityLevel)
      : impl_(new ::keymaster::AndroidKeymaster(
                [&]() -> auto {
                    auto context =
                            new PureSoftKeymasterContext(KmVersion::KEYMINT_1,
                                                         static_cast<keymaster_security_level_t>(
                                                                 securityLevel));
                    context->SetSystemVersion(::keymaster::GetOsVersion(),
                                              ::keymaster::GetOsPatchlevel());
                    return context;
                }(),
                kOperationTableSize)),
        securityLevel_(securityLevel) {}

MicrodroidKeyMintDevice::~MicrodroidKeyMintDevice() {}

ScopedAStatus MicrodroidKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
    info->versionNumber = 1;
    info->securityLevel = securityLevel_;
    info->keyMintName = "FakeKeyMintDevice";
    info->keyMintAuthorName = "Google";
    info->timestampTokenRequired = false;
    return ScopedAStatus::ok();
}

ScopedAStatus MicrodroidKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
    if (data.size() == 0) {
        return ScopedAStatus::ok();
    }

    AddEntropyRequest request(impl_->message_version());
    request.random_data.Reinitialize(data.data(), data.size());

    AddEntropyResponse response(impl_->message_version());
    impl_->AddRngEntropy(request, &response);

    return kmError2ScopedAStatus(response.error);
}

ScopedAStatus MicrodroidKeyMintDevice::generateKey(const vector<KeyParameter>& keyParams,
                                                   const optional<AttestationKey>& attestationKey,
                                                   KeyCreationResult* creationResult) {
    GenerateKeyRequest request(impl_->message_version());
    request.key_description.Reinitialize(KmParamSet(keyParams));
    if (attestationKey) {
        request.attestation_signing_key_blob =
                KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
        request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
        request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
                                               attestationKey->issuerSubjectName.size());
    }

    GenerateKeyResponse response(impl_->message_version());
    impl_->GenerateKey(request, &response);

    if (response.error != KM_ERROR_OK) {
        // Note a key difference between this current aidl and previous hal, is
        // that hal returns void where as aidl returns the error status.  If
        // aidl returns error, then aidl will not return any change you may make
        // to the out parameters.  This is quite different from hal where all
        // output variable can be modified due to hal returning void.
        //
        // So the caller need to be aware not to expect aidl functions to clear
        // the output variables for you in case of error.  If you left some
        // wrong data set in the out parameters, they will stay there.
        return kmError2ScopedAStatus(response.error);
    }

    creationResult->keyBlob = kmBlob2vector(response.key_blob);
    creationResult->keyCharacteristics =
            convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
                                      response.enforced);
    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
    return ScopedAStatus::ok();
}

ScopedAStatus MicrodroidKeyMintDevice::importKey(const vector<KeyParameter>& keyParams,
                                                 KeyFormat keyFormat,
                                                 const vector<uint8_t>& keyData,
                                                 const optional<AttestationKey>& attestationKey,
                                                 KeyCreationResult* creationResult) {
    ImportKeyRequest request(impl_->message_version());
    request.key_description.Reinitialize(KmParamSet(keyParams));
    request.key_format = legacy_enum_conversion(keyFormat);
    request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
    if (attestationKey) {
        request.attestation_signing_key_blob =
                KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
        request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
        request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
                                               attestationKey->issuerSubjectName.size());
    }

    ImportKeyResponse response(impl_->message_version());
    impl_->ImportKey(request, &response);

    if (response.error != KM_ERROR_OK) {
        return kmError2ScopedAStatus(response.error);
    }

    creationResult->keyBlob = kmBlob2vector(response.key_blob);
    creationResult->keyCharacteristics =
            convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
                                      response.enforced);
    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);

    return ScopedAStatus::ok();
}

ScopedAStatus MicrodroidKeyMintDevice::importWrappedKey(
        const vector<uint8_t>& wrappedKeyData,        //
        const vector<uint8_t>& wrappingKeyBlob,       //
        const vector<uint8_t>& maskingKey,            //
        const vector<KeyParameter>& unwrappingParams, //
        int64_t passwordSid, int64_t biometricSid,    //
        KeyCreationResult* creationResult) {
    ImportWrappedKeyRequest request(impl_->message_version());
    request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
    request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
    request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
    request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
    request.password_sid = static_cast<uint64_t>(passwordSid);
    request.biometric_sid = static_cast<uint64_t>(biometricSid);

    ImportWrappedKeyResponse response(impl_->message_version());
    impl_->ImportWrappedKey(request, &response);

    if (response.error != KM_ERROR_OK) {
        return kmError2ScopedAStatus(response.error);
    }

    creationResult->keyBlob = kmBlob2vector(response.key_blob);
    creationResult->keyCharacteristics =
            convertKeyCharacteristics(securityLevel_, request.additional_params,
                                      response.unenforced, response.enforced);
    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);

    return ScopedAStatus::ok();
}

ScopedAStatus MicrodroidKeyMintDevice::upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
                                                  const vector<KeyParameter>& upgradeParams,
                                                  vector<uint8_t>* keyBlob) {
    UpgradeKeyRequest request(impl_->message_version());
    request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
    request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));

    UpgradeKeyResponse response(impl_->message_version());
    impl_->UpgradeKey(request, &response);

    if (response.error != KM_ERROR_OK) {
        return kmError2ScopedAStatus(response.error);
    }

    *keyBlob = kmBlob2vector(response.upgraded_key);
    return ScopedAStatus::ok();
}

ScopedAStatus MicrodroidKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
    DeleteKeyRequest request(impl_->message_version());
    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());

    DeleteKeyResponse response(impl_->message_version());
    impl_->DeleteKey(request, &response);

    return kmError2ScopedAStatus(response.error);
}

ScopedAStatus MicrodroidKeyMintDevice::deleteAllKeys() {
    // There's nothing to be done to delete software key blobs.
    DeleteAllKeysRequest request(impl_->message_version());
    DeleteAllKeysResponse response(impl_->message_version());
    impl_->DeleteAllKeys(request, &response);

    return kmError2ScopedAStatus(response.error);
}

ScopedAStatus MicrodroidKeyMintDevice::destroyAttestationIds() {
    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
}

ScopedAStatus MicrodroidKeyMintDevice::begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
                                             const vector<KeyParameter>& params,
                                             const optional<HardwareAuthToken>& authToken,
                                             BeginResult* result) {
    BeginOperationRequest request(impl_->message_version());
    request.purpose = legacy_enum_conversion(purpose);
    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
    request.additional_params.Reinitialize(KmParamSet(params));

    vector<uint8_t> vector_token = authToken2AidlVec(authToken);
    request.additional_params.push_back(TAG_AUTH_TOKEN,
                                        reinterpret_cast<uint8_t*>(vector_token.data()),
                                        vector_token.size());

    BeginOperationResponse response(impl_->message_version());
    impl_->BeginOperation(request, &response);

    if (response.error != KM_ERROR_OK) {
        return kmError2ScopedAStatus(response.error);
    }

    result->params = kmParamSet2Aidl(response.output_params);
    result->challenge = response.op_handle;
    result->operation =
            ndk::SharedRefBase::make<AndroidKeyMintOperation>(impl_, response.op_handle);
    return ScopedAStatus::ok();
}

ScopedAStatus MicrodroidKeyMintDevice::deviceLocked(
        bool passwordOnly, const std::optional<secureclock::TimeStampToken>& timestampToken) {
    DeviceLockedRequest request(impl_->message_version());
    request.passwordOnly = passwordOnly;
    if (timestampToken.has_value()) {
        request.token.challenge = timestampToken->challenge;
        request.token.mac = {timestampToken->mac.data(), timestampToken->mac.size()};
        request.token.timestamp = timestampToken->timestamp.milliSeconds;
    }
    DeviceLockedResponse response = impl_->DeviceLocked(request);
    return kmError2ScopedAStatus(response.error);
}

ScopedAStatus MicrodroidKeyMintDevice::earlyBootEnded() {
    EarlyBootEndedResponse response = impl_->EarlyBootEnded();
    return kmError2ScopedAStatus(response.error);
}

ScopedAStatus MicrodroidKeyMintDevice::convertStorageKeyToEphemeral(
        const std::vector<uint8_t>& /* storageKeyBlob */,
        std::vector<uint8_t>* /* ephemeralKeyBlob */) {
    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
}

ScopedAStatus MicrodroidKeyMintDevice::getKeyCharacteristics(
        const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
        const std::vector<uint8_t>& appData, std::vector<KeyCharacteristics>* keyCharacteristics) {
    GetKeyCharacteristicsRequest request(impl_->message_version());
    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
    addClientAndAppData(appId, appData, &request.additional_params);

    GetKeyCharacteristicsResponse response(impl_->message_version());
    impl_->GetKeyCharacteristics(request, &response);

    if (response.error != KM_ERROR_OK) {
        return kmError2ScopedAStatus(response.error);
    }

    AuthorizationSet emptySet;
    *keyCharacteristics = convertKeyCharacteristics(securityLevel_, emptySet, response.unenforced,
                                                    response.enforced,
                                                    /* include_keystore_enforced = */ false);

    return ScopedAStatus::ok();
}

IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel) {
    return ::new MicrodroidKeyMintDevice(securityLevel);
}

} // namespace aidl::android::hardware::security::keymint
