/*
 * Copyright 2015 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.
 */

#include <keymaster/soft_keymaster_device.h>

#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <algorithm>

#include <type_traits>

#include <openssl/x509.h>

#include <hardware/keymaster1.h>
#define LOG_TAG "SoftKeymasterDevice"
#include <cutils/log.h>

#include <keymaster/android_keymaster.h>
#include <keymaster/android_keymaster_messages.h>
#include <keymaster/authorization_set.h>
#include <keymaster/soft_keymaster_context.h>
#include <keymaster/soft_keymaster_logger.h>

#include "openssl_utils.h"

struct keystore_module soft_keymaster_device_module = {
    .common =
        {
            .tag = HARDWARE_MODULE_TAG,
            .module_api_version = KEYMASTER_MODULE_API_VERSION_1_0,
            .hal_api_version = HARDWARE_HAL_API_VERSION,
            .id = KEYSTORE_HARDWARE_MODULE_ID,
            .name = "OpenSSL-based SoftKeymaster HAL",
            .author = "The Android Open Source Project",
            .methods = NULL,
            .dso = 0,
            .reserved = {},
        },
};

namespace keymaster {

const size_t kOperationTableSize = 16;

typedef std::map<std::pair<keymaster_algorithm_t, keymaster_purpose_t>,
                 std::vector<keymaster_digest_t>> DigestMap;

template <typename T> std::vector<T> make_vector(const T* array, size_t len) {
    return std::vector<T>(array, array + len);
}

static keymaster_error_t add_digests(keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
                                     keymaster_purpose_t purpose, DigestMap* map) {
    auto key = std::make_pair(algorithm, purpose);

    keymaster_digest_t* digests;
    size_t digests_length;
    keymaster_error_t error =
        dev->get_supported_digests(dev, algorithm, purpose, &digests, &digests_length);
    if (error != KM_ERROR_OK) {
        LOG_E("Error %d getting supported digests from keymaster1 device", error);
        return error;
    }
    std::unique_ptr<keymaster_digest_t, Malloc_Delete> digests_deleter(digests);

    (*map)[key] = make_vector(digests, digests_length);
    return KM_ERROR_OK;
}

static keymaster_error_t map_digests(keymaster1_device_t* dev, DigestMap* map) {
    map->clear();

    keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC};
    keymaster_purpose_t sig_purposes[] = {KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY};
    for (auto algorithm : sig_algorithms)
        for (auto purpose : sig_purposes) {
            keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
            if (error != KM_ERROR_OK)
                return error;
        }

    keymaster_algorithm_t crypt_algorithms[] = {KM_ALGORITHM_RSA};
    keymaster_purpose_t crypt_purposes[] = {KM_PURPOSE_ENCRYPT, KM_PURPOSE_DECRYPT};
    for (auto algorithm : crypt_algorithms)
        for (auto purpose : crypt_purposes) {
            keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
            if (error != KM_ERROR_OK)
                return error;
        }

    return KM_ERROR_OK;
}

SoftKeymasterDevice::SoftKeymasterDevice()
    : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr),
      context_(new SoftKeymasterContext),
      impl_(new AndroidKeymaster(context_, kOperationTableSize)) {
    static_assert(std::is_standard_layout<SoftKeymasterDevice>::value,
                  "SoftKeymasterDevice must be standard layout");
    static_assert(offsetof(SoftKeymasterDevice, device_) == 0,
                  "device_ must be the first member of SoftKeymasterDevice");
    static_assert(offsetof(SoftKeymasterDevice, device_.common) == 0,
                  "common must be the first member of keymaster_device");
    LOG_I("Creating device", 0);
    LOG_D("Device address: %p", this);

    initialize_device_struct(KEYMASTER_SOFTWARE_ONLY | KEYMASTER_BLOBS_ARE_STANDALONE |
                             KEYMASTER_SUPPORTS_EC);
}

