/*
 * 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_keymaster1_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 = nullptr,
            .dso = 0,
            .reserved = {},
        },
};

struct keystore_module soft_keymaster2_device_module = {
    .common =
        {
            .tag = HARDWARE_MODULE_TAG,
            .module_api_version = KEYMASTER_MODULE_API_VERSION_2_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 = nullptr,
            .dso = 0,
            .reserved = {},
        },
};

namespace keymaster {

const size_t kMaximumAttestationChallengeLength = 128;
const size_t kOperationTableSize = 16;

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,
                                     SoftKeymasterDevice::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,
                                     SoftKeymasterDevice::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)), configured_(false) {
    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)), configured_(false) {
    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_ = km1_device_.common.module->name;
    module_name_.append("(Wrapping ");
    module_name_.append(keymaster0_device->common.module->name);
    module_name_.append(")");

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

    km1_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_ = km1_device_.common.module->name;
    module_name_.append(" (Wrapping ");
    module_name_.append(keymaster1_device->common.module->name);
    module_name_.append(")");

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

    km1_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(&km1_device_, 0, sizeof(km1_device_));

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

    km1_device_.flags = flags;

    km1_device_.context = this;

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

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

    // keymaster2 APIs
    memset(&km2_device_, 0, sizeof(km2_device_));

    km2_device_.context = this;

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

    km2_device_.configure = configure;
    km2_device_.add_rng_entropy = add_rng_entropy;
    km2_device_.generate_key = generate_key;
    km2_device_.get_key_characteristics = get_key_characteristics;
    km2_device_.import_key = import_key;
    km2_device_.export_key = export_key;
    km2_device_.attest_key = attest_key;
    km2_device_.upgrade_key = upgrade_key;
    km2_device_.delete_key = delete_key;
    km2_device_.delete_all_keys = delete_all_keys;
    km2_device_.begin = begin;
    km2_device_.update = update;
    km2_device_.finish = finish;
    km2_device_.abort = abort;
}

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

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

keymaster2_device_t* SoftKeymasterDevice::keymaster2_device() {
    return &km2_device_;
}

namespace {

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

template <typename T> SoftKeymasterDevice* convert_device(const T* dev) {
    static_assert((std::is_same<T, keymaster0_device_t>::value ||
                   std::is_same<T, keymaster1_device_t>::value ||
                   std::is_same<T, keymaster2_device_t>::value),
                  "convert_device should only be applied to keymaster devices");
    return reinterpret_cast<SoftKeymasterDevice*>(dev->context);
}

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

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

}  // unnamed namespaced

/* static */
int SoftKeymasterDevice::close_device(hw_device_t* dev) {
    switch (dev->module->module_api_version) {
    case KEYMASTER_MODULE_API_VERSION_2_0: {
        delete convert_device(reinterpret_cast<keymaster2_device_t*>(dev));
        break;
    }

    case KEYMASTER_MODULE_API_VERSION_1_0: {
        delete convert_device(reinterpret_cast<keymaster1_device_t*>(dev));
        break;
    }

    default:
        return -1;
    }

    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::configure(const keymaster2_device_t* dev,
                                                 const keymaster_key_param_set_t* params) {
    AuthorizationSet params_copy(*params);
    uint32_t os_version;
    uint32_t os_patchlevel;
    if (!params_copy.GetTagValue(TAG_OS_VERSION, &os_version) ||
        !params_copy.GetTagValue(TAG_OS_PATCHLEVEL, &os_patchlevel)) {
        LOG_E("Configuration parameters must contain OS version and patch level", 0);
        return KM_ERROR_INVALID_ARGUMENT;
    }

    keymaster_error_t error =
        convert_device(dev)->context_->SetSystemVersion(os_version, os_patchlevel);
    if (error == KM_ERROR_OK)
        convert_device(dev)->configured_ = true;
    return error;
}

/* 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;
}

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

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    SoftKeymasterDevice* sk_dev = convert_device(dev);
    return add_rng_entropy(&sk_dev->km1_device_, data, data_length);
}

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) {
        // This is a keymaster1 method, and keymaster1 doesn't include version info, so remove it.
        response.enforced.erase(response.enforced.find(TAG_OS_VERSION));
        response.enforced.erase(response.enforced.find(TAG_OS_PATCHLEVEL));
        response.unenforced.erase(response.unenforced.find(TAG_OS_VERSION));
        response.unenforced.erase(response.unenforced.find(TAG_OS_PATCHLEVEL));

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

    return KM_ERROR_OK;
}

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

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    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)) {
        keymaster_key_characteristics_t* chars_ptr;
        keymaster_error_t error = km1_dev->generate_key(km1_dev, params, key_blob,
                                                        characteristics ? &chars_ptr : nullptr);
        if (error != KM_ERROR_OK)
            return error;

        if (characteristics) {
            *characteristics = *chars_ptr;
            free(chars_ptr);
        }

        return KM_ERROR_OK;
    }

    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) {
        response.enforced.CopyToParamSet(&characteristics->hw_enforced);
        response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
    }

    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;

    // This is a keymaster1 method, and keymaster1 doesn't include version info, so remove it.
    response.enforced.erase(response.enforced.find(TAG_OS_VERSION));
    response.enforced.erase(response.enforced.find(TAG_OS_PATCHLEVEL));
    response.unenforced.erase(response.unenforced.find(TAG_OS_VERSION));
    response.unenforced.erase(response.unenforced.find(TAG_OS_PATCHLEVEL));

    *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 keymaster2_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)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    if (!characteristics)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    SoftKeymasterDevice* sk_dev = convert_device(dev);

    const keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
    if (km1_dev) {
        keymaster_key_characteristics_t* tmp_characteristics;
        keymaster_error_t error = km1_dev->get_key_characteristics(km1_dev, key_blob, client_id,
                                                                   app_data, &tmp_characteristics);
        if (error == KM_ERROR_OK) {
            *characteristics = *tmp_characteristics;
            free(tmp_characteristics);
        }
        return error;
    }

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

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

    response.enforced.CopyToParamSet(&characteristics->hw_enforced);
    response.unenforced.CopyToParamSet(&characteristics->sw_enforced);

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

    if (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::import_key(
    const keymaster2_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 (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    SoftKeymasterDevice* sk_dev = convert_device(dev);

    keymaster_error_t error;
    if (characteristics) {
        keymaster_key_characteristics_t* characteristics_ptr;
        error = import_key(&sk_dev->km1_device_, params, key_format, key_data, key_blob,
                           &characteristics_ptr);
        if (error == KM_ERROR_OK) {
            *characteristics = *characteristics_ptr;
            free(characteristics_ptr);
        }
    } else {
        error = import_key(&sk_dev->km1_device_, params, key_format, key_data, key_blob, nullptr);
    }

    return error;
}

/* 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::export_key(const keymaster2_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 (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    SoftKeymasterDevice* sk_dev = convert_device(dev);
    return export_key(&sk_dev->km1_device_, export_format, key_to_export, client_id, app_data,
                      export_data);
}

/* static */
keymaster_error_t SoftKeymasterDevice::attest_key(const keymaster2_device_t* dev,
                                                  const keymaster_key_blob_t* key_to_attest,
                                                  const keymaster_key_param_set_t* attest_params,
                                                  keymaster_cert_chain_t* cert_chain) {
    if (!dev || !key_to_attest || !attest_params || !cert_chain)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    cert_chain->entry_count = 0;
    cert_chain->entries = nullptr;

    AttestKeyRequest request;
    request.SetKeyMaterial(*key_to_attest);
    request.attest_params.Reinitialize(*attest_params);

    keymaster_blob_t attestation_challenge = {};
    request.attest_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge);
    if (attestation_challenge.data_length > kMaximumAttestationChallengeLength) {
        LOG_E("%d-byte attestation challenge; only %d bytes allowed",
              attestation_challenge.data_length, kMaximumAttestationChallengeLength);
        return KM_ERROR_INVALID_INPUT_LENGTH;
    }

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

    // Allocate and clear storage for cert_chain.
    keymaster_cert_chain_t& rsp_chain = response.certificate_chain;
    cert_chain->entries = reinterpret_cast<keymaster_blob_t*>(
        malloc(rsp_chain.entry_count * sizeof(*cert_chain->entries)));
    if (!cert_chain->entries)
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    cert_chain->entry_count = rsp_chain.entry_count;
    for (keymaster_blob_t& entry : array_range(cert_chain->entries, cert_chain->entry_count))
        entry = {};

    // Copy cert_chain contents
    size_t i = 0;
    for (keymaster_blob_t& entry : array_range(rsp_chain.entries, rsp_chain.entry_count)) {
        cert_chain->entries[i].data = reinterpret_cast<uint8_t*>(malloc(entry.data_length));
        if (!cert_chain->entries[i].data) {
            keymaster_free_cert_chain(cert_chain);
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
        }
        cert_chain->entries[i].data_length = entry.data_length;
        memcpy(const_cast<uint8_t*>(cert_chain->entries[i].data), entry.data, entry.data_length);
        ++i;
    }

    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::upgrade_key(const keymaster2_device_t* dev,
                                                   const keymaster_key_blob_t* key_to_upgrade,
                                                   const keymaster_key_param_set_t* upgrade_params,
                                                   keymaster_key_blob_t* upgraded_key) {
    if (!dev || !key_to_upgrade || !upgrade_params)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!upgraded_key)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    UpgradeKeyRequest request;
    request.SetKeyMaterial(*key_to_upgrade);
    request.upgrade_params.Reinitialize(*upgrade_params);

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

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

    return KM_ERROR_OK;
}

