/*
 * 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 "trusty_keymaster_context.h"

#include <array>
#include <utility>

#include <keymaster/android_keymaster_utils.h>
#include <keymaster/contexts/soft_attestation_cert.h>
#include <keymaster/key_blob_utils/auth_encrypted_key_blob.h>
#include <keymaster/key_blob_utils/ocb_utils.h>
#include <keymaster/km_openssl/aes_key.h>
#include <keymaster/km_openssl/asymmetric_key.h>
#include <keymaster/km_openssl/attestation_record.h>
#include <keymaster/km_openssl/attestation_utils.h>
#include <keymaster/km_openssl/certificate_utils.h>
#include <keymaster/km_openssl/ec_key_factory.h>
#include <keymaster/km_openssl/hmac_key.h>
#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/km_openssl/rsa_key_factory.h>
#include <keymaster/km_openssl/triple_des_key.h>
#include <keymaster/logger.h>
#include <keymaster/operation.h>
#include <keymaster/wrapped_key.h>
#include <lib/hwkey/hwkey.h>
#include <lib/rng/trusty_rng.h>
#include <openssl/hmac.h>

#include "secure_storage_manager.h"
#include "trusty_aes_key.h"

constexpr bool kUseSecureDeletion = true;
uint8_t allZerosOrHashOfVerifiedBootKey[32] = {};

#ifdef KEYMASTER_DEBUG
#pragma message \
        "Compiling with fake Keymaster Root of Trust values! DO NOT SHIP THIS!"
#endif

// TRUSTY_KM_WRAPPING_KEY_SIZE controls the size of the AES key that is used
// to wrap keys before allowing NS to hold on to them.
// Previously, it had a hardcoded value of 16 bytes, but current guidance is to
// expand this to a 256-bit (32-byte) key.
//
// The plan is to leave old devices as they are, and issue new devices with a
// 32-byte key to ensure compatibility. New devices should set
// TRUSTY_WRAPPING_KEY_SIZE to 32 in their device Makefile to control this.

#ifndef TRUSTY_KM_WRAPPING_KEY_SIZE
#define TRUSTY_KM_WRAPPING_KEY_SIZE 16
#endif

namespace keymaster {

namespace {
static const int kAesKeySize = TRUSTY_KM_WRAPPING_KEY_SIZE;
static const int kCallsBetweenRngReseeds = 32;
static const int kRngReseedSize = 64;
static const uint8_t kMasterKeyDerivationData[kAesKeySize] = "KeymasterMaster";

bool UpgradeIntegerTag(keymaster_tag_t tag,
                       uint32_t value,
                       AuthorizationSet* set,
                       bool* set_changed) {
    int index = set->find(tag);
    if (index == -1) {
        *set_changed = true;
        set->push_back(keymaster_key_param_t{.tag = tag, .integer = value});
        return true;
    }

    if (set->params[index].integer > value) {
        return false;
    }

    if (set->params[index].integer != value) {
        *set_changed = true;
        set->params[index].integer = value;
    }
    return true;
}

}  // anonymous namespace

TrustyKeymasterContext::TrustyKeymasterContext()
        : AttestationContext(KmVersion::KEYMASTER_4),
          enforcement_policy_(this),
          secure_deletion_secret_storage_(*this /* random_source */),
          rng_initialized_(false),
          calls_since_reseed_(0) {
    LOG_D("Creating TrustyKeymaster", 0);
    rsa_factory_.reset(new (std::nothrow) RsaKeyFactory(*this /* blob_maker */,
                                                        *this /* context */));
    tdes_factory_.reset(new (std::nothrow) TripleDesKeyFactory(
            *this /* blob_maker */, *this /* random_source */));
    ec_factory_.reset(new (std::nothrow) EcKeyFactory(*this /* blob_maker */,
                                                      *this /* context */));
    aes_factory_.reset(new (std::nothrow) TrustyAesKeyFactory(
            *this /* blob_maker */, *this /* random_source */));
    hmac_factory_.reset(new (std::nothrow) HmacKeyFactory(
            *this /* blob_maker */, *this /* random_source */));
    boot_params_.verified_boot_key.Reinitialize("Unbound", 7);
    trusty_remote_provisioning_context_.reset(
            new (std::nothrow) TrustyRemoteProvisioningContext());
}

const KeyFactory* TrustyKeymasterContext::GetKeyFactory(
        keymaster_algorithm_t algorithm) const {
    switch (algorithm) {
    case KM_ALGORITHM_RSA:
        return rsa_factory_.get();
    case KM_ALGORITHM_EC:
        return ec_factory_.get();
    case KM_ALGORITHM_AES:
        return aes_factory_.get();
    case KM_ALGORITHM_HMAC:
        return hmac_factory_.get();
    case KM_ALGORITHM_TRIPLE_DES:
        return tdes_factory_.get();
    default:
        return nullptr;
    }
}

static keymaster_algorithm_t supported_algorithms[] = {
        KM_ALGORITHM_RSA, KM_ALGORITHM_EC, KM_ALGORITHM_AES, KM_ALGORITHM_HMAC,
        KM_ALGORITHM_TRIPLE_DES};

const keymaster_algorithm_t* TrustyKeymasterContext::GetSupportedAlgorithms(
        size_t* algorithms_count) const {
    *algorithms_count = array_length(supported_algorithms);
    return supported_algorithms;
}

OperationFactory* TrustyKeymasterContext::GetOperationFactory(
        keymaster_algorithm_t algorithm,
        keymaster_purpose_t purpose) const {
    const KeyFactory* key_factory = GetKeyFactory(algorithm);
    if (!key_factory)
        return nullptr;
    return key_factory->GetOperationFactory(purpose);
}

static keymaster_error_t TranslateAuthorizationSetError(
        AuthorizationSet::Error err) {
    switch (err) {
    case AuthorizationSet::OK:
        return KM_ERROR_OK;
    case AuthorizationSet::ALLOCATION_FAILURE:
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    case AuthorizationSet::MALFORMED_DATA:
        return KM_ERROR_UNKNOWN_ERROR;
    }
    return KM_ERROR_OK;
}