SoftKeymasterDevice::SoftKeymasterDevice(SoftKeymasterContext* context)
    : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr), context_(context),
      impl_(new AndroidKeymaster(context_, kOperationTableSize)) {
    static_assert(std::is_standard_layout<SoftKeymasterDevice>::value,
                  "SoftKeymasterDevice must be standard layout");
    static_assert(offsetof(SoftKeymasterDevice, device_) == 0,
                  "device_ must be the first member of SoftKeymasterDevice");
    static_assert(offsetof(SoftKeymasterDevice, device_.common) == 0,
                  "common must be the first member of keymaster_device");
    LOG_I("Creating test device", 0);
    LOG_D("Device address: %p", this);

    initialize_device_struct(KEYMASTER_SOFTWARE_ONLY | KEYMASTER_BLOBS_ARE_STANDALONE |
                             KEYMASTER_SUPPORTS_EC);
}

keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster0_device_t* keymaster0_device) {
    assert(keymaster0_device);
    LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster0", 0);

    if (!context_)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    keymaster_error_t error = context_->SetHardwareDevice(keymaster0_device);
    if (error != KM_ERROR_OK)
        return error;

    initialize_device_struct(keymaster0_device->flags);

    module_name_ = device_.common.module->name;
    module_name_.append("(Wrapping ");
    module_name_.append(keymaster0_device->common.module->name);
    module_name_.append(")");

    updated_module_ = *device_.common.module;
    updated_module_.name = module_name_.c_str();

    device_.common.module = &updated_module_;

    wrapped_km0_device_ = keymaster0_device;
    wrapped_km1_device_ = nullptr;
    return KM_ERROR_OK;
}

keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster1_device_t* keymaster1_device) {
    assert(keymaster1_device);
    LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster1", 0);

    if (!context_)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    keymaster_error_t error = map_digests(keymaster1_device, &km1_device_digests_);
    if (error != KM_ERROR_OK)
        return error;

    error = context_->SetHardwareDevice(keymaster1_device);
    if (error != KM_ERROR_OK)
        return error;

    initialize_device_struct(keymaster1_device->flags);

    module_name_ = device_.common.module->name;
    module_name_.append(" (Wrapping ");
    module_name_.append(keymaster1_device->common.module->name);
    module_name_.append(")");

    updated_module_ = *device_.common.module;
    updated_module_.name = module_name_.c_str();

    device_.common.module = &updated_module_;

    wrapped_km0_device_ = nullptr;
    wrapped_km1_device_ = keymaster1_device;
    return KM_ERROR_OK;
}

