2021-09-30 20:02:55 +03:00
/*
* Copyright ( c ) 2021 , Idan Horowitz < idan . horowitz @ serenityos . org >
2022-03-30 15:58:02 +02:00
* Copyright ( c ) 2022 , stelar7 < dudedbz @ gmail . com >
2021-09-30 20:02:55 +03:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <AK/Random.h>
2022-03-30 15:58:02 +02:00
# include <AK/StringBuilder.h>
2024-12-20 10:34:14 -06:00
# include <LibCrypto/SecureRandom.h>
2021-09-30 20:02:55 +03:00
# include <LibJS/Runtime/TypedArray.h>
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/CryptoPrototype.h>
2023-02-12 21:25:57 +01: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-09-30 20:02:55 +03:00
# include <LibWeb/Crypto/Crypto.h>
2021-12-13 20:48:27 +00:00
# include <LibWeb/Crypto/SubtleCrypto.h>
2023-11-23 20:12:06 +13:00
# include <LibWeb/WebIDL/Buffers.h>
2021-09-30 20:02:55 +03:00
namespace Web : : Crypto {
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( Crypto ) ;
2023-11-19 19:47:52 +01:00
2024-11-15 04:01:23 +13:00
GC : : Ref < Crypto > Crypto : : create ( JS : : Realm & realm )
2022-09-04 13:15:05 +02:00
{
2024-11-14 05:50:17 +13:00
return realm . create < Crypto > ( realm ) ;
2022-09-04 13:15:05 +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
Crypto : : Crypto ( JS : : Realm & realm )
: PlatformObject ( realm )
2022-09-04 13:15:05 +02:00
{
}
Crypto : : ~ Crypto ( ) = default ;
2023-08-07 08:41:28 +02:00
void Crypto : : initialize ( JS : : Realm & realm )
2021-12-13 20:48:27 +00: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 ( Crypto ) ;
2023-08-13 13:05:26 +02:00
m_subtle = SubtleCrypto : : create ( realm ) ;
2021-12-13 20:48:27 +00:00
}
2024-11-15 04:01:23 +13:00
GC : : Ref < SubtleCrypto > Crypto : : subtle ( ) const
2022-09-03 19:59:53 +02:00
{
return * m_subtle ;
}
2022-03-30 15:58:02 +02:00
// https://w3c.github.io/webcrypto/#dfn-Crypto-method-getRandomValues
2024-11-15 04:01:23 +13:00
WebIDL : : ExceptionOr < GC : : Root < WebIDL : : ArrayBufferView > > Crypto : : get_random_values ( GC : : Root < WebIDL : : ArrayBufferView > array ) const
2021-09-30 20:02:55 +03:00
{
// 1. If array is not an Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array, then throw a TypeMismatchError and terminate the algorithm.
2023-11-23 20:12:06 +13:00
if ( ! array - > is_typed_array_base ( ) )
2024-10-12 20:56:21 +02:00
return WebIDL : : TypeMismatchError : : create ( realm ( ) , " array must be one of Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array " _string ) ;
2021-09-30 20:02:55 +03:00
2024-11-15 04:01:23 +13:00
auto const & typed_array = * array - > bufferable_object ( ) . get < GC : : Ref < JS : : TypedArrayBase > > ( ) ;
2024-10-28 04:00:57 +01:00
if ( ! typed_array . element_name ( ) . is_one_of ( " Int8Array " , " Uint8Array " , " Uint8ClampedArray " , " Int16Array " , " Uint16Array " , " Int32Array " , " Uint32Array " , " BigInt64Array " , " BigUint64Array " ) )
return WebIDL : : TypeMismatchError : : create ( realm ( ) , " array must be one of Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array " _string ) ;
2023-12-24 14:55:10 -05:00
auto typed_array_record = JS : : make_typed_array_with_buffer_witness_record ( typed_array , JS : : ArrayBuffer : : Order : : SeqCst ) ;
// IMPLEMENTATION DEFINED: If the viewed array buffer is out-of-bounds, throw a InvalidStateError and terminate the algorithm.
if ( JS : : is_typed_array_out_of_bounds ( typed_array_record ) )
return WebIDL : : InvalidStateError : : create ( realm ( ) , MUST ( String : : formatted ( JS : : ErrorType : : BufferOutOfBounds . message ( ) , " TypedArray " sv ) ) ) ;
2021-09-30 20:02:55 +03:00
// 2. If the byteLength of array is greater than 65536, throw a QuotaExceededError and terminate the algorithm.
2023-12-24 14:55:10 -05:00
if ( JS : : typed_array_byte_length ( typed_array_record ) > 65536 )
2024-10-12 20:56:21 +02:00
return WebIDL : : QuotaExceededError : : create ( realm ( ) , " array's byteLength may not be greater than 65536 " _string ) ;
2021-09-30 20:02:55 +03:00
// FIXME: Handle SharedArrayBuffers
// 3. Overwrite all elements of array with cryptographically strong random values of the appropriate type.
2024-12-20 10:34:14 -06:00
: : Crypto : : fill_with_secure_random ( array - > viewed_array_buffer ( ) - > buffer ( ) . bytes ( ) . slice ( array - > byte_offset ( ) , array - > byte_length ( ) ) ) ;
2021-09-30 20:02:55 +03:00
// 4. Return array.
return array ;
}
2022-03-30 15:58:02 +02:00
// https://w3c.github.io/webcrypto/#dfn-Crypto-method-randomUUID
2023-02-23 18:58:56 +01:00
WebIDL : : ExceptionOr < String > Crypto : : random_uuid ( ) const
2022-03-30 15:58:02 +02:00
{
2023-02-23 18:58:56 +01:00
auto & vm = realm ( ) . vm ( ) ;
2023-03-13 16:22:07 +03:00
return TRY_OR_THROW_OOM ( vm , generate_random_uuid ( ) ) ;
}
void Crypto : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
2023-11-19 16:18:00 +13:00
visitor . visit ( m_subtle ) ;
2023-03-13 16:22:07 +03:00
}
// https://w3c.github.io/webcrypto/#dfn-generate-a-random-uuid
ErrorOr < String > generate_random_uuid ( )
{
2022-03-30 15:58:02 +02:00
// 1. Let bytes be a byte sequence of length 16.
u8 bytes [ 16 ] ;
// 2. Fill bytes with cryptographically secure random bytes.
2024-12-20 10:34:14 -06:00
: : Crypto : : fill_with_secure_random ( bytes ) ;
2022-03-30 15:58:02 +02:00
// 3. Set the 4 most significant bits of bytes[6], which represent the UUID version, to 0100.
bytes [ 6 ] & = ~ ( 1 < < 7 ) ;
bytes [ 6 ] | = 1 < < 6 ;
bytes [ 6 ] & = ~ ( 1 < < 5 ) ;
bytes [ 6 ] & = ~ ( 1 < < 4 ) ;
// 4. Set the 2 most significant bits of bytes[8], which represent the UUID variant, to 10.
bytes [ 8 ] | = 1 < < 7 ;
bytes [ 8 ] & = ~ ( 1 < < 6 ) ;
2022-04-01 20:58:27 +03:00
/* 5. Return the string concatenation of
«
2022-03-30 15:58:02 +02:00
hexadecimal representation of bytes [ 0 ] ,
2022-04-01 20:58:27 +03:00
hexadecimal representation of bytes [ 1 ] ,
2022-03-30 15:58:02 +02:00
hexadecimal representation of bytes [ 2 ] ,
hexadecimal representation of bytes [ 3 ] ,
2022-04-01 20:58:27 +03:00
" - " ,
hexadecimal representation of bytes [ 4 ] ,
2022-03-30 15:58:02 +02:00
hexadecimal representation of bytes [ 5 ] ,
" - " ,
2022-04-01 20:58:27 +03:00
hexadecimal representation of bytes [ 6 ] ,
2022-03-30 15:58:02 +02:00
hexadecimal representation of bytes [ 7 ] ,
" - " ,
2022-04-01 20:58:27 +03:00
hexadecimal representation of bytes [ 8 ] ,
2022-03-30 15:58:02 +02:00
hexadecimal representation of bytes [ 9 ] ,
" - " ,
2022-04-01 20:58:27 +03:00
hexadecimal representation of bytes [ 10 ] ,
hexadecimal representation of bytes [ 11 ] ,
hexadecimal representation of bytes [ 12 ] ,
hexadecimal representation of bytes [ 13 ] ,
hexadecimal representation of bytes [ 14 ] ,
2022-03-30 15:58:02 +02:00
hexadecimal representation of bytes [ 15 ]
» .
*/
StringBuilder builder ;
2023-03-13 16:22:07 +03:00
TRY ( builder . try_appendff ( " {:02x}{:02x}{:02x}{:02x}- " , bytes [ 0 ] , bytes [ 1 ] , bytes [ 2 ] , bytes [ 3 ] ) ) ;
TRY ( builder . try_appendff ( " {:02x}{:02x}- " , bytes [ 4 ] , bytes [ 5 ] ) ) ;
TRY ( builder . try_appendff ( " {:02x}{:02x}- " , bytes [ 6 ] , bytes [ 7 ] ) ) ;
TRY ( builder . try_appendff ( " {:02x}{:02x}- " , bytes [ 8 ] , bytes [ 9 ] ) ) ;
TRY ( builder . try_appendff ( " {:02x}{:02x}{:02x}{:02x}{:02x}{:02x} " , bytes [ 10 ] , bytes [ 11 ] , bytes [ 12 ] , bytes [ 13 ] , bytes [ 14 ] , bytes [ 15 ] ) ) ;
return builder . to_string ( ) ;
2023-07-07 22:48:11 -04:00
}
2022-09-13 01:23:28 +02:00
2021-09-30 20:02:55 +03:00
}