JSValue JSWebKitSubtleCrypto::verify(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 4) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(0)); ASSERT(scope.exception() || algorithm); if (!algorithm) return jsUndefined(); auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(&state, algorithm->identifier(), state.uncheckedArgument(0)); ASSERT(scope.exception() || parameters); if (!parameters) return jsUndefined(); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); if (!key->allows(CryptoKeyUsageVerify)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'")); setDOMException(&state, NOT_SUPPORTED_ERR); return jsUndefined(); } CryptoOperationData signature; auto success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(2), signature); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); CryptoOperationData data; success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(3), data); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](bool result) mutable { wrapper->resolve(result); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(nullptr); }; auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
JSValue JSSubtleCrypto::verify(ExecState* exec) { if (exec->argumentCount() < 4) return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); auto algorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(0)); if (!algorithm) { ASSERT(exec->hadException()); return jsUndefined(); } auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(exec, algorithm->identifier(), exec->uncheckedArgument(0)); if (!parameters) { ASSERT(exec->hadException()); return jsUndefined(); } RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(exec->uncheckedArgument(1)); if (!key) return throwTypeError(exec); if (!key->allows(CryptoKeyUsageVerify)) { m_impl->document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'")); setDOMException(exec, NOT_SUPPORTED_ERR); return jsUndefined(); } CryptoOperationData signature; if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(2), signature)) { ASSERT(exec->hadException()); return jsUndefined(); } CryptoOperationData data; if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(3), data)) { ASSERT(exec->hadException()); return jsUndefined(); } JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject()); DeferredWrapper wrapper(exec, globalObject(), promiseDeferred); auto successCallback = [wrapper](bool result) mutable { wrapper.resolve(result); }; auto failureCallback = [wrapper]() mutable { wrapper.reject(nullptr); }; ExceptionCode ec = 0; algorithm->verify(*parameters, *key, signature, data, WTF::move(successCallback), WTF::move(failureCallback), ec); if (ec) { setDOMException(exec, ec); return jsUndefined(); } return promiseDeferred->promise(); }
JSValue JSWebKitSubtleCrypto::digest(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 2) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto parameters = JSCryptoAlgorithmDictionary::createParametersForDigest(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1)); RETURN_IF_EXCEPTION(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. }; auto result = algorithm->digest(*parameters, data, WTFMove(successCallback), WTFMove(failureCallback)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
static RefPtr<CryptoAlgorithmParameters> createRsaOaepParams(ExecState* exec, JSValue value) { if (!value.isObject()) { throwTypeError(exec); return nullptr; } JSDictionary jsDictionary(exec, value.getObject()); auto result = adoptRef(*new CryptoAlgorithmRsaOaepParams); if (!getHashAlgorithm(jsDictionary, result->hash, HashRequirement::Required)) { ASSERT(exec->hadException()); return nullptr; } JSValue labelValue = getProperty(exec, value.getObject(), "label"); if (exec->hadException()) return nullptr; result->hasLabel = !labelValue.isUndefinedOrNull(); if (!result->hasLabel) return WTFMove(result); CryptoOperationData labelData; if (!cryptoOperationDataFromJSValue(exec, labelValue, labelData)) { ASSERT(exec->hadException()); return nullptr; } result->label.append(labelData.first, labelData.second); return WTFMove(result); }
static RefPtr<CryptoAlgorithmParameters> createAesCbcParams(ExecState* exec, JSValue value) { if (!value.isObject()) { throwTypeError(exec); return nullptr; } JSValue iv = getProperty(exec, value.getObject(), "iv"); if (exec->hadException()) return nullptr; auto result = adoptRef(*new CryptoAlgorithmAesCbcParams); CryptoOperationData ivData; if (!cryptoOperationDataFromJSValue(exec, iv, ivData)) { ASSERT(exec->hadException()); return nullptr; } if (ivData.second != 16) { exec->vm().throwException(exec, createError(exec, "AES-CBC initialization data must be 16 bytes")); return nullptr; } memcpy(result->iv.data(), ivData.first, ivData.second); return WTFMove(result); }
JSValue JSWebKitSubtleCrypto::verify(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 4) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); if (!key->allows(CryptoKeyUsageVerify)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'")); throwNotSupportedError(state, scope); return jsUndefined(); } auto signature = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2)); RETURN_IF_EXCEPTION(scope, { }); auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](bool result) mutable { wrapper->resolve<IDLBoolean>(result); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback)); 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)); 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; }
JSValue JSSubtleCrypto::digest(ExecState* exec) { if (exec->argumentCount() < 2) return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); auto algorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(0)); if (!algorithm) { ASSERT(exec->hadException()); return jsUndefined(); } auto parameters = JSCryptoAlgorithmDictionary::createParametersForDigest(exec, algorithm->identifier(), exec->uncheckedArgument(0)); if (!parameters) { ASSERT(exec->hadException()); return jsUndefined(); } CryptoOperationData data; if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), data)) { ASSERT(exec->hadException()); return jsUndefined(); } 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); }; ExceptionCode ec = 0; algorithm->digest(*parameters, data, WTF::move(successCallback), WTF::move(failureCallback), ec); if (ec) { setDOMException(exec, ec); return jsUndefined(); } return promiseDeferred->promise(); }
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(); }
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; }