bool SoftKeymasterDevice::Keymaster1DeviceIsGood() {
    std::vector<keymaster_digest_t> expected_rsa_digests = {
        KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,     KM_DIGEST_SHA_2_224,
        KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
    std::vector<keymaster_digest_t> expected_ec_digests = {
        KM_DIGEST_NONE,      KM_DIGEST_SHA1,      KM_DIGEST_SHA_2_224,
        KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};

    for (auto& entry : km1_device_digests_) {
        if (entry.first.first == KM_ALGORITHM_RSA)
            if (!std::is_permutation(entry.second.begin(), entry.second.end(),
                                     expected_rsa_digests.begin()))
                return false;
        if (entry.first.first == KM_ALGORITHM_EC)
            if (!std::is_permutation(entry.second.begin(), entry.second.end(),
                                     expected_ec_digests.begin()))
                return false;
    }
    return true;
}

void SoftKeymasterDevice::initialize_device_struct(uint32_t flags) {
    memset(&device_, 0, sizeof(device_));

    device_.common.tag = HARDWARE_DEVICE_TAG;
    device_.common.version = 1;
    device_.common.module = reinterpret_cast<hw_module_t*>(&soft_keymaster_device_module);
    device_.common.close = &close_device;

    device_.flags = flags;

    // keymaster0 APIs
    device_.generate_keypair = nullptr;
    device_.import_keypair = nullptr;
    device_.get_keypair_public = nullptr;
    device_.delete_keypair = nullptr;
    device_.delete_all = nullptr;
    device_.sign_data = nullptr;
    device_.verify_data = nullptr;

    // keymaster1 APIs
    device_.get_supported_algorithms = get_supported_algorithms;
    device_.get_supported_block_modes = get_supported_block_modes;
    device_.get_supported_padding_modes = get_supported_padding_modes;
    device_.get_supported_digests = get_supported_digests;
    device_.get_supported_import_formats = get_supported_import_formats;
    device_.get_supported_export_formats = get_supported_export_formats;
    device_.add_rng_entropy = add_rng_entropy;
    device_.generate_key = generate_key;
    device_.get_key_characteristics = get_key_characteristics;
    device_.import_key = import_key;
    device_.export_key = export_key;
    device_.delete_key = delete_key;
    device_.delete_all_keys = delete_all_keys;
    device_.begin = begin;
    device_.update = update;
    device_.finish = finish;
    device_.abort = abort;

    device_.context = NULL;
}

hw_device_t* SoftKeymasterDevice::hw_device() {
    return &device_.common;
}

keymaster1_device_t* SoftKeymasterDevice::keymaster_device() {
    return &device_;
}

static keymaster_key_characteristics_t* BuildCharacteristics(const AuthorizationSet& hw_enforced,
                                                             const AuthorizationSet& sw_enforced) {
    keymaster_key_characteristics_t* characteristics =
        reinterpret_cast<keymaster_key_characteristics_t*>(
            malloc(sizeof(keymaster_key_characteristics_t)));
    if (characteristics) {
        hw_enforced.CopyToParamSet(&characteristics->hw_enforced);
        sw_enforced.CopyToParamSet(&characteristics->sw_enforced);
    }
    return characteristics;
}

template <typename RequestType>
static void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
                                RequestType* request) {
    request->additional_params.Clear();
    if (client_id)
        request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
    if (app_data)
        request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
}

static inline SoftKeymasterDevice* convert_device(const keymaster1_device_t* dev) {
    return reinterpret_cast<SoftKeymasterDevice*>(const_cast<keymaster1_device_t*>(dev));
}

/* static */
int SoftKeymasterDevice::close_device(hw_device_t* dev) {
    delete reinterpret_cast<SoftKeymasterDevice*>(dev);
    return 0;
}