keymaster_error_t TrustyKeymasterContext::SetAuthorizations(
        const AuthorizationSet& key_description,
        keymaster_key_origin_t origin,
        AuthorizationSet* hw_enforced,
        AuthorizationSet* sw_enforced,
        bool has_secure_deletion) const {
    sw_enforced->Clear();
    hw_enforced->Clear();

    for (auto& entry : key_description) {
        switch (entry.tag) {
        // Tags that should never appear in key descriptions.
        case KM_TAG_ASSOCIATED_DATA:
        case KM_TAG_AUTH_TOKEN:
        case KM_TAG_BOOTLOADER_ONLY:
        case KM_TAG_INVALID:
        case KM_TAG_MAC_LENGTH:
        case KM_TAG_NONCE:
        case KM_TAG_ROOT_OF_TRUST:
        case KM_TAG_UNIQUE_ID:
        case KM_TAG_IDENTITY_CREDENTIAL_KEY:
            return KM_ERROR_INVALID_KEY_BLOB;

        // Tags used only to provide information for certificate creation, but
        // which should not be included in blobs.
        case KM_TAG_ATTESTATION_APPLICATION_ID:
        case KM_TAG_ATTESTATION_CHALLENGE:
        case KM_TAG_ATTESTATION_ID_BRAND:
        case KM_TAG_ATTESTATION_ID_DEVICE:
        case KM_TAG_ATTESTATION_ID_IMEI:
        case KM_TAG_ATTESTATION_ID_MANUFACTURER:
        case KM_TAG_ATTESTATION_ID_MEID:
        case KM_TAG_ATTESTATION_ID_MODEL:
        case KM_TAG_ATTESTATION_ID_PRODUCT:
        case KM_TAG_ATTESTATION_ID_SERIAL:
        case KM_TAG_CERTIFICATE_NOT_AFTER:
        case KM_TAG_CERTIFICATE_NOT_BEFORE:
        case KM_TAG_CERTIFICATE_SERIAL:
        case KM_TAG_CERTIFICATE_SUBJECT:
        case KM_TAG_RESET_SINCE_ID_ROTATION:
            break;

        // Unimplemented tags for which we return an error.
        case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
            return KM_ERROR_INVALID_ARGUMENT;

        // Unimplemented tags we silently ignore.
        case KM_TAG_ALLOW_WHILE_ON_BODY:
            break;

        // Obsolete tags we silently ignore.
        case KM_TAG_ALL_APPLICATIONS:
        case KM_TAG_ROLLBACK_RESISTANT:
        case KM_TAG_CONFIRMATION_TOKEN:

        // Tags that should not be added to blobs.
        case KM_TAG_APPLICATION_ID:
        case KM_TAG_APPLICATION_DATA:
            break;

        // Tags we ignore because they'll be set below.
        case KM_TAG_BOOT_PATCHLEVEL:
        case KM_TAG_ORIGIN:
        case KM_TAG_OS_PATCHLEVEL:
        case KM_TAG_OS_VERSION:
        case KM_TAG_VENDOR_PATCHLEVEL:
            break;

        // Tags that are hardware-enforced
        case KM_TAG_ALGORITHM:
        case KM_TAG_AUTH_TIMEOUT:
        case KM_TAG_BLOB_USAGE_REQUIREMENTS:
        case KM_TAG_BLOCK_MODE:
        case KM_TAG_CALLER_NONCE:
        case KM_TAG_DIGEST:
        case KM_TAG_EARLY_BOOT_ONLY:
        case KM_TAG_ECIES_SINGLE_HASH_MODE:
        case KM_TAG_EC_CURVE:
        case KM_TAG_KDF:
        case KM_TAG_KEY_SIZE:
        case KM_TAG_MAX_USES_PER_BOOT:
        case KM_TAG_MIN_MAC_LENGTH:
        case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
        case KM_TAG_NO_AUTH_REQUIRED:
        case KM_TAG_PADDING:
        case KM_TAG_PURPOSE:
        case KM_TAG_ROLLBACK_RESISTANCE:
        case KM_TAG_RSA_OAEP_MGF_DIGEST:
        case KM_TAG_RSA_PUBLIC_EXPONENT:
        case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
        case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
        case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
        case KM_TAG_USER_SECURE_ID:
            hw_enforced->push_back(entry);
            break;

        // KM_TAG_STORAGE_KEY handling depends if the feature is enabled.
        case KM_TAG_STORAGE_KEY:
#if WITH_HWWSK_SUPPORT
            hw_enforced->push_back(entry);
            break;
#else
            return KM_ERROR_UNIMPLEMENTED;
#endif

        case KM_TAG_USER_AUTH_TYPE: {
            keymaster_key_param_t elem = entry;

            // This implementation does support TEE enforced password auth
            elem.enumerated = entry.enumerated & HW_AUTH_PASSWORD;

#if TEE_FINGERPRINT_AUTH_SUPPORTED
            // If HW_AUTH_FINGERPRINT is supported it needs to be included too
            elem.enumerated |= entry.enumerated & HW_AUTH_FINGERPRINT;
#endif
            hw_enforced->push_back(elem);
        } break;

        case KM_TAG_USAGE_COUNT_LIMIT:
            LOG_D("Found usage count limit tag: %u", entry.integer);
            if (entry.integer == 1 && has_secure_deletion) {
                // We can enforce a usage count of 1 in HW.
                hw_enforced->push_back(entry);
            } else {
                // Otherwise we delegate to keystore.
                sw_enforced->push_back(entry);
            }
            break;

        // Keystore-enforced tags
        case KM_TAG_ACTIVE_DATETIME:
        case KM_TAG_ALL_USERS:
        case KM_TAG_CREATION_DATETIME:
        case KM_TAG_EXPORTABLE:
        case KM_TAG_INCLUDE_UNIQUE_ID:
        case KM_TAG_MAX_BOOT_LEVEL:
        case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
        case KM_TAG_USAGE_EXPIRE_DATETIME:
        case KM_TAG_USER_ID:
            sw_enforced->push_back(entry);
            break;
        }
    }

    hw_enforced->push_back(TAG_ORIGIN, origin);

    // these values will be 0 if not set by bootloader
    hw_enforced->push_back(TAG_OS_VERSION, boot_params_.boot_os_version);
    hw_enforced->push_back(TAG_OS_PATCHLEVEL, boot_params_.boot_os_patchlevel);

    if (vendor_patchlevel_.has_value()) {
        hw_enforced->push_back(TAG_VENDOR_PATCHLEVEL,
                               vendor_patchlevel_.value());
    }
    if (boot_patchlevel_.has_value()) {
        hw_enforced->push_back(TAG_BOOT_PATCHLEVEL, boot_patchlevel_.value());
    }

    if (sw_enforced->is_valid() != AuthorizationSet::OK)
        return TranslateAuthorizationSetError(sw_enforced->is_valid());
    if (hw_enforced->is_valid() != AuthorizationSet::OK)
        return TranslateAuthorizationSetError(hw_enforced->is_valid());
    return KM_ERROR_OK;
}

keymaster_error_t TrustyKeymasterContext::BuildHiddenAuthorizations(
        const AuthorizationSet& input_set,
        AuthorizationSet* hidden) const {
    keymaster_blob_t entry;
    if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
        hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
    if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
        hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);

    // Copy verified boot key, verified boot state, and device lock state to
    // hidden authorization set for binding to key.
    keymaster_key_param_t root_of_trust;
    root_of_trust.tag = KM_TAG_ROOT_OF_TRUST;
    root_of_trust.blob.data = boot_params_.verified_boot_key.begin();
    root_of_trust.blob.data_length =
            boot_params_.verified_boot_key.buffer_size();
    hidden->push_back(root_of_trust);

    root_of_trust.blob.data =
            reinterpret_cast<const uint8_t*>(&boot_params_.verified_boot_state);
    root_of_trust.blob.data_length = sizeof(boot_params_.verified_boot_state);
    hidden->push_back(root_of_trust);

    root_of_trust.blob.data =
            reinterpret_cast<const uint8_t*>(&boot_params_.device_locked);
    root_of_trust.blob.data_length = sizeof(boot_params_.device_locked);
    hidden->push_back(root_of_trust);

    return TranslateAuthorizationSetError(hidden->is_valid());
}

