| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-08-22 18:31:08 +01:00
										 |  |  |  * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org> | 
					
						
							| 
									
										
										
										
											2023-12-15 21:05:09 +01:00
										 |  |  |  * Copyright (c) 2023, stelar7 <dudedbz@gmail.com> | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 19:11:08 -07:00
										 |  |  | #include <AK/QuickSort.h>
 | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | #include <LibCrypto/Hash/HashManager.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/ArrayBuffer.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/Promise.h>
 | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  | #include <LibWeb/Bindings/ExceptionOrUtils.h>
 | 
					
						
							| 
									
										
										
											
												LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
											
										 
											2022-09-25 18:11:21 -06:00
										 |  |  | #include <LibWeb/Bindings/Intrinsics.h>
 | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | #include <LibWeb/Crypto/SubtleCrypto.h>
 | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  | #include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Platform/EventLoopPlugin.h>
 | 
					
						
							| 
									
										
										
										
											2022-09-24 16:14:37 +01:00
										 |  |  | #include <LibWeb/WebIDL/AbstractOperations.h>
 | 
					
						
							| 
									
										
										
										
											2023-11-23 20:07:25 +13:00
										 |  |  | #include <LibWeb/WebIDL/Buffers.h>
 | 
					
						
							| 
									
										
										
										
											2023-02-12 21:25:57 +01:00
										 |  |  | #include <LibWeb/WebIDL/ExceptionOr.h>
 | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  | #include <LibWeb/WebIDL/Promise.h>
 | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Web::Crypto { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 19:11:08 -07:00
										 |  |  | static void normalize_key_usages(Vector<Bindings::KeyUsage>& key_usages) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     quick_sort(key_usages); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-19 19:47:52 +01:00
										 |  |  | JS_DEFINE_ALLOCATOR(SubtleCrypto); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-13 13:05:26 +02:00
										 |  |  | JS::NonnullGCPtr<SubtleCrypto> SubtleCrypto::create(JS::Realm& realm) | 
					
						
							| 
									
										
										
										
											2022-09-03 19:59:53 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-13 13:05:26 +02:00
										 |  |  |     return realm.heap().allocate<SubtleCrypto>(realm, realm); | 
					
						
							| 
									
										
										
										
											2022-09-03 19:59:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
											
										 
											2022-09-25 18:11:21 -06:00
										 |  |  | SubtleCrypto::SubtleCrypto(JS::Realm& realm) | 
					
						
							|  |  |  |     : PlatformObject(realm) | 
					
						
							| 
									
										
										
										
											2022-09-03 19:59:53 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SubtleCrypto::~SubtleCrypto() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-07 08:41:28 +02:00
										 |  |  | void SubtleCrypto::initialize(JS::Realm& realm) | 
					
						
							| 
									
										
										
										
											2023-01-10 06:28:20 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-07 08:41:28 +02:00
										 |  |  |     Base::initialize(realm); | 
					
						
							| 
									
										
										
										
											2023-11-22 12:55:21 +13:00
										 |  |  |     set_prototype(&Bindings::ensure_web_prototype<Bindings::SubtleCryptoPrototype>(realm, "SubtleCrypto"_fly_string)); | 
					
						
							| 
									
										
										
										
											2023-01-10 06:28:20 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | // https://w3c.github.io/webcrypto/#dfn-normalize-an-algorithm
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  | WebIDL::ExceptionOr<SubtleCrypto::NormalizedAlgorithmAndParameter> SubtleCrypto::normalize_an_algorithm(AlgorithmIdentifier const& algorithm, String operation) | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     auto& realm = this->realm(); | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     auto& vm = this->vm(); | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // If alg is an instance of a DOMString:
 | 
					
						
							|  |  |  |     if (algorithm.has<String>()) { | 
					
						
							|  |  |  |         // Return the result of running the normalize an algorithm algorithm,
 | 
					
						
							|  |  |  |         // with the alg set to a new Algorithm dictionary whose name attribute is alg, and with the op set to op.
 | 
					
						
							|  |  |  |         auto dictionary = JS::make_handle(JS::Object::create(realm, realm.intrinsics().object_prototype())); | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |         TRY(dictionary->create_data_property("name", JS::PrimitiveString::create(vm, algorithm.get<String>()))); | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return normalize_an_algorithm(dictionary, operation); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // If alg is an object:
 | 
					
						
							|  |  |  |     // 1. Let registeredAlgorithms be the associative container stored at the op key of supportedAlgorithms.
 | 
					
						
							|  |  |  |     // NOTE: There should always be a container at the op key.
 | 
					
						
							|  |  |  |     auto internal_object = supported_algorithms(); | 
					
						
							|  |  |  |     auto maybe_registered_algorithms = internal_object.get(operation); | 
					
						
							|  |  |  |     auto registered_algorithms = maybe_registered_algorithms.value(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 2. Let initialAlg be the result of converting the ECMAScript object represented by alg to
 | 
					
						
							|  |  |  |     // the IDL dictionary type Algorithm, as defined by [WebIDL].
 | 
					
						
							|  |  |  |     // 3. If an error occurred, return the error and terminate this algorithm.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     // Note: We're not going to bother creating an Algorithm object, all we want is the name attribute so that we can
 | 
					
						
							|  |  |  |     //       fetch the actual algorithm factory from the registeredAlgorithms map.
 | 
					
						
							|  |  |  |     auto initial_algorithm = TRY(algorithm.get<JS::Handle<JS::Object>>()->get("name")); | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 4. Let algName be the value of the name attribute of initialAlg.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     auto algorithm_name = TRY(initial_algorithm.to_string(vm)); | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     RegisteredAlgorithm desired_type; | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 5. If registeredAlgorithms contains a key that is a case-insensitive string match for algName:
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     if (auto it = registered_algorithms.find(algorithm_name); it != registered_algorithms.end()) { | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  |         // 1. Set algName to the value of the matching key.
 | 
					
						
							|  |  |  |         // 2. Let desiredType be the IDL dictionary type stored at algName in registeredAlgorithms.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |         desired_type = it->value; | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // Otherwise:
 | 
					
						
							|  |  |  |         // Return a new NotSupportedError and terminate this algorithm.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |         return WebIDL::NotSupportedError::create(realm, MUST(String::formatted("Algorithm '{}' is not supported", algorithm_name))); | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 8. Let normalizedAlgorithm be the result of converting the ECMAScript object represented by alg
 | 
					
						
							|  |  |  |     // to the IDL dictionary type desiredType, as defined by [WebIDL].
 | 
					
						
							|  |  |  |     // 9. Set the name attribute of normalizedAlgorithm to algName.
 | 
					
						
							|  |  |  |     // 10. If an error occurred, return the error and terminate this algorithm.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     // 11. Let dictionaries be a list consisting of the IDL dictionary type desiredType
 | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  |     // and all of desiredType's inherited dictionaries, in order from least to most derived.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     // 12. For each dictionary dictionary in dictionaries:
 | 
					
						
							|  |  |  |     //    Note: All of these steps are handled by the create_methods and parameter_from_value methods.
 | 
					
						
							|  |  |  |     auto methods = desired_type.create_methods(realm); | 
					
						
							|  |  |  |     auto parameter = TRY(desired_type.parameter_from_value(vm, algorithm.get<JS::Handle<JS::Object>>())); | 
					
						
							|  |  |  |     auto normalized_algorithm = NormalizedAlgorithmAndParameter { move(methods), move(parameter) }; | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 13. Return normalizedAlgorithm.
 | 
					
						
							|  |  |  |     return normalized_algorithm; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
											
										 
											2022-09-25 18:11:21 -06:00
										 |  |  | // https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-digest
 | 
					
						
							| 
									
										
										
										
											2023-12-15 21:07:27 +01:00
										 |  |  | JS::NonnullGCPtr<JS::Promise> SubtleCrypto::digest(AlgorithmIdentifier const& algorithm, JS::Handle<WebIDL::BufferSource> const& data) | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
											
												LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
											
										 
											2022-09-25 18:11:21 -06:00
										 |  |  |     auto& realm = this->realm(); | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 1. Let algorithm be the algorithm parameter passed to the digest() method.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the digest() method.
 | 
					
						
							| 
									
										
										
										
											2023-11-23 20:07:25 +13:00
										 |  |  |     auto data_buffer_or_error = WebIDL::get_buffer_source_copy(*data->raw_object()); | 
					
						
							| 
									
										
										
										
											2024-03-08 15:37:28 +00:00
										 |  |  |     if (data_buffer_or_error.is_error()) | 
					
						
							|  |  |  |         return WebIDL::create_rejected_promise_from_exception(realm, WebIDL::OperationError::create(realm, "Failed to copy bytes from ArrayBuffer"_fly_string)); | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  |     auto data_buffer = data_buffer_or_error.release_value(); | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "digest".
 | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  |     auto normalized_algorithm = normalize_an_algorithm(algorithm, "digest"_string); | 
					
						
							| 
									
										
										
										
											2023-12-14 20:56:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  |     // 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
 | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  |     // FIXME: Spec bug: link to https://webidl.spec.whatwg.org/#a-promise-rejected-with
 | 
					
						
							| 
									
										
										
										
											2024-03-08 15:37:28 +00:00
										 |  |  |     if (normalized_algorithm.is_error()) | 
					
						
							|  |  |  |         return WebIDL::create_rejected_promise_from_exception(realm, normalized_algorithm.release_error()); | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 5. Let promise be a new Promise.
 | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  |     auto promise = WebIDL::create_promise(realm); | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 6. Return promise and perform the remaining steps in parallel.
 | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  |     Platform::EventLoopPlugin::the().deferred_invoke([&realm, algorithm_object = normalized_algorithm.release_value(), promise, data_buffer = move(data_buffer)]() -> void { | 
					
						
							|  |  |  |         HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
 | 
					
						
							|  |  |  |         // FIXME: Need spec reference to https://webidl.spec.whatwg.org/#reject
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 8. Let result be the result of performing the digest operation specified by normalizedAlgorithm using algorithm, with data as message.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |         auto result = algorithm_object.methods->digest(*algorithm_object.parameter, data_buffer); | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |         if (result.is_exception()) { | 
					
						
							|  |  |  |             WebIDL::reject_promise(realm, promise, Bindings::dom_exception_to_throw_completion(realm.vm(), result.release_error()).release_value().value()); | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 9. Resolve promise with result.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |         WebIDL::resolve_promise(realm, promise, result.release_value()); | 
					
						
							| 
									
										
										
										
											2024-01-23 11:52:15 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return verify_cast<JS::Promise>(*promise->promise()); | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 22:03:04 +01:00
										 |  |  | // https://w3c.github.io/webcrypto/#SubtleCrypto-method-importKey
 | 
					
						
							|  |  |  | JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Promise>> SubtleCrypto::import_key(Bindings::KeyFormat format, KeyDataType key_data, AlgorithmIdentifier algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto& realm = this->realm(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 1. Let format, algorithm, extractable and usages, be the format, algorithm, extractable
 | 
					
						
							|  |  |  |     // and key_usages parameters passed to the importKey() method, respectively.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Variant<ByteBuffer, Bindings::JsonWebKey, Empty> real_key_data; | 
					
						
							|  |  |  |     // 2. If format is equal to the string "raw", "pkcs8", or "spki":
 | 
					
						
							|  |  |  |     if (format == Bindings::KeyFormat::Raw || format == Bindings::KeyFormat::Pkcs8 || format == Bindings::KeyFormat::Spki) { | 
					
						
							|  |  |  |         // 1. If the keyData parameter passed to the importKey() method is a JsonWebKey dictionary, throw a TypeError.
 | 
					
						
							|  |  |  |         if (key_data.has<Bindings::JsonWebKey>()) { | 
					
						
							|  |  |  |             return realm.vm().throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 2. Let keyData be the result of getting a copy of the bytes held by the keyData parameter passed to the importKey() method.
 | 
					
						
							|  |  |  |         real_key_data = MUST(WebIDL::get_buffer_source_copy(*key_data.get<JS::Handle<WebIDL::BufferSource>>()->raw_object())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (format == Bindings::KeyFormat::Jwk) { | 
					
						
							|  |  |  |         // 1. If the keyData parameter passed to the importKey() method is not a JsonWebKey dictionary, throw a TypeError.
 | 
					
						
							|  |  |  |         if (!key_data.has<Bindings::JsonWebKey>()) { | 
					
						
							|  |  |  |             return realm.vm().throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "JsonWebKey"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 2. Let keyData be the keyData parameter passed to the importKey() method.
 | 
					
						
							|  |  |  |         real_key_data = key_data.get<Bindings::JsonWebKey>(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // NOTE: The spec jumps to 5 here for some reason?
 | 
					
						
							|  |  |  |     // 5. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "importKey".
 | 
					
						
							|  |  |  |     auto normalized_algorithm = normalize_an_algorithm(algorithm, "importKey"_string); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 6. If an error occurred, return a Promise rejected with normalizedAlgorithm.
 | 
					
						
							| 
									
										
										
										
											2024-03-08 15:37:28 +00:00
										 |  |  |     if (normalized_algorithm.is_error()) | 
					
						
							|  |  |  |         return WebIDL::create_rejected_promise_from_exception(realm, normalized_algorithm.release_error()); | 
					
						
							| 
									
										
										
										
											2023-12-15 22:03:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 7. Let promise be a new Promise.
 | 
					
						
							|  |  |  |     auto promise = WebIDL::create_promise(realm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 8. Return promise and perform the remaining steps in parallel.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 19:11:08 -07:00
										 |  |  |     Platform::EventLoopPlugin::the().deferred_invoke([&realm, real_key_data = move(real_key_data), normalized_algorithm = normalized_algorithm.release_value(), promise, format, extractable, key_usages = move(key_usages), algorithm = move(algorithm)]() mutable -> void { | 
					
						
							| 
									
										
										
										
											2023-12-15 22:03:04 +01:00
										 |  |  |         HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 9. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 10. Let result be the CryptoKey object that results from performing the import key operation
 | 
					
						
							|  |  |  |         // specified by normalizedAlgorithm using keyData, algorithm, format, extractable and usages.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |         auto maybe_result = normalized_algorithm.methods->import_key(*normalized_algorithm.parameter, format, real_key_data.downcast<CryptoKey::InternalKeyData>(), extractable, key_usages); | 
					
						
							| 
									
										
										
										
											2023-12-15 22:03:04 +01:00
										 |  |  |         if (maybe_result.is_error()) { | 
					
						
							|  |  |  |             WebIDL::reject_promise(realm, promise, Bindings::dom_exception_to_throw_completion(realm.vm(), maybe_result.release_error()).release_value().value()); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         auto result = maybe_result.release_value(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 11. If the [[type]] internal slot of result is "secret" or "private" and usages is empty, then throw a SyntaxError.
 | 
					
						
							|  |  |  |         if ((result->type() == Bindings::KeyType::Secret || result->type() == Bindings::KeyType::Private) && key_usages.is_empty()) { | 
					
						
							|  |  |  |             WebIDL::reject_promise(realm, promise, WebIDL::SyntaxError::create(realm, "usages must not be empty"_fly_string)); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 12. Set the [[extractable]] internal slot of result to extractable.
 | 
					
						
							|  |  |  |         result->set_extractable(extractable); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 13. Set the [[usages]] internal slot of result to the normalized value of usages.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 19:11:08 -07:00
										 |  |  |         normalize_key_usages(key_usages); | 
					
						
							|  |  |  |         result->set_usages(key_usages); | 
					
						
							| 
									
										
										
										
											2023-12-15 22:03:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // 14. Resolve promise with result.
 | 
					
						
							|  |  |  |         WebIDL::resolve_promise(realm, promise, result); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return verify_cast<JS::Promise>(*promise->promise()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | SubtleCrypto::SupportedAlgorithmsMap& SubtleCrypto::supported_algorithms_internal() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static SubtleCrypto::SupportedAlgorithmsMap s_supported_algorithms; | 
					
						
							|  |  |  |     return s_supported_algorithms; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 23:40:52 +01:00
										 |  |  | // https://w3c.github.io/webcrypto/#algorithm-normalization-internalS
 | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | SubtleCrypto::SupportedAlgorithmsMap SubtleCrypto::supported_algorithms() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto& internal_object = supported_algorithms_internal(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!internal_object.is_empty()) { | 
					
						
							|  |  |  |         return internal_object; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 1. For each value, v in the List of supported operations,
 | 
					
						
							|  |  |  |     // set the v key of the internal object supportedAlgorithms to a new associative container.
 | 
					
						
							|  |  |  |     auto supported_operations = Vector { | 
					
						
							|  |  |  |         "encrypt"_string, | 
					
						
							|  |  |  |         "decrypt"_string, | 
					
						
							|  |  |  |         "sign"_string, | 
					
						
							|  |  |  |         "verify"_string, | 
					
						
							|  |  |  |         "digest"_string, | 
					
						
							|  |  |  |         "deriveBits"_string, | 
					
						
							|  |  |  |         "wrapKey"_string, | 
					
						
							|  |  |  |         "unwrapKey"_string, | 
					
						
							|  |  |  |         "generateKey"_string, | 
					
						
							|  |  |  |         "importKey"_string, | 
					
						
							|  |  |  |         "exportKey"_string, | 
					
						
							|  |  |  |         "get key length"_string, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto& operation : supported_operations) { | 
					
						
							|  |  |  |         internal_object.set(operation, {}); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // https://w3c.github.io/webcrypto/#algorithm-conventions
 | 
					
						
							|  |  |  |     // https://w3c.github.io/webcrypto/#sha
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     define_an_algorithm<SHA>("digest"_string, "SHA-1"_string); | 
					
						
							|  |  |  |     define_an_algorithm<SHA>("digest"_string, "SHA-256"_string); | 
					
						
							|  |  |  |     define_an_algorithm<SHA>("digest"_string, "SHA-384"_string); | 
					
						
							|  |  |  |     define_an_algorithm<SHA>("digest"_string, "SHA-512"_string); | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 22:03:04 +01:00
										 |  |  |     // https://w3c.github.io/webcrypto/#pbkdf2
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     define_an_algorithm<PBKDF2>("importKey"_string, "PBKDF2"_string); | 
					
						
							| 
									
										
										
										
											2023-12-15 22:03:04 +01:00
										 |  |  |     // FIXME: define_an_algorithm("deriveBits"_string, "PBKDF2"_string, "Pbkdf2Params"_string);
 | 
					
						
							|  |  |  |     // FIXME: define_an_algorithm("get key length"_string, "PBKDF2"_string, ""_string);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  |     return internal_object; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // https://w3c.github.io/webcrypto/#concept-define-an-algorithm
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  | template<typename Methods, typename Param> | 
					
						
							|  |  |  | void SubtleCrypto::define_an_algorithm(AK::String op, AK::String algorithm) | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     auto& internal_object = supported_algorithms_internal(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 1. Let registeredAlgorithms be the associative container stored at the op key of supportedAlgorithms.
 | 
					
						
							|  |  |  |     // NOTE: There should always be a container at the op key.
 | 
					
						
							|  |  |  |     auto maybe_registered_algorithms = internal_object.get(op); | 
					
						
							|  |  |  |     auto registered_algorithms = maybe_registered_algorithms.value(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 2. Set the alg key of registeredAlgorithms to the IDL dictionary type type.
 | 
					
						
							| 
									
										
										
										
											2024-03-06 16:53:50 -07:00
										 |  |  |     registered_algorithms.set(algorithm, RegisteredAlgorithm { &Methods::create, &Param::from_value }); | 
					
						
							| 
									
										
										
										
											2023-12-14 00:38:14 +01:00
										 |  |  |     internal_object.set(op, registered_algorithms); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 22:09:55 +00:00
										 |  |  | } |