/*
 * Copyright (C) 2016 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "JSSubtleCrypto.h"

#if ENABLE(SUBTLE_CRYPTO)

#include "CryptoAlgorithm.h"
#include "CryptoAlgorithmRegistry.h"
#include "JSAesCbcParams.h"
#include "JSAesKeyGenParams.h"
#include "JSCryptoAlgorithmParameters.h"
#include "JSCryptoKey.h"
#include "JSCryptoKeyPair.h"
#include "JSDOMPromise.h"
#include "JSDOMWrapper.h"
#include "JSHmacKeyParams.h"
#include "JSJsonWebKey.h"
#include "JSRsaHashedImportParams.h"
#include "JSRsaHashedKeyGenParams.h"
#include "JSRsaKeyGenParams.h"
#include "JSRsaOaepParams.h"
#include "ScriptState.h"
#include <runtime/Error.h>
#include <runtime/IteratorOperations.h>
#include <runtime/JSArray.h>
#include <runtime/JSONObject.h>

using namespace JSC;

namespace WebCore {

enum class Operations {
    Encrypt,
    Decrypt,
    Sign,
    Verify,
    Digest,
    DeriveKey,
    DeriveBits,
    GenerateKey,
    ImportKey,
    WrapKey,
    UnwrapKey
};

static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState&, JSValue, Operations);

static CryptoAlgorithmIdentifier toHashIdentifier(ExecState& state, JSValue value)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    auto digestParams = normalizeCryptoAlgorithmParameters(state, value, Operations::Digest);
    RETURN_IF_EXCEPTION(scope, { });
    return digestParams->identifier;
}

static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState& state, JSValue value, Operations operation)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (value.isString()) {
        JSObject* newParams = constructEmptyObject(&state);
        newParams->putDirect(vm, Identifier::fromString(&vm, "name"), value);
        return normalizeCryptoAlgorithmParameters(state, newParams, operation);
    }

    if (value.isObject()) {
        auto params = convertDictionary<CryptoAlgorithmParameters>(state, value);
        RETURN_IF_EXCEPTION(scope, nullptr);

        auto identifier = CryptoAlgorithmRegistry::singleton().identifier(params.name);
        if (!identifier) {
            setDOMException(&state, NOT_SUPPORTED_ERR);
            return nullptr;
        }

        std::unique_ptr<CryptoAlgorithmParameters> result;
        switch (operation) {
        case Operations::Encrypt:
        case Operations::Decrypt:
            switch (*identifier) {
            case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
                result = std::make_unique<CryptoAlgorithmParameters>(params);
                break;
            case CryptoAlgorithmIdentifier::RSA_OAEP: {
                auto params = convertDictionary<CryptoAlgorithmRsaOaepParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmRsaOaepParams>(params);
                break;
            }
            case CryptoAlgorithmIdentifier::AES_CBC: {
                auto params = convertDictionary<CryptoAlgorithmAesCbcParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmAesCbcParams>(params);
                break;
            }
            default:
                setDOMException(&state, NOT_SUPPORTED_ERR);
                return nullptr;
            }
            break;
        case Operations::Sign:
        case Operations::Verify:
            switch (*identifier) {
            case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
            case CryptoAlgorithmIdentifier::HMAC:
                result = std::make_unique<CryptoAlgorithmParameters>(params);
                break;
            default:
                setDOMException(&state, NOT_SUPPORTED_ERR);
                return nullptr;
            }
            break;
        case Operations::Digest:
            switch (*identifier) {
            case CryptoAlgorithmIdentifier::SHA_1:
            case CryptoAlgorithmIdentifier::SHA_224:
            case CryptoAlgorithmIdentifier::SHA_256:
            case CryptoAlgorithmIdentifier::SHA_384:
            case CryptoAlgorithmIdentifier::SHA_512:
                result = std::make_unique<CryptoAlgorithmParameters>(params);
                break;
            default:
                setDOMException(&state, NOT_SUPPORTED_ERR);
                return nullptr;
            }
            break;
        case Operations::DeriveKey:
        case Operations::DeriveBits:
            setDOMException(&state, NOT_SUPPORTED_ERR);
            return nullptr;
        case Operations::GenerateKey:
            switch (*identifier) {
            case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: {
                auto params = convertDictionary<CryptoAlgorithmRsaKeyGenParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmRsaKeyGenParams>(params);
                break;
            }
            case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
            case CryptoAlgorithmIdentifier::RSA_PSS:
            case CryptoAlgorithmIdentifier::RSA_OAEP: {
                auto params = convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                params.hashIdentifier = toHashIdentifier(state, params.hash);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmRsaHashedKeyGenParams>(params);
                break;
            }
            case CryptoAlgorithmIdentifier::AES_CTR:
            case CryptoAlgorithmIdentifier::AES_CBC:
            case CryptoAlgorithmIdentifier::AES_CMAC:
            case CryptoAlgorithmIdentifier::AES_GCM:
            case CryptoAlgorithmIdentifier::AES_CFB:
            case CryptoAlgorithmIdentifier::AES_KW: {
                auto params = convertDictionary<CryptoAlgorithmAesKeyGenParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmAesKeyGenParams>(params);
                break;
            }
            case CryptoAlgorithmIdentifier::HMAC: {
                auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                params.hashIdentifier = toHashIdentifier(state, params.hash);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
                break;
            }
            default:
                setDOMException(&state, NOT_SUPPORTED_ERR);
                return nullptr;
            }
            break;
        case Operations::ImportKey:
            switch (*identifier) {
            case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
                result = std::make_unique<CryptoAlgorithmParameters>(params);
                break;
            case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
            case CryptoAlgorithmIdentifier::RSA_PSS:
            case CryptoAlgorithmIdentifier::RSA_OAEP: {
                auto params = convertDictionary<CryptoAlgorithmRsaHashedImportParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                params.hashIdentifier = toHashIdentifier(state, params.hash);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmRsaHashedImportParams>(params);
                break;
            }
            case CryptoAlgorithmIdentifier::AES_CTR:
            case CryptoAlgorithmIdentifier::AES_CBC:
            case CryptoAlgorithmIdentifier::AES_CMAC:
            case CryptoAlgorithmIdentifier::AES_GCM:
            case CryptoAlgorithmIdentifier::AES_CFB:
            case CryptoAlgorithmIdentifier::AES_KW:
                result = std::make_unique<CryptoAlgorithmParameters>(params);
                break;
            case CryptoAlgorithmIdentifier::HMAC: {
                auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value);
                RETURN_IF_EXCEPTION(scope, nullptr);
                params.hashIdentifier = toHashIdentifier(state, params.hash);
                RETURN_IF_EXCEPTION(scope, nullptr);
                result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
                break;
            }
            default:
                setDOMException(&state, NOT_SUPPORTED_ERR);
                return nullptr;
            }
            break;
        case Operations::WrapKey:
        case Operations::UnwrapKey:
            switch (*identifier) {
            case CryptoAlgorithmIdentifier::AES_KW:
                result = std::make_unique<CryptoAlgorithmParameters>(params);
                break;
            default:
                setDOMException(&state, NOT_SUPPORTED_ERR);
                return nullptr;
            }
            break;
        default:
            ASSERT_NOT_REACHED();
            return nullptr;
        }

        result->identifier = *identifier;
        return result;
    }

    throwTypeError(&state, scope, ASCIILiteral("Invalid AlgorithmIdentifier"));
    return nullptr;
}

static CryptoKeyUsageBitmap toCryptoKeyUsageBitmap(CryptoKeyUsage usage)
{
    switch (usage) {
    case CryptoKeyUsage::Encrypt:
        return CryptoKeyUsageEncrypt;
    case CryptoKeyUsage::Decrypt:
        return CryptoKeyUsageDecrypt;
    case CryptoKeyUsage::Sign:
        return CryptoKeyUsageSign;
    case CryptoKeyUsage::Verify:
        return CryptoKeyUsageVerify;
    case CryptoKeyUsage::DeriveKey:
        return CryptoKeyUsageDeriveKey;
    case CryptoKeyUsage::DeriveBits:
        return CryptoKeyUsageDeriveBits;
    case CryptoKeyUsage::WrapKey:
        return CryptoKeyUsageWrapKey;
    case CryptoKeyUsage::UnwrapKey:
        return CryptoKeyUsageUnwrapKey;
    }

    ASSERT_NOT_REACHED();
    return 0;
}

static CryptoKeyUsageBitmap cryptoKeyUsageBitmapFromJSValue(ExecState& state, JSValue value)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    CryptoKeyUsageBitmap result = 0;
    auto usages = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(state, value);
    RETURN_IF_EXCEPTION(scope, 0);
    // Maybe we shouldn't silently bypass duplicated usages?
    for (auto usage : usages)
        result |= toCryptoKeyUsageBitmap(usage);

    return result;
}

static RefPtr<CryptoAlgorithm> createAlgorithm(ExecState& state, CryptoAlgorithmIdentifier identifier)
{
    auto result = CryptoAlgorithmRegistry::singleton().create(identifier);
    if (!result)
        setDOMException(&state, NOT_SUPPORTED_ERR);
    return result;
}

// Maybe we want more specific error messages?
static void rejectWithException(Ref<DeferredPromise>&& passedPromise, ExceptionCode ec)
{
    switch (ec) {
    case NOT_SUPPORTED_ERR:
        passedPromise->reject(ec, ASCIILiteral("The algorithm is not supported"));
        return;
    case SYNTAX_ERR:
        passedPromise->reject(ec, ASCIILiteral("A required parameter was missing or out-of-range"));
        return;
    case INVALID_STATE_ERR:
        passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the current state of the provided key"));
        return;
    case INVALID_ACCESS_ERR:
        passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the provided key"));
        return;
    case UnknownError:
        passedPromise->reject(ec, ASCIILiteral("The operation failed for an unknown transient reason (e.g. out of memory)"));
        return;
    case DataError:
        passedPromise->reject(ec, ASCIILiteral("Data provided to an operation does not meet requirements"));
        return;
    case OperationError:
        passedPromise->reject(ec, ASCIILiteral("The operation failed for an operation-specific reason"));
        return;
    }
    ASSERT_NOT_REACHED();
}

static KeyData toKeyData(ExecState& state, SubtleCrypto::KeyFormat format, JSValue value)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    KeyData result;
    switch (format) {
    case SubtleCrypto::KeyFormat::Spki:
    case SubtleCrypto::KeyFormat::Pkcs8:
    case SubtleCrypto::KeyFormat::Raw: {
        BufferSource bufferSource = convert<IDLBufferSource>(state, value);
        RETURN_IF_EXCEPTION(scope, result);
        Vector<uint8_t> vector;
        vector.append(bufferSource.data(), bufferSource.length());
        result = WTFMove(vector);
        return result;
    }
    case SubtleCrypto::KeyFormat::Jwk: {
        result = convertDictionary<JsonWebKey>(state, value);
        RETURN_IF_EXCEPTION(scope, result);
        CryptoKeyUsageBitmap usages = 0;
        if (WTF::get<JsonWebKey>(result).key_ops) {
            // Maybe we shouldn't silently bypass duplicated usages?
            for (auto usage : WTF::get<JsonWebKey>(result).key_ops.value())
                usages |= toCryptoKeyUsageBitmap(usage);
        }
        WTF::get<JsonWebKey>(result).usages = usages;
        return result;
    }
    }
    ASSERT_NOT_REACHED();
    return result;
}

// FIXME: We should get rid of this once https://bugs.webkit.org/show_bug.cgi?id=163711 is fixed.
static JSValue toJSValueFromJsonWebKey(JSDOMGlobalObject& globalObject, JsonWebKey&& key)
{
    ExecState& state = *globalObject.globalExec();
    VM& vm = state.vm();

    auto* result = constructEmptyObject(&state);
    result->putDirect(vm, Identifier::fromString(&vm, "kty"), toJS<IDLDOMString>(state, key.kty));
    if (key.use)
        result->putDirect(vm, Identifier::fromString(&vm, "use"), toJS<IDLDOMString>(state, key.use.value()));
    if (key.key_ops)
        result->putDirect(vm, Identifier::fromString(&vm, "key_ops"), toJS<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(state, globalObject, key.key_ops.value()));
    if (key.alg)
        result->putDirect(vm, Identifier::fromString(&vm, "alg"), toJS<IDLDOMString>(state, key.alg.value()));
    if (key.ext)
        result->putDirect(vm, Identifier::fromString(&vm, "ext"), toJS<IDLBoolean>(state, key.ext.value()));
    if (key.crv)
        result->putDirect(vm, Identifier::fromString(&vm, "crv"), toJS<IDLDOMString>(state, key.crv.value()));
    if (key.x)
        result->putDirect(vm, Identifier::fromString(&vm, "x"), toJS<IDLDOMString>(state, key.x.value()));
    if (key.y)
        result->putDirect(vm, Identifier::fromString(&vm, "y"), toJS<IDLDOMString>(state, key.y.value()));
    if (key.d)
        result->putDirect(vm, Identifier::fromString(&vm, "d"), toJS<IDLDOMString>(state, key.d.value()));
    if (key.n)
        result->putDirect(vm, Identifier::fromString(&vm, "n"), toJS<IDLDOMString>(state, key.n.value()));
    if (key.e)
        result->putDirect(vm, Identifier::fromString(&vm, "e"), toJS<IDLDOMString>(state, key.e.value()));
    if (key.p)
        result->putDirect(vm, Identifier::fromString(&vm, "p"), toJS<IDLDOMString>(state, key.p.value()));
    if (key.q)
        result->putDirect(vm, Identifier::fromString(&vm, "q"), toJS<IDLDOMString>(state, key.q.value()));
    if (key.dp)
        result->putDirect(vm, Identifier::fromString(&vm, "dp"), toJS<IDLDOMString>(state, key.dp.value()));
    if (key.dq)
        result->putDirect(vm, Identifier::fromString(&vm, "dq"), toJS<IDLDOMString>(state, key.dq.value()));
    if (key.qi)
        result->putDirect(vm, Identifier::fromString(&vm, "qi"), toJS<IDLDOMString>(state, key.qi.value()));
    if (key.oth) {
        MarkedArgumentBuffer list;
        for (auto& value : key.oth.value()) {
            auto* info = constructEmptyObject(&state);
            info->putDirect(vm, Identifier::fromString(&vm, "r"), toJS<IDLDOMString>(state, value.r));
            info->putDirect(vm, Identifier::fromString(&vm, "d"), toJS<IDLDOMString>(state, value.d));
            info->putDirect(vm, Identifier::fromString(&vm, "t"), toJS<IDLDOMString>(state, value.t));
            list.append(info);
        }
        result->putDirect(vm, Identifier::fromString(&vm, "oth"), constructArray(&state, static_cast<Structure*>(nullptr), list));
    }
    if (key.k)
        result->putDirect(vm, Identifier::fromString(&vm, "k"), toJS<IDLDOMString>(state, key.k.value()));

    return result;
}

static RefPtr<CryptoKey> toCryptoKey(ExecState& state, JSValue value)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    RefPtr<CryptoKey> result = JSCryptoKey::toWrapped(value);
    if (!result) {
        throwTypeError(&state, scope, ASCIILiteral("Invalid CryptoKey"));
        return nullptr;
    }
    return result;
}

static Vector<uint8_t> toVector(ExecState& state, JSValue value)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    BufferSource data = convert<IDLBufferSource>(state, value);
    RETURN_IF_EXCEPTION(scope, { });
    Vector<uint8_t> dataVector;
    dataVector.append(data.data(), data.length());

    return dataVector;
}

static void supportExportKeyThrow(ExecState& state, CryptoAlgorithmIdentifier identifier)
{
    switch (identifier) {
    case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
    case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
    case CryptoAlgorithmIdentifier::RSA_PSS:
    case CryptoAlgorithmIdentifier::RSA_OAEP:
    case CryptoAlgorithmIdentifier::AES_CTR:
    case CryptoAlgorithmIdentifier::AES_CBC:
    case CryptoAlgorithmIdentifier::AES_CMAC:
    case CryptoAlgorithmIdentifier::AES_GCM:
    case CryptoAlgorithmIdentifier::AES_CFB:
    case CryptoAlgorithmIdentifier::AES_KW:
    case CryptoAlgorithmIdentifier::HMAC:
        return;
    default:
        setDOMException(&state, NOT_SUPPORTED_ERR);
    }
}

static void jsSubtleCryptoFunctionEncryptPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 3)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Encrypt);
    RETURN_IF_EXCEPTION(scope, void());

    auto key = toCryptoKey(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto data = toVector(state, state.uncheckedArgument(2));
    RETURN_IF_EXCEPTION(scope, void());

    if (params->identifier != key->algorithmIdentifier()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

    if (!key->allows(CryptoKeyUsageEncrypt)) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support encryption"));
        return;
    }

    auto algorithm = createAlgorithm(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& cipherText) mutable {
        fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), cipherText.data(), cipherText.size());
        return;
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
    ASSERT(subtle);
    algorithm->encrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
}

static void jsSubtleCryptoFunctionDecryptPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 3)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Decrypt);
    RETURN_IF_EXCEPTION(scope, void());

    auto key = toCryptoKey(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto data = toVector(state, state.uncheckedArgument(2));
    RETURN_IF_EXCEPTION(scope, void());

    if (params->identifier != key->algorithmIdentifier()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

    if (!key->allows(CryptoKeyUsageDecrypt)) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support decryption"));
        return;
    }

    auto algorithm = createAlgorithm(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& plainText) mutable {
        fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), plainText.data(), plainText.size());
        return;
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
    ASSERT(subtle);
    algorithm->decrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
}

static void jsSubtleCryptoFunctionSignPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 3)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Sign);
    RETURN_IF_EXCEPTION(scope, void());

    auto key = toCryptoKey(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto data = toVector(state, state.uncheckedArgument(2));
    RETURN_IF_EXCEPTION(scope, void());

    if (params->identifier != key->algorithmIdentifier()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

    if (!key->allows(CryptoKeyUsageSign)) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support signing"));
        return;
    }

    auto algorithm = createAlgorithm(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& signature) mutable {
        fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), signature.data(), signature.size());
        return;
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    JSSubtleCrypto* subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
    ASSERT(subtle);
    algorithm->sign(key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
}

static void jsSubtleCryptoFunctionVerifyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 4)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Verify);
    RETURN_IF_EXCEPTION(scope, void());

    auto key = toCryptoKey(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto signature = toVector(state, state.uncheckedArgument(2));
    RETURN_IF_EXCEPTION(scope, void());

    auto data = toVector(state, state.uncheckedArgument(3));
    RETURN_IF_EXCEPTION(scope, void());

    if (params->identifier != key->algorithmIdentifier()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

    if (!key->allows(CryptoKeyUsageVerify)) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support verification"));
        return;
    }

    auto algorithm = createAlgorithm(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](bool result) mutable {
        capturedPromise->resolve<IDLBoolean>(result);
        return;
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
    ASSERT(subtle);
    algorithm->verify(key.releaseNonNull(), WTFMove(signature), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
}

static void jsSubtleCryptoFunctionDigestPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 2)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Digest);
    RETURN_IF_EXCEPTION(scope, void());

    auto data = toVector(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto algorithm = createAlgorithm(state, params->identifier);
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& digest) mutable {
        fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), digest.data(), digest.size());
        return;
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
    ASSERT(subtle);
    algorithm->digest(WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
}

static void jsSubtleCryptoFunctionDeriveKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 5)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveKey);
    RETURN_IF_EXCEPTION(scope, void());

    // We should always return a NOT_SUPPORTED_ERR since we currently don't support any algorithms that has deriveKey operation.
    ASSERT_NOT_REACHED();
}

static void jsSubtleCryptoFunctionDeriveBitsPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 3)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveBits);
    RETURN_IF_EXCEPTION(scope, void());

    // We should always return a NOT_SUPPORTED_ERR since we currently don't support any algorithms that has deriveBits operation.
    ASSERT_NOT_REACHED();
}

static void jsSubtleCryptoFunctionGenerateKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 3)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::GenerateKey);
    RETURN_IF_EXCEPTION(scope, void());

    auto extractable = state.uncheckedArgument(1).toBoolean(&state);
    RETURN_IF_EXCEPTION(scope, void());

    auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(2));
    RETURN_IF_EXCEPTION(scope, void());

    auto algorithm = createAlgorithm(state, params->identifier);
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](KeyOrKeyPair&& keyOrKeyPair) mutable {
        WTF::switchOn(keyOrKeyPair,
            [&capturedPromise] (RefPtr<CryptoKey>& key) {
                if ((key->type() == CryptoKeyType::Private || key->type() == CryptoKeyType::Secret) && !key->usagesBitmap()) {
                    rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR);
                    return;
                }
                capturedPromise->resolve<IDLInterface<CryptoKey>>(*key);
            },
            [&capturedPromise] (CryptoKeyPair& keyPair) {
                if (!keyPair.privateKey->usagesBitmap()) {
                    rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR);
                    return;
                }
                capturedPromise->resolve<IDLDictionary<CryptoKeyPair>>(keyPair);
            }
        );
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously
    // regardless what kind of keys it produces: https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-generateKey
    // That's simply not efficient for AES and HMAC keys. Therefore, we perform it as an async task conditionally.
    algorithm->generateKey(*params, extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state));
}

static void jsSubtleCryptoFunctionImportKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 5)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, void());

    auto keyData = toKeyData(state, format, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(2), Operations::ImportKey);
    RETURN_IF_EXCEPTION(scope, void());

    auto extractable = state.uncheckedArgument(3).toBoolean(&state);
    RETURN_IF_EXCEPTION(scope, void());

    auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(4));
    RETURN_IF_EXCEPTION(scope, void());

    auto algorithm = createAlgorithm(state, params->identifier);
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](CryptoKey& key) mutable {
        if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) {
            rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR);
            return;
        }
        capturedPromise->resolve<IDLInterface<CryptoKey>>(key);
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
    // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey
    // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
    algorithm->importKey(format, WTFMove(keyData), WTFMove(params), extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback));
}

static void jsSubtleCryptoFunctionExportKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 2)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, void());

    auto key = toCryptoKey(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    supportExportKeyThrow(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    if (!key->extractable()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable"));
        return;
    }

    auto algorithm = createAlgorithm(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [capturedPromise = promise.copyRef()](SubtleCrypto::KeyFormat format, KeyData&& key) mutable {
        switch (format) {
        case SubtleCrypto::KeyFormat::Spki:
        case SubtleCrypto::KeyFormat::Pkcs8:
        case SubtleCrypto::KeyFormat::Raw: {
            Vector<uint8_t>& rawKey = WTF::get<Vector<uint8_t>>(key);
            fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), rawKey.data(), rawKey.size());
            return;
        }
        case SubtleCrypto::KeyFormat::Jwk:
            capturedPromise->resolve<IDLAny>(toJSValueFromJsonWebKey(*(capturedPromise->globalObject()), WTFMove(WTF::get<JsonWebKey>(key))));
            return;
        }
        ASSERT_NOT_REACHED();
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
    // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-exportKey
    // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
    algorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback));
}

static void jsSubtleCryptoFunctionWrapKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 4)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, void());

    auto key = toCryptoKey(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto wrappingKey = toCryptoKey(state, state.uncheckedArgument(2));
    RETURN_IF_EXCEPTION(scope, void());

    auto catchScope = DECLARE_CATCH_SCOPE(vm);
    bool isEncryption = false;
    auto wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::WrapKey);
    if (catchScope.exception()) {
        catchScope.clearException();
        wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::Encrypt);
        RETURN_IF_EXCEPTION(scope, void());
        isEncryption = true;
    }

    if (wrapParams->identifier != wrappingKey->algorithmIdentifier()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

    if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't support wrapKey operation"));
        return;
    }

    supportExportKeyThrow(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    if (!key->extractable()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable"));
        return;
    }

    auto exportAlgorithm = createAlgorithm(state, key->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto wrapAlgorithm = createAlgorithm(state, wrappingKey->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto context = scriptExecutionContextFromExecState(&state);

    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
    ASSERT(subtle);
    auto& workQueue = subtle->wrapped().workQueue();

    auto callback = [promise = promise.copyRef(), wrapAlgorithm, wrappingKey = WTFMove(wrappingKey), wrapParams = WTFMove(wrapParams), isEncryption, context, &workQueue](SubtleCrypto::KeyFormat format, KeyData&& key) mutable {
        Vector<uint8_t> bytes;
        switch (format) {
        case SubtleCrypto::KeyFormat::Spki:
        case SubtleCrypto::KeyFormat::Pkcs8:
        case SubtleCrypto::KeyFormat::Raw:
            bytes = WTF::get<Vector<uint8_t>>(key);
            break;
        case SubtleCrypto::KeyFormat::Jwk: {
            auto jwk = toJSValueFromJsonWebKey(*(promise->globalObject()), WTFMove(WTF::get<JsonWebKey>(key)));
            String jwkString = JSONStringify(promise->globalObject()->globalExec(), jwk, 0);
            CString jwkUtf8String = jwkString.utf8(StrictConversion);
            bytes.append(jwkUtf8String.data(), jwkUtf8String.length());
        }
        }

        auto callback = [promise = promise.copyRef()](const Vector<uint8_t>& wrappedKey) mutable {
            fulfillPromiseWithArrayBuffer(WTFMove(promise), wrappedKey.data(), wrappedKey.size());
            return;
        };
        auto exceptionCallback = [promise = WTFMove(promise)](ExceptionCode ec) mutable {
            rejectWithException(WTFMove(promise), ec);
        };

        if (!isEncryption) {
            // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
            // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey
            // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
            wrapAlgorithm->wrapKey(wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback));
            return;
        }
        // The following operation should be performed asynchronously.
        wrapAlgorithm->encrypt(WTFMove(wrapParams), wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback), *context, workQueue);
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    // The following operation should be performed synchronously.
    exportAlgorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback));
}

static void jsSubtleCryptoFunctionUnwrapKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (UNLIKELY(state.argumentCount() < 7)) {
        promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
        return;
    }

    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, void());

    auto wrappedKey = toVector(state, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, void());

    auto unwrappingKey = toCryptoKey(state, state.uncheckedArgument(2));
    RETURN_IF_EXCEPTION(scope, void());

    auto catchScope = DECLARE_CATCH_SCOPE(vm);
    bool isDecryption = false;
    auto unwrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::UnwrapKey);
    if (catchScope.exception()) {
        catchScope.clearException();
        unwrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::Decrypt);
        RETURN_IF_EXCEPTION(scope, void());
        isDecryption = true;
    }

    auto unwrappedKeyAlgorithm = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(4), Operations::ImportKey);
    RETURN_IF_EXCEPTION(scope, void());

    auto extractable = state.uncheckedArgument(5).toBoolean(&state);
    RETURN_IF_EXCEPTION(scope, void());

    auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(6));
    RETURN_IF_EXCEPTION(scope, void());

    if (unwrapParams->identifier != unwrappingKey->algorithmIdentifier()) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Unwrapping CryptoKey doesn't match unwrap AlgorithmIdentifier"));
        return;
    }

    if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Unwrapping CryptoKey doesn't support unwrapKey operation"));
        return;
    }

    auto importAlgorithm = createAlgorithm(state, unwrappedKeyAlgorithm->identifier);
    RETURN_IF_EXCEPTION(scope, void());

    auto unwrapAlgorithm = createAlgorithm(state, unwrappingKey->algorithmIdentifier());
    RETURN_IF_EXCEPTION(scope, void());

    auto callback = [promise = promise.copyRef(), format, importAlgorithm, unwrappedKeyAlgorithm = WTFMove(unwrappedKeyAlgorithm), extractable, keyUsages](const Vector<uint8_t>& bytes) mutable {
        ExecState& state = *(promise->globalObject()->globalExec());
        VM& vm = state.vm();
        auto scope = DECLARE_THROW_SCOPE(vm);

        KeyData keyData;
        switch (format) {
        case SubtleCrypto::KeyFormat::Spki:
        case SubtleCrypto::KeyFormat::Pkcs8:
        case SubtleCrypto::KeyFormat::Raw:
            keyData = bytes;
            break;
        case SubtleCrypto::KeyFormat::Jwk: {
            String jwkString(reinterpret_cast_ptr<const char*>(bytes.data()), bytes.size());
            JSC::JSLockHolder locker(vm);
            auto jwk = JSONParse(&state, jwkString);
            if (!jwk) {
                promise->reject(DataError, ASCIILiteral("WrappedKey cannot be converted to a JSON object"));
                return;
            }
            keyData = toKeyData(state, format, jwk);
            RETURN_IF_EXCEPTION(scope, void());
        }
        }

        auto callback = [promise = promise.copyRef()](CryptoKey& key) mutable {
            if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) {
                rejectWithException(WTFMove(promise), SYNTAX_ERR);
                return;
            }
            promise->resolve<IDLInterface<CryptoKey>>(key);
        };
        auto exceptionCallback = [promise = WTFMove(promise)](ExceptionCode ec) mutable {
            rejectWithException(WTFMove(promise), ec);
        };

        // The following operation should be performed synchronously.
        importAlgorithm->importKey(format, WTFMove(keyData), WTFMove(unwrappedKeyAlgorithm), extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback));
    };
    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
        rejectWithException(WTFMove(capturedPromise), ec);
    };

    if (!isDecryption) {
        // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
        // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-unwrapKey
        // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
        unwrapAlgorithm->unwrapKey(unwrappingKey.releaseNonNull(), WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback));
        return;
    }
    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
    ASSERT(subtle);
    // The following operation should be performed asynchronously.
    unwrapAlgorithm->decrypt(WTFMove(unwrapParams), unwrappingKey.releaseNonNull(), WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
}

JSValue JSSubtleCrypto::encrypt(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionEncryptPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::decrypt(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionDecryptPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::sign(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionSignPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::verify(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionVerifyPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::digest(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionDigestPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::deriveKey(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionDeriveKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::deriveBits(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionDeriveBitsPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::generateKey(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionGenerateKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::importKey(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionImportKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::exportKey(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionExportKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::wrapKey(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionWrapKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

JSValue JSSubtleCrypto::unwrapKey(ExecState& state)
{
    return callPromiseFunction<jsSubtleCryptoFunctionUnwrapKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
}

} // namespace WebCore

#endif
