JSValue JSWebKitSubtleCrypto::exportKey(ExecState& state)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (state.argumentCount() < 2)
        return throwException(&state, scope, createNotEnoughArgumentsError(&state));

    auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
    if (!key)
        return throwTypeError(&state, scope);

    RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
    auto promise = wrapper->promise();
    auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
        fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
    };
    auto failureCallback = [wrapper]() mutable {
        wrapper->reject(); // FIXME: This should reject with an Exception.
    };

    WebCore::exportKey(state, keyFormat, *key, WTFMove(successCallback), WTFMove(failureCallback));
    RETURN_IF_EXCEPTION(scope, JSValue());

    return promise;
}
Esempio n. 2
0
JSValue JSSubtleCrypto::exportKey(ExecState* exec)
{
    if (exec->argumentCount() < 2)
        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));

    CryptoKeyFormat keyFormat;
    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(exec->uncheckedArgument(1));
    if (!key)
        return throwTypeError(exec);

    JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
    DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
    auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
        wrapper.resolve(result);
    };
    auto failureCallback = [wrapper]() mutable {
        wrapper.reject(nullptr);
    };

    WebCore::exportKey(exec, keyFormat, *key, WTF::move(successCallback), WTF::move(failureCallback));
    if (exec->hadException())
        return jsUndefined();

    return promiseDeferred->promise();
}
JSValue JSWebKitSubtleCrypto::wrapKey(ExecState& state)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (state.argumentCount() < 4)
        return throwException(&state, scope, createNotEnoughArgumentsError(&state));

    auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
    if (!key)
        return throwTypeError(&state, scope);

    RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2));
    if (!key)
        return throwTypeError(&state, scope);

    if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) {
        wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'wrapKey'"));
        throwNotSupportedError(state, scope);
        return jsUndefined();
    }

    auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3));
    RETURN_IF_EXCEPTION(scope, { });

    auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(3));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
    auto promise = wrapper->promise();

    auto exportSuccessCallback = [keyFormat, algorithm, parameters, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable {
        auto encryptSuccessCallback = [wrapper](const Vector<uint8_t>& encryptedData) mutable {
            fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), encryptedData.data(), encryptedData.size());
        };
        auto encryptFailureCallback = [wrapper]() mutable {
        wrapper->reject(); // FIXME: This should reject with an Exception.
        };
        auto result = algorithm->encryptForWrapKey(*parameters, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTFMove(encryptSuccessCallback), WTFMove(encryptFailureCallback));
        if (result.hasException()) {
            // FIXME: Report failure details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
            wrapper->reject(); // FIXME: This should reject with an Exception.
        }
    };

    auto exportFailureCallback = [wrapper]() mutable {
        wrapper->reject(); // FIXME: This should reject with an Exception.
    };

    WebCore::exportKey(state, keyFormat, *key, WTFMove(exportSuccessCallback), WTFMove(exportFailureCallback));

    return promise;
}
JSValue JSWebKitSubtleCrypto::importKey(ExecState& state)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (state.argumentCount() < 3)
        return throwException(&state, scope, createNotEnoughArgumentsError(&state));

    auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, { });

    auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<CryptoAlgorithm> algorithm;
    RefPtr<CryptoAlgorithmParametersDeprecated> parameters;
    if (!state.uncheckedArgument(2).isNull()) {
        algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(2));
        RETURN_IF_EXCEPTION(scope, { });

        parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, algorithm->identifier(), state.uncheckedArgument(2));
        RETURN_IF_EXCEPTION(scope, { });
    }

    bool extractable = state.argument(3).toBoolean(&state);
    RETURN_IF_EXCEPTION(scope, JSValue());

    CryptoKeyUsageBitmap keyUsages = 0;
    if (state.argumentCount() >= 5) {
        keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(4));
        RETURN_IF_EXCEPTION(scope, { });
    }

    RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
    auto promise = wrapper->promise();
    auto successCallback = [wrapper](CryptoKey& result) mutable {
        wrapper->resolve<IDLInterface<CryptoKey>>(result);
    };
    auto failureCallback = [wrapper]() mutable {
        wrapper->reject(); // FIXME: This should reject with an Exception.
    };

    WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback));
    RETURN_IF_EXCEPTION(scope, JSValue());

    return promise;
}
Esempio n. 5
0
JSValue JSSubtleCrypto::unwrapKey(ExecState* exec)
{
    if (exec->argumentCount() < 5)
        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));

    CryptoKeyFormat keyFormat;
    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    CryptoOperationData wrappedKeyData;
    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), wrappedKeyData)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(exec->uncheckedArgument(2));
    if (!unwrappingKey)
        return throwTypeError(exec);

    if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
        m_impl->document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'unwrapKey'"));
        setDOMException(exec, NOT_SUPPORTED_ERR);
        return jsUndefined();
    }

    std::unique_ptr<CryptoAlgorithm> unwrapAlgorithm;
    std::unique_ptr<CryptoAlgorithmParameters> unwrapAlgorithmParameters;
    unwrapAlgorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(3));
    if (!unwrapAlgorithm) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }
    unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(exec, unwrapAlgorithm->identifier(), exec->uncheckedArgument(3));
    if (!unwrapAlgorithmParameters) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    std::unique_ptr<CryptoAlgorithm> unwrappedKeyAlgorithm;
    std::unique_ptr<CryptoAlgorithmParameters> unwrappedKeyAlgorithmParameters;
    if (!exec->uncheckedArgument(4).isNull()) {
        unwrappedKeyAlgorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(4));
        if (!unwrappedKeyAlgorithm) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
        unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(exec, unwrappedKeyAlgorithm->identifier(), exec->uncheckedArgument(4));
        if (!unwrappedKeyAlgorithmParameters) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
    }

    bool extractable = false;
    if (exec->argumentCount() >= 6) {
        extractable = exec->uncheckedArgument(5).toBoolean(exec);
        if (exec->hadException())
            return jsUndefined();
    }

    CryptoKeyUsage keyUsages = 0;
    if (exec->argumentCount() >= 7) {
        if (!cryptoKeyUsagesFromJSValue(exec, exec->argument(6), keyUsages)) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
    }

    JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
    DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
    Strong<JSDOMGlobalObject> domGlobalObject(exec->vm(), globalObject());

    CryptoAlgorithm* unwrappedKeyAlgorithmPtr = unwrappedKeyAlgorithm.release();
    CryptoAlgorithmParameters* unwrappedKeyAlgorithmParametersPtr = unwrappedKeyAlgorithmParameters.release();

    auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithmPtr, unwrappedKeyAlgorithmParametersPtr, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable {
        auto importSuccessCallback = [wrapper](CryptoKey& key) mutable {
            wrapper.resolve(&key);
        };
        auto importFailureCallback = [wrapper]() mutable {
            wrapper.reject(nullptr);
        };
        ExecState* exec = domGlobalObject->globalExec();
        WebCore::importKey(exec, keyFormat, std::make_pair(result.data(), result.size()), std::unique_ptr<CryptoAlgorithm>(unwrappedKeyAlgorithmPtr), std::unique_ptr<CryptoAlgorithmParameters>(unwrappedKeyAlgorithmParametersPtr), extractable, keyUsages, WTF::move(importSuccessCallback), WTF::move(importFailureCallback));
        if (exec->hadException()) {
            // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
            exec->clearException();
            importFailureCallback();
        }
    };

    auto decryptFailureCallback = [wrapper, unwrappedKeyAlgorithmPtr, unwrappedKeyAlgorithmParametersPtr]() mutable {
        delete unwrappedKeyAlgorithmPtr;
        delete unwrappedKeyAlgorithmParametersPtr;
        wrapper.reject(nullptr);
    };

    ExceptionCode ec = 0;
    unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTF::move(decryptSuccessCallback), WTF::move(decryptFailureCallback), ec);
    if (ec) {
        delete unwrappedKeyAlgorithmPtr;
        delete unwrappedKeyAlgorithmParametersPtr;
        setDOMException(exec, ec);
        return jsUndefined();
    }

    return promiseDeferred->promise();
}
Esempio n. 6
0
JSValue JSSubtleCrypto::wrapKey(ExecState* exec)
{
    if (exec->argumentCount() < 4)
        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));

    CryptoKeyFormat keyFormat;
    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(exec->uncheckedArgument(1));
    if (!key)
        return throwTypeError(exec);

    RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(exec->uncheckedArgument(2));
    if (!key)
        return throwTypeError(exec);

    if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) {
        m_impl->document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'wrapKey'"));
        setDOMException(exec, NOT_SUPPORTED_ERR);
        return jsUndefined();
    }

    auto algorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(3));
    if (!algorithm) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(exec, algorithm->identifier(), exec->uncheckedArgument(3));
    if (!parameters) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
    DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);

    CryptoAlgorithm* algorithmPtr = algorithm.release();
    CryptoAlgorithmParameters* parametersPtr = parameters.release();

    auto exportSuccessCallback = [keyFormat, algorithmPtr, parametersPtr, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable {
        auto encryptSuccessCallback = [wrapper, algorithmPtr, parametersPtr](const Vector<uint8_t>& encryptedData) mutable {
            delete algorithmPtr;
            delete parametersPtr;
            wrapper.resolve(encryptedData);
        };
        auto encryptFailureCallback = [wrapper, algorithmPtr, parametersPtr]() mutable {
            delete algorithmPtr;
            delete parametersPtr;
            wrapper.reject(nullptr);
        };
        ExceptionCode ec = 0;
        algorithmPtr->encryptForWrapKey(*parametersPtr, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTF::move(encryptSuccessCallback), WTF::move(encryptFailureCallback), ec);
        if (ec) {
            // FIXME: Report failure details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
            encryptFailureCallback();
        }
    };

    auto exportFailureCallback = [wrapper, algorithmPtr, parametersPtr]() mutable {
        delete algorithmPtr;
        delete parametersPtr;
        wrapper.reject(nullptr);
    };

    ExceptionCode ec = 0;
    WebCore::exportKey(exec, keyFormat, *key, WTF::move(exportSuccessCallback), WTF::move(exportFailureCallback));
    if (ec) {
        delete algorithmPtr;
        delete parametersPtr;
        setDOMException(exec, ec);
        return jsUndefined();
    }

    return promiseDeferred->promise();
}
Esempio n. 7
0
JSValue JSSubtleCrypto::importKey(ExecState* exec)
{
    if (exec->argumentCount() < 3)
        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));

    CryptoKeyFormat keyFormat;
    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    CryptoOperationData data;
    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), data)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    std::unique_ptr<CryptoAlgorithm> algorithm;
    std::unique_ptr<CryptoAlgorithmParameters> parameters;
    if (!exec->uncheckedArgument(2).isNull()) {
        algorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(2));
        if (!algorithm) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
        parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(exec, algorithm->identifier(), exec->uncheckedArgument(2));
        if (!parameters) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
    }

    bool extractable = false;
    if (exec->argumentCount() >= 4) {
        extractable = exec->uncheckedArgument(3).toBoolean(exec);
        if (exec->hadException())
            return jsUndefined();
    }

    CryptoKeyUsage keyUsages = 0;
    if (exec->argumentCount() >= 5) {
        if (!cryptoKeyUsagesFromJSValue(exec, exec->argument(4), keyUsages)) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
    }

    JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
    DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
    auto successCallback = [wrapper](CryptoKey& result) mutable {
        wrapper.resolve(&result);
    };
    auto failureCallback = [wrapper]() mutable {
        wrapper.reject(nullptr);
    };

    WebCore::importKey(exec, keyFormat, data, WTF::move(algorithm), WTF::move(parameters), extractable, keyUsages, WTF::move(successCallback), WTF::move(failureCallback));
    if (exec->hadException())
        return jsUndefined();

    return promiseDeferred->promise();
}
JSValue JSWebKitSubtleCrypto::unwrapKey(ExecState& state)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (state.argumentCount() < 5)
        return throwException(&state, scope, createNotEnoughArgumentsError(&state));

    auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, { });

    auto wrappedKeyData = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2));
    if (!unwrappingKey)
        return throwTypeError(&state, scope);

    if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
        wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'unwrapKey'"));
        throwNotSupportedError(state, scope);
        return jsUndefined();
    }

    auto unwrapAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3));
    RETURN_IF_EXCEPTION(scope, { });

    auto unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(state, scope, unwrapAlgorithm->identifier(), state.uncheckedArgument(3));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<CryptoAlgorithm> unwrappedKeyAlgorithm;
    RefPtr<CryptoAlgorithmParametersDeprecated> unwrappedKeyAlgorithmParameters;
    if (!state.uncheckedArgument(4).isNull()) {
        unwrappedKeyAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(4));
        RETURN_IF_EXCEPTION(scope, { });

        unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, unwrappedKeyAlgorithm->identifier(), state.uncheckedArgument(4));
        RETURN_IF_EXCEPTION(scope, { });
    }

    bool extractable = state.argument(5).toBoolean(&state);
    RETURN_IF_EXCEPTION(scope, { });

    CryptoKeyUsageBitmap keyUsages = 0;
    if (state.argumentCount() >= 7) {
        keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(6));
        RETURN_IF_EXCEPTION(scope, { });
    }

    RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
    auto promise = wrapper->promise();
    Strong<JSDOMGlobalObject> domGlobalObject(state.vm(), globalObject());

    auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable {
        auto importSuccessCallback = [wrapper](CryptoKey& key) mutable {
            wrapper->resolve<IDLInterface<CryptoKey>>(key);
        };
        auto importFailureCallback = [wrapper]() mutable {
            wrapper->reject(); // FIXME: This should reject with an Exception.
        };

        VM& vm = domGlobalObject->vm();
        auto scope = DECLARE_CATCH_SCOPE(vm);

        ExecState& state = *domGlobalObject->globalExec();
        WebCore::importKey(state, keyFormat, std::make_pair(result.data(), result.size()), unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, WTFMove(importSuccessCallback), WTFMove(importFailureCallback));
        if (UNLIKELY(scope.exception())) {
            // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
            scope.clearException();
            wrapper->reject(); // FIXME: This should reject with an Exception.
        }
    };

    auto decryptFailureCallback = [wrapper]() mutable {
        wrapper->reject(); // FIXME: This should reject with an Exception.
    };

    auto result = unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTFMove(decryptSuccessCallback), WTFMove(decryptFailureCallback));
    if (result.hasException()) {
        propagateException(state, scope, result.releaseException());
        return { };
    }

    return promise;
}
JSValue JSWebKitSubtleCrypto::importKey(ExecState& state)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (state.argumentCount() < 3)
        return throwException(&state, scope, createNotEnoughArgumentsError(&state));

    CryptoKeyFormat keyFormat;
    auto success = cryptoKeyFormatFromJSValue(state, state.argument(0), keyFormat);
    ASSERT(scope.exception() || success);
    if (!success)
        return jsUndefined();

    CryptoOperationData data;
    success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(1), data);
    ASSERT(scope.exception() || success);
    if (!success)
        return jsUndefined();

    RefPtr<CryptoAlgorithm> algorithm;
    RefPtr<CryptoAlgorithmParametersDeprecated> parameters;
    if (!state.uncheckedArgument(2).isNull()) {
        algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(2));
        ASSERT(scope.exception() || algorithm);
        if (!algorithm)
            return jsUndefined();

        parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(&state, algorithm->identifier(), state.uncheckedArgument(2));
        ASSERT(scope.exception() || parameters);
        if (!parameters)
            return jsUndefined();
    }

    bool extractable = false;
    if (state.argumentCount() >= 4) {
        extractable = state.uncheckedArgument(3).toBoolean(&state);
        RETURN_IF_EXCEPTION(scope, JSValue());
    }

    CryptoKeyUsageBitmap keyUsages = 0;
    if (state.argumentCount() >= 5) {
        auto success = cryptoKeyUsagesFromJSValue(state, state.argument(4), keyUsages);
        ASSERT(scope.exception() || success);
        if (!success)
            return jsUndefined();
    }

    RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
    auto promise = wrapper->promise();
    auto successCallback = [wrapper](CryptoKey& result) mutable {
        wrapper->resolve(result);
    };
    auto failureCallback = [wrapper]() mutable {
        wrapper->reject(nullptr);
    };

    WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback));
    RETURN_IF_EXCEPTION(scope, JSValue());

    return promise;
}