/*
 * 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_SECOND_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_SECOND_IMEI:
            // TODO: Check that the second IMEI matches.
            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