keymaster_error_t TrustyKeymasterContext::GetKdfState(
        EncryptedKey* info) const {
    long rc = hwkey_open();
    if (rc < 0) {
        LOG_S("Error failing to open a connection to hwkey: %d", rc);
        return KM_ERROR_UNKNOWN_ERROR;
    }

    hwkey_session_t session = (hwkey_session_t)rc;
    struct hwkey_versioned_key_options opt = {
            .kdf_version = HWKEY_KDF_VERSION_BEST,
            .shared_key = false,
            .rollback_version_source = HWKEY_ROLLBACK_COMMITTED_VERSION,
            .os_rollback_version = HWKEY_ROLLBACK_VERSION_CURRENT,
            .context = NULL,
            .context_len = 0,
            .key = NULL,
            .key_len = 0,
    };
    rc = hwkey_derive_versioned(session, &opt);
    if (rc < 0) {
        LOG_S("Error deriving versioned master key: %d", rc);
        hwkey_close(session);
        return KM_ERROR_UNKNOWN_ERROR;
    }
    hwkey_close(session);
    // Any versioned format will put the KDF selection into the correct mode.
    info->format = AES_GCM_WITH_SW_ENFORCED_VERSIONED;
    info->kdf_version = opt.kdf_version;
    info->addl_info = opt.os_rollback_version;
    return KM_ERROR_OK;
}

keymaster_error_t TrustyKeymasterContext::CreateAuthEncryptedKeyBlob(
        const AuthorizationSet& key_description,
        const KeymasterKeyBlob& key_material,
        const AuthorizationSet& hw_enforced,
        const AuthorizationSet& sw_enforced,
        const std::optional<SecureDeletionData>& secure_deletion_data,
        KeymasterKeyBlob* blob) const {
    AuthorizationSet hidden;
    keymaster_error_t error =
            BuildHiddenAuthorizations(key_description, &hidden);
    if (error != KM_ERROR_OK)
        return error;

    KeymasterKeyBlob master_key;
    EncryptedKey info;
    error = GetKdfState(&info);
    if (error != KM_ERROR_OK) {
        return error;
    }
    error = DeriveMasterKey(&master_key, info);
    if (error != KM_ERROR_OK) {
        return error;
    }

    KmErrorOr<EncryptedKey> encrypted_key;
    if (secure_deletion_data) {
        encrypted_key = EncryptKey(
                key_material, AES_GCM_WITH_SECURE_DELETION_VERSIONED,
                hw_enforced, sw_enforced, hidden, *secure_deletion_data,
                master_key, *this /* random */);
    } else {
        encrypted_key = EncryptKey(
                key_material, AES_GCM_WITH_SW_ENFORCED_VERSIONED, hw_enforced,
                sw_enforced, hidden, SecureDeletionData{}, master_key,
                *this /* random */);
    }
    if (!encrypted_key) {
        return encrypted_key.error();
    }

    encrypted_key->kdf_version = info.kdf_version;
    encrypted_key->addl_info = info.addl_info;
    KmErrorOr<KeymasterKeyBlob> serialized_key = SerializeAuthEncryptedBlob(
            *encrypted_key, hw_enforced, sw_enforced,
            secure_deletion_data ? secure_deletion_data->key_slot : 0);

    if (!serialized_key) {
        return serialized_key.error();
    }

    *blob = std::move(*serialized_key);
    return KM_ERROR_OK;
}

class KeySlotCleanup {
public:
    KeySlotCleanup(const SecureDeletionSecretStorage& storage,
                   uint32_t key_slot)
            : storage_(storage), key_slot_(key_slot) {}
    ~KeySlotCleanup() {
        if (key_slot_ != 0) {
            storage_.DeleteKey(key_slot_);
        }
    }

    void release() { key_slot_ = 0; }

private:
    const SecureDeletionSecretStorage& storage_;
    uint32_t key_slot_;
};

keymaster_error_t TrustyKeymasterContext::CreateKeyBlob(
        const AuthorizationSet& key_description,
        keymaster_key_origin_t origin,
        const KeymasterKeyBlob& key_material,
        KeymasterKeyBlob* blob,
        AuthorizationSet* hw_enforced,
        AuthorizationSet* sw_enforced) const {
    bool request_rollback_resistance =
            key_description.Contains(TAG_ROLLBACK_RESISTANCE);
    bool request_usage_limit =
            key_description.Contains(TAG_USAGE_COUNT_LIMIT, 1);
    bool request_secure_deletion =
            request_rollback_resistance || request_usage_limit;

    LOG_D("Getting secure deletion data", 0);
    std::optional<SecureDeletionData> sdd;
    if (kUseSecureDeletion) {
        sdd = secure_deletion_secret_storage_.CreateDataForNewKey(
                request_secure_deletion,
                /* is_upgrade */ false);
    }

    if (sdd) {
        LOG_D("Got secure deletion data, FR size = %zu, SD size = %zu, slot = %u",
              sdd->factory_reset_secret.buffer_size(),
              sdd->secure_deletion_secret.buffer_size(), sdd->key_slot);
    } else if (!kUseSecureDeletion) {
        LOG_I("Not using secure deletion", 0);
    } else {
        LOG_W("Failed to get secure deletion data. storageproxy not up?", 0);
    }

    uint32_t key_slot = sdd ? sdd->key_slot : 0;
    bool has_secure_deletion = key_slot != 0;
    if (request_secure_deletion && !has_secure_deletion) {
        LOG_E("Secure deletion requested (rollback_resistance:%d, usage_limit:%d) but no slot available!",
              request_rollback_resistance, request_usage_limit);
        return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
    }

    // At this point we may have stored a secure deletion secret for this key.
    // If something goes wrong before we return the blob, that slot will leak.
    // Create an object to clean up on the error paths.
    KeySlotCleanup key_slot_cleanup(secure_deletion_secret_storage_, key_slot);

    keymaster_error_t error =
            SetAuthorizations(key_description, origin, hw_enforced, sw_enforced,
                              has_secure_deletion);

    if (error != KM_ERROR_OK) {
        return error;
    }

    error = CreateAuthEncryptedKeyBlob(key_description, key_material,
                                       *hw_enforced, *sw_enforced,
                                       std::move(sdd), blob);
    if (error != KM_ERROR_OK) {
        return error;
    }

    key_slot_cleanup.release();
    return KM_ERROR_OK;
}

