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>
2024-03-13 21:19:57 -06:00
# include <LibWeb/Crypto/KeyAlgorithms.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 ) ;
}
2024-03-14 21:52:17 -06:00
struct RegisteredAlgorithm {
NonnullOwnPtr < AlgorithmMethods > ( * create_methods ) ( JS : : Realm & ) = nullptr ;
JS : : ThrowCompletionOr < NonnullOwnPtr < AlgorithmParams > > ( * parameter_from_value ) ( JS : : VM & , JS : : Value ) = nullptr ;
} ;
using SupportedAlgorithmsMap = HashMap < String , HashMap < String , RegisteredAlgorithm , AK : : ASCIICaseInsensitiveStringTraits > > ;
static SupportedAlgorithmsMap & supported_algorithms_internal ( ) ;
static SupportedAlgorithmsMap supported_algorithms ( ) ;
template < typename Methods , typename Param = AlgorithmParams >
static void define_an_algorithm ( String op , String algorithm ) ;
2024-03-06 19:11:08 -07:00
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 ) ;
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( SubtleCrypto ) ;
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-14 21:52:17 -06:00
WebIDL : : ExceptionOr < NormalizedAlgorithmAndParameter > normalize_an_algorithm ( JS : : Realm & realm , AlgorithmIdentifier const & algorithm , String operation )
2023-12-14 00:38:14 +01:00
{
2024-03-14 21:52:17 -06:00
auto & vm = realm . 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
2024-03-14 21:52:17 -06:00
return normalize_an_algorithm ( realm , dictionary , operation ) ;
2023-12-14 00:38:14 +01:00
}
// 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-27 19:24:33 +01:00
return WebIDL : : NotSupportedError : : create ( realm , MUST ( String : : formatted ( " Algorithm '{}' is not supported for operation '{}' " , algorithm_name , operation ) ) ) ;
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 ;
}
2024-03-14 22:39:48 -06:00
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-encrypt
JS : : NonnullGCPtr < JS : : Promise > SubtleCrypto : : encrypt ( AlgorithmIdentifier const & algorithm , JS : : NonnullGCPtr < CryptoKey > key , JS : : Handle < WebIDL : : BufferSource > const & data_parameter )
{
auto & realm = this - > realm ( ) ;
auto & vm = this - > vm ( ) ;
// 1. Let algorithm and key be the algorithm and key parameters passed to the encrypt() method, respectively.
// 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the encrypt() method.
auto data_or_error = WebIDL : : get_buffer_source_copy ( * data_parameter - > raw_object ( ) ) ;
if ( data_or_error . is_error ( ) ) {
VERIFY ( data_or_error . error ( ) . code ( ) = = ENOMEM ) ;
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ) ;
}
auto data = data_or_error . release_value ( ) ;
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "encrypt".
auto normalized_algorithm = normalize_an_algorithm ( realm , algorithm , " encrypt " _string ) ;
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
if ( normalized_algorithm . is_error ( ) )
return WebIDL : : create_rejected_promise_from_exception ( realm , normalized_algorithm . release_error ( ) ) ;
// 5. Let promise be a new Promise.
auto promise = WebIDL : : create_promise ( realm ) ;
// 6. Return promise and perform the remaining steps in parallel.
Platform : : EventLoopPlugin : : the ( ) . deferred_invoke ( [ & realm , normalized_algorithm = normalized_algorithm . release_value ( ) , promise , key , data = move ( data ) ] ( ) - > 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.
// 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of key then throw an InvalidAccessError.
if ( normalized_algorithm . parameter - > name ! = key - > algorithm_name ( ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Algorithm mismatch " _fly_string ) ) ;
return ;
}
// 9. If the [[usages]] internal slot of key does not contain an entry that is "encrypt", then throw an InvalidAccessError.
if ( ! key - > internal_usages ( ) . contains_slow ( Bindings : : KeyUsage : : Encrypt ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Key does not support encryption " _fly_string ) ) ;
return ;
}
// 10. Let ciphertext be the result of performing the encrypt operation specified by normalizedAlgorithm using algorithm and key and with data as plaintext.
auto cipher_text = normalized_algorithm . methods - > encrypt ( * normalized_algorithm . parameter , key , data ) ;
if ( cipher_text . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , cipher_text . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
// 9. Resolve promise with ciphertext.
WebIDL : : resolve_promise ( realm , promise , cipher_text . release_value ( ) ) ;
} ) ;
return verify_cast < JS : : Promise > ( * promise - > promise ( ) ) ;
}
2024-03-14 22:47:06 -06:00
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-decrypt
JS : : NonnullGCPtr < JS : : Promise > SubtleCrypto : : decrypt ( AlgorithmIdentifier const & algorithm , JS : : NonnullGCPtr < CryptoKey > key , JS : : Handle < WebIDL : : BufferSource > const & data_parameter )
{
auto & realm = this - > realm ( ) ;
auto & vm = this - > vm ( ) ;
// 1. Let algorithm and key be the algorithm and key parameters passed to the decrypt() method, respectively.
// 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the decrypt() method.
auto data_or_error = WebIDL : : get_buffer_source_copy ( * data_parameter - > raw_object ( ) ) ;
if ( data_or_error . is_error ( ) ) {
VERIFY ( data_or_error . error ( ) . code ( ) = = ENOMEM ) ;
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ) ;
}
auto data = data_or_error . release_value ( ) ;
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "decrypt".
auto normalized_algorithm = normalize_an_algorithm ( realm , algorithm , " decrypt " _string ) ;
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
if ( normalized_algorithm . is_error ( ) )
return WebIDL : : create_rejected_promise_from_exception ( realm , normalized_algorithm . release_error ( ) ) ;
// 5. Let promise be a new Promise.
auto promise = WebIDL : : create_promise ( realm ) ;
// 6. Return promise and perform the remaining steps in parallel.
Platform : : EventLoopPlugin : : the ( ) . deferred_invoke ( [ & realm , normalized_algorithm = normalized_algorithm . release_value ( ) , promise , key , data = move ( data ) ] ( ) - > 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.
// 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of key then throw an InvalidAccessError.
if ( normalized_algorithm . parameter - > name ! = key - > algorithm_name ( ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Algorithm mismatch " _fly_string ) ) ;
return ;
}
// 9. If the [[usages]] internal slot of key does not contain an entry that is "decrypt", then throw an InvalidAccessError.
if ( ! key - > internal_usages ( ) . contains_slow ( Bindings : : KeyUsage : : Decrypt ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Key does not support encryption " _fly_string ) ) ;
return ;
}
// 10. Let plaintext be the result of performing the decrypt operation specified by normalizedAlgorithm using algorithm and key and with data as ciphertext.
auto plain_text = normalized_algorithm . methods - > decrypt ( * normalized_algorithm . parameter , key , data ) ;
if ( plain_text . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , plain_text . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
// 9. Resolve promise with plaintext.
WebIDL : : resolve_promise ( realm , promise , plain_text . release_value ( ) ) ;
} ) ;
return verify_cast < JS : : Promise > ( * promise - > promise ( ) ) ;
}
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 ( ) ;
2024-03-14 22:38:09 -06:00
auto & vm = this - > vm ( ) ;
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-14 22:38:09 -06:00
if ( data_buffer_or_error . is_error ( ) ) {
VERIFY ( data_buffer_or_error . error ( ) . code ( ) = = ENOMEM ) ;
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ) ;
}
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".
2024-03-14 21:52:17 -06:00
auto normalized_algorithm = normalize_an_algorithm ( realm , 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
}
2024-03-06 19:15:03 -07:00
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-generateKey
JS : : ThrowCompletionOr < JS : : NonnullGCPtr < JS : : Promise > > SubtleCrypto : : generate_key ( AlgorithmIdentifier algorithm , bool extractable , Vector < Bindings : : KeyUsage > key_usages )
{
auto & realm = this - > realm ( ) ;
// 1. Let algorithm, extractable and usages be the algorithm, extractable and keyUsages
// parameters passed to the generateKey() method, respectively.
// 2. Let normalizedAlgorithm be the result of normalizing an algorithm,
// with alg set to algorithm and op set to "generateKey".
2024-03-14 21:52:17 -06:00
auto normalized_algorithm = normalize_an_algorithm ( realm , algorithm , " generateKey " _string ) ;
2024-03-06 19:15:03 -07:00
// 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
if ( normalized_algorithm . is_error ( ) )
return WebIDL : : create_rejected_promise_from_exception ( realm , normalized_algorithm . release_error ( ) ) ;
// 4. Let promise be a new Promise.
auto promise = WebIDL : : create_promise ( realm ) ;
// 5. Return promise and perform the remaining steps in parallel.
Platform : : EventLoopPlugin : : the ( ) . deferred_invoke ( [ & realm , normalized_algorithm = normalized_algorithm . release_value ( ) , promise , extractable , key_usages = move ( key_usages ) ] ( ) - > void {
HTML : : TemporaryExecutionContext context ( Bindings : : host_defined_environment_settings_object ( realm ) , HTML : : TemporaryExecutionContext : : CallbacksEnabled : : Yes ) ;
// 6. If the following steps or referenced procedures say to throw an error, reject promise with
// the returned error and then terminate the algorithm.
// 7. Let result be the result of performing the generate key operation specified by normalizedAlgorithm
// using algorithm, extractable and usages.
auto result_or_error = normalized_algorithm . methods - > generate_key ( * normalized_algorithm . parameter , extractable , key_usages ) ;
if ( result_or_error . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , result_or_error . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
auto result = result_or_error . release_value ( ) ;
// 8. If result is a CryptoKey object:
// If the [[type]] internal slot of result is "secret" or "private" and usages is empty, then throw a SyntaxError.
// If result is a CryptoKeyPair object:
// If the [[usages]] internal slot of the privateKey attribute of result is the empty sequence, then throw a SyntaxError.
// 9. Resolve promise with result.
result . visit (
[ & ] ( JS : : NonnullGCPtr < CryptoKey > & key ) {
if ( ( key - > type ( ) = = Bindings : : KeyType : : Secret | | key - > 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 ;
}
WebIDL : : resolve_promise ( realm , promise , key ) ;
} ,
[ & ] ( JS : : NonnullGCPtr < CryptoKeyPair > & key_pair ) {
if ( key_pair - > private_key ( ) - > internal_usages ( ) . is_empty ( ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : SyntaxError : : create ( realm , " usages must not be empty " _fly_string ) ) ;
return ;
}
WebIDL : : resolve_promise ( realm , promise , key_pair ) ;
} ) ;
} ) ;
return verify_cast < JS : : Promise > ( * promise - > promise ( ) ) ;
}
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".
2024-03-14 21:52:17 -06:00
auto normalized_algorithm = normalize_an_algorithm ( realm , algorithm , " importKey " _string ) ;
2023-12-15 22:03:04 +01:00
// 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 ( ) ) ;
}
2024-03-13 21:19:57 -06:00
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-exportKey
JS : : ThrowCompletionOr < JS : : NonnullGCPtr < JS : : Promise > > SubtleCrypto : : export_key ( Bindings : : KeyFormat format , JS : : NonnullGCPtr < CryptoKey > key )
{
auto & realm = this - > realm ( ) ;
// 1. Let format and key be the format and key parameters passed to the exportKey() method, respectively.
// 2. Let promise be a new Promise.
auto promise = WebIDL : : create_promise ( realm ) ;
// 3. Return promise and perform the remaining steps in parallel.
2024-03-14 21:52:17 -06:00
Platform : : EventLoopPlugin : : the ( ) . deferred_invoke ( [ & realm , key , promise , format ] ( ) - > void {
2024-03-13 21:19:57 -06:00
HTML : : TemporaryExecutionContext context ( Bindings : : host_defined_environment_settings_object ( realm ) , HTML : : TemporaryExecutionContext : : CallbacksEnabled : : Yes ) ;
// 4. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
// 5. If the name member of the [[algorithm]] internal slot of key does not identify a registered algorithm that supports the export key operation,
// then throw a NotSupportedError.
// Note: Handled by the base AlgorithmMethods implementation
auto & algorithm = verify_cast < KeyAlgorithm > ( * key - > algorithm ( ) ) ;
// FIXME: Stash the AlgorithmMethods on the KeyAlgorithm
2024-03-14 21:52:17 -06:00
auto normalized_algorithm_or_error = normalize_an_algorithm ( realm , algorithm . name ( ) , " exportKey " _string ) ;
2024-03-13 21:19:57 -06:00
if ( normalized_algorithm_or_error . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , normalized_algorithm_or_error . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
auto normalized_algorithm = normalized_algorithm_or_error . release_value ( ) ;
// 6. If the [[extractable]] internal slot of key is false, then throw an InvalidAccessError.
if ( ! key - > extractable ( ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Key is not extractable " _fly_string ) ) ;
return ;
}
// 7. Let result be the result of performing the export key operation specified by the [[algorithm]] internal slot of key using key and format.
auto result_or_error = normalized_algorithm . methods - > export_key ( format , key ) ;
if ( result_or_error . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , result_or_error . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
// 8. Resolve promise with result.
WebIDL : : resolve_promise ( realm , promise , result_or_error . release_value ( ) ) ;
} ) ;
2024-03-26 23:53:35 +01:00
return verify_cast < JS : : Promise > ( * promise - > promise ( ) ) ;
}
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-sign
JS : : ThrowCompletionOr < JS : : NonnullGCPtr < JS : : Promise > > SubtleCrypto : : sign ( AlgorithmIdentifier const & algorithm , JS : : NonnullGCPtr < CryptoKey > key , JS : : Handle < WebIDL : : BufferSource > const & data_parameter )
{
auto & realm = this - > realm ( ) ;
auto & vm = this - > vm ( ) ;
// 1. Let algorithm and key be the algorithm and key parameters passed to the sign() method, respectively.
// 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the sign() method.
auto data_or_error = WebIDL : : get_buffer_source_copy ( * data_parameter - > raw_object ( ) ) ;
if ( data_or_error . is_error ( ) ) {
VERIFY ( data_or_error . error ( ) . code ( ) = = ENOMEM ) ;
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ) ;
}
auto data = data_or_error . release_value ( ) ;
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "sign".
auto normalized_algorithm = normalize_an_algorithm ( realm , algorithm , " sign " _string ) ;
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
if ( normalized_algorithm . is_error ( ) )
return WebIDL : : create_rejected_promise_from_exception ( realm , normalized_algorithm . release_error ( ) ) ;
// 5. Let promise be a new Promise.
auto promise = WebIDL : : create_promise ( realm ) ;
// 6. Return promise and perform the remaining steps in parallel.
Platform : : EventLoopPlugin : : the ( ) . deferred_invoke ( [ & realm , normalized_algorithm = normalized_algorithm . release_value ( ) , promise , key , data = move ( data ) ] ( ) - > 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.
// 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of key then throw an InvalidAccessError.
if ( normalized_algorithm . parameter - > name ! = key - > algorithm_name ( ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Algorithm mismatch " _fly_string ) ) ;
return ;
}
// 9. If the [[usages]] internal slot of key does not contain an entry that is "sign", then throw an InvalidAccessError.
if ( ! key - > internal_usages ( ) . contains_slow ( Bindings : : KeyUsage : : Sign ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Key does not support signing " _fly_string ) ) ;
return ;
}
// 10. Let result be the result of performing the sign operation specified by normalizedAlgorithm using key and algorithm and with data as message.
auto result = normalized_algorithm . methods - > sign ( * normalized_algorithm . parameter , key , data ) ;
if ( result . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , result . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
// 9. Resolve promise with result.
WebIDL : : resolve_promise ( realm , promise , result . release_value ( ) ) ;
} ) ;
2024-03-13 21:19:57 -06:00
return verify_cast < JS : : Promise > ( * promise - > promise ( ) ) ;
}
2024-03-27 01:50:25 +01:00
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-verify
JS : : ThrowCompletionOr < JS : : NonnullGCPtr < JS : : Promise > > SubtleCrypto : : verify ( AlgorithmIdentifier const & algorithm , JS : : NonnullGCPtr < CryptoKey > key , JS : : Handle < WebIDL : : BufferSource > const & signature_data , JS : : Handle < WebIDL : : BufferSource > const & data_parameter )
{
auto & realm = this - > realm ( ) ;
auto & vm = this - > vm ( ) ;
// 1. Let algorithm and key be the algorithm and key parameters passed to the verify() method, respectively.
// 2. Let signature be the result of getting a copy of the bytes held by the signature parameter passed to the verify() method.
auto signature_or_error = WebIDL : : get_buffer_source_copy ( * signature_data - > raw_object ( ) ) ;
if ( signature_or_error . is_error ( ) ) {
VERIFY ( signature_or_error . error ( ) . code ( ) = = ENOMEM ) ;
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ) ;
}
auto signature = signature_or_error . release_value ( ) ;
// 3. Let data be the result of getting a copy of the bytes held by the data parameter passed to the verify() method.
auto data_or_error = WebIDL : : get_buffer_source_copy ( * data_parameter - > raw_object ( ) ) ;
if ( data_or_error . is_error ( ) ) {
VERIFY ( data_or_error . error ( ) . code ( ) = = ENOMEM ) ;
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ) ;
}
auto data = data_or_error . release_value ( ) ;
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "verify".
auto normalized_algorithm = normalize_an_algorithm ( realm , algorithm , " verify " _string ) ;
// 5. If an error occurred, return a Promise rejected with normalizedAlgorithm.
if ( normalized_algorithm . is_error ( ) )
return WebIDL : : create_rejected_promise_from_exception ( realm , normalized_algorithm . release_error ( ) ) ;
// 6. Let promise be a new Promise.
auto promise = WebIDL : : create_promise ( realm ) ;
// 7. Return promise and perform the remaining steps in parallel.
Platform : : EventLoopPlugin : : the ( ) . deferred_invoke ( [ & realm , normalized_algorithm = normalized_algorithm . release_value ( ) , promise , key , signature = move ( signature ) , data = move ( data ) ] ( ) - > void {
HTML : : TemporaryExecutionContext context ( Bindings : : host_defined_environment_settings_object ( realm ) , HTML : : TemporaryExecutionContext : : CallbacksEnabled : : Yes ) ;
// 8. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
// 9. If the name member of normalizedAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of key then throw an InvalidAccessError.
if ( normalized_algorithm . parameter - > name ! = key - > algorithm_name ( ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Algorithm mismatch " _fly_string ) ) ;
return ;
}
// 10. If the [[usages]] internal slot of key does not contain an entry that is "verify", then throw an InvalidAccessError.
if ( ! key - > internal_usages ( ) . contains_slow ( Bindings : : KeyUsage : : Verify ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Key does not support verification " _fly_string ) ) ;
return ;
}
// 11. Let result be the result of performing the verify operation specified by normalizedAlgorithm using key, algorithm and signature and with data as message.
auto result = normalized_algorithm . methods - > verify ( * normalized_algorithm . parameter , key , signature , data ) ;
if ( result . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , result . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
// 12. Resolve promise with result.
WebIDL : : resolve_promise ( realm , promise , result . release_value ( ) ) ;
} ) ;
return verify_cast < JS : : Promise > ( * promise - > promise ( ) ) ;
}
2024-03-27 19:15:49 +01:00
// https://w3c.github.io/webcrypto/#SubtleCrypto-method-deriveBits
JS : : ThrowCompletionOr < JS : : NonnullGCPtr < JS : : Promise > > SubtleCrypto : : derive_bits ( AlgorithmIdentifier algorithm , JS : : NonnullGCPtr < CryptoKey > base_key , u32 length )
{
auto & realm = this - > realm ( ) ;
// 1. Let algorithm, baseKey and length, be the algorithm, baseKey and length parameters passed to the deriveBits() method, respectively.
// 2. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "deriveBits".
auto normalized_algorithm = normalize_an_algorithm ( realm , algorithm , " deriveBits " _string ) ;
// 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
if ( normalized_algorithm . is_error ( ) )
return WebIDL : : create_rejected_promise_from_exception ( realm , normalized_algorithm . release_error ( ) ) ;
// 4. Let promise be a new Promise object.
auto promise = WebIDL : : create_promise ( realm ) ;
// 5. Return promise and perform the remaining steps in parallel.
Platform : : EventLoopPlugin : : the ( ) . deferred_invoke ( [ & realm , normalized_algorithm = normalized_algorithm . release_value ( ) , promise , base_key , length ] ( ) - > void {
HTML : : TemporaryExecutionContext context ( Bindings : : host_defined_environment_settings_object ( realm ) , HTML : : TemporaryExecutionContext : : CallbacksEnabled : : Yes ) ;
// 6. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
// 7. If the name member of normalizedAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of baseKey then throw an InvalidAccessError.
if ( normalized_algorithm . parameter - > name ! = base_key - > algorithm_name ( ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Algorithm mismatch " _fly_string ) ) ;
return ;
}
// 8. If the [[usages]] internal slot of baseKey does not contain an entry that is "deriveBits", then throw an InvalidAccessError.
if ( ! base_key - > internal_usages ( ) . contains_slow ( Bindings : : KeyUsage : : Derivebits ) ) {
WebIDL : : reject_promise ( realm , promise , WebIDL : : InvalidAccessError : : create ( realm , " Key does not support deriving bits " _fly_string ) ) ;
return ;
}
// 9. Let result be the result of creating an ArrayBuffer containing the result of performing the derive bits operation specified by normalizedAlgorithm using baseKey, algorithm and length.
auto result = normalized_algorithm . methods - > derive_bits ( * normalized_algorithm . parameter , base_key , length ) ;
if ( result . is_error ( ) ) {
WebIDL : : reject_promise ( realm , promise , Bindings : : dom_exception_to_throw_completion ( realm . vm ( ) , result . release_error ( ) ) . release_value ( ) . value ( ) ) ;
return ;
}
// 10. Resolve promise with result.
WebIDL : : resolve_promise ( realm , promise , result . release_value ( ) ) ;
} ) ;
return verify_cast < JS : : Promise > ( * promise - > promise ( ) ) ;
}
2024-03-14 21:52:17 -06:00
SupportedAlgorithmsMap & supported_algorithms_internal ( )
2023-12-14 00:38:14 +01:00
{
2024-03-14 21:52:17 -06:00
static SupportedAlgorithmsMap s_supported_algorithms ;
2023-12-14 00:38:14 +01:00
return s_supported_algorithms ;
}
2023-12-15 23:40:52 +01:00
// https://w3c.github.io/webcrypto/#algorithm-normalization-internalS
2024-03-14 21:52:17 -06:00
SupportedAlgorithmsMap supported_algorithms ( )
2023-12-14 00:38:14 +01:00
{
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);
2024-03-08 16:30:17 -07:00
// https://w3c.github.io/webcrypto/#rsa-oaep
define_an_algorithm < RSAOAEP , RsaHashedKeyGenParams > ( " generateKey " _string , " RSA-OAEP " _string ) ;
2024-03-13 21:19:57 -06:00
define_an_algorithm < RSAOAEP > ( " exportKey " _string , " RSA-OAEP " _string ) ;
2024-03-14 21:57:32 -06:00
define_an_algorithm < RSAOAEP , RsaHashedImportParams > ( " importKey " _string , " RSA-OAEP " _string ) ;
2024-03-14 23:07:13 -06:00
define_an_algorithm < RSAOAEP , RsaOaepParams > ( " encrypt " _string , " RSA-OAEP " _string ) ;
2024-03-14 23:12:13 -06:00
define_an_algorithm < RSAOAEP , RsaOaepParams > ( " decrypt " _string , " RSA-OAEP " _string ) ;
2024-03-08 16:30:17 -07:00
2024-03-27 01:27:42 +01:00
// https://w3c.github.io/webcrypto/#ecdsa
2024-03-27 01:34:04 +01:00
define_an_algorithm < ECDSA , EcdsaParams > ( " sign " _string , " ECDSA " _string ) ;
2024-03-27 02:35:17 +01:00
define_an_algorithm < ECDSA , EcdsaParams > ( " verify " _string , " ECDSA " _string ) ;
2024-03-27 01:27:42 +01:00
define_an_algorithm < ECDSA , EcKeyGenParams > ( " generateKey " _string , " ECDSA " _string ) ;
2024-03-31 23:04:12 +02:00
// https://wicg.github.io/webcrypto-secure-curves/#ed25519
2024-03-31 23:04:58 +02:00
define_an_algorithm < ED25519 > ( " sign " _string , " Ed25519 " _string ) ;
2024-03-31 23:05:05 +02:00
define_an_algorithm < ED25519 > ( " verify " _string , " Ed25519 " _string ) ;
2024-03-31 23:04:12 +02:00
define_an_algorithm < ED25519 > ( " generateKey " _string , " Ed25519 " _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 >
2024-03-14 21:52:17 -06:00
void 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
}