/* * Copyright (c) 2024, Andrew Kaster * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace Web::Crypto { using AlgorithmIdentifier = Variant, String>; using HashAlgorithmIdentifier = AlgorithmIdentifier; using KeyDataType = Variant, Bindings::JsonWebKey>; // https://w3c.github.io/webcrypto/#algorithm-overview struct AlgorithmParams { virtual ~AlgorithmParams(); explicit AlgorithmParams(String name) : name(move(name)) { } String name; static JS::ThrowCompletionOr> from_value(JS::VM&, JS::Value); }; // https://w3c.github.io/webcrypto/#pbkdf2-params struct PBKDF2Params : public AlgorithmParams { virtual ~PBKDF2Params() override; PBKDF2Params(String name, JS::Handle salt, u32 iterations, HashAlgorithmIdentifier hash) : AlgorithmParams(move(name)) , salt(move(salt)) , iterations(iterations) , hash(move(hash)) { } JS::Handle salt; u32 iterations; HashAlgorithmIdentifier hash; static JS::ThrowCompletionOr> from_value(JS::VM&, JS::Value); }; // https://w3c.github.io/webcrypto/#dfn-RsaKeyGenParams struct RsaKeyGenParams : public AlgorithmParams { virtual ~RsaKeyGenParams() override; RsaKeyGenParams(String name, u32 modulus_length, ::Crypto::UnsignedBigInteger public_exponent) : AlgorithmParams(move(name)) , modulus_length(modulus_length) , public_exponent(move(public_exponent)) { } u32 modulus_length; // NOTE that the raw data is going to be in Big Endian u8[] format ::Crypto::UnsignedBigInteger public_exponent; static JS::ThrowCompletionOr> from_value(JS::VM&, JS::Value); }; // https://w3c.github.io/webcrypto/#dfn-RsaHashedKeyGenParams struct RsaHashedKeyGenParams : public RsaKeyGenParams { virtual ~RsaHashedKeyGenParams() override; RsaHashedKeyGenParams(String name, u32 modulus_length, ::Crypto::UnsignedBigInteger public_exponent, HashAlgorithmIdentifier hash) : RsaKeyGenParams(move(name), modulus_length, move(public_exponent)) , hash(move(hash)) { } HashAlgorithmIdentifier hash; static JS::ThrowCompletionOr> from_value(JS::VM&, JS::Value); }; class AlgorithmMethods { public: virtual ~AlgorithmMethods(); virtual WebIDL::ExceptionOr> digest(AlgorithmParams const&, ByteBuffer const&) { return WebIDL::NotSupportedError::create(m_realm, "digest is not supported"_fly_string); } virtual WebIDL::ExceptionOr> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector const&) { return WebIDL::NotSupportedError::create(m_realm, "importKey is not supported"_fly_string); } virtual WebIDL::ExceptionOr, JS::NonnullGCPtr>> generate_key(AlgorithmParams const&, bool, Vector const&) { return WebIDL::NotSupportedError::create(m_realm, "generateKey is not supported"_fly_string); } virtual WebIDL::ExceptionOr> export_key(Bindings::KeyFormat, JS::NonnullGCPtr) { return WebIDL::NotSupportedError::create(m_realm, "exportKey is not supported"_fly_string); } static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new AlgorithmMethods(realm)); } protected: explicit AlgorithmMethods(JS::Realm& realm) : m_realm(realm) { } JS::Realm& m_realm; }; class RSAOAEP : public AlgorithmMethods { public: virtual WebIDL::ExceptionOr, JS::NonnullGCPtr>> generate_key(AlgorithmParams const&, bool, Vector const&) override; virtual WebIDL::ExceptionOr> export_key(Bindings::KeyFormat, JS::NonnullGCPtr) override; static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new RSAOAEP(realm)); } private: explicit RSAOAEP(JS::Realm& realm) : AlgorithmMethods(realm) { } }; class PBKDF2 : public AlgorithmMethods { public: virtual WebIDL::ExceptionOr> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector const&) override; static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new PBKDF2(realm)); } private: explicit PBKDF2(JS::Realm& realm) : AlgorithmMethods(realm) { } }; class SHA : public AlgorithmMethods { public: virtual WebIDL::ExceptionOr> digest(AlgorithmParams const&, ByteBuffer const&) override; static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new SHA(realm)); } private: explicit SHA(JS::Realm& realm) : AlgorithmMethods(realm) { } }; ErrorOr base64_url_uint_encode(::Crypto::UnsignedBigInteger); }