keymaster_error_t TrustyKeymasterContext::UpgradeKeyBlob(
        const KeymasterKeyBlob& key_to_upgrade,
        const AuthorizationSet& upgrade_params,
        KeymasterKeyBlob* upgraded_key) const {
    UniquePtr<Key> key;
    keymaster_error_t error =
            ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
    LOG_I("Upgrading key blob", 1);
    if (error != KM_ERROR_OK) {
        return error;
    }

    bool set_changed = false;
    if (boot_params_.boot_os_version == 0) {
        // We need to allow "upgrading" OS version to zero, to support upgrading
        // from proper numbered releases to unnumbered development and preview
        // releases.

        if (int pos = key->sw_enforced().find(TAG_OS_VERSION);
            pos != -1 &&
            key->sw_enforced()[pos].integer != boot_params_.boot_os_version) {
            set_changed = true;
            key->sw_enforced()[pos].integer = boot_params_.boot_os_version;
        }
    }

    if (!UpgradeIntegerTag(TAG_OS_VERSION, boot_params_.boot_os_version,
                           &key->hw_enforced(), &set_changed) ||
        !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, boot_params_.boot_os_patchlevel,
                           &key->hw_enforced(), &set_changed) ||
        (vendor_patchlevel_.has_value() &&
         !UpgradeIntegerTag(TAG_VENDOR_PATCHLEVEL, vendor_patchlevel_.value(),
                            &key->hw_enforced(), &set_changed)) ||
        (boot_patchlevel_.has_value() &&
         !UpgradeIntegerTag(TAG_BOOT_PATCHLEVEL, boot_patchlevel_.value(),
                            &key->hw_enforced(), &set_changed))) {
        // One of the version fields would have been a downgrade. Not allowed.
        return KM_ERROR_INVALID_ARGUMENT;
    }

    if (!set_changed) {
        return KM_ERROR_OK;
    }

    bool has_secure_deletion = false;
    if (key->secure_deletion_slot() != 0) {
        LOG_D("Upgrading rollback-protected key blob in slot %u",
              key->secure_deletion_slot());
        has_secure_deletion = true;
    }
    if (!has_secure_deletion &&
        upgrade_params.Contains(TAG_ROLLBACK_RESISTANCE)) {
        LOG_D("Upgrading non rollback-protected key, adding rollback protection",
              0);
        has_secure_deletion = true;
    }

    std::optional<SecureDeletionData> sdd;
    if (kUseSecureDeletion) {
        sdd = secure_deletion_secret_storage_.CreateDataForNewKey(
                has_secure_deletion, true /* is_upgrade */);
    }

    // At this point we may have stored a secure deletion secret for this key.
    // If something goes wrong before we return the blob, that slot will leak.
    // Create an object to clean up on the error paths.
    KeySlotCleanup key_slot_cleanup(secure_deletion_secret_storage_,
                                    sdd ? sdd->key_slot : 0);

    error = CreateAuthEncryptedKeyBlob(upgrade_params, key->key_material(),
                                       key->hw_enforced(), key->sw_enforced(),
                                       std::move(sdd), upgraded_key);
    if (error != KM_ERROR_OK) {
        return error;
    }

    key_slot_cleanup.release();
    return KM_ERROR_OK;
}

constexpr std::array<uint8_t, 7> kKeystoreKeyBlobMagic = {'p', 'K', 'M', 'b',
                                                          'l', 'o', 'b'};
constexpr size_t kKeystoreKeyTypeOffset = kKeystoreKeyBlobMagic.size();
constexpr size_t kKeystoreKeyBlobPrefixSize = kKeystoreKeyTypeOffset + 1;

KmErrorOr<DeserializedKey> TrustyKeymasterContext::DeserializeKmCompatKeyBlob(
        const KeymasterKeyBlob& blob) const {
    // This blob has a keystore km_compat prefix.  This means that it was
    // created by keystore calling TrustyKeymaster through the km_compat layer.
    // The km_compat layer adds this prefix to determine whether it's actually a
    // hardware blob that should be passed through to Keymaster, or whether it's
    // a software only key and should be used by the emulation layer.
    //
    // In the case of hardware blobs, km_compat strips the prefix before handing
    // the blob to Keymaster.  In the case of software blobs, km_compat never
    // hands the blob to Keymaster.
    //
    // The fact that we've received this prefixed blob means that it was created
    // through km_compat... but the device has now been upgraded from
    // TrustyKeymaster to TrustyKeyMint, and so keystore is no longer using the
    // km_compat layer, and the blob is just passed through with its prefix
    // intact.
    auto keyType = *(blob.begin() + kKeystoreKeyTypeOffset);
    switch (keyType) {
    case 0:
        // This is a hardware blob. Strip the prefix and use the blob.
        return DeserializeAuthEncryptedBlob(
                KeymasterKeyBlob(blob.begin() + kKeystoreKeyBlobPrefixSize,
                                 blob.size() - kKeystoreKeyBlobPrefixSize));

    case 1:
        LOG_E("Software key blobs are not supported.", 0);
        return KM_ERROR_INVALID_KEY_BLOB;

    default:
        LOG_E("Invalid keystore blob prefix value %d", keyType);
        return KM_ERROR_INVALID_KEY_BLOB;
    }
}

bool is_km_compat_blob(const KeymasterKeyBlob& blob) {
    return blob.size() >= kKeystoreKeyBlobPrefixSize &&
           std::equal(kKeystoreKeyBlobMagic.begin(),
                      kKeystoreKeyBlobMagic.end(), blob.begin());
}

KmErrorOr<DeserializedKey> TrustyKeymasterContext::DeserializeKeyBlob(
        const KeymasterKeyBlob& blob) const {
    if (is_km_compat_blob(blob)) {
        return DeserializeKmCompatKeyBlob(blob);
    } else {
        return DeserializeAuthEncryptedBlob(blob);
    }
}

keymaster_error_t TrustyKeymasterContext::ParseKeyBlob(
        const KeymasterKeyBlob& blob,
        const AuthorizationSet& additional_params,
        UniquePtr<Key>* key) const {
    keymaster_error_t error;

    if (!key) {
        return KM_ERROR_UNEXPECTED_NULL_POINTER;
    }

    KmErrorOr<DeserializedKey> deserialized_key = DeserializeKeyBlob(blob);
    if (!deserialized_key) {
        return deserialized_key.error();
    }
    LOG_D("Deserialized blob with format: %d",
          deserialized_key->encrypted_key.format);

    KeymasterKeyBlob master_key;
    error = DeriveMasterKey(&master_key, deserialized_key->encrypted_key);
    if (error != KM_ERROR_OK) {
        return error;
    }

    AuthorizationSet hidden;
    error = BuildHiddenAuthorizations(additional_params, &hidden);
    if (error != KM_ERROR_OK) {
        return error;
    }

    SecureDeletionData sdd;
    if (deserialized_key->encrypted_key.format ==
                AES_GCM_WITH_SECURE_DELETION ||
        deserialized_key->encrypted_key.format ==
                AES_GCM_WITH_SECURE_DELETION_VERSIONED) {
        // This key requires secure deletion data.
        sdd = secure_deletion_secret_storage_.GetDataForKey(
                deserialized_key->key_slot);
    }

    LOG_D("Decrypting blob with format: %d",
          deserialized_key->encrypted_key.format);
    KmErrorOr<KeymasterKeyBlob> key_material =
            DecryptKey(*deserialized_key, hidden, sdd, master_key);
    if (!key_material) {
        return key_material.error();
    }

    keymaster_algorithm_t algorithm;
    if (!deserialized_key->hw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) {
        return KM_ERROR_INVALID_KEY_BLOB;
    }

    auto factory = GetKeyFactory(algorithm);
    error = factory->LoadKey(std::move(*key_material), additional_params,
                             std::move(deserialized_key->hw_enforced),
                             std::move(deserialized_key->sw_enforced), key);
    if (key && key->get()) {
        (*key)->set_secure_deletion_slot(deserialized_key->key_slot);
    }

    return error;
}