/* static */
keymaster_error_t SoftKeymasterDevice::get_supported_algorithms(const keymaster1_device_t* dev,
                                                                keymaster_algorithm_t** algorithms,
                                                                size_t* algorithms_length) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!algorithms || !algorithms_length)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->get_supported_algorithms(km1_dev, algorithms, algorithms_length);

    SupportedAlgorithmsRequest request;
    SupportedAlgorithmsResponse response;
    convert_device(dev)->impl_->SupportedAlgorithms(request, &response);
    if (response.error != KM_ERROR_OK) {
        LOG_E("get_supported_algorithms failed with %d", response.error);

        return response.error;
    }

    *algorithms_length = response.results_length;
    *algorithms =
        reinterpret_cast<keymaster_algorithm_t*>(malloc(*algorithms_length * sizeof(**algorithms)));
    if (!*algorithms)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    std::copy(response.results, response.results + response.results_length, *algorithms);
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::get_supported_block_modes(const keymaster1_device_t* dev,
                                                                 keymaster_algorithm_t algorithm,
                                                                 keymaster_purpose_t purpose,
                                                                 keymaster_block_mode_t** modes,
                                                                 size_t* modes_length) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!modes || !modes_length)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->get_supported_block_modes(km1_dev, algorithm, purpose, modes, modes_length);

    SupportedBlockModesRequest request;
    request.algorithm = algorithm;
    request.purpose = purpose;
    SupportedBlockModesResponse response;
    convert_device(dev)->impl_->SupportedBlockModes(request, &response);

    if (response.error != KM_ERROR_OK) {
        LOG_E("get_supported_block_modes failed with %d", response.error);

        return response.error;
    }

    *modes_length = response.results_length;
    *modes = reinterpret_cast<keymaster_block_mode_t*>(malloc(*modes_length * sizeof(**modes)));
    if (!*modes)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    std::copy(response.results, response.results + response.results_length, *modes);
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::get_supported_padding_modes(const keymaster1_device_t* dev,
                                                                   keymaster_algorithm_t algorithm,
                                                                   keymaster_purpose_t purpose,
                                                                   keymaster_padding_t** modes,
                                                                   size_t* modes_length) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!modes || !modes_length)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->get_supported_padding_modes(km1_dev, algorithm, purpose, modes,
                                                    modes_length);

    SupportedPaddingModesRequest request;
    request.algorithm = algorithm;
    request.purpose = purpose;
    SupportedPaddingModesResponse response;
    convert_device(dev)->impl_->SupportedPaddingModes(request, &response);

    if (response.error != KM_ERROR_OK) {
        LOG_E("get_supported_padding_modes failed with %d", response.error);
        return response.error;
    }

    *modes_length = response.results_length;
    *modes = reinterpret_cast<keymaster_padding_t*>(malloc(*modes_length * sizeof(**modes)));
    if (!*modes)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    std::copy(response.results, response.results + response.results_length, *modes);
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::get_supported_digests(const keymaster1_device_t* dev,
                                                             keymaster_algorithm_t algorithm,
                                                             keymaster_purpose_t purpose,
                                                             keymaster_digest_t** digests,
                                                             size_t* digests_length) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!digests || !digests_length)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->get_supported_digests(km1_dev, algorithm, purpose, digests, digests_length);

    SupportedDigestsRequest request;
    request.algorithm = algorithm;
    request.purpose = purpose;
    SupportedDigestsResponse response;
    convert_device(dev)->impl_->SupportedDigests(request, &response);

    if (response.error != KM_ERROR_OK) {
        LOG_E("get_supported_digests failed with %d", response.error);
        return response.error;
    }

    *digests_length = response.results_length;
    *digests = reinterpret_cast<keymaster_digest_t*>(malloc(*digests_length * sizeof(**digests)));
    if (!*digests)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    std::copy(response.results, response.results + response.results_length, *digests);
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::get_supported_import_formats(
    const keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
    keymaster_key_format_t** formats, size_t* formats_length) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!formats || !formats_length)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->get_supported_import_formats(km1_dev, algorithm, formats, formats_length);

    SupportedImportFormatsRequest request;
    request.algorithm = algorithm;
    SupportedImportFormatsResponse response;
    convert_device(dev)->impl_->SupportedImportFormats(request, &response);

    if (response.error != KM_ERROR_OK) {
        LOG_E("get_supported_import_formats failed with %d", response.error);
        return response.error;
    }

    *formats_length = response.results_length;
    *formats =
        reinterpret_cast<keymaster_key_format_t*>(malloc(*formats_length * sizeof(**formats)));
    if (!*formats)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    std::copy(response.results, response.results + response.results_length, *formats);
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::get_supported_export_formats(
    const keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
    keymaster_key_format_t** formats, size_t* formats_length) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!formats || !formats_length)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->get_supported_export_formats(km1_dev, algorithm, formats, formats_length);

    SupportedExportFormatsRequest request;
    request.algorithm = algorithm;
    SupportedExportFormatsResponse response;
    convert_device(dev)->impl_->SupportedExportFormats(request, &response);

    if (response.error != KM_ERROR_OK) {
        LOG_E("get_supported_export_formats failed with %d", response.error);
        return response.error;
    }

    *formats_length = response.results_length;
    *formats =
        reinterpret_cast<keymaster_key_format_t*>(malloc(*formats_length * sizeof(**formats)));
    if (!*formats)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    std::copy(response.results, response.results + *formats_length, *formats);
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster1_device_t* dev,
                                                       const uint8_t* data, size_t data_length) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->add_rng_entropy(km1_dev, data, data_length);

    AddEntropyRequest request;
    request.random_data.Reinitialize(data, data_length);
    AddEntropyResponse response;
    convert_device(dev)->impl_->AddRngEntropy(request, &response);
    if (response.error != KM_ERROR_OK)
        LOG_E("add_rng_entropy failed with %d", response.error);
    return response.error;
}

