/*
 * 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(const AuthorizationSet& requestParams,
                                                     const AuthorizationSet& sw_enforced,
                                                     const AuthorizationSet& hw_enforced,
                                                     bool include_keystore_enforced = true) {
    KeyCharacteristics keyMintEnforced{SecurityLevel::SOFTWARE, {}};
    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()
      : impl_(new ::keymaster::AndroidKeymaster(
                [&]() -> auto {
                    auto context = new PureSoftKeymasterContext(KmVersion::KEYMINT_1,
                                                                KM_SECURITY_LEVEL_SOFTWARE);
                    context->SetSystemVersion(::keymaster::GetOsVersion(),
                                              ::keymaster::GetOsPatchlevel());
                    return context;
                }(),
                kOperationTableSize)) {}

MicrodroidKeyMintDevice::~MicrodroidKeyMintDevice() {}

ScopedAStatus MicrodroidKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
    info->versionNumber = 1;
    info->securityLevel = SecurityLevel::SOFTWARE;
    info->keyMintName = "MicrodroidKeyMintDevice";
    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(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(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(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>&) {
    // There's nothing to be done to delete software key blobs.
    return kmError2ScopedAStatus(KM_ERROR_OK);
}

ScopedAStatus MicrodroidKeyMintDevice::deleteAllKeys() {
    // There's nothing to be done to delete software key blobs.
    return kmError2ScopedAStatus(KM_ERROR_OK);
}

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, const std::optional<secureclock::TimeStampToken>&) {
    // Microdroid doesn't yet have a concept of a locked device.
    return kmError2ScopedAStatus(KM_ERROR_OK);
}

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

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(emptySet, response.unenforced, response.enforced,
                                      /* include_keystore_enforced = */ false);

    return ScopedAStatus::ok();
}

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