diff options
Diffstat (limited to 'src')
236 files changed, 18571 insertions, 40 deletions
diff --git a/src/bun.js/bindings/ScriptExecutionContext.cpp b/src/bun.js/bindings/ScriptExecutionContext.cpp index 5b8d88871..151c66495 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.cpp +++ b/src/bun.js/bindings/ScriptExecutionContext.cpp @@ -10,6 +10,16 @@ extern "C" void Bun__startLoop(us_loop_t* loop); namespace WebCore { +static unsigned lastUniqueIdentifier = 0; + +static Lock allScriptExecutionContextsMapLock; +static HashMap<ScriptExecutionContextIdentifier, ScriptExecutionContext*>& allScriptExecutionContextsMap() WTF_REQUIRES_LOCK(allScriptExecutionContextsMapLock) +{ + static NeverDestroyed<HashMap<ScriptExecutionContextIdentifier, ScriptExecutionContext*>> contexts; + ASSERT(allScriptExecutionContextsMapLock.isLocked()); + return contexts; +} + template<bool SSL, bool isServer> static void registerHTTPContextForWebSocket(ScriptExecutionContext* script, us_socket_context_t* ctx, us_loop_t* loop) { @@ -39,6 +49,18 @@ us_socket_context_t* ScriptExecutionContext::webSocketContextSSL() return m_ssl_client_websockets_ctx; } +bool ScriptExecutionContext::postTaskTo(ScriptExecutionContextIdentifier identifier, Function<void(ScriptExecutionContext&)>&& task) +{ + Locker locker { allScriptExecutionContextsMapLock }; + auto* context = allScriptExecutionContextsMap().get(identifier); + + if (!context) + return false; + + context->postTaskConcurrently(WTFMove(task)); + return true; +} + us_socket_context_t* ScriptExecutionContext::webSocketContextNoSSL() { if (!m_client_websockets_ctx) { @@ -78,4 +100,31 @@ us_socket_context_t* ScriptExecutionContext::connectedWebSocketKindClientSSL() return registerWebSocketClientContext<true>(this, webSocketContextSSL()); } -}
\ No newline at end of file +void ScriptExecutionContext::regenerateIdentifier() +{ + Locker locker { allScriptExecutionContextsMapLock }; + + ASSERT(allScriptExecutionContextsMap().contains(m_identifier)); + allScriptExecutionContextsMap().remove(m_identifier); + + m_identifier = ++lastUniqueIdentifier; + + ASSERT(!allScriptExecutionContextsMap().contains(m_identifier)); + allScriptExecutionContextsMap().add(m_identifier, this); +} + +void ScriptExecutionContext::addToContextsMap() +{ + Locker locker { allScriptExecutionContextsMapLock }; + ASSERT(!allScriptExecutionContextsMap().contains(m_identifier)); + allScriptExecutionContextsMap().add(m_identifier, this); +} + +void ScriptExecutionContext::removeFromContextsMap() +{ + Locker locker { allScriptExecutionContextsMapLock }; + ASSERT(allScriptExecutionContextsMap().contains(m_identifier)); + allScriptExecutionContextsMap().remove(m_identifier); +} + +} diff --git a/src/bun.js/bindings/ScriptExecutionContext.h b/src/bun.js/bindings/ScriptExecutionContext.h index ab86b6816..1643820dd 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.h +++ b/src/bun.js/bindings/ScriptExecutionContext.h @@ -68,13 +68,17 @@ protected: bool m_isCleanupTask; }; +using ScriptExecutionContextIdentifier = uint32_t; + class ScriptExecutionContext : public CanMakeWeakPtr<ScriptExecutionContext> { -public: + public: ScriptExecutionContext(JSC::VM* vm, JSC::JSGlobalObject* globalObject) : m_vm(vm) , m_globalObject(globalObject) + , m_identifier(0) { + regenerateIdentifier(); } JSC::JSGlobalObject* jsGlobalObject() @@ -106,12 +110,23 @@ public: // { // } + static bool postTaskTo(ScriptExecutionContextIdentifier identifier, Function<void(ScriptExecutionContext&)>&& task); + + void regenerateIdentifier(); + void addToContextsMap(); + void removeFromContextsMap(); + + void postTaskConcurrently(Function<void(ScriptExecutionContext&)>&& lambda) + { + auto* task = new EventLoopTask(WTFMove(lambda)); + reinterpret_cast<Zig::GlobalObject*>(m_globalObject)->queueTaskConcurrently(task); + } // Executes the task on context's thread asynchronously. + void postTask(Function<void(ScriptExecutionContext&)>&& lambda) { auto* task = new EventLoopTask(WTFMove(lambda)); reinterpret_cast<Zig::GlobalObject*>(m_globalObject)->queueTask(task); } // Executes the task on context's thread asynchronously. - void postTask(EventLoopTask* task) { reinterpret_cast<Zig::GlobalObject*>(m_globalObject)->queueTask(task); @@ -126,11 +141,13 @@ public: } JSC::VM& vm() { return *m_vm; } + ScriptExecutionContextIdentifier identifier() const { return m_identifier; } private: JSC::VM* m_vm = nullptr; JSC::JSGlobalObject* m_globalObject = nullptr; WTF::URL m_url = WTF::URL(); + ScriptExecutionContextIdentifier m_identifier; us_socket_context_t* webSocketContextSSL(); us_socket_context_t* webSocketContextNoSSL(); diff --git a/src/bun.js/bindings/WebCoreOpaqueRoot.h b/src/bun.js/bindings/WebCoreOpaqueRoot.h new file mode 100644 index 000000000..93388c5c0 --- /dev/null +++ b/src/bun.js/bindings/WebCoreOpaqueRoot.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 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. ``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 + * 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. + * + */ + +#pragma once + + +namespace WebCore { + +class WebCoreOpaqueRoot { +public: + template<typename T, typename = typename std::enable_if_t<!std::is_same_v<T, void>>> + explicit WebCoreOpaqueRoot(T* pointer) + : m_pointer(static_cast<void*>(pointer)) + { + } + + WebCoreOpaqueRoot(std::nullptr_t) { } + + bool isNode() const { return false; } + void* pointer() const { return m_pointer; } + +private: + void* m_pointer { nullptr }; + bool m_isNode { false }; +}; + +template<typename Visitor> +ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, WebCoreOpaqueRoot root) +{ + visitor.addOpaqueRoot(root.pointer()); +} + +template<typename Visitor, typename ImplType> +ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, ImplType* impl) +{ + addWebCoreOpaqueRoot(visitor, root(impl)); +} + +template<typename Visitor, typename ImplType> +ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, ImplType& impl) +{ + addWebCoreOpaqueRoot(visitor, root(&impl)); +} + +template<typename Visitor> +ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, WebCoreOpaqueRoot root) +{ + return visitor.containsOpaqueRoot(root.pointer()); +} + +template<typename Visitor, typename ImplType> +ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, ImplType& impl) +{ + return containsWebCoreOpaqueRoot(visitor, root(&impl)); +} + +template<typename Visitor, typename ImplType> +ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, ImplType* impl) +{ + return containsWebCoreOpaqueRoot(visitor, root(impl)); +} + +} // namespace WebCore diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index c91a232e6..71113e9a6 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -163,6 +163,9 @@ using JSBuffer = WebCore::JSBuffer; #include "DOMJITHelpers.h" #include <JavaScriptCore/DFGAbstractHeap.h> +#include "JSCryptoKey.h" +#include "JSSubtleCrypto.h" + #include "OnigurumaRegExp.h" #ifdef __APPLE__ @@ -427,7 +430,10 @@ GlobalObject::GlobalObject(JSC::VM& vm, JSC::Structure* structure) m_scriptExecutionContext = new WebCore::ScriptExecutionContext(&vm, this); } -GlobalObject::~GlobalObject() = default; +GlobalObject::~GlobalObject() +{ + scriptExecutionContext()->removeFromContextsMap(); +} void GlobalObject::destroy(JSCell* cell) { @@ -1264,6 +1270,40 @@ JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_WritableStreamDefaultWriterC return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_WritableStreamDefaultWriterConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); } +static inline JSValue getterSubtleCryptoBodyConstructor(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) +{ + UNUSED_PARAM(lexicalGlobalObject); + return JSSubtleCrypto::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); +} + +JSC_DEFINE_CUSTOM_GETTER(getterSubtleCryptoConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<Zig::GlobalObject>::get<getterSubtleCryptoBodyConstructor>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue getterCryptoKeyBodyConstructor(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) +{ + UNUSED_PARAM(lexicalGlobalObject); + return JSCryptoKey::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); +} + +JSC_DEFINE_CUSTOM_GETTER(getterCryptoKeyConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<Zig::GlobalObject>::get<getterCryptoKeyBodyConstructor>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue getterSubtleCryptoBody(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) +{ + UNUSED_PARAM(lexicalGlobalObject); + return thisObject.subtleCrypto(); +} + +JSC_DEFINE_CUSTOM_GETTER(getterSubtleCrypto, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return JSValue::encode( + getterSubtleCryptoBody(*lexicalGlobalObject, *reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject))); +} + JSC_DECLARE_HOST_FUNCTION(makeThisTypeErrorForBuiltins); JSC_DECLARE_HOST_FUNCTION(makeGetterTypeErrorForBuiltins); JSC_DECLARE_HOST_FUNCTION(makeDOMExceptionForBuiltins); @@ -1951,6 +1991,15 @@ void GlobalObject::finishCreation(VM& vm) this->initGeneratedLazyClasses(); + m_subtleCryptoObject.initLater( + [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) { + auto& global = *reinterpret_cast<Zig::GlobalObject*>(init.owner); + RefPtr<WebCore::SubtleCrypto> crypto = WebCore::SubtleCrypto::create(global.scriptExecutionContext()); + + init.set( + toJSNewlyCreated<IDLInterface<SubtleCrypto>>(*init.owner, global, WTFMove(crypto)).getObject()); + }); + m_NapiClassStructure.initLater( [](LazyClassStructure::Initializer& init) { init.setStructure(Zig::NapiClass::createStructure(init.vm, init.global, init.global->functionPrototype())); @@ -2218,7 +2267,7 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) auto& builtinNames = WebCore::builtinNames(vm); WTF::Vector<GlobalPropertyInfo> extraStaticGlobals; - extraStaticGlobals.reserveCapacity(40); + extraStaticGlobals.reserveCapacity(42); JSC::Identifier queueMicrotaskIdentifier = JSC::Identifier::fromString(vm, "queueMicrotask"_s); extraStaticGlobals.uncheckedAppend( @@ -2272,6 +2321,18 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) "atob"_s, functionATOB, ImplementationVisibility::Public), JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); + JSC::Identifier SubtleCryptoIdentifier = JSC::Identifier::fromString(vm, "SubtleCrypto"_s); + extraStaticGlobals.uncheckedAppend( + GlobalPropertyInfo { SubtleCryptoIdentifier, + JSC::CustomGetterSetter::create(vm, getterSubtleCryptoConstructor, nullptr), + JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0 }); + + JSC::Identifier CryptoKeyIdentifier = JSC::Identifier::fromString(vm, "CryptoKey"_s); + extraStaticGlobals.uncheckedAppend( + GlobalPropertyInfo { CryptoKeyIdentifier, + JSC::CustomGetterSetter::create(vm, getterCryptoKeyConstructor, nullptr), + JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0 }); + JSC::Identifier btoaIdentifier = JSC::Identifier::fromString(vm, "btoa"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { btoaIdentifier, @@ -2598,6 +2659,8 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm Crypto__getRandomValues__put(this, JSValue::encode(object)); Crypto__randomUUID__put(this, JSValue::encode(object)); + object->putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "subtle"_s), JSC::CustomGetterSetter::create(vm, getterSubtleCrypto, nullptr), + JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { JSC::Identifier::fromString(vm, jsClass->className()), JSC::JSValue(object), JSC::PropertyAttribute::DontDelete | 0 }); @@ -2688,6 +2751,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_processObject.visit(visitor); thisObject->m_performanceObject.visit(visitor); thisObject->m_navigatorObject.visit(visitor); + thisObject->m_subtleCryptoObject.visit(visitor); thisObject->m_JSHTTPResponseSinkClassStructure.visit(visitor); thisObject->m_JSHTTPSResponseSinkClassStructure.visit(visitor); @@ -2719,7 +2783,8 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.addOpaqueRoot(context); } -extern "C" void Bun__queueMicrotask(JSC__JSGlobalObject*, WebCore::EventLoopTask* task); +extern "C" void Bun__queueTask(JSC__JSGlobalObject*, WebCore::EventLoopTask* task); +extern "C" void Bun__queueTaskConcurrently(JSC__JSGlobalObject*, WebCore::EventLoopTask* task); extern "C" void Bun__performTask(Zig::GlobalObject* globalObject, WebCore::EventLoopTask* task) { task->performTask(*globalObject->scriptExecutionContext()); @@ -2727,7 +2792,12 @@ extern "C" void Bun__performTask(Zig::GlobalObject* globalObject, WebCore::Event void GlobalObject::queueTask(WebCore::EventLoopTask* task) { - Bun__queueMicrotask(this, task); + Bun__queueTask(this, task); +} + +void GlobalObject::queueTaskConcurrently(WebCore::EventLoopTask* task) +{ + Bun__queueTaskConcurrently(this, task); } extern "C" void Bun__handleRejectedPromise(Zig::GlobalObject* JSGlobalObject, JSC::JSPromise* promise); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 8c0cc4796..9bd954a60 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -138,6 +138,7 @@ public: WebCore::ScriptExecutionContext* scriptExecutionContext() const; void queueTask(WebCore::EventLoopTask* task); + void queueTaskConcurrently(WebCore::EventLoopTask* task); JSDOMStructureMap& structures() WTF_REQUIRES_LOCK(m_gcLock) { return m_structures; } JSDOMStructureMap& structures(NoLockingNecessaryTag) WTF_IGNORES_THREAD_SAFETY_ANALYSIS @@ -238,6 +239,11 @@ public: void* bunVM() { return m_bunVM; } bool isThreadLocalDefaultGlobalObject = false; + JSObject* subtleCrypto() + { + return m_subtleCryptoObject.getInitializedOnMainThread(this); + } + EncodedJSValue assignToStream(JSValue stream, JSValue controller); enum class PromiseFunctions : uint8_t { @@ -368,7 +374,6 @@ public: BunPlugin::OnResolve onResolvePlugins[BunPluginTargetMax + 1] {}; BunPluginTarget defaultBunPluginTarget = BunPluginTargetBun; - void reload(); JSC::Structure* pendingVirtualModuleResultStructure() { return m_pendingVirtualModuleResultStructure.get(this); } @@ -419,6 +424,8 @@ private: LazyProperty<JSGlobalObject, JSMap> m_requireMap; LazyProperty<JSGlobalObject, JSObject> m_performanceObject; + LazyProperty<JSGlobalObject, JSObject> m_subtleCryptoObject; + LazyProperty<JSGlobalObject, JSC::Structure> m_pendingVirtualModuleResultStructure; LazyProperty<JSGlobalObject, JSObject> m_encodeIntoObjectPrototype; diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index f927e47c7..a8737dd54 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -2148,6 +2148,11 @@ pub const JSGlobalObject = extern struct { return @ptrCast(*JSC.VirtualMachine, @alignCast(std.meta.alignment(JSC.VirtualMachine), this.bunVM_())); } + /// We can't do the threadlocal check when queued from another thread + pub fn bunVMConcurrently(this: *JSGlobalObject) *JSC.VirtualMachine { + return @ptrCast(*JSC.VirtualMachine, @alignCast(std.meta.alignment(JSC.VirtualMachine), this.bunVM_())); + } + pub fn handleRejectedPromises(this: *JSGlobalObject) void { return cppFn("handleRejectedPromises", .{this}); } diff --git a/src/bun.js/bindings/root.h b/src/bun.js/bindings/root.h index 0e8f2b262..69698bf8c 100644 --- a/src/bun.js/bindings/root.h +++ b/src/bun.js/bindings/root.h @@ -71,12 +71,18 @@ #include "wtf/PlatformCallingConventions.h" #include "JavaScriptCore/JSCInlines.h" +#include "wtf/IsoMalloc.h" +#include "wtf/IsoMallocInlines.h" -#define WTF_MAKE_ISO_ALLOCATED(className) \ - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(className) +#define ENABLE_WEB_CRYPTO 1 +#define USE_OPENSSL 1 +#define HAVE_RSA_PSS 1 -#define WTF_MAKE_ISO_ALLOCATED_EXPORT(className, a) WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(className); +// #define WTF_MAKE_ISO_ALLOCATED(className) \ +// WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(className) -#define WTF_MAKE_ISO_ALLOCATED_IMPL(className) +// #define WTF_MAKE_ISO_ALLOCATED_EXPORT(className, a) WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(className); + +// #define WTF_MAKE_ISO_ALLOCATED_IMPL(className) #endif
\ No newline at end of file diff --git a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h index 1477cc4b2..b6641ea4d 100644 --- a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h @@ -324,8 +324,8 @@ public: // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDocumentTimeline; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForKeyframeEffect; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForWebAnimation; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCryptoKey; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSubtleCrypto; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCryptoKey; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSubtleCrypto; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCSSConditionRule; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCSSCounterStyleRule; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCSSFontFaceRule; diff --git a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h index e1e9a35c3..32c367014 100644 --- a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h @@ -314,8 +314,8 @@ public: // std::unique_ptr<IsoSubspace> m_subspaceForDocumentTimeline; // std::unique_ptr<IsoSubspace> m_subspaceForKeyframeEffect; // std::unique_ptr<IsoSubspace> m_subspaceForWebAnimation; - // std::unique_ptr<IsoSubspace> m_subspaceForCryptoKey; - // std::unique_ptr<IsoSubspace> m_subspaceForSubtleCrypto; + std::unique_ptr<IsoSubspace> m_subspaceForCryptoKey; + std::unique_ptr<IsoSubspace> m_subspaceForSubtleCrypto; // std::unique_ptr<IsoSubspace> m_subspaceForCSSConditionRule; // std::unique_ptr<IsoSubspace> m_subspaceForCSSCounterStyleRule; // std::unique_ptr<IsoSubspace> m_subspaceForCSSFontFaceRule; diff --git a/src/bun.js/bindings/webcore/EventEmitter.cpp b/src/bun.js/bindings/webcore/EventEmitter.cpp index 8d34ab7a2..d997019d6 100644 --- a/src/bun.js/bindings/webcore/EventEmitter.cpp +++ b/src/bun.js/bindings/webcore/EventEmitter.cpp @@ -1,9 +1,7 @@ -#include <iostream> -#include "config.h" -#include "Event.h" - #include "EventEmitter.h" +#include "Event.h" + #include "DOMWrapperWorld.h" #include "EventNames.h" #include "JSErrorHandler.h" @@ -18,7 +16,6 @@ namespace WebCore { WTF_MAKE_ISO_ALLOCATED_IMPL(EventEmitter); -WTF_MAKE_ISO_ALLOCATED_IMPL(EventEmitterWithInlineData); Ref<EventEmitter> EventEmitter::create(ScriptExecutionContext& context) { diff --git a/src/bun.js/bindings/webcore/EventEmitter.h b/src/bun.js/bindings/webcore/EventEmitter.h index 4aa143604..ae337fd8a 100644 --- a/src/bun.js/bindings/webcore/EventEmitter.h +++ b/src/bun.js/bindings/webcore/EventEmitter.h @@ -1,5 +1,7 @@ #pragma once +#include "root.h" + #include "IdentifierEventListenerMap.h" #include "ExceptionOr.h" #include "ContextDestructionObserver.h" @@ -10,8 +12,6 @@ #include <wtf/WeakPtr.h> -#include "root.h" - namespace JSC { class JSValue; class JSObject; diff --git a/src/bun.js/bindings/webcrypto/AesCbcCfbParams.idl b/src/bun.js/bindings/webcrypto/AesCbcCfbParams.idl new file mode 100644 index 000000000..85e5a6536 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/AesCbcCfbParams.idl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// This is a unified dictionary for AesCbcParams and AesCfbParams. +// https://www.w3.org/TR/WebCryptoAPI/#dfn-AesCbcParams, and +// https://www.w3.org/TR/2014/CR-WebCryptoAPI-20141211/#dfn-AesCfbParams +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmAesCbcCfbParams +] dictionary AesCbcCfbParams : CryptoAlgorithmParameters { + // The initialization vector. MUST be 16 bytes. + required BufferSource iv; +}; diff --git a/src/bun.js/bindings/webcrypto/AesCtrParams.idl b/src/bun.js/bindings/webcrypto/AesCtrParams.idl new file mode 100644 index 000000000..2f5e295b2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/AesCtrParams.idl @@ -0,0 +1,40 @@ +/* Copyright (C) 2017 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. +*/ + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmAesCtrParams +] dictionary AesCtrParams : CryptoAlgorithmParameters { + // The initial value of the counter block. counter MUST be 16 bytes + // (the AES block size). The counter bits are the rightmost length + // bits of the counter block. The rest of the counter block is for + // the nonce. The counter bits are incremented using the standard + // incrementing function specified in NIST SP 800-38A Appendix B.1: + // the counter bits are interpreted as a big-endian integer and + // incremented by one. + required BufferSource counter; + // The length, in bits, of the rightmost part of the counter block + // that is incremented. + required [EnforceRange] octet length; +}; diff --git a/src/bun.js/bindings/webcrypto/AesGcmParams.idl b/src/bun.js/bindings/webcrypto/AesGcmParams.idl new file mode 100644 index 000000000..3d1c6f87c --- /dev/null +++ b/src/bun.js/bindings/webcrypto/AesGcmParams.idl @@ -0,0 +1,35 @@ +/* Copyright (C) 2017 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. + */ + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmAesGcmParams +] dictionary AesGcmParams : CryptoAlgorithmParameters { + // The initialization vector to use. May be up to 2^64-1 bytes long. + required BufferSource iv; + // The additional authentication data to include. + BufferSource additionalData; + // The desired length of the authentication tag. May be 0 - 128. + [EnforceRange] octet tagLength; +}; diff --git a/src/bun.js/bindings/webcrypto/AesKeyParams.idl b/src/bun.js/bindings/webcrypto/AesKeyParams.idl new file mode 100644 index 000000000..fdc4574f2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/AesKeyParams.idl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// This is a unified dictionary for AesDerivedKeyParams and AesKeyGenParams. +// https://www.w3.org/TR/WebCryptoAPI/#aes-derivedkey-params, and +// https://www.w3.org/TR/WebCryptoAPI/#aes-keygen-params +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmAesKeyParams +] dictionary AesKeyParams : CryptoAlgorithmParameters { + // The length, in bits, of the key. + required [EnforceRange] unsigned short length; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoAesKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoAesKeyAlgorithm.h new file mode 100644 index 000000000..e2aa6cfba --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAesKeyAlgorithm.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoKeyAlgorithm.h" + +namespace WebCore { + +struct CryptoAesKeyAlgorithm : CryptoKeyAlgorithm { + // The length, in bits, of the key. + unsigned short length; +}; + +} diff --git a/src/bun.js/bindings/webcrypto/CryptoAesKeyAlgorithm.idl b/src/bun.js/bindings/webcrypto/CryptoAesKeyAlgorithm.idl new file mode 100644 index 000000000..4f7513e35 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAesKeyAlgorithm.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 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. + */ + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject +] dictionary CryptoAesKeyAlgorithm : CryptoKeyAlgorithm { + // The length, in bits, of the key. + required unsigned short length; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp new file mode 100644 index 000000000..ca3b97bff --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +#include "ScriptExecutionContext.h" + +namespace WebCore { + +void CryptoAlgorithm::encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::generateKey(const CryptoAlgorithmParameters&, bool, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&& exceptionCallback) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&& exceptionCallback) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::wrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&& exceptionCallback) +{ + exceptionCallback(NotSupportedError); +} + +void CryptoAlgorithm::unwrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&& exceptionCallback) +{ + exceptionCallback(NotSupportedError); +} + +ExceptionOr<size_t> CryptoAlgorithm::getKeyLength(const CryptoAlgorithmParameters&) +{ + return Exception { NotSupportedError }; +} + +template<typename ResultCallbackType, typename OperationType> +static void dispatchAlgorithmOperation(WorkQueue& workQueue, ScriptExecutionContext& context, ResultCallbackType&& callback, CryptoAlgorithm::ExceptionCallback&& exceptionCallback, OperationType&& operation) +{ + workQueue.dispatch( + [operation = WTFMove(operation), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), contextIdentifier = context.identifier()]() mutable { + auto result = operation(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [result = crossThreadCopy(WTFMove(result)), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](auto&) mutable { + if (result.hasException()) { + exceptionCallback(result.releaseException().code()); + return; + } + callback(result.releaseReturnValue()); + }); + }); +} + +void CryptoAlgorithm::dispatchOperationInWorkQueue(WorkQueue& workQueue, ScriptExecutionContext& context, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, Function<ExceptionOr<Vector<uint8_t>>()>&& operation) +{ + dispatchAlgorithmOperation(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), WTFMove(operation)); +} + +void CryptoAlgorithm::dispatchOperationInWorkQueue(WorkQueue& workQueue, ScriptExecutionContext& context, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, Function<ExceptionOr<bool>()>&& operation) +{ + dispatchAlgorithmOperation(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), WTFMove(operation)); +} + +} + +#endif diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.h new file mode 100644 index 000000000..40dbb0ad6 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithmIdentifier.h" +#include "CryptoKeyFormat.h" +#include "CryptoKeyPair.h" +#include "CryptoKeyUsage.h" +#include "ExceptionOr.h" +#include "JsonWebKey.h" +#include <variant> +#include <wtf/Function.h> +#include <wtf/ThreadSafeRefCounted.h> +#include <wtf/Vector.h> +#include <wtf/WorkQueue.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmParameters; +class CryptoKey; +class ScriptExecutionContext; + +using KeyData = std::variant<Vector<uint8_t>, JsonWebKey>; +using KeyOrKeyPair = std::variant<RefPtr<CryptoKey>, CryptoKeyPair>; + +class CryptoAlgorithm : public ThreadSafeRefCounted<CryptoAlgorithm> { +public: + virtual ~CryptoAlgorithm() = default; + + virtual CryptoAlgorithmIdentifier identifier() const = 0; + + using BoolCallback = Function<void(bool)>; + using KeyCallback = Function<void(CryptoKey&)>; + using KeyOrKeyPairCallback = Function<void(KeyOrKeyPair&&)>; + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=169395 + using VectorCallback = Function<void(const Vector<uint8_t>&)>; + using VoidCallback = Function<void()>; + using ExceptionCallback = Function<void(ExceptionCode)>; + using KeyDataCallback = Function<void(CryptoKeyFormat, KeyData&&)>; + + virtual void encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&); + virtual void decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&); + virtual void sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&); + virtual void verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&& signature, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&); + virtual void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&); + virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&); + virtual void deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&); + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=169262 + virtual void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&); + virtual void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&); + virtual void wrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&); + virtual void unwrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&); + virtual ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&); + + static void dispatchOperationInWorkQueue(WorkQueue&, ScriptExecutionContext&, VectorCallback&&, ExceptionCallback&&, Function<ExceptionOr<Vector<uint8_t>>()>&&); + static void dispatchOperationInWorkQueue(WorkQueue&, ScriptExecutionContext&, BoolCallback&&, ExceptionCallback&&, Function<ExceptionOr<bool>()>&&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBC.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBC.cpp new file mode 100644 index 000000000..c13df346e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBC.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmAES_CBC.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCbcCfbParams.h" +#include "CryptoAlgorithmAesKeyParams.h" +#include "CryptoKeyAES.h" +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +namespace CryptoAlgorithmAES_CBCInternal { +static constexpr auto ALG128 = "A128CBC"_s; +static constexpr auto ALG192 = "A192CBC"_s; +static constexpr auto ALG256 = "A256CBC"_s; +static const size_t IVSIZE = 16; +} + +static inline bool usagesAreInvalidForCryptoAlgorithmAES_CBC(CryptoKeyUsageBitmap usages) +{ + return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits); +} + +Ref<CryptoAlgorithm> CryptoAlgorithmAES_CBC::create() +{ + return adoptRef(*new CryptoAlgorithmAES_CBC); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmAES_CBC::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmAES_CBC::encrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& plainText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + using namespace CryptoAlgorithmAES_CBCInternal; + + auto& aesParameters = downcast<CryptoAlgorithmAesCbcCfbParams>(parameters); + if (aesParameters.ivVector().size() != IVSIZE) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), plainText = WTFMove(plainText)] { + return platformEncrypt(parameters, downcast<CryptoKeyAES>(key.get()), plainText); + }); +} + +void CryptoAlgorithmAES_CBC::decrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + using namespace CryptoAlgorithmAES_CBCInternal; + + auto& aesParameters = downcast<CryptoAlgorithmAesCbcCfbParams>(parameters); + if (aesParameters.ivVector().size() != IVSIZE) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), cipherText = WTFMove(cipherText)] { + return platformDecrypt(parameters, downcast<CryptoKeyAES>(key.get()), cipherText); + }); +} + +void CryptoAlgorithmAES_CBC::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters); + + if (usagesAreInvalidForCryptoAlgorithmAES_CBC(usages)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_CBC, aesParameters.length, extractable, usages); + if (!result) { + exceptionCallback(OperationError); + return; + } + + callback(WTFMove(result)); +} + +void CryptoAlgorithmAES_CBC::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_CBCInternal; + + if (usagesAreInvalidForCryptoAlgorithmAES_CBC(usages)) { + exceptionCallback(SyntaxError); + return; + } + + RefPtr<CryptoKeyAES> result; + switch (format) { + case CryptoKeyFormat::Raw: + result = CryptoKeyAES::importRaw(parameters.identifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Jwk: { + auto checkAlgCallback = [](size_t length, const String& alg) -> bool { + switch (length) { + case CryptoKeyAES::s_length128: + return alg.isNull() || alg == ALG128; + case CryptoKeyAES::s_length192: + return alg.isNull() || alg == ALG192; + case CryptoKeyAES::s_length256: + return alg.isNull() || alg == ALG256; + } + return false; + }; + result = CryptoKeyAES::importJwk(parameters.identifier, WTFMove(std::get<JsonWebKey>(data)), extractable, usages, WTFMove(checkAlgCallback)); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmAES_CBC::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_CBCInternal; + const auto& aesKey = downcast<CryptoKeyAES>(key.get()); + + if (aesKey.key().isEmpty()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Raw: + result = Vector<uint8_t>(aesKey.key()); + break; + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = aesKey.exportJwk(); + switch (aesKey.key().size() * 8) { + case CryptoKeyAES::s_length128: + jwk.alg = String(ALG128); + break; + case CryptoKeyAES::s_length192: + jwk.alg = String(ALG192); + break; + case CryptoKeyAES::s_length256: + jwk.alg = String(ALG256); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +ExceptionOr<size_t> CryptoAlgorithmAES_CBC::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + return CryptoKeyAES::getKeyLength(parameters); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBC.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBC.h new file mode 100644 index 000000000..b7443a733 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBC.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesCbcCfbParams; +class CryptoKeyAES; + +class CryptoAlgorithmAES_CBC final : public CryptoAlgorithm { +public: + enum class Padding : uint8_t { + Yes, + No + }; + + static constexpr ASCIILiteral s_name = "AES-CBC"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::AES_CBC; + static Ref<CryptoAlgorithm> create(); + + // Operations can be performed directly. + WEBCORE_EXPORT static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&, Padding padding = Padding::Yes); + WEBCORE_EXPORT static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&, Padding padding = Padding::Yes); + +private: + CryptoAlgorithmAES_CBC() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBCOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBCOpenSSL.cpp new file mode 100644 index 000000000..c271c067f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CBCOpenSSL.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmAES_CBC.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCbcCfbParams.h" +#include "CryptoKeyAES.h" +#include "OpenSSLCryptoUniquePtr.h" +#include <openssl/evp.h> + +namespace WebCore { + +static const EVP_CIPHER* aesAlgorithm(size_t keySize) +{ + if (keySize * 8 == 128) + return EVP_aes_128_cbc(); + + if (keySize * 8 == 192) + return EVP_aes_192_cbc(); + + if (keySize * 8 == 256) + return EVP_aes_256_cbc(); + + return nullptr; +} + +static std::optional<Vector<uint8_t>> cryptEncrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, Vector<uint8_t>&& plainText) +{ + const EVP_CIPHER* algorithm = aesAlgorithm(key.size()); + if (!algorithm) + return std::nullopt; + + EvpCipherCtxPtr ctx; + int len; + + // Create and initialize the context + if (!(ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new()))) + return std::nullopt; + + size_t plainSize = plainText.size(); + const size_t cipherTextLen = roundUpToMultipleOf(EVP_CIPHER_block_size(algorithm), plainSize + 1); + Vector<uint8_t> cipherText(cipherTextLen); + + // Initialize the encryption operation + if (1 != EVP_EncryptInit_ex(ctx.get(), algorithm, nullptr, key.data(), iv.data())) + return std::nullopt; + + // Provide the message to be encrypted, and obtain the encrypted output + if (1 != EVP_EncryptUpdate(ctx.get(), cipherText.data(), &len, plainText.data(), plainSize)) + return std::nullopt; + + // Finalize the encryption. Further ciphertext bytes may be written at this stage + if (1 != EVP_EncryptFinal_ex(ctx.get(), cipherText.data() + len, &len)) + return std::nullopt; + + return cipherText; +} + +static std::optional<Vector<uint8_t>> cryptDecrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, const Vector<uint8_t>& cipherText) +{ + const EVP_CIPHER* algorithm = aesAlgorithm(key.size()); + if (!algorithm) + return std::nullopt; + + EvpCipherCtxPtr ctx; + + size_t cipherSize = cipherText.size(); + Vector<uint8_t> plainText(cipherSize); + int len; + int plainTextLen; + + // Create and initialize the context + if (!(ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new()))) + return std::nullopt; + + // Initialize the decryption operation + if (1 != EVP_DecryptInit_ex(ctx.get(), algorithm, nullptr, key.data(), iv.data())) + return std::nullopt; + + // Provide the message to be decrypted, and obtain the plaintext output + if (1 != EVP_DecryptUpdate(ctx.get(), plainText.data(), &len, cipherText.data(), cipherSize)) + return std::nullopt; + plainTextLen = len; + + // Finalize the decryption. Further plaintext bytes may be written at this stage + if (1 != EVP_DecryptFinal_ex(ctx.get(), plainText.data() + len, &len)) + return std::nullopt; + plainTextLen += len; + + plainText.shrink(plainTextLen); + + return plainText; +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformEncrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText, Padding) +{ + auto output = cryptEncrypt(key.key(), parameters.ivVector(), Vector<uint8_t>(plainText)); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformDecrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText, Padding) +{ + auto output = cryptDecrypt(key.key(), parameters.ivVector(), cipherText); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFB.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFB.cpp new file mode 100644 index 000000000..88e8075b6 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFB.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2017 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 "CryptoAlgorithmAES_CFB.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCbcCfbParams.h" +#include "CryptoAlgorithmAesKeyParams.h" +#include "CryptoKeyAES.h" +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +namespace CryptoAlgorithmAES_CFBInternal { +static constexpr auto ALG128 = "A128CFB8"_s; +static constexpr auto ALG192 = "A192CFB8"_s; +static constexpr auto ALG256 = "A256CFB8"_s; +static const size_t IVSIZE = 16; +} + +static inline bool usagesAreInvalidForCryptoAlgorithmAES_CFB(CryptoKeyUsageBitmap usages) +{ + return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits); +} + +Ref<CryptoAlgorithm> CryptoAlgorithmAES_CFB::create() +{ + return adoptRef(*new CryptoAlgorithmAES_CFB); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmAES_CFB::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmAES_CFB::encrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& plainText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + using namespace CryptoAlgorithmAES_CFBInternal; + + auto& aesParameters = downcast<CryptoAlgorithmAesCbcCfbParams>(parameters); + if (aesParameters.ivVector().size() != IVSIZE) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), plainText = WTFMove(plainText)] { + return platformEncrypt(parameters, downcast<CryptoKeyAES>(key.get()), plainText); + }); +} + +void CryptoAlgorithmAES_CFB::decrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + using namespace CryptoAlgorithmAES_CFBInternal; + + auto& aesParameters = downcast<CryptoAlgorithmAesCbcCfbParams>(parameters); + if (aesParameters.ivVector().size() != IVSIZE) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), cipherText = WTFMove(cipherText)] { + return platformDecrypt(parameters, downcast<CryptoKeyAES>(key.get()), cipherText); + }); +} + +void CryptoAlgorithmAES_CFB::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters); + + if (usagesAreInvalidForCryptoAlgorithmAES_CFB(usages)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_CFB, aesParameters.length, extractable, usages); + if (!result) { + exceptionCallback(OperationError); + return; + } + + callback(WTFMove(result)); +} + +void CryptoAlgorithmAES_CFB::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_CFBInternal; + + if (usagesAreInvalidForCryptoAlgorithmAES_CFB(usages)) { + exceptionCallback(SyntaxError); + return; + } + + RefPtr<CryptoKeyAES> result; + switch (format) { + case CryptoKeyFormat::Raw: + result = CryptoKeyAES::importRaw(parameters.identifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Jwk: { + auto checkAlgCallback = [](size_t length, const String& alg) -> bool { + switch (length) { + case CryptoKeyAES::s_length128: + return alg.isNull() || alg == ALG128; + case CryptoKeyAES::s_length192: + return alg.isNull() || alg == ALG192; + case CryptoKeyAES::s_length256: + return alg.isNull() || alg == ALG256; + } + return false; + }; + result = CryptoKeyAES::importJwk(parameters.identifier, WTFMove(std::get<JsonWebKey>(data)), extractable, usages, WTFMove(checkAlgCallback)); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmAES_CFB::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_CFBInternal; + const auto& aesKey = downcast<CryptoKeyAES>(key.get()); + + if (aesKey.key().isEmpty()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Raw: + result = Vector<uint8_t>(aesKey.key()); + break; + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = aesKey.exportJwk(); + switch (aesKey.key().size() * 8) { + case CryptoKeyAES::s_length128: + jwk.alg = String(ALG128); + break; + case CryptoKeyAES::s_length192: + jwk.alg = String(ALG192); + break; + case CryptoKeyAES::s_length256: + jwk.alg = String(ALG256); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +ExceptionOr<size_t> CryptoAlgorithmAES_CFB::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + return CryptoKeyAES::getKeyLength(parameters); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFB.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFB.h new file mode 100644 index 000000000..508a20336 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFB.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesCbcCfbParams; +class CryptoKeyAES; + +class CryptoAlgorithmAES_CFB final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "AES-CFB-8"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::AES_CFB; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmAES_CFB() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; + + static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&); + static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFBOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFBOpenSSL.cpp new file mode 100644 index 000000000..bfa431d68 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CFBOpenSSL.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2022 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmAES_CFB.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCbcCfbParams.h" +#include "CryptoKeyAES.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +static std::optional<Vector<uint8_t>> cfb8(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, const Vector<uint8_t>& input, bool encrypt) +{ + if (iv.size() != AES_BLOCK_SIZE) + return std::nullopt; + + AESKey aesKey; + if (!aesKey.setKey(key, AES_ENCRYPT)) + return std::nullopt; + + // Instead of memmoving the input vector every time, we have a AES_BLOCK_SIZE * 2 length buffer + // and shift the input position (shiftRegister + shift) as well as the feedback position + // (shiftRegister + shift + AES_BLOCK_SIZE) until the feedback position reaches + // the end of the buffer. + uint8_t shiftRegister[AES_BLOCK_SIZE * 2]; + memcpy(shiftRegister, iv.data(), AES_BLOCK_SIZE); + size_t shift = 0; + + Vector<uint8_t> output(input.size()); + + uint8_t encryptedBlock[AES_BLOCK_SIZE]; + for (size_t i = 0; i < output.size(); i++) { + AES_encrypt(shiftRegister + shift, encryptedBlock, aesKey.key()); + + // In the CFB8 mode the first byte (most significant 8 bits) of the encrypted block + // is used as a key stream. The output stream is generated by XORing the input and the key stream. + output[i] = input[i] ^ encryptedBlock[0]; + + // Feed back the 8 bit cipher to the shift register. The cipher stream is + // "output" in the encryption mode and "input" in the decryption mode. + shiftRegister[AES_BLOCK_SIZE + (shift++)] = encrypt ? output[i] : input[i]; + if (shift == AES_BLOCK_SIZE) { + memcpy(shiftRegister, shiftRegister + AES_BLOCK_SIZE, AES_BLOCK_SIZE); + shift = 0; + } + } + memset(encryptedBlock, 0, sizeof encryptedBlock); + + return output; +} + +static std::optional<Vector<uint8_t>> cryptEncrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, Vector<uint8_t>&& plainText) +{ + return cfb8(key, iv, plainText, true); +} + +static std::optional<Vector<uint8_t>> cryptDecrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, const Vector<uint8_t>& cipherText) +{ + return cfb8(key, iv, cipherText, false); +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CFB::platformEncrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText) +{ + auto output = cryptEncrypt(key.key(), parameters.ivVector(), Vector<uint8_t>(plainText)); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CFB::platformDecrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText) +{ + auto output = cryptDecrypt(key.key(), parameters.ivVector(), cipherText); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTR.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTR.cpp new file mode 100644 index 000000000..9b2648e8a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTR.cpp @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmAES_CTR.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCtrParams.h" +#include "CryptoAlgorithmAesKeyParams.h" +#include "CryptoKeyAES.h" +#include <wtf/CrossThreadCopier.h> +#include <wtf/FlipBytes.h> + +namespace WebCore { + +namespace CryptoAlgorithmAES_CTRInternal { +static constexpr auto ALG128 = "A128CTR"_s; +static constexpr auto ALG192 = "A192CTR"_s; +static constexpr auto ALG256 = "A256CTR"_s; +static const size_t CounterSize = 16; +static const uint64_t AllBitsSet = ~(uint64_t)0; +} + +static inline bool usagesAreInvalidForCryptoAlgorithmAES_CTR(CryptoKeyUsageBitmap usages) +{ + return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits); +} + +static bool parametersAreValid(const CryptoAlgorithmAesCtrParams& parameters) +{ + using namespace CryptoAlgorithmAES_CTRInternal; + if (parameters.counterVector().size() != CounterSize) + return false; + if (!parameters.length || parameters.length > 128) + return false; + return true; +} + +Ref<CryptoAlgorithm> CryptoAlgorithmAES_CTR::create() +{ + return adoptRef(*new CryptoAlgorithmAES_CTR); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmAES_CTR::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmAES_CTR::encrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& plainText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto& aesParameters = downcast<CryptoAlgorithmAesCtrParams>(parameters); + if (!parametersAreValid(aesParameters)) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), plainText = WTFMove(plainText)] { + return platformEncrypt(parameters, downcast<CryptoKeyAES>(key.get()), plainText); + }); +} + +void CryptoAlgorithmAES_CTR::decrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto& aesParameters = downcast<CryptoAlgorithmAesCtrParams>(parameters); + if (!parametersAreValid(aesParameters)) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), cipherText = WTFMove(cipherText)] { + return platformDecrypt(parameters, downcast<CryptoKeyAES>(key.get()), cipherText); + }); +} + +void CryptoAlgorithmAES_CTR::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters); + + if (usagesAreInvalidForCryptoAlgorithmAES_CTR(usages)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_CTR, aesParameters.length, extractable, usages); + if (!result) { + exceptionCallback(OperationError); + return; + } + + callback(WTFMove(result)); +} + +void CryptoAlgorithmAES_CTR::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_CTRInternal; + + if (usagesAreInvalidForCryptoAlgorithmAES_CTR(usages)) { + exceptionCallback(SyntaxError); + return; + } + + RefPtr<CryptoKeyAES> result; + switch (format) { + case CryptoKeyFormat::Raw: + result = CryptoKeyAES::importRaw(parameters.identifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Jwk: { + auto checkAlgCallback = [](size_t length, const String& alg) -> bool { + switch (length) { + case CryptoKeyAES::s_length128: + return alg.isNull() || alg == ALG128; + case CryptoKeyAES::s_length192: + return alg.isNull() || alg == ALG192; + case CryptoKeyAES::s_length256: + return alg.isNull() || alg == ALG256; + } + return false; + }; + result = CryptoKeyAES::importJwk(parameters.identifier, WTFMove(std::get<JsonWebKey>(data)), extractable, usages, WTFMove(checkAlgCallback)); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmAES_CTR::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_CTRInternal; + const auto& aesKey = downcast<CryptoKeyAES>(key.get()); + + if (aesKey.key().isEmpty()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Raw: + result = Vector<uint8_t>(aesKey.key()); + break; + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = aesKey.exportJwk(); + switch (aesKey.key().size() * 8) { + case CryptoKeyAES::s_length128: + jwk.alg = String(ALG128); + break; + case CryptoKeyAES::s_length192: + jwk.alg = String(ALG192); + break; + case CryptoKeyAES::s_length256: + jwk.alg = String(ALG256); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +ExceptionOr<size_t> CryptoAlgorithmAES_CTR::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + return CryptoKeyAES::getKeyLength(parameters); +} + +CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockHelper(const Vector<uint8_t>& counterVector, size_t counterLength) + : m_counterLength(counterLength) +{ + using namespace CryptoAlgorithmAES_CTRInternal; + + ASSERT(counterVector.size() == CounterSize); + ASSERT(counterLength <= CounterSize * 8); + bool littleEndian = false; // counterVector is stored in big-endian. + memcpy(&m_bits.m_hi, counterVector.data(), 8); + m_bits.m_hi = flipBytesIfLittleEndian(m_bits.m_hi, littleEndian); + memcpy(&m_bits.m_lo, counterVector.data() + 8, 8); + m_bits.m_lo = flipBytesIfLittleEndian(m_bits.m_lo, littleEndian); +} + +size_t CryptoAlgorithmAES_CTR::CounterBlockHelper::countToOverflowSaturating() const +{ + CounterBlockBits counterMask; + counterMask.set(); + counterMask <<= m_counterLength; + counterMask = ~counterMask; + + auto countMinusOne = ~m_bits & counterMask; + + CounterBlockBits sizeTypeMask; + sizeTypeMask.set(); + sizeTypeMask <<= sizeof(size_t) * 8; + if ((sizeTypeMask & countMinusOne).any()) { + // Saturating to the size_t max since the count is greater than that. + return std::numeric_limits<size_t>::max(); + } + + countMinusOne &= ~sizeTypeMask; + if (countMinusOne.all()) { + // As all bits are set, adding one would result in an overflow. + // Return size_t max instead. + return std::numeric_limits<size_t>::max(); + } + + static_assert(sizeof(size_t) <= sizeof(uint64_t)); + return countMinusOne.m_lo + 1; +} + +Vector<uint8_t> CryptoAlgorithmAES_CTR::CounterBlockHelper::counterVectorAfterOverflow() const +{ + using namespace CryptoAlgorithmAES_CTRInternal; + + CounterBlockBits nonceMask; + nonceMask.set(); + nonceMask <<= m_counterLength; + auto bits = m_bits & nonceMask; + + bool littleEndian = false; // counterVector is stored in big-endian. + Vector<uint8_t> counterVector(CounterSize); + uint64_t hi = flipBytesIfLittleEndian(bits.m_hi, littleEndian); + memcpy(counterVector.data(), &hi, 8); + uint64_t lo = flipBytesIfLittleEndian(bits.m_lo, littleEndian); + memcpy(counterVector.data() + 8, &lo, 8); + + return counterVector; +} + +void CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockBits::set() +{ + using namespace CryptoAlgorithmAES_CTRInternal; + m_hi = AllBitsSet; + m_lo = AllBitsSet; +} + +bool CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockBits::all() const +{ + using namespace CryptoAlgorithmAES_CTRInternal; + return m_hi == AllBitsSet && m_lo == AllBitsSet; +} + +bool CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockBits::any() const +{ + return m_hi || m_lo; +} + +auto CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockBits::operator&(const CounterBlockBits& rhs) const -> CounterBlockBits +{ + return { m_hi & rhs.m_hi, m_lo & rhs.m_lo }; +} + +auto CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockBits::operator~() const -> CounterBlockBits +{ + return { ~m_hi, ~m_lo }; +} + +auto CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockBits::operator <<=(unsigned shift) -> CounterBlockBits& +{ + if (shift < 64) { + m_hi = (m_hi << shift) | m_lo >> (64 - shift); + m_lo <<= shift; + } else if (shift < 128) { + shift -= 64; + m_hi = m_lo << shift; + m_lo = 0; + } else { + m_hi = 0; + m_lo = 0; + } + return *this; +} + +auto CryptoAlgorithmAES_CTR::CounterBlockHelper::CounterBlockBits::operator &=(const CounterBlockBits& rhs) -> CounterBlockBits& +{ + m_hi &= rhs.m_hi; + m_lo &= rhs.m_lo; + return *this; +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTR.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTR.h new file mode 100644 index 000000000..8bd39339d --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTR.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesCtrParams; +class CryptoKeyAES; + +class CryptoAlgorithmAES_CTR final : public CryptoAlgorithm { +public: + class CounterBlockHelper { + public: + CounterBlockHelper(const Vector<uint8_t>& counterVector, size_t counterLength); + + size_t countToOverflowSaturating() const; + Vector<uint8_t> counterVectorAfterOverflow() const; + + private: + // 128 bits integer with miminum required operators. + struct CounterBlockBits { + void set(); + bool all() const; + bool any() const; + + CounterBlockBits operator&(const CounterBlockBits&) const; + CounterBlockBits operator~() const; + CounterBlockBits& operator <<=(unsigned); + CounterBlockBits& operator &=(const CounterBlockBits&); + + uint64_t m_hi { 0 }; + uint64_t m_lo { 0 }; + }; + + CounterBlockBits m_bits; + const size_t m_counterLength; + }; + + static constexpr ASCIILiteral s_name = "AES-CTR"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::AES_CTR; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmAES_CTR() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; + + static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmAesCtrParams&, const CryptoKeyAES&, const Vector<uint8_t>&); + static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmAesCtrParams&, const CryptoKeyAES&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTROpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTROpenSSL.cpp new file mode 100644 index 000000000..ca2f9b559 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_CTROpenSSL.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmAES_CTR.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCtrParams.h" +#include "CryptoKeyAES.h" +#include "OpenSSLCryptoUniquePtr.h" +#include <openssl/evp.h> + +namespace WebCore { + +static const EVP_CIPHER* aesAlgorithm(size_t keySize) +{ + if (keySize * 8 == 128) + return EVP_aes_128_ctr(); + + if (keySize * 8 == 192) + return EVP_aes_192_ctr(); + + if (keySize * 8 == 256) + return EVP_aes_256_ctr(); + + return nullptr; +} + +static std::optional<Vector<uint8_t>> crypt(int operation, const Vector<uint8_t>& key, const Vector<uint8_t>& counter, size_t counterLength, const Vector<uint8_t>& inputText) +{ + constexpr size_t blockSize = 16; + const EVP_CIPHER* algorithm = aesAlgorithm(key.size()); + if (!algorithm) + return std::nullopt; + + EvpCipherCtxPtr ctx; + int len; + + // Create and initialize the context + if (!(ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new()))) + return std::nullopt; + + const size_t blocks = roundUpToMultipleOf(blockSize, inputText.size()) / blockSize; + + // Detect loop + if (counterLength < sizeof(size_t) * 8 && blocks > ((size_t)1 << counterLength)) + return std::nullopt; + + // Calculate capacity before overflow + CryptoAlgorithmAES_CTR::CounterBlockHelper counterBlockHelper(counter, counterLength); + size_t capacity = counterBlockHelper.countToOverflowSaturating(); + + // Divide data into two parts if necessary + size_t headSize = inputText.size(); + if (capacity < blocks) + headSize = capacity * blockSize; + + Vector<uint8_t> outputText(inputText.size()); + // First part + { + // Initialize the encryption(decryption) operation + if (1 != EVP_CipherInit_ex(ctx.get(), algorithm, nullptr, key.data(), counter.data(), operation)) + return std::nullopt; + + // Disable padding + if (1 != EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) + return std::nullopt; + + // Provide the message to be encrypted(decrypted), and obtain the encrypted(decrypted) output + if (1 != EVP_CipherUpdate(ctx.get(), outputText.data(), &len, inputText.data(), headSize)) + return std::nullopt; + + // Finalize the encryption(decryption) + if (1 != EVP_CipherFinal_ex(ctx.get(), outputText.data() + len, &len)) + return std::nullopt; + } + + // Sedond part + if (capacity < blocks) { + size_t tailSize = inputText.size() - headSize; + + Vector<uint8_t> remainingCounter = counterBlockHelper.counterVectorAfterOverflow(); + + // Initialize the encryption(decryption) operation + if (1 != EVP_CipherInit_ex(ctx.get(), algorithm, nullptr, key.data(), remainingCounter.data(), operation)) + return std::nullopt; + + // Disable padding + if (1 != EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) + return std::nullopt; + + // Provide the message to be encrypted(decrypted), and obtain the encrypted(decrypted) output + if (1 != EVP_CipherUpdate(ctx.get(), outputText.data() + headSize, &len, inputText.data() + headSize, tailSize)) + return std::nullopt; + + // Finalize the encryption(decryption) + if (1 != EVP_CipherFinal_ex(ctx.get(), outputText.data() + headSize + len, &len)) + return std::nullopt; + } + + return outputText; +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CTR::platformEncrypt(const CryptoAlgorithmAesCtrParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText) +{ + auto output = crypt(1, key.key(), parameters.counterVector(), parameters.length, plainText); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CTR::platformDecrypt(const CryptoAlgorithmAesCtrParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText) +{ + auto output = crypt(0, key.key(), parameters.counterVector(), parameters.length, cipherText); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCM.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCM.cpp new file mode 100644 index 000000000..2dcbbb7b8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCM.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2017 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 "CryptoAlgorithmAES_GCM.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesGcmParams.h" +#include "CryptoAlgorithmAesKeyParams.h" +#include "CryptoKeyAES.h" +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +namespace CryptoAlgorithmAES_GCMInternal { +static constexpr auto ALG128 = "A128GCM"_s; +static constexpr auto ALG192 = "A192GCM"_s; +static constexpr auto ALG256 = "A256GCM"_s; +#if CPU(ADDRESS64) +static const uint64_t PlainTextMaxLength = 549755813632ULL; // 2^39 - 256 +#endif +static const uint8_t DefaultTagLength = 128; +static const uint8_t ValidTagLengths[] = { 32, 64, 96, 104, 112, 120, 128 }; +} + +static inline bool usagesAreInvalidForCryptoAlgorithmAES_GCM(CryptoKeyUsageBitmap usages) +{ + return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits); +} + +static inline bool tagLengthIsValid(uint8_t tagLength) +{ + using namespace CryptoAlgorithmAES_GCMInternal; + for (size_t i = 0; i < sizeof(ValidTagLengths); i++) { + if (tagLength == ValidTagLengths[i]) + return true; + } + return false; +} + +Ref<CryptoAlgorithm> CryptoAlgorithmAES_GCM::create() +{ + return adoptRef(*new CryptoAlgorithmAES_GCM); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmAES_GCM::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmAES_GCM::encrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& plainText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + using namespace CryptoAlgorithmAES_GCMInternal; + + auto& aesParameters = downcast<CryptoAlgorithmAesGcmParams>(parameters); + +#if CPU(ADDRESS64) + if (plainText.size() > PlainTextMaxLength) { + exceptionCallback(OperationError); + return; + } + if (aesParameters.ivVector().size() > UINT64_MAX) { + exceptionCallback(OperationError); + return; + } + if (aesParameters.additionalDataVector().size() > UINT64_MAX) { + exceptionCallback(OperationError); + return; + } +#endif + + aesParameters.tagLength = aesParameters.tagLength ? aesParameters.tagLength : DefaultTagLength; + if (!tagLengthIsValid(*(aesParameters.tagLength))) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), plainText = WTFMove(plainText)] { + return platformEncrypt(parameters, downcast<CryptoKeyAES>(key.get()), plainText); + }); +} + +void CryptoAlgorithmAES_GCM::decrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + using namespace CryptoAlgorithmAES_GCMInternal; + + auto& aesParameters = downcast<CryptoAlgorithmAesGcmParams>(parameters); + + aesParameters.tagLength = aesParameters.tagLength ? aesParameters.tagLength : DefaultTagLength; + if (!tagLengthIsValid(*(aesParameters.tagLength))) { + exceptionCallback(OperationError); + return; + } + if (cipherText.size() < *(aesParameters.tagLength) / 8) { + exceptionCallback(OperationError); + return; + } + +#if CPU(ADDRESS64) + if (aesParameters.ivVector().size() > UINT64_MAX) { + exceptionCallback(OperationError); + return; + } + if (aesParameters.additionalDataVector().size() > UINT64_MAX) { + exceptionCallback(OperationError); + return; + } +#endif + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(aesParameters), key = WTFMove(key), cipherText = WTFMove(cipherText)] { + return platformDecrypt(parameters, downcast<CryptoKeyAES>(key.get()), cipherText); + }); +} + +void CryptoAlgorithmAES_GCM::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters); + + if (usagesAreInvalidForCryptoAlgorithmAES_GCM(usages)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_GCM, aesParameters.length, extractable, usages); + if (!result) { + exceptionCallback(OperationError); + return; + } + + callback(WTFMove(result)); +} + +void CryptoAlgorithmAES_GCM::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_GCMInternal; + + if (usagesAreInvalidForCryptoAlgorithmAES_GCM(usages)) { + exceptionCallback(SyntaxError); + return; + } + + RefPtr<CryptoKeyAES> result; + switch (format) { + case CryptoKeyFormat::Raw: + result = CryptoKeyAES::importRaw(parameters.identifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Jwk: { + auto checkAlgCallback = [](size_t length, const String& alg) -> bool { + switch (length) { + case CryptoKeyAES::s_length128: + return alg.isNull() || alg == ALG128; + case CryptoKeyAES::s_length192: + return alg.isNull() || alg == ALG192; + case CryptoKeyAES::s_length256: + return alg.isNull() || alg == ALG256; + } + return false; + }; + result = CryptoKeyAES::importJwk(parameters.identifier, WTFMove(std::get<JsonWebKey>(data)), extractable, usages, WTFMove(checkAlgCallback)); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmAES_GCM::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_GCMInternal; + const auto& aesKey = downcast<CryptoKeyAES>(key.get()); + + if (aesKey.key().isEmpty()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Raw: + result = Vector<uint8_t>(aesKey.key()); + break; + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = aesKey.exportJwk(); + switch (aesKey.key().size() * 8) { + case CryptoKeyAES::s_length128: + jwk.alg = String(ALG128); + break; + case CryptoKeyAES::s_length192: + jwk.alg = String(ALG192); + break; + case CryptoKeyAES::s_length256: + jwk.alg = String(ALG256); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +ExceptionOr<size_t> CryptoAlgorithmAES_GCM::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + return CryptoKeyAES::getKeyLength(parameters); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCM.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCM.h new file mode 100644 index 000000000..53310e111 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCM.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesGcmParams; +class CryptoKeyAES; + +class CryptoAlgorithmAES_GCM final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "AES-GCM"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::AES_GCM; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmAES_GCM() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; + + static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmAesGcmParams&, const CryptoKeyAES&, const Vector<uint8_t>&); + static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmAesGcmParams&, const CryptoKeyAES&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCMOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCMOpenSSL.cpp new file mode 100644 index 000000000..0117524c8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_GCMOpenSSL.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmAES_GCM.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesGcmParams.h" +#include "CryptoKeyAES.h" +#include "OpenSSLCryptoUniquePtr.h" +#include <openssl/evp.h> + +namespace WebCore { + +static const EVP_CIPHER* aesAlgorithm(size_t keySize) +{ + if (keySize * 8 == 128) + return EVP_aes_128_gcm(); + + if (keySize * 8 == 192) + return EVP_aes_192_gcm(); + + if (keySize * 8 == 256) + return EVP_aes_256_gcm(); + + return nullptr; +} + +static std::optional<Vector<uint8_t>> cryptEncrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, const Vector<uint8_t>& plainText, const Vector<uint8_t>& additionalData, uint8_t tagLength) +{ + const EVP_CIPHER* algorithm = aesAlgorithm(key.size()); + if (!algorithm) + return std::nullopt; + + EvpCipherCtxPtr ctx; + int len; + + Vector<uint8_t> cipherText(plainText.size() + tagLength); + size_t tagOffset = plainText.size(); + + // Create and initialize the context + if (!(ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new()))) + return std::nullopt; + + // Disable padding + if (1 != EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) + return std::nullopt; + + // Initialize the encryption operation + if (1 != EVP_EncryptInit_ex(ctx.get(), algorithm, nullptr, nullptr, nullptr)) + return std::nullopt; + + // Set IV length + if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, iv.size(), nullptr)) + return std::nullopt; + + // Initialize key and IV + if (1 != EVP_EncryptInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data())) + return std::nullopt; + + // Provide any AAD data + if (additionalData.size() > 0) { + if (1 != EVP_EncryptUpdate(ctx.get(), nullptr, &len, additionalData.data(), additionalData.size())) + return std::nullopt; + } + + // Provide the message to be encrypted, and obtain the encrypted output + if (1 != EVP_EncryptUpdate(ctx.get(), cipherText.data(), &len, plainText.data(), plainText.size())) + return std::nullopt; + + // Finalize the encryption. Normally ciphertext bytes may be written at + // this stage, but this does not occur in GCM mode + if (1 != EVP_EncryptFinal_ex(ctx.get(), cipherText.data() + len, &len)) + return std::nullopt; + + // Get the tag + if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, tagLength, cipherText.data() + tagOffset)) + return std::nullopt; + + return cipherText; +} + +static std::optional<Vector<uint8_t>> cryptDecrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, const Vector<uint8_t>& cipherText, const Vector<uint8_t>& additionalData, uint8_t tagLength) +{ + const EVP_CIPHER* algorithm = aesAlgorithm(key.size()); + if (!algorithm) + return std::nullopt; + + EvpCipherCtxPtr ctx; + int len; + int plainTextLen; + int cipherTextLen = cipherText.size() - tagLength; + + Vector<uint8_t> plainText(cipherText.size()); + Vector<uint8_t> tag { cipherText.data() + cipherTextLen, tagLength }; + + // Create and initialize the context + if (!(ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new()))) + return std::nullopt; + + // Disable padding + if (1 != EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) + return std::nullopt; + + // Initialize the encryption operation + if (1 != EVP_DecryptInit_ex(ctx.get(), algorithm, nullptr, nullptr, nullptr)) + return std::nullopt; + + // Set IV length + if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, iv.size(), nullptr)) + return std::nullopt; + + // Initialize key and IV + if (1 != EVP_DecryptInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data())) + return std::nullopt; + + // Provide any AAD data + if (additionalData.size() > 0) { + if (1 != EVP_DecryptUpdate(ctx.get(), nullptr, &len, additionalData.data(), additionalData.size())) + return std::nullopt; + } + + // Set expected tag value + if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(), tag.data())) + return std::nullopt; + + // Provide the message to be encrypted, and obtain the encrypted output + if (1 != EVP_DecryptUpdate(ctx.get(), plainText.data(), &len, cipherText.data(), cipherTextLen)) + return std::nullopt; + plainTextLen = len; + + // Finalize the decryption + if (1 != EVP_DecryptFinal_ex(ctx.get(), plainText.data() + len, &len)) + return std::nullopt; + + plainTextLen += len; + + plainText.shrink(plainTextLen); + + return plainText; +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_GCM::platformEncrypt(const CryptoAlgorithmAesGcmParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText) +{ + auto output = cryptEncrypt(key.key(), parameters.ivVector(), plainText, parameters.additionalDataVector(), parameters.tagLength.value_or(0) / 8); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_GCM::platformDecrypt(const CryptoAlgorithmAesGcmParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText) +{ + auto output = cryptDecrypt(key.key(), parameters.ivVector(), cipherText, parameters.additionalDataVector(), parameters.tagLength.value_or(0) / 8); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KW.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KW.cpp new file mode 100644 index 000000000..adc65b645 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KW.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmAES_KW.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesKeyParams.h" +#include "CryptoKeyAES.h" +#include <variant> + +namespace WebCore { + +namespace CryptoAlgorithmAES_KWInternal { +static constexpr auto ALG128 = "A128KW"_s; +static constexpr auto ALG192 = "A192KW"_s; +static constexpr auto ALG256 = "A256KW"_s; +} + +static inline bool usagesAreInvalidForCryptoAlgorithmAES_KW(CryptoKeyUsageBitmap usages) +{ + return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt); +} + +Ref<CryptoAlgorithm> CryptoAlgorithmAES_KW::create() +{ + return adoptRef(*new CryptoAlgorithmAES_KW); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmAES_KW::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmAES_KW::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + if (usagesAreInvalidForCryptoAlgorithmAES_KW(usages)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_KW, downcast<CryptoAlgorithmAesKeyParams>(parameters).length, extractable, usages); + if (!result) { + exceptionCallback(OperationError); + return; + } + + callback(WTFMove(result)); +} + +void CryptoAlgorithmAES_KW::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_KWInternal; + + if (usagesAreInvalidForCryptoAlgorithmAES_KW(usages)) { + exceptionCallback(SyntaxError); + return; + } + + RefPtr<CryptoKeyAES> result; + switch (format) { + case CryptoKeyFormat::Raw: + result = CryptoKeyAES::importRaw(parameters.identifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Jwk: { + result = CryptoKeyAES::importJwk(parameters.identifier, WTFMove(std::get<JsonWebKey>(data)), extractable, usages, [](size_t length, const String& alg) -> bool { + switch (length) { + case CryptoKeyAES::s_length128: + return alg.isNull() || alg == ALG128; + case CryptoKeyAES::s_length192: + return alg.isNull() || alg == ALG192; + case CryptoKeyAES::s_length256: + return alg.isNull() || alg == ALG256; + } + return false; + }); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmAES_KW::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmAES_KWInternal; + const auto& aesKey = downcast<CryptoKeyAES>(key.get()); + + if (aesKey.key().isEmpty()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Raw: + result = Vector<uint8_t>(aesKey.key()); + break; + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = aesKey.exportJwk(); + switch (aesKey.key().size() * 8) { + case CryptoKeyAES::s_length128: + jwk.alg = String(ALG128); + break; + case CryptoKeyAES::s_length192: + jwk.alg = String(ALG192); + break; + case CryptoKeyAES::s_length256: + jwk.alg = String(ALG256); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +void CryptoAlgorithmAES_KW::wrapKey(Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + if (data.size() % 8) { + exceptionCallback(OperationError); + return; + } + + auto result = platformWrapKey(downcast<CryptoKeyAES>(key.get()), WTFMove(data)); + if (result.hasException()) { + exceptionCallback(result.releaseException().code()); + return; + } + + callback(result.releaseReturnValue()); +} + +void CryptoAlgorithmAES_KW::unwrapKey(Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + auto result = platformUnwrapKey(downcast<CryptoKeyAES>(key.get()), WTFMove(data)); + if (result.hasException()) { + exceptionCallback(result.releaseException().code()); + return; + } + + callback(result.releaseReturnValue()); +} + +ExceptionOr<size_t> CryptoAlgorithmAES_KW::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + return CryptoKeyAES::getKeyLength(parameters); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KW.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KW.h new file mode 100644 index 000000000..a08dec3f2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KW.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKeyAES; + +class CryptoAlgorithmAES_KW final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "AES-KW"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::AES_KW; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmAES_KW() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + void wrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&) final; + void unwrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; + + static ExceptionOr<Vector<uint8_t>> platformWrapKey(const CryptoKeyAES&, const Vector<uint8_t>&); + static ExceptionOr<Vector<uint8_t>> platformUnwrapKey(const CryptoKeyAES&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KWOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KWOpenSSL.cpp new file mode 100644 index 000000000..606747201 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAES_KWOpenSSL.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmAES_KW.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyAES.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +static std::optional<Vector<uint8_t>> cryptWrapKey(const Vector<uint8_t>& key, const Vector<uint8_t>& data) +{ + if (data.size() % 8) + return std::nullopt; + + AESKey aesKey; + if (!aesKey.setKey(key, AES_ENCRYPT)) + return std::nullopt; + + Vector<uint8_t> cipherText(data.size() + 8); + if (AES_wrap_key(aesKey.key(), nullptr, cipherText.data(), data.data(), data.size()) < 0) + return std::nullopt; + + return cipherText; +} + +static std::optional<Vector<uint8_t>> cryptUnwrapKey(const Vector<uint8_t>& key, const Vector<uint8_t>& data) +{ + if (data.size() % 8 || !data.size()) + return std::nullopt; + + AESKey aesKey; + if (!aesKey.setKey(key, AES_DECRYPT)) + return std::nullopt; + + Vector<uint8_t> plainText(data.size() - 8); + if (AES_unwrap_key(aesKey.key(), nullptr, plainText.data(), data.data(), data.size()) < 0) + return std::nullopt; + + return plainText; +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_KW::platformWrapKey(const CryptoKeyAES& key, const Vector<uint8_t>& data) +{ + auto output = cryptWrapKey(key.key(), data); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_KW::platformUnwrapKey(const CryptoKeyAES& key, const Vector<uint8_t>& data) +{ + auto output = cryptUnwrapKey(key.key(), data); + if (!output) + return Exception { OperationError }; + return WTFMove(*output); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesCbcCfbParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesCbcCfbParams.h new file mode 100644 index 000000000..b2d8d8958 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesCbcCfbParams.h @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#pragma once + +#include "BufferSource.h" +#include "CryptoAlgorithmParameters.h" +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesCbcCfbParams final : public CryptoAlgorithmParameters { +public: + BufferSource iv; + + Class parametersClass() const final { return Class::AesCbcCfbParams; } + + const Vector<uint8_t>& ivVector() const + { + if (!m_ivVector.isEmpty() || !iv.length()) + return m_ivVector; + + m_ivVector.append(iv.data(), iv.length()); + return m_ivVector; + } + + CryptoAlgorithmAesCbcCfbParams isolatedCopy() const + { + CryptoAlgorithmAesCbcCfbParams result; + result.identifier = identifier; + result.m_ivVector = ivVector(); + + return result; + } + +private: + mutable Vector<uint8_t> m_ivVector; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(AesCbcCfbParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesCtrParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesCtrParams.h new file mode 100644 index 000000000..ded52af74 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesCtrParams.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "BufferSource.h" +#include "CryptoAlgorithmParameters.h" +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesCtrParams final : public CryptoAlgorithmParameters { +public: + BufferSource counter; + size_t length; + + Class parametersClass() const final { return Class::AesCtrParams; } + + const Vector<uint8_t>& counterVector() const + { + if (!m_counterVector.isEmpty() || !counter.length()) + return m_counterVector; + + m_counterVector.append(counter.data(), counter.length()); + return m_counterVector; + } + + CryptoAlgorithmAesCtrParams isolatedCopy() const + { + CryptoAlgorithmAesCtrParams result; + result.identifier = identifier; + result.m_counterVector = counterVector(); + result.length = length; + + return result; + } + +private: + mutable Vector<uint8_t> m_counterVector; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(AesCtrParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesGcmParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesGcmParams.h new file mode 100644 index 000000000..67af03987 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesGcmParams.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "BufferSource.h" +#include "CryptoAlgorithmParameters.h" +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesGcmParams final : public CryptoAlgorithmParameters { +public: + BufferSource iv; + // Use additionalDataVector() instead of additionalData. The label will be gone once additionalDataVector() is called. + mutable std::optional<BufferSource::VariantType> additionalData; + mutable std::optional<uint8_t> tagLength; + + Class parametersClass() const final { return Class::AesGcmParams; } + + const Vector<uint8_t>& ivVector() const + { + if (!m_ivVector.isEmpty() || !iv.length()) + return m_ivVector; + + m_ivVector.append(iv.data(), iv.length()); + return m_ivVector; + } + + const Vector<uint8_t>& additionalDataVector() const + { + if (!m_additionalDataVector.isEmpty() || !additionalData) + return m_additionalDataVector; + + BufferSource additionalDataBuffer = WTFMove(*additionalData); + additionalData = std::nullopt; + if (!additionalDataBuffer.length()) + return m_additionalDataVector; + + m_additionalDataVector.append(additionalDataBuffer.data(), additionalDataBuffer.length()); + return m_additionalDataVector; + } + + CryptoAlgorithmAesGcmParams isolatedCopy() const + { + CryptoAlgorithmAesGcmParams result; + result.identifier = identifier; + result.m_ivVector = ivVector(); + result.m_additionalDataVector = additionalDataVector(); + result.tagLength = tagLength; + + return result; + } + +private: + mutable Vector<uint8_t> m_ivVector; + mutable Vector<uint8_t> m_additionalDataVector; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(AesGcmParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesKeyParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesKeyParams.h new file mode 100644 index 000000000..c86fdcc7b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmAesKeyParams.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#pragma once + +#include "CryptoAlgorithmParameters.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmAesKeyParams final : public CryptoAlgorithmParameters { +public: + unsigned short length; + + Class parametersClass() const final { return Class::AesKeyParams; } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(AesKeyParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.cpp new file mode 100644 index 000000000..05be9bb88 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2017 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 "CryptoAlgorithmECDH.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmEcKeyParams.h" +#include "CryptoAlgorithmEcdhKeyDeriveParams.h" +#include "CryptoKeyEC.h" +#include "ScriptExecutionContext.h" + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmECDH::create() +{ + return adoptRef(*new CryptoAlgorithmECDH); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmECDH::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmECDH::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(parameters); + + if (usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier::ECDH, ecParameters.namedCurve, extractable, usages); + if (result.hasException()) { + exceptionCallback(result.releaseException().code()); + return; + } + + auto pair = result.releaseReturnValue(); + pair.publicKey->setUsagesBitmap(0); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & (CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits)); + callback(WTFMove(pair)); +} + +void CryptoAlgorithmECDH::deriveBits(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& baseKey, size_t length, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto& ecParameters = downcast<CryptoAlgorithmEcdhKeyDeriveParams>(parameters); + + if (baseKey->type() != CryptoKey::Type::Private) { + exceptionCallback(InvalidAccessError); + return; + } + ASSERT(ecParameters.publicKey); + if (ecParameters.publicKey->type() != CryptoKey::Type::Public) { + exceptionCallback(InvalidAccessError); + return; + } + if (baseKey->algorithmIdentifier() != ecParameters.publicKey->algorithmIdentifier()) { + exceptionCallback(InvalidAccessError); + return; + } + auto& ecBaseKey = downcast<CryptoKeyEC>(baseKey.get()); + auto& ecPublicKey = downcast<CryptoKeyEC>(*(ecParameters.publicKey.get())); + if (ecBaseKey.namedCurve() != ecPublicKey.namedCurve()) { + exceptionCallback(InvalidAccessError); + return; + } + + auto unifiedCallback = [callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](std::optional<Vector<uint8_t>>&& derivedKey, size_t length) mutable { + if (!derivedKey) { + exceptionCallback(OperationError); + return; + } + if (!length) { + callback(WTFMove(*derivedKey)); + return; + } + auto lengthInBytes = std::ceil(length / 8.); + if (lengthInBytes > (*derivedKey).size()) { + exceptionCallback(OperationError); + return; + } + (*derivedKey).shrink(lengthInBytes); + callback(WTFMove(*derivedKey)); + }; + + // This is a special case that can't use dispatchOperation() because it bundles + // the result validation and callback dispatch into unifiedCallback. + workQueue.dispatch( + [baseKey = WTFMove(baseKey), publicKey = ecParameters.publicKey, length, unifiedCallback = WTFMove(unifiedCallback), contextIdentifier = context.identifier()]() mutable { + auto derivedKey = platformDeriveBits(downcast<CryptoKeyEC>(baseKey.get()), downcast<CryptoKeyEC>(*publicKey)); + ScriptExecutionContext::postTaskTo(contextIdentifier, [derivedKey = WTFMove(derivedKey), length, unifiedCallback = WTFMove(unifiedCallback)](auto&) mutable { + unifiedCallback(WTFMove(derivedKey), length); + }); + }); +} + +void CryptoAlgorithmECDH::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(parameters); + + RefPtr<CryptoKeyEC> result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey key = WTFMove(std::get<JsonWebKey>(data)); + + bool isUsagesAllowed = false; + if (!key.d.isNull()) { + isUsagesAllowed = isUsagesAllowed || !(usages ^ CryptoKeyUsageDeriveKey); + isUsagesAllowed = isUsagesAllowed || !(usages ^ CryptoKeyUsageDeriveBits); + isUsagesAllowed = isUsagesAllowed || !(usages ^ (CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits)); + } + isUsagesAllowed = isUsagesAllowed || !usages; + if (!isUsagesAllowed) { + exceptionCallback(SyntaxError); + return; + } + + if (usages && !key.use.isNull() && key.use != "enc"_s) { + exceptionCallback(DataError); + return; + } + + result = CryptoKeyEC::importJwk(ecParameters.identifier, ecParameters.namedCurve, WTFMove(key), extractable, usages); + break; + } + case CryptoKeyFormat::Raw: + if (usages) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importRaw(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Spki: + if (usages) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importSpki(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Pkcs8: + if (usages && (usages ^ CryptoKeyUsageDeriveKey) && (usages ^ CryptoKeyUsageDeriveBits) && (usages ^ (CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits))) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importPkcs8(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmECDH::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + const auto& ecKey = downcast<CryptoKeyEC>(key.get()); + + if (!ecKey.keySizeInBits()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Jwk: { + auto jwk = ecKey.exportJwk(); + if (jwk.hasException()) { + exceptionCallback(jwk.releaseException().code()); + return; + } + result = jwk.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Raw: { + auto raw = ecKey.exportRaw(); + if (raw.hasException()) { + exceptionCallback(raw.releaseException().code()); + return; + } + result = raw.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Spki: { + auto spki = ecKey.exportSpki(); + if (spki.hasException()) { + exceptionCallback(spki.releaseException().code()); + return; + } + result = spki.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Pkcs8: { + auto pkcs8 = ecKey.exportPkcs8(); + if (pkcs8.hasException()) { + exceptionCallback(pkcs8.releaseException().code()); + return; + } + result = pkcs8.releaseReturnValue(); + break; + } + } + + callback(format, WTFMove(result)); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.h new file mode 100644 index 000000000..32d55456c --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKeyEC; + +class CryptoAlgorithmECDH final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "ECDH"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::ECDH; + static Ref<CryptoAlgorithm> create(); + + // Operations can be performed directly. + WEBCORE_EXPORT static std::optional<Vector<uint8_t>> platformDeriveBits(const CryptoKeyEC&, const CryptoKeyEC&); + +private: + CryptoAlgorithmECDH() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDHOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDHOpenSSL.cpp new file mode 100644 index 000000000..fdd07a9e4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDHOpenSSL.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmECDH.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyEC.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +std::optional<Vector<uint8_t>> CryptoAlgorithmECDH::platformDeriveBits(const CryptoKeyEC& baseKey, const CryptoKeyEC& publicKey) +{ + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(baseKey.platformKey(), nullptr)); + if (!ctx) + return std::nullopt; + + if (EVP_PKEY_derive_init(ctx.get()) <= 0) + return std::nullopt; + + if (EVP_PKEY_derive_set_peer(ctx.get(), publicKey.platformKey()) <= 0) + return std::nullopt; + + // Call with a nullptr to get the required buffer size. + size_t keyLen; + if (EVP_PKEY_derive(ctx.get(), nullptr, &keyLen) <= 0) + return std::nullopt; + + Vector<uint8_t> key(keyLen); + if (EVP_PKEY_derive(ctx.get(), key.data(), &keyLen) <= 0) + return std::nullopt; + + // Shrink the buffer since the new keyLen may differ from the buffer size. + key.shrink(keyLen); + + return key; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp new file mode 100644 index 000000000..dbc000620 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2017 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 "CryptoAlgorithmECDSA.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmEcKeyParams.h" +#include "CryptoAlgorithmEcdsaParams.h" +#include "CryptoKeyEC.h" +#include <JavaScriptCore/JSCJSValueInlines.h> +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +namespace CryptoAlgorithmECDSAInternal { +static constexpr auto ALG256 = "ES256"_s; +static constexpr auto ALG384 = "ES384"_s; +static constexpr auto ALG512 = "ES512"_s; +static constexpr auto P256 = "P-256"_s; +static constexpr auto P384 = "P-384"_s; +static constexpr auto P521 = "P-521"_s; +} + +Ref<CryptoAlgorithm> CryptoAlgorithmECDSA::create() +{ + return adoptRef(*new CryptoAlgorithmECDSA); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmECDSA::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmECDSA::sign(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Private) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmEcdsaParams>(parameters)), key = WTFMove(key), data = WTFMove(data)] { + return platformSign(parameters, downcast<CryptoKeyEC>(key.get()), data); + }); +} + +void CryptoAlgorithmECDSA::verify(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Public) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmEcdsaParams>(parameters)), key = WTFMove(key), signature = WTFMove(signature), data = WTFMove(data)] { + return platformVerify(parameters, downcast<CryptoKeyEC>(key.get()), signature, data); + }); +} + +void CryptoAlgorithmECDSA::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(parameters); + + if (usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier::ECDSA, ecParameters.namedCurve, extractable, usages); + if (result.hasException()) { + exceptionCallback(result.releaseException().code()); + return; + } + + auto pair = result.releaseReturnValue(); + pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & CryptoKeyUsageVerify); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & CryptoKeyUsageSign); + callback(WTFMove(pair)); +} + +void CryptoAlgorithmECDSA::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmECDSAInternal; + const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(parameters); + + RefPtr<CryptoKeyEC> result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey key = WTFMove(std::get<JsonWebKey>(data)); + + if (usages && ((!key.d.isNull() && (usages ^ CryptoKeyUsageSign)) || (key.d.isNull() && (usages ^ CryptoKeyUsageVerify)))) { + exceptionCallback(SyntaxError); + return; + } + if (usages && !key.use.isNull() && key.use != "sig"_s) { + exceptionCallback(DataError); + return; + } + + bool isMatched = false; + if (key.crv == P256) + isMatched = key.alg.isNull() || key.alg == ALG256; + if (key.crv == P384) + isMatched = key.alg.isNull() || key.alg == ALG384; + if (key.crv == P521) + isMatched = key.alg.isNull() || key.alg == ALG512; + if (!isMatched) { + exceptionCallback(DataError); + return; + } + + result = CryptoKeyEC::importJwk(ecParameters.identifier, ecParameters.namedCurve, WTFMove(key), extractable, usages); + break; + } + case CryptoKeyFormat::Raw: + if (usages && (usages ^ CryptoKeyUsageVerify)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importRaw(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Spki: + if (usages && (usages ^ CryptoKeyUsageVerify)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importSpki(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Pkcs8: + if (usages && (usages ^ CryptoKeyUsageSign)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importPkcs8(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmECDSA::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + const auto& ecKey = downcast<CryptoKeyEC>(key.get()); + + if (!ecKey.keySizeInBits()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Jwk: { + auto jwk = ecKey.exportJwk(); + if (jwk.hasException()) { + exceptionCallback(jwk.releaseException().code()); + return; + } + result = jwk.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Raw: { + auto raw = ecKey.exportRaw(); + if (raw.hasException()) { + exceptionCallback(raw.releaseException().code()); + return; + } + result = raw.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Spki: { + auto spki = ecKey.exportSpki(); + if (spki.hasException()) { + exceptionCallback(spki.releaseException().code()); + return; + } + result = spki.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Pkcs8: { + auto pkcs8 = ecKey.exportPkcs8(); + if (pkcs8.hasException()) { + exceptionCallback(pkcs8.releaseException().code()); + return; + } + result = pkcs8.releaseReturnValue(); + break; + } + } + + callback(format, WTFMove(result)); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.h new file mode 100644 index 000000000..b7c7889f8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmEcdsaParams; +class CryptoKeyEC; + +class CryptoAlgorithmECDSA final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "ECDSA"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::ECDSA; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmECDSA() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&& signature, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + + static ExceptionOr<Vector<uint8_t>> platformSign(const CryptoAlgorithmEcdsaParams&, const CryptoKeyEC&, const Vector<uint8_t>&); + static ExceptionOr<bool> platformVerify(const CryptoAlgorithmEcdsaParams&, const CryptoKeyEC&, const Vector<uint8_t>&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSAOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSAOpenSSL.cpp new file mode 100644 index 000000000..46aec1869 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSAOpenSSL.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmECDSA.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmEcdsaParams.h" +#include "CryptoKeyEC.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmECDSA::platformSign(const CryptoAlgorithmEcdsaParams& parameters, const CryptoKeyEC& key, const Vector<uint8_t>& data) +{ + size_t keySizeInBytes = (key.keySizeInBits() + 7) / 8; + + const EVP_MD* md = digestAlgorithm(parameters.hashIdentifier); + if (!md) + return Exception { NotSupportedError }; + + std::optional<Vector<uint8_t>> digest = calculateDigest(md, data); + if (!digest) + return Exception { OperationError }; + + EC_KEY* ecKey = EVP_PKEY_get0_EC_KEY(key.platformKey()); + if (!ecKey) + return Exception { OperationError }; + + // We use ECDSA_do_sign rather than EVP API because the latter handles ECDSA signature in DER format + // while this function is supposed to return simply concatinated "r" and "s". + auto sig = ECDSASigPtr(ECDSA_do_sign(digest->data(), digest->size(), ecKey)); + if (!sig) + return Exception { OperationError }; + + const BIGNUM* r; + const BIGNUM* s; + ECDSA_SIG_get0(sig.get(), &r, &s); + + // Concatenate r and s, expanding r and s to keySizeInBytes. + Vector<uint8_t> signature = convertToBytesExpand(r, keySizeInBytes); + signature.appendVector(convertToBytesExpand(s, keySizeInBytes)); + + return signature; +} + +ExceptionOr<bool> CryptoAlgorithmECDSA::platformVerify(const CryptoAlgorithmEcdsaParams& parameters, const CryptoKeyEC& key, const Vector<uint8_t>& signature, const Vector<uint8_t>& data) +{ + size_t keySizeInBytes = (key.keySizeInBits() + 7) / 8; + + // Bail if the signature size isn't double the key size (i.e. concatenated r and s components). + if (signature.size() != keySizeInBytes * 2) + return false; + + auto sig = ECDSASigPtr(ECDSA_SIG_new()); + auto r = BN_bin2bn(signature.data(), keySizeInBytes, nullptr); + auto s = BN_bin2bn(signature.data() + keySizeInBytes, keySizeInBytes, nullptr); + + if (!ECDSA_SIG_set0(sig.get(), r, s)) + return Exception { OperationError }; + + const EVP_MD* md = digestAlgorithm(parameters.hashIdentifier); + if (!md) + return Exception { NotSupportedError }; + + std::optional<Vector<uint8_t>> digest = calculateDigest(md, data); + if (!digest) + return Exception { OperationError }; + + EC_KEY* ecKey = EVP_PKEY_get0_EC_KEY(key.platformKey()); + if (!ecKey) + return Exception { OperationError }; + + int ret = ECDSA_do_verify(digest->data(), digest->size(), sig.get(), ecKey); + return ret == 1; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcKeyParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcKeyParams.h new file mode 100644 index 000000000..eb5c459e7 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcKeyParams.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithmParameters.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmEcKeyParams final : public CryptoAlgorithmParameters { +public: + String namedCurve; + + Class parametersClass() const final { return Class::EcKeyParams; } + + CryptoAlgorithmEcKeyParams isolatedCopy() const + { + CryptoAlgorithmEcKeyParams result; + result.identifier = identifier; + result.namedCurve = namedCurve.isolatedCopy(); + + return result; + } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(EcKeyParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcdhKeyDeriveParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcdhKeyDeriveParams.h new file mode 100644 index 000000000..e8149253b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcdhKeyDeriveParams.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithmParameters.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKey; + +class CryptoAlgorithmEcdhKeyDeriveParams final : public CryptoAlgorithmParameters { +public: + RefPtr<CryptoKey> publicKey; + + Class parametersClass() const final { return Class::EcdhKeyDeriveParams; } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(EcdhKeyDeriveParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcdsaParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcdsaParams.h new file mode 100644 index 000000000..e08de2802 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmEcdsaParams.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithmParameters.h" +#include <JavaScriptCore/JSObject.h> +#include <JavaScriptCore/Strong.h> +#include <variant> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmEcdsaParams final : public CryptoAlgorithmParameters { +public: + // FIXME: Consider merging hash and hashIdentifier. + std::variant<JSC::Strong<JSC::JSObject>, String> hash; + CryptoAlgorithmIdentifier hashIdentifier; + + Class parametersClass() const final { return Class::EcdsaParams; } + + CryptoAlgorithmEcdsaParams isolatedCopy() const + { + CryptoAlgorithmEcdsaParams result; + result.identifier = identifier; + result.hashIdentifier = hashIdentifier; + + return result; + } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(EcdsaParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDF.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDF.cpp new file mode 100644 index 000000000..5c7a2f4c5 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDF.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 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 "CryptoAlgorithmHKDF.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmHkdfParams.h" +#include "CryptoKeyRaw.h" +#include <JavaScriptCore/JSCJSValueInlines.h> +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmHKDF::create() +{ + return adoptRef(*new CryptoAlgorithmHKDF); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmHKDF::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmHKDF::deriveBits(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& baseKey, size_t length, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (!length || length % 8) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmHkdfParams>(parameters)), baseKey = WTFMove(baseKey), length] { + return platformDeriveBits(parameters, downcast<CryptoKeyRaw>(baseKey.get()), length); + }); +} + +void CryptoAlgorithmHKDF::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + if (format != CryptoKeyFormat::Raw) { + exceptionCallback(NotSupportedError); + return; + } + if (usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + if (extractable) { + exceptionCallback(SyntaxError); + return; + } + + callback(CryptoKeyRaw::create(parameters.identifier, WTFMove(std::get<Vector<uint8_t>>(data)), usages)); +} + +ExceptionOr<size_t> CryptoAlgorithmHKDF::getKeyLength(const CryptoAlgorithmParameters&) +{ + return 0; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDF.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDF.h new file mode 100644 index 000000000..8f3939b19 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDF.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmHkdfParams; +class CryptoKeyRaw; + +class CryptoAlgorithmHKDF final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "HKDF"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::HKDF; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmHKDF() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; + + static ExceptionOr<Vector<uint8_t>> platformDeriveBits(const CryptoAlgorithmHkdfParams&, const CryptoKeyRaw&, size_t); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDFOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDFOpenSSL.cpp new file mode 100644 index 000000000..e3c113f33 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHKDFOpenSSL.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmHKDF.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmHkdfParams.h" +#include "CryptoKeyRaw.h" +#include "OpenSSLUtilities.h" +#include <openssl/hkdf.h> + +namespace WebCore { + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmHKDF::platformDeriveBits(const CryptoAlgorithmHkdfParams& parameters, const CryptoKeyRaw& key, size_t length) +{ + auto algorithm = digestAlgorithm(parameters.hashIdentifier); + if (!algorithm) + return Exception { NotSupportedError }; + + Vector<uint8_t> output(length / 8); + if (HKDF(output.data(), output.size(), algorithm, key.key().data(), key.key().size(), parameters.saltVector().data(), parameters.saltVector().size(), parameters.infoVector().data(), parameters.infoVector().size()) <= 0) + return Exception { OperationError }; + + return output; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMAC.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMAC.cpp new file mode 100644 index 000000000..58eaf1b0d --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMAC.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmHMAC.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmHmacKeyParams.h" +#include "CryptoKeyHMAC.h" +#include <variant> + +namespace WebCore { + +namespace CryptoAlgorithmHMACInternal { +static constexpr auto ALG1 = "HS1"_s; +static constexpr auto ALG224 = "HS224"_s; +static constexpr auto ALG256 = "HS256"_s; +static constexpr auto ALG384 = "HS384"_s; +static constexpr auto ALG512 = "HS512"_s; +} + +static inline bool usagesAreInvalidForCryptoAlgorithmHMAC(CryptoKeyUsageBitmap usages) +{ + return usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey); +} + +Ref<CryptoAlgorithm> CryptoAlgorithmHMAC::create() +{ + return adoptRef(*new CryptoAlgorithmHMAC); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmHMAC::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmHMAC::sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [key = WTFMove(key), data = WTFMove(data)] { + return platformSign(downcast<CryptoKeyHMAC>(key.get()), data); + }); +} + +void CryptoAlgorithmHMAC::verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [key = WTFMove(key), signature = WTFMove(signature), data = WTFMove(data)] { + return platformVerify(downcast<CryptoKeyHMAC>(key.get()), signature, data); + }); +} + +void CryptoAlgorithmHMAC::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& hmacParameters = downcast<CryptoAlgorithmHmacKeyParams>(parameters); + + if (usagesAreInvalidForCryptoAlgorithmHMAC(usages)) { + exceptionCallback(SyntaxError); + return; + } + + if (hmacParameters.length && !hmacParameters.length.value()) { + exceptionCallback(OperationError); + return; + } + + auto result = CryptoKeyHMAC::generate(hmacParameters.length.value_or(0), hmacParameters.hashIdentifier, extractable, usages); + if (!result) { + exceptionCallback(OperationError); + return; + } + + callback(WTFMove(result)); +} + +void CryptoAlgorithmHMAC::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmHMACInternal; + + const auto& hmacParameters = downcast<CryptoAlgorithmHmacKeyParams>(parameters); + + if (usagesAreInvalidForCryptoAlgorithmHMAC(usages)) { + exceptionCallback(SyntaxError); + return; + } + + RefPtr<CryptoKeyHMAC> result; + switch (format) { + case CryptoKeyFormat::Raw: + result = CryptoKeyHMAC::importRaw(hmacParameters.length.value_or(0), hmacParameters.hashIdentifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Jwk: { + auto checkAlgCallback = [](CryptoAlgorithmIdentifier hash, const String& alg) -> bool { + switch (hash) { + case CryptoAlgorithmIdentifier::SHA_1: + return alg.isNull() || alg == ALG1; + case CryptoAlgorithmIdentifier::SHA_224: + return alg.isNull() || alg == ALG224; + case CryptoAlgorithmIdentifier::SHA_256: + return alg.isNull() || alg == ALG256; + case CryptoAlgorithmIdentifier::SHA_384: + return alg.isNull() || alg == ALG384; + case CryptoAlgorithmIdentifier::SHA_512: + return alg.isNull() || alg == ALG512; + default: + return false; + } + return false; + }; + result = CryptoKeyHMAC::importJwk(hmacParameters.length.value_or(0), hmacParameters.hashIdentifier, WTFMove(std::get<JsonWebKey>(data)), extractable, usages, WTFMove(checkAlgCallback)); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmHMAC::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmHMACInternal; + const auto& hmacKey = downcast<CryptoKeyHMAC>(key.get()); + + if (hmacKey.key().isEmpty()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Raw: + result = Vector<uint8_t>(hmacKey.key()); + break; + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = hmacKey.exportJwk(); + switch (hmacKey.hashAlgorithmIdentifier()) { + case CryptoAlgorithmIdentifier::SHA_1: + jwk.alg = String(ALG1); + break; + case CryptoAlgorithmIdentifier::SHA_224: + jwk.alg = String(ALG224); + break; + case CryptoAlgorithmIdentifier::SHA_256: + jwk.alg = String(ALG256); + break; + case CryptoAlgorithmIdentifier::SHA_384: + jwk.alg = String(ALG384); + break; + case CryptoAlgorithmIdentifier::SHA_512: + jwk.alg = String(ALG512); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +ExceptionOr<size_t> CryptoAlgorithmHMAC::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + return CryptoKeyHMAC::getKeyLength(parameters); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMAC.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMAC.h new file mode 100644 index 000000000..9f1084698 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMAC.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKeyHMAC; + +class CryptoAlgorithmHMAC final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "HMAC"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::HMAC; + static Ref<CryptoAlgorithm> create(); + + // Operations can be performed directly. + static ExceptionOr<Vector<uint8_t>> platformSign(const CryptoKeyHMAC&, const Vector<uint8_t>&); + static ExceptionOr<bool> platformVerify(const CryptoKeyHMAC&, const Vector<uint8_t>&, const Vector<uint8_t>&); + +private: + CryptoAlgorithmHMAC() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&& signature, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMACOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMACOpenSSL.cpp new file mode 100644 index 000000000..ad35cafe5 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHMACOpenSSL.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmHMAC.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyHMAC.h" +#include "OpenSSLCryptoUniquePtr.h" +#include "OpenSSLUtilities.h" +#include <openssl/evp.h> +#include <wtf/CryptographicUtilities.h> + +namespace WebCore { + +static std::optional<Vector<uint8_t>> calculateSignature(const EVP_MD* algorithm, const Vector<uint8_t>& key, const uint8_t* data, size_t dataLength) +{ + HMACCtxPtr ctx; + if (!(ctx = HMACCtxPtr(HMAC_CTX_new()))) + return std::nullopt; + + if (1 != HMAC_Init_ex(ctx.get(), key.data(), key.size(), algorithm, nullptr)) + return std::nullopt; + + // Call update with the message + if (1 != HMAC_Update(ctx.get(), data, dataLength)) + return std::nullopt; + + // Finalize the DigestSign operation + Vector<uint8_t> cipherText(EVP_MAX_MD_SIZE); + unsigned len = 0; + if (1 != HMAC_Final(ctx.get(), cipherText.data(), &len)) + return std::nullopt; + + cipherText.shrink(len); + return cipherText; +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmHMAC::platformSign(const CryptoKeyHMAC& key, const Vector<uint8_t>& data) +{ + auto algorithm = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!algorithm) + return Exception { OperationError }; + + auto result = calculateSignature(algorithm, key.key(), data.data(), data.size()); + if (!result) + return Exception { OperationError }; + return WTFMove(*result); +} + +ExceptionOr<bool> CryptoAlgorithmHMAC::platformVerify(const CryptoKeyHMAC& key, const Vector<uint8_t>& signature, const Vector<uint8_t>& data) +{ + auto algorithm = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!algorithm) + return Exception { OperationError }; + + auto expectedSignature = calculateSignature(algorithm, key.key(), data.data(), data.size()); + if (!expectedSignature) + return Exception { OperationError }; + // Using a constant time comparison to prevent timing attacks. + return signature.size() == expectedSignature->size() && !constantTimeMemcmp(expectedSignature->data(), signature.data(), expectedSignature->size()); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHkdfParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHkdfParams.h new file mode 100644 index 000000000..961886391 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHkdfParams.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "BufferSource.h" +#include "CryptoAlgorithmParameters.h" +#include <JavaScriptCore/JSObject.h> +#include <JavaScriptCore/Strong.h> +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmHkdfParams final : public CryptoAlgorithmParameters { +public: + // FIXME: Consider merging hash and hashIdentifier. + std::variant<JSC::Strong<JSC::JSObject>, String> hash; + CryptoAlgorithmIdentifier hashIdentifier; + BufferSource salt; + BufferSource info; + + const Vector<uint8_t>& saltVector() const + { + if (!m_saltVector.isEmpty() || !salt.length()) + return m_saltVector; + + m_saltVector.append(salt.data(), salt.length()); + return m_saltVector; + } + + const Vector<uint8_t>& infoVector() const + { + if (!m_infoVector.isEmpty() || !info.length()) + return m_infoVector; + + m_infoVector.append(info.data(), info.length()); + return m_infoVector; + } + + Class parametersClass() const final { return Class::HkdfParams; } + + CryptoAlgorithmHkdfParams isolatedCopy() const + { + CryptoAlgorithmHkdfParams result; + result.identifier = identifier; + result.m_saltVector = saltVector(); + result.m_infoVector = infoVector(); + result.hashIdentifier = hashIdentifier; + + return result; + } + +private: + mutable Vector<uint8_t> m_saltVector; + mutable Vector<uint8_t> m_infoVector; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(HkdfParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmHmacKeyParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHmacKeyParams.h new file mode 100644 index 000000000..c9b09f90c --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmHmacKeyParams.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmParameters.h" +#include <JavaScriptCore/JSObject.h> +#include <JavaScriptCore/Strong.h> +#include <variant> + +namespace WebCore { + +class CryptoAlgorithmHmacKeyParams final : public CryptoAlgorithmParameters { +public: + // FIXME: Consider merging hash and hashIdentifier. + std::variant<JSC::Strong<JSC::JSObject>, String> hash; + CryptoAlgorithmIdentifier hashIdentifier; + std::optional<size_t> length; + + Class parametersClass() const final { return Class::HmacKeyParams; } + + CryptoAlgorithmHmacKeyParams isolatedCopy() const + { + CryptoAlgorithmHmacKeyParams result; + result.identifier = identifier; + result.hashIdentifier = hashIdentifier; + result.length = length; + + return result; + } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(HmacKeyParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmIdentifier.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmIdentifier.h new file mode 100644 index 000000000..657a7aadb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmIdentifier.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +enum class CryptoAlgorithmIdentifier { + RSAES_PKCS1_v1_5 = 1, + RSASSA_PKCS1_v1_5, + RSA_PSS, + RSA_OAEP, + ECDSA, + ECDH, + AES_CTR, + AES_CBC, + AES_GCM, + AES_CFB, + AES_KW, + HMAC, + SHA_1, + SHA_224, + SHA_256, + SHA_384, + SHA_512, + HKDF, + PBKDF2 +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2.cpp new file mode 100644 index 000000000..268c051d9 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 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 "CryptoAlgorithmPBKDF2.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmPbkdf2Params.h" +#include "CryptoKeyRaw.h" +#include <JavaScriptCore/JSCJSValueInlines.h> +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmPBKDF2::create() +{ + return adoptRef(*new CryptoAlgorithmPBKDF2); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmPBKDF2::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmPBKDF2::deriveBits(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& baseKey, size_t length, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (!length || length % 8) { + exceptionCallback(OperationError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmPbkdf2Params>(parameters)), baseKey = WTFMove(baseKey), length] { + return platformDeriveBits(parameters, downcast<CryptoKeyRaw>(baseKey.get()), length); + }); +} + +void CryptoAlgorithmPBKDF2::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + if (format != CryptoKeyFormat::Raw) { + exceptionCallback(NotSupportedError); + return; + } + if (usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + if (extractable) { + exceptionCallback(SyntaxError); + return; + } + + callback(CryptoKeyRaw::create(parameters.identifier, WTFMove(std::get<Vector<uint8_t>>(data)), usages)); +} + +ExceptionOr<size_t> CryptoAlgorithmPBKDF2::getKeyLength(const CryptoAlgorithmParameters&) +{ + return 0; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2.h new file mode 100644 index 000000000..34069e51f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmPbkdf2Params; +class CryptoKeyRaw; + +class CryptoAlgorithmPBKDF2 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "PBKDF2"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::PBKDF2; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmPBKDF2() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final; + + static ExceptionOr<Vector<uint8_t>> platformDeriveBits(const CryptoAlgorithmPbkdf2Params&, const CryptoKeyRaw&, size_t); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2OpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2OpenSSL.cpp new file mode 100644 index 000000000..124d7e2d1 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPBKDF2OpenSSL.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmPBKDF2.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmPbkdf2Params.h" +#include "CryptoKeyRaw.h" +#include "OpenSSLUtilities.h" +#include <openssl/evp.h> + +namespace WebCore { + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmPBKDF2::platformDeriveBits(const CryptoAlgorithmPbkdf2Params& parameters, const CryptoKeyRaw& key, size_t length) +{ + auto algorithm = digestAlgorithm(parameters.hashIdentifier); + if (!algorithm) + return Exception { NotSupportedError }; + + // iterations must not be zero. + if (!parameters.iterations) + return Exception { OperationError }; + + Vector<uint8_t> output(length / 8); + if (PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(key.key().data()), key.key().size(), parameters.saltVector().data(), parameters.saltVector().size(), parameters.iterations, algorithm, output.size(), output.data()) <= 0) + return Exception { OperationError }; + + return output; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.h new file mode 100644 index 000000000..8398404b8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#pragma once + +#include "CryptoAlgorithmIdentifier.h" +#include <wtf/TypeCasts.h> +#include <wtf/text/WTFString.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmParameters { + WTF_MAKE_FAST_ALLOCATED; +public: + enum class Class { + None, + AesCbcCfbParams, + AesCtrParams, + AesGcmParams, + AesKeyParams, + EcKeyParams, + EcdhKeyDeriveParams, + EcdsaParams, + HkdfParams, + HmacKeyParams, + Pbkdf2Params, + RsaHashedKeyGenParams, + RsaHashedImportParams, + RsaKeyGenParams, + RsaOaepParams, + RsaPssParams, + }; + + // FIXME: Consider merging name and identifier. + String name; + CryptoAlgorithmIdentifier identifier; + + virtual ~CryptoAlgorithmParameters() = default; + + virtual Class parametersClass() const { return Class::None; } +}; + +} // namespace WebCore + +#define SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(ToClassName) \ +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::CryptoAlgorithm##ToClassName) \ +static bool isType(const WebCore::CryptoAlgorithmParameters& parameters) { return parameters.parametersClass() == WebCore::CryptoAlgorithmParameters::Class::ToClassName; } \ +SPECIALIZE_TYPE_TRAITS_END() + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.idl b/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.idl new file mode 100644 index 000000000..5d6aa9604 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.idl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +[ + Conditional=WEB_CRYPTO, +] dictionary CryptoAlgorithmParameters { + required DOMString name; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmPbkdf2Params.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPbkdf2Params.h new file mode 100644 index 000000000..2aff182c4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmPbkdf2Params.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "BufferSource.h" +#include "CryptoAlgorithmParameters.h" +#include <JavaScriptCore/JSObject.h> +#include <JavaScriptCore/Strong.h> +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmPbkdf2Params final : public CryptoAlgorithmParameters { +public: + BufferSource salt; + unsigned long iterations; + // FIXME: Consider merging hash and hashIdentifier. + std::variant<JSC::Strong<JSC::JSObject>, String> hash; + CryptoAlgorithmIdentifier hashIdentifier; + + const Vector<uint8_t>& saltVector() const + { + if (!m_saltVector.isEmpty() || !salt.length()) + return m_saltVector; + + m_saltVector.append(salt.data(), salt.length()); + return m_saltVector; + } + + Class parametersClass() const final { return Class::Pbkdf2Params; } + + CryptoAlgorithmPbkdf2Params isolatedCopy() const + { + CryptoAlgorithmPbkdf2Params result; + result.identifier = identifier; + result.m_saltVector = saltVector(); + result.iterations = iterations; + result.hashIdentifier = hashIdentifier; + + return result; + } + +private: + mutable Vector<uint8_t> m_saltVector; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(Pbkdf2Params) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5.cpp new file mode 100644 index 000000000..9eace1362 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmRSAES_PKCS1_v1_5.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaKeyGenParams.h" +#include "CryptoKeyPair.h" +#include "CryptoKeyRSA.h" +#include <variant> + +namespace WebCore { + +static constexpr auto ALG = "RSA1_5"_s; + +Ref<CryptoAlgorithm> CryptoAlgorithmRSAES_PKCS1_v1_5::create() +{ + return adoptRef(*new CryptoAlgorithmRSAES_PKCS1_v1_5); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmRSAES_PKCS1_v1_5::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmRSAES_PKCS1_v1_5::encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& plainText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Public) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [key = WTFMove(key), plainText = WTFMove(plainText)] { + return platformEncrypt(downcast<CryptoKeyRSA>(key.get()), plainText); + }); +} + +void CryptoAlgorithmRSAES_PKCS1_v1_5::decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Private) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [key = WTFMove(key), cipherText = WTFMove(cipherText)] { + return platformDecrypt(downcast<CryptoKeyRSA>(key.get()), cipherText); + }); +} + +void CryptoAlgorithmRSAES_PKCS1_v1_5::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context) +{ + const auto& rsaParameters = downcast<CryptoAlgorithmRsaKeyGenParams>(parameters); + + if (usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + + auto keyPairCallback = [capturedCallback = WTFMove(callback)](CryptoKeyPair&& pair) { + pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & CryptoKeyUsageEncrypt); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & CryptoKeyUsageDecrypt); + capturedCallback(WTFMove(pair)); + }; + auto failureCallback = [capturedCallback = WTFMove(exceptionCallback)]() { + capturedCallback(OperationError); + }; + // Notice: CryptoAlgorithmIdentifier::SHA_1 is just a placeholder. It should not have any effect. + CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5, CryptoAlgorithmIdentifier::SHA_1, false, rsaParameters.modulusLength, rsaParameters.publicExponentVector(), extractable, usages, WTFMove(keyPairCallback), WTFMove(failureCallback), &context); +} + +void CryptoAlgorithmRSAES_PKCS1_v1_5::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + RefPtr<CryptoKeyRSA> result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey key = WTFMove(std::get<JsonWebKey>(data)); + if (usages && ((!key.d.isNull() && (usages ^ CryptoKeyUsageDecrypt)) || (key.d.isNull() && (usages ^ CryptoKeyUsageEncrypt)))) { + exceptionCallback(SyntaxError); + return; + } + if (usages && !key.use.isNull() && key.use != "enc"_s) { + exceptionCallback(DataError); + return; + } + if (!key.alg.isNull() && key.alg != ALG) { + exceptionCallback(DataError); + return; + } + result = CryptoKeyRSA::importJwk(parameters.identifier, std::nullopt, WTFMove(key), extractable, usages); + break; + } + case CryptoKeyFormat::Spki: { + if (usages && (usages ^ CryptoKeyUsageEncrypt)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyRSA::importSpki(parameters.identifier, std::nullopt, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + case CryptoKeyFormat::Pkcs8: { + if (usages && (usages ^ CryptoKeyUsageDecrypt)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyRSA::importPkcs8(parameters.identifier, std::nullopt, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmRSAES_PKCS1_v1_5::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + const auto& rsaKey = downcast<CryptoKeyRSA>(key.get()); + + if (!rsaKey.keySizeInBits()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = rsaKey.exportJwk(); + jwk.alg = String(ALG); + result = WTFMove(jwk); + break; + } + case CryptoKeyFormat::Spki: { + auto spki = rsaKey.exportSpki(); + if (spki.hasException()) { + exceptionCallback(spki.releaseException().code()); + return; + } + result = spki.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Pkcs8: { + auto pkcs8 = rsaKey.exportPkcs8(); + if (pkcs8.hasException()) { + exceptionCallback(pkcs8.releaseException().code()); + return; + } + result = pkcs8.releaseReturnValue(); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5.h new file mode 100644 index 000000000..d21e6c1ee --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKeyRSA; + +class CryptoAlgorithmRSAES_PKCS1_v1_5 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "RSAES-PKCS1-v1_5"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmRSAES_PKCS1_v1_5() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + + static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoKeyRSA&, const Vector<uint8_t>&); + static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoKeyRSA&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5OpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5OpenSSL.cpp new file mode 100644 index 000000000..63b5b9551 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSAES_PKCS1_v1_5OpenSSL.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmRSAES_PKCS1_v1_5.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyRSA.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmRSAES_PKCS1_v1_5::platformEncrypt(const CryptoKeyRSA& key, const Vector<uint8_t>& plainText) +{ + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_encrypt_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) <= 0) + return Exception { OperationError }; + + size_t cipherTextLen; + if (EVP_PKEY_encrypt(ctx.get(), nullptr, &cipherTextLen, plainText.data(), plainText.size()) <= 0) + return Exception { OperationError }; + + Vector<uint8_t> cipherText(cipherTextLen); + if (EVP_PKEY_encrypt(ctx.get(), cipherText.data(), &cipherTextLen, plainText.data(), plainText.size()) <= 0) + return Exception { OperationError }; + cipherText.shrink(cipherTextLen); + + return cipherText; +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmRSAES_PKCS1_v1_5::platformDecrypt(const CryptoKeyRSA& key, const Vector<uint8_t>& cipherText) +{ + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) <= 0) + return Exception { OperationError }; + + size_t plainTextLen; + if (EVP_PKEY_decrypt(ctx.get(), nullptr, &plainTextLen, cipherText.data(), cipherText.size()) <= 0) + return Exception { OperationError }; + + Vector<uint8_t> plainText(plainTextLen); + if (EVP_PKEY_decrypt(ctx.get(), plainText.data(), &plainTextLen, cipherText.data(), cipherText.size()) <= 0) + return Exception { OperationError }; + plainText.shrink(plainTextLen); + + return plainText; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5.cpp new file mode 100644 index 000000000..156e641f2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmRSASSA_PKCS1_v1_5.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaHashedImportParams.h" +#include "CryptoAlgorithmRsaHashedKeyGenParams.h" +#include "CryptoKeyPair.h" +#include "CryptoKeyRSA.h" +#include <variant> + +namespace WebCore { + +namespace CryptoAlgorithmRSASSA_PKCS1_v1_5Internal { +static constexpr auto ALG1 = "RS1"_s; +static constexpr auto ALG224 = "RS224"_s; +static constexpr auto ALG256 = "RS256"_s; +static constexpr auto ALG384 = "RS384"_s; +static constexpr auto ALG512 = "RS512"_s; +} + +Ref<CryptoAlgorithm> CryptoAlgorithmRSASSA_PKCS1_v1_5::create() +{ + return adoptRef(*new CryptoAlgorithmRSASSA_PKCS1_v1_5); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmRSASSA_PKCS1_v1_5::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmRSASSA_PKCS1_v1_5::sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Private) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [key = WTFMove(key), data = WTFMove(data)] { + return platformSign(downcast<CryptoKeyRSA>(key.get()), data); + }); +} + +void CryptoAlgorithmRSASSA_PKCS1_v1_5::verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Public) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [key = WTFMove(key), signature = WTFMove(signature), data = WTFMove(data)] { + return platformVerify(downcast<CryptoKeyRSA>(key.get()), signature, data); + }); +} + +void CryptoAlgorithmRSASSA_PKCS1_v1_5::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context) +{ + const auto& rsaParameters = downcast<CryptoAlgorithmRsaHashedKeyGenParams>(parameters); + + if (usages & (CryptoKeyUsageDecrypt | CryptoKeyUsageEncrypt | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + + auto keyPairCallback = [capturedCallback = WTFMove(callback)](CryptoKeyPair&& pair) { + pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & CryptoKeyUsageVerify); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & CryptoKeyUsageSign); + capturedCallback(WTFMove(pair)); + }; + auto failureCallback = [capturedCallback = WTFMove(exceptionCallback)]() { + capturedCallback(OperationError); + }; + CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5, rsaParameters.hashIdentifier, true, rsaParameters.modulusLength, rsaParameters.publicExponentVector(), extractable, usages, WTFMove(keyPairCallback), WTFMove(failureCallback), &context); +} + +void CryptoAlgorithmRSASSA_PKCS1_v1_5::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmRSASSA_PKCS1_v1_5Internal; + + const auto& rsaParameters = downcast<CryptoAlgorithmRsaHashedImportParams>(parameters); + + RefPtr<CryptoKeyRSA> result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey key = WTFMove(std::get<JsonWebKey>(data)); + + if (usages && ((!key.d.isNull() && (usages ^ CryptoKeyUsageSign)) || (key.d.isNull() && (usages ^ CryptoKeyUsageVerify)))) { + exceptionCallback(SyntaxError); + return; + } + if (usages && !key.use.isNull() && key.use != "sig"_s) { + exceptionCallback(DataError); + return; + } + + bool isMatched = false; + switch (rsaParameters.hashIdentifier) { + case CryptoAlgorithmIdentifier::SHA_1: + isMatched = key.alg.isNull() || key.alg == ALG1; + break; + case CryptoAlgorithmIdentifier::SHA_224: + isMatched = key.alg.isNull() || key.alg == ALG224; + break; + case CryptoAlgorithmIdentifier::SHA_256: + isMatched = key.alg.isNull() || key.alg == ALG256; + break; + case CryptoAlgorithmIdentifier::SHA_384: + isMatched = key.alg.isNull() || key.alg == ALG384; + break; + case CryptoAlgorithmIdentifier::SHA_512: + isMatched = key.alg.isNull() || key.alg == ALG512; + break; + default: + break; + } + if (!isMatched) { + exceptionCallback(DataError); + return; + } + + result = CryptoKeyRSA::importJwk(rsaParameters.identifier, rsaParameters.hashIdentifier, WTFMove(key), extractable, usages); + break; + } + case CryptoKeyFormat::Spki: { + if (usages && (usages ^ CryptoKeyUsageVerify)) { + exceptionCallback(SyntaxError); + return; + } + // FIXME: <webkit.org/b/165436> + result = CryptoKeyRSA::importSpki(rsaParameters.identifier, rsaParameters.hashIdentifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + case CryptoKeyFormat::Pkcs8: { + if (usages && (usages ^ CryptoKeyUsageSign)) { + exceptionCallback(SyntaxError); + return; + } + // FIXME: <webkit.org/b/165436> + result = CryptoKeyRSA::importPkcs8(parameters.identifier, rsaParameters.hashIdentifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmRSASSA_PKCS1_v1_5::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmRSASSA_PKCS1_v1_5Internal; + const auto& rsaKey = downcast<CryptoKeyRSA>(key.get()); + + if (!rsaKey.keySizeInBits()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = rsaKey.exportJwk(); + switch (rsaKey.hashAlgorithmIdentifier()) { + case CryptoAlgorithmIdentifier::SHA_1: + jwk.alg = String(ALG1); + break; + case CryptoAlgorithmIdentifier::SHA_224: + jwk.alg = String(ALG224); + break; + case CryptoAlgorithmIdentifier::SHA_256: + jwk.alg = String(ALG256); + break; + case CryptoAlgorithmIdentifier::SHA_384: + jwk.alg = String(ALG384); + break; + case CryptoAlgorithmIdentifier::SHA_512: + jwk.alg = String(ALG512); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + case CryptoKeyFormat::Spki: { + auto spki = rsaKey.exportSpki(); + if (spki.hasException()) { + exceptionCallback(spki.releaseException().code()); + return; + } + result = spki.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Pkcs8: { + auto pkcs8 = rsaKey.exportPkcs8(); + if (pkcs8.hasException()) { + exceptionCallback(pkcs8.releaseException().code()); + return; + } + result = pkcs8.releaseReturnValue(); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5.h new file mode 100644 index 000000000..d185d3a4b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKeyRSA; + +class CryptoAlgorithmRSASSA_PKCS1_v1_5 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "RSASSA-PKCS1-v1_5"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmRSASSA_PKCS1_v1_5() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&& signature, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + + static ExceptionOr<Vector<uint8_t>> platformSign(const CryptoKeyRSA&, const Vector<uint8_t>&); + static ExceptionOr<bool> platformVerify(const CryptoKeyRSA&, const Vector<uint8_t>&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5OpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5OpenSSL.cpp new file mode 100644 index 000000000..acfeee790 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSASSA_PKCS1_v1_5OpenSSL.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2021 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmRSASSA_PKCS1_v1_5.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyRSA.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmRSASSA_PKCS1_v1_5::platformSign(const CryptoKeyRSA& key, const Vector<uint8_t>& data) +{ + const EVP_MD* md = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!md) + return Exception { NotSupportedError }; + + std::optional<Vector<uint8_t>> digest = calculateDigest(md, data); + if (!digest) + return Exception { OperationError }; + + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_sign_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_signature_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + size_t signatureLen; + if (EVP_PKEY_sign(ctx.get(), nullptr, &signatureLen, digest->data(), digest->size()) <= 0) + return Exception { OperationError }; + + Vector<uint8_t> signature(signatureLen); + if (EVP_PKEY_sign(ctx.get(), signature.data(), &signatureLen, digest->data(), digest->size()) <= 0) + return Exception { OperationError }; + signature.shrink(signatureLen); + + return signature; +} + +ExceptionOr<bool> CryptoAlgorithmRSASSA_PKCS1_v1_5::platformVerify(const CryptoKeyRSA& key, const Vector<uint8_t>& signature, const Vector<uint8_t>& data) +{ + const EVP_MD* md = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!md) + return Exception { NotSupportedError }; + + std::optional<Vector<uint8_t>> digest = calculateDigest(md, data); + if (!digest) + return Exception { OperationError }; + + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_verify_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_signature_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + int ret = EVP_PKEY_verify(ctx.get(), signature.data(), signature.size(), digest->data(), digest->size()); + + return ret == 1; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEP.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEP.cpp new file mode 100644 index 000000000..259778276 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEP.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmRSA_OAEP.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaHashedImportParams.h" +#include "CryptoAlgorithmRsaHashedKeyGenParams.h" +#include "CryptoAlgorithmRsaOaepParams.h" +#include "CryptoKeyPair.h" +#include "CryptoKeyRSA.h" +#include <variant> +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +namespace CryptoAlgorithmRSA_OAEPInternal { +static constexpr auto ALG1 = "RSA-OAEP"_s; +static constexpr auto ALG224 = "RSA-OAEP-224"_s; +static constexpr auto ALG256 = "RSA-OAEP-256"_s; +static constexpr auto ALG384 = "RSA-OAEP-384"_s; +static constexpr auto ALG512 = "RSA-OAEP-512"_s; +} + +Ref<CryptoAlgorithm> CryptoAlgorithmRSA_OAEP::create() +{ + return adoptRef(*new CryptoAlgorithmRSA_OAEP); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmRSA_OAEP::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmRSA_OAEP::encrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& plainText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Public) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmRsaOaepParams>(parameters)), key = WTFMove(key), plainText = WTFMove(plainText)] { + return platformEncrypt(parameters, downcast<CryptoKeyRSA>(key.get()), plainText); + }); +} + +void CryptoAlgorithmRSA_OAEP::decrypt(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Private) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmRsaOaepParams>(parameters)), key = WTFMove(key), cipherText = WTFMove(cipherText)] { + return platformDecrypt(parameters, downcast<CryptoKeyRSA>(key.get()), cipherText); + }); +} + +void CryptoAlgorithmRSA_OAEP::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context) +{ + const auto& rsaParameters = downcast<CryptoAlgorithmRsaHashedKeyGenParams>(parameters); + + if (usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits)) { + exceptionCallback(SyntaxError); + return; + } + + auto keyPairCallback = [capturedCallback = WTFMove(callback)](CryptoKeyPair&& pair) { + pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & (CryptoKeyUsageEncrypt | CryptoKeyUsageWrapKey)); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & (CryptoKeyUsageDecrypt | CryptoKeyUsageUnwrapKey)); + capturedCallback(WTFMove(pair)); + }; + auto failureCallback = [capturedCallback = WTFMove(exceptionCallback)]() { + capturedCallback(OperationError); + }; + CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier::RSA_OAEP, rsaParameters.hashIdentifier, true, rsaParameters.modulusLength, rsaParameters.publicExponentVector(), extractable, usages, WTFMove(keyPairCallback), WTFMove(failureCallback), &context); +} + +void CryptoAlgorithmRSA_OAEP::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmRSA_OAEPInternal; + + const auto& rsaParameters = downcast<CryptoAlgorithmRsaHashedImportParams>(parameters); + + RefPtr<CryptoKeyRSA> result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey key = WTFMove(std::get<JsonWebKey>(data)); + + bool isUsagesAllowed = false; + if (!key.d.isNull()) { + isUsagesAllowed = isUsagesAllowed || !(usages ^ CryptoKeyUsageDecrypt); + isUsagesAllowed = isUsagesAllowed || !(usages ^ CryptoKeyUsageUnwrapKey); + isUsagesAllowed = isUsagesAllowed || !(usages ^ (CryptoKeyUsageDecrypt | CryptoKeyUsageUnwrapKey)); + } else { + isUsagesAllowed = isUsagesAllowed || !(usages ^ CryptoKeyUsageEncrypt); + isUsagesAllowed = isUsagesAllowed || !(usages ^ CryptoKeyUsageWrapKey); + isUsagesAllowed = isUsagesAllowed || !(usages ^ (CryptoKeyUsageEncrypt | CryptoKeyUsageWrapKey)); + } + isUsagesAllowed = isUsagesAllowed || !usages; + if (!isUsagesAllowed) { + exceptionCallback(SyntaxError); + return; + } + + if (usages && !key.use.isNull() && key.use != "enc"_s) { + exceptionCallback(DataError); + return; + } + + bool isMatched = false; + switch (rsaParameters.hashIdentifier) { + case CryptoAlgorithmIdentifier::SHA_1: + isMatched = key.alg.isNull() || key.alg == ALG1; + break; + case CryptoAlgorithmIdentifier::SHA_224: + isMatched = key.alg.isNull() || key.alg == ALG224; + break; + case CryptoAlgorithmIdentifier::SHA_256: + isMatched = key.alg.isNull() || key.alg == ALG256; + break; + case CryptoAlgorithmIdentifier::SHA_384: + isMatched = key.alg.isNull() || key.alg == ALG384; + break; + case CryptoAlgorithmIdentifier::SHA_512: + isMatched = key.alg.isNull() || key.alg == ALG512; + break; + default: + break; + } + if (!isMatched) { + exceptionCallback(DataError); + return; + } + + result = CryptoKeyRSA::importJwk(rsaParameters.identifier, rsaParameters.hashIdentifier, WTFMove(key), extractable, usages); + break; + } + case CryptoKeyFormat::Spki: { + if (usages && (usages ^ CryptoKeyUsageEncrypt) && (usages ^ CryptoKeyUsageWrapKey) && (usages ^ (CryptoKeyUsageEncrypt | CryptoKeyUsageWrapKey))) { + exceptionCallback(SyntaxError); + return; + } + // FIXME: <webkit.org/b/165436> + result = CryptoKeyRSA::importSpki(rsaParameters.identifier, rsaParameters.hashIdentifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + case CryptoKeyFormat::Pkcs8: { + if (usages && (usages ^ CryptoKeyUsageDecrypt) && (usages ^ CryptoKeyUsageUnwrapKey) && (usages ^ (CryptoKeyUsageDecrypt | CryptoKeyUsageUnwrapKey))) { + exceptionCallback(SyntaxError); + return; + } + // FIXME: <webkit.org/b/165436> + result = CryptoKeyRSA::importPkcs8(parameters.identifier, rsaParameters.hashIdentifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmRSA_OAEP::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmRSA_OAEPInternal; + const auto& rsaKey = downcast<CryptoKeyRSA>(key.get()); + + if (!rsaKey.keySizeInBits()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = rsaKey.exportJwk(); + switch (rsaKey.hashAlgorithmIdentifier()) { + case CryptoAlgorithmIdentifier::SHA_1: + jwk.alg = String(ALG1); + break; + case CryptoAlgorithmIdentifier::SHA_224: + jwk.alg = String(ALG224); + break; + case CryptoAlgorithmIdentifier::SHA_256: + jwk.alg = String(ALG256); + break; + case CryptoAlgorithmIdentifier::SHA_384: + jwk.alg = String(ALG384); + break; + case CryptoAlgorithmIdentifier::SHA_512: + jwk.alg = String(ALG512); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + case CryptoKeyFormat::Spki: { + // FIXME: <webkit.org/b/165437> + auto spki = rsaKey.exportSpki(); + if (spki.hasException()) { + exceptionCallback(spki.releaseException().code()); + return; + } + result = spki.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Pkcs8: { + // FIXME: <webkit.org/b/165437> + auto pkcs8 = rsaKey.exportPkcs8(); + if (pkcs8.hasException()) { + exceptionCallback(pkcs8.releaseException().code()); + return; + } + result = pkcs8.releaseReturnValue(); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEP.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEP.h new file mode 100644 index 000000000..dba7ea9d5 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEP.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmRsaOaepParams; +class CryptoKeyRSA; + +class CryptoAlgorithmRSA_OAEP final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "RSA-OAEP"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::RSA_OAEP; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmRSA_OAEP() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void encrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void decrypt(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + + static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmRsaOaepParams&, const CryptoKeyRSA&, const Vector<uint8_t>&); + static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmRsaOaepParams&, const CryptoKeyRSA&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEPOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEPOpenSSL.cpp new file mode 100644 index 000000000..4a3dbb6b7 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_OAEPOpenSSL.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2021 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmRSA_OAEP.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaOaepParams.h" +#include "CryptoKeyRSA.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmRSA_OAEP::platformEncrypt(const CryptoAlgorithmRsaOaepParams& parameters, const CryptoKeyRSA& key, const Vector<uint8_t>& plainText) +{ +#if defined(EVP_PKEY_CTX_set_rsa_oaep_md) && defined(EVP_PKEY_CTX_set_rsa_mgf1_md) && defined(EVP_PKEY_CTX_set0_rsa_oaep_label) + const EVP_MD* md = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!md) + return Exception { NotSupportedError }; + + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_encrypt_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + if (!parameters.labelVector().isEmpty()) { + size_t labelSize = parameters.labelVector().size(); + // The library takes ownership of the label so the caller should not free the original memory pointed to by label. + auto label = OPENSSL_malloc(labelSize); + memcpy(label, parameters.labelVector().data(), labelSize); + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx.get(), label, labelSize) <= 0) { + OPENSSL_free(label); + return Exception { OperationError }; + } + } + + size_t cipherTextLen; + if (EVP_PKEY_encrypt(ctx.get(), nullptr, &cipherTextLen, plainText.data(), plainText.size()) <= 0) + return Exception { OperationError }; + + Vector<uint8_t> cipherText(cipherTextLen); + if (EVP_PKEY_encrypt(ctx.get(), cipherText.data(), &cipherTextLen, plainText.data(), plainText.size()) <= 0) + return Exception { OperationError }; + cipherText.shrink(cipherTextLen); + + return cipherText; +#else + return Exception { NotSupportedError }; +#endif +} + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmRSA_OAEP::platformDecrypt(const CryptoAlgorithmRsaOaepParams& parameters, const CryptoKeyRSA& key, const Vector<uint8_t>& cipherText) +{ +#if defined(EVP_PKEY_CTX_set_rsa_oaep_md) && defined(EVP_PKEY_CTX_set_rsa_mgf1_md) && defined(EVP_PKEY_CTX_set0_rsa_oaep_label) + const EVP_MD* md = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!md) + return Exception { NotSupportedError }; + + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + if (!parameters.labelVector().isEmpty()) { + size_t labelSize = parameters.labelVector().size(); + // The library takes ownership of the label so the caller should not free the original memory pointed to by label. + auto label = OPENSSL_malloc(labelSize); + memcpy(label, parameters.labelVector().data(), labelSize); + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx.get(), label, labelSize) <= 0) { + OPENSSL_free(label); + return Exception { OperationError }; + } + } + + size_t plainTextLen; + if (EVP_PKEY_decrypt(ctx.get(), nullptr, &plainTextLen, cipherText.data(), cipherText.size()) <= 0) + return Exception { OperationError }; + + Vector<uint8_t> plainText(plainTextLen); + if (EVP_PKEY_decrypt(ctx.get(), plainText.data(), &plainTextLen, cipherText.data(), cipherText.size()) <= 0) + return Exception { OperationError }; + plainText.shrink(plainTextLen); + + return plainText; +#else + return Exception { NotSupportedError }; +#endif +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSS.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSS.cpp new file mode 100644 index 000000000..2d3f5d931 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSS.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2017 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 "CryptoAlgorithmRSA_PSS.h" + +#if ENABLE(WEB_CRYPTO) && HAVE(RSA_PSS) + +#include "CryptoAlgorithmRsaHashedImportParams.h" +#include "CryptoAlgorithmRsaHashedKeyGenParams.h" +#include "CryptoAlgorithmRsaPssParams.h" +#include "CryptoKeyPair.h" +#include "CryptoKeyRSA.h" +#include <variant> +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +namespace CryptoAlgorithmRSA_PSSInternal { +static constexpr auto ALG1 = "PS1"_s; +static constexpr auto ALG224 = "PS224"_s; +static constexpr auto ALG256 = "PS256"_s; +static constexpr auto ALG384 = "PS384"_s; +static constexpr auto ALG512 = "PS512"_s; +} + +Ref<CryptoAlgorithm> CryptoAlgorithmRSA_PSS::create() +{ + return adoptRef(*new CryptoAlgorithmRSA_PSS); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmRSA_PSS::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmRSA_PSS::sign(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Private) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmRsaPssParams>(parameters)), key = WTFMove(key), data = WTFMove(data)] { + return platformSign(parameters, downcast<CryptoKeyRSA>(key.get()), data); + }); +} + +void CryptoAlgorithmRSA_PSS::verify(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Public) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmRsaPssParams>(parameters)), key = WTFMove(key), signature = WTFMove(signature), data = WTFMove(data)] { + return platformVerify(parameters, downcast<CryptoKeyRSA>(key.get()), signature, data); + }); +} + +void CryptoAlgorithmRSA_PSS::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context) +{ + const auto& rsaParameters = downcast<CryptoAlgorithmRsaHashedKeyGenParams>(parameters); + + if (usages & (CryptoKeyUsageDecrypt | CryptoKeyUsageEncrypt | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + + auto keyPairCallback = [capturedCallback = WTFMove(callback)](CryptoKeyPair&& pair) { + pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & CryptoKeyUsageVerify); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & CryptoKeyUsageSign); + capturedCallback(WTFMove(pair)); + }; + auto failureCallback = [capturedCallback = WTFMove(exceptionCallback)]() { + capturedCallback(OperationError); + }; + CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier::RSA_PSS, rsaParameters.hashIdentifier, true, rsaParameters.modulusLength, rsaParameters.publicExponentVector(), extractable, usages, WTFMove(keyPairCallback), WTFMove(failureCallback), &context); +} + +void CryptoAlgorithmRSA_PSS::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmRSA_PSSInternal; + + const auto& rsaParameters = downcast<CryptoAlgorithmRsaHashedImportParams>(parameters); + + RefPtr<CryptoKeyRSA> result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey key = WTFMove(std::get<JsonWebKey>(data)); + + if (usages && ((!key.d.isNull() && (usages ^ CryptoKeyUsageSign)) || (key.d.isNull() && (usages ^ CryptoKeyUsageVerify)))) { + exceptionCallback(SyntaxError); + return; + } + if (usages && !key.use.isNull() && key.use != "sig"_s) { + exceptionCallback(DataError); + return; + } + + bool isMatched = false; + switch (rsaParameters.hashIdentifier) { + case CryptoAlgorithmIdentifier::SHA_1: + isMatched = key.alg.isNull() || key.alg == ALG1; + break; + case CryptoAlgorithmIdentifier::SHA_224: + isMatched = key.alg.isNull() || key.alg == ALG224; + break; + case CryptoAlgorithmIdentifier::SHA_256: + isMatched = key.alg.isNull() || key.alg == ALG256; + break; + case CryptoAlgorithmIdentifier::SHA_384: + isMatched = key.alg.isNull() || key.alg == ALG384; + break; + case CryptoAlgorithmIdentifier::SHA_512: + isMatched = key.alg.isNull() || key.alg == ALG512; + break; + default: + break; + } + if (!isMatched) { + exceptionCallback(DataError); + return; + } + + result = CryptoKeyRSA::importJwk(rsaParameters.identifier, rsaParameters.hashIdentifier, WTFMove(key), extractable, usages); + break; + } + case CryptoKeyFormat::Spki: { + if (usages && (usages ^ CryptoKeyUsageVerify)) { + exceptionCallback(SyntaxError); + return; + } + // FIXME: <webkit.org/b/165436> + result = CryptoKeyRSA::importSpki(rsaParameters.identifier, rsaParameters.hashIdentifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + case CryptoKeyFormat::Pkcs8: { + if (usages && (usages ^ CryptoKeyUsageSign)) { + exceptionCallback(SyntaxError); + return; + } + // FIXME: <webkit.org/b/165436> + result = CryptoKeyRSA::importPkcs8(parameters.identifier, rsaParameters.hashIdentifier, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmRSA_PSS::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmRSA_PSSInternal; + const auto& rsaKey = downcast<CryptoKeyRSA>(key.get()); + + if (!rsaKey.keySizeInBits()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey jwk = rsaKey.exportJwk(); + switch (rsaKey.hashAlgorithmIdentifier()) { + case CryptoAlgorithmIdentifier::SHA_1: + jwk.alg = String(ALG1); + break; + case CryptoAlgorithmIdentifier::SHA_224: + jwk.alg = String(ALG224); + break; + case CryptoAlgorithmIdentifier::SHA_256: + jwk.alg = String(ALG256); + break; + case CryptoAlgorithmIdentifier::SHA_384: + jwk.alg = String(ALG384); + break; + case CryptoAlgorithmIdentifier::SHA_512: + jwk.alg = String(ALG512); + break; + default: + ASSERT_NOT_REACHED(); + } + result = WTFMove(jwk); + break; + } + case CryptoKeyFormat::Spki: { + auto spki = rsaKey.exportSpki(); + if (spki.hasException()) { + exceptionCallback(spki.releaseException().code()); + return; + } + result = spki.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Pkcs8: { + auto pkcs8 = rsaKey.exportPkcs8(); + if (pkcs8.hasException()) { + exceptionCallback(pkcs8.releaseException().code()); + return; + } + result = pkcs8.releaseReturnValue(); + break; + } + default: + exceptionCallback(NotSupportedError); + return; + } + + callback(format, WTFMove(result)); +} + +} + +#endif // ENABLE(WEB_CRYPTO) && HAVE(RSA_PSS) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSS.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSS.h new file mode 100644 index 000000000..b1f7f772c --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSS.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) && HAVE(RSA_PSS) + +namespace WebCore { + +class CryptoAlgorithmRsaPssParams; +class CryptoKeyRSA; + +class CryptoAlgorithmRSA_PSS final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "RSA-PSS"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::RSA_PSS; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmRSA_PSS() = default; + CryptoAlgorithmIdentifier identifier() const final; + + void sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, Vector<uint8_t>&& signature, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; + void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final; + void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final; + void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final; + + static ExceptionOr<Vector<uint8_t>> platformSign(const CryptoAlgorithmRsaPssParams&, const CryptoKeyRSA&, const Vector<uint8_t>&); + static ExceptionOr<bool> platformVerify(const CryptoAlgorithmRsaPssParams&, const CryptoKeyRSA&, const Vector<uint8_t>&, const Vector<uint8_t>&); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) && HAVE(RSA_PSS) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSSOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSSOpenSSL.cpp new file mode 100644 index 000000000..62267c581 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRSA_PSSOpenSSL.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2021 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmRSA_PSS.h" + +#if ENABLE(WEB_CRYPTO) && HAVE(RSA_PSS) + +#include "CryptoAlgorithmRsaPssParams.h" +#include "CryptoKeyRSA.h" +#include "OpenSSLUtilities.h" + +namespace WebCore { + +ExceptionOr<Vector<uint8_t>> CryptoAlgorithmRSA_PSS::platformSign(const CryptoAlgorithmRsaPssParams& parameters, const CryptoKeyRSA& key, const Vector<uint8_t>& data) +{ +#if defined(EVP_PKEY_CTX_set_rsa_pss_saltlen) && defined(EVP_PKEY_CTX_set_rsa_mgf1_md) + const EVP_MD* md = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!md) + return Exception { NotSupportedError }; + + std::optional<Vector<uint8_t>> digest = calculateDigest(md, data); + if (!digest) + return Exception { OperationError }; + + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_sign_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PSS_PADDING ) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx.get(), parameters.saltLength) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_signature_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + size_t signatureLen; + if (EVP_PKEY_sign(ctx.get(), nullptr, &signatureLen, digest->data(), digest->size()) <= 0) + return Exception { OperationError }; + + Vector<uint8_t> signature(signatureLen); + if (EVP_PKEY_sign(ctx.get(), signature.data(), &signatureLen, digest->data(), digest->size()) <= 0) + return Exception { OperationError }; + signature.shrink(signatureLen); + + return signature; +#else + return Exception { NotSupportedError }; +#endif +} + +ExceptionOr<bool> CryptoAlgorithmRSA_PSS::platformVerify(const CryptoAlgorithmRsaPssParams& parameters, const CryptoKeyRSA& key, const Vector<uint8_t>& signature, const Vector<uint8_t>& data) +{ +#if defined(EVP_PKEY_CTX_set_rsa_pss_saltlen) && defined(EVP_PKEY_CTX_set_rsa_mgf1_md) + const EVP_MD* md = digestAlgorithm(key.hashAlgorithmIdentifier()); + if (!md) + return Exception { NotSupportedError }; + + std::optional<Vector<uint8_t>> digest = calculateDigest(md, data); + if (!digest) + return Exception { OperationError }; + + auto ctx = EvpPKeyCtxPtr(EVP_PKEY_CTX_new(key.platformKey(), nullptr)); + if (!ctx) + return Exception { OperationError }; + + if (EVP_PKEY_verify_init(ctx.get()) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PSS_PADDING ) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx.get(), parameters.saltLength) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_signature_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), md) <= 0) + return Exception { OperationError }; + + int ret = EVP_PKEY_verify(ctx.get(), signature.data(), signature.size(), digest->data(), digest->size()); + + return ret == 1; +#else + return Exception { NotSupportedError }; +#endif +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistry.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistry.cpp new file mode 100644 index 000000000..92c90fbe4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistry.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmRegistry.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithm.h" +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +CryptoAlgorithmRegistry& CryptoAlgorithmRegistry::singleton() +{ + static LazyNeverDestroyed<CryptoAlgorithmRegistry> registry; + static std::once_flag onceKey; + std::call_once(onceKey, [&] { + registry.construct(); + }); + return registry; +} + +CryptoAlgorithmRegistry::CryptoAlgorithmRegistry() +{ + platformRegisterAlgorithms(); +} + +std::optional<CryptoAlgorithmIdentifier> CryptoAlgorithmRegistry::identifier(const String& name) +{ + if (name.isEmpty()) + return std::nullopt; + + Locker locker { m_lock }; + + // FIXME: How is it helpful to call isolatedCopy on the argument to find? + auto identifier = m_identifiers.find(name.isolatedCopy()); + if (identifier == m_identifiers.end()) + return std::nullopt; + + return identifier->value; +} + +String CryptoAlgorithmRegistry::name(CryptoAlgorithmIdentifier identifier) +{ + Locker locker { m_lock }; + + auto contructor = m_constructors.find(static_cast<unsigned>(identifier)); + if (contructor == m_constructors.end()) + return { }; + + return contructor->value.first.isolatedCopy(); +} + +RefPtr<CryptoAlgorithm> CryptoAlgorithmRegistry::create(CryptoAlgorithmIdentifier identifier) +{ + Locker locker { m_lock }; + + auto contructor = m_constructors.find(static_cast<unsigned>(identifier)); + if (contructor == m_constructors.end()) + return nullptr; + + return contructor->value.second(); +} + +void CryptoAlgorithmRegistry::registerAlgorithm(const String& name, CryptoAlgorithmIdentifier identifier, CryptoAlgorithmConstructor constructor) +{ + Locker locker { m_lock }; + + ASSERT(!m_identifiers.contains(name)); + ASSERT(!m_constructors.contains(static_cast<unsigned>(identifier))); + + m_identifiers.add(name, identifier); + m_constructors.add(static_cast<unsigned>(identifier), std::make_pair(name, constructor)); +} + + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistry.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistry.h new file mode 100644 index 000000000..49d75b2af --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistry.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithmIdentifier.h" +#include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/Lock.h> +#include <wtf/Noncopyable.h> +#include <wtf/text/StringHash.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithm; + +class CryptoAlgorithmRegistry { + WTF_MAKE_NONCOPYABLE(CryptoAlgorithmRegistry); + friend class LazyNeverDestroyed<CryptoAlgorithmRegistry>; + +public: + static CryptoAlgorithmRegistry& singleton(); + + std::optional<CryptoAlgorithmIdentifier> identifier(const String&); + String name(CryptoAlgorithmIdentifier); + + RefPtr<CryptoAlgorithm> create(CryptoAlgorithmIdentifier); + +private: + CryptoAlgorithmRegistry(); + void platformRegisterAlgorithms(); + + using CryptoAlgorithmConstructor = Ref<CryptoAlgorithm> (*)(); + + template<typename AlgorithmClass> void registerAlgorithm() + { + registerAlgorithm(AlgorithmClass::s_name, AlgorithmClass::s_identifier, AlgorithmClass::create); + } + + void registerAlgorithm(const String& name, CryptoAlgorithmIdentifier, CryptoAlgorithmConstructor); + + Lock m_lock; + HashMap<String, CryptoAlgorithmIdentifier, ASCIICaseInsensitiveHash> m_identifiers WTF_GUARDED_BY_LOCK(m_lock); + HashMap<unsigned, std::pair<String, CryptoAlgorithmConstructor>> m_constructors WTF_GUARDED_BY_LOCK(m_lock); +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistryOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistryOpenSSL.cpp new file mode 100644 index 000000000..1976a01a8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRegistryOpenSSL.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoAlgorithmRegistry.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAES_CBC.h" +#include "CryptoAlgorithmAES_CFB.h" +#include "CryptoAlgorithmAES_CTR.h" +#include "CryptoAlgorithmAES_GCM.h" +#include "CryptoAlgorithmAES_KW.h" +#include "CryptoAlgorithmECDH.h" +#include "CryptoAlgorithmECDSA.h" +#include "CryptoAlgorithmHKDF.h" +#include "CryptoAlgorithmHMAC.h" +#include "CryptoAlgorithmPBKDF2.h" +#include "CryptoAlgorithmRSAES_PKCS1_v1_5.h" +#include "CryptoAlgorithmRSASSA_PKCS1_v1_5.h" +#include "CryptoAlgorithmRSA_OAEP.h" +#include "CryptoAlgorithmRSA_PSS.h" +#include "CryptoAlgorithmSHA1.h" +#include "CryptoAlgorithmSHA224.h" +#include "CryptoAlgorithmSHA256.h" +#include "CryptoAlgorithmSHA384.h" +#include "CryptoAlgorithmSHA512.h" + +namespace WebCore { + +void CryptoAlgorithmRegistry::platformRegisterAlgorithms() +{ + registerAlgorithm<CryptoAlgorithmAES_CBC>(); + registerAlgorithm<CryptoAlgorithmAES_CFB>(); + registerAlgorithm<CryptoAlgorithmAES_CTR>(); + registerAlgorithm<CryptoAlgorithmAES_GCM>(); + registerAlgorithm<CryptoAlgorithmAES_KW>(); + registerAlgorithm<CryptoAlgorithmECDH>(); + registerAlgorithm<CryptoAlgorithmECDSA>(); + registerAlgorithm<CryptoAlgorithmHKDF>(); + registerAlgorithm<CryptoAlgorithmHMAC>(); + registerAlgorithm<CryptoAlgorithmPBKDF2>(); + registerAlgorithm<CryptoAlgorithmRSAES_PKCS1_v1_5>(); + registerAlgorithm<CryptoAlgorithmRSASSA_PKCS1_v1_5>(); + registerAlgorithm<CryptoAlgorithmRSA_OAEP>(); + registerAlgorithm<CryptoAlgorithmRSA_PSS>(); + registerAlgorithm<CryptoAlgorithmSHA1>(); + registerAlgorithm<CryptoAlgorithmSHA224>(); + registerAlgorithm<CryptoAlgorithmSHA256>(); + registerAlgorithm<CryptoAlgorithmSHA384>(); + registerAlgorithm<CryptoAlgorithmSHA512>(); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaHashedImportParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaHashedImportParams.h new file mode 100644 index 000000000..4883f7869 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaHashedImportParams.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#pragma once + +#include "CryptoAlgorithmParameters.h" +#include <JavaScriptCore/JSObject.h> +#include <JavaScriptCore/Strong.h> +#include <variant> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmRsaHashedImportParams final : public CryptoAlgorithmParameters { +public: + // FIXME: Consider merging hash and hashIdentifier. + std::variant<JSC::Strong<JSC::JSObject>, String> hash; + CryptoAlgorithmIdentifier hashIdentifier; + + Class parametersClass() const final { return Class::RsaHashedImportParams; } + + CryptoAlgorithmRsaHashedImportParams isolatedCopy() const + { + CryptoAlgorithmRsaHashedImportParams result; + result.identifier = identifier; + result.hashIdentifier = hashIdentifier; + + return result; + } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(RsaHashedImportParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaHashedKeyGenParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaHashedKeyGenParams.h new file mode 100644 index 000000000..ea72bde12 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaHashedKeyGenParams.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#pragma once + +#include "CryptoAlgorithmRsaKeyGenParams.h" +#include <JavaScriptCore/JSObject.h> +#include <JavaScriptCore/Strong.h> +#include <variant> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmRsaHashedKeyGenParams final : public CryptoAlgorithmRsaKeyGenParams { +public: + // FIXME: Consider merging hash and hashIdentifier. + std::variant<JSC::Strong<JSC::JSObject>, String> hash; + CryptoAlgorithmIdentifier hashIdentifier; + + Class parametersClass() const final { return Class::RsaHashedKeyGenParams; } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(RsaHashedKeyGenParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaKeyGenParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaKeyGenParams.h new file mode 100644 index 000000000..af67fd2ad --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaKeyGenParams.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#pragma once + +#include "CryptoAlgorithmParameters.h" +#include <JavaScriptCore/Uint8Array.h> +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmRsaKeyGenParams : public CryptoAlgorithmParameters { +public: + size_t modulusLength; + RefPtr<Uint8Array> publicExponent; + + Class parametersClass() const override { return Class::RsaKeyGenParams; } + + const Vector<uint8_t>& publicExponentVector() const + { + if (!m_publicExponentVector.isEmpty() || !publicExponent->byteLength()) + return m_publicExponentVector; + + m_publicExponentVector.append(publicExponent->data(), publicExponent->byteLength()); + return m_publicExponentVector; + } +private: + mutable Vector<uint8_t> m_publicExponentVector; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(RsaKeyGenParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaOaepParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaOaepParams.h new file mode 100644 index 000000000..769f3d9cb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaOaepParams.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#pragma once + +#include "BufferSource.h" +#include "CryptoAlgorithmParameters.h" +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmRsaOaepParams final : public CryptoAlgorithmParameters { +public: + // Use labelVector() instead of label. The label will be gone once labelVector() is called. + mutable std::optional<BufferSource::VariantType> label; + + Class parametersClass() const final { return Class::RsaOaepParams; } + + const Vector<uint8_t>& labelVector() const + { + if (!m_labelVector.isEmpty() || !label) + return m_labelVector; + + BufferSource labelBuffer = WTFMove(*label); + label = std::nullopt; + if (!labelBuffer.length()) + return m_labelVector; + + m_labelVector.append(labelBuffer.data(), labelBuffer.length()); + return m_labelVector; + } + + CryptoAlgorithmRsaOaepParams isolatedCopy() const + { + CryptoAlgorithmRsaOaepParams result; + result.identifier = identifier; + result.m_labelVector = labelVector(); + + return result; + } + +private: + mutable Vector<uint8_t> m_labelVector; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(RsaOaepParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaPssParams.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaPssParams.h new file mode 100644 index 000000000..412f4ce05 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmRsaPssParams.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoAlgorithmParameters.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmRsaPssParams final : public CryptoAlgorithmParameters { +public: + size_t saltLength; + + Class parametersClass() const final { return Class::RsaPssParams; } + + CryptoAlgorithmRsaPssParams isolatedCopy() const + { + CryptoAlgorithmRsaPssParams result; + result.identifier = identifier; + result.saltLength = saltLength; + + return result; + } +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(RsaPssParams) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp new file mode 100644 index 000000000..f602467e0 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmSHA1.h" + +#if ENABLE(WEB_CRYPTO) + +#include "ScriptExecutionContext.h" +#include "CryptoDigest.h" + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmSHA1::create() +{ + return adoptRef(*new CryptoAlgorithmSHA1); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmSHA1::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmSHA1::digest(Vector<uint8_t>&& message, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto digest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_1); + if (!digest) { + exceptionCallback(OperationError); + return; + } + + workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + digest->addBytes(message.data(), message.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + }); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.h new file mode 100644 index 000000000..1fd775a81 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmSHA1 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "SHA-1"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::SHA_1; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmSHA1() = default; + CryptoAlgorithmIdentifier identifier() const final; + void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp new file mode 100644 index 000000000..dfb8204b5 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmSHA224.h" + +#if ENABLE(WEB_CRYPTO) + +#include "ScriptExecutionContext.h" +#include "CryptoDigest.h" + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmSHA224::create() +{ + return adoptRef(*new CryptoAlgorithmSHA224); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmSHA224::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmSHA224::digest(Vector<uint8_t>&& message, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto digest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_224); + if (!digest) { + exceptionCallback(OperationError); + return; + } + + workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + digest->addBytes(message.data(), message.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + }); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.h new file mode 100644 index 000000000..493e162ab --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmSHA224 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "SHA-224"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::SHA_224; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmSHA224() = default; + CryptoAlgorithmIdentifier identifier() const final; + void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp new file mode 100644 index 000000000..216eccb5d --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmSHA256.h" + +#if ENABLE(WEB_CRYPTO) + +#include "ScriptExecutionContext.h" +#include "CryptoDigest.h" + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmSHA256::create() +{ + return adoptRef(*new CryptoAlgorithmSHA256); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmSHA256::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmSHA256::digest(Vector<uint8_t>&& message, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto digest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256); + if (!digest) { + exceptionCallback(OperationError); + return; + } + + workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + digest->addBytes(message.data(), message.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + }); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.h new file mode 100644 index 000000000..f5a8543c8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmSHA256 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "SHA-256"_s; + static const CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::SHA_256; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmSHA256() = default; + CryptoAlgorithmIdentifier identifier() const final; + void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp new file mode 100644 index 000000000..134e89bd8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmSHA384.h" + +#if ENABLE(WEB_CRYPTO) + +#include "ScriptExecutionContext.h" +#include "CryptoDigest.h" + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmSHA384::create() +{ + return adoptRef(*new CryptoAlgorithmSHA384); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmSHA384::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmSHA384::digest(Vector<uint8_t>&& message, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto digest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_384); + if (!digest) { + exceptionCallback(OperationError); + return; + } + + workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + digest->addBytes(message.data(), message.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + }); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.h new file mode 100644 index 000000000..e5bf2232a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmSHA384 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "SHA-384"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::SHA_384; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmSHA384() = default; + CryptoAlgorithmIdentifier identifier() const final; + void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp new file mode 100644 index 000000000..016a47bf1 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 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 "CryptoAlgorithmSHA512.h" + +#if ENABLE(WEB_CRYPTO) + +#include "ScriptExecutionContext.h" +#include "CryptoDigest.h" + +namespace WebCore { + +Ref<CryptoAlgorithm> CryptoAlgorithmSHA512::create() +{ + return adoptRef(*new CryptoAlgorithmSHA512); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmSHA512::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmSHA512::digest(Vector<uint8_t>&& message, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + auto digest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_512); + if (!digest) { + exceptionCallback(OperationError); + return; + } + + workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + digest->addBytes(message.data(), message.size()); + auto result = digest->computeHash(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { + callback(result); + }); + }); +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.h new file mode 100644 index 000000000..05f98fc4a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithm.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmSHA512 final : public CryptoAlgorithm { +public: + static constexpr ASCIILiteral s_name = "SHA-512"_s; + static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::SHA_512; + static Ref<CryptoAlgorithm> create(); + +private: + CryptoAlgorithmSHA512() = default; + CryptoAlgorithmIdentifier identifier() const final; + void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoDigest.cpp b/src/bun.js/bindings/webcrypto/CryptoDigest.cpp new file mode 100644 index 000000000..8704c0c08 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoDigest.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018 Sony Interactive Entertainment Inc. + * + * 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 "CryptoDigest.h" + +#include <openssl/sha.h> + +namespace { +struct SHA1Functions { + static constexpr auto init = SHA1_Init; + static constexpr auto update = SHA1_Update; + static constexpr auto final = SHA1_Final; + static constexpr size_t digestLength = SHA_DIGEST_LENGTH; +}; + +struct SHA224Functions { + static constexpr auto init = SHA224_Init; + static constexpr auto update = SHA224_Update; + static constexpr auto final = SHA224_Final; + static constexpr size_t digestLength = SHA224_DIGEST_LENGTH; +}; + +struct SHA256Functions { + static constexpr auto init = SHA256_Init; + static constexpr auto update = SHA256_Update; + static constexpr auto final = SHA256_Final; + static constexpr size_t digestLength = SHA256_DIGEST_LENGTH; +}; + +struct SHA384Functions { + static constexpr auto init = SHA384_Init; + static constexpr auto update = SHA384_Update; + static constexpr auto final = SHA384_Final; + static constexpr size_t digestLength = SHA384_DIGEST_LENGTH; +}; + +struct SHA512Functions { + static constexpr auto init = SHA512_Init; + static constexpr auto update = SHA512_Update; + static constexpr auto final = SHA512_Final; + static constexpr size_t digestLength = SHA512_DIGEST_LENGTH; +}; +} + +namespace PAL { + +struct CryptoDigestContext { + virtual ~CryptoDigestContext() = default; + virtual void addBytes(const void* input, size_t length) = 0; + virtual Vector<uint8_t> computeHash() = 0; +}; + +template<typename SHAContext, typename SHAFunctions> +struct CryptoDigestContextImpl : public CryptoDigestContext { + WTF_MAKE_STRUCT_FAST_ALLOCATED; + + static std::unique_ptr<CryptoDigestContext> create() + { + return makeUnique<CryptoDigestContextImpl>(); + } + + CryptoDigestContextImpl() + { + SHAFunctions::init(&m_context); + } + + void addBytes(const void* input, size_t length) override + { + SHAFunctions::update(&m_context, input, length); + } + + Vector<uint8_t> computeHash() override + { + Vector<uint8_t> result(SHAFunctions::digestLength); + SHAFunctions::final(result.data(), &m_context); + return result; + } + +private: + SHAContext m_context; +}; + +CryptoDigest::CryptoDigest() +{ +} + +CryptoDigest::~CryptoDigest() +{ +} + +std::unique_ptr<CryptoDigest> CryptoDigest::create(CryptoDigest::Algorithm algorithm) +{ + std::unique_ptr<CryptoDigest> digest(new CryptoDigest); + + switch (algorithm) { + case CryptoDigest::Algorithm::SHA_1: + digest->m_context = CryptoDigestContextImpl<SHA_CTX, SHA1Functions>::create(); + return digest; + case CryptoDigest::Algorithm::SHA_224: + digest->m_context = CryptoDigestContextImpl<SHA256_CTX, SHA224Functions>::create(); + return digest; + case CryptoDigest::Algorithm::SHA_256: + digest->m_context = CryptoDigestContextImpl<SHA256_CTX, SHA256Functions>::create(); + return digest; + case CryptoDigest::Algorithm::SHA_384: + digest->m_context = CryptoDigestContextImpl<SHA512_CTX, SHA384Functions>::create(); + return digest; + case CryptoDigest::Algorithm::SHA_512: + digest->m_context = CryptoDigestContextImpl<SHA512_CTX, SHA512Functions>::create(); + return digest; + } + + return nullptr; +} + +void CryptoDigest::addBytes(const void* input, size_t length) +{ + ASSERT(m_context); + m_context->addBytes(input, length); +} + +Vector<uint8_t> CryptoDigest::computeHash() +{ + ASSERT(m_context); + return m_context->computeHash(); +} + +} // namespace PAL diff --git a/src/bun.js/bindings/webcrypto/CryptoDigest.h b/src/bun.js/bindings/webcrypto/CryptoDigest.h new file mode 100644 index 000000000..5da849a1d --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoDigest.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013, 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. + */ + +#pragma once + +#include <wtf/Noncopyable.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +#ifndef PAL_EXPORT +#define PAL_EXPORT +#endif + +namespace PAL { + +struct CryptoDigestContext; + +class CryptoDigest { + WTF_MAKE_NONCOPYABLE(CryptoDigest); + +public: + enum class Algorithm { + SHA_1, + SHA_224, + SHA_256, + SHA_384, + SHA_512, + }; + PAL_EXPORT static std::unique_ptr<CryptoDigest> create(Algorithm); + PAL_EXPORT ~CryptoDigest(); + + PAL_EXPORT void addBytes(const void* input, size_t length); + PAL_EXPORT Vector<uint8_t> computeHash(); + PAL_EXPORT String toHexString(); + +private: + CryptoDigest(); + + std::unique_ptr<CryptoDigestContext> m_context; +}; + +} // namespace PAL diff --git a/src/bun.js/bindings/webcrypto/CryptoEcKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoEcKeyAlgorithm.h new file mode 100644 index 000000000..dc6e67683 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoEcKeyAlgorithm.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoKeyAlgorithm.h" + +namespace WebCore { + +struct CryptoEcKeyAlgorithm : CryptoKeyAlgorithm { + // The named curve that the key uses + String namedCurve; +}; + +} + diff --git a/src/bun.js/bindings/webcrypto/CryptoEcKeyAlgorithm.idl b/src/bun.js/bindings/webcrypto/CryptoEcKeyAlgorithm.idl new file mode 100644 index 000000000..1096a3b1b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoEcKeyAlgorithm.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 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. + */ + +typedef DOMString NamedCurve; + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject +] dictionary CryptoEcKeyAlgorithm : CryptoKeyAlgorithm { + // The named curve that the key uses + required NamedCurve namedCurve; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoHmacKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoHmacKeyAlgorithm.h new file mode 100644 index 000000000..92aa132ba --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoHmacKeyAlgorithm.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoKeyAlgorithm.h" + +namespace WebCore { + +struct CryptoHmacKeyAlgorithm : CryptoKeyAlgorithm { + // The inner hash function to use. + CryptoKeyAlgorithm hash; + // The length (in bits) of the key. + unsigned length; +}; + +} + + diff --git a/src/bun.js/bindings/webcrypto/CryptoHmacKeyAlgorithm.idl b/src/bun.js/bindings/webcrypto/CryptoHmacKeyAlgorithm.idl new file mode 100644 index 000000000..a836f0d25 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoHmacKeyAlgorithm.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 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. + */ + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject +] dictionary CryptoHmacKeyAlgorithm : CryptoKeyAlgorithm { + // The inner hash function to use. + required CryptoKeyAlgorithm hash; + // The length (in bits) of the key. + required unsigned long length; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoKey.cpp b/src/bun.js/bindings/webcrypto/CryptoKey.cpp new file mode 100644 index 000000000..4491a11fb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKey.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2013 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 "CryptoKey.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRegistry.h" +#include "WebCoreOpaqueRoot.h" +#include <wtf/CryptographicallyRandomNumber.h> +#include <openssl/rand.h> + +namespace WebCore { + +CryptoKey::CryptoKey(CryptoAlgorithmIdentifier algorithmIdentifier, Type type, bool extractable, CryptoKeyUsageBitmap usages) + : m_algorithmIdentifier(algorithmIdentifier) + , m_type(type) + , m_extractable(extractable) + , m_usages(usages) +{ +} + +CryptoKey::~CryptoKey() = default; + +auto CryptoKey::usages() const -> Vector<CryptoKeyUsage> +{ + // The result is ordered alphabetically. + Vector<CryptoKeyUsage> result; + if (m_usages & CryptoKeyUsageDecrypt) + result.append(CryptoKeyUsage::Decrypt); + if (m_usages & CryptoKeyUsageDeriveBits) + result.append(CryptoKeyUsage::DeriveBits); + if (m_usages & CryptoKeyUsageDeriveKey) + result.append(CryptoKeyUsage::DeriveKey); + if (m_usages & CryptoKeyUsageEncrypt) + result.append(CryptoKeyUsage::Encrypt); + if (m_usages & CryptoKeyUsageSign) + result.append(CryptoKeyUsage::Sign); + if (m_usages & CryptoKeyUsageUnwrapKey) + result.append(CryptoKeyUsage::UnwrapKey); + if (m_usages & CryptoKeyUsageVerify) + result.append(CryptoKeyUsage::Verify); + if (m_usages & CryptoKeyUsageWrapKey) + result.append(CryptoKeyUsage::WrapKey); + return result; +} + +WebCoreOpaqueRoot root(CryptoKey* key) +{ + return WebCoreOpaqueRoot { key }; +} + + + + +Vector<uint8_t> CryptoKey::randomData(size_t size) +{ + Vector<uint8_t> result(size); + RAND_bytes(result.data(), result.size()); + return result; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKey.h b/src/bun.js/bindings/webcrypto/CryptoKey.h new file mode 100644 index 000000000..f91229173 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKey.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAesKeyAlgorithm.h" +#include "CryptoAlgorithmIdentifier.h" +#include "CryptoEcKeyAlgorithm.h" +#include "CryptoHmacKeyAlgorithm.h" +#include "CryptoKeyAlgorithm.h" +#include "CryptoKeyType.h" +#include "CryptoKeyUsage.h" +#include "CryptoRsaHashedKeyAlgorithm.h" +#include "CryptoRsaKeyAlgorithm.h" +#include <variant> +#include <wtf/Forward.h> +#include <wtf/ThreadSafeRefCounted.h> +#include <wtf/TypeCasts.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class WebCoreOpaqueRoot; + +enum class CryptoKeyClass { + AES, + EC, + HMAC, + RSA, + Raw, +}; + +class CryptoKey : public ThreadSafeRefCounted<CryptoKey> { +public: + using Type = CryptoKeyType; + using KeyAlgorithm = std::variant<CryptoKeyAlgorithm, CryptoAesKeyAlgorithm, CryptoEcKeyAlgorithm, CryptoHmacKeyAlgorithm, CryptoRsaHashedKeyAlgorithm, CryptoRsaKeyAlgorithm>; + + CryptoKey(CryptoAlgorithmIdentifier, Type, bool extractable, CryptoKeyUsageBitmap); + virtual ~CryptoKey(); + + Type type() const; + bool extractable() const { return m_extractable; } + Vector<CryptoKeyUsage> usages() const; + virtual KeyAlgorithm algorithm() const = 0; + + virtual CryptoKeyClass keyClass() const = 0; + + CryptoAlgorithmIdentifier algorithmIdentifier() const { return m_algorithmIdentifier; } + CryptoKeyUsageBitmap usagesBitmap() const { return m_usages; } + void setUsagesBitmap(CryptoKeyUsageBitmap usage) { m_usages = usage; }; + bool allows(CryptoKeyUsageBitmap usage) const { return usage == (m_usages & usage); } + + static Vector<uint8_t> randomData(size_t); + +private: + CryptoAlgorithmIdentifier m_algorithmIdentifier; + Type m_type; + bool m_extractable; + CryptoKeyUsageBitmap m_usages; +}; + +inline auto CryptoKey::type() const -> Type +{ + return m_type; +} + +WebCoreOpaqueRoot root(CryptoKey*); + +} // namespace WebCore + +#define SPECIALIZE_TYPE_TRAITS_CRYPTO_KEY(ToClassName, KeyClass) \ +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToClassName) \ + static bool isType(const WebCore::CryptoKey& key) { return key.keyClass() == WebCore::KeyClass; } \ +SPECIALIZE_TYPE_TRAITS_END() + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKey.idl b/src/bun.js/bindings/webcrypto/CryptoKey.idl new file mode 100644 index 000000000..31ad11f72 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKey.idl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 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. + */ + +enum KeyType { + "public", + "private", + "secret" +}; + +typedef (CryptoKeyAlgorithm or CryptoAesKeyAlgorithm or CryptoEcKeyAlgorithm or CryptoHmacKeyAlgorithm or CryptoRsaHashedKeyAlgorithm or CryptoRsaKeyAlgorithm) KeyAlgorithm; + +[ + Conditional=WEB_CRYPTO, + Exposed=(Window,Worker), + GenerateIsReachable=Impl, + SecureContext, + SkipVTableValidation +] interface CryptoKey { + readonly attribute KeyType type; + readonly attribute boolean extractable; + [CachedAttribute] readonly attribute KeyAlgorithm algorithm; + [CachedAttribute] readonly attribute sequence<CryptoKeyUsage> usages; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyAES.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyAES.cpp new file mode 100644 index 000000000..17cbf48d9 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyAES.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2013 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 "CryptoKeyAES.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAesKeyAlgorithm.h" +#include "CryptoAlgorithmAesKeyParams.h" +#include "CryptoAlgorithmRegistry.h" +#include "ExceptionOr.h" +#include "JsonWebKey.h" +#include <wtf/text/Base64.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +static inline bool lengthIsValid(size_t length) +{ + return (length == CryptoKeyAES::s_length128) || (length == CryptoKeyAES::s_length192) || (length == CryptoKeyAES::s_length256); +} + +CryptoKeyAES::CryptoKeyAES(CryptoAlgorithmIdentifier algorithm, const Vector<uint8_t>& key, bool extractable, CryptoKeyUsageBitmap usage) + : CryptoKey(algorithm, CryptoKeyType::Secret, extractable, usage) + , m_key(key) +{ + ASSERT(isValidAESAlgorithm(algorithm)); +} + +CryptoKeyAES::CryptoKeyAES(CryptoAlgorithmIdentifier algorithm, Vector<uint8_t>&& key, bool extractable, CryptoKeyUsageBitmap usage) + : CryptoKey(algorithm, CryptoKeyType::Secret, extractable, usage) + , m_key(WTFMove(key)) +{ + ASSERT(isValidAESAlgorithm(algorithm)); +} + +CryptoKeyAES::~CryptoKeyAES() = default; + +bool CryptoKeyAES::isValidAESAlgorithm(CryptoAlgorithmIdentifier algorithm) +{ + return algorithm == CryptoAlgorithmIdentifier::AES_CTR + || algorithm == CryptoAlgorithmIdentifier::AES_CBC + || algorithm == CryptoAlgorithmIdentifier::AES_GCM + || algorithm == CryptoAlgorithmIdentifier::AES_CFB + || algorithm == CryptoAlgorithmIdentifier::AES_KW; +} + +RefPtr<CryptoKeyAES> CryptoKeyAES::generate(CryptoAlgorithmIdentifier algorithm, size_t lengthBits, bool extractable, CryptoKeyUsageBitmap usages) +{ + if (!lengthIsValid(lengthBits)) + return nullptr; + return adoptRef(new CryptoKeyAES(algorithm, randomData(lengthBits / 8), extractable, usages)); +} + +RefPtr<CryptoKeyAES> CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier algorithm, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + if (!lengthIsValid(keyData.size() * 8)) + return nullptr; + return adoptRef(new CryptoKeyAES(algorithm, WTFMove(keyData), extractable, usages)); +} + +RefPtr<CryptoKeyAES> CryptoKeyAES::importJwk(CryptoAlgorithmIdentifier algorithm, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages, CheckAlgCallback&& callback) +{ + if (keyData.kty != "oct"_s) + return nullptr; + if (keyData.k.isNull()) + return nullptr; + auto octetSequence = base64URLDecode(keyData.k); + if (!octetSequence) + return nullptr; + if (!callback(octetSequence->size() * 8, keyData.alg)) + return nullptr; + if (usages && !keyData.use.isNull() && keyData.use != "enc"_s) + return nullptr; + if (keyData.key_ops && ((keyData.usages & usages) != usages)) + return nullptr; + if (keyData.ext && !keyData.ext.value() && extractable) + return nullptr; + + return adoptRef(new CryptoKeyAES(algorithm, WTFMove(*octetSequence), extractable, usages)); +} + +JsonWebKey CryptoKeyAES::exportJwk() const +{ + JsonWebKey result; + result.kty = "oct"_s; + result.k = base64URLEncodeToString(m_key); + result.key_ops = usages(); + result.ext = extractable(); + return result; +} + +ExceptionOr<size_t> CryptoKeyAES::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters); + if (!lengthIsValid(aesParameters.length)) + return Exception { OperationError }; + return aesParameters.length; +} + +auto CryptoKeyAES::algorithm() const -> KeyAlgorithm +{ + CryptoAesKeyAlgorithm result; + result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()); + result.length = m_key.size() * 8; + return result; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyAES.h b/src/bun.js/bindings/webcrypto/CryptoKeyAES.h new file mode 100644 index 000000000..341ca6bc7 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyAES.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include "CryptoAlgorithmIdentifier.h" +#include "CryptoKey.h" +#include "ExceptionOr.h" +#include <wtf/Function.h> +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoAlgorithmParameters; + +struct JsonWebKey; + +class CryptoKeyAES final : public CryptoKey { +public: + static const int s_length128 = 128; + static const int s_length192 = 192; + static const int s_length256 = 256; + + static Ref<CryptoKeyAES> create(CryptoAlgorithmIdentifier algorithm, const Vector<uint8_t>& key, bool extractable, CryptoKeyUsageBitmap usage) + { + return adoptRef(*new CryptoKeyAES(algorithm, key, extractable, usage)); + } + virtual ~CryptoKeyAES(); + + static bool isValidAESAlgorithm(CryptoAlgorithmIdentifier); + + static RefPtr<CryptoKeyAES> generate(CryptoAlgorithmIdentifier, size_t lengthBits, bool extractable, CryptoKeyUsageBitmap); + WEBCORE_EXPORT static RefPtr<CryptoKeyAES> importRaw(CryptoAlgorithmIdentifier, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + using CheckAlgCallback = Function<bool(size_t, const String&)>; + static RefPtr<CryptoKeyAES> importJwk(CryptoAlgorithmIdentifier, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap, CheckAlgCallback&&); + + CryptoKeyClass keyClass() const final { return CryptoKeyClass::AES; } + + const Vector<uint8_t>& key() const { return m_key; } + JsonWebKey exportJwk() const; + + static ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&); + +private: + CryptoKeyAES(CryptoAlgorithmIdentifier, const Vector<uint8_t>& key, bool extractable, CryptoKeyUsageBitmap); + CryptoKeyAES(CryptoAlgorithmIdentifier, Vector<uint8_t>&& key, bool extractable, CryptoKeyUsageBitmap); + + KeyAlgorithm algorithm() const final; + + Vector<uint8_t> m_key; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_KEY(CryptoKeyAES, CryptoKeyClass::AES) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoKeyAlgorithm.h new file mode 100644 index 000000000..dcfeec9e7 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyAlgorithm.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include <wtf/text/WTFString.h> + +namespace WebCore { + +struct CryptoKeyAlgorithm { + String name; +}; + +} diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyAlgorithm.idl b/src/bun.js/bindings/webcrypto/CryptoKeyAlgorithm.idl new file mode 100644 index 000000000..a7d314786 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyAlgorithm.idl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 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. + */ + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject +] dictionary CryptoKeyAlgorithm { + required DOMString name; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp new file mode 100644 index 000000000..d62a38b53 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2017-2019 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CryptoKeyEC.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRegistry.h" +#include "JsonWebKey.h" +#include <wtf/text/Base64.h> + +namespace WebCore { + +static const ASCIILiteral P256 { "P-256"_s }; +static const ASCIILiteral P384 { "P-384"_s }; +static const ASCIILiteral P521 { "P-521"_s }; + +static std::optional<CryptoKeyEC::NamedCurve> toNamedCurve(const String& curve) +{ + if (curve == P256) + return CryptoKeyEC::NamedCurve::P256; + if (curve == P384) + return CryptoKeyEC::NamedCurve::P384; + if (curve == P521) + return CryptoKeyEC::NamedCurve::P521; + + return std::nullopt; +} + +CryptoKeyEC::CryptoKeyEC(CryptoAlgorithmIdentifier identifier, NamedCurve curve, CryptoKeyType type, PlatformECKeyContainer&& platformKey, bool extractable, CryptoKeyUsageBitmap usages) + : CryptoKey(identifier, type, extractable, usages) + , m_platformKey(WTFMove(platformKey)) + , m_curve(curve) +{ + // Only CryptoKeyEC objects for supported curves should be created. + ASSERT(platformSupportedCurve(curve)); +} + +ExceptionOr<CryptoKeyPair> CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier identifier, const String& curve, bool extractable, CryptoKeyUsageBitmap usages) +{ + auto namedCurve = toNamedCurve(curve); + if (!namedCurve || !platformSupportedCurve(*namedCurve)) + return Exception { NotSupportedError }; + + auto result = platformGeneratePair(identifier, *namedCurve, extractable, usages); + if (!result) + return Exception { OperationError }; + + return WTFMove(*result); +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::importRaw(CryptoAlgorithmIdentifier identifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + auto namedCurve = toNamedCurve(curve); + if (!namedCurve || !platformSupportedCurve(*namedCurve)) + return nullptr; + + return platformImportRaw(identifier, *namedCurve, WTFMove(keyData), extractable, usages); +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::importJwk(CryptoAlgorithmIdentifier identifier, const String& curve, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + if (keyData.kty != "EC"_s) + return nullptr; + if (keyData.key_ops && ((keyData.usages & usages) != usages)) + return nullptr; + if (keyData.ext && !keyData.ext.value() && extractable) + return nullptr; + + if (keyData.crv.isNull() || curve != keyData.crv) + return nullptr; + auto namedCurve = toNamedCurve(keyData.crv); + if (!namedCurve || !platformSupportedCurve(*namedCurve)) + return nullptr; + + if (keyData.x.isNull() || keyData.y.isNull()) + return nullptr; + auto x = base64URLDecode(keyData.x); + if (!x) + return nullptr; + auto y = base64URLDecode(keyData.y); + if (!y) + return nullptr; + if (keyData.d.isNull()) { + // import public key + return platformImportJWKPublic(identifier, *namedCurve, WTFMove(*x), WTFMove(*y), extractable, usages); + } + + auto d = base64URLDecode(keyData.d); + if (!d) + return nullptr; + // import private key + return platformImportJWKPrivate(identifier, *namedCurve, WTFMove(*x), WTFMove(*y), WTFMove(*d), extractable, usages); +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::importSpki(CryptoAlgorithmIdentifier identifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + auto namedCurve = toNamedCurve(curve); + if (!namedCurve || !platformSupportedCurve(*namedCurve)) + return nullptr; + + return platformImportSpki(identifier, *namedCurve, WTFMove(keyData), extractable, usages); +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::importPkcs8(CryptoAlgorithmIdentifier identifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + auto namedCurve = toNamedCurve(curve); + if (!namedCurve || !platformSupportedCurve(*namedCurve)) + return nullptr; + + return platformImportPkcs8(identifier, *namedCurve, WTFMove(keyData), extractable, usages); +} + +ExceptionOr<Vector<uint8_t>> CryptoKeyEC::exportRaw() const +{ + if (type() != CryptoKey::Type::Public) + return Exception { InvalidAccessError }; + + auto&& result = platformExportRaw(); + if (result.isEmpty()) + return Exception { OperationError }; + return WTFMove(result); +} + +ExceptionOr<JsonWebKey> CryptoKeyEC::exportJwk() const +{ + JsonWebKey result; + result.kty = "EC"_s; + switch (m_curve) { + case NamedCurve::P256: + result.crv = P256; + break; + case NamedCurve::P384: + result.crv = P384; + break; + case NamedCurve::P521: + result.crv = P521; + break; + } + result.key_ops = usages(); + result.ext = extractable(); + if (!platformAddFieldElements(result)) + return Exception { OperationError }; + return result; +} + +ExceptionOr<Vector<uint8_t>> CryptoKeyEC::exportSpki() const +{ + if (type() != CryptoKey::Type::Public) + return Exception { InvalidAccessError }; + + auto&& result = platformExportSpki(); + if (result.isEmpty()) + return Exception { OperationError }; + return WTFMove(result); +} + +ExceptionOr<Vector<uint8_t>> CryptoKeyEC::exportPkcs8() const +{ + if (type() != CryptoKey::Type::Private) + return Exception { InvalidAccessError }; + + auto&& result = platformExportPkcs8(); + if (result.isEmpty()) + return Exception { OperationError }; + return WTFMove(result); +} + +String CryptoKeyEC::namedCurveString() const +{ + switch (m_curve) { + case NamedCurve::P256: + return String(P256); + case NamedCurve::P384: + return String(P384); + case NamedCurve::P521: + return String(P521); + } + + ASSERT_NOT_REACHED(); + return emptyString(); +} + +bool CryptoKeyEC::isValidECAlgorithm(CryptoAlgorithmIdentifier algorithm) +{ + return algorithm == CryptoAlgorithmIdentifier::ECDSA || algorithm == CryptoAlgorithmIdentifier::ECDH; +} + +auto CryptoKeyEC::algorithm() const -> KeyAlgorithm +{ + CryptoEcKeyAlgorithm result; + result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()); + + switch (m_curve) { + case NamedCurve::P256: + result.namedCurve = P256; + break; + case NamedCurve::P384: + result.namedCurve = P384; + break; + case NamedCurve::P521: + result.namedCurve = P521; + break; + } + + return result; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyEC.h b/src/bun.js/bindings/webcrypto/CryptoKeyEC.h new file mode 100644 index 000000000..f2cf7383f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyEC.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2017-2019 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CryptoKey.h" +#include "CryptoKeyPair.h" +#include "ExceptionOr.h" + +#if ENABLE(WEB_CRYPTO) + +#if 0 +#include "CommonCryptoUtilities.h" + +typedef CCECCryptorRef PlatformECKey; +namespace WebCore { +struct CCECCryptorRefDeleter { + void operator()(CCECCryptorRef key) const { CCECCryptorRelease(key); } +}; +} +typedef std::unique_ptr<typename std::remove_pointer<CCECCryptorRef>::type, WebCore::CCECCryptorRefDeleter> PlatformECKeyContainer; +#endif + +#if USE(GCRYPT) +#include <pal/crypto/gcrypt/Handle.h> + +typedef gcry_sexp_t PlatformECKey; +typedef std::unique_ptr<typename std::remove_pointer<gcry_sexp_t>::type, PAL::GCrypt::HandleDeleter<gcry_sexp_t>> PlatformECKeyContainer; +#endif + +#if USE(OPENSSL) +#include "OpenSSLCryptoUniquePtr.h" +typedef EVP_PKEY* PlatformECKey; +typedef WebCore::EvpPKeyPtr PlatformECKeyContainer; +#endif + +namespace WebCore { + +struct JsonWebKey; + +class CryptoKeyEC final : public CryptoKey { +public: + enum class NamedCurve { + P256, + P384, + P521, + }; + + static Ref<CryptoKeyEC> create(CryptoAlgorithmIdentifier identifier, NamedCurve curve, CryptoKeyType type, PlatformECKeyContainer&& platformKey, bool extractable, CryptoKeyUsageBitmap usages) + { + return adoptRef(*new CryptoKeyEC(identifier, curve, type, WTFMove(platformKey), extractable, usages)); + } + virtual ~CryptoKeyEC() = default; + + WEBCORE_EXPORT static ExceptionOr<CryptoKeyPair> generatePair(CryptoAlgorithmIdentifier, const String& curve, bool extractable, CryptoKeyUsageBitmap); + WEBCORE_EXPORT static RefPtr<CryptoKeyEC> importRaw(CryptoAlgorithmIdentifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> importJwk(CryptoAlgorithmIdentifier, const String& curve, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> importSpki(CryptoAlgorithmIdentifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> importPkcs8(CryptoAlgorithmIdentifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + + WEBCORE_EXPORT ExceptionOr<Vector<uint8_t>> exportRaw() const; + ExceptionOr<JsonWebKey> exportJwk() const; + ExceptionOr<Vector<uint8_t>> exportSpki() const; + ExceptionOr<Vector<uint8_t>> exportPkcs8() const; + + size_t keySizeInBits() const; + size_t keySizeInBytes() const { return std::ceil(keySizeInBits() / 8.); } + NamedCurve namedCurve() const { return m_curve; } + String namedCurveString() const; + PlatformECKey platformKey() const { return m_platformKey.get(); } + static bool isValidECAlgorithm(CryptoAlgorithmIdentifier); + +private: + CryptoKeyEC(CryptoAlgorithmIdentifier, NamedCurve, CryptoKeyType, PlatformECKeyContainer&&, bool extractable, CryptoKeyUsageBitmap); + + CryptoKeyClass keyClass() const final { return CryptoKeyClass::EC; } + + KeyAlgorithm algorithm() const final; + + static bool platformSupportedCurve(NamedCurve); + static std::optional<CryptoKeyPair> platformGeneratePair(CryptoAlgorithmIdentifier, NamedCurve, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> platformImportRaw(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> platformImportJWKPublic(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> platformImportJWKPrivate(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, Vector<uint8_t>&& d, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> platformImportSpki(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> platformImportPkcs8(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + Vector<uint8_t> platformExportRaw() const; + bool platformAddFieldElements(JsonWebKey&) const; + Vector<uint8_t> platformExportSpki() const; + Vector<uint8_t> platformExportPkcs8() const; + + PlatformECKeyContainer m_platformKey; + NamedCurve m_curve; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_KEY(CryptoKeyEC, CryptoKeyClass::EC) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyECOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyECOpenSSL.cpp new file mode 100644 index 000000000..bb5dc5e62 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyECOpenSSL.cpp @@ -0,0 +1,464 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "CryptoKeyEC.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JsonWebKey.h" +#include "OpenSSLUtilities.h" +#include <wtf/text/Base64.h> + +namespace WebCore { + +static int curveIdentifier(CryptoKeyEC::NamedCurve curve) +{ + switch (curve) { + case CryptoKeyEC::NamedCurve::P256: + return NID_X9_62_prime256v1; + case CryptoKeyEC::NamedCurve::P384: + return NID_secp384r1; + case CryptoKeyEC::NamedCurve::P521: + return NID_secp521r1; + } + + ASSERT_NOT_REACHED(); + return NID_undef; +} + +static size_t curveSize(CryptoKeyEC::NamedCurve curve) +{ + switch (curve) { + case CryptoKeyEC::NamedCurve::P256: + return 256; + case CryptoKeyEC::NamedCurve::P384: + return 384; + case CryptoKeyEC::NamedCurve::P521: + return 521; + } + + ASSERT_NOT_REACHED(); + return 0; +} + +static ECKeyPtr createECKey(CryptoKeyEC::NamedCurve curve) +{ + auto key = ECKeyPtr(EC_KEY_new_by_curve_name(curveIdentifier(curve))); + if (key) { + // OPENSSL_EC_NAMED_CURVE needs to be set to export the key with the curve name, not with the curve parameters. + EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE); + } + return key; +} + +// This function verifies that the group represents the named curve. +static bool verifyCurve(const EC_GROUP* group, CryptoKeyEC::NamedCurve curve) +{ + if (!group) + return false; + + auto key = createECKey(curve); + if (!key) + return false; + + return !EC_GROUP_cmp(group, EC_KEY_get0_group(key.get()), nullptr); +} + +size_t CryptoKeyEC::keySizeInBits() const +{ + // EVP_PKEY_size() returns the size of DER-encoded key and cannot be used for this function's purpose. + // Instead we resolve the key size by CryptoKeyEC::NamedCurve. + size_t size = curveSize(m_curve); + return size; +} + +bool CryptoKeyEC::platformSupportedCurve(NamedCurve curve) +{ + return curve == NamedCurve::P256 || curve == NamedCurve::P384 || curve == NamedCurve::P521; +} + +std::optional<CryptoKeyPair> CryptoKeyEC::platformGeneratePair(CryptoAlgorithmIdentifier identifier, NamedCurve curve, bool extractable, CryptoKeyUsageBitmap usages) +{ + // To generate a key pair, we generate a private key and extract the public key from the private key. + auto privateECKey = createECKey(curve); + if (!privateECKey) + return std::nullopt; + + if (EC_KEY_generate_key(privateECKey.get()) <= 0) + return std::nullopt; + + auto point = ECPointPtr(EC_POINT_dup(EC_KEY_get0_public_key(privateECKey.get()), EC_KEY_get0_group(privateECKey.get()))); + if (!point) + return std::nullopt; + + auto publicECKey = createECKey(curve); + if (!publicECKey) + return std::nullopt; + + if (EC_KEY_set_public_key(publicECKey.get(), point.get()) <= 0) + return std::nullopt; + + auto privatePKey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_EC_KEY(privatePKey.get(), privateECKey.get()) <= 0) + return std::nullopt; + + auto publicPKey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_EC_KEY(publicPKey.get(), publicECKey.get()) <= 0) + return std::nullopt; + + auto publicKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Public, WTFMove(publicPKey), true, usages); + auto privateKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Private, WTFMove(privatePKey), extractable, usages); + return CryptoKeyPair { WTFMove(publicKey), WTFMove(privateKey) }; +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportRaw(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + auto key = createECKey(curve); + if (!key) + return nullptr; + + auto group = EC_KEY_get0_group(key.get()); + auto point = ECPointPtr(EC_POINT_new(group)); + // Load an EC point from the keyData. This point is used as a public key. + if (EC_POINT_oct2point(group, point.get(), keyData.data(), keyData.size(), nullptr) <= 0) + return nullptr; + + if (EC_KEY_set_public_key(key.get(), point.get()) <= 0) + return nullptr; + + if (EC_KEY_check_key(key.get()) <= 0) + return nullptr; + + auto pkey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0) + return nullptr; + + return create(identifier, curve, CryptoKeyType::Public, WTFMove(pkey), extractable, usages); +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportJWKPublic(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, bool extractable, CryptoKeyUsageBitmap usages) +{ + auto key = createECKey(curve); + if (!key) + return nullptr; + + auto group = EC_KEY_get0_group(key.get()); + auto point = ECPointPtr(EC_POINT_new(group)); + + // Currently we only support elliptic curves over GF(p). + if (EC_POINT_set_affine_coordinates_GFp(group, point.get(), convertToBigNumber(x).get(), convertToBigNumber(y).get(), nullptr) <= 0) + return nullptr; + + if (EC_KEY_set_public_key(key.get(), point.get()) <= 0) + return nullptr; + + if (EC_KEY_check_key(key.get()) <= 0) + return nullptr; + + auto pkey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0) + return nullptr; + + return create(identifier, curve, CryptoKeyType::Public, WTFMove(pkey), extractable, usages); +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportJWKPrivate(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, Vector<uint8_t>&& d, bool extractable, CryptoKeyUsageBitmap usages) +{ + auto key = createECKey(curve); + if (!key) + return nullptr; + + auto group = EC_KEY_get0_group(key.get()); + auto point = ECPointPtr(EC_POINT_new(group)); + + // Currently we only support elliptic curves over GF(p). + if (EC_POINT_set_affine_coordinates_GFp(group, point.get(), convertToBigNumber(x).get(), convertToBigNumber(y).get(), nullptr) <= 0) + return nullptr; + + if (EC_KEY_set_public_key(key.get(), point.get()) <= 0) + return nullptr; + + if (EC_KEY_set_private_key(key.get(), convertToBigNumber(d).get()) <= 0) + return nullptr; + + if (EC_KEY_check_key(key.get()) <= 0) + return nullptr; + + auto pkey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0) + return nullptr; + + return create(identifier, curve, CryptoKeyType::Private, WTFMove(pkey), extractable, usages); +} + +static const ASN1_OBJECT* ecPublicKeyIdentifier() +{ + static ASN1_OBJECT* oid = OBJ_txt2obj("1.2.840.10045.2.1", 1); + return oid; +} + +static const ASN1_OBJECT* ecDHIdentifier() +{ + static ASN1_OBJECT* oid = OBJ_txt2obj("1.3.132.1.12", 1); + return oid; +} + +static bool supportedAlgorithmIdentifier(CryptoAlgorithmIdentifier identifier, const ASN1_OBJECT* oid) +{ + switch (identifier) { + case CryptoAlgorithmIdentifier::ECDSA: + // ECDSA only supports id-ecPublicKey algorithms for imported keys. + if (!OBJ_cmp(oid, ecPublicKeyIdentifier())) + return true; + return false; + case CryptoAlgorithmIdentifier::ECDH: + // ECDH supports both id-ecPublicKey and id-ecDH algorithms for imported keys. + if (!OBJ_cmp(oid, ecPublicKeyIdentifier())) + return true; + if (!OBJ_cmp(oid, ecDHIdentifier())) + return true; + return false; + default: + ASSERT_NOT_REACHED(); + return false; + } +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + // In this function we extract the subjectPublicKey after verifying that the algorithm in the SPKI data + // match the given identifier and curve. Then construct an EC key with the named curve and set the public key. + + // SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING + // } + + const uint8_t* ptr = keyData.data(); + auto subjectPublicKeyInfo = ASN1SequencePtr(d2i_ASN1_SEQUENCE_ANY(nullptr, &ptr, keyData.size())); + if (!subjectPublicKeyInfo) + return nullptr; + if (ptr - keyData.data() != (ptrdiff_t)keyData.size()) + return nullptr; + + if (sk_ASN1_TYPE_num(subjectPublicKeyInfo.get()) != 2) + return nullptr; + + ASN1_TYPE* value = sk_ASN1_TYPE_value(subjectPublicKeyInfo.get(), 0); + if (value->type != V_ASN1_SEQUENCE) + return nullptr; + + // AlgorithmIdentifier ::= SEQUENCE { + // algorithm OBJECT IDENTIFIER, + // parameters ANY DEFINED BY algorithm OPTIONAL + // } + + ptr = value->value.sequence->data; + auto algorithm = ASN1SequencePtr(d2i_ASN1_SEQUENCE_ANY(nullptr, &ptr, value->value.sequence->length)); + if (!algorithm) + return nullptr; + + if (sk_ASN1_TYPE_num(algorithm.get()) != 2) + return nullptr; + + value = sk_ASN1_TYPE_value(algorithm.get(), 0); + if (value->type != V_ASN1_OBJECT) + return nullptr; + + if (!supportedAlgorithmIdentifier(identifier, value->value.object)) + return nullptr; + + // ECParameters ::= CHOICE { + // namedCurve OBJECT IDENTIFIER + // -- implicitCurve null + // -- specifiedCurve SpecifiedECDomain + // } + // + // Only "namedCurve" is supported. + value = sk_ASN1_TYPE_value(algorithm.get(), 1); + if (value->type != V_ASN1_OBJECT) + return nullptr; + + int curveNID = OBJ_obj2nid(value->value.object); + if (curveNID != curveIdentifier(curve)) + return nullptr; + + // subjectPublicKey must be a BIT STRING. + value = sk_ASN1_TYPE_value(subjectPublicKeyInfo.get(), 1); + if (value->type != V_ASN1_BIT_STRING) + return nullptr; + + ASN1_BIT_STRING* bitString = value->value.bit_string; + + // The SPKI data has been verified at this point. We prepare platform data next. + auto key = createECKey(curve); + if (!key) + return nullptr; + + auto group = EC_KEY_get0_group(key.get()); + if (!group) + return nullptr; + + auto point = ECPointPtr(EC_POINT_new(group)); + if (!point) + return nullptr; + + if (EC_POINT_oct2point(group, point.get(), bitString->data, bitString->length, 0) <= 0) + return nullptr; + + if (EC_KEY_set_public_key(key.get(), point.get()) <= 0) + return nullptr; + + if (EC_KEY_check_key(key.get()) <= 0) + return nullptr; + + EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE); + + auto pkey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0) + return nullptr; + + return adoptRef(new CryptoKeyEC(identifier, curve, CryptoKeyType::Public, WTFMove(pkey), extractable, usages)); +} + +RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportPkcs8(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + // We need a local pointer variable to pass to d2i (DER to internal) functions(). + const uint8_t* ptr = keyData.data(); + + // We use d2i_PKCS8_PRIV_KEY_INFO() to import a private key. + auto p8inf = PKCS8PrivKeyInfoPtr(d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, keyData.size())); + if (!p8inf) + return nullptr; + if (ptr - keyData.data() != (ptrdiff_t)keyData.size()) + return nullptr; + + auto pkey = EvpPKeyPtr(EVP_PKCS82PKEY(p8inf.get())); + if (!pkey || EVP_PKEY_base_id(pkey.get()) != EVP_PKEY_EC) + return nullptr; + + auto ecKey = EVP_PKEY_get0_EC_KEY(pkey.get()); + if (!ecKey) + return nullptr; + + if (EC_KEY_check_key(ecKey) <= 0) + return nullptr; + + if (!verifyCurve(EC_KEY_get0_group(ecKey), curve)) + return nullptr; + + EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); + + return adoptRef(new CryptoKeyEC(identifier, curve, CryptoKeyType::Private, WTFMove(pkey), extractable, usages)); +} + +Vector<uint8_t> CryptoKeyEC::platformExportRaw() const +{ + EC_KEY* key = EVP_PKEY_get0_EC_KEY(platformKey()); + if (!key) + return { }; + + const EC_POINT* point = EC_KEY_get0_public_key(key); + const EC_GROUP* group = EC_KEY_get0_group(key); + size_t keyDataSize = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr); + if (!keyDataSize) + return { }; + + Vector<uint8_t> keyData(keyDataSize); + if (EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, keyData.data(), keyData.size(), nullptr) != keyDataSize) + return { }; + + return keyData; +} + +bool CryptoKeyEC::platformAddFieldElements(JsonWebKey& jwk) const +{ + size_t keySizeInBytes = (keySizeInBits() + 7) / 8; + + EC_KEY* key = EVP_PKEY_get0_EC_KEY(platformKey()); + if (!key) + return false; + + const EC_POINT* publicKey = EC_KEY_get0_public_key(key); + if (publicKey) { + auto ctx = BNCtxPtr(BN_CTX_new()); + auto x = BIGNUMPtr(BN_new()); + auto y = BIGNUMPtr(BN_new()); + if (1 == EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key), publicKey, x.get(), y.get(), ctx.get())) { + jwk.x = base64URLEncodeToString(convertToBytesExpand(x.get(), keySizeInBytes)); + jwk.y = base64URLEncodeToString(convertToBytesExpand(y.get(), keySizeInBytes)); + } + } + + if (type() == Type::Private) { + const BIGNUM* privateKey = EC_KEY_get0_private_key(key); + if (privateKey) + jwk.d = base64URLEncodeToString(convertToBytes(privateKey)); + } + return true; +} + +Vector<uint8_t> CryptoKeyEC::platformExportSpki() const +{ + if (type() != CryptoKeyType::Public) + return { }; + + int len = i2d_PUBKEY(platformKey(), nullptr); + if (len < 0) + return { }; + + Vector<uint8_t> keyData(len); + auto ptr = keyData.data(); + if (i2d_PUBKEY(platformKey(), &ptr) < 0) + return { }; + + return keyData; +} + +Vector<uint8_t> CryptoKeyEC::platformExportPkcs8() const +{ + if (type() != CryptoKeyType::Private) + return { }; + + auto p8inf = PKCS8PrivKeyInfoPtr(EVP_PKEY2PKCS8(platformKey())); + if (!p8inf) + return { }; + + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf.get(), nullptr); + if (len < 0) + return { }; + + Vector<uint8_t> keyData(len); + auto ptr = keyData.data(); + if (i2d_PKCS8_PRIV_KEY_INFO(p8inf.get(), &ptr) < 0) + return { }; + + return keyData; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyFormat.h b/src/bun.js/bindings/webcrypto/CryptoKeyFormat.h new file mode 100644 index 000000000..2bf7faeff --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyFormat.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +enum class CryptoKeyFormat { + Raw, + Spki, + Pkcs8, + Jwk +}; + +} + +#endif diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.cpp new file mode 100644 index 000000000..aafb3b2fe --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2013 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 "CryptoKeyHMAC.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmHmacKeyParams.h" +#include "CryptoAlgorithmRegistry.h" +#include "ExceptionOr.h" +#include "JsonWebKey.h" +#include <wtf/text/Base64.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +static size_t getKeyLengthFromHash(CryptoAlgorithmIdentifier hash) +{ + switch (hash) { + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + return 512; + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + return 1024; + default: + ASSERT_NOT_REACHED(); + return 0; + } +} + +CryptoKeyHMAC::CryptoKeyHMAC(const Vector<uint8_t>& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usage) + : CryptoKey(CryptoAlgorithmIdentifier::HMAC, CryptoKeyType::Secret, extractable, usage) + , m_hash(hash) + , m_key(key) +{ +} + +CryptoKeyHMAC::CryptoKeyHMAC(Vector<uint8_t>&& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usage) + : CryptoKey(CryptoAlgorithmIdentifier::HMAC, CryptoKeyType::Secret, extractable, usage) + , m_hash(hash) + , m_key(WTFMove(key)) +{ +} + +CryptoKeyHMAC::~CryptoKeyHMAC() = default; + +RefPtr<CryptoKeyHMAC> CryptoKeyHMAC::generate(size_t lengthBits, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usages) +{ + if (!lengthBits) { + lengthBits = getKeyLengthFromHash(hash); + if (!lengthBits) + return nullptr; + } + // CommonHMAC only supports key length that is a multiple of 8. Therefore, here we are a little bit different + // from the spec as of 11 December 2014: https://www.w3.org/TR/WebCryptoAPI/#hmac-operations + if (lengthBits % 8) + return nullptr; + + return adoptRef(new CryptoKeyHMAC(randomData(lengthBits / 8), hash, extractable, usages)); +} + +RefPtr<CryptoKeyHMAC> CryptoKeyHMAC::importRaw(size_t lengthBits, CryptoAlgorithmIdentifier hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + size_t length = keyData.size() * 8; + if (!length) + return nullptr; + // CommonHMAC only supports key length that is a multiple of 8. Therefore, here we are a little bit different + // from the spec as of 11 December 2014: https://www.w3.org/TR/WebCryptoAPI/#hmac-operations + if (lengthBits && lengthBits != length) + return nullptr; + + return adoptRef(new CryptoKeyHMAC(WTFMove(keyData), hash, extractable, usages)); +} + +RefPtr<CryptoKeyHMAC> CryptoKeyHMAC::importJwk(size_t lengthBits, CryptoAlgorithmIdentifier hash, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages, CheckAlgCallback&& callback) +{ + if (keyData.kty != "oct"_s) + return nullptr; + if (keyData.k.isNull()) + return nullptr; + auto octetSequence = base64URLDecode(keyData.k); + if (!octetSequence) + return nullptr; + if (!callback(hash, keyData.alg)) + return nullptr; + if (usages && !keyData.use.isNull() && keyData.use != "sig"_s) + return nullptr; + if (keyData.key_ops && ((keyData.usages & usages) != usages)) + return nullptr; + if (keyData.ext && !keyData.ext.value() && extractable) + return nullptr; + + return CryptoKeyHMAC::importRaw(lengthBits, hash, WTFMove(*octetSequence), extractable, usages); +} + +JsonWebKey CryptoKeyHMAC::exportJwk() const +{ + JsonWebKey result; + result.kty = "oct"_s; + result.k = base64URLEncodeToString(m_key); + result.key_ops = usages(); + result.ext = extractable(); + return result; +} + +ExceptionOr<size_t> CryptoKeyHMAC::getKeyLength(const CryptoAlgorithmParameters& parameters) +{ + auto& aesParameters = downcast<CryptoAlgorithmHmacKeyParams>(parameters); + + size_t result = aesParameters.length ? *(aesParameters.length) : getKeyLengthFromHash(aesParameters.hashIdentifier); + if (result) + return result; + + return Exception { TypeError }; +} + +auto CryptoKeyHMAC::algorithm() const -> KeyAlgorithm +{ + CryptoHmacKeyAlgorithm result; + result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()); + result.hash.name = CryptoAlgorithmRegistry::singleton().name(m_hash); + result.length = m_key.size() * 8; + return result; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.h b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.h new file mode 100644 index 000000000..0c7ba38cb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKey.h" +#include "ExceptionOr.h" +#include <wtf/Function.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class CryptoAlgorithmParameters; +struct JsonWebKey; + +class CryptoKeyHMAC final : public CryptoKey { +public: + static Ref<CryptoKeyHMAC> create(const Vector<uint8_t>& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usage) + { + return adoptRef(*new CryptoKeyHMAC(key, hash, extractable, usage)); + } + virtual ~CryptoKeyHMAC(); + + static RefPtr<CryptoKeyHMAC> generate(size_t lengthBits, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyHMAC> importRaw(size_t lengthBits, CryptoAlgorithmIdentifier hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + using CheckAlgCallback = Function<bool(CryptoAlgorithmIdentifier, const String&)>; + static RefPtr<CryptoKeyHMAC> importJwk(size_t lengthBits, CryptoAlgorithmIdentifier hash, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap, CheckAlgCallback&&); + + CryptoKeyClass keyClass() const final { return CryptoKeyClass::HMAC; } + + const Vector<uint8_t>& key() const { return m_key; } + JsonWebKey exportJwk() const; + + CryptoAlgorithmIdentifier hashAlgorithmIdentifier() const { return m_hash; } + + static ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&); + +private: + CryptoKeyHMAC(const Vector<uint8_t>& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap); + CryptoKeyHMAC(Vector<uint8_t>&& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap); + + KeyAlgorithm algorithm() const final; + + CryptoAlgorithmIdentifier m_hash; + Vector<uint8_t> m_key; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_KEY(CryptoKeyHMAC, CryptoKeyClass::HMAC) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyPair.h b/src/bun.js/bindings/webcrypto/CryptoKeyPair.h new file mode 100644 index 000000000..29630ca0c --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyPair.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include <wtf/RefPtr.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKey; + +struct CryptoKeyPair { + RefPtr<CryptoKey> publicKey; + RefPtr<CryptoKey> privateKey; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyPair.idl b/src/bun.js/bindings/webcrypto/CryptoKeyPair.idl new file mode 100644 index 000000000..bf3e48839 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyPair.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013-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. + */ + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject +] dictionary CryptoKeyPair { + CryptoKey publicKey; + CryptoKey privateKey; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp new file mode 100644 index 000000000..273218721 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp @@ -0,0 +1,178 @@ +/* + * 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 "CryptoKeyRSA.h" + +#include "CryptoKeyRSAComponents.h" +#include "JsonWebKey.h" +#include <wtf/text/Base64.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +RefPtr<CryptoKeyRSA> CryptoKeyRSA::importJwk(CryptoAlgorithmIdentifier algorithm, std::optional<CryptoAlgorithmIdentifier> hash, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + if (keyData.kty != "RSA"_s) + return nullptr; + if (keyData.key_ops && ((keyData.usages & usages) != usages)) + return nullptr; + if (keyData.ext && !keyData.ext.value() && extractable) + return nullptr; + + if (keyData.n.isNull() || keyData.e.isNull()) + return nullptr; + auto modulus = base64URLDecode(keyData.n); + if (!modulus) + return nullptr; + // Per RFC 7518 Section 6.3.1.1: https://tools.ietf.org/html/rfc7518#section-6.3.1.1 + if (!modulus->isEmpty() && !modulus->at(0)) + modulus->remove(0); + auto exponent = base64URLDecode(keyData.e); + if (!exponent) + return nullptr; + if (keyData.d.isNull()) { + // import public key + auto publicKeyComponents = CryptoKeyRSAComponents::createPublic(WTFMove(*modulus), WTFMove(*exponent)); + // Notice: CryptoAlgorithmIdentifier::SHA_1 is just a placeholder. It should not have any effect if hash is std::nullopt. + return CryptoKeyRSA::create(algorithm, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, *publicKeyComponents, extractable, usages); + } + + // import private key + auto privateExponent = base64URLDecode(keyData.d); + if (!privateExponent) + return nullptr; + if (keyData.p.isNull() && keyData.q.isNull() && keyData.dp.isNull() && keyData.dp.isNull() && keyData.qi.isNull()) { + auto privateKeyComponents = CryptoKeyRSAComponents::createPrivate(WTFMove(*modulus), WTFMove(*exponent), WTFMove(*privateExponent)); + // Notice: CryptoAlgorithmIdentifier::SHA_1 is just a placeholder. It should not have any effect if hash is std::nullopt. + return CryptoKeyRSA::create(algorithm, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, *privateKeyComponents, extractable, usages); + } + + if (keyData.p.isNull() || keyData.q.isNull() || keyData.dp.isNull() || keyData.dq.isNull() || keyData.qi.isNull()) + return nullptr; + + auto firstPrimeFactor = base64URLDecode(keyData.p); + if (!firstPrimeFactor) + return nullptr; + auto firstFactorCRTExponent = base64URLDecode(keyData.dp); + if (!firstFactorCRTExponent) + return nullptr; + auto secondPrimeFactor = base64URLDecode(keyData.q); + if (!secondPrimeFactor) + return nullptr; + auto secondFactorCRTExponent = base64URLDecode(keyData.dq); + if (!secondFactorCRTExponent) + return nullptr; + auto secondFactorCRTCoefficient = base64URLDecode(keyData.qi); + if (!secondFactorCRTCoefficient) + return nullptr; + + CryptoKeyRSAComponents::PrimeInfo firstPrimeInfo; + firstPrimeInfo.primeFactor = WTFMove(*firstPrimeFactor); + firstPrimeInfo.factorCRTExponent = WTFMove(*firstFactorCRTExponent); + + CryptoKeyRSAComponents::PrimeInfo secondPrimeInfo; + secondPrimeInfo.primeFactor = WTFMove(*secondPrimeFactor); + secondPrimeInfo.factorCRTExponent = WTFMove(*secondFactorCRTExponent); + secondPrimeInfo.factorCRTCoefficient = WTFMove(*secondFactorCRTCoefficient); + + if (!keyData.oth) { + auto privateKeyComponents = CryptoKeyRSAComponents::createPrivateWithAdditionalData(WTFMove(*modulus), WTFMove(*exponent), WTFMove(*privateExponent), WTFMove(firstPrimeInfo), WTFMove(secondPrimeInfo), { }); + // Notice: CryptoAlgorithmIdentifier::SHA_1 is just a placeholder. It should not have any effect if hash is std::nullopt. + return CryptoKeyRSA::create(algorithm, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, *privateKeyComponents, extractable, usages); + } + + Vector<CryptoKeyRSAComponents::PrimeInfo> otherPrimeInfos; + for (const auto& value : keyData.oth.value()) { + auto primeFactor = base64URLDecode(value.r); + if (!primeFactor) + return nullptr; + auto factorCRTExponent = base64URLDecode(value.d); + if (!factorCRTExponent) + return nullptr; + auto factorCRTCoefficient = base64URLDecode(value.t); + if (!factorCRTCoefficient) + return nullptr; + + CryptoKeyRSAComponents::PrimeInfo info; + info.primeFactor = WTFMove(*primeFactor); + info.factorCRTExponent = WTFMove(*factorCRTExponent); + info.factorCRTCoefficient = WTFMove(*factorCRTCoefficient); + + otherPrimeInfos.append(WTFMove(info)); + } + + auto privateKeyComponents = CryptoKeyRSAComponents::createPrivateWithAdditionalData(WTFMove(*modulus), WTFMove(*exponent), WTFMove(*privateExponent), WTFMove(firstPrimeInfo), WTFMove(secondPrimeInfo), WTFMove(otherPrimeInfos)); + // Notice: CryptoAlgorithmIdentifier::SHA_1 is just a placeholder. It should not have any effect if hash is std::nullopt. + return CryptoKeyRSA::create(algorithm, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, *privateKeyComponents, extractable, usages); +} + +JsonWebKey CryptoKeyRSA::exportJwk() const +{ + JsonWebKey result; + result.kty = "RSA"_s; + result.key_ops = usages(); + result.ext = extractable(); + + auto rsaComponents = exportData(); + + if (!rsaComponents) + return result; + + // public key + result.n = base64URLEncodeToString(rsaComponents->modulus()); + result.e = base64URLEncodeToString(rsaComponents->exponent()); + if (rsaComponents->type() == CryptoKeyRSAComponents::Type::Public) + return result; + + // private key + result.d = base64URLEncodeToString(rsaComponents->privateExponent()); + if (!rsaComponents->hasAdditionalPrivateKeyParameters()) + return result; + + result.p = base64URLEncodeToString(rsaComponents->firstPrimeInfo().primeFactor); + result.q = base64URLEncodeToString(rsaComponents->secondPrimeInfo().primeFactor); + result.dp = base64URLEncodeToString(rsaComponents->firstPrimeInfo().factorCRTExponent); + result.dq = base64URLEncodeToString(rsaComponents->secondPrimeInfo().factorCRTExponent); + result.qi = base64URLEncodeToString(rsaComponents->secondPrimeInfo().factorCRTCoefficient); + if (rsaComponents->otherPrimeInfos().isEmpty()) + return result; + + Vector<RsaOtherPrimesInfo> oth; + for (const auto& info : rsaComponents->otherPrimeInfos()) { + RsaOtherPrimesInfo otherInfo; + otherInfo.r = base64URLEncodeToString(info.primeFactor); + otherInfo.d = base64URLEncodeToString(info.factorCRTExponent); + otherInfo.t = base64URLEncodeToString(info.factorCRTCoefficient); + oth.append(WTFMove(otherInfo)); + } + result.oth = WTFMove(oth); + return result; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRSA.h b/src/bun.js/bindings/webcrypto/CryptoKeyRSA.h new file mode 100644 index 000000000..70f9cf648 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRSA.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2013-2019 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CryptoKey.h" +#include "ExceptionOr.h" +#include <wtf/Function.h> + +#if ENABLE(WEB_CRYPTO) + +#if 0 +#include "CommonCryptoUtilities.h" + +typedef CCRSACryptorRef PlatformRSAKey; +namespace WebCore { +struct CCRSACryptorRefDeleter { + void operator()(CCRSACryptorRef key) const { CCRSACryptorRelease(key); } +}; +} +typedef std::unique_ptr<typename std::remove_pointer<CCRSACryptorRef>::type, WebCore::CCRSACryptorRefDeleter> PlatformRSAKeyContainer; +#endif + +#if USE(GCRYPT) +#include <pal/crypto/gcrypt/Handle.h> + +typedef gcry_sexp_t PlatformRSAKey; +typedef std::unique_ptr<typename std::remove_pointer<gcry_sexp_t>::type, PAL::GCrypt::HandleDeleter<gcry_sexp_t>> PlatformRSAKeyContainer; +#endif + +#if USE(OPENSSL) +#include "OpenSSLCryptoUniquePtr.h" +typedef EVP_PKEY* PlatformRSAKey; +typedef WebCore::EvpPKeyPtr PlatformRSAKeyContainer; +#endif + +namespace WebCore { + +class CryptoKeyRSAComponents; +class PromiseWrapper; +class ScriptExecutionContext; + +struct CryptoKeyPair; +struct JsonWebKey; + +class CryptoKeyRSA final : public CryptoKey { +public: + static Ref<CryptoKeyRSA> create(CryptoAlgorithmIdentifier identifier, CryptoAlgorithmIdentifier hash, bool hasHash, CryptoKeyType type, PlatformRSAKeyContainer&& platformKey, bool extractable, CryptoKeyUsageBitmap usage) + { + return adoptRef(*new CryptoKeyRSA(identifier, hash, hasHash, type, WTFMove(platformKey), extractable, usage)); + } + static RefPtr<CryptoKeyRSA> create(CryptoAlgorithmIdentifier, CryptoAlgorithmIdentifier hash, bool hasHash, const CryptoKeyRSAComponents&, bool extractable, CryptoKeyUsageBitmap); + virtual ~CryptoKeyRSA() = default; + + bool isRestrictedToHash(CryptoAlgorithmIdentifier&) const; + + size_t keySizeInBits() const; + + using KeyPairCallback = Function<void(CryptoKeyPair&&)>; + using VoidCallback = Function<void()>; + static void generatePair(CryptoAlgorithmIdentifier, CryptoAlgorithmIdentifier hash, bool hasHash, unsigned modulusLength, const Vector<uint8_t>& publicExponent, bool extractable, CryptoKeyUsageBitmap, KeyPairCallback&&, VoidCallback&& failureCallback, ScriptExecutionContext*); + static RefPtr<CryptoKeyRSA> importJwk(CryptoAlgorithmIdentifier, std::optional<CryptoAlgorithmIdentifier> hash, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyRSA> importSpki(CryptoAlgorithmIdentifier, std::optional<CryptoAlgorithmIdentifier> hash, Vector<uint8_t>&&, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyRSA> importPkcs8(CryptoAlgorithmIdentifier, std::optional<CryptoAlgorithmIdentifier> hash, Vector<uint8_t>&&, bool extractable, CryptoKeyUsageBitmap); + + PlatformRSAKey platformKey() const { return m_platformKey.get(); } + JsonWebKey exportJwk() const; + ExceptionOr<Vector<uint8_t>> exportSpki() const; + ExceptionOr<Vector<uint8_t>> exportPkcs8() const; + + std::unique_ptr<CryptoKeyRSAComponents> exportData() const; + + CryptoAlgorithmIdentifier hashAlgorithmIdentifier() const { return m_hash; } + +private: + CryptoKeyRSA(CryptoAlgorithmIdentifier, CryptoAlgorithmIdentifier hash, bool hasHash, CryptoKeyType, PlatformRSAKeyContainer&&, bool extractable, CryptoKeyUsageBitmap); + + CryptoKeyClass keyClass() const final { return CryptoKeyClass::RSA; } + + KeyAlgorithm algorithm() const final; + + PlatformRSAKeyContainer m_platformKey; + + bool m_restrictedToSpecificHash; + CryptoAlgorithmIdentifier m_hash; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_KEY(CryptoKeyRSA, CryptoKeyClass::RSA) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRSAComponents.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyRSAComponents.cpp new file mode 100644 index 000000000..f9b6052cd --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRSAComponents.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2013 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 "CryptoKeyRSAComponents.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +CryptoKeyRSAComponents::CryptoKeyRSAComponents(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent) + : m_type(Type::Public) + , m_modulus(modulus) + , m_exponent(exponent) +{ +} + +CryptoKeyRSAComponents::CryptoKeyRSAComponents(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent) + : m_type(Type::Public) + , m_modulus(WTFMove(modulus)) + , m_exponent(WTFMove(exponent)) +{ +} + +CryptoKeyRSAComponents::CryptoKeyRSAComponents(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent, const Vector<uint8_t>& privateExponent) + : m_type(Type::Private) + , m_modulus(modulus) + , m_exponent(exponent) + , m_privateExponent(privateExponent) + , m_hasAdditionalPrivateKeyParameters(false) +{ +} + +CryptoKeyRSAComponents::CryptoKeyRSAComponents(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent, Vector<uint8_t>&& privateExponent) + : m_type(Type::Private) + , m_modulus(WTFMove(modulus)) + , m_exponent(WTFMove(exponent)) + , m_privateExponent(WTFMove(privateExponent)) + , m_hasAdditionalPrivateKeyParameters(false) +{ +} + +CryptoKeyRSAComponents::CryptoKeyRSAComponents(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent, const Vector<uint8_t>& privateExponent, const PrimeInfo& firstPrimeInfo, const PrimeInfo& secondPrimeInfo, const Vector<PrimeInfo>& otherPrimeInfos) + : m_type(Type::Private) + , m_modulus(modulus) + , m_exponent(exponent) + , m_privateExponent(privateExponent) + , m_hasAdditionalPrivateKeyParameters(true) + , m_firstPrimeInfo(firstPrimeInfo) + , m_secondPrimeInfo(secondPrimeInfo) + , m_otherPrimeInfos(otherPrimeInfos) +{ +} + +CryptoKeyRSAComponents::CryptoKeyRSAComponents(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent, Vector<uint8_t>&& privateExponent, PrimeInfo&& firstPrimeInfo, PrimeInfo&& secondPrimeInfo, Vector<PrimeInfo>&& otherPrimeInfos) + : m_type(Type::Private) + , m_modulus(WTFMove(modulus)) + , m_exponent(WTFMove(exponent)) + , m_privateExponent(WTFMove(privateExponent)) + , m_hasAdditionalPrivateKeyParameters(true) + , m_firstPrimeInfo(WTFMove(firstPrimeInfo)) + , m_secondPrimeInfo(WTFMove(secondPrimeInfo)) + , m_otherPrimeInfos(WTFMove(otherPrimeInfos)) +{ +} + +CryptoKeyRSAComponents::~CryptoKeyRSAComponents() = default; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRSAComponents.h b/src/bun.js/bindings/webcrypto/CryptoKeyRSAComponents.h new file mode 100644 index 000000000..26ed55c4e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRSAComponents.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKeyRSAComponents { +public: + enum class Type { + Public, + Private + }; + + struct PrimeInfo { + Vector<uint8_t> primeFactor; + Vector<uint8_t> factorCRTExponent; + Vector<uint8_t> factorCRTCoefficient; + }; + + static std::unique_ptr<CryptoKeyRSAComponents> createPublic(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent) + { + return std::unique_ptr<CryptoKeyRSAComponents>(new CryptoKeyRSAComponents(modulus, exponent)); + } + static std::unique_ptr<CryptoKeyRSAComponents> createPublic(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent) + { + return std::unique_ptr<CryptoKeyRSAComponents>(new CryptoKeyRSAComponents(WTFMove(modulus), WTFMove(exponent))); + } + + static std::unique_ptr<CryptoKeyRSAComponents> createPrivate(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent, const Vector<uint8_t>& privateExponent) + { + return std::unique_ptr<CryptoKeyRSAComponents>(new CryptoKeyRSAComponents(modulus, exponent, privateExponent)); + } + static std::unique_ptr<CryptoKeyRSAComponents> createPrivate(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent, Vector<uint8_t>&& privateExponent) + { + return std::unique_ptr<CryptoKeyRSAComponents>(new CryptoKeyRSAComponents(WTFMove(modulus), WTFMove(exponent), WTFMove(privateExponent))); + } + + static std::unique_ptr<CryptoKeyRSAComponents> createPrivateWithAdditionalData(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent, const Vector<uint8_t>& privateExponent, const PrimeInfo& firstPrimeInfo, const PrimeInfo& secondPrimeInfo, const Vector<PrimeInfo>& otherPrimeInfos) + { + return std::unique_ptr<CryptoKeyRSAComponents>(new CryptoKeyRSAComponents(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos)); + } + static std::unique_ptr<CryptoKeyRSAComponents> createPrivateWithAdditionalData(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent, Vector<uint8_t>&& privateExponent, PrimeInfo&& firstPrimeInfo, PrimeInfo&& secondPrimeInfo, Vector<PrimeInfo>&& otherPrimeInfos) + { + return std::unique_ptr<CryptoKeyRSAComponents>(new CryptoKeyRSAComponents(WTFMove(modulus), WTFMove(exponent), WTFMove(privateExponent), WTFMove(firstPrimeInfo), WTFMove(secondPrimeInfo), WTFMove(otherPrimeInfos))); + } + + virtual ~CryptoKeyRSAComponents(); + + Type type() const { return m_type; } + + // Private and public keys. + const Vector<uint8_t>& modulus() const { return m_modulus; } + const Vector<uint8_t>& exponent() const { return m_exponent; } + + // Only private keys. + const Vector<uint8_t>& privateExponent() const { return m_privateExponent; } + bool hasAdditionalPrivateKeyParameters() const { return m_hasAdditionalPrivateKeyParameters; } + const PrimeInfo& firstPrimeInfo() const { return m_firstPrimeInfo; } + const PrimeInfo& secondPrimeInfo() const { return m_secondPrimeInfo; } + const Vector<PrimeInfo>& otherPrimeInfos() const { return m_otherPrimeInfos; } + +private: + CryptoKeyRSAComponents(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent); + CryptoKeyRSAComponents(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent); + + CryptoKeyRSAComponents(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent, const Vector<uint8_t>& privateExponent); + CryptoKeyRSAComponents(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent, Vector<uint8_t>&& privateExponent); + + CryptoKeyRSAComponents(const Vector<uint8_t>& modulus, const Vector<uint8_t>& exponent, const Vector<uint8_t>& privateExponent, const PrimeInfo& firstPrimeInfo, const PrimeInfo& secondPrimeInfo, const Vector<PrimeInfo>& otherPrimeInfos); + CryptoKeyRSAComponents(Vector<uint8_t>&& modulus, Vector<uint8_t>&& exponent, Vector<uint8_t>&& privateExponent, PrimeInfo&& firstPrimeInfo, PrimeInfo&& secondPrimeInfo, Vector<PrimeInfo>&& otherPrimeInfos); + + Type m_type; + + // Private and public keys. + Vector<uint8_t> m_modulus; + Vector<uint8_t> m_exponent; + + // Only private keys. + Vector<uint8_t> m_privateExponent; + bool m_hasAdditionalPrivateKeyParameters; + PrimeInfo m_firstPrimeInfo; + PrimeInfo m_secondPrimeInfo; + Vector<PrimeInfo> m_otherPrimeInfos; // When three or more primes have been used, the number of array elements is be the number of primes used minus two. +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRSAOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyRSAOpenSSL.cpp new file mode 100644 index 000000000..ef4794e36 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRSAOpenSSL.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2021 Sony Interactive Entertainment Inc. + * + * 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 "CryptoKeyRSA.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRegistry.h" +#include "CryptoKeyPair.h" +#include "CryptoKeyRSAComponents.h" +#include "OpenSSLUtilities.h" +#include <JavaScriptCore/TypedArrayInlines.h> +#include <openssl/x509.h> +#include <openssl/evp.h> + +namespace WebCore { + +static size_t getRSAModulusLength(RSA* rsa) +{ + if (!rsa) + return 0; + return RSA_size(rsa) * 8; +} + +RefPtr<CryptoKeyRSA> CryptoKeyRSA::create(CryptoAlgorithmIdentifier identifier, CryptoAlgorithmIdentifier hash, bool hasHash, const CryptoKeyRSAComponents& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + CryptoKeyType keyType; + switch (keyData.type()) { + case CryptoKeyRSAComponents::Type::Public: + keyType = CryptoKeyType::Public; + break; + case CryptoKeyRSAComponents::Type::Private: + keyType = CryptoKeyType::Private; + break; + default: + return nullptr; + } + + // When creating a private key, we require the p and q prime information. + if (keyType == CryptoKeyType::Private && !keyData.hasAdditionalPrivateKeyParameters()) + return nullptr; + + // But we don't currently support creating keys with any additional prime information. + if (!keyData.otherPrimeInfos().isEmpty()) + return nullptr; + + // For both public and private keys, we need the public modulus and exponent. + if (keyData.modulus().isEmpty() || keyData.exponent().isEmpty()) + return nullptr; + + // For private keys, we require the private exponent, as well as p and q prime information. + if (keyType == CryptoKeyType::Private) { + if (keyData.privateExponent().isEmpty() || keyData.firstPrimeInfo().primeFactor.isEmpty() || keyData.secondPrimeInfo().primeFactor.isEmpty()) + return nullptr; + } + + auto rsa = RSAPtr(RSA_new()); + if (!rsa) + return nullptr; + + auto n = convertToBigNumber(keyData.modulus()); + auto e = convertToBigNumber(keyData.exponent()); + if (!n || !e) + return nullptr; + + // Calling with d null is fine as long as n and e are not null + if (!RSA_set0_key(rsa.get(), n.get(), e.get(), nullptr)) + return nullptr; + + // Ownership transferred to OpenSSL + n.release(); + e.release(); + + if (keyType == CryptoKeyType::Private) { + auto d = convertToBigNumber(keyData.privateExponent()); + if (!d) + return nullptr; + + // Calling with n and e null is fine as long as they were set prior + if (!RSA_set0_key(rsa.get(), nullptr, nullptr, d.get())) + return nullptr; + + // Ownership transferred to OpenSSL + d.release(); + + auto p = convertToBigNumber(keyData.firstPrimeInfo().primeFactor); + auto q = convertToBigNumber(keyData.secondPrimeInfo().primeFactor); + if (!p || !q) + return nullptr; + + if (!RSA_set0_factors(rsa.get(), p.get(), q.get())) + return nullptr; + + // Ownership transferred to OpenSSL + p.release(); + q.release(); + + // We set dmp1, dmpq1, and iqmp member of the RSA struct if the keyData has corresponding data. + + // dmp1 -- d mod (p - 1) + auto dmp1 = (!keyData.firstPrimeInfo().factorCRTExponent.isEmpty()) ? convertToBigNumber(keyData.firstPrimeInfo().factorCRTExponent) : nullptr; + // dmq1 -- d mod (q - 1) + auto dmq1 = (!keyData.secondPrimeInfo().factorCRTExponent.isEmpty()) ? convertToBigNumber(keyData.secondPrimeInfo().factorCRTExponent) : nullptr; + // iqmp -- q^(-1) mod p + auto iqmp = (!keyData.secondPrimeInfo().factorCRTCoefficient.isEmpty()) ? convertToBigNumber(keyData.secondPrimeInfo().factorCRTCoefficient) : nullptr; + + if (!RSA_set0_crt_params(rsa.get(), dmp1.get(), dmq1.get(), iqmp.get())) + return nullptr; + + // Ownership transferred to OpenSSL + dmp1.release(); + dmq1.release(); + iqmp.release(); + } + + auto pkey = EvpPKeyPtr(EVP_PKEY_new()); + if (!pkey) + return nullptr; + + if (EVP_PKEY_set1_RSA(pkey.get(), rsa.get()) != 1) + return nullptr; + + return adoptRef(new CryptoKeyRSA(identifier, hash, hasHash, keyType, WTFMove(pkey), extractable, usages)); +} + +CryptoKeyRSA::CryptoKeyRSA(CryptoAlgorithmIdentifier identifier, CryptoAlgorithmIdentifier hash, bool hasHash, CryptoKeyType type, PlatformRSAKeyContainer&& platformKey, bool extractable, CryptoKeyUsageBitmap usages) + : CryptoKey(identifier, type, extractable, usages) + , m_platformKey(WTFMove(platformKey)) + , m_restrictedToSpecificHash(hasHash) + , m_hash(hash) +{ +} + +bool CryptoKeyRSA::isRestrictedToHash(CryptoAlgorithmIdentifier& identifier) const +{ + if (!m_restrictedToSpecificHash) + return false; + + identifier = m_hash; + return true; +} + +size_t CryptoKeyRSA::keySizeInBits() const +{ + RSA* rsa = EVP_PKEY_get0_RSA(m_platformKey.get()); + if (!rsa) + return 0; + + return getRSAModulusLength(rsa); +} + +// Convert the exponent vector to a 32-bit value, if possible. +static std::optional<uint32_t> exponentVectorToUInt32(const Vector<uint8_t>& exponent) +{ + if (exponent.size() > 4) { + if (std::any_of(exponent.begin(), exponent.end() - 4, [](uint8_t element) { return !!element; })) + return std::nullopt; + } + + uint32_t result = 0; + for (size_t size = exponent.size(), i = std::min<size_t>(4, size); i > 0; --i) { + result <<= 8; + result += exponent[size - i]; + } + + return result; +} + +void CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier algorithm, CryptoAlgorithmIdentifier hash, bool hasHash, unsigned modulusLength, const Vector<uint8_t>& publicExponent, bool extractable, CryptoKeyUsageBitmap usages, KeyPairCallback&& callback, VoidCallback&& failureCallback, ScriptExecutionContext*) +{ + // OpenSSL doesn't report an error if the exponent is smaller than three or even. + auto e = exponentVectorToUInt32(publicExponent); + if (!e || *e < 3 || !(*e & 0x1)) { + failureCallback(); + return; + } + + auto exponent = convertToBigNumber(publicExponent); + auto privateRSA = RSAPtr(RSA_new()); + if (!exponent || RSA_generate_key_ex(privateRSA.get(), modulusLength, exponent.get(), nullptr) <= 0) { + failureCallback(); + return; + } + + auto publicRSA = RSAPtr(RSAPublicKey_dup(privateRSA.get())); + if (!publicRSA) { + failureCallback(); + return; + } + + auto privatePKey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_RSA(privatePKey.get(), privateRSA.get()) <= 0) { + failureCallback(); + return; + } + + auto publicPKey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_RSA(publicPKey.get(), publicRSA.get()) <= 0) { + failureCallback(); + return; + } + + auto publicKey = CryptoKeyRSA::create(algorithm, hash, hasHash, CryptoKeyType::Public, WTFMove(publicPKey), true, usages); + auto privateKey = CryptoKeyRSA::create(algorithm, hash, hasHash, CryptoKeyType::Private, WTFMove(privatePKey), extractable, usages); + callback(CryptoKeyPair { WTFMove(publicKey), WTFMove(privateKey) }); +} + +RefPtr<CryptoKeyRSA> CryptoKeyRSA::importSpki(CryptoAlgorithmIdentifier identifier, std::optional<CryptoAlgorithmIdentifier> hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + // We need a local pointer variable to pass to d2i (DER to internal) functions(). + const uint8_t* ptr = keyData.data(); + + // We use d2i_PUBKEY() to import a public key. + auto pkey = EvpPKeyPtr(d2i_PUBKEY(nullptr, &ptr, keyData.size())); + if (!pkey || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA) + return nullptr; + + return adoptRef(new CryptoKeyRSA(identifier, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, CryptoKeyType::Public, WTFMove(pkey), extractable, usages)); +} + +RefPtr<CryptoKeyRSA> CryptoKeyRSA::importPkcs8(CryptoAlgorithmIdentifier identifier, std::optional<CryptoAlgorithmIdentifier> hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + // We need a local pointer variable to pass to d2i (DER to internal) functions(). + const uint8_t* ptr = keyData.data(); + + // We use d2i_PKCS8_PRIV_KEY_INFO() to import a private key. + auto p8inf = PKCS8PrivKeyInfoPtr(d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, keyData.size())); + if (!p8inf) + return nullptr; + + auto pkey = EvpPKeyPtr(EVP_PKCS82PKEY(p8inf.get())); + if (!pkey || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA) + return nullptr; + + return adoptRef(new CryptoKeyRSA(identifier, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, CryptoKeyType::Private, WTFMove(pkey), extractable, usages)); +} + +ExceptionOr<Vector<uint8_t>> CryptoKeyRSA::exportSpki() const +{ + if (type() != CryptoKeyType::Public) + return Exception { InvalidAccessError }; + + int len = i2d_PUBKEY(platformKey(), nullptr); + if (len < 0) + return Exception { OperationError }; + + Vector<uint8_t> keyData(len); + auto ptr = keyData.data(); + if (i2d_PUBKEY(platformKey(), &ptr) < 0) + return Exception { OperationError }; + + return keyData; +} + +ExceptionOr<Vector<uint8_t>> CryptoKeyRSA::exportPkcs8() const +{ + if (type() != CryptoKeyType::Private) + return Exception { InvalidAccessError }; + + auto p8inf = PKCS8PrivKeyInfoPtr(EVP_PKEY2PKCS8(platformKey())); + if (!p8inf) + return Exception { OperationError }; + + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf.get(), nullptr); + if (len < 0) + return Exception { OperationError }; + + Vector<uint8_t> keyData(len); + auto ptr = keyData.data(); + if (i2d_PKCS8_PRIV_KEY_INFO(p8inf.get(), &ptr) < 0) + return Exception { OperationError }; + + return keyData; +} + +auto CryptoKeyRSA::algorithm() const -> KeyAlgorithm +{ + RSA* rsa = EVP_PKEY_get0_RSA(platformKey()); + + auto modulusLength = getRSAModulusLength(rsa); + Vector<uint8_t> publicExponent; + + if (rsa) { + const BIGNUM* e; + RSA_get0_key(rsa, nullptr, &e, nullptr); + publicExponent = convertToBytes(e); + } + + if (m_restrictedToSpecificHash) { + CryptoRsaHashedKeyAlgorithm result; + result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()); + result.modulusLength = modulusLength; + result.publicExponent = Uint8Array::tryCreate(publicExponent.data(), publicExponent.size()); + result.hash.name = CryptoAlgorithmRegistry::singleton().name(m_hash); + return result; + } + + CryptoRsaKeyAlgorithm result; + result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()); + result.modulusLength = modulusLength; + result.publicExponent = Uint8Array::tryCreate(publicExponent.data(), publicExponent.size()); + return result; +} + +std::unique_ptr<CryptoKeyRSAComponents> CryptoKeyRSA::exportData() const +{ + RSA* rsa = EVP_PKEY_get0_RSA(platformKey()); + if (!rsa) + return nullptr; + + const BIGNUM* n; + const BIGNUM* e; + const BIGNUM* d; + RSA_get0_key(rsa, &n, &e, &d); + + switch (type()) { + case CryptoKeyType::Public: + // We need the public modulus and exponent for the public key. + if (!n || !e) + return nullptr; + return CryptoKeyRSAComponents::createPublic(convertToBytes(n), convertToBytes(e)); + case CryptoKeyType::Private: { + // We need the public modulus, exponent, and private exponent, as well as p and q prime information. + const BIGNUM* p; + const BIGNUM* q; + RSA_get0_factors(rsa, &p, &q); + + if (!n || !e || !d || !p || !q) + return nullptr; + + CryptoKeyRSAComponents::PrimeInfo firstPrimeInfo; + firstPrimeInfo.primeFactor = convertToBytes(p); + + CryptoKeyRSAComponents::PrimeInfo secondPrimeInfo; + secondPrimeInfo.primeFactor = convertToBytes(q); + + auto context = BNCtxPtr(BN_CTX_new()); + + const BIGNUM* dmp1; + const BIGNUM* dmq1; + const BIGNUM* iqmp; + RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); + + // dmp1 -- d mod (p - 1) + if (dmp1) + firstPrimeInfo.factorCRTExponent = convertToBytes(dmp1); + else { + auto dmp1New = BIGNUMPtr(BN_new()); + auto pm1 = BIGNUMPtr(BN_dup(p)); + if (BN_sub_word(pm1.get(), 1) == 1 && BN_mod(dmp1New.get(), d, pm1.get(), context.get()) == 1) + firstPrimeInfo.factorCRTExponent = convertToBytes(dmp1New.get()); + } + + // dmq1 -- d mod (q - 1) + if (dmq1) + secondPrimeInfo.factorCRTExponent = convertToBytes(dmq1); + else { + auto dmq1New = BIGNUMPtr(BN_new()); + auto qm1 = BIGNUMPtr(BN_dup(q)); + if (BN_sub_word(qm1.get(), 1) == 1 && BN_mod(dmq1New.get(), d, qm1.get(), context.get()) == 1) + secondPrimeInfo.factorCRTExponent = convertToBytes(dmq1New.get()); + } + + // iqmp -- q^(-1) mod p + if (iqmp) + secondPrimeInfo.factorCRTCoefficient = convertToBytes(iqmp); + else { + auto iqmpNew = BIGNUMPtr(BN_mod_inverse(nullptr, q, p, context.get())); + if (iqmpNew) + secondPrimeInfo.factorCRTCoefficient = convertToBytes(iqmpNew.get()); + } + + return CryptoKeyRSAComponents::createPrivateWithAdditionalData( + convertToBytes(n), convertToBytes(e), convertToBytes(d), + WTFMove(firstPrimeInfo), WTFMove(secondPrimeInfo), Vector<CryptoKeyRSAComponents::PrimeInfo> { }); + } + default: + ASSERT_NOT_REACHED(); + return nullptr; + } +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRaw.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyRaw.cpp new file mode 100644 index 000000000..c75684189 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRaw.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 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 "CryptoKeyRaw.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRegistry.h" + +namespace WebCore { + +CryptoKeyRaw::CryptoKeyRaw(CryptoAlgorithmIdentifier identifier, Vector<uint8_t>&& keyData, CryptoKeyUsageBitmap usages) + : CryptoKey(identifier, CryptoKeyType::Secret, false, usages) + , m_key(WTFMove(keyData)) +{ +} + +auto CryptoKeyRaw::algorithm() const -> KeyAlgorithm +{ + CryptoKeyAlgorithm result; + result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()); + return result; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRaw.h b/src/bun.js/bindings/webcrypto/CryptoKeyRaw.h new file mode 100644 index 000000000..df5b6b831 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRaw.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoKey.h" + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +class CryptoKeyRaw final : public CryptoKey { +public: + static Ref<CryptoKeyRaw> create(CryptoAlgorithmIdentifier identifier, Vector<uint8_t>&& keyData, CryptoKeyUsageBitmap usages) + { + return adoptRef(*new CryptoKeyRaw(identifier, WTFMove(keyData), usages)); + } + + const Vector<uint8_t>& key() const { return m_key; } + +private: + CryptoKeyRaw(CryptoAlgorithmIdentifier, Vector<uint8_t>&& keyData, CryptoKeyUsageBitmap); + + CryptoKeyClass keyClass() const final { return CryptoKeyClass::Raw; } + + KeyAlgorithm algorithm() const final; + + Vector<uint8_t> m_key; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CRYPTO_KEY(CryptoKeyRaw, CryptoKeyClass::Raw) + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyType.h b/src/bun.js/bindings/webcrypto/CryptoKeyType.h new file mode 100644 index 000000000..f090806db --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyType.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +enum class CryptoKeyType { + Public, + Private, + Secret +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyUsage.h b/src/bun.js/bindings/webcrypto/CryptoKeyUsage.h new file mode 100644 index 000000000..cfd186f75 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyUsage.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +enum { + CryptoKeyUsageEncrypt = 1 << 0, + CryptoKeyUsageDecrypt = 1 << 1, + CryptoKeyUsageSign = 1 << 2, + CryptoKeyUsageVerify = 1 << 3, + CryptoKeyUsageDeriveKey = 1 << 4, + CryptoKeyUsageDeriveBits = 1 << 5, + CryptoKeyUsageWrapKey = 1 << 6, + CryptoKeyUsageUnwrapKey = 1 << 7 +}; + +typedef int CryptoKeyUsageBitmap; + +// Only for binding purpose. +enum class CryptoKeyUsage { + Encrypt, + Decrypt, + Sign, + Verify, + DeriveKey, + DeriveBits, + WrapKey, + UnwrapKey +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyUsage.idl b/src/bun.js/bindings/webcrypto/CryptoKeyUsage.idl new file mode 100644 index 000000000..a42262deb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoKeyUsage.idl @@ -0,0 +1,37 @@ +/* + * 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. + */ + +[ + Conditional=WEB_CRYPTO, +] enum CryptoKeyUsage { + "encrypt", + "decrypt", + "sign", + "verify", + "deriveKey", + "deriveBits", + "wrapKey", + "unwrapKey" +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoRsaHashedKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoRsaHashedKeyAlgorithm.h new file mode 100644 index 000000000..30109aa90 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoRsaHashedKeyAlgorithm.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoRsaKeyAlgorithm.h" + +namespace WebCore { + +struct CryptoRsaHashedKeyAlgorithm : CryptoRsaKeyAlgorithm { + // The hash algorithm that is used with this key + CryptoKeyAlgorithm hash; +}; + +} + diff --git a/src/bun.js/bindings/webcrypto/CryptoRsaHashedKeyAlgorithm.idl b/src/bun.js/bindings/webcrypto/CryptoRsaHashedKeyAlgorithm.idl new file mode 100644 index 000000000..7541718ec --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoRsaHashedKeyAlgorithm.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 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. + */ + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject +] dictionary CryptoRsaHashedKeyAlgorithm : CryptoRsaKeyAlgorithm { + // The hash algorithm that is used with this key + required CryptoKeyAlgorithm hash; +}; diff --git a/src/bun.js/bindings/webcrypto/CryptoRsaKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoRsaKeyAlgorithm.h new file mode 100644 index 000000000..7723d09f4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoRsaKeyAlgorithm.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 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. + */ + +#pragma once + +#include "CryptoKeyAlgorithm.h" +#include <JavaScriptCore/Uint8Array.h> + +namespace WebCore { + +struct CryptoRsaKeyAlgorithm : CryptoKeyAlgorithm { + // The length, in bits, of the RSA modulus + unsigned modulusLength; + // The RSA public exponent + RefPtr<Uint8Array> publicExponent; +}; + +} + diff --git a/src/bun.js/bindings/webcrypto/CryptoRsaKeyAlgorithm.idl b/src/bun.js/bindings/webcrypto/CryptoRsaKeyAlgorithm.idl new file mode 100644 index 000000000..207315358 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoRsaKeyAlgorithm.idl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 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. + */ + +typedef Uint8Array BigInteger; + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject +] dictionary CryptoRsaKeyAlgorithm : CryptoKeyAlgorithm { + // The length, in bits, of the RSA modulus + required unsigned long modulusLength; + // The RSA public exponent + required BigInteger publicExponent; +}; diff --git a/src/bun.js/bindings/webcrypto/EcKeyParams.idl b/src/bun.js/bindings/webcrypto/EcKeyParams.idl new file mode 100644 index 000000000..97ea4b7a2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/EcKeyParams.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 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. + */ + +// This is a unified dictionary for EcKeyImportParams and EcKeyGenParams. +// https://www.w3.org/TR/WebCryptoAPI/#EcKeyImportParams-dictionary, and +// https://www.w3.org/TR/WebCryptoAPI/#EcKeyGenParams-dictionary +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmEcKeyParams +] dictionary EcKeyParams : CryptoAlgorithmParameters { + required DOMString namedCurve; +}; diff --git a/src/bun.js/bindings/webcrypto/EcdhKeyDeriveParams.idl b/src/bun.js/bindings/webcrypto/EcdhKeyDeriveParams.idl new file mode 100644 index 000000000..568f190cc --- /dev/null +++ b/src/bun.js/bindings/webcrypto/EcdhKeyDeriveParams.idl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 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. + */ + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmEcdhKeyDeriveParams, +] dictionary EcdhKeyDeriveParams : CryptoAlgorithmParameters { + // We should rename this to public once https://bugs.webkit.org/show_bug.cgi?id=169333 is fixed. + // The peer's EC public key. + required CryptoKey publicKey; +}; diff --git a/src/bun.js/bindings/webcrypto/EcdsaParams.idl b/src/bun.js/bindings/webcrypto/EcdsaParams.idl new file mode 100644 index 000000000..5323fccd1 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/EcdsaParams.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 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. + */ + +typedef (object or DOMString) HashAlgorithmIdentifier; + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmEcdsaParams +] dictionary EcdsaParams : CryptoAlgorithmParameters { + // The hash algorithm to use + required HashAlgorithmIdentifier hash; +}; diff --git a/src/bun.js/bindings/webcrypto/HkdfParams.idl b/src/bun.js/bindings/webcrypto/HkdfParams.idl new file mode 100644 index 000000000..651634505 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/HkdfParams.idl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 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. + */ + +typedef (object or DOMString) HashAlgorithmIdentifier; + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmHkdfParams, +] dictionary HkdfParams : CryptoAlgorithmParameters { + // The algorithm to use with HMAC (e.g.: SHA-256) + required HashAlgorithmIdentifier hash; + // A bit string that corresponds to the salt used in the extract step. + required BufferSource salt; + // A bit string that corresponds to the context and application specific context for the derived keying material. + required BufferSource info; +}; diff --git a/src/bun.js/bindings/webcrypto/HmacKeyParams.idl b/src/bun.js/bindings/webcrypto/HmacKeyParams.idl new file mode 100644 index 000000000..d751b9411 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/HmacKeyParams.idl @@ -0,0 +1,41 @@ +/* + * 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. + */ + +typedef (object or DOMString) HashAlgorithmIdentifier; + +// This is a unified dictionary for HmacImportParams and HmacKeyGenParams. +// https://www.w3.org/TR/WebCryptoAPI/#hmac-importparams, and +// https://www.w3.org/TR/WebCryptoAPI/#hmac-keygen-params +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmHmacKeyParams +] dictionary HmacKeyParams : CryptoAlgorithmParameters { + // The inner hash function to use. + required HashAlgorithmIdentifier hash; + // The length (in bits) of the key to generate. If unspecified, the + // recommended length will be used, which is the size of the associated hash function's block + // size. + [EnforceRange] unsigned long length; +}; diff --git a/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp new file mode 100644 index 000000000..af0ddfda7 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp @@ -0,0 +1,85 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSAesCbcCfbParams.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmAesCbcCfbParams convertDictionary<CryptoAlgorithmAesCbcCfbParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmAesCbcCfbParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesCbcCfbParams", "DOMString"); + return { }; + } + JSValue ivValue; + if (isNullOrUndefined) + ivValue = jsUndefined(); + else { + ivValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "iv"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!ivValue.isUndefined()) { + result.iv = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, ivValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iv", "AesCbcCfbParams", "(ArrayBufferView or ArrayBuffer)"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.dep b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.dep new file mode 100644 index 000000000..e8fe070b8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmAesCbcCfbParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.h b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.h new file mode 100644 index 000000000..81a61fc13 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCbcCfbParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmAesCbcCfbParams convertDictionary<CryptoAlgorithmAesCbcCfbParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp b/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp new file mode 100644 index 000000000..97ce6322e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp @@ -0,0 +1,100 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSAesCtrParams.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmAesCtrParams convertDictionary<CryptoAlgorithmAesCtrParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmAesCtrParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesCtrParams", "DOMString"); + return { }; + } + JSValue counterValue; + if (isNullOrUndefined) + counterValue = jsUndefined(); + else { + counterValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "counter"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!counterValue.isUndefined()) { + result.counter = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, counterValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "counter", "AesCtrParams", "(ArrayBufferView or ArrayBuffer)"); + return { }; + } + JSValue lengthValue; + if (isNullOrUndefined) + lengthValue = jsUndefined(); + else { + lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!lengthValue.isUndefined()) { + result.length = convert<IDLEnforceRangeAdaptor<IDLOctet>>(lexicalGlobalObject, lengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "AesCtrParams", "octet"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSAesCtrParams.dep b/src/bun.js/bindings/webcrypto/JSAesCtrParams.dep new file mode 100644 index 000000000..75e3da1b8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesCtrParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmAesCtrParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSAesCtrParams.h b/src/bun.js/bindings/webcrypto/JSAesCtrParams.h new file mode 100644 index 000000000..2e8a66c8e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesCtrParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesCtrParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmAesCtrParams convertDictionary<CryptoAlgorithmAesCtrParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp b/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp new file mode 100644 index 000000000..7e13f82e9 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp @@ -0,0 +1,108 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSAesGcmParams.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmAesGcmParams convertDictionary<CryptoAlgorithmAesGcmParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmAesGcmParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesGcmParams", "DOMString"); + return { }; + } + JSValue additionalDataValue; + if (isNullOrUndefined) + additionalDataValue = jsUndefined(); + else { + additionalDataValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "additionalData"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!additionalDataValue.isUndefined()) { + result.additionalData = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, additionalDataValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue ivValue; + if (isNullOrUndefined) + ivValue = jsUndefined(); + else { + ivValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "iv"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!ivValue.isUndefined()) { + result.iv = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, ivValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iv", "AesGcmParams", "(ArrayBufferView or ArrayBuffer)"); + return { }; + } + JSValue tagLengthValue; + if (isNullOrUndefined) + tagLengthValue = jsUndefined(); + else { + tagLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "tagLength"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!tagLengthValue.isUndefined()) { + result.tagLength = convert<IDLEnforceRangeAdaptor<IDLOctet>>(lexicalGlobalObject, tagLengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSAesGcmParams.dep b/src/bun.js/bindings/webcrypto/JSAesGcmParams.dep new file mode 100644 index 000000000..7ea1a9ef3 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesGcmParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmAesGcmParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSAesGcmParams.h b/src/bun.js/bindings/webcrypto/JSAesGcmParams.h new file mode 100644 index 000000000..56308053a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesGcmParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesGcmParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmAesGcmParams convertDictionary<CryptoAlgorithmAesGcmParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp new file mode 100644 index 000000000..2437d14ea --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp @@ -0,0 +1,83 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSAesKeyParams.h" + +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmAesKeyParams convertDictionary<CryptoAlgorithmAesKeyParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmAesKeyParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesKeyParams", "DOMString"); + return { }; + } + JSValue lengthValue; + if (isNullOrUndefined) + lengthValue = jsUndefined(); + else { + lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!lengthValue.isUndefined()) { + result.length = convert<IDLEnforceRangeAdaptor<IDLUnsignedShort>>(lexicalGlobalObject, lengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "AesKeyParams", "unsigned short"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSAesKeyParams.dep b/src/bun.js/bindings/webcrypto/JSAesKeyParams.dep new file mode 100644 index 000000000..a23ff45ae --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesKeyParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmAesKeyParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSAesKeyParams.h b/src/bun.js/bindings/webcrypto/JSAesKeyParams.h new file mode 100644 index 000000000..0dd7782af --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSAesKeyParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmAesKeyParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmAesKeyParams convertDictionary<CryptoAlgorithmAesKeyParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp new file mode 100644 index 000000000..3f7568947 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp @@ -0,0 +1,101 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoAesKeyAlgorithm.h" + +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAesKeyAlgorithm convertDictionary<CryptoAesKeyAlgorithm>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAesKeyAlgorithm result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoAesKeyAlgorithm", "DOMString"); + return { }; + } + JSValue lengthValue; + if (isNullOrUndefined) + lengthValue = jsUndefined(); + else { + lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!lengthValue.isUndefined()) { + result.length = convert<IDLUnsignedShort>(lexicalGlobalObject, lengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "CryptoAesKeyAlgorithm", "unsigned short"); + return { }; + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const CryptoAesKeyAlgorithm& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + auto nameValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.name); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); + auto lengthValue = toJS<IDLUnsignedShort>(lexicalGlobalObject, throwScope, dictionary.length); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "length"_s), lengthValue); + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.dep b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.dep new file mode 100644 index 000000000..aaea407df --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.dep @@ -0,0 +1,2 @@ +CryptoAesKeyAlgorithm.h : CryptoKeyAlgorithm.idl +CryptoKeyAlgorithm.idl : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.h new file mode 100644 index 000000000..5297bbaf8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAesKeyAlgorithm.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAesKeyAlgorithm convertDictionary<CryptoAesKeyAlgorithm>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const CryptoAesKeyAlgorithm&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp new file mode 100644 index 000000000..298e6afe4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp @@ -0,0 +1,68 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoAlgorithmParameters.h" + +#include "JSDOMConvertStrings.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmParameters convertDictionary<CryptoAlgorithmParameters>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmParameters result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoAlgorithmParameters", "DOMString"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.dep b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.dep new file mode 100644 index 000000000..e638f59cb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.dep @@ -0,0 +1 @@ +CryptoAlgorithmParameters.h : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.h b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.h new file mode 100644 index 000000000..3c0ea58db --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmParameters.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmParameters convertDictionary<CryptoAlgorithmParameters>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp new file mode 100644 index 000000000..e63283c97 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp @@ -0,0 +1,100 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoEcKeyAlgorithm.h" + +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoEcKeyAlgorithm convertDictionary<CryptoEcKeyAlgorithm>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoEcKeyAlgorithm result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoEcKeyAlgorithm", "DOMString"); + return { }; + } + JSValue namedCurveValue; + if (isNullOrUndefined) + namedCurveValue = jsUndefined(); + else { + namedCurveValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "namedCurve"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!namedCurveValue.isUndefined()) { + result.namedCurve = convert<IDLDOMString>(lexicalGlobalObject, namedCurveValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "namedCurve", "CryptoEcKeyAlgorithm", "DOMString"); + return { }; + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const CryptoEcKeyAlgorithm& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + auto nameValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.name); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); + auto namedCurveValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.namedCurve); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "namedCurve"_s), namedCurveValue); + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.dep b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.dep new file mode 100644 index 000000000..789ae54a0 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.dep @@ -0,0 +1,2 @@ +CryptoEcKeyAlgorithm.h : CryptoKeyAlgorithm.idl +CryptoKeyAlgorithm.idl : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.h new file mode 100644 index 000000000..c48a18536 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoEcKeyAlgorithm.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoEcKeyAlgorithm convertDictionary<CryptoEcKeyAlgorithm>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const CryptoEcKeyAlgorithm&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp new file mode 100644 index 000000000..850eeb2aa --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp @@ -0,0 +1,119 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoHmacKeyAlgorithm.h" + +#include "JSCryptoKeyAlgorithm.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoHmacKeyAlgorithm convertDictionary<CryptoHmacKeyAlgorithm>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoHmacKeyAlgorithm result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoHmacKeyAlgorithm", "DOMString"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLDictionary<CryptoKeyAlgorithm>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "CryptoHmacKeyAlgorithm", "CryptoKeyAlgorithm"); + return { }; + } + JSValue lengthValue; + if (isNullOrUndefined) + lengthValue = jsUndefined(); + else { + lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!lengthValue.isUndefined()) { + result.length = convert<IDLUnsignedLong>(lexicalGlobalObject, lengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "CryptoHmacKeyAlgorithm", "unsigned long"); + return { }; + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const CryptoHmacKeyAlgorithm& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + auto nameValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.name); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); + auto hashValue = toJS<IDLDictionary<CryptoKeyAlgorithm>>(lexicalGlobalObject, globalObject, throwScope, dictionary.hash); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "hash"_s), hashValue); + auto lengthValue = toJS<IDLUnsignedLong>(lexicalGlobalObject, throwScope, dictionary.length); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "length"_s), lengthValue); + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.dep b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.dep new file mode 100644 index 000000000..6d506eae2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.dep @@ -0,0 +1,2 @@ +CryptoHmacKeyAlgorithm.h : CryptoKeyAlgorithm.idl +CryptoKeyAlgorithm.idl : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.h new file mode 100644 index 000000000..8d273991d --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoHmacKeyAlgorithm.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoHmacKeyAlgorithm convertDictionary<CryptoHmacKeyAlgorithm>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const CryptoHmacKeyAlgorithm&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp new file mode 100644 index 000000000..dea8e3ff7 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp @@ -0,0 +1,361 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoKey.h" + +#include "ActiveDOMObject.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "JSCryptoAesKeyAlgorithm.h" +#include "JSCryptoEcKeyAlgorithm.h" +#include "JSCryptoHmacKeyAlgorithm.h" +#include "JSCryptoKeyAlgorithm.h" +#include "JSCryptoKeyUsage.h" +#include "JSCryptoRsaHashedKeyAlgorithm.h" +#include "JSCryptoRsaKeyAlgorithm.h" +#include "JSDOMAttribute.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructorNotConstructable.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertDictionary.h" +#include "JSDOMConvertSequences.h" +#include "JSDOMConvertUnion.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMWrapperCache.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include "WebCoreOpaqueRoot.h" +#include <JavaScriptCore/FunctionPrototype.h> +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSArray.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/JSString.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <variant> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/SortedArrayMap.h> +#include <wtf/URL.h> + + +namespace WebCore { +using namespace JSC; + +String convertEnumerationToString(CryptoKey::Type enumerationValue) +{ + static const NeverDestroyed<String> values[] = { + MAKE_STATIC_STRING_IMPL("public"), + MAKE_STATIC_STRING_IMPL("private"), + MAKE_STATIC_STRING_IMPL("secret"), + }; + static_assert(static_cast<size_t>(CryptoKey::Type::Public) == 0, "CryptoKey::Type::Public is not 0 as expected"); + static_assert(static_cast<size_t>(CryptoKey::Type::Private) == 1, "CryptoKey::Type::Private is not 1 as expected"); + static_assert(static_cast<size_t>(CryptoKey::Type::Secret) == 2, "CryptoKey::Type::Secret is not 2 as expected"); + ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values)); + return values[static_cast<size_t>(enumerationValue)]; +} + +template<> JSString* convertEnumerationToJS(JSGlobalObject& lexicalGlobalObject, CryptoKey::Type enumerationValue) +{ + return jsStringWithCache(lexicalGlobalObject.vm(), convertEnumerationToString(enumerationValue)); +} + +template<> std::optional<CryptoKey::Type> parseEnumeration<CryptoKey::Type>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + auto stringValue = value.toWTFString(&lexicalGlobalObject); + static constexpr std::pair<ComparableASCIILiteral, CryptoKey::Type> mappings[] = { + { "private", CryptoKey::Type::Private }, + { "public", CryptoKey::Type::Public }, + { "secret", CryptoKey::Type::Secret }, + }; + static constexpr SortedArrayMap enumerationMapping { mappings }; + if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); LIKELY(enumerationValue)) + return *enumerationValue; + return std::nullopt; +} + +template<> const char* expectedEnumerationValues<CryptoKey::Type>() +{ + return "\"public\", \"private\", \"secret\""; +} + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsCryptoKeyConstructor); +static JSC_DECLARE_CUSTOM_GETTER(jsCryptoKey_type); +static JSC_DECLARE_CUSTOM_GETTER(jsCryptoKey_extractable); +static JSC_DECLARE_CUSTOM_GETTER(jsCryptoKey_algorithm); +static JSC_DECLARE_CUSTOM_GETTER(jsCryptoKey_usages); + +class JSCryptoKeyPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSCryptoKeyPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSCryptoKeyPrototype* ptr = new (NotNull, JSC::allocateCell<JSCryptoKeyPrototype>(vm)) JSCryptoKeyPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCryptoKeyPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSCryptoKeyPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCryptoKeyPrototype, JSCryptoKeyPrototype::Base); + +using JSCryptoKeyDOMConstructor = JSDOMConstructorNotConstructable<JSCryptoKey>; + +template<> const ClassInfo JSCryptoKeyDOMConstructor::s_info = { "CryptoKey"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCryptoKeyDOMConstructor) }; + +template<> JSValue JSCryptoKeyDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + UNUSED_PARAM(vm); + return globalObject.functionPrototype(); +} + +template<> void JSCryptoKeyDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "CryptoKey"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSCryptoKey::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); +} + +/* Hash table for prototype */ + +static const HashTableValue JSCryptoKeyPrototypeTableValues[] = +{ + { "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsCryptoKeyConstructor, 0 } }, + { "type"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsCryptoKey_type, 0 } }, + { "extractable"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsCryptoKey_extractable, 0 } }, + { "algorithm"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsCryptoKey_algorithm, 0 } }, + { "usages"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsCryptoKey_usages, 0 } }, +}; + +const ClassInfo JSCryptoKeyPrototype::s_info = { "CryptoKey"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCryptoKeyPrototype) }; + +void JSCryptoKeyPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSCryptoKey::info(), JSCryptoKeyPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSCryptoKey::s_info = { "CryptoKey"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCryptoKey) }; + +JSCryptoKey::JSCryptoKey(Structure* structure, JSDOMGlobalObject& globalObject, Ref<CryptoKey>&& impl) + : JSDOMWrapper<CryptoKey>(structure, globalObject, WTFMove(impl)) +{ +} + +void JSCryptoKey::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); + + // static_assert(!std::is_base_of<ActiveDOMObject, CryptoKey>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); + +} + +JSObject* JSCryptoKey::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSCryptoKeyPrototype::create(vm, &globalObject, JSCryptoKeyPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); +} + +JSObject* JSCryptoKey::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSCryptoKey>(vm, globalObject); +} + +JSValue JSCryptoKey::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSCryptoKeyDOMConstructor, DOMConstructorID::CryptoKey>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +void JSCryptoKey::destroy(JSC::JSCell* cell) +{ + JSCryptoKey* thisObject = static_cast<JSCryptoKey*>(cell); + thisObject->JSCryptoKey::~JSCryptoKey(); +} + +JSC_DEFINE_CUSTOM_GETTER(jsCryptoKeyConstructor, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSCryptoKeyPrototype*>(JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSCryptoKey::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSValue jsCryptoKey_typeGetter(JSGlobalObject& lexicalGlobalObject, JSCryptoKey& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLEnumeration<CryptoKey::Type>>(lexicalGlobalObject, throwScope, impl.type()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsCryptoKey_type, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSCryptoKey>::get<jsCryptoKey_typeGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsCryptoKey_extractableGetter(JSGlobalObject& lexicalGlobalObject, JSCryptoKey& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.extractable()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsCryptoKey_extractable, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSCryptoKey>::get<jsCryptoKey_extractableGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsCryptoKey_algorithmGetter(JSGlobalObject& lexicalGlobalObject, JSCryptoKey& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + if (JSValue cachedValue = thisObject.m_algorithm.get()) + return cachedValue; + auto& impl = thisObject.wrapped(); + JSValue result = toJS<IDLUnion<IDLDictionary<CryptoKeyAlgorithm>, IDLDictionary<CryptoAesKeyAlgorithm>, IDLDictionary<CryptoEcKeyAlgorithm>, IDLDictionary<CryptoHmacKeyAlgorithm>, IDLDictionary<CryptoRsaHashedKeyAlgorithm>, IDLDictionary<CryptoRsaKeyAlgorithm>>>(lexicalGlobalObject, *thisObject.globalObject(), throwScope, impl.algorithm()); + RETURN_IF_EXCEPTION(throwScope, { }); + thisObject.m_algorithm.set(JSC::getVM(&lexicalGlobalObject), &thisObject, result); + return result; +} + +JSC_DEFINE_CUSTOM_GETTER(jsCryptoKey_algorithm, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSCryptoKey>::get<jsCryptoKey_algorithmGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsCryptoKey_usagesGetter(JSGlobalObject& lexicalGlobalObject, JSCryptoKey& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + if (JSValue cachedValue = thisObject.m_usages.get()) + return cachedValue; + auto& impl = thisObject.wrapped(); + JSValue result = toJS<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(lexicalGlobalObject, *thisObject.globalObject(), throwScope, impl.usages()); + RETURN_IF_EXCEPTION(throwScope, { }); + thisObject.m_usages.set(JSC::getVM(&lexicalGlobalObject), &thisObject, result); + return result; +} + +JSC_DEFINE_CUSTOM_GETTER(jsCryptoKey_usages, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSCryptoKey>::get<jsCryptoKey_usagesGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +JSC::GCClient::IsoSubspace* JSCryptoKey::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSCryptoKey, UseCustomHeapCellType::No>(vm, + [] (auto& spaces) { return spaces.m_clientSubspaceForCryptoKey.get(); }, + [] (auto& spaces, auto&& space) { spaces.m_clientSubspaceForCryptoKey = WTFMove(space); }, + [] (auto& spaces) { return spaces.m_subspaceForCryptoKey.get(); }, + [] (auto& spaces, auto&& space) { spaces.m_subspaceForCryptoKey = WTFMove(space); } + ); +} + +template<typename Visitor> +void JSCryptoKey::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSCryptoKey*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.append(thisObject->m_algorithm); + visitor.append(thisObject->m_usages); +} + +DEFINE_VISIT_CHILDREN(JSCryptoKey); + +void JSCryptoKey::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSCryptoKey*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +bool JSCryptoKeyOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, AbstractSlotVisitor& visitor, const char** reason) +{ + auto* jsCryptoKey = jsCast<JSCryptoKey*>(handle.slot()->asCell()); + CryptoKey* owner = &jsCryptoKey->wrapped(); + if (UNLIKELY(reason)) + *reason = "Reachable from CryptoKey"; + return visitor.containsOpaqueRoot(context); +} + +void JSCryptoKeyOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +{ + auto* jsCryptoKey = static_cast<JSCryptoKey*>(handle.slot()->asCell()); + auto& world = *static_cast<DOMWrapperWorld*>(context); + uncacheWrapper(world, &jsCryptoKey->wrapped(), jsCryptoKey); +} + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<CryptoKey>&& impl) +{ + return createWrapper<CryptoKey>(globalObject, WTFMove(impl)); +} + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, CryptoKey& impl) +{ + return wrap(lexicalGlobalObject, globalObject, impl); +} + +CryptoKey* JSCryptoKey::toWrapped(JSC::VM&, JSC::JSValue value) +{ + if (auto* wrapper = jsDynamicCast<JSCryptoKey*>(value)) + return &wrapper->wrapped(); + return nullptr; +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKey.dep b/src/bun.js/bindings/webcrypto/JSCryptoKey.dep new file mode 100644 index 000000000..b1bf0ac9d --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKey.dep @@ -0,0 +1 @@ +JSCryptoKey.h : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKey.h b/src/bun.js/bindings/webcrypto/JSCryptoKey.h new file mode 100644 index 000000000..57a6dbbfb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKey.h @@ -0,0 +1,108 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKey.h" +#include "JSDOMConvertEnumeration.h" +#include "JSDOMWrapper.h" +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +class JSCryptoKey : public JSDOMWrapper<CryptoKey> { +public: + using Base = JSDOMWrapper<CryptoKey>; + static JSCryptoKey* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<CryptoKey>&& impl) + { + JSCryptoKey* ptr = new (NotNull, JSC::allocateCell<JSCryptoKey>(globalObject->vm())) JSCryptoKey(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + static CryptoKey* toWrapped(JSC::VM&, JSC::JSValue); + static void destroy(JSC::JSCell*); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + mutable JSC::WriteBarrier<JSC::Unknown> m_algorithm; + mutable JSC::WriteBarrier<JSC::Unknown> m_usages; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + DECLARE_VISIT_CHILDREN; + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); +protected: + JSCryptoKey(JSC::Structure*, JSDOMGlobalObject&, Ref<CryptoKey>&&); + + void finishCreation(JSC::VM&); +}; + +class JSCryptoKeyOwner final : public JSC::WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final; + void finalize(JSC::Handle<JSC::Unknown>, void* context) final; +}; + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, CryptoKey*) +{ + static NeverDestroyed<JSCryptoKeyOwner> owner; + return &owner.get(); +} + +inline void* wrapperKey(CryptoKey* wrappableObject) +{ + return wrappableObject; +} + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, CryptoKey&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, CryptoKey* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<CryptoKey>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<CryptoKey>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +template<> struct JSDOMWrapperConverterTraits<CryptoKey> { + using WrapperClass = JSCryptoKey; + using ToWrappedReturnType = CryptoKey*; +}; +String convertEnumerationToString(CryptoKey::Type); +template<> JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, CryptoKey::Type); + +template<> std::optional<CryptoKey::Type> parseEnumeration<CryptoKey::Type>(JSC::JSGlobalObject&, JSC::JSValue); +template<> const char* expectedEnumerationValues<CryptoKey::Type>(); + + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp new file mode 100644 index 000000000..c7009a16d --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp @@ -0,0 +1,83 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoKeyAlgorithm.h" + +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoKeyAlgorithm convertDictionary<CryptoKeyAlgorithm>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoKeyAlgorithm result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoKeyAlgorithm", "DOMString"); + return { }; + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const CryptoKeyAlgorithm& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + auto nameValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.name); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.dep b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.dep new file mode 100644 index 000000000..b0b711d25 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.dep @@ -0,0 +1 @@ +CryptoKeyAlgorithm.h : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.h new file mode 100644 index 000000000..979c0e0a4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyAlgorithm.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoKeyAlgorithm convertDictionary<CryptoKeyAlgorithm>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const CryptoKeyAlgorithm&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.cpp new file mode 100644 index 000000000..82947e907 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.cpp @@ -0,0 +1,99 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoKeyPair.h" + +#include "JSCryptoKey.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoKeyPair convertDictionary<CryptoKeyPair>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoKeyPair result; + JSValue privateKeyValue; + if (isNullOrUndefined) + privateKeyValue = jsUndefined(); + else { + privateKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "privateKey"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!privateKeyValue.isUndefined()) { + result.privateKey = convert<IDLInterface<CryptoKey>>(lexicalGlobalObject, privateKeyValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue publicKeyValue; + if (isNullOrUndefined) + publicKeyValue = jsUndefined(); + else { + publicKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicKey"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!publicKeyValue.isUndefined()) { + result.publicKey = convert<IDLInterface<CryptoKey>>(lexicalGlobalObject, publicKeyValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const CryptoKeyPair& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + if (!IDLInterface<CryptoKey>::isNullValue(dictionary.privateKey)) { + auto privateKeyValue = toJS<IDLInterface<CryptoKey>>(lexicalGlobalObject, globalObject, throwScope, IDLInterface<CryptoKey>::extractValueFromNullable(dictionary.privateKey)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "privateKey"_s), privateKeyValue); + } + if (!IDLInterface<CryptoKey>::isNullValue(dictionary.publicKey)) { + auto publicKeyValue = toJS<IDLInterface<CryptoKey>>(lexicalGlobalObject, globalObject, throwScope, IDLInterface<CryptoKey>::extractValueFromNullable(dictionary.publicKey)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "publicKey"_s), publicKeyValue); + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.dep b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.dep new file mode 100644 index 000000000..904d979ee --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.dep @@ -0,0 +1 @@ +CryptoKeyPair.h : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.h b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.h new file mode 100644 index 000000000..1284c368e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyPair.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoKeyPair convertDictionary<CryptoKeyPair>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const CryptoKeyPair&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp new file mode 100644 index 000000000..09d4b348b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp @@ -0,0 +1,91 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoKeyUsage.h" + +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSString.h> +#include <wtf/NeverDestroyed.h> +#include <wtf/SortedArrayMap.h> + + +namespace WebCore { +using namespace JSC; + +String convertEnumerationToString(CryptoKeyUsage enumerationValue) +{ + static const NeverDestroyed<String> values[] = { + MAKE_STATIC_STRING_IMPL("encrypt"), + MAKE_STATIC_STRING_IMPL("decrypt"), + MAKE_STATIC_STRING_IMPL("sign"), + MAKE_STATIC_STRING_IMPL("verify"), + MAKE_STATIC_STRING_IMPL("deriveKey"), + MAKE_STATIC_STRING_IMPL("deriveBits"), + MAKE_STATIC_STRING_IMPL("wrapKey"), + MAKE_STATIC_STRING_IMPL("unwrapKey"), + }; + static_assert(static_cast<size_t>(CryptoKeyUsage::Encrypt) == 0, "CryptoKeyUsage::Encrypt is not 0 as expected"); + static_assert(static_cast<size_t>(CryptoKeyUsage::Decrypt) == 1, "CryptoKeyUsage::Decrypt is not 1 as expected"); + static_assert(static_cast<size_t>(CryptoKeyUsage::Sign) == 2, "CryptoKeyUsage::Sign is not 2 as expected"); + static_assert(static_cast<size_t>(CryptoKeyUsage::Verify) == 3, "CryptoKeyUsage::Verify is not 3 as expected"); + static_assert(static_cast<size_t>(CryptoKeyUsage::DeriveKey) == 4, "CryptoKeyUsage::DeriveKey is not 4 as expected"); + static_assert(static_cast<size_t>(CryptoKeyUsage::DeriveBits) == 5, "CryptoKeyUsage::DeriveBits is not 5 as expected"); + static_assert(static_cast<size_t>(CryptoKeyUsage::WrapKey) == 6, "CryptoKeyUsage::WrapKey is not 6 as expected"); + static_assert(static_cast<size_t>(CryptoKeyUsage::UnwrapKey) == 7, "CryptoKeyUsage::UnwrapKey is not 7 as expected"); + ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values)); + return values[static_cast<size_t>(enumerationValue)]; +} + +template<> JSString* convertEnumerationToJS(JSGlobalObject& lexicalGlobalObject, CryptoKeyUsage enumerationValue) +{ + return jsStringWithCache(lexicalGlobalObject.vm(), convertEnumerationToString(enumerationValue)); +} + +template<> std::optional<CryptoKeyUsage> parseEnumeration<CryptoKeyUsage>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + auto stringValue = value.toWTFString(&lexicalGlobalObject); + static constexpr std::pair<ComparableASCIILiteral, CryptoKeyUsage> mappings[] = { + { "decrypt", CryptoKeyUsage::Decrypt }, + { "deriveBits", CryptoKeyUsage::DeriveBits }, + { "deriveKey", CryptoKeyUsage::DeriveKey }, + { "encrypt", CryptoKeyUsage::Encrypt }, + { "sign", CryptoKeyUsage::Sign }, + { "unwrapKey", CryptoKeyUsage::UnwrapKey }, + { "verify", CryptoKeyUsage::Verify }, + { "wrapKey", CryptoKeyUsage::WrapKey }, + }; + static constexpr SortedArrayMap enumerationMapping { mappings }; + if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); LIKELY(enumerationValue)) + return *enumerationValue; + return std::nullopt; +} + +template<> const char* expectedEnumerationValues<CryptoKeyUsage>() +{ + return "\"encrypt\", \"decrypt\", \"sign\", \"verify\", \"deriveKey\", \"deriveBits\", \"wrapKey\", \"unwrapKey\""; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.h b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.h new file mode 100644 index 000000000..7119cf1d1 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.h @@ -0,0 +1,38 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoKeyUsage.h" +#include "JSDOMConvertEnumeration.h" + +namespace WebCore { + +String convertEnumerationToString(CryptoKeyUsage); +template<> JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, CryptoKeyUsage); + +template<> std::optional<CryptoKeyUsage> parseEnumeration<CryptoKeyUsage>(JSC::JSGlobalObject&, JSC::JSValue); +template<> const char* expectedEnumerationValues<CryptoKeyUsage>(); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp new file mode 100644 index 000000000..2a2cdb8a2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp @@ -0,0 +1,137 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoRsaHashedKeyAlgorithm.h" + +#include "JSCryptoKeyAlgorithm.h" +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoRsaHashedKeyAlgorithm convertDictionary<CryptoRsaHashedKeyAlgorithm>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoRsaHashedKeyAlgorithm result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoRsaHashedKeyAlgorithm", "DOMString"); + return { }; + } + JSValue modulusLengthValue; + if (isNullOrUndefined) + modulusLengthValue = jsUndefined(); + else { + modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!modulusLengthValue.isUndefined()) { + result.modulusLength = convert<IDLUnsignedLong>(lexicalGlobalObject, modulusLengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "CryptoRsaHashedKeyAlgorithm", "unsigned long"); + return { }; + } + JSValue publicExponentValue; + if (isNullOrUndefined) + publicExponentValue = jsUndefined(); + else { + publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!publicExponentValue.isUndefined()) { + result.publicExponent = convert<IDLUint8Array>(lexicalGlobalObject, publicExponentValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "CryptoRsaHashedKeyAlgorithm", "Uint8Array"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLDictionary<CryptoKeyAlgorithm>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "CryptoRsaHashedKeyAlgorithm", "CryptoKeyAlgorithm"); + return { }; + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const CryptoRsaHashedKeyAlgorithm& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + auto nameValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.name); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); + auto modulusLengthValue = toJS<IDLUnsignedLong>(lexicalGlobalObject, throwScope, dictionary.modulusLength); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "modulusLength"_s), modulusLengthValue); + auto publicExponentValue = toJS<IDLUint8Array>(lexicalGlobalObject, globalObject, throwScope, dictionary.publicExponent); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "publicExponent"_s), publicExponentValue); + auto hashValue = toJS<IDLDictionary<CryptoKeyAlgorithm>>(lexicalGlobalObject, globalObject, throwScope, dictionary.hash); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "hash"_s), hashValue); + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.dep b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.dep new file mode 100644 index 000000000..360e6c612 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.dep @@ -0,0 +1,3 @@ +CryptoRsaHashedKeyAlgorithm.h : CryptoRsaKeyAlgorithm.idl CryptoKeyAlgorithm.idl +CryptoRsaKeyAlgorithm.idl : +CryptoKeyAlgorithm.idl : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.h new file mode 100644 index 000000000..ef51231f4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoRsaHashedKeyAlgorithm.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoRsaHashedKeyAlgorithm convertDictionary<CryptoRsaHashedKeyAlgorithm>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const CryptoRsaHashedKeyAlgorithm&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp new file mode 100644 index 000000000..79407e27f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp @@ -0,0 +1,119 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSCryptoRsaKeyAlgorithm.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoRsaKeyAlgorithm convertDictionary<CryptoRsaKeyAlgorithm>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoRsaKeyAlgorithm result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoRsaKeyAlgorithm", "DOMString"); + return { }; + } + JSValue modulusLengthValue; + if (isNullOrUndefined) + modulusLengthValue = jsUndefined(); + else { + modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!modulusLengthValue.isUndefined()) { + result.modulusLength = convert<IDLUnsignedLong>(lexicalGlobalObject, modulusLengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "CryptoRsaKeyAlgorithm", "unsigned long"); + return { }; + } + JSValue publicExponentValue; + if (isNullOrUndefined) + publicExponentValue = jsUndefined(); + else { + publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!publicExponentValue.isUndefined()) { + result.publicExponent = convert<IDLUint8Array>(lexicalGlobalObject, publicExponentValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "CryptoRsaKeyAlgorithm", "Uint8Array"); + return { }; + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const CryptoRsaKeyAlgorithm& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + auto nameValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.name); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); + auto modulusLengthValue = toJS<IDLUnsignedLong>(lexicalGlobalObject, throwScope, dictionary.modulusLength); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "modulusLength"_s), modulusLengthValue); + auto publicExponentValue = toJS<IDLUint8Array>(lexicalGlobalObject, globalObject, throwScope, dictionary.publicExponent); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "publicExponent"_s), publicExponentValue); + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.dep b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.dep new file mode 100644 index 000000000..e907cd5f8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.dep @@ -0,0 +1,2 @@ +CryptoRsaKeyAlgorithm.h : CryptoKeyAlgorithm.idl +CryptoKeyAlgorithm.idl : diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.h b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.h new file mode 100644 index 000000000..3adcf0132 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoRsaKeyAlgorithm.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoRsaKeyAlgorithm convertDictionary<CryptoRsaKeyAlgorithm>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const CryptoRsaKeyAlgorithm&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp new file mode 100644 index 000000000..51fcfb966 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp @@ -0,0 +1,82 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSEcKeyParams.h" + +#include "JSDOMConvertStrings.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmEcKeyParams convertDictionary<CryptoAlgorithmEcKeyParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmEcKeyParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "EcKeyParams", "DOMString"); + return { }; + } + JSValue namedCurveValue; + if (isNullOrUndefined) + namedCurveValue = jsUndefined(); + else { + namedCurveValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "namedCurve"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!namedCurveValue.isUndefined()) { + result.namedCurve = convert<IDLDOMString>(lexicalGlobalObject, namedCurveValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "namedCurve", "EcKeyParams", "DOMString"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSEcKeyParams.dep b/src/bun.js/bindings/webcrypto/JSEcKeyParams.dep new file mode 100644 index 000000000..4735dd21b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcKeyParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmEcKeyParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSEcKeyParams.h b/src/bun.js/bindings/webcrypto/JSEcKeyParams.h new file mode 100644 index 000000000..b4e39fcea --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcKeyParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmEcKeyParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmEcKeyParams convertDictionary<CryptoAlgorithmEcKeyParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp new file mode 100644 index 000000000..9005a34ff --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp @@ -0,0 +1,84 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSEcdhKeyDeriveParams.h" + +#include "JSCryptoKey.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertStrings.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmEcdhKeyDeriveParams convertDictionary<CryptoAlgorithmEcdhKeyDeriveParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmEcdhKeyDeriveParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "EcdhKeyDeriveParams", "DOMString"); + return { }; + } + JSValue publicKeyValue; + if (isNullOrUndefined) + publicKeyValue = jsUndefined(); + else { + publicKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicKey"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!publicKeyValue.isUndefined()) { + result.publicKey = convert<IDLInterface<CryptoKey>>(lexicalGlobalObject, publicKeyValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicKey", "EcdhKeyDeriveParams", "CryptoKey"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.dep b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.dep new file mode 100644 index 000000000..5681b50bf --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmEcdhKeyDeriveParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.h b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.h new file mode 100644 index 000000000..657b1ee31 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmEcdhKeyDeriveParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmEcdhKeyDeriveParams convertDictionary<CryptoAlgorithmEcdhKeyDeriveParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp b/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp new file mode 100644 index 000000000..700b30e6e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp @@ -0,0 +1,85 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSEcdsaParams.h" + +#include "JSDOMConvertObject.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmEcdsaParams convertDictionary<CryptoAlgorithmEcdsaParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmEcdsaParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "EcdsaParams", "DOMString"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLUnion<IDLObject, IDLDOMString>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "EcdsaParams", "(object or DOMString)"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSEcdsaParams.dep b/src/bun.js/bindings/webcrypto/JSEcdsaParams.dep new file mode 100644 index 000000000..294efafe8 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcdsaParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmEcdsaParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSEcdsaParams.h b/src/bun.js/bindings/webcrypto/JSEcdsaParams.h new file mode 100644 index 000000000..b17bf046f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSEcdsaParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmEcdsaParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmEcdsaParams convertDictionary<CryptoAlgorithmEcdsaParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp b/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp new file mode 100644 index 000000000..3b68fa3de --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp @@ -0,0 +1,114 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSHkdfParams.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertObject.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmHkdfParams convertDictionary<CryptoAlgorithmHkdfParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmHkdfParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "HkdfParams", "DOMString"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLUnion<IDLObject, IDLDOMString>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "HkdfParams", "(object or DOMString)"); + return { }; + } + JSValue infoValue; + if (isNullOrUndefined) + infoValue = jsUndefined(); + else { + infoValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "info"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!infoValue.isUndefined()) { + result.info = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, infoValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "info", "HkdfParams", "(ArrayBufferView or ArrayBuffer)"); + return { }; + } + JSValue saltValue; + if (isNullOrUndefined) + saltValue = jsUndefined(); + else { + saltValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "salt"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!saltValue.isUndefined()) { + result.salt = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, saltValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "salt", "HkdfParams", "(ArrayBufferView or ArrayBuffer)"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSHkdfParams.dep b/src/bun.js/bindings/webcrypto/JSHkdfParams.dep new file mode 100644 index 000000000..bf1ae962f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSHkdfParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmHkdfParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSHkdfParams.h b/src/bun.js/bindings/webcrypto/JSHkdfParams.h new file mode 100644 index 000000000..76251ef07 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSHkdfParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmHkdfParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmHkdfParams convertDictionary<CryptoAlgorithmHkdfParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp new file mode 100644 index 000000000..2debe2409 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp @@ -0,0 +1,97 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSHmacKeyParams.h" + +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertObject.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmHmacKeyParams convertDictionary<CryptoAlgorithmHmacKeyParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmHmacKeyParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "HmacKeyParams", "DOMString"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLUnion<IDLObject, IDLDOMString>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "HmacKeyParams", "(object or DOMString)"); + return { }; + } + JSValue lengthValue; + if (isNullOrUndefined) + lengthValue = jsUndefined(); + else { + lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!lengthValue.isUndefined()) { + result.length = convert<IDLEnforceRangeAdaptor<IDLUnsignedLong>>(lexicalGlobalObject, lengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSHmacKeyParams.dep b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.dep new file mode 100644 index 000000000..fbf7eea2f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmHmacKeyParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSHmacKeyParams.h b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.h new file mode 100644 index 000000000..2d1c61f44 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmHmacKeyParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmHmacKeyParams convertDictionary<CryptoAlgorithmHmacKeyParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp new file mode 100644 index 000000000..39ed1ff31 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp @@ -0,0 +1,361 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSJsonWebKey.h" + +#include "JSCryptoKeyUsage.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertEnumeration.h" +#include "JSDOMConvertSequences.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include "JSRsaOtherPrimesInfo.h" +#include <JavaScriptCore/JSArray.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> JsonWebKey convertDictionary<JsonWebKey>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + JsonWebKey result; + JSValue algValue; + if (isNullOrUndefined) + algValue = jsUndefined(); + else { + algValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "alg"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!algValue.isUndefined()) { + result.alg = convert<IDLDOMString>(lexicalGlobalObject, algValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue crvValue; + if (isNullOrUndefined) + crvValue = jsUndefined(); + else { + crvValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "crv"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!crvValue.isUndefined()) { + result.crv = convert<IDLDOMString>(lexicalGlobalObject, crvValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue dValue; + if (isNullOrUndefined) + dValue = jsUndefined(); + else { + dValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "d"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!dValue.isUndefined()) { + result.d = convert<IDLDOMString>(lexicalGlobalObject, dValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue dpValue; + if (isNullOrUndefined) + dpValue = jsUndefined(); + else { + dpValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "dp"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!dpValue.isUndefined()) { + result.dp = convert<IDLDOMString>(lexicalGlobalObject, dpValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue dqValue; + if (isNullOrUndefined) + dqValue = jsUndefined(); + else { + dqValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "dq"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!dqValue.isUndefined()) { + result.dq = convert<IDLDOMString>(lexicalGlobalObject, dqValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue eValue; + if (isNullOrUndefined) + eValue = jsUndefined(); + else { + eValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "e"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!eValue.isUndefined()) { + result.e = convert<IDLDOMString>(lexicalGlobalObject, eValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue extValue; + if (isNullOrUndefined) + extValue = jsUndefined(); + else { + extValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "ext"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!extValue.isUndefined()) { + result.ext = convert<IDLBoolean>(lexicalGlobalObject, extValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue kValue; + if (isNullOrUndefined) + kValue = jsUndefined(); + else { + kValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "k"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!kValue.isUndefined()) { + result.k = convert<IDLDOMString>(lexicalGlobalObject, kValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue key_opsValue; + if (isNullOrUndefined) + key_opsValue = jsUndefined(); + else { + key_opsValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "key_ops"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!key_opsValue.isUndefined()) { + result.key_ops = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(lexicalGlobalObject, key_opsValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue ktyValue; + if (isNullOrUndefined) + ktyValue = jsUndefined(); + else { + ktyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "kty"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!ktyValue.isUndefined()) { + result.kty = convert<IDLDOMString>(lexicalGlobalObject, ktyValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "kty", "JsonWebKey", "DOMString"); + return { }; + } + JSValue nValue; + if (isNullOrUndefined) + nValue = jsUndefined(); + else { + nValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "n"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nValue.isUndefined()) { + result.n = convert<IDLDOMString>(lexicalGlobalObject, nValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue othValue; + if (isNullOrUndefined) + othValue = jsUndefined(); + else { + othValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "oth"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!othValue.isUndefined()) { + result.oth = convert<IDLSequence<IDLDictionary<RsaOtherPrimesInfo>>>(lexicalGlobalObject, othValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue pValue; + if (isNullOrUndefined) + pValue = jsUndefined(); + else { + pValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "p"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!pValue.isUndefined()) { + result.p = convert<IDLDOMString>(lexicalGlobalObject, pValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue qValue; + if (isNullOrUndefined) + qValue = jsUndefined(); + else { + qValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "q"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!qValue.isUndefined()) { + result.q = convert<IDLDOMString>(lexicalGlobalObject, qValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue qiValue; + if (isNullOrUndefined) + qiValue = jsUndefined(); + else { + qiValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "qi"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!qiValue.isUndefined()) { + result.qi = convert<IDLDOMString>(lexicalGlobalObject, qiValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue useValue; + if (isNullOrUndefined) + useValue = jsUndefined(); + else { + useValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "use"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!useValue.isUndefined()) { + result.use = convert<IDLDOMString>(lexicalGlobalObject, useValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue xValue; + if (isNullOrUndefined) + xValue = jsUndefined(); + else { + xValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "x"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!xValue.isUndefined()) { + result.x = convert<IDLDOMString>(lexicalGlobalObject, xValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue yValue; + if (isNullOrUndefined) + yValue = jsUndefined(); + else { + yValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "y"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!yValue.isUndefined()) { + result.y = convert<IDLDOMString>(lexicalGlobalObject, yValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const JsonWebKey& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + if (!IDLDOMString::isNullValue(dictionary.alg)) { + auto algValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.alg)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "alg"_s), algValue); + } + if (!IDLDOMString::isNullValue(dictionary.crv)) { + auto crvValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.crv)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "crv"_s), crvValue); + } + if (!IDLDOMString::isNullValue(dictionary.d)) { + auto dValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.d)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "d"_s), dValue); + } + if (!IDLDOMString::isNullValue(dictionary.dp)) { + auto dpValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.dp)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "dp"_s), dpValue); + } + if (!IDLDOMString::isNullValue(dictionary.dq)) { + auto dqValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.dq)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "dq"_s), dqValue); + } + if (!IDLDOMString::isNullValue(dictionary.e)) { + auto eValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.e)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "e"_s), eValue); + } + if (!IDLBoolean::isNullValue(dictionary.ext)) { + auto extValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, IDLBoolean::extractValueFromNullable(dictionary.ext)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "ext"_s), extValue); + } + if (!IDLDOMString::isNullValue(dictionary.k)) { + auto kValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.k)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "k"_s), kValue); + } + if (!IDLSequence<IDLEnumeration<CryptoKeyUsage>>::isNullValue(dictionary.key_ops)) { + auto key_opsValue = toJS<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(lexicalGlobalObject, globalObject, throwScope, IDLSequence<IDLEnumeration<CryptoKeyUsage>>::extractValueFromNullable(dictionary.key_ops)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "key_ops"_s), key_opsValue); + } + auto ktyValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.kty); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "kty"_s), ktyValue); + if (!IDLDOMString::isNullValue(dictionary.n)) { + auto nValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.n)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "n"_s), nValue); + } + if (!IDLSequence<IDLDictionary<RsaOtherPrimesInfo>>::isNullValue(dictionary.oth)) { + auto othValue = toJS<IDLSequence<IDLDictionary<RsaOtherPrimesInfo>>>(lexicalGlobalObject, globalObject, throwScope, IDLSequence<IDLDictionary<RsaOtherPrimesInfo>>::extractValueFromNullable(dictionary.oth)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "oth"_s), othValue); + } + if (!IDLDOMString::isNullValue(dictionary.p)) { + auto pValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.p)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "p"_s), pValue); + } + if (!IDLDOMString::isNullValue(dictionary.q)) { + auto qValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.q)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "q"_s), qValue); + } + if (!IDLDOMString::isNullValue(dictionary.qi)) { + auto qiValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.qi)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "qi"_s), qiValue); + } + if (!IDLDOMString::isNullValue(dictionary.use)) { + auto useValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.use)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "use"_s), useValue); + } + if (!IDLDOMString::isNullValue(dictionary.x)) { + auto xValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.x)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "x"_s), xValue); + } + if (!IDLDOMString::isNullValue(dictionary.y)) { + auto yValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, IDLDOMString::extractValueFromNullable(dictionary.y)); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "y"_s), yValue); + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSJsonWebKey.dep b/src/bun.js/bindings/webcrypto/JSJsonWebKey.dep new file mode 100644 index 000000000..c68f31aca --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSJsonWebKey.dep @@ -0,0 +1 @@ +JsonWebKey.h : diff --git a/src/bun.js/bindings/webcrypto/JSJsonWebKey.h b/src/bun.js/bindings/webcrypto/JSJsonWebKey.h new file mode 100644 index 000000000..07e7960be --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSJsonWebKey.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "JSDOMConvertDictionary.h" +#include "JsonWebKey.h" + +namespace WebCore { + +template<> JsonWebKey convertDictionary<JsonWebKey>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const JsonWebKey&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp new file mode 100644 index 000000000..871d8ffd9 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp @@ -0,0 +1,115 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSPbkdf2Params.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertObject.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmPbkdf2Params convertDictionary<CryptoAlgorithmPbkdf2Params>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmPbkdf2Params result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "Pbkdf2Params", "DOMString"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLUnion<IDLObject, IDLDOMString>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "Pbkdf2Params", "(object or DOMString)"); + return { }; + } + JSValue iterationsValue; + if (isNullOrUndefined) + iterationsValue = jsUndefined(); + else { + iterationsValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "iterations"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!iterationsValue.isUndefined()) { + result.iterations = convert<IDLEnforceRangeAdaptor<IDLUnsignedLong>>(lexicalGlobalObject, iterationsValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iterations", "Pbkdf2Params", "unsigned long"); + return { }; + } + JSValue saltValue; + if (isNullOrUndefined) + saltValue = jsUndefined(); + else { + saltValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "salt"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!saltValue.isUndefined()) { + result.salt = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, saltValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "salt", "Pbkdf2Params", "(ArrayBufferView or ArrayBuffer)"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSPbkdf2Params.dep b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.dep new file mode 100644 index 000000000..c950639a4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmPbkdf2Params.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSPbkdf2Params.h b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.h new file mode 100644 index 000000000..176e91b79 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmPbkdf2Params.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmPbkdf2Params convertDictionary<CryptoAlgorithmPbkdf2Params>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp new file mode 100644 index 000000000..e48fba0fd --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp @@ -0,0 +1,85 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSRsaHashedImportParams.h" + +#include "JSDOMConvertObject.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmRsaHashedImportParams convertDictionary<CryptoAlgorithmRsaHashedImportParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmRsaHashedImportParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaHashedImportParams", "DOMString"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLUnion<IDLObject, IDLDOMString>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "RsaHashedImportParams", "(object or DOMString)"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.dep b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.dep new file mode 100644 index 000000000..7a7393d6e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmRsaHashedImportParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.h b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.h new file mode 100644 index 000000000..116bceb04 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaHashedImportParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmRsaHashedImportParams convertDictionary<CryptoAlgorithmRsaHashedImportParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp new file mode 100644 index 000000000..c5abfe52a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp @@ -0,0 +1,115 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSRsaHashedKeyGenParams.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertObject.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmRsaHashedKeyGenParams convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmRsaHashedKeyGenParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaHashedKeyGenParams", "DOMString"); + return { }; + } + JSValue modulusLengthValue; + if (isNullOrUndefined) + modulusLengthValue = jsUndefined(); + else { + modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!modulusLengthValue.isUndefined()) { + result.modulusLength = convert<IDLEnforceRangeAdaptor<IDLUnsignedLong>>(lexicalGlobalObject, modulusLengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "RsaHashedKeyGenParams", "unsigned long"); + return { }; + } + JSValue publicExponentValue; + if (isNullOrUndefined) + publicExponentValue = jsUndefined(); + else { + publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!publicExponentValue.isUndefined()) { + result.publicExponent = convert<IDLUint8Array>(lexicalGlobalObject, publicExponentValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "RsaHashedKeyGenParams", "Uint8Array"); + return { }; + } + JSValue hashValue; + if (isNullOrUndefined) + hashValue = jsUndefined(); + else { + hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!hashValue.isUndefined()) { + result.hash = convert<IDLUnion<IDLObject, IDLDOMString>>(lexicalGlobalObject, hashValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "RsaHashedKeyGenParams", "(object or DOMString)"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.dep b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.dep new file mode 100644 index 000000000..788f8828b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.dep @@ -0,0 +1,3 @@ +CryptoAlgorithmRsaHashedKeyGenParams.h : RsaKeyGenParams.idl CryptoAlgorithmParameters.idl +RsaKeyGenParams.idl : +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.h b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.h new file mode 100644 index 000000000..30e9075e4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaHashedKeyGenParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmRsaHashedKeyGenParams convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp new file mode 100644 index 000000000..54644978a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp @@ -0,0 +1,98 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSRsaKeyGenParams.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmRsaKeyGenParams convertDictionary<CryptoAlgorithmRsaKeyGenParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmRsaKeyGenParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaKeyGenParams", "DOMString"); + return { }; + } + JSValue modulusLengthValue; + if (isNullOrUndefined) + modulusLengthValue = jsUndefined(); + else { + modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!modulusLengthValue.isUndefined()) { + result.modulusLength = convert<IDLEnforceRangeAdaptor<IDLUnsignedLong>>(lexicalGlobalObject, modulusLengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "RsaKeyGenParams", "unsigned long"); + return { }; + } + JSValue publicExponentValue; + if (isNullOrUndefined) + publicExponentValue = jsUndefined(); + else { + publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!publicExponentValue.isUndefined()) { + result.publicExponent = convert<IDLUint8Array>(lexicalGlobalObject, publicExponentValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "RsaKeyGenParams", "Uint8Array"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.dep b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.dep new file mode 100644 index 000000000..228557474 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmRsaKeyGenParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.h b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.h new file mode 100644 index 000000000..5ed39bcff --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaKeyGenParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmRsaKeyGenParams convertDictionary<CryptoAlgorithmRsaKeyGenParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp new file mode 100644 index 000000000..16264b7d9 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp @@ -0,0 +1,82 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSRsaOaepParams.h" + +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include <JavaScriptCore/JSCInlines.h> +#include <variant> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmRsaOaepParams convertDictionary<CryptoAlgorithmRsaOaepParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmRsaOaepParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaOaepParams", "DOMString"); + return { }; + } + JSValue labelValue; + if (isNullOrUndefined) + labelValue = jsUndefined(); + else { + labelValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "label"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!labelValue.isUndefined()) { + result.label = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(lexicalGlobalObject, labelValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaOaepParams.dep b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.dep new file mode 100644 index 000000000..1380355f2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmRsaOaepParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSRsaOaepParams.h b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.h new file mode 100644 index 000000000..049a11cf0 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaOaepParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmRsaOaepParams convertDictionary<CryptoAlgorithmRsaOaepParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp new file mode 100644 index 000000000..420e17fb4 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp @@ -0,0 +1,117 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSRsaOtherPrimesInfo.h" + +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/ObjectConstructor.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> RsaOtherPrimesInfo convertDictionary<RsaOtherPrimesInfo>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + RsaOtherPrimesInfo result; + JSValue dValue; + if (isNullOrUndefined) + dValue = jsUndefined(); + else { + dValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "d"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!dValue.isUndefined()) { + result.d = convert<IDLDOMString>(lexicalGlobalObject, dValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "d", "RsaOtherPrimesInfo", "DOMString"); + return { }; + } + JSValue rValue; + if (isNullOrUndefined) + rValue = jsUndefined(); + else { + rValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "r"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!rValue.isUndefined()) { + result.r = convert<IDLDOMString>(lexicalGlobalObject, rValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "r", "RsaOtherPrimesInfo", "DOMString"); + return { }; + } + JSValue tValue; + if (isNullOrUndefined) + tValue = jsUndefined(); + else { + tValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "t"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!tValue.isUndefined()) { + result.t = convert<IDLDOMString>(lexicalGlobalObject, tValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "t", "RsaOtherPrimesInfo", "DOMString"); + return { }; + } + return result; +} + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const RsaOtherPrimesInfo& dictionary) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); + + auto dValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.d); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "d"_s), dValue); + auto rValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.r); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "r"_s), rValue); + auto tValue = toJS<IDLDOMString>(lexicalGlobalObject, throwScope, dictionary.t); + RETURN_IF_EXCEPTION(throwScope, { }); + result->putDirect(vm, JSC::Identifier::fromString(vm, "t"_s), tValue); + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.dep b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.dep new file mode 100644 index 000000000..ca7765d12 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.dep @@ -0,0 +1 @@ +RsaOtherPrimesInfo.h : diff --git a/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.h b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.h new file mode 100644 index 000000000..2f8fa46f2 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.h @@ -0,0 +1,36 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "JSDOMConvertDictionary.h" +#include "RsaOtherPrimesInfo.h" + +namespace WebCore { + +template<> RsaOtherPrimesInfo convertDictionary<RsaOtherPrimesInfo>(JSC::JSGlobalObject&, JSC::JSValue); + +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const RsaOtherPrimesInfo&); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp new file mode 100644 index 000000000..3498ec0e9 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp @@ -0,0 +1,83 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSRsaPssParams.h" + +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +#if ENABLE(WEB_CRYPTO) + +template<> CryptoAlgorithmRsaPssParams convertDictionary<CryptoAlgorithmRsaPssParams>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + CryptoAlgorithmRsaPssParams result; + JSValue nameValue; + if (isNullOrUndefined) + nameValue = jsUndefined(); + else { + nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!nameValue.isUndefined()) { + result.name = convert<IDLDOMString>(lexicalGlobalObject, nameValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaPssParams", "DOMString"); + return { }; + } + JSValue saltLengthValue; + if (isNullOrUndefined) + saltLengthValue = jsUndefined(); + else { + saltLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "saltLength"_s)); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!saltLengthValue.isUndefined()) { + result.saltLength = convert<IDLEnforceRangeAdaptor<IDLUnsignedLong>>(lexicalGlobalObject, saltLengthValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else { + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "saltLength", "RsaPssParams", "unsigned long"); + return { }; + } + return result; +} + +#endif + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSRsaPssParams.dep b/src/bun.js/bindings/webcrypto/JSRsaPssParams.dep new file mode 100644 index 000000000..a23b9a774 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaPssParams.dep @@ -0,0 +1,2 @@ +CryptoAlgorithmRsaPssParams.h : CryptoAlgorithmParameters.idl +CryptoAlgorithmParameters.idl : diff --git a/src/bun.js/bindings/webcrypto/JSRsaPssParams.h b/src/bun.js/bindings/webcrypto/JSRsaPssParams.h new file mode 100644 index 000000000..85013f028 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSRsaPssParams.h @@ -0,0 +1,34 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmRsaPssParams.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> CryptoAlgorithmRsaPssParams convertDictionary<CryptoAlgorithmRsaPssParams>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp new file mode 100644 index 000000000..66dddf20e --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp @@ -0,0 +1,678 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(WEB_CRYPTO) + +#include "JSSubtleCrypto.h" + +#include "ActiveDOMObject.h" +#include "DOMPromiseProxy.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "JSCryptoKey.h" +#include "JSCryptoKeyUsage.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructorNotConstructable.h" +#include "JSDOMConvertAny.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertDictionary.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertObject.h" +#include "JSDOMConvertPromise.h" +#include "JSDOMConvertSequences.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMOperation.h" +#include "JSDOMOperationReturningPromise.h" +#include "JSDOMWrapperCache.h" +#include "JSJsonWebKey.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include "WebCoreOpaqueRoot.h" +#include <JavaScriptCore/FunctionPrototype.h> +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSArray.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/JSString.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <variant> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/SortedArrayMap.h> +#include <wtf/URL.h> + + +namespace WebCore { +using namespace JSC; + +String convertEnumerationToString(SubtleCrypto::KeyFormat enumerationValue) +{ + static const NeverDestroyed<String> values[] = { + MAKE_STATIC_STRING_IMPL("raw"), + MAKE_STATIC_STRING_IMPL("spki"), + MAKE_STATIC_STRING_IMPL("pkcs8"), + MAKE_STATIC_STRING_IMPL("jwk"), + }; + static_assert(static_cast<size_t>(SubtleCrypto::KeyFormat::Raw) == 0, "SubtleCrypto::KeyFormat::Raw is not 0 as expected"); + static_assert(static_cast<size_t>(SubtleCrypto::KeyFormat::Spki) == 1, "SubtleCrypto::KeyFormat::Spki is not 1 as expected"); + static_assert(static_cast<size_t>(SubtleCrypto::KeyFormat::Pkcs8) == 2, "SubtleCrypto::KeyFormat::Pkcs8 is not 2 as expected"); + static_assert(static_cast<size_t>(SubtleCrypto::KeyFormat::Jwk) == 3, "SubtleCrypto::KeyFormat::Jwk is not 3 as expected"); + ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values)); + return values[static_cast<size_t>(enumerationValue)]; +} + +template<> JSString* convertEnumerationToJS(JSGlobalObject& lexicalGlobalObject, SubtleCrypto::KeyFormat enumerationValue) +{ + return jsStringWithCache(lexicalGlobalObject.vm(), convertEnumerationToString(enumerationValue)); +} + +template<> std::optional<SubtleCrypto::KeyFormat> parseEnumeration<SubtleCrypto::KeyFormat>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + auto stringValue = value.toWTFString(&lexicalGlobalObject); + static constexpr std::pair<ComparableASCIILiteral, SubtleCrypto::KeyFormat> mappings[] = { + { "jwk", SubtleCrypto::KeyFormat::Jwk }, + { "pkcs8", SubtleCrypto::KeyFormat::Pkcs8 }, + { "raw", SubtleCrypto::KeyFormat::Raw }, + { "spki", SubtleCrypto::KeyFormat::Spki }, + }; + static constexpr SortedArrayMap enumerationMapping { mappings }; + if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); LIKELY(enumerationValue)) + return *enumerationValue; + return std::nullopt; +} + +template<> const char* expectedEnumerationValues<SubtleCrypto::KeyFormat>() +{ + return "\"raw\", \"spki\", \"pkcs8\", \"jwk\""; +} + +// Functions + +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_encrypt); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_decrypt); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_sign); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_verify); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_digest); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_generateKey); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_deriveKey); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_deriveBits); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_importKey); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_exportKey); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_wrapKey); +static JSC_DECLARE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_unwrapKey); + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsSubtleCryptoConstructor); + +class JSSubtleCryptoPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSSubtleCryptoPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSSubtleCryptoPrototype* ptr = new (NotNull, JSC::allocateCell<JSSubtleCryptoPrototype>(vm)) JSSubtleCryptoPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSubtleCryptoPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSSubtleCryptoPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSubtleCryptoPrototype, JSSubtleCryptoPrototype::Base); + +using JSSubtleCryptoDOMConstructor = JSDOMConstructorNotConstructable<JSSubtleCrypto>; + +template<> const ClassInfo JSSubtleCryptoDOMConstructor::s_info = { "SubtleCrypto"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSubtleCryptoDOMConstructor) }; + +template<> JSValue JSSubtleCryptoDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + UNUSED_PARAM(vm); + return globalObject.functionPrototype(); +} + +template<> void JSSubtleCryptoDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "SubtleCrypto"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSSubtleCrypto::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); +} + +/* Hash table for prototype */ + +static const HashTableValue JSSubtleCryptoPrototypeTableValues[] = +{ + { "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsSubtleCryptoConstructor, 0 } }, + { "encrypt"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_encrypt, 3 } }, + { "decrypt"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_decrypt, 3 } }, + { "sign"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_sign, 3 } }, + { "verify"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_verify, 4 } }, + { "digest"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_digest, 2 } }, + { "generateKey"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_generateKey, 3 } }, + { "deriveKey"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_deriveKey, 5 } }, + { "deriveBits"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_deriveBits, 3 } }, + { "importKey"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_importKey, 5 } }, + { "exportKey"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_exportKey, 2 } }, + { "wrapKey"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_wrapKey, 4 } }, + { "unwrapKey"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSubtleCryptoPrototypeFunction_unwrapKey, 7 } }, +}; + +const ClassInfo JSSubtleCryptoPrototype::s_info = { "SubtleCrypto"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSubtleCryptoPrototype) }; + +void JSSubtleCryptoPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSSubtleCrypto::info(), JSSubtleCryptoPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSSubtleCrypto::s_info = { "SubtleCrypto"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSubtleCrypto) }; + +JSSubtleCrypto::JSSubtleCrypto(Structure* structure, JSDOMGlobalObject& globalObject, Ref<SubtleCrypto>&& impl) + : JSDOMWrapper<SubtleCrypto>(structure, globalObject, WTFMove(impl)) +{ +} + +void JSSubtleCrypto::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); + + // static_assert(!std::is_base_of<ActiveDOMObject, SubtleCrypto>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); + +} + +JSObject* JSSubtleCrypto::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSSubtleCryptoPrototype::create(vm, &globalObject, JSSubtleCryptoPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); +} + +JSObject* JSSubtleCrypto::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSSubtleCrypto>(vm, globalObject); +} + +JSValue JSSubtleCrypto::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSSubtleCryptoDOMConstructor, DOMConstructorID::SubtleCrypto>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +void JSSubtleCrypto::destroy(JSC::JSCell* cell) +{ + JSSubtleCrypto* thisObject = static_cast<JSSubtleCrypto*>(cell); + thisObject->JSSubtleCrypto::~JSSubtleCrypto(); +} + +JSC_DEFINE_CUSTOM_GETTER(jsSubtleCryptoConstructor, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSSubtleCryptoPrototype*>(JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSSubtleCrypto::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_encryptBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 3)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto key = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "encrypt", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto data = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.encrypt(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), *key, WTFMove(data), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_encrypt, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_encryptBody>(*lexicalGlobalObject, *callFrame, "encrypt"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_decryptBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 3)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto key = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "decrypt", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto data = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.decrypt(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), *key, WTFMove(data), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_decrypt, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_decryptBody>(*lexicalGlobalObject, *callFrame, "decrypt"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_signBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 3)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto key = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "sign", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto data = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.sign(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), *key, WTFMove(data), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_sign, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_signBody>(*lexicalGlobalObject, *callFrame, "sign"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_verifyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 4)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto key = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "verify", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto signature = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument3 = callFrame->uncheckedArgument(3); + auto data = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(*lexicalGlobalObject, argument3.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.verify(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), *key, WTFMove(signature), WTFMove(data), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_verify, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_verifyBody>(*lexicalGlobalObject, *callFrame, "verify"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_digestBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 2)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto data = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.digest(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), WTFMove(data), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_digest, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_digestBody>(*lexicalGlobalObject, *callFrame, "digest"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_generateKeyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 3)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto extractable = convert<IDLBoolean>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto keyUsages = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.generateKey(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), WTFMove(extractable), WTFMove(keyUsages), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_generateKey, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_generateKeyBody>(*lexicalGlobalObject, *callFrame, "generateKey"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_deriveKeyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 5)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto baseKey = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "baseKey", "SubtleCrypto", "deriveKey", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto derivedKeyType = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument3 = callFrame->uncheckedArgument(3); + auto extractable = convert<IDLBoolean>(*lexicalGlobalObject, argument3.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument4 = callFrame->uncheckedArgument(4); + auto keyUsages = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(*lexicalGlobalObject, argument4.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.deriveKey(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), *baseKey, WTFMove(derivedKeyType), WTFMove(extractable), WTFMove(keyUsages), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_deriveKey, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_deriveKeyBody>(*lexicalGlobalObject, *callFrame, "deriveKey"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_deriveBitsBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 3)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto baseKey = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "baseKey", "SubtleCrypto", "deriveBits", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto length = convert<IDLUnsignedLong>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLArrayBuffer>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.deriveBits(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(algorithm), *baseKey, WTFMove(length), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_deriveBits, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_deriveBitsBody>(*lexicalGlobalObject, *callFrame, "deriveBits"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_importKeyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 5)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "importKey", expectedEnumerationValues<SubtleCrypto::KeyFormat>()); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto keyData = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer, IDLDictionary<JsonWebKey>>>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto algorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument3 = callFrame->uncheckedArgument(3); + auto extractable = convert<IDLBoolean>(*lexicalGlobalObject, argument3.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument4 = callFrame->uncheckedArgument(4); + auto keyUsages = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(*lexicalGlobalObject, argument4.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLInterface<CryptoKey>>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.importKey(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(format), WTFMove(keyData), WTFMove(algorithm), WTFMove(extractable), WTFMove(keyUsages), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_importKey, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_importKeyBody>(*lexicalGlobalObject, *callFrame, "importKey"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_exportKeyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 2)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "exportKey", expectedEnumerationValues<SubtleCrypto::KeyFormat>()); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto key = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "exportKey", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.exportKey(WTFMove(format), *key, WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_exportKey, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_exportKeyBody>(*lexicalGlobalObject, *callFrame, "exportKey"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_wrapKeyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 4)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "wrapKey", expectedEnumerationValues<SubtleCrypto::KeyFormat>()); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto key = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "wrapKey", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto wrappingKey = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument2.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 2, "wrappingKey", "SubtleCrypto", "wrapKey", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument3 = callFrame->uncheckedArgument(3); + auto wrapAlgorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument3.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLAny>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.wrapKey(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(format), *key, *wrappingKey, WTFMove(wrapAlgorithm), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_wrapKey, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_wrapKeyBody>(*lexicalGlobalObject, *callFrame, "wrapKey"); +} + +static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_unwrapKeyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperationReturningPromise<JSSubtleCrypto>::ClassParameter castedThis, Ref<DeferredPromise>&& promise) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 7)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto format = convert<IDLEnumeration<SubtleCrypto::KeyFormat>>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "unwrapKey", expectedEnumerationValues<SubtleCrypto::KeyFormat>()); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto wrappedKey = convert<IDLUnion<IDLArrayBufferView, IDLArrayBuffer>>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); + auto unwrappingKey = convert<IDLInterface<CryptoKey>>(*lexicalGlobalObject, argument2.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 2, "unwrappingKey", "SubtleCrypto", "unwrapKey", "CryptoKey"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument3 = callFrame->uncheckedArgument(3); + auto unwrapAlgorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument3.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument4 = callFrame->uncheckedArgument(4); + auto unwrappedKeyAlgorithm = convert<IDLUnion<IDLObject, IDLDOMString>>(*lexicalGlobalObject, argument4.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument5 = callFrame->uncheckedArgument(5); + auto extractable = convert<IDLBoolean>(*lexicalGlobalObject, argument5.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument6 = callFrame->uncheckedArgument(6); + auto keyUsages = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(*lexicalGlobalObject, argument6.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLPromise<IDLInterface<CryptoKey>>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.unwrapKey(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(format), WTFMove(wrappedKey), *unwrappingKey, WTFMove(unwrapAlgorithm), WTFMove(unwrappedKeyAlgorithm), WTFMove(extractable), WTFMove(keyUsages), WTFMove(promise)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsSubtleCryptoPrototypeFunction_unwrapKey, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperationReturningPromise<JSSubtleCrypto>::call<jsSubtleCryptoPrototypeFunction_unwrapKeyBody>(*lexicalGlobalObject, *callFrame, "unwrapKey"); +} + +JSC::GCClient::IsoSubspace* JSSubtleCrypto::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSSubtleCrypto, UseCustomHeapCellType::No>(vm, + [] (auto& spaces) { return spaces.m_clientSubspaceForSubtleCrypto.get(); }, + [] (auto& spaces, auto&& space) { spaces.m_clientSubspaceForSubtleCrypto = WTFMove(space); }, + [] (auto& spaces) { return spaces.m_subspaceForSubtleCrypto.get(); }, + [] (auto& spaces, auto&& space) { spaces.m_subspaceForSubtleCrypto = WTFMove(space); } + ); +} + +void JSSubtleCrypto::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSSubtleCrypto*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +bool JSSubtleCryptoOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, AbstractSlotVisitor& visitor, const char** reason) +{ + auto* jsSubtleCrypto = jsCast<JSSubtleCrypto*>(handle.slot()->asCell()); + ScriptExecutionContext* owner = WTF::getPtr(jsSubtleCrypto->wrapped().scriptExecutionContext()); + if (!owner) + return false; + if (UNLIKELY(reason)) + *reason = "Reachable from ScriptExecutionContext"; + return visitor.containsOpaqueRoot(context); +} + +void JSSubtleCryptoOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +{ + auto* jsSubtleCrypto = static_cast<JSSubtleCrypto*>(handle.slot()->asCell()); + auto& world = *static_cast<DOMWrapperWorld*>(context); + uncacheWrapper(world, &jsSubtleCrypto->wrapped(), jsSubtleCrypto); +} + +#if ENABLE(BINDING_INTEGRITY) +#if PLATFORM(WIN) +#pragma warning(disable: 4483) +extern "C" { extern void (*const __identifier("??_7SubtleCrypto@WebCore@@6B@")[])(); } +#else +extern "C" { extern void* _ZTVN7WebCore12SubtleCryptoE[]; } +#endif +#endif + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<SubtleCrypto>&& impl) +{ + + if constexpr (std::is_polymorphic_v<SubtleCrypto>) { +#if ENABLE(BINDING_INTEGRITY) + const void* actualVTablePointer = getVTablePointer(impl.ptr()); +#if PLATFORM(WIN) + void* expectedVTablePointer = __identifier("??_7SubtleCrypto@WebCore@@6B@"); +#else + void* expectedVTablePointer = &_ZTVN7WebCore12SubtleCryptoE[2]; +#endif + + // If you hit this assertion you either have a use after free bug, or + // SubtleCrypto has subclasses. If SubtleCrypto has subclasses that get passed + // to toJS() we currently require SubtleCrypto you to opt out of binding hardening + // by adding the SkipVTableValidation attribute to the interface IDL definition + RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); +#endif + } + return createWrapper<SubtleCrypto>(globalObject, WTFMove(impl)); +} + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, SubtleCrypto& impl) +{ + return wrap(lexicalGlobalObject, globalObject, impl); +} + +SubtleCrypto* JSSubtleCrypto::toWrapped(JSC::VM&, JSC::JSValue value) +{ + if (auto* wrapper = jsDynamicCast<JSSubtleCrypto*>(value)) + return &wrapper->wrapped(); + return nullptr; +} + +} + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.dep b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.dep new file mode 100644 index 000000000..d1a56becf --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.dep @@ -0,0 +1 @@ +JSSubtleCrypto.h : diff --git a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.h b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.h new file mode 100644 index 000000000..d5d082dd1 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.h @@ -0,0 +1,104 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "JSDOMConvertEnumeration.h" +#include "JSDOMWrapper.h" +#include "SubtleCrypto.h" +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +class JSSubtleCrypto : public JSDOMWrapper<SubtleCrypto> { +public: + using Base = JSDOMWrapper<SubtleCrypto>; + static JSSubtleCrypto* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<SubtleCrypto>&& impl) + { + JSSubtleCrypto* ptr = new (NotNull, JSC::allocateCell<JSSubtleCrypto>(globalObject->vm())) JSSubtleCrypto(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + static SubtleCrypto* toWrapped(JSC::VM&, JSC::JSValue); + static void destroy(JSC::JSCell*); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); +protected: + JSSubtleCrypto(JSC::Structure*, JSDOMGlobalObject&, Ref<SubtleCrypto>&&); + + void finishCreation(JSC::VM&); +}; + +class JSSubtleCryptoOwner final : public JSC::WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final; + void finalize(JSC::Handle<JSC::Unknown>, void* context) final; +}; + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, SubtleCrypto*) +{ + static NeverDestroyed<JSSubtleCryptoOwner> owner; + return &owner.get(); +} + +inline void* wrapperKey(SubtleCrypto* wrappableObject) +{ + return wrappableObject; +} + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, SubtleCrypto&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, SubtleCrypto* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<SubtleCrypto>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<SubtleCrypto>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +template<> struct JSDOMWrapperConverterTraits<SubtleCrypto> { + using WrapperClass = JSSubtleCrypto; + using ToWrappedReturnType = SubtleCrypto*; +}; +String convertEnumerationToString(SubtleCrypto::KeyFormat); +template<> JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, SubtleCrypto::KeyFormat); + +template<> std::optional<SubtleCrypto::KeyFormat> parseEnumeration<SubtleCrypto::KeyFormat>(JSC::JSGlobalObject&, JSC::JSValue); +template<> const char* expectedEnumerationValues<SubtleCrypto::KeyFormat>(); + + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JsonWebKey.h b/src/bun.js/bindings/webcrypto/JsonWebKey.h new file mode 100644 index 000000000..eec00d747 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JsonWebKey.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#pragma once + +#include "CryptoKeyUsage.h" +#include "RsaOtherPrimesInfo.h" +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +struct JsonWebKey { + String kty; + String use; + // FIXME: Consider merging key_ops and usages. + std::optional<Vector<CryptoKeyUsage>> key_ops; + CryptoKeyUsageBitmap usages; + String alg; + + std::optional<bool> ext; + + String crv; + String x; + String y; + String d; + String n; + String e; + String p; + String q; + String dp; + String dq; + String qi; + std::optional<Vector<RsaOtherPrimesInfo>> oth; + String k; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/JsonWebKey.idl b/src/bun.js/bindings/webcrypto/JsonWebKey.idl new file mode 100644 index 000000000..5f4ca5c44 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/JsonWebKey.idl @@ -0,0 +1,53 @@ +/* + * 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. + */ + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject, +] dictionary JsonWebKey { + // The following fields are defined in Section 3.1 of JSON Web Key + required DOMString kty; + DOMString use; + sequence<CryptoKeyUsage> key_ops; + DOMString alg; + + // The following fields are defined in JSON Web Key Parameters Registration + boolean ext; + + // The following fields are defined in Section 6 of JSON Web Algorithms + DOMString crv; + DOMString x; + DOMString y; + DOMString d; + DOMString n; + DOMString e; + DOMString p; + DOMString q; + DOMString dp; + DOMString dq; + DOMString qi; + sequence<RsaOtherPrimesInfo> oth; + DOMString k; +}; diff --git a/src/bun.js/bindings/webcrypto/OpenSSLCryptoUniquePtr.h b/src/bun.js/bindings/webcrypto/OpenSSLCryptoUniquePtr.h new file mode 100644 index 000000000..b87aa561a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/OpenSSLCryptoUniquePtr.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 Igalia S.L. + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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. ``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 + * 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. + */ + +#pragma once + +#include <memory> +#include <openssl/ec.h> +#include <openssl/hmac.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/kdf.h> +#include <openssl/param_build.h> +#endif +#include <openssl/x509.h> + +namespace WebCore { + +template <typename T> +struct OpenSSLCryptoPtrDeleter { + void operator()(T* ptr) const = delete; +}; + +template <typename T> +using OpenSSLCryptoPtr = std::unique_ptr<T, OpenSSLCryptoPtrDeleter<T>>; + +#define DEFINE_OPENSSL_CRYPTO_PTR_FULL(alias, typeName, deleterFunc) \ + template<> struct OpenSSLCryptoPtrDeleter<typeName> { \ + void operator()(typeName* ptr) const { \ + deleterFunc; \ + } \ + }; \ + using alias = OpenSSLCryptoPtr<typeName>; + +#define DEFINE_OPENSSL_CRYPTO_PTR(alias, typeName, deleterFunc) \ + DEFINE_OPENSSL_CRYPTO_PTR_FULL(alias, typeName, deleterFunc(ptr)) + +DEFINE_OPENSSL_CRYPTO_PTR(EvpCipherCtxPtr, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free) +DEFINE_OPENSSL_CRYPTO_PTR(EvpDigestCtxPtr, EVP_MD_CTX, EVP_MD_CTX_free) +DEFINE_OPENSSL_CRYPTO_PTR(EvpPKeyPtr, EVP_PKEY, EVP_PKEY_free) +DEFINE_OPENSSL_CRYPTO_PTR(EvpPKeyCtxPtr, EVP_PKEY_CTX, EVP_PKEY_CTX_free) + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +DEFINE_OPENSSL_CRYPTO_PTR(OsslParamBldPtr, OSSL_PARAM_BLD, OSSL_PARAM_BLD_free) +DEFINE_OPENSSL_CRYPTO_PTR(OsslParamPtr, OSSL_PARAM, OSSL_PARAM_free) +DEFINE_OPENSSL_CRYPTO_PTR(EVPKDFCtxPtr, EVP_KDF_CTX, EVP_KDF_CTX_free) +DEFINE_OPENSSL_CRYPTO_PTR(EVPKDFPtr, EVP_KDF, EVP_KDF_free) +#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L + +// These are deprecated in OpenSSL 3. FIXME: Migrate to EvpKey. See Bug #245146. +DEFINE_OPENSSL_CRYPTO_PTR(RSAPtr, RSA, RSA_free) +DEFINE_OPENSSL_CRYPTO_PTR(ECKeyPtr, EC_KEY, EC_KEY_free) +DEFINE_OPENSSL_CRYPTO_PTR(HMACCtxPtr, HMAC_CTX, HMAC_CTX_free) + +DEFINE_OPENSSL_CRYPTO_PTR(ECPointPtr, EC_POINT, EC_POINT_clear_free) +DEFINE_OPENSSL_CRYPTO_PTR(PKCS8PrivKeyInfoPtr, PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free) +DEFINE_OPENSSL_CRYPTO_PTR(BIGNUMPtr, BIGNUM, BN_clear_free) +DEFINE_OPENSSL_CRYPTO_PTR(BNCtxPtr, BN_CTX, BN_CTX_free) +DEFINE_OPENSSL_CRYPTO_PTR(ECDSASigPtr, ECDSA_SIG, ECDSA_SIG_free) +DEFINE_OPENSSL_CRYPTO_PTR(X509Ptr, X509, X509_free) +DEFINE_OPENSSL_CRYPTO_PTR(BIOPtr, BIO, BIO_free) + +DEFINE_OPENSSL_CRYPTO_PTR_FULL(ASN1SequencePtr, ASN1_SEQUENCE_ANY, sk_ASN1_TYPE_pop_free(ptr, ASN1_TYPE_free)) + +#undef DEFINE_OPENSSL_CRYPTO_PTR +#undef DEFINE_OPENSSL_CRYPTO_PTR_FULL + +} // namespace WebCore diff --git a/src/bun.js/bindings/webcrypto/OpenSSLUtilities.cpp b/src/bun.js/bindings/webcrypto/OpenSSLUtilities.cpp new file mode 100644 index 000000000..2996cae2a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/OpenSSLUtilities.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2021 Sony Interactive Entertainment Inc. + * + * 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 "OpenSSLUtilities.h" + +#if ENABLE(WEB_CRYPTO) + +#include "OpenSSLCryptoUniquePtr.h" + +namespace WebCore { + +const EVP_MD* digestAlgorithm(CryptoAlgorithmIdentifier hashFunction) +{ + switch (hashFunction) { + case CryptoAlgorithmIdentifier::SHA_1: + return EVP_sha1(); + case CryptoAlgorithmIdentifier::SHA_224: + return EVP_sha224(); + case CryptoAlgorithmIdentifier::SHA_256: + return EVP_sha256(); + case CryptoAlgorithmIdentifier::SHA_384: + return EVP_sha384(); + case CryptoAlgorithmIdentifier::SHA_512: + return EVP_sha512(); + default: + return nullptr; + } +} + +std::optional<Vector<uint8_t>> calculateDigest(const EVP_MD* algorithm, const Vector<uint8_t>& message) +{ + EvpDigestCtxPtr ctx; + if (!(ctx = EvpDigestCtxPtr(EVP_MD_CTX_create()))) + return std::nullopt; + + int digestLength = EVP_MD_size(algorithm); + if (digestLength <= 0) + return std::nullopt; + Vector<uint8_t> digest(digestLength); + + if (EVP_DigestInit_ex(ctx.get(), algorithm, nullptr) != 1) + return std::nullopt; + + if (EVP_DigestUpdate(ctx.get(), message.data(), message.size()) != 1) + return std::nullopt; + + if (EVP_DigestFinal_ex(ctx.get(), digest.data(), nullptr) != 1) + return std::nullopt; + + return digest; +} + +Vector<uint8_t> convertToBytes(const BIGNUM* bignum) +{ + Vector<uint8_t> bytes(BN_num_bytes(bignum)); + BN_bn2bin(bignum, bytes.data()); + return bytes; +} + +Vector<uint8_t> convertToBytesExpand(const BIGNUM* bignum, size_t minimumBufferSize) +{ + int length = BN_num_bytes(bignum); + if (length < 0) + return { }; + + size_t bufferSize = std::max<size_t>(length, minimumBufferSize); + + Vector<uint8_t> bytes(bufferSize); + + size_t paddingLength = bufferSize - length; + if (paddingLength > 0) { + uint8_t padding = BN_is_negative(bignum) ? 0xFF : 0x00; + for (size_t i = 0; i < paddingLength; i++) + bytes[i] = padding; + } + BN_bn2bin(bignum, bytes.data() + paddingLength); + return bytes; +} + +BIGNUMPtr convertToBigNumber(const Vector<uint8_t>& bytes) +{ + return BIGNUMPtr(BN_bin2bn(bytes.data(), bytes.size(), nullptr)); +} + +bool AESKey::setKey(const Vector<uint8_t>& key, int enc) +{ + size_t keySize = key.size() * 8; + if (keySize != 128 && keySize != 192 && keySize != 256) + return false; + + if (enc == AES_ENCRYPT) { + if (AES_set_encrypt_key(key.data(), keySize, &m_key) < 0) + return false; + return true; + } + + if (enc == AES_DECRYPT) { + if (AES_set_decrypt_key(key.data(), keySize, &m_key) < 0) + return false; + return true; + } + + ASSERT_NOT_REACHED(); + return false; +} + +AESKey::~AESKey() +{ + memset(&m_key, 0, sizeof m_key); +} + +} // namespace WebCore + + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/OpenSSLUtilities.h b/src/bun.js/bindings/webcrypto/OpenSSLUtilities.h new file mode 100644 index 000000000..53d884c58 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/OpenSSLUtilities.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 Sony Interactive Entertainment Inc. + * + * 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. + */ + +#pragma once + +#include "CryptoAlgorithmIdentifier.h" +#include "OpenSSLCryptoUniquePtr.h" +#include <openssl/aes.h> +#include <openssl/evp.h> +#include <stdint.h> +#include <wtf/Noncopyable.h> +#include <wtf/Vector.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +const EVP_MD* digestAlgorithm(CryptoAlgorithmIdentifier hashFunction); + +std::optional<Vector<uint8_t>> calculateDigest(const EVP_MD* algorithm, const Vector<uint8_t>& message); + +Vector<uint8_t> convertToBytes(const BIGNUM*); + +Vector<uint8_t> convertToBytesExpand(const BIGNUM*, size_t bufferSize); + +BIGNUMPtr convertToBigNumber(const Vector<uint8_t>& bytes); + +class AESKey { + WTF_MAKE_NONCOPYABLE(AESKey); +public: + AESKey() = default; + ~AESKey(); + + bool setKey(const Vector<uint8_t>& key, int enc /* AES_ENCRYPT or AES_DECRYPT */); + + AES_KEY* key() { return &m_key; } +private: + AES_KEY m_key; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/Pbkdf2Params.idl b/src/bun.js/bindings/webcrypto/Pbkdf2Params.idl new file mode 100644 index 000000000..6d3cf6a2a --- /dev/null +++ b/src/bun.js/bindings/webcrypto/Pbkdf2Params.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 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. + */ + +typedef (object or DOMString) HashAlgorithmIdentifier; + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmPbkdf2Params, +] dictionary Pbkdf2Params : CryptoAlgorithmParameters { + required BufferSource salt; + required [EnforceRange] unsigned long iterations; + required HashAlgorithmIdentifier hash; +}; diff --git a/src/bun.js/bindings/webcrypto/RsaHashedImportParams.idl b/src/bun.js/bindings/webcrypto/RsaHashedImportParams.idl new file mode 100644 index 000000000..29136ca54 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/RsaHashedImportParams.idl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +typedef (object or DOMString) HashAlgorithmIdentifier; + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmRsaHashedImportParams +] dictionary RsaHashedImportParams : CryptoAlgorithmParameters { + // The hash algorithm to use + required HashAlgorithmIdentifier hash; +}; diff --git a/src/bun.js/bindings/webcrypto/RsaHashedKeyGenParams.idl b/src/bun.js/bindings/webcrypto/RsaHashedKeyGenParams.idl new file mode 100644 index 000000000..eed495d55 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/RsaHashedKeyGenParams.idl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +typedef (object or DOMString) HashAlgorithmIdentifier; + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmRsaHashedKeyGenParams +] dictionary RsaHashedKeyGenParams : RsaKeyGenParams { + // The hash algorithm to use + required HashAlgorithmIdentifier hash; +}; diff --git a/src/bun.js/bindings/webcrypto/RsaKeyGenParams.idl b/src/bun.js/bindings/webcrypto/RsaKeyGenParams.idl new file mode 100644 index 000000000..e7d3862cb --- /dev/null +++ b/src/bun.js/bindings/webcrypto/RsaKeyGenParams.idl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmRsaKeyGenParams +] dictionary RsaKeyGenParams : CryptoAlgorithmParameters { + // The length, in bits, of the RSA modulus + required [EnforceRange] unsigned long modulusLength; + // The RSA public exponent + required Uint8Array publicExponent; +}; diff --git a/src/bun.js/bindings/webcrypto/RsaOaepParams.idl b/src/bun.js/bindings/webcrypto/RsaOaepParams.idl new file mode 100644 index 000000000..615c677c3 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/RsaOaepParams.idl @@ -0,0 +1,32 @@ +/* +* 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. +*/ + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmRsaOaepParams +] dictionary RsaOaepParams : CryptoAlgorithmParameters { + // The optional label/application data to associate with the message + BufferSource label; +}; diff --git a/src/bun.js/bindings/webcrypto/RsaOtherPrimesInfo.h b/src/bun.js/bindings/webcrypto/RsaOtherPrimesInfo.h new file mode 100644 index 000000000..1a8adc7ce --- /dev/null +++ b/src/bun.js/bindings/webcrypto/RsaOtherPrimesInfo.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#pragma once + +#include <wtf/text/WTFString.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +struct RsaOtherPrimesInfo { + String r; + String d; + String t; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/RsaOtherPrimesInfo.idl b/src/bun.js/bindings/webcrypto/RsaOtherPrimesInfo.idl new file mode 100644 index 000000000..9b1f30e2b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/RsaOtherPrimesInfo.idl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +[ + Conditional=WEB_CRYPTO, + JSGenerateToJSObject, +] dictionary RsaOtherPrimesInfo { + // The following fields are defined in Section 6.3.2.7 of JSON Web Algorithms + required DOMString r; + required DOMString d; + required DOMString t; +}; diff --git a/src/bun.js/bindings/webcrypto/RsaPssParams.idl b/src/bun.js/bindings/webcrypto/RsaPssParams.idl new file mode 100644 index 000000000..9a728324f --- /dev/null +++ b/src/bun.js/bindings/webcrypto/RsaPssParams.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 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. + */ + +[ + Conditional=WEB_CRYPTO, + ImplementedAs=CryptoAlgorithmRsaPssParams +] dictionary RsaPssParams : CryptoAlgorithmParameters { + // The desired length of the random salt + required [EnforceRange] unsigned long saltLength; +}; diff --git a/src/bun.js/bindings/webcrypto/SerializedCryptoKeyWrap.h b/src/bun.js/bindings/webcrypto/SerializedCryptoKeyWrap.h new file mode 100644 index 000000000..f1cf02058 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/SerializedCryptoKeyWrap.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014 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. + */ + +#pragma once + +#include <wtf/Forward.h> +#include <wtf/text/WTFString.h> + +#if ENABLE(WEB_CRYPTO) + +namespace WebCore { + +// The purpose of the following APIs is to protect serialized CryptoKey data in IndexedDB or +// any other local storage that go through the structured clone algorithm. However, a side effect +// of this extra layer of protection is redundant communications between mainThread(document) and +// workerThreads. Please refer to WorkerGlobalScope for detailed explanation. P.S. This extra layer +// of protection is not required by the spec as of 11 December 2014: +// https://www.w3.org/TR/WebCryptoAPI/#security-developers + +WEBCORE_EXPORT std::optional<Vector<uint8_t>> defaultWebCryptoMasterKey(); +WEBCORE_EXPORT bool deleteDefaultWebCryptoMasterKey(); + +WEBCORE_EXPORT bool wrapSerializedCryptoKey(const Vector<uint8_t>& masterKey, const Vector<uint8_t>& key, Vector<uint8_t>& result); +WEBCORE_EXPORT bool unwrapSerializedCryptoKey(const Vector<uint8_t>& masterKey, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key); + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/SerializedCryptoKeyWrapOpenSSL.cpp b/src/bun.js/bindings/webcrypto/SerializedCryptoKeyWrapOpenSSL.cpp new file mode 100644 index 000000000..50088d542 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/SerializedCryptoKeyWrapOpenSSL.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * 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 "SerializedCryptoKeyWrap.h" + +#include "CryptoAlgorithmAES_CTR.h" + +#if ENABLE(WEB_CRYPTO) + +// #include "NotImplemented.h" + +namespace WebCore { + +std::optional<Vector<uint8_t>> defaultWebCryptoMasterKey() +{ + // notImplemented(); + return std::nullopt; +} + +// Initially these helper functions were intended to perform KEK wrapping and unwrapping, +// but this is not required anymore, despite the function names and the Mac implementation +// still indicating otherwise. +// See https://bugs.webkit.org/show_bug.cgi?id=173883 for more info. + +bool wrapSerializedCryptoKey(const Vector<uint8_t>& masterKey, const Vector<uint8_t>& key, Vector<uint8_t>& result) +{ + UNUSED_PARAM(masterKey); + + // No wrapping performed -- the serialized key data is copied into the `result` variable. + result = Vector<uint8_t>(key); + return true; +} + +bool unwrapSerializedCryptoKey(const Vector<uint8_t>& masterKey, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) +{ + UNUSED_PARAM(masterKey); + + // No unwrapping performed -- the serialized key data is copied into the `key` variable. + key = Vector<uint8_t>(wrappedKey); + return true; +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp new file mode 100644 index 000000000..d8b7d7942 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp @@ -0,0 +1,1193 @@ +/* + * Copyright (C) 2016-2019 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SubtleCrypto.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithm.h" +#include "CryptoAlgorithmRegistry.h" +#include "JSAesCbcCfbParams.h" +#include "JSAesCtrParams.h" +#include "JSAesGcmParams.h" +#include "JSAesKeyParams.h" +#include "JSCryptoAlgorithmParameters.h" +#include "JSCryptoKey.h" +#include "JSCryptoKeyPair.h" +#include "JSDOMPromiseDeferred.h" +#include "JSDOMWrapper.h" +#include "JSEcKeyParams.h" +#include "JSEcdhKeyDeriveParams.h" +#include "JSEcdsaParams.h" +#include "JSHkdfParams.h" +#include "JSHmacKeyParams.h" +#include "JSJsonWebKey.h" +#include "JSPbkdf2Params.h" +#include "JSRsaHashedImportParams.h" +#include "JSRsaHashedKeyGenParams.h" +#include "JSRsaKeyGenParams.h" +#include "JSRsaOaepParams.h" +#include "JSRsaPssParams.h" +#include <JavaScriptCore/JSONObject.h> + +namespace WebCore { +using namespace JSC; + +SubtleCrypto::SubtleCrypto(ScriptExecutionContext* context) + : ContextDestructionObserver(context) + , m_workQueue(WorkQueue::create("com.apple.WebKit.CryptoQueue")) +{ +} + +SubtleCrypto::~SubtleCrypto() = default; + +enum class Operations { + Encrypt, + Decrypt, + Sign, + Verify, + Digest, + GenerateKey, + DeriveBits, + ImportKey, + WrapKey, + UnwrapKey, + GetKeyLength +}; + +static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAlgorithmParameters(JSGlobalObject&, WebCore::SubtleCrypto::AlgorithmIdentifier, Operations); + +static ExceptionOr<CryptoAlgorithmIdentifier> toHashIdentifier(JSGlobalObject& state, SubtleCrypto::AlgorithmIdentifier algorithmIdentifier) +{ + auto digestParams = normalizeCryptoAlgorithmParameters(state, algorithmIdentifier, Operations::Digest); + if (digestParams.hasException()) + return digestParams.releaseException(); + return digestParams.returnValue()->identifier; +} + +static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAlgorithmParameters(JSGlobalObject& state, SubtleCrypto::AlgorithmIdentifier algorithmIdentifier, Operations operation) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (std::holds_alternative<String>(algorithmIdentifier)) { + auto newParams = Strong<JSObject>(vm, constructEmptyObject(&state)); + newParams->putDirect(vm, Identifier::fromString(vm, "name"_s), jsString(vm, std::get<String>(algorithmIdentifier))); + + return normalizeCryptoAlgorithmParameters(state, newParams, operation); + } + + auto& value = std::get<JSC::Strong<JSC::JSObject>>(algorithmIdentifier); + + auto params = convertDictionary<CryptoAlgorithmParameters>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + + auto identifier = CryptoAlgorithmRegistry::singleton().identifier(params.name); + if (UNLIKELY(!identifier)) + return Exception { NotSupportedError }; + + std::unique_ptr<CryptoAlgorithmParameters> result; + switch (operation) { + case Operations::Encrypt: + case Operations::Decrypt: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + case CryptoAlgorithmIdentifier::RSA_OAEP: { + auto params = convertDictionary<CryptoAlgorithmRsaOaepParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmRsaOaepParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CFB: { + auto params = convertDictionary<CryptoAlgorithmAesCbcCfbParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmAesCbcCfbParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_CTR: { + auto params = convertDictionary<CryptoAlgorithmAesCtrParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmAesCtrParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_GCM: { + auto params = convertDictionary<CryptoAlgorithmAesGcmParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmAesGcmParams>(params); + break; + } + default: + return Exception { NotSupportedError }; + } + break; + case Operations::Sign: + case Operations::Verify: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::HMAC: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + case CryptoAlgorithmIdentifier::ECDSA: { + auto params = convertDictionary<CryptoAlgorithmEcdsaParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmEcdsaParams>(params); + break; + } + case CryptoAlgorithmIdentifier::RSA_PSS: { + auto params = convertDictionary<CryptoAlgorithmRsaPssParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmRsaPssParams>(params); + break; + } + default: + return Exception { NotSupportedError }; + } + break; + case Operations::Digest: + switch (*identifier) { + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + default: + return Exception { NotSupportedError }; + } + break; + case Operations::GenerateKey: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: { + auto params = convertDictionary<CryptoAlgorithmRsaKeyGenParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmRsaKeyGenParams>(params); + break; + } + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: { + auto params = convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmRsaHashedKeyGenParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: { + auto params = convertDictionary<CryptoAlgorithmAesKeyParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmAesKeyParams>(params); + break; + } + case CryptoAlgorithmIdentifier::HMAC: { + auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmHmacKeyParams>(params); + break; + } + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: { + auto params = convertDictionary<CryptoAlgorithmEcKeyParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmEcKeyParams>(params); + break; + } + default: + return Exception { NotSupportedError }; + } + break; + case Operations::DeriveBits: + switch (*identifier) { + case CryptoAlgorithmIdentifier::ECDH: { + // Remove this hack once https://bugs.webkit.org/show_bug.cgi?id=169333 is fixed. + JSValue nameValue = value.get()->get(&state, Identifier::fromString(vm, "name"_s)); + JSValue publicValue = value.get()->get(&state, Identifier::fromString(vm, "public"_s)); + JSObject* newValue = constructEmptyObject(&state); + newValue->putDirect(vm, Identifier::fromString(vm, "name"_s), nameValue); + newValue->putDirect(vm, Identifier::fromString(vm, "publicKey"_s), publicValue); + + auto params = convertDictionary<CryptoAlgorithmEcdhKeyDeriveParams>(state, newValue); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmEcdhKeyDeriveParams>(params); + break; + } + case CryptoAlgorithmIdentifier::HKDF: { + auto params = convertDictionary<CryptoAlgorithmHkdfParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmHkdfParams>(params); + break; + } + case CryptoAlgorithmIdentifier::PBKDF2: { + auto params = convertDictionary<CryptoAlgorithmPbkdf2Params>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmPbkdf2Params>(params); + break; + } + default: + return Exception { NotSupportedError }; + } + break; + case Operations::ImportKey: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: { + auto params = convertDictionary<CryptoAlgorithmRsaHashedImportParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmRsaHashedImportParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + case CryptoAlgorithmIdentifier::HMAC: { + auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmHmacKeyParams>(params); + break; + } + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: { + auto params = convertDictionary<CryptoAlgorithmEcKeyParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmEcKeyParams>(params); + break; + } + case CryptoAlgorithmIdentifier::HKDF: + case CryptoAlgorithmIdentifier::PBKDF2: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + default: + return Exception { NotSupportedError }; + } + break; + case Operations::WrapKey: + case Operations::UnwrapKey: + switch (*identifier) { + case CryptoAlgorithmIdentifier::AES_KW: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + default: + return Exception { NotSupportedError }; + } + break; + case Operations::GetKeyLength: + switch (*identifier) { + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: { + auto params = convertDictionary<CryptoAlgorithmAesKeyParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + result = makeUnique<CryptoAlgorithmAesKeyParams>(params); + break; + } + case CryptoAlgorithmIdentifier::HMAC: { + auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value.get()); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + auto hashIdentifier = toHashIdentifier(state, params.hash); + if (hashIdentifier.hasException()) + return hashIdentifier.releaseException(); + params.hashIdentifier = hashIdentifier.releaseReturnValue(); + result = makeUnique<CryptoAlgorithmHmacKeyParams>(params); + break; + } + case CryptoAlgorithmIdentifier::HKDF: + case CryptoAlgorithmIdentifier::PBKDF2: + result = makeUnique<CryptoAlgorithmParameters>(params); + break; + default: + return Exception { NotSupportedError }; + } + break; + } + + result->identifier = *identifier; + return result; +} + +static CryptoKeyUsageBitmap toCryptoKeyUsageBitmap(CryptoKeyUsage usage) +{ + switch (usage) { + case CryptoKeyUsage::Encrypt: + return CryptoKeyUsageEncrypt; + case CryptoKeyUsage::Decrypt: + return CryptoKeyUsageDecrypt; + case CryptoKeyUsage::Sign: + return CryptoKeyUsageSign; + case CryptoKeyUsage::Verify: + return CryptoKeyUsageVerify; + case CryptoKeyUsage::DeriveKey: + return CryptoKeyUsageDeriveKey; + case CryptoKeyUsage::DeriveBits: + return CryptoKeyUsageDeriveBits; + case CryptoKeyUsage::WrapKey: + return CryptoKeyUsageWrapKey; + case CryptoKeyUsage::UnwrapKey: + return CryptoKeyUsageUnwrapKey; + } + + RELEASE_ASSERT_NOT_REACHED(); +} + +static CryptoKeyUsageBitmap toCryptoKeyUsageBitmap(const Vector<CryptoKeyUsage>& usages) +{ + CryptoKeyUsageBitmap result = 0; + // Maybe we shouldn't silently bypass duplicated usages? + for (auto usage : usages) + result |= toCryptoKeyUsageBitmap(usage); + + return result; +} + +// Maybe we want more specific error messages? +static void rejectWithException(Ref<DeferredPromise>&& passedPromise, ExceptionCode ec) +{ + switch (ec) { + case NotSupportedError: + passedPromise->reject(ec, "The algorithm is not supported"_s); + return; + case SyntaxError: + passedPromise->reject(ec, "A required parameter was missing or out-of-range"_s); + return; + case InvalidStateError: + passedPromise->reject(ec, "The requested operation is not valid for the current state of the provided key"_s); + return; + case InvalidAccessError: + passedPromise->reject(ec, "The requested operation is not valid for the provided key"_s); + return; + case UnknownError: + passedPromise->reject(ec, "The operation failed for an unknown transient reason (e.g. out of memory)"_s); + return; + case DataError: + passedPromise->reject(ec, "Data provided to an operation does not meet requirements"_s); + return; + case OperationError: + passedPromise->reject(ec, "The operation failed for an operation-specific reason"_s); + return; + default: + break; + } + ASSERT_NOT_REACHED(); +} + +static void normalizeJsonWebKey(JsonWebKey& webKey) +{ + // Maybe we shouldn't silently bypass duplicated usages? + webKey.usages = webKey.key_ops ? toCryptoKeyUsageBitmap(webKey.key_ops.value()) : 0; +} + +// FIXME: This returns an std::optional<KeyData> and takes a promise, rather than returning an +// ExceptionOr<KeyData> and letting the caller handle the promise, to work around an issue where +// Variant types (which KeyData is) in ExceptionOr<> cause compile issues on some platforms. This +// should be resolved by adopting a standards compliant std::variant (see https://webkit.org/b/175583) +static std::optional<KeyData> toKeyData(SubtleCrypto::KeyFormat format, SubtleCrypto::KeyDataVariant&& keyDataVariant, Ref<DeferredPromise>& promise) +{ + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: + return WTF::switchOn( + keyDataVariant, + [&promise](JsonWebKey&) -> std::optional<KeyData> { + promise->reject(Exception { TypeError }); + return std::nullopt; + }, + [](auto& bufferSource) -> std::optional<KeyData> { + return KeyData { Vector { static_cast<const uint8_t*>(bufferSource->data()), bufferSource->byteLength() } }; + }); + case SubtleCrypto::KeyFormat::Jwk: + return WTF::switchOn( + keyDataVariant, + [](JsonWebKey& webKey) -> std::optional<KeyData> { + normalizeJsonWebKey(webKey); + return KeyData { webKey }; + }, + [&promise](auto&) -> std::optional<KeyData> { + promise->reject(Exception { TypeError }); + return std::nullopt; + }); + } + + RELEASE_ASSERT_NOT_REACHED(); +} + +static Vector<uint8_t> copyToVector(BufferSource&& data) +{ + return { data.data(), data.length() }; +} + +static bool isSupportedExportKey(CryptoAlgorithmIdentifier identifier) +{ + switch (identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + case CryptoAlgorithmIdentifier::HMAC: + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + return true; + default: + return false; + } +} + +RefPtr<DeferredPromise> getPromise(DeferredPromise* index, WeakPtr<SubtleCrypto> weakThis) +{ + if (weakThis) + return weakThis->m_pendingPromises.take(index); + return nullptr; +} + +static std::unique_ptr<CryptoAlgorithmParameters> crossThreadCopyImportParams(const CryptoAlgorithmParameters& importParams) +{ + switch (importParams.parametersClass()) { + case CryptoAlgorithmParameters::Class::None: { + auto result = makeUnique<CryptoAlgorithmParameters>(); + result->identifier = importParams.identifier; + return result; + } + case CryptoAlgorithmParameters::Class::EcKeyParams: + return makeUnique<CryptoAlgorithmEcKeyParams>(crossThreadCopy(downcast<CryptoAlgorithmEcKeyParams>(importParams))); + case CryptoAlgorithmParameters::Class::HmacKeyParams: + return makeUnique<CryptoAlgorithmHmacKeyParams>(crossThreadCopy(downcast<CryptoAlgorithmHmacKeyParams>(importParams))); + case CryptoAlgorithmParameters::Class::RsaHashedImportParams: + return makeUnique<CryptoAlgorithmRsaHashedImportParams>(crossThreadCopy(downcast<CryptoAlgorithmRsaHashedImportParams>(importParams))); + default: + ASSERT_NOT_REACHED(); + return nullptr; + } +} + +void SubtleCrypto::addAuthenticatedEncryptionWarningIfNecessary(CryptoAlgorithmIdentifier algorithmIdentifier) +{ + // if (algorithmIdentifier == CryptoAlgorithmIdentifier::AES_CBC || algorithmIdentifier == CryptoAlgorithmIdentifier::AES_CTR) { + // if (!scriptExecutionContext()->hasLoggedAuthenticatedEncryptionWarning()) { + // scriptExecutionContext()->addConsoleMessage(MessageSource::Security, MessageLevel::Warning, "AES-CBC and AES-CTR do not provide authentication by default, and implementing it manually can result in minor, but serious mistakes. We recommended using authenticated encryption like AES-GCM to protect against chosen-ciphertext attacks."_s); + // scriptExecutionContext()->setHasLoggedAuthenticatedEncryptionWarning(true); + // } + // } +} + +// MARK: - Exposed functions. + +void SubtleCrypto::encrypt(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise) +{ + addAuthenticatedEncryptionWarningIfNecessary(key.algorithmIdentifier()); + + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Encrypt); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto data = copyToVector(WTFMove(dataBufferSource)); + + if (params->identifier != key.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s); + return; + } + + if (!key.allows(CryptoKeyUsageEncrypt)) { + promise->reject(InvalidAccessError, "CryptoKey doesn't support encryption"_s); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier()); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](const Vector<uint8_t>& cipherText) mutable { + if (auto promise = getPromise(index, weakThis)) + fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), cipherText.data(), cipherText.size()); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + algorithm->encrypt(*params, key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +void SubtleCrypto::decrypt(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise) +{ + addAuthenticatedEncryptionWarningIfNecessary(key.algorithmIdentifier()); + + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Decrypt); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto data = copyToVector(WTFMove(dataBufferSource)); + + if (params->identifier != key.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s); + return; + } + + if (!key.allows(CryptoKeyUsageDecrypt)) { + promise->reject(InvalidAccessError, "CryptoKey doesn't support decryption"_s); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier()); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](const Vector<uint8_t>& plainText) mutable { + if (auto promise = getPromise(index, weakThis)) + fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), plainText.data(), plainText.size()); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + algorithm->decrypt(*params, key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +void SubtleCrypto::sign(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise) +{ + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Sign); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto data = copyToVector(WTFMove(dataBufferSource)); + + if (params->identifier != key.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s); + return; + } + + if (!key.allows(CryptoKeyUsageSign)) { + promise->reject(InvalidAccessError, "CryptoKey doesn't support signing"_s); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier()); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](const Vector<uint8_t>& signature) mutable { + if (auto promise = getPromise(index, weakThis)) + fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), signature.data(), signature.size()); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + algorithm->sign(*params, key, WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +void SubtleCrypto::verify(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& signatureBufferSource, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise) +{ + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Verify); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto signature = copyToVector(WTFMove(signatureBufferSource)); + auto data = copyToVector(WTFMove(dataBufferSource)); + + if (params->identifier != key.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s); + return; + } + + if (!key.allows(CryptoKeyUsageVerify)) { + promise->reject(InvalidAccessError, "CryptoKey doesn't support verification"_s); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier()); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](bool result) mutable { + if (auto promise = getPromise(index, weakThis)) + promise->resolve<IDLBoolean>(result); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + algorithm->verify(*params, key, WTFMove(signature), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +void SubtleCrypto::digest(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, BufferSource&& dataBufferSource, Ref<DeferredPromise>&& promise) +{ + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Digest); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto data = copyToVector(WTFMove(dataBufferSource)); + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](const Vector<uint8_t>& digest) mutable { + if (auto promise = getPromise(index, weakThis)) + fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), digest.data(), digest.size()); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + algorithm->digest(WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +void SubtleCrypto::generateKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise) +{ + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::GenerateKey); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages); + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](KeyOrKeyPair&& keyOrKeyPair) mutable { + if (auto promise = getPromise(index, weakThis)) { + 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, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + // The 26 January 2017 version of the specification suggests we should perform the following task asynchronously + // regardless what kind of keys it produces: https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-generateKey + // That's simply not efficient for AES, HMAC and EC keys. Therefore, we perform it as an async task only for RSA keys. + algorithm->generateKey(*params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext()); +} + +void SubtleCrypto::deriveKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& baseKey, AlgorithmIdentifier&& derivedKeyType, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise) +{ + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::DeriveBits); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto importParamsOrException = normalizeCryptoAlgorithmParameters(state, derivedKeyType, Operations::ImportKey); + if (importParamsOrException.hasException()) { + promise->reject(importParamsOrException.releaseException()); + return; + } + auto importParams = importParamsOrException.releaseReturnValue(); + + auto getLengthParamsOrException = normalizeCryptoAlgorithmParameters(state, derivedKeyType, Operations::GetKeyLength); + if (getLengthParamsOrException.hasException()) { + promise->reject(getLengthParamsOrException.releaseException()); + return; + } + auto getLengthParams = getLengthParamsOrException.releaseReturnValue(); + + auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages); + + if (params->identifier != baseKey.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s); + return; + } + + if (!baseKey.allows(CryptoKeyUsageDeriveKey)) { + promise->reject(InvalidAccessError, "CryptoKey doesn't support CryptoKey derivation"_s); + return; + } + + auto getLengthAlgorithm = CryptoAlgorithmRegistry::singleton().create(getLengthParams->identifier); + + auto result = getLengthAlgorithm->getKeyLength(*getLengthParams); + if (result.hasException()) { + promise->reject(result.releaseException().code(), "Cannot get key length from derivedKeyType"_s); + return; + } + size_t length = result.releaseReturnValue(); + + auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(importParams->identifier); + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis, importAlgorithm = WTFMove(importAlgorithm), importParams = crossThreadCopyImportParams(*importParams), extractable, keyUsagesBitmap](const Vector<uint8_t>& derivedKey) mutable { + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=169395 + KeyData data = derivedKey; + auto callback = [index, weakThis](CryptoKey& key) mutable { + if (auto promise = getPromise(index, weakThis)) { + if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) { + rejectWithException(promise.releaseNonNull(), SyntaxError); + return; + } + promise->resolve<IDLInterface<CryptoKey>>(key); + } + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + importAlgorithm->importKey(SubtleCrypto::KeyFormat::Raw, WTFMove(data), *importParams, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback)); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + algorithm->deriveBits(*params, baseKey, length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +void SubtleCrypto::deriveBits(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& baseKey, unsigned length, Ref<DeferredPromise>&& promise) +{ + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::DeriveBits); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + if (params->identifier != baseKey.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "CryptoKey doesn't match AlgorithmIdentifier"_s); + return; + } + + if (!baseKey.allows(CryptoKeyUsageDeriveBits)) { + promise->reject(InvalidAccessError, "CryptoKey doesn't support bits derivation"_s); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](const Vector<uint8_t>& derivedKey) mutable { + if (auto promise = getPromise(index, weakThis)) + fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), derivedKey.data(), derivedKey.size()); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + algorithm->deriveBits(*params, baseKey, length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +void SubtleCrypto::importKey(JSC::JSGlobalObject& state, KeyFormat format, KeyDataVariant&& keyDataVariant, AlgorithmIdentifier&& algorithmIdentifier, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise) +{ + auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::ImportKey); + if (paramsOrException.hasException()) { + promise->reject(paramsOrException.releaseException()); + return; + } + auto params = paramsOrException.releaseReturnValue(); + + auto keyDataOrNull = toKeyData(format, WTFMove(keyDataVariant), promise); + if (!keyDataOrNull) { + // When toKeyData, it means the promise has been rejected, and we should return. + return; + } + + auto keyData = *keyDataOrNull; + auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages); + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](CryptoKey& key) mutable { + if (auto promise = getPromise(index, weakThis)) { + if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) { + rejectWithException(promise.releaseNonNull(), SyntaxError); + return; + } + promise->resolve<IDLInterface<CryptoKey>>(key); + } + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + algorithm->importKey(format, WTFMove(keyData), *params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback)); +} + +void SubtleCrypto::exportKey(KeyFormat format, CryptoKey& key, Ref<DeferredPromise>&& promise) +{ + if (!isSupportedExportKey(key.algorithmIdentifier())) { + promise->reject(Exception { NotSupportedError }); + return; + } + + if (!key.extractable()) { + promise->reject(InvalidAccessError, "The CryptoKey is nonextractable"_s); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier()); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis](SubtleCrypto::KeyFormat format, KeyData&& key) mutable { + if (auto promise = getPromise(index, weakThis)) { + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: { + Vector<uint8_t>& rawKey = std::get<Vector<uint8_t>>(key); + fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), rawKey.data(), rawKey.size()); + return; + } + case SubtleCrypto::KeyFormat::Jwk: + promise->resolve<IDLDictionary<JsonWebKey>>(WTFMove(std::get<JsonWebKey>(key))); + return; + } + ASSERT_NOT_REACHED(); + } + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-exportKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + algorithm->exportKey(format, key, WTFMove(callback), WTFMove(exceptionCallback)); +} + +void SubtleCrypto::wrapKey(JSC::JSGlobalObject& state, KeyFormat format, CryptoKey& key, CryptoKey& wrappingKey, AlgorithmIdentifier&& wrapAlgorithmIdentifier, Ref<DeferredPromise>&& promise) +{ + bool isEncryption = false; + + auto wrapParamsOrException = normalizeCryptoAlgorithmParameters(state, wrapAlgorithmIdentifier, Operations::WrapKey); + if (wrapParamsOrException.hasException()) { + ASSERT(wrapParamsOrException.exception().code() != ExistingExceptionError); + + wrapParamsOrException = normalizeCryptoAlgorithmParameters(state, wrapAlgorithmIdentifier, Operations::Encrypt); + if (wrapParamsOrException.hasException()) { + promise->reject(wrapParamsOrException.releaseException()); + return; + } + + isEncryption = true; + } + auto wrapParams = wrapParamsOrException.releaseReturnValue(); + + if (wrapParams->identifier != wrappingKey.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "Wrapping CryptoKey doesn't match AlgorithmIdentifier"_s); + return; + } + + if (!wrappingKey.allows(CryptoKeyUsageWrapKey)) { + promise->reject(InvalidAccessError, "Wrapping CryptoKey doesn't support wrapKey operation"_s); + return; + } + + if (!isSupportedExportKey(key.algorithmIdentifier())) { + promise->reject(Exception { NotSupportedError }); + return; + } + + if (!key.extractable()) { + promise->reject(InvalidAccessError, "The CryptoKey is nonextractable"_s); + return; + } + + auto exportAlgorithm = CryptoAlgorithmRegistry::singleton().create(key.algorithmIdentifier()); + auto wrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(wrappingKey.algorithmIdentifier()); + + auto context = scriptExecutionContext(); + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis, wrapAlgorithm, wrappingKey = Ref { wrappingKey }, wrapParams = WTFMove(wrapParams), isEncryption, context, workQueue = m_workQueue](SubtleCrypto::KeyFormat format, KeyData&& key) mutable { + if (weakThis) { + if (auto promise = weakThis->m_pendingPromises.get(index)) { + Vector<uint8_t> bytes; + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: + bytes = std::get<Vector<uint8_t>>(key); + break; + case SubtleCrypto::KeyFormat::Jwk: { + // FIXME: Converting to JS just to JSON-Stringify seems inefficient. We should find a way to go directly from the struct to JSON. + auto jwk = toJS<IDLDictionary<JsonWebKey>>(*(promise->globalObject()), *(promise->globalObject()), WTFMove(std::get<JsonWebKey>(key))); + String jwkString = JSONStringify(promise->globalObject(), jwk, 0); + CString jwkUTF8String = jwkString.utf8(StrictConversion); + bytes.append(jwkUTF8String.data(), jwkUTF8String.length()); + } + } + + auto callback = [index, weakThis](const Vector<uint8_t>& wrappedKey) mutable { + if (auto promise = getPromise(index, weakThis)) + fulfillPromiseWithArrayBuffer(promise.releaseNonNull(), wrappedKey.data(), wrappedKey.size()); + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + if (!isEncryption) { + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + wrapAlgorithm->wrapKey(wrappingKey.get(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback)); + return; + } + // The following operation should be performed asynchronously. + wrapAlgorithm->encrypt(*wrapParams, WTFMove(wrappingKey), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback), *context, workQueue); + } + } + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + // The following operation should be performed synchronously. + exportAlgorithm->exportKey(format, key, WTFMove(callback), WTFMove(exceptionCallback)); +} + +void SubtleCrypto::unwrapKey(JSC::JSGlobalObject& state, KeyFormat format, BufferSource&& wrappedKeyBufferSource, CryptoKey& unwrappingKey, AlgorithmIdentifier&& unwrapAlgorithmIdentifier, AlgorithmIdentifier&& unwrappedKeyAlgorithmIdentifier, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&& promise) +{ + auto wrappedKey = copyToVector(WTFMove(wrappedKeyBufferSource)); + + bool isDecryption = false; + + auto unwrapParamsOrException = normalizeCryptoAlgorithmParameters(state, unwrapAlgorithmIdentifier, Operations::UnwrapKey); + if (unwrapParamsOrException.hasException()) { + unwrapParamsOrException = normalizeCryptoAlgorithmParameters(state, unwrapAlgorithmIdentifier, Operations::Decrypt); + if (unwrapParamsOrException.hasException()) { + promise->reject(unwrapParamsOrException.releaseException()); + return; + } + + isDecryption = true; + } + auto unwrapParams = unwrapParamsOrException.releaseReturnValue(); + + auto unwrappedKeyAlgorithmOrException = normalizeCryptoAlgorithmParameters(state, unwrappedKeyAlgorithmIdentifier, Operations::ImportKey); + if (unwrappedKeyAlgorithmOrException.hasException()) { + promise->reject(unwrappedKeyAlgorithmOrException.releaseException()); + return; + } + auto unwrappedKeyAlgorithm = unwrappedKeyAlgorithmOrException.releaseReturnValue(); + + auto keyUsagesBitmap = toCryptoKeyUsageBitmap(keyUsages); + + if (unwrapParams->identifier != unwrappingKey.algorithmIdentifier()) { + promise->reject(InvalidAccessError, "Unwrapping CryptoKey doesn't match unwrap AlgorithmIdentifier"_s); + return; + } + + if (!unwrappingKey.allows(CryptoKeyUsageUnwrapKey)) { + promise->reject(InvalidAccessError, "Unwrapping CryptoKey doesn't support unwrapKey operation"_s); + return; + } + + auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappedKeyAlgorithm->identifier); + if (UNLIKELY(!importAlgorithm)) { + promise->reject(Exception { NotSupportedError }); + return; + } + + auto unwrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappingKey.algorithmIdentifier()); + if (UNLIKELY(!unwrapAlgorithm)) { + promise->reject(Exception { NotSupportedError }); + return; + } + + auto index = promise.ptr(); + m_pendingPromises.add(index, WTFMove(promise)); + WeakPtr weakThis { *this }; + auto callback = [index, weakThis, format, importAlgorithm, unwrappedKeyAlgorithm = crossThreadCopyImportParams(*unwrappedKeyAlgorithm), extractable, keyUsagesBitmap](const Vector<uint8_t>& bytes) mutable { + if (weakThis) { + if (RefPtr promise = weakThis->m_pendingPromises.get(index)) { + KeyData keyData; + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: + keyData = bytes; + break; + case SubtleCrypto::KeyFormat::Jwk: { + auto& state = *(promise->globalObject()); + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + String jwkString(bytes.data(), bytes.size()); + JSLockHolder locker(vm); + auto jwkObject = JSONParse(&state, jwkString); + if (!jwkObject) { + promise->reject(DataError, "WrappedKey cannot be converted to a JSON object"_s); + return; + } + auto jwk = convert<IDLDictionary<JsonWebKey>>(state, jwkObject); + RETURN_IF_EXCEPTION(scope, void()); + normalizeJsonWebKey(jwk); + + keyData = jwk; + break; + } + } + + auto callback = [index, weakThis](CryptoKey& key) mutable { + if (auto promise = getPromise(index, weakThis)) { + if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) { + rejectWithException(promise.releaseNonNull(), SyntaxError); + return; + } + promise->resolve<IDLInterface<CryptoKey>>(key); + } + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + // The following operation should be performed synchronously. + importAlgorithm->importKey(format, WTFMove(keyData), *unwrappedKeyAlgorithm, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback)); + } + } + }; + auto exceptionCallback = [index, weakThis](ExceptionCode ec) mutable { + if (auto promise = getPromise(index, weakThis)) + rejectWithException(promise.releaseNonNull(), ec); + }; + + if (!isDecryption) { + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-unwrapKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + unwrapAlgorithm->unwrapKey(unwrappingKey, WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback)); + return; + } + + unwrapAlgorithm->decrypt(*unwrapParams, unwrappingKey, WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext(), m_workQueue); +} + +} + +#endif diff --git a/src/bun.js/bindings/webcrypto/SubtleCrypto.h b/src/bun.js/bindings/webcrypto/SubtleCrypto.h new file mode 100644 index 000000000..5ee622250 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/SubtleCrypto.h @@ -0,0 +1,91 @@ +/* + * 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. + */ + +#pragma once + +#if ENABLE(WEB_CRYPTO) + +#include "ContextDestructionObserver.h" +#include "CryptoKeyFormat.h" +#include <JavaScriptCore/Strong.h> +#include <variant> +#include <wtf/Ref.h> +#include <wtf/RefCounted.h> +#include <wtf/WeakPtr.h> +#include <wtf/WorkQueue.h> + +namespace JSC { +class ArrayBufferView; +class ArrayBuffer; +class CallFrame; +} + +namespace WebCore { + +struct JsonWebKey; + +class BufferSource; +class CryptoKey; +class DeferredPromise; + +enum class CryptoAlgorithmIdentifier; +enum class CryptoKeyUsage; + +class SubtleCrypto : public ContextDestructionObserver, public RefCounted<SubtleCrypto>, public CanMakeWeakPtr<SubtleCrypto> { +public: + static Ref<SubtleCrypto> create(ScriptExecutionContext* context) { return adoptRef(*new SubtleCrypto(context)); } + ~SubtleCrypto(); + + using KeyFormat = CryptoKeyFormat; + + using AlgorithmIdentifier = std::variant<JSC::Strong<JSC::JSObject>, String>; + using KeyDataVariant = std::variant<RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, JsonWebKey>; + + void encrypt(JSC::JSGlobalObject&, AlgorithmIdentifier&&, CryptoKey&, BufferSource&& data, Ref<DeferredPromise>&&); + void decrypt(JSC::JSGlobalObject&, AlgorithmIdentifier&&, CryptoKey&, BufferSource&& data, Ref<DeferredPromise>&&); + void sign(JSC::JSGlobalObject&, AlgorithmIdentifier&&, CryptoKey&, BufferSource&& data, Ref<DeferredPromise>&&); + void verify(JSC::JSGlobalObject&, AlgorithmIdentifier&&, CryptoKey&, BufferSource&& signature, BufferSource&& data, Ref<DeferredPromise>&&); + void digest(JSC::JSGlobalObject&, AlgorithmIdentifier&&, BufferSource&& data, Ref<DeferredPromise>&&); + void generateKey(JSC::JSGlobalObject&, AlgorithmIdentifier&&, bool extractable, Vector<CryptoKeyUsage>&& keyUsages, Ref<DeferredPromise>&&); + void deriveKey(JSC::JSGlobalObject&, AlgorithmIdentifier&&, CryptoKey& baseKey, AlgorithmIdentifier&& derivedKeyType, bool extractable, Vector<CryptoKeyUsage>&&, Ref<DeferredPromise>&&); + void deriveBits(JSC::JSGlobalObject&, AlgorithmIdentifier&&, CryptoKey& baseKey, unsigned length, Ref<DeferredPromise>&&); + void importKey(JSC::JSGlobalObject&, KeyFormat, KeyDataVariant&&, AlgorithmIdentifier&&, bool extractable, Vector<CryptoKeyUsage>&&, Ref<DeferredPromise>&&); + void exportKey(KeyFormat, CryptoKey&, Ref<DeferredPromise>&&); + void wrapKey(JSC::JSGlobalObject&, KeyFormat, CryptoKey&, CryptoKey& wrappingKey, AlgorithmIdentifier&& wrapAlgorithm, Ref<DeferredPromise>&&); + void unwrapKey(JSC::JSGlobalObject&, KeyFormat, BufferSource&& wrappedKey, CryptoKey& unwrappingKey, AlgorithmIdentifier&& unwrapAlgorithm, AlgorithmIdentifier&& unwrappedKeyAlgorithm, bool extractable, Vector<CryptoKeyUsage>&&, Ref<DeferredPromise>&&); + +private: + explicit SubtleCrypto(ScriptExecutionContext*); + + void addAuthenticatedEncryptionWarningIfNecessary(CryptoAlgorithmIdentifier); + inline friend RefPtr<DeferredPromise> getPromise(DeferredPromise*, WeakPtr<SubtleCrypto>); + + Ref<WorkQueue> m_workQueue; + HashMap<DeferredPromise*, Ref<DeferredPromise>> m_pendingPromises; +}; + +} + +#endif diff --git a/src/bun.js/bindings/webcrypto/SubtleCrypto.idl b/src/bun.js/bindings/webcrypto/SubtleCrypto.idl new file mode 100644 index 000000000..358b9950b --- /dev/null +++ b/src/bun.js/bindings/webcrypto/SubtleCrypto.idl @@ -0,0 +1,48 @@ +/* + * 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. + */ + +enum KeyFormat { "raw", "spki", "pkcs8", "jwk" }; + +typedef (object or DOMString) AlgorithmIdentifier; + +[ + Conditional=WEB_CRYPTO, + Exposed=(Window,Worker), + GenerateIsReachable=ImplScriptExecutionContext, + SecureContext, +] interface SubtleCrypto { + [CallWith=CurrentGlobalObject] Promise<any> encrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); + [CallWith=CurrentGlobalObject] Promise<any> decrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); + [CallWith=CurrentGlobalObject] Promise<any> sign(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); + [CallWith=CurrentGlobalObject] Promise<any> verify(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource signature, BufferSource data); + [CallWith=CurrentGlobalObject] Promise<any> digest(AlgorithmIdentifier algorithm, BufferSource data); + [CallWith=CurrentGlobalObject] Promise<any> generateKey(AlgorithmIdentifier algorithm, boolean extractable, sequence<CryptoKeyUsage> keyUsages); + [CallWith=CurrentGlobalObject] Promise<any> deriveKey(AlgorithmIdentifier algorithm, CryptoKey baseKey, AlgorithmIdentifier derivedKeyType, boolean extractable, sequence<CryptoKeyUsage> keyUsages); + [CallWith=CurrentGlobalObject] Promise<ArrayBuffer> deriveBits(AlgorithmIdentifier algorithm, CryptoKey baseKey, unsigned long length); + [CallWith=CurrentGlobalObject] Promise<CryptoKey> importKey(KeyFormat format, (BufferSource or JsonWebKey) keyData, AlgorithmIdentifier algorithm, boolean extractable, sequence<CryptoKeyUsage> keyUsages); + Promise<any> exportKey(KeyFormat format, CryptoKey key); + [CallWith=CurrentGlobalObject] Promise<any> wrapKey(KeyFormat format, CryptoKey key, CryptoKey wrappingKey, AlgorithmIdentifier wrapAlgorithm); + [CallWith=CurrentGlobalObject] Promise<CryptoKey> unwrapKey(KeyFormat format, BufferSource wrappedKey, CryptoKey unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier unwrappedKeyAlgorithm, boolean extractable, sequence<CryptoKeyUsage> keyUsages); +}; diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index e17652754..d87a7edcb 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -204,6 +204,7 @@ const UnboundedQueue = @import("./unbounded_queue.zig").UnboundedQueue; pub const ConcurrentTask = struct { task: Task = undefined, next: ?*ConcurrentTask = null, + auto_delete: bool = false, pub const Queue = UnboundedQueue(ConcurrentTask, .next); @@ -326,6 +327,7 @@ pub const EventLoop = struct { writable[0] = task.task; writable = writable[1..]; this.tasks.count += 1; + if (task.auto_delete) bun.default_allocator.destroy(task); if (writable.len == 0) break; } diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 07c5318b2..9ba69aaa2 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -273,7 +273,8 @@ comptime { _ = Bun__getDefaultGlobal; _ = Bun__getVM; _ = Bun__drainMicrotasks; - _ = Bun__queueMicrotask; + _ = Bun__queueTask; + _ = Bun__queueTaskConcurrently; _ = Bun__handleRejectedPromise; _ = Bun__readOriginTimer; _ = Bun__onDidAppendPlugin; @@ -281,10 +282,24 @@ comptime { } } -pub export fn Bun__queueMicrotask(global: *JSGlobalObject, task: *JSC.CppTask) void { +/// This function is called on the main thread +/// The bunVM() call will assert this +pub export fn Bun__queueTask(global: *JSGlobalObject, task: *JSC.CppTask) void { global.bunVM().eventLoop().enqueueTask(Task.init(task)); } +/// This function is called on another thread +/// The main difference: we need to allocate the task & wakeup the thread +/// We can avoid that if we run it from the main thread. +pub export fn Bun__queueTaskConcurrently(global: *JSGlobalObject, task: *JSC.CppTask) void { + var concurrent = bun.default_allocator.create(JSC.ConcurrentTask) catch unreachable; + concurrent.* = JSC.ConcurrentTask{ + .task = Task.init(task), + .auto_delete = true, + }; + global.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(concurrent); +} + pub export fn Bun__handleRejectedPromise(global: *JSGlobalObject, promise: *JSC.JSPromise) void { const result = promise.result(global.vm()); global.bunVM().runErrorHandler(result, null); diff --git a/src/bun.js/webcore.zig b/src/bun.js/webcore.zig index ffc12ab99..c8bf7545d 100644 --- a/src/bun.js/webcore.zig +++ b/src/bun.js/webcore.zig @@ -395,19 +395,7 @@ pub const Crypto = struct { }; var slice = array_buffer.byteSlice(); - switch (slice.len) { - 0 => {}, - 1...JSC.RareData.EntropyCache.size / 8 => { - if (arguments.len > 1) { - bun.rand(slice); - } else { - std.mem.copy(u8, slice, globalThis.bunVM().rareData().entropySlice(slice.len)); - } - }, - else => { - bun.rand(slice); - }, - } + randomData(globalThis, slice.ptr, slice.len); return arguments[0]; } @@ -418,6 +406,17 @@ pub const Crypto = struct { array: *JSC.JSUint8Array, ) callconv(.C) JSC.JSValue { var slice = array.slice(); + randomData(globalThis, slice.ptr, slice.len); + return @intToEnum(JSC.JSValue, @bitCast(i64, @ptrToInt(array))); + } + + fn randomData( + globalThis: *JSC.JSGlobalObject, + ptr: [*]u8, + len: usize, + ) void { + var slice = ptr[0..len]; + switch (slice.len) { 0 => {}, // 512 bytes or less we reuse from the same cache as UUID generation. @@ -428,8 +427,6 @@ pub const Crypto = struct { bun.rand(slice); }, } - - return @intToEnum(JSC.JSValue, @bitCast(i64, @ptrToInt(array))); } pub fn randomUUID( |