/* static */
keymaster_error_t SoftKeymasterDevice::delete_key(const keymaster1_device_t* 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_key(const keymaster2_device_t* dev,
                                                  const keymaster_key_blob_t* key) {
    if (!dev || !key || !key->key_material)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

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

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

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

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

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

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

/* 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::begin(const keymaster2_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 (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    SoftKeymasterDevice* sk_dev = convert_device(dev);
    return begin(&sk_dev->km1_device_, purpose, key, in_params, out_params, operation_handle);
}

/* 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::update(const keymaster2_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 (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    SoftKeymasterDevice* sk_dev = convert_device(dev);
    return update(&sk_dev->km1_device_, operation_handle, in_params, input, input_consumed,
                  out_params, output);
}

/* 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::finish(const keymaster2_device_t* dev,
                                              keymaster_operation_handle_t operation_handle,
                                              const keymaster_key_param_set_t* params,
                                              const keymaster_blob_t* input,
                                              const keymaster_blob_t* signature,
                                              keymaster_key_param_set_t* out_params,
                                              keymaster_blob_t* output) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    if (input && input->data)
        return KM_ERROR_UNIMPLEMENTED;  // TODO(swillden): Implement this

    SoftKeymasterDevice* sk_dev = convert_device(dev);
    return finish(&sk_dev->km1_device_, operation_handle, params, signature, out_params, output);
}

/* 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 */
keymaster_error_t SoftKeymasterDevice::abort(const keymaster2_device_t* dev,
                                             keymaster_operation_handle_t operation_handle) {
    if (!dev)
        return KM_ERROR_UNEXPECTED_NULL_POINTER;

    if (!convert_device(dev)->configured())
        return KM_ERROR_KEYMASTER_NOT_CONFIGURED;

    SoftKeymasterDevice* sk_dev = convert_device(dev);
    return abort(&sk_dev->km1_device_, operation_handle);
}

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