template <typename Collection, typename Value> bool contains(const Collection& c, const Value& v) {
    return std::find(c.begin(), c.end(), v) != c.end();
}

bool SoftKeymasterDevice::FindUnsupportedDigest(keymaster_algorithm_t algorithm,
                                                keymaster_purpose_t purpose,
                                                const AuthorizationSet& params,
                                                keymaster_digest_t* unsupported) const {
    assert(wrapped_km1_device_);

    auto supported_digests = km1_device_digests_.find(std::make_pair(algorithm, purpose));
    if (supported_digests == km1_device_digests_.end())
        // Invalid algorith/purpose pair (e.g. EC encrypt).  Let the error be handled by HW module.
        return false;

    for (auto& entry : params)
        if (entry.tag == TAG_DIGEST)
            if (!contains(supported_digests->second, entry.enumerated)) {
                LOG_I("Digest %d requested but not supported by module %s", entry.enumerated,
                      wrapped_km1_device_->common.module->name);
                *unsupported = static_cast<keymaster_digest_t>(entry.enumerated);
                return true;
            }
    return false;
}

bool SoftKeymasterDevice::RequiresSoftwareDigesting(keymaster_algorithm_t algorithm,
                                                    keymaster_purpose_t purpose,
                                                    const AuthorizationSet& params) const {
    assert(wrapped_km1_device_);
    if (!wrapped_km1_device_)
        return true;

    switch (algorithm) {
    case KM_ALGORITHM_AES:
    case KM_ALGORITHM_HMAC:
        LOG_D("Not performing software digesting for algorithm %d", algorithm);
        return false;
    case KM_ALGORITHM_RSA:
    case KM_ALGORITHM_EC:
        break;
    }

    keymaster_digest_t unsupported;
    if (!FindUnsupportedDigest(algorithm, purpose, params, &unsupported)) {
        LOG_D("Requested digest(s) supported for algorithm %d and purpose %d", algorithm, purpose);
        return false;
    }

    return true;
}

bool SoftKeymasterDevice::KeyRequiresSoftwareDigesting(
    const AuthorizationSet& key_description) const {
    assert(wrapped_km1_device_);
    if (!wrapped_km1_device_)
        return true;

    keymaster_algorithm_t algorithm;
    if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
        // The hardware module will return an error during keygen.
        return false;
    }

    for (auto& entry : key_description)
        if (entry.tag == TAG_PURPOSE) {
            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(entry.enumerated);
            if (RequiresSoftwareDigesting(algorithm, purpose, key_description))
                return true;
        }

    return false;
}

