/*
 * 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 (WTF::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 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 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&) -> Optional<KeyData> {
                promise->reject(Exception { TypeError });
                return WTF::nullopt;
            },
            [] (auto& bufferSource) -> Optional<KeyData> {
                Vector<uint8_t> result;
                result.append(static_cast<const uint8_t*>(bufferSource->data()), bufferSource->byteLength());
                return KeyData { result };
            }
        );
    case SubtleCrypto::KeyFormat::Jwk:
        return WTF::switchOn(keyDataVariant,
            [] (JsonWebKey& webKey) -> Optional<KeyData> {
                normalizeJsonWebKey(webKey);
                return KeyData { webKey };
            },
            [&promise] (auto&) -> Optional<KeyData> {
                promise->reject(Exception { TypeError });
                return WTF::nullopt;
            }
        );
    }

    RELEASE_ASSERT_NOT_REACHED();
}

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

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

// MARK: - Exposed functions.

void SubtleCrypto::encrypt(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise)
{
    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)
{
    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 = makeRef(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()) {
        ASSERT(unwrapParamsOrException.exception().code() != ExistingExceptionError);

        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(reinterpret_cast_ptr<const char*>(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
