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

#include "config.h"
#include "SubtleCrypto.h"

#if ENABLE(SUBTLE_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(ExecState&, WebCore::SubtleCrypto::AlgorithmIdentifier, Operations);

static ExceptionOr<CryptoAlgorithmIdentifier> toHashIdentifier(ExecState& 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(ExecState& 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(&state, 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 = std::make_unique<CryptoAlgorithmParameters>(params);
            break;
        case CryptoAlgorithmIdentifier::RSA_OAEP: {
            auto params = convertDictionary<CryptoAlgorithmRsaOaepParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = std::make_unique<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 = std::make_unique<CryptoAlgorithmAesCbcCfbParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_CTR: {
            auto params = convertDictionary<CryptoAlgorithmAesCtrParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = std::make_unique<CryptoAlgorithmAesCtrParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_GCM: {
            auto params = convertDictionary<CryptoAlgorithmAesGcmParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = std::make_unique<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 = std::make_unique<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 = std::make_unique<CryptoAlgorithmEcdsaParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::RSA_PSS: {
            auto params = convertDictionary<CryptoAlgorithmRsaPssParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = std::make_unique<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 = std::make_unique<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 = std::make_unique<CryptoAlgorithmRsaKeyGenParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
        case CryptoAlgorithmIdentifier::RSA_PSS:
        case CryptoAlgorithmIdentifier::RSA_OAEP: {
            auto params = convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = std::make_unique<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 = std::make_unique<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 = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::ECDSA:
        case CryptoAlgorithmIdentifier::ECDH: {
            auto params = convertDictionary<CryptoAlgorithmEcKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = std::make_unique<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(&state, "name"));
            JSValue publicValue = value.get()->get(&state, Identifier::fromString(&state, "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 = std::make_unique<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 = std::make_unique<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 = std::make_unique<CryptoAlgorithmPbkdf2Params>(params);
            break;
        }
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::ImportKey:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
            result = std::make_unique<CryptoAlgorithmParameters>(params);
            break;
        case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
        case CryptoAlgorithmIdentifier::RSA_PSS:
        case CryptoAlgorithmIdentifier::RSA_OAEP: {
            auto params = convertDictionary<CryptoAlgorithmRsaHashedImportParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = std::make_unique<CryptoAlgorithmRsaHashedImportParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::AES_CTR:
        case CryptoAlgorithmIdentifier::AES_CBC:
        case CryptoAlgorithmIdentifier::AES_GCM:
        case CryptoAlgorithmIdentifier::AES_CFB:
        case CryptoAlgorithmIdentifier::AES_KW:
            result = std::make_unique<CryptoAlgorithmParameters>(params);
            break;
        case CryptoAlgorithmIdentifier::HMAC: {
            auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            auto hashIdentifier = toHashIdentifier(state, params.hash);
            if (hashIdentifier.hasException())
                return hashIdentifier.releaseException();
            params.hashIdentifier = hashIdentifier.releaseReturnValue();
            result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::ECDSA:
        case CryptoAlgorithmIdentifier::ECDH: {
            auto params = convertDictionary<CryptoAlgorithmEcKeyParams>(state, value.get());
            RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
            result = std::make_unique<CryptoAlgorithmEcKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::HKDF:
        case CryptoAlgorithmIdentifier::PBKDF2:
            result = std::make_unique<CryptoAlgorithmParameters>(params);
            break;
        default:
            return Exception { NotSupportedError };
        }
        break;
    case Operations::WrapKey:
    case Operations::UnwrapKey:
        switch (*identifier) {
        case CryptoAlgorithmIdentifier::AES_KW:
            result = std::make_unique<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 = std::make_unique<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 = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
            break;
        }
        case CryptoAlgorithmIdentifier::HKDF:
        case CryptoAlgorithmIdentifier::PBKDF2:
            result = std::make_unique<CryptoAlgorithmParameters>(params);
            break;
        default:
            return Exception { NotSupportedError };
        }
        break;
    }

    result->identifier = *identifier;
    return WTFMove(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, ASCIILiteral("The algorithm is not supported"));
        return;
    case SyntaxError:
        passedPromise->reject(ec, ASCIILiteral("A required parameter was missing or out-of-range"));
        return;
    case InvalidStateError:
        passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the current state of the provided key"));
        return;
    case InvalidAccessError:
        passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the provided key"));
        return;
    case UnknownError:
        passedPromise->reject(ec, ASCIILiteral("The operation failed for an unknown transient reason (e.g. out of memory)"));
        return;
    case DataError:
        passedPromise->reject(ec, ASCIILiteral("Data provided to an operation does not meet requirements"));
        return;
    case OperationError:
        passedPromise->reject(ec, ASCIILiteral("The operation failed for an operation-specific reason"));
        return;
    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> {
                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) -> 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)
{
    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) {
        if (auto promise = subtleCryptoWeakPointer->m_pendingPromises.take(index))
            return WTFMove(promise.value());
    }
    return nullptr;
}

// MARK: - Exposed functions.

void SubtleCrypto::encrypt(JSC::ExecState& 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, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

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

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

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = m_weakPtrFactory.createWeakPtr(*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(WTFMove(params), key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::decrypt(JSC::ExecState& 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, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

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

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

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = m_weakPtrFactory.createWeakPtr(*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(WTFMove(params), key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::sign(JSC::ExecState& 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, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

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

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

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = m_weakPtrFactory.createWeakPtr(*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(WTFMove(params), key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::verify(JSC::ExecState& 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, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

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

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

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = m_weakPtrFactory.createWeakPtr(*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(WTFMove(params), key, WTFMove(signature), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::digest(JSC::ExecState& 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 = m_weakPtrFactory.createWeakPtr(*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::ExecState& 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 = m_weakPtrFactory.createWeakPtr(*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::ExecState& 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, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

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

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

    auto result = getLengthAlgorithm->getKeyLength(*getLengthParams);
    if (result.hasException()) {
        promise->reject(result.releaseException().code(), ASCIILiteral("Cannot get key length from derivedKeyType"));
        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 = m_weakPtrFactory.createWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer, importAlgorithm, importParams = WTFMove(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), WTFMove(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(WTFMove(params), baseKey, length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::deriveBits(JSC::ExecState& 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, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

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

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

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = m_weakPtrFactory.createWeakPtr(*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(WTFMove(params), baseKey, length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

void SubtleCrypto::importKey(JSC::ExecState& 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 = m_weakPtrFactory.createWeakPtr(*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), WTFMove(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, ASCIILiteral("The CryptoKey is nonextractable"));
        return;
    }

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

    auto index = promise.ptr();
    m_pendingPromises.add(index, WTFMove(promise));
    auto subtleCryptoWeakPointer = m_weakPtrFactory.createWeakPtr(*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::ExecState& 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, ASCIILiteral("Wrapping CryptoKey doesn't match AlgorithmIdentifier"));
        return;
    }

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

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

    if (!key.extractable()) {
        promise->reject(InvalidAccessError, ASCIILiteral("The CryptoKey is nonextractable"));
        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 = m_weakPtrFactory.createWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer, wrapAlgorithm, wrappingKey = makeRef(wrappingKey), wrapParams = WTFMove(wrapParams), isEncryption, context, workQueue = m_workQueue.copyRef()](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()->globalExec()), *(promise->globalObject()), WTFMove(WTF::get<JsonWebKey>(key)));
                    String jwkString = JSONStringify(promise->globalObject()->globalExec(), jwk, 0);
                    CString jwkUtf8String = jwkString.utf8(StrictConversion);
                    bytes.append(jwkUtf8String.data(), jwkUtf8String.length());
                }
                }

                auto callback = [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(WTFMove(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::ExecState& 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, ASCIILiteral("Unwrapping CryptoKey doesn't match unwrap AlgorithmIdentifier"));
        return;
    }

    if (!unwrappingKey.allows(CryptoKeyUsageUnwrapKey)) {
        promise->reject(InvalidAccessError, ASCIILiteral("Unwrapping CryptoKey doesn't support unwrapKey operation"));
        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 = m_weakPtrFactory.createWeakPtr(*this);
    auto callback = [index, subtleCryptoWeakPointer, format, importAlgorithm, unwrappedKeyAlgorithm = WTFMove(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()->globalExec());
                    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, ASCIILiteral("WrappedKey cannot be converted to a JSON object"));
                        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), WTFMove(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(WTFMove(unwrapParams), unwrappingKey, WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue);
}

}

#endif
