/*
 * Copyright (C) 2016-2019 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 "SubtleCrypto.h"

#if ENABLE(WEB_CRYPTO)

#include "CryptoAlgorithm.h"
#include "CryptoAlgorithmRegistry.h"
#include "JSAesCbcCfbParams.h"
#include "JSAesCtrParams.h"
#include "JSAesGcmParams.h"
#include "JSAesKeyParams.h"
#include "JSCryptoAlgorithmParameters.h"
#include "JSCryptoKey.h"
#include "JSCryptoKeyPair.h"
#include "JSDOMPromiseDeferred.h"
#include "JSDOMWrapper.h"
#include "JSEcKeyParams.h"
#include "JSEcdhKeyDeriveParams.h"
#include "JSEcdsaParams.h"
#include "JSHkdfParams.h"
#include "JSHmacKeyParams.h"
#include "JSJsonWebKey.h"
#include "JSPbkdf2Params.h"
#include "JSRsaHashedImportParams.h"
#include "JSRsaHashedKeyGenParams.h"
#include "JSRsaKeyGenParams.h"
#include "JSRsaOaepParams.h"
#include "JSRsaPssParams.h"
#include <JavaScriptCore/JSONObject.h>

namespace WebCore {
using namespace JSC;

SubtleCrypto::SubtleCrypto(ScriptExecutionContext* context)
    : ContextDestructionObserver(context)
    , m_workQueue(WorkQueue::create("com.apple.WebKit.CryptoQueue"))
{
}

SubtleCrypto::~SubtleCrypto() = default;

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

static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAlgorithmParameters(JSGlobalObject&, WebCore::SubtleCrypto::AlgorithmIdentifier, Operations);

static ExceptionOr<CryptoAlgorithmIdentifier> toHashIdentifier(JSGlobalObject& state, SubtleCrypto::AlgorithmIdentifier algorithmIdentifier)
{
    auto digestParams = normalizeCryptoAlgorithmParameters(state, algorithmIdentifier, Operations::Digest);
    if (digestParams.hasException())
        return digestParams.releaseException();
    return digestParams.returnValue()->identifier;
}

static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAlgorithmParameters(JSGlobalObject& state, SubtleCrypto::AlgorithmIdentifier algorithmIdentifier, Operations operation)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (std::holds_alternative<String>(algorithmIdentifier)) {
        auto newParams = Strong<JSObject>(vm, constructEmptyObject(&state));
        newParams->putDirect(vm, Identifier::fromString(vm, "name"), jsString(vm, WTF::get<String>(algorithmIdentifier)));
        
        return normalizeCryptoAlgorithmParameters(state, newParams, operation);
    }

    auto& value = WTF::get<JSC::Strong<JSC::JSObject>>(algorithmIdentifier);

    auto params = convertDictionary<CryptoAlgorithmParameters>(state, value.get());
    RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });

    auto identifier = CryptoAlgorithmRegistry::singleton().identifier(params.name);
    if (UNLIKELY(!identifier))
        return Exception { NotSupportedError };

    std::unique_ptr<CryptoAlgorithmParameters> result;
    switch (operation) {
    case Operations::Encrypt:
    case Operations::Decrypt:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
            result = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        case CryptoAlgorithmIdentifier::RSA_OAEP: {
            auto params = convertDictionary<CryptoAlgorithmRsaOaepParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmRsaOaepParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_CBC:
        case CryptoAlgorithmIdentifier::AES_CFB: {
            auto params = convertDictionary<CryptoAlgorithmAesCbcCfbParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmAesCbcCfbParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_CTR: {
            auto params = convertDictionary<CryptoAlgorithmAesCtrParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmAesCtrParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_GCM: {
            auto params = convertDictionary<CryptoAlgorithmAesGcmParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmAesGcmParams>(params);
            break;
        }
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::Sign:
    case Operations::Verify:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
        case CryptoAlgorithmIdentifier::HMAC:
            result = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        case CryptoAlgorithmIdentifier::ECDSA: {
            auto params = convertDictionary<CryptoAlgorithmEcdsaParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmEcdsaParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::RSA_PSS: {
            auto params = convertDictionary<CryptoAlgorithmRsaPssParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmRsaPssParams>(params);
            break;
        }
        default:
            return Exception { NotSupportedError };
        }
        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 = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::GenerateKey:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: {
            auto params = convertDictionary<CryptoAlgorithmRsaKeyGenParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmRsaKeyGenParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
        case CryptoAlgorithmIdentifier::RSA_PSS:
        case CryptoAlgorithmIdentifier::RSA_OAEP: {
            auto params = convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmRsaHashedKeyGenParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_CTR:
        case CryptoAlgorithmIdentifier::AES_CBC:
        case CryptoAlgorithmIdentifier::AES_GCM:
        case CryptoAlgorithmIdentifier::AES_CFB:
        case CryptoAlgorithmIdentifier::AES_KW: {
            auto params = convertDictionary<CryptoAlgorithmAesKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmAesKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::HMAC: {
            auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmHmacKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::ECDSA:
        case CryptoAlgorithmIdentifier::ECDH: {
            auto params = convertDictionary<CryptoAlgorithmEcKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmEcKeyParams>(params);
            break;
        }
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::DeriveBits:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::ECDH: {
            // Remove this hack once https://bugs.webkit.org/show_bug.cgi?id=169333 is fixed.
            JSValue nameValue = value.get()->get(&state, Identifier::fromString(vm, "name"));
            JSValue publicValue = value.get()->get(&state, Identifier::fromString(vm, "public"));
            JSObject* newValue = constructEmptyObject(&state);
            newValue->putDirect(vm, Identifier::fromString(vm, "name"), nameValue);
            newValue->putDirect(vm, Identifier::fromString(vm, "publicKey"), publicValue);

            auto params = convertDictionary<CryptoAlgorithmEcdhKeyDeriveParams>(state, newValue);
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmEcdhKeyDeriveParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::HKDF: {
            auto params = convertDictionary<CryptoAlgorithmHkdfParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmHkdfParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::PBKDF2: {
            auto params = convertDictionary<CryptoAlgorithmPbkdf2Params>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmPbkdf2Params>(params);
            break;
        }
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::ImportKey:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
            result = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
        case CryptoAlgorithmIdentifier::RSA_PSS:
        case CryptoAlgorithmIdentifier::RSA_OAEP: {
            auto params = convertDictionary<CryptoAlgorithmRsaHashedImportParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmRsaHashedImportParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_CTR:
        case CryptoAlgorithmIdentifier::AES_CBC:
        case CryptoAlgorithmIdentifier::AES_GCM:
        case CryptoAlgorithmIdentifier::AES_CFB:
        case CryptoAlgorithmIdentifier::AES_KW:
            result = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        case CryptoAlgorithmIdentifier::HMAC: {
            auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmHmacKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::ECDSA:
        case CryptoAlgorithmIdentifier::ECDH: {
            auto params = convertDictionary<CryptoAlgorithmEcKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmEcKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::HKDF:
        case CryptoAlgorithmIdentifier::PBKDF2:
            result = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::WrapKey:
    case Operations::UnwrapKey:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::AES_KW:
            result = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::GetKeyLength:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::AES_CTR:
        case CryptoAlgorithmIdentifier::AES_CBC:
        case CryptoAlgorithmIdentifier::AES_GCM:
        case CryptoAlgorithmIdentifier::AES_CFB:
        case CryptoAlgorithmIdentifier::AES_KW: {
            auto params = convertDictionary<CryptoAlgorithmAesKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = makeUnique<CryptoAlgorithmAesKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::HMAC: {
            auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = makeUnique<CryptoAlgorithmHmacKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::HKDF:
        case CryptoAlgorithmIdentifier::PBKDF2:
            result = makeUnique<CryptoAlgorithmParameters>(params);
            break;
        default:
            return Exception { NotSupportedError };
        }
        break;
    }

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

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

    RELEASE_ASSERT_NOT_REACHED();
}

static CryptoKeyUsageBitmap toCryptoKeyUsageBitmap(const Vector<CryptoKeyUsage>& usages)
{
    CryptoKeyUsageBitmap result = 0;
    // Maybe we shouldn't silently bypass duplicated usages?
    for (auto usage : usages)
        result |= toCryptoKeyUsageBitmap(usage);

    return result;
}

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

static void normalizeJsonWebKey(JsonWebKey& webKey)
{
    // Maybe we shouldn't silently bypass duplicated usages?
    webKey.usages = webKey.key_ops ? toCryptoKeyUsageBitmap(webKey.key_ops.value()) : 0;
}

// FIXME: This returns an std::optional<KeyData> and takes a promise, rather than returning an
// ExceptionOr<KeyData> and letting the caller handle the promise, to work around an issue where
// Variant types (which KeyData is) in ExceptionOr<> cause compile issues on some platforms. This
// should be resolved by adopting a standards compliant std::variant (see https://webkit.org/b/175583)
static std::optional<KeyData> toKeyData(SubtleCrypto::KeyFormat format, SubtleCrypto::KeyDataVariant&& keyDataVariant, Ref<DeferredPromise>& promise)
{
    switch (format) {
    case SubtleCrypto::KeyFormat::Spki:
    case SubtleCrypto::KeyFormat::Pkcs8:
    case SubtleCrypto::KeyFormat::Raw:
        return WTF::switchOn(keyDataVariant,
            [&promise] (JsonWebKey&) -> std::optional<KeyData> {
                promise->reject(Exception { TypeError });
                return std::nullopt;
            },
            [] (auto& bufferSource) -> std::optional<KeyData> {
                return KeyData { Vector { static_cast<const uint8_t*>(bufferSource->data()), bufferSource->byteLength() } };
            }
        );
    case SubtleCrypto::KeyFormat::Jwk:
        return WTF::switchOn(keyDataVariant,
            [] (JsonWebKey& webKey) -> std::optional<KeyData> {
                normalizeJsonWebKey(webKey);
                return KeyData { webKey };
            },
            [&promise] (auto&) -> std::optional<KeyData> {
                promise->reject(Exception { TypeError });
                return std::nullopt;
            }
        );
    }

    RELEASE_ASSERT_NOT_REACHED();
}

static Vector<uint8_t> copyToVector(BufferSource&& data)
{
    return { data.data(), data.length() };
}

static bool isSupportedExportKey(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_GCM:
    case CryptoAlgorithmIdentifier::AES_CFB:
    case CryptoAlgorithmIdentifier::AES_KW:
    case CryptoAlgorithmIdentifier::HMAC:
    case CryptoAlgorithmIdentifier::ECDSA:
    case CryptoAlgorithmIdentifier::ECDH:
        return true;
    default:
        return false;
    }
}

RefPtr<DeferredPromise> getPromise(DeferredPromise* index, WeakPtr<SubtleCrypto> subtleCryptoWeakPointer)
{
    if (subtleCryptoWeakPointer)
        return subtleCryptoWeakPointer->m_pendingPromises.take(index);
    return nullptr;
}

static std::unique_ptr<CryptoAlgorithmParameters> crossThreadCopyImportParams(const CryptoAlgorithmParameters& importParams)
{
    switch (importParams.parametersClass()) {
    case CryptoAlgorithmParameters::Class::None: {
        auto result = makeUnique<CryptoAlgorithmParameters>();
        result->identifier = importParams.identifier;
        return result;
    }
    case CryptoAlgorithmParameters::Class::EcKeyParams:
        return makeUnique<CryptoAlgorithmEcKeyParams>(crossThreadCopy(downcast<CryptoAlgorithmEcKeyParams>(importParams)));
    case CryptoAlgorithmParameters::Class::HmacKeyParams:
        return makeUnique<CryptoAlgorithmHmacKeyParams>(crossThreadCopy(downcast<CryptoAlgorithmHmacKeyParams>(importParams)));
    case CryptoAlgorithmParameters::Class::RsaHashedImportParams:
        return makeUnique<CryptoAlgorithmRsaHashedImportParams>(crossThreadCopy(downcast<CryptoAlgorithmRsaHashedImportParams>(importParams)));
    default:
        ASSERT_NOT_REACHED();
        return nullptr;
    }
}

void SubtleCrypto::addAuthenticatedEncryptionWarningIfNecessary(CryptoAlgorithmIdentifier algorithmIdentifier)
{
    if (algorithmIdentifier == CryptoAlgorithmIdentifier::AES_CBC || algorithmIdentifier == CryptoAlgorithmIdentifier::AES_CTR)
        scriptExecutionContext()->addConsoleMessage(MessageSource::Security, MessageLevel::Warning, "AES-CBC and AES-CTR do not provide authentication by default, and implementing it manually can result in minor, but serious mistakes. We recommended using authenticated encryption like AES-GCM to protect against chosen-ciphertext attacks.");
}

// MARK: - Exposed functions.

void SubtleCrypto::encrypt(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise)
{
    addAuthenticatedEncryptionWarningIfNecessary(key.algorithmIdentifier());

    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Encrypt);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto data = copyToVector(WTFMove(dataBufferSource));

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

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

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier());

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](const Vector<uint8_t>& cipherText) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), cipherText.data(), cipherText.size());
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    algorithm->encrypt(*params, key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::decrypt(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise)
{
    addAuthenticatedEncryptionWarningIfNecessary(key.algorithmIdentifier());

    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Decrypt);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto data = copyToVector(WTFMove(dataBufferSource));

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

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

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier());

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](const Vector<uint8_t>& plainText) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), plainText.data(), plainText.size());
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    algorithm->decrypt(*params, key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::sign(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise)
{
    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Sign);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto data = copyToVector(WTFMove(dataBufferSource));

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

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

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier());

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](const Vector<uint8_t>& signature) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), signature.data(), signature.size());
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    algorithm->sign(*params, key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::verify(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& signatureBufferSource, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise)
{
    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Verify);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto signature = copyToVector(WTFMove(signatureBufferSource));
    auto data = copyToVector(WTFMove(dataBufferSource));

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

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

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier());

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](bool result) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            promise->resolve<IDLBoolean>(result);
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    algorithm->verify(*params, key, WTFMove(signature), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::digest(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise)
{
    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Digest);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto data = copyToVector(WTFMove(dataBufferSource));

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](const Vector<uint8_t>& digest) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), digest.data(), digest.size());
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    algorithm->digest(WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::generateKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise)
{
    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::GenerateKey);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages);

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](KeyOrKeyPair&& keyOrKeyPair) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer)) {
            WTF::switchOn(keyOrKeyPair,
                [&promise] (RefPtr<CryptoKey>& key) {
                    if ((key->type() == CryptoKeyType::Private || key->type() == CryptoKeyType::Secret) && !key->usagesBitmap()) {
                        rejectWithException(promise.releaseNonNull(), SyntaxError);
                        return;
                    }
                    promise->resolve<IDLInterface<CryptoKey>>(*key);
                },
                [&promise] (CryptoKeyPair& keyPair) {
                    if (!keyPair.privateKey->usagesBitmap()) {
                        rejectWithException(promise.releaseNonNull(), SyntaxError);
                        return;
                    }
                    promise->resolve<IDLDictionary<CryptoKeyPair>>(keyPair);
                }
            );
        }
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    // The 26 January 2017 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, HMAC and EC keys. Therefore, we perform it as an async task only for RSA keys.
    algorithm->generateKey(*params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext());
}

void SubtleCrypto::deriveKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& baseKey, AlgorithmIdentifier&& derivedKeyType, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise)
{
    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::DeriveBits);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto importParamsOrException = normalizeCryptoAlgorithmParameters(state, derivedKeyType, Operations::ImportKey);
    if (importParamsOrException.hasException()) {
        promise->reject(importParamsOrException.releaseException());
        return;
    }
    auto importParams = importParamsOrException.releaseReturnValue();

    auto getLengthParamsOrException = normalizeCryptoAlgorithmParameters(state, derivedKeyType, Operations::GetKeyLength);
    if (getLengthParamsOrException.hasException()) {
        promise->reject(getLengthParamsOrException.releaseException());
        return;
    }
    auto getLengthParams = getLengthParamsOrException.releaseReturnValue();

    auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages);

    if (params->identifier != baseKey.algorithmIdentifier()) {
        promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s);
        return;
    }

    if (!baseKey.allows(CryptoKeyUsageDeriveKey)) {
        promise->reject(InvalidAccessError, "CryptoKey doesn't support CryptoKey derivation"_s);
        return;
    }

    auto getLengthAlgorithm = CryptoAlgorithmRegistry::singleton().create(getLengthParams->identifier);

    auto result = getLengthAlgorithm->getKeyLength(*getLengthParams);
    if (result.hasException()) {
        promise->reject(result.releaseException().code(), "Cannot get key length from derivedKeyType"_s);
        return;
    }
    size_t length = result.releaseReturnValue();

    auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(importParams->identifier);
    auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer, importAlgorithm = WTFMove(importAlgorithm), importParams = crossThreadCopyImportParams(*importParams), extractable, keyUsagesBitmap](const Vector<uint8_t>& derivedKey) mutable {
        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=169395
        KeyData data = derivedKey;
        auto callback = [index, subtleCryptoWeakPointer](CryptoKey& key) mutable {
            if (auto promise = getPromise(index, subtleCryptoWeakPointer)) {
                if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) {
                    rejectWithException(promise.releaseNonNull(), SyntaxError);
                    return;
                }
                promise->resolve<IDLInterface<CryptoKey>>(key);
            }
        };
        auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
            if (auto promise = getPromise(index, subtleCryptoWeakPointer))
                rejectWithException(promise.releaseNonNull(), ec);
        };

        importAlgorithm->importKey(SubtleCrypto::KeyFormat::Raw, WTFMove(data), *importParams, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback));
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    algorithm->deriveBits(*params, baseKey, length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::deriveBits(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& baseKey, unsigned length, Ref<DeferredPromise>&& promise)
{
    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::DeriveBits);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    if (params->identifier != baseKey.algorithmIdentifier()) {
        promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s);
        return;
    }

    if (!baseKey.allows(CryptoKeyUsageDeriveBits)) {
        promise->reject(InvalidAccessError, "CryptoKey doesn't support bits derivation"_s);
        return;
    }

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](const Vector<uint8_t>& derivedKey) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), derivedKey.data(), derivedKey.size());
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

    algorithm->deriveBits(*params, baseKey, length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::importKey(JSC::JSGlobalObject& state, KeyFormat format, KeyDataVariant&& keyDataVariant, AlgorithmIdentifier&& algorithmIdentifier, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise)
{
    auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::ImportKey);
    if (paramsOrException.hasException()) {
        promise->reject(paramsOrException.releaseException());
        return;
    }
    auto params = paramsOrException.releaseReturnValue();

    auto keyDataOrNull = toKeyData(format, WTFMove(keyDataVariant), promise);
    if (!keyDataOrNull) {
        // When toKeyData, it means the promise has been rejected, and we should return.
        return;
    }

    auto keyData = *keyDataOrNull;
    auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages);

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](CryptoKey& key) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer)) {
            if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) {
                rejectWithException(promise.releaseNonNull(), SyntaxError);
                return;
            }
            promise->resolve<IDLInterface<CryptoKey>>(key);
        }
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), 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), *params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback));
}

void SubtleCrypto::exportKey(KeyFormat format, CryptoKey& key, Ref<DeferredPromise>&& promise)
{
    if (!isSupportedExportKey(key.algorithmIdentifier())) {
        promise->reject(Exception { NotSupportedError });
        return;
    }

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

    auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier());

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer](SubtleCrypto::KeyFormat format, KeyData&& key) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer)) {
            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(promise.releaseNonNull(), rawKey.data(), rawKey.size());
                return;
            }
            case SubtleCrypto::KeyFormat::Jwk:
                promise->resolve<IDLDictionary<JsonWebKey>>(WTFMove(WTF::get<JsonWebKey>(key)));
                return;
            }
            ASSERT_NOT_REACHED();
        }
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), 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, WTFMove(callback), WTFMove(exceptionCallback));
}

void SubtleCrypto::wrapKey(JSC::JSGlobalObject& state, KeyFormat format, CryptoKey& key, CryptoKey& wrappingKey, AlgorithmIdentifier&& wrapAlgorithmIdentifier, Ref<DeferredPromise>&& promise)
{
    bool isEncryption = false;

    auto wrapParamsOrException = normalizeCryptoAlgorithmParameters(state, wrapAlgorithmIdentifier, Operations::WrapKey);
    if (wrapParamsOrException.hasException()) {
        ASSERT(wrapParamsOrException.exception().code() != ExistingExceptionError);

        wrapParamsOrException = normalizeCryptoAlgorithmParameters(state, wrapAlgorithmIdentifier, Operations::Encrypt);
        if (wrapParamsOrException.hasException()) {
            promise->reject(wrapParamsOrException.releaseException());
            return;
        }

        isEncryption = true;
    }
    auto wrapParams = wrapParamsOrException.releaseReturnValue();

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

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

    if (!isSupportedExportKey(key.algorithmIdentifier())) {
        promise->reject(Exception { NotSupportedError });
        return;
    }

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

    auto exportAlgorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier());
    auto wrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(wrappingKey.algorithmIdentifier());

    auto context = scriptExecutionContext();

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer, wrapAlgorithm, wrappingKey = Ref { wrappingKey }, wrapParams = WTFMove(wrapParams), isEncryption, context, workQueue = m_workQueue](SubtleCrypto::KeyFormat format, KeyData&& key) mutable {
        if (subtleCryptoWeakPointer) {
            if (auto promise = subtleCryptoWeakPointer->m_pendingPromises.get(index)) {
                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: {
                    // FIXME: Converting to JS just to JSON-Stringify seems inefficient. We should find a way to go directly from the struct to JSON.
                    auto jwk = toJS<IDLDictionary<JsonWebKey>>(*(promise->globalObject()), *(promise->globalObject()), WTFMove(WTF::get<JsonWebKey>(key)));
                    String jwkString = JSONStringify(promise->globalObject(), jwk, 0);
                    CString jwkUtf8String = jwkString.utf8(StrictConversion);
                    bytes.append(jwkUtf8String.data(), jwkUtf8String.length());
                }
                }

                auto callback = [index, subtleCryptoWeakPointer](const Vector<uint8_t>& wrappedKey) mutable {
                    if (auto promise = getPromise(index, subtleCryptoWeakPointer))
                        fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), wrappedKey.data(), wrappedKey.size());
                };
                auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
                    if (auto promise = getPromise(index, subtleCryptoWeakPointer))
                        rejectWithException(promise.releaseNonNull(), 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.get(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback));
                    return;
                }
                // The following operation should be performed asynchronously.
                wrapAlgorithm->encrypt(*wrapParams, WTFMove(wrappingKey), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback), *context, workQueue);
            }
        }
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), ec);
    };

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

void SubtleCrypto::unwrapKey(JSC::JSGlobalObject& state, KeyFormat format, BufferSource&& wrappedKeyBufferSource, CryptoKey& unwrappingKey, AlgorithmIdentifier&& unwrapAlgorithmIdentifier, AlgorithmIdentifier&& unwrappedKeyAlgorithmIdentifier, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise)
{
    auto wrappedKey = copyToVector(WTFMove(wrappedKeyBufferSource));

    bool isDecryption = false;

    auto unwrapParamsOrException = normalizeCryptoAlgorithmParameters(state, unwrapAlgorithmIdentifier, Operations::UnwrapKey);
    if (unwrapParamsOrException.hasException()) {
        unwrapParamsOrException = normalizeCryptoAlgorithmParameters(state, unwrapAlgorithmIdentifier, Operations::Decrypt);
        if (unwrapParamsOrException.hasException()) {
            promise->reject(unwrapParamsOrException.releaseException());
            return;
        }

        isDecryption = true;
    }
    auto unwrapParams = unwrapParamsOrException.releaseReturnValue();

    auto unwrappedKeyAlgorithmOrException = normalizeCryptoAlgorithmParameters(state, unwrappedKeyAlgorithmIdentifier, Operations::ImportKey);
    if (unwrappedKeyAlgorithmOrException.hasException()) {
        promise->reject(unwrappedKeyAlgorithmOrException.releaseException());
        return;
    }
    auto unwrappedKeyAlgorithm = unwrappedKeyAlgorithmOrException.releaseReturnValue();

    auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages);

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

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

    auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappedKeyAlgorithm->identifier);
    if (UNLIKELY(!importAlgorithm)) {
        promise->reject(Exception { NotSupportedError });
        return;
    }

    auto unwrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappingKey.algorithmIdentifier());
    if (UNLIKELY(!unwrapAlgorithm)) {
        promise->reject(Exception { NotSupportedError });
        return;
    }

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = makeWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer, format, importAlgorithm, unwrappedKeyAlgorithm = crossThreadCopyImportParams(*unwrappedKeyAlgorithm), extractable, keyUsagesBitmap](const Vector<uint8_t>& bytes) mutable {
        if (subtleCryptoWeakPointer) {
            if (auto promise = subtleCryptoWeakPointer->m_pendingPromises.get(index)) {
                KeyData keyData;
                switch (format) {
                case SubtleCrypto::KeyFormat::Spki:
                case SubtleCrypto::KeyFormat::Pkcs8:
                case SubtleCrypto::KeyFormat::Raw:
                    keyData = bytes;
                    break;
                case SubtleCrypto::KeyFormat::Jwk: {
                    auto& state = *(promise->globalObject());
                    auto& vm = state.vm();
                    auto scope = DECLARE_THROW_SCOPE(vm);

                    String jwkString(bytes.data(), bytes.size());
                    JSLockHolder locker(vm);
                    auto jwkObject = JSONParse(&state, jwkString);
                    if (!jwkObject) {
                        promise->reject(DataError, "WrappedKey cannot be converted to a JSON object"_s);
                        return;
                    }
                    auto jwk = convert<IDLDictionary<JsonWebKey>>(state, jwkObject);
                    RETURN_IF_EXCEPTION(scope, void());
                    normalizeJsonWebKey(jwk);

                    keyData = jwk;
                    break;
                }
                }

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

                // The following operation should be performed synchronously.
                importAlgorithm->importKey(format, WTFMove(keyData), *unwrappedKeyAlgorithm, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback));
            }
        }
    };
    auto exceptionCallback = [index, subtleCryptoWeakPointer](ExceptionCode ec) mutable {
        if (auto promise = getPromise(index, subtleCryptoWeakPointer))
            rejectWithException(promise.releaseNonNull(), 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, WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback));
        return;
    }

    unwrapAlgorithm->decrypt(*unwrapParams, unwrappingKey, WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

}

#endif