keymaster_error_t TrustyKeymasterContext::DeleteKey(
        const KeymasterKeyBlob& blob) const {
    KmErrorOr<DeserializedKey> deserialized_key = DeserializeKeyBlob(blob);
    if (deserialized_key) {
        LOG_D("Deserialized blob with format: %d",
              deserialized_key->encrypted_key.format);
        secure_deletion_secret_storage_.DeleteKey(deserialized_key->key_slot);
    }

    return KM_ERROR_OK;
}

keymaster_error_t TrustyKeymasterContext::DeleteAllKeys() const {
    secure_deletion_secret_storage_.DeleteAllKeys();
    return KM_ERROR_OK;
}

keymaster_error_t TrustyKeymasterContext::AddRngEntropy(const uint8_t* buf,
                                                        size_t length) const {
    if (trusty_rng_add_entropy(buf, length) != 0)
        return KM_ERROR_UNKNOWN_ERROR;
    return KM_ERROR_OK;
}

bool TrustyKeymasterContext::SeedRngIfNeeded() const {
    if (ShouldReseedRng())
        const_cast<TrustyKeymasterContext*>(this)->ReseedRng();
    return rng_initialized_;
}

bool TrustyKeymasterContext::ShouldReseedRng() const {
    if (!rng_initialized_) {
        LOG_I("RNG not initalized, reseed", 0);
        return true;
    }

    if (++calls_since_reseed_ % kCallsBetweenRngReseeds == 0) {
        LOG_I("Periodic reseed", 0);
        return true;
    }
    return false;
}

bool TrustyKeymasterContext::ReseedRng() {
    uint8_t rand_seed[kRngReseedSize];
    memset(rand_seed, 0, kRngReseedSize);
    if (trusty_rng_hw_rand(rand_seed, kRngReseedSize) != 0) {
        LOG_E("Failed to get bytes from HW RNG", 0);
        return false;
    }
    LOG_I("Reseeding with %d bytes from HW RNG", kRngReseedSize);
    trusty_rng_add_entropy(rand_seed, kRngReseedSize);

    rng_initialized_ = true;
    return true;
}

// Gee wouldn't it be nice if the crypto service headers defined this.
enum DerivationParams {
    DERIVATION_DATA_PARAM = 0,
    OUTPUT_BUFFER_PARAM = 1,
};