/* static */
keymaster_error_t SoftKeymasterDevice::generate_key(
    const keymaster1_device_t* dev, const keymaster_key_param_set_t* params,
    keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t** characteristics) {
    if (!dev || !params)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!key_blob)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    SoftKeymasterDevice* sk_dev = convert_device(dev);

    GenerateKeyRequest request;
    request.key_description.Reinitialize(*params);

    keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
    if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description))
        return km1_dev->generate_key(km1_dev, params, key_blob, characteristics);

    GenerateKeyResponse response;
    sk_dev->impl_->GenerateKey(request, &response);
    if (response.error != KM_ERROR_OK)
        return response.error;

    key_blob->key_material_size = response.key_blob.key_material_size;
    uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(key_blob->key_material_size));
    if (!tmp)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    memcpy(tmp, response.key_blob.key_material, response.key_blob.key_material_size);
    key_blob->key_material = tmp;

    if (characteristics) {
        *characteristics = BuildCharacteristics(response.enforced, response.unenforced);
        if (!*characteristics)
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::get_key_characteristics(
    const keymaster1_device_t* dev, const keymaster_key_blob_t* key_blob,
    const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
    keymaster_key_characteristics_t** characteristics) {
    if (!dev || !key_blob || !key_blob->key_material)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!characteristics)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->get_key_characteristics(km1_dev, key_blob, client_id, app_data,
                                                characteristics);

    GetKeyCharacteristicsRequest request;
    request.SetKeyMaterial(*key_blob);
    AddClientAndAppData(client_id, app_data, &request);

    GetKeyCharacteristicsResponse response;
    convert_device(dev)->impl_->GetKeyCharacteristics(request, &response);
    if (response.error != KM_ERROR_OK)
        return response.error;

    *characteristics = BuildCharacteristics(response.enforced, response.unenforced);
    if (!*characteristics)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::import_key(
    const keymaster1_device_t* dev, const keymaster_key_param_set_t* params,
    keymaster_key_format_t key_format, const keymaster_blob_t* key_data,
    keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t** characteristics) {
    if (!params || !key_data)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!key_blob)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    SoftKeymasterDevice* sk_dev = convert_device(dev);

    ImportKeyRequest request;
    request.key_description.Reinitialize(*params);

    keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
    if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description))
        return km1_dev->import_key(km1_dev, params, key_format, key_data, key_blob,
                                   characteristics);

    *characteristics = nullptr;

    request.key_format = key_format;
    request.SetKeyMaterial(key_data->data, key_data->data_length);

    ImportKeyResponse response;
    convert_device(dev)->impl_->ImportKey(request, &response);
    if (response.error != KM_ERROR_OK)
        return response.error;

    key_blob->key_material_size = response.key_blob.key_material_size;
    key_blob->key_material = reinterpret_cast<uint8_t*>(malloc(key_blob->key_material_size));
    if (!key_blob->key_material)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    memcpy(const_cast<uint8_t*>(key_blob->key_material), response.key_blob.key_material,
           response.key_blob.key_material_size);

    if (characteristics) {
        *characteristics = BuildCharacteristics(response.enforced, response.unenforced);
        if (!*characteristics)
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::export_key(const keymaster1_device_t* dev,
                                                  keymaster_key_format_t export_format,
                                                  const keymaster_key_blob_t* key_to_export,
                                                  const keymaster_blob_t* client_id,
                                                  const keymaster_blob_t* app_data,
                                                  keymaster_blob_t* export_data) {
    if (!key_to_export || !key_to_export->key_material)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!export_data)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev)
        return km1_dev->export_key(km1_dev, export_format, key_to_export, client_id, app_data,
                                   export_data);

    export_data->data = nullptr;
    export_data->data_length = 0;

    ExportKeyRequest request;
    request.key_format = export_format;
    request.SetKeyMaterial(*key_to_export);
    AddClientAndAppData(client_id, app_data, &request);

    ExportKeyResponse response;
    convert_device(dev)->impl_->ExportKey(request, &response);
    if (response.error != KM_ERROR_OK)
        return response.error;

    export_data->data_length = response.key_data_length;
    uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(export_data->data_length));
    if (!tmp)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    memcpy(tmp, response.key_data, export_data->data_length);
    export_data->data = tmp;
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::delete_key(const struct keymaster1_device* dev,
                                                  const keymaster_key_blob_t* key) {
    if (!dev || !key || !key->key_material)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    KeymasterKeyBlob blob(*key);
    return convert_device(dev)->context_->DeleteKey(blob);
}

/* static */
keymaster_error_t SoftKeymasterDevice::delete_all_keys(const struct keymaster1_device* dev) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    return convert_device(dev)->context_->DeleteAllKeys();
}

static bool FindAlgorithm(const keymaster_key_param_set_t& params,
                          keymaster_algorithm_t* algorithm) {
    for (size_t i = 0; i < params.length; ++i)
        if (params.params[i].tag == KM_TAG_ALGORITHM) {
            *algorithm = static_cast<keymaster_algorithm_t>(params.params[i].enumerated);
            return true;
        }
    return false;
}