keymaster_error_t TrustyKeymasterContext::DeriveMasterKey(
        KeymasterKeyBlob* master_key,
        const EncryptedKey& enc_key) const {
    LOG_D("Deriving master key", 0);

    long rc = hwkey_open();
    if (rc < 0) {
        return KM_ERROR_UNKNOWN_ERROR;
    }

    hwkey_session_t session = (hwkey_session_t)rc;

    if (!master_key->Reset(kAesKeySize)) {
        LOG_S("Could not allocate memory for master key buffer", 0);
        hwkey_close(session);
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    if (enc_key.format < AES_GCM_WITH_SW_ENFORCED_VERSIONED) {
        uint32_t kdf_version = HWKEY_KDF_VERSION_1;
        rc = hwkey_derive(session, &kdf_version, kMasterKeyDerivationData,
                          master_key->writable_data(), kAesKeySize);
        if (rc < 0) {
            LOG_S("Error deriving legacy master key: %d", rc);
            hwkey_close(session);
            return KM_ERROR_UNKNOWN_ERROR;
        }
    } else {
        struct hwkey_versioned_key_options opt = {
                .kdf_version = enc_key.kdf_version,
                .shared_key = false,
                .rollback_version_source = HWKEY_ROLLBACK_COMMITTED_VERSION,
                .os_rollback_version = enc_key.addl_info,
                .context = kMasterKeyDerivationData,
                .context_len = sizeof(kMasterKeyDerivationData),
                .key = master_key->writable_data(),
                .key_len = kAesKeySize,
        };
        rc = hwkey_derive_versioned(session, &opt);
        if (rc < 0) {
            LOG_S("Error deriving versioned master key: %d", rc);
            hwkey_close(session);
            return KM_ERROR_UNKNOWN_ERROR;
        }
    }

    hwkey_close(session);
    LOG_D("Key derivation complete", 0);
    return KM_ERROR_OK;
}

bool TrustyKeymasterContext::InitializeAuthTokenKey() {
    if (auth_token_key_initialized_)
        return true;

    keymaster_key_blob_t key;
    key.key_material = auth_token_key_;
    key.key_material_size = kAuthTokenKeySize;
    keymaster_error_t error = enforcement_policy_.GetHmacKey(&key);
    if (error == KM_ERROR_OK)
        auth_token_key_initialized_ = true;
    else
        auth_token_key_initialized_ = false;

    return auth_token_key_initialized_;
}

keymaster_error_t TrustyKeymasterContext::GetAuthTokenKey(
        keymaster_key_blob_t* key) const {
    if (!auth_token_key_initialized_ &&
        !const_cast<TrustyKeymasterContext*>(this)->InitializeAuthTokenKey())
        return KM_ERROR_UNKNOWN_ERROR;

    key->key_material = auth_token_key_;
    key->key_material_size = kAuthTokenKeySize;
    return KM_ERROR_OK;
}

keymaster_error_t TrustyKeymasterContext::SetSystemVersion(
        uint32_t os_version,
        uint32_t os_patchlevel) {
    if (!version_info_set_) {
        // Note that version info is now set by Configure, rather than by the
        // bootloader.  This is to ensure that system-only updates can be done,
        // to avoid breaking Project Treble.
        boot_params_.boot_os_version = os_version;
        boot_params_.boot_os_patchlevel = os_patchlevel;
        version_info_set_ = true;
    }

#ifdef KEYMASTER_DEBUG
    Buffer fake_root_of_trust("000111222333444555666777888999000", 32);
    Buffer verified_boot_hash_none;
    if (!root_of_trust_set_) {
        /* Sets bootloader parameters to what is expected on a 'good' device,
         * will pass attestation CTS tests. FOR DEBUGGING ONLY.
         */
        SetBootParams(os_version, os_patchlevel, fake_root_of_trust,
                      KM_VERIFIED_BOOT_VERIFIED, true, verified_boot_hash_none);
    }
#endif

    return KM_ERROR_OK;
}

void TrustyKeymasterContext::GetSystemVersion(uint32_t* os_version,
                                              uint32_t* os_patchlevel) const {
    *os_version = boot_params_.boot_os_version;
    *os_patchlevel = boot_params_.boot_os_patchlevel;
}

const AttestationContext::VerifiedBootParams*
TrustyKeymasterContext::GetVerifiedBootParams(keymaster_error_t* error) const {
    VerifiedBootParams& vb_parms =
            const_cast<VerifiedBootParams&>(verified_boot_params_);

    if (boot_params_.verified_boot_key.buffer_size() == 0) {
        // If an empty verified boot key was passed by the boot loader, set the
        // verfified boot key in attestation parameters to 32 bytes of all
        // zeros.
        vb_parms.verified_boot_key = {allZerosOrHashOfVerifiedBootKey,
                                      sizeof(allZerosOrHashOfVerifiedBootKey)};
    } else if (boot_params_.verified_boot_key.buffer_size() > 0 &&
               boot_params_.verified_boot_key.buffer_size() <= 32) {
        vb_parms.verified_boot_key = {
                boot_params_.verified_boot_key.begin(),
                boot_params_.verified_boot_key.buffer_size()};
    } else if (boot_params_.verified_boot_key.buffer_size() > 32) {
        // If the verified boot key itself was passed by the boot loader, set
        // SHA-256 hash of it to the verified boot key parameter of the
        // attetation information.
        vb_parms.verified_boot_key = {
                SHA256(boot_params_.verified_boot_key.begin(),
                       boot_params_.verified_boot_key.buffer_size(),
                       allZerosOrHashOfVerifiedBootKey),
                SHA256_DIGEST_LENGTH};
    }

    vb_parms.verified_boot_hash = {
            boot_params_.verified_boot_hash.begin(),
            boot_params_.verified_boot_hash.buffer_size()};
    vb_parms.verified_boot_state = boot_params_.verified_boot_state;
    vb_parms.device_locked = boot_params_.device_locked;

    *error = KM_ERROR_OK;
    return &verified_boot_params_;
}

#define PROTO_BYTES_DOES_NOT_MATCH_BLOB(blob, proto) \
    ((blob).data_length != (proto).size) ||          \
            (memcmp((blob).data, (proto).bytes, (proto).size) != 0)

keymaster_error_t TrustyKeymasterContext::VerifyAndCopyDeviceIds(
        const AuthorizationSet& attestation_params,
        AuthorizationSet* values_to_attest) const {
    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    if (ss_manager == nullptr) {
        LOG_E("Failed to open secure storage session.", 0);
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }

    AttestationIds ids;
    auto err = ss_manager->ReadAttestationIds(&ids);
    if (err != KM_ERROR_OK) {
        return err;
    }

    bool found_mismatch = false;
    for (auto& entry : attestation_params) {
        switch (entry.tag) {
        case KM_TAG_ATTESTATION_ID_BRAND:
            found_mismatch |=
                    PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob, ids.brand);
            values_to_attest->push_back(entry);
            break;

        case KM_TAG_ATTESTATION_ID_DEVICE:
            found_mismatch |=
                    PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob, ids.device);
            values_to_attest->push_back(entry);
            break;

        case KM_TAG_ATTESTATION_ID_PRODUCT:
            found_mismatch |=
                    PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob, ids.product);
            values_to_attest->push_back(entry);
            break;

        case KM_TAG_ATTESTATION_ID_SERIAL:
            found_mismatch |=
                    PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob, ids.serial);
            values_to_attest->push_back(entry);
            break;

        case KM_TAG_ATTESTATION_ID_IMEI:
            found_mismatch |=
                    PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob, ids.imei);
            values_to_attest->push_back(entry);
            break;

        case KM_TAG_ATTESTATION_ID_MEID:
            found_mismatch |=
                    PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob, ids.meid);
            values_to_attest->push_back(entry);
            break;

        case KM_TAG_ATTESTATION_ID_MANUFACTURER:
            found_mismatch |= PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob,
                                                              ids.manufacturer);
            values_to_attest->push_back(entry);
            break;

        case KM_TAG_ATTESTATION_ID_MODEL:
            found_mismatch |=
                    PROTO_BYTES_DOES_NOT_MATCH_BLOB(entry.blob, ids.model);
            values_to_attest->push_back(entry);
            break;

        default:
            // Ignore non-ID tags.
            break;
        }
    }

    if (found_mismatch) {
        values_to_attest->Clear();
        return KM_ERROR_CANNOT_ATTEST_IDS;
    }

    return KM_ERROR_OK;
}

Buffer TrustyKeymasterContext::GenerateUniqueId(
        uint64_t creation_date_time,
        const keymaster_blob_t& application_id,
        bool reset_since_rotation,
        keymaster_error_t* error) const {
    if (unique_id_hbk_.empty()) {
        KeymasterKeyBlob hbk;
        keymaster_error_t derive_error =
                enforcement_policy_.GetUniqueIdKey(&hbk);
        if (derive_error != KM_ERROR_OK) {
            LOG_E("Failed to derive unique ID HBK: %d", derive_error);
            *error = derive_error;
            return {};
        }
        unique_id_hbk_ = std::vector(hbk.begin(), hbk.end());
    }

    *error = KM_ERROR_OK;
    return keymaster::generate_unique_id(unique_id_hbk_, creation_date_time,
                                         application_id, reset_since_rotation);
}

KeymasterKeyBlob TrustyKeymasterContext::GetAttestationKey(
        keymaster_algorithm_t algorithm,
        keymaster_error_t* error) const {
    AttestationKeySlot key_slot;

    switch (algorithm) {
    case KM_ALGORITHM_RSA:
        key_slot = AttestationKeySlot::kRsa;
        break;

    case KM_ALGORITHM_EC:
        key_slot = AttestationKeySlot::kEcdsa;
        break;

    default:
        *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
        return {};
    }

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    if (ss_manager == nullptr) {
        LOG_E("Failed to open secure storage session.", 0);
        *error = KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
        return {};
    }
    auto result = ss_manager->ReadKeyFromStorage(key_slot, error);
#if KEYMASTER_SOFT_ATTESTATION_FALLBACK
    if (*error != KM_ERROR_OK) {
        LOG_I("Failed to read attestation key from RPMB, falling back to test key",
              0);
        auto key = getAttestationKey(algorithm, error);
        if (*error != KM_ERROR_OK) {
            LOG_D("Software attestation key missing: %d", *error);
            return {};
        }
        result = KeymasterKeyBlob(*key);
        if (!result.key_material)
            *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
#endif
    return result;
}

CertificateChain TrustyKeymasterContext::GetAttestationChain(
        keymaster_algorithm_t algorithm,
        keymaster_error_t* error) const {
    AttestationKeySlot key_slot;
    switch (algorithm) {
    case KM_ALGORITHM_RSA:
        key_slot = AttestationKeySlot::kRsa;
        break;
    case KM_ALGORITHM_EC:
        key_slot = AttestationKeySlot::kEcdsa;
        break;
    default:
        *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
        return {};
    }

    CertificateChain chain;
    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    if (ss_manager == nullptr) {
        LOG_E("Failed to open secure storage session.", 0);
        *error = KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    } else {
        *error = ss_manager->ReadCertChainFromStorage(key_slot, &chain);
    }
#if KEYMASTER_SOFT_ATTESTATION_FALLBACK
    if ((*error != KM_ERROR_OK) || (chain.entry_count == 0)) {
        LOG_I("Failed to read attestation chain from RPMB, falling back to test chain",
              0);
        chain = getAttestationChain(algorithm, error);
    }
#endif
    return chain;
}

CertificateChain TrustyKeymasterContext::GenerateAttestation(
        const Key& key,
        const AuthorizationSet& attest_params,
        UniquePtr<Key> attest_key,
        const KeymasterBlob& issuer_subject,
        keymaster_error_t* error) const {
    *error = KM_ERROR_OK;
    keymaster_algorithm_t key_algorithm;
    if (!key.authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) {
        *error = KM_ERROR_UNKNOWN_ERROR;
        return {};
    }

    if ((key_algorithm != KM_ALGORITHM_RSA &&
         key_algorithm != KM_ALGORITHM_EC)) {
        *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
        return {};
    }

    // We have established that the given key has the correct algorithm, and
    // because this is the TrustyKeymasterContext we can assume that the Key is
    // an AsymmetricKey. So we can downcast.
    const AsymmetricKey& asymmetric_key =
            static_cast<const AsymmetricKey&>(key);

    AttestKeyInfo attest_key_info(attest_key, &issuer_subject, error);
    if (*error != KM_ERROR_OK) {
        return {};
    }

    return generate_attestation(asymmetric_key, attest_params,
                                std::move(attest_key_info), *this, error);
}

CertificateChain TrustyKeymasterContext::GenerateSelfSignedCertificate(
        const Key& key,
        const AuthorizationSet& cert_params,
        bool fake_signature,
        keymaster_error_t* error) const {
    keymaster_algorithm_t key_algorithm;
    if (!key.authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) {
        *error = KM_ERROR_UNKNOWN_ERROR;
        return {};
    }

    if ((key_algorithm != KM_ALGORITHM_RSA &&
         key_algorithm != KM_ALGORITHM_EC)) {
        *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
        return {};
    }

    const AsymmetricKey& asymmetric_key =
            static_cast<const AsymmetricKey&>(key);

    return generate_self_signed_cert(asymmetric_key, cert_params,
                                     fake_signature, error);
}

keymaster_error_t TrustyKeymasterContext::SetBootParams(
        uint32_t /* os_version */,
        uint32_t /* os_patchlevel */,
        const Buffer& verified_boot_key,
        keymaster_verified_boot_t verified_boot_state,
        bool device_locked,
        const Buffer& verified_boot_hash) {
    if (root_of_trust_set_)
        return KM_ERROR_ROOT_OF_TRUST_ALREADY_SET;
    boot_params_.verified_boot_hash.Reinitialize(verified_boot_hash);
    root_of_trust_set_ = true;
    boot_params_.verified_boot_state = verified_boot_state;
    boot_params_.device_locked = device_locked;
    boot_params_.verified_boot_key.Reinitialize("", 0);

    if (verified_boot_key.buffer_size()) {
        boot_params_.verified_boot_key.Reinitialize(verified_boot_key);
    } else {
        // If no boot key was passed, default to unverified/unlocked
        boot_params_.verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
    }

    if ((verified_boot_state != KM_VERIFIED_BOOT_VERIFIED) &&
        (verified_boot_state != KM_VERIFIED_BOOT_SELF_SIGNED)) {
        // If the device image was not verified or self signed, it cannot be
        // locked
        boot_params_.device_locked = false;
    }

    trusty_remote_provisioning_context_->SetBootParams(&boot_params_);

    return KM_ERROR_OK;
}

// Mostly adapted from pure_soft_keymaster_context.cpp
keymaster_error_t TrustyKeymasterContext::UnwrapKey(
        const KeymasterKeyBlob& wrapped_key_blob,
        const KeymasterKeyBlob& wrapping_key_blob,
        const AuthorizationSet& wrapping_key_params,
        const KeymasterKeyBlob& masking_key,
        AuthorizationSet* wrapped_key_params,
        keymaster_key_format_t* wrapped_key_format,
        KeymasterKeyBlob* wrapped_key_material) const {
    LOG_D("UnwrapKey:0", 0);

    keymaster_error_t error = KM_ERROR_OK;

    if (wrapped_key_material == NULL) {
        return KM_ERROR_UNEXPECTED_NULL_POINTER;
    }

    LOG_D("UnwrapKey:1", 0);
    // Step 1 from IKeymasterDevice.hal file spec
    // Parse wrapping key
    UniquePtr<Key> wrapping_key;
    error = ParseKeyBlob(wrapping_key_blob, wrapping_key_params, &wrapping_key);
    if (error != KM_ERROR_OK) {
        LOG_E("Failed to parse wrapping key", 0);
        return error;
    }

    AuthProxy wrapping_key_auths(wrapping_key->hw_enforced(),
                                 wrapping_key->sw_enforced());

    // Check Wrapping Key Purpose
    if (!wrapping_key_auths.Contains(TAG_PURPOSE, KM_PURPOSE_WRAP)) {
        LOG_E("Wrapping key did not have KM_PURPOSE_WRAP", 0);
        return KM_ERROR_INCOMPATIBLE_PURPOSE;
    }

    // Check Padding mode is RSA_OAEP and digest is SHA_2_256 (spec
    // mandated)
    if (!wrapping_key_auths.Contains(TAG_DIGEST, KM_DIGEST_SHA_2_256)) {
        LOG_E("Wrapping key lacks authorization for SHA2-256", 0);
        return KM_ERROR_INCOMPATIBLE_DIGEST;
    }
    if (!wrapping_key_auths.Contains(TAG_PADDING, KM_PAD_RSA_OAEP)) {
        LOG_E("Wrapping key lacks authorization for padding OAEP", 0);
        return KM_ERROR_INCOMPATIBLE_PADDING_MODE;
    }

    // Check that that was also the padding mode and digest specified
    if (!wrapping_key_params.Contains(TAG_DIGEST, KM_DIGEST_SHA_2_256)) {
        LOG_E("Wrapping key must use SHA2-256", 0);
        return KM_ERROR_INCOMPATIBLE_DIGEST;
    }
    if (!wrapping_key_params.Contains(TAG_PADDING, KM_PAD_RSA_OAEP)) {
        LOG_E("Wrapping key must use OAEP padding", 0);
        return KM_ERROR_INCOMPATIBLE_PADDING_MODE;
    }

    LOG_D("UnwrapKey:2", 0);
    // Step 2 from IKeymasterDevice.hal spec
    // Parse wrapped key
    KeymasterBlob iv;
    KeymasterKeyBlob transit_key;
    KeymasterKeyBlob secure_key;
    KeymasterBlob tag;
    KeymasterBlob wrapped_key_description;
    error = parse_wrapped_key(wrapped_key_blob, &iv, &transit_key, &secure_key,
                              &tag, wrapped_key_params, wrapped_key_format,
                              &wrapped_key_description);
    if (error != KM_ERROR_OK) {
        return error;
    }

    // Decrypt encryptedTransportKey (transit_key) with wrapping_key
    auto operation_factory = wrapping_key->key_factory()->GetOperationFactory(
            KM_PURPOSE_DECRYPT);
    if (operation_factory == NULL) {
        return KM_ERROR_UNKNOWN_ERROR;
    }

    AuthorizationSet out_params;
    OperationPtr operation(operation_factory->CreateOperation(
            std::move(*wrapping_key), wrapping_key_params, &error));
    if ((operation.get() == NULL) || (error != KM_ERROR_OK)) {
        return error;
    }

    error = operation->Begin(wrapping_key_params, &out_params);
    if (error != KM_ERROR_OK) {
        return error;
    }

    Buffer input;
    Buffer output;
    // Explicitly reinitialize rather than constructing in order to report
    // allocation failure.
    if (!input.Reinitialize(transit_key.key_material,
                            transit_key.key_material_size)) {
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    error = operation->Finish(wrapping_key_params, input,
                              Buffer() /* signature */, &out_params, &output);
    if (error != KM_ERROR_OK) {
        return error;
    }

    KeymasterKeyBlob transport_key = {
            output.peek_read(),
            output.available_read(),
    };

    LOG_D("UnwrapKey:3", 0);
    // Step 3 of IKeymasterDevice.hal
    // XOR the transit key with the masking key
    if (transport_key.key_material_size != masking_key.key_material_size) {
        return KM_ERROR_INVALID_ARGUMENT;
    }
    for (size_t i = 0; i < transport_key.key_material_size; i++) {
        transport_key.writable_data()[i] ^= masking_key.key_material[i];
    }

    LOG_D("UnwrapKey:4", 0);
    // Step 4 of IKeymasterDevice.hal
    // transit_key_authorizations is defined by spec
    // TODO the mac len is NOT in the spec, but probably should be
    auto transport_key_authorizations =
            AuthorizationSetBuilder()
                    .AesEncryptionKey(256)
                    .Padding(KM_PAD_NONE)
                    .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
                    .Authorization(TAG_NONCE, iv)
                    .Authorization(TAG_MIN_MAC_LENGTH, 128)
                    .build();
    auto validity = transport_key_authorizations.is_valid();
    if (validity != AuthorizationSet::Error::OK) {
        return TranslateAuthorizationSetError(validity);
    }

    // gcm_params is also defined by spec
    // TODO same problem with mac len not being specced
    auto gcm_params = AuthorizationSetBuilder()
                              .Padding(KM_PAD_NONE)
                              .Authorization(TAG_BLOCK_MODE, KM_MODE_GCM)
                              .Authorization(TAG_NONCE, iv)
                              .Authorization(TAG_MAC_LENGTH, 128)
                              .build();
    validity = gcm_params.is_valid();
    if (validity != AuthorizationSet::Error::OK) {
        return TranslateAuthorizationSetError(validity);
    }

    auto aes_factory = GetKeyFactory(KM_ALGORITHM_AES);
    if (aes_factory == NULL) {
        return KM_ERROR_UNKNOWN_ERROR;
    }

    UniquePtr<Key> aes_transport_key;
    error = aes_factory->LoadKey(std::move(transport_key), gcm_params,
                                 std::move(transport_key_authorizations),
                                 AuthorizationSet(), &aes_transport_key);
    if (error != KM_ERROR_OK) {
        return error;
    }

    auto aes_operation_factory =
            GetOperationFactory(KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT);
    if (aes_operation_factory == NULL) {
        return KM_ERROR_UNKNOWN_ERROR;
    }

    OperationPtr aes_operation(aes_operation_factory->CreateOperation(
            std::move(*aes_transport_key), gcm_params, &error));
    if ((aes_operation.get() == NULL) || (error != KM_ERROR_OK)) {
        return error;
    }

    error = aes_operation->Begin(gcm_params, &out_params);
    if (error != KM_ERROR_OK) {
        return error;
    }

    size_t update_consumed = 0;
    AuthorizationSet update_outparams;

    Buffer encrypted_key;
    Buffer plaintext_key;

    // Separate initialization to catch memory errors
    size_t total_key_size = secure_key.key_material_size + tag.data_length;
    if (!plaintext_key.Reinitialize(total_key_size)) {
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
    if (!encrypted_key.Reinitialize(total_key_size)) {
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    // Concatenate key data
    if (!encrypted_key.write(secure_key.key_material,
                             secure_key.key_material_size)) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    if (!encrypted_key.write(tag.data, tag.data_length)) {
        return KM_ERROR_UNKNOWN_ERROR;
    }

    auto update_params =
            AuthorizationSetBuilder()
                    .Authorization(TAG_ASSOCIATED_DATA,
                                   wrapped_key_description.data,
                                   wrapped_key_description.data_length)
                    .build();
    validity = update_params.is_valid();
    if (validity != AuthorizationSet::Error::OK) {
        return TranslateAuthorizationSetError(validity);
    }

    error = aes_operation->Update(update_params, encrypted_key,
                                  &update_outparams, &plaintext_key,
                                  &update_consumed);
    if (error != KM_ERROR_OK) {
        return error;
    }

    AuthorizationSet finish_params;
    AuthorizationSet finish_out_params;
    Buffer finish_input;
    error = aes_operation->Finish(finish_params, finish_input,
                                  Buffer() /* signature */, &finish_out_params,
                                  &plaintext_key);
    if (error != KM_ERROR_OK) {
        return error;
    }

    *wrapped_key_material = {plaintext_key.peek_read(),
                             plaintext_key.available_read()};

    if (!wrapped_key_material->key_material && plaintext_key.peek_read()) {
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    LOG_D("UnwrapKey:Done", 0);
    return error;
}

keymaster_error_t TrustyKeymasterContext::CheckConfirmationToken(
        const uint8_t* input_data,
        size_t input_data_size,
        const uint8_t confirmation_token[kConfirmationTokenSize]) const {
    // Note: ConfirmationUI is using the same secret key as auth tokens, the
    // difference is that messages are prefixed using the message tag
    // "confirmation token".
    keymaster_key_blob_t auth_token_key;
    keymaster_error_t error = GetAuthTokenKey(&auth_token_key);
    if (error != KM_ERROR_OK) {
        return error;
    }

    uint8_t computed_hash[EVP_MAX_MD_SIZE];
    unsigned int computed_hash_length;
    if (!HMAC(EVP_sha256(), auth_token_key.key_material,
              auth_token_key.key_material_size, input_data, input_data_size,
              computed_hash, &computed_hash_length)) {
        return KM_ERROR_UNKNOWN_ERROR;
    }

    if (computed_hash_length != kConfirmationTokenSize ||
        memcmp_s(computed_hash, confirmation_token, kConfirmationTokenSize) !=
                0) {
        return KM_ERROR_NO_USER_CONFIRMATION;
    }

    return KM_ERROR_OK;
}

}  // namespace keymaster