static keymaster_error_t GetAlgorithm(const keymaster1_device_t* dev,
                                      const keymaster_key_blob_t& key,
                                      const AuthorizationSet& in_params,
                                      keymaster_algorithm_t* algorithm) {
    keymaster_blob_t client_id = {nullptr, 0};
    keymaster_blob_t app_data = {nullptr, 0};
    keymaster_blob_t* client_id_ptr = nullptr;
    keymaster_blob_t* app_data_ptr = nullptr;
    if (in_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
        client_id_ptr = &client_id;
    if (in_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
        app_data_ptr = &app_data;

    keymaster_key_characteristics_t* characteristics;
    keymaster_error_t error =
        dev->get_key_characteristics(dev, &key, client_id_ptr, app_data_ptr, &characteristics);
    if (error != KM_ERROR_OK)
        return error;
    std::unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete>
        characteristics_deleter(characteristics);

    if (FindAlgorithm(characteristics->hw_enforced, algorithm))
        return KM_ERROR_OK;

    if (FindAlgorithm(characteristics->sw_enforced, algorithm))
        return KM_ERROR_OK;

    return KM_ERROR_INVALID_KEY_BLOB;
}

/* static */
keymaster_error_t SoftKeymasterDevice::begin(const keymaster1_device_t* dev,
                                             keymaster_purpose_t purpose,
                                             const keymaster_key_blob_t* key,
                                             const keymaster_key_param_set_t* in_params,
                                             keymaster_key_param_set_t* out_params,
                                             keymaster_operation_handle_t* operation_handle) {
    if (!key || !key->key_material)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!operation_handle)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev) {
        AuthorizationSet in_params_set(*in_params);

        keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
        keymaster_error_t error = GetAlgorithm(km1_dev, *key, in_params_set, &algorithm);
        if (error != KM_ERROR_OK)
            return error;

        if (!convert_device(dev)->RequiresSoftwareDigesting(algorithm, purpose, in_params_set)) {
            LOG_D("Operation supported by %s, passing through to keymaster1 module",
                  km1_dev->common.module->name);
            return km1_dev->begin(km1_dev, purpose, key, in_params, out_params, operation_handle);
        }
        LOG_I("Doing software digesting for keymaster1 module %s", km1_dev->common.module->name);
    }

    if (out_params) {
        out_params->params = nullptr;
        out_params->length = 0;
    }

    BeginOperationRequest request;
    request.purpose = purpose;
    request.SetKeyMaterial(*key);
    request.additional_params.Reinitialize(*in_params);

    BeginOperationResponse response;
    convert_device(dev)->impl_->BeginOperation(request, &response);
    if (response.error != KM_ERROR_OK)
        return response.error;

    if (response.output_params.size() > 0) {
        if (out_params)
            response.output_params.CopyToParamSet(out_params);
        else
            return KM_ERROR_OUTPUT_PARAMETER_NULL;
    }

    *operation_handle = response.op_handle;
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::update(const keymaster1_device_t* dev,
                                              keymaster_operation_handle_t operation_handle,
                                              const keymaster_key_param_set_t* in_params,
                                              const keymaster_blob_t* input, size_t* input_consumed,
                                              keymaster_key_param_set_t* out_params,
                                              keymaster_blob_t* output) {
    if (!input)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!input_consumed)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
        // This operation is being handled by km1_dev (or doesn't exist).  Pass it through to
        // km1_dev.  Otherwise, we'll use the software AndroidKeymaster, which may delegate to
        // km1_dev after doing necessary digesting.
        return km1_dev->update(km1_dev, operation_handle, in_params, input, input_consumed,
                               out_params, output);
    }

    if (out_params) {
        out_params->params = nullptr;
        out_params->length = 0;
    }
    if (output) {
        output->data = nullptr;
        output->data_length = 0;
    }

    UpdateOperationRequest request;
    request.op_handle = operation_handle;
    if (input)
        request.input.Reinitialize(input->data, input->data_length);
    if (in_params)
        request.additional_params.Reinitialize(*in_params);

    UpdateOperationResponse response;
    convert_device(dev)->impl_->UpdateOperation(request, &response);
    if (response.error != KM_ERROR_OK)
        return response.error;

    if (response.output_params.size() > 0) {
        if (out_params)
            response.output_params.CopyToParamSet(out_params);
        else
            return KM_ERROR_OUTPUT_PARAMETER_NULL;
    }

    *input_consumed = response.input_consumed;
    if (output) {
        output->data_length = response.output.available_read();
        uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
        if (!tmp)
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
        memcpy(tmp, response.output.peek_read(), output->data_length);
        output->data = tmp;
    } else if (response.output.available_read() > 0) {
        return KM_ERROR_OUTPUT_PARAMETER_NULL;
    }
    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::finish(const keymaster1_device_t* dev,
                                              keymaster_operation_handle_t operation_handle,
                                              const keymaster_key_param_set_t* params,
                                              const keymaster_blob_t* signature,
                                              keymaster_key_param_set_t* out_params,
                                              keymaster_blob_t* output) {
    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
        // This operation is being handled by km1_dev (or doesn't exist).  Pass it through to
        // km1_dev.  Otherwise, we'll use the software AndroidKeymaster, which may delegate to
        // km1_dev after doing necessary digesting.
        return km1_dev->finish(km1_dev, operation_handle, params, signature, out_params, output);
    }

    if (out_params) {
        out_params->params = nullptr;
        out_params->length = 0;
    }

    if (output) {
        output->data = nullptr;
        output->data_length = 0;
    }

    FinishOperationRequest request;
    request.op_handle = operation_handle;
    if (signature && signature->data_length > 0)
        request.signature.Reinitialize(signature->data, signature->data_length);
    request.additional_params.Reinitialize(*params);

    FinishOperationResponse response;
    convert_device(dev)->impl_->FinishOperation(request, &response);
    if (response.error != KM_ERROR_OK)
        return response.error;

    if (response.output_params.size() > 0) {
        if (out_params)
            response.output_params.CopyToParamSet(out_params);
        else
            return KM_ERROR_OUTPUT_PARAMETER_NULL;
    }
    if (output) {
        output->data_length = response.output.available_read();
        uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
        if (!tmp)
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
        memcpy(tmp, response.output.peek_read(), output->data_length);
        output->data = tmp;
    } else if (response.output.available_read() > 0) {
        return KM_ERROR_OUTPUT_PARAMETER_NULL;
    }

    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::abort(const keymaster1_device_t* dev,
                                             keymaster_operation_handle_t operation_handle) {
    const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
    if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
        // This operation is being handled by km1_dev (or doesn't exist).  Pass it through to
        // km1_dev.  Otherwise, we'll use the software AndroidKeymaster, which may delegate to
        // km1_dev.
        return km1_dev->abort(km1_dev, operation_handle);
    }

    AbortOperationRequest request;
    request.op_handle = operation_handle;
    AbortOperationResponse response;
    convert_device(dev)->impl_->AbortOperation(request, &response);
    return response.error;
}

/* static */
void SoftKeymasterDevice::StoreDefaultNewKeyParams(keymaster_algorithm_t algorithm,
                                                   AuthorizationSet* auth_set) {
    auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_SIGN);
    auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_VERIFY);
    auth_set->push_back(TAG_ALL_USERS);
    auth_set->push_back(TAG_NO_AUTH_REQUIRED);

    // All digests.
    auth_set->push_back(TAG_DIGEST, KM_DIGEST_NONE);
    auth_set->push_back(TAG_DIGEST, KM_DIGEST_MD5);
    auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA1);
    auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_224);
    auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
    auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_384);
    auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_512);

    if (algorithm == KM_ALGORITHM_RSA) {
        auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_ENCRYPT);
        auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
        auth_set->push_back(TAG_PADDING, KM_PAD_NONE);
        auth_set->push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
        auth_set->push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
        auth_set->push_back(TAG_PADDING, KM_PAD_RSA_PSS);
        auth_set->push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
    }
}

}  // namespace keymaster
