diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 31d18bd027e..0e68b9f1d55 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2024, Andrew Kaster + * Copyright (c) 2024, stelar7 * * SPDX-License-Identifier: BSD-2-Clause */ @@ -2394,4 +2395,73 @@ WebIDL::ExceptionOr> X25519::derive_bits(Algor return JS::ArrayBuffer::create(realm, move(result)); } +WebIDL::ExceptionOr, JS::NonnullGCPtr>> X25519::generate_key([[maybe_unused]] AlgorithmParams const& params, bool extractable, Vector const& key_usages) +{ + // 1. If usages contains an entry which is not "deriveKey" or "deriveBits" then throw a SyntaxError. + for (auto const& usage : key_usages) { + if (usage != Bindings::KeyUsage::Derivekey && usage != Bindings::KeyUsage::Derivebits) { + return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage)))); + } + } + + // 2. Generate an X25519 key pair, with the private key being 32 random bytes, + // and the public key being X25519(a, 9), as defined in [RFC7748], section 6.1. + ::Crypto::Curves::X25519 curve; + auto maybe_private_key = curve.generate_private_key(); + if (maybe_private_key.is_error()) + return WebIDL::OperationError::create(m_realm, "Failed to generate private key"_string); + + auto private_key_data = maybe_private_key.release_value(); + + auto maybe_public_key = curve.generate_public_key(private_key_data); + if (maybe_public_key.is_error()) + return WebIDL::OperationError::create(m_realm, "Failed to generate public key"_string); + + auto public_key_data = maybe_public_key.release_value(); + + // 3. Let algorithm be a new KeyAlgorithm object. + auto algorithm = KeyAlgorithm::create(m_realm); + + // 4. Set the name attribute of algorithm to "X25519". + algorithm->set_name("X25519"_string); + + // 5. Let publicKey be a new CryptoKey associated with the relevant global object of this [HTML], + // and representing the public key of the generated key pair. + auto public_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { public_key_data }); + + // 6. Set the [[type]] internal slot of publicKey to "public" + public_key->set_type(Bindings::KeyType::Public); + + // 7. Set the [[algorithm]] internal slot of publicKey to algorithm. + public_key->set_algorithm(algorithm); + + // 8. Set the [[extractable]] internal slot of publicKey to true. + public_key->set_extractable(true); + + // 9. Set the [[usages]] internal slot of publicKey to be the empty list. + public_key->set_usages({}); + + // 10. Let privateKey be a new CryptoKey associated with the relevant global object of this [HTML], + // and representing the private key of the generated key pair. + auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { private_key_data }); + + // 11. Set the [[type]] internal slot of privateKey to "private" + private_key->set_type(Bindings::KeyType::Private); + + // 12. Set the [[algorithm]] internal slot of privateKey to algorithm. + private_key->set_algorithm(algorithm); + + // 13. Set the [[extractable]] internal slot of privateKey to extractable. + private_key->set_extractable(extractable); + + // 14. Set the [[usages]] internal slot of privateKey to be the usage intersection of usages and [ "deriveKey", "deriveBits" ]. + private_key->set_usages(usage_intersection(key_usages, { { Bindings::KeyUsage::Derivekey, Bindings::KeyUsage::Derivebits } })); + + // 15. Let result be a new CryptoKeyPair dictionary. + // 16. Set the publicKey attribute of result to be publicKey. + // 17. Set the privateKey attribute of result to be privateKey. + // 18. Return the result of converting result to an ECMAScript Object, as defined by [WebIDL]. + return Variant, JS::NonnullGCPtr> { CryptoKeyPair::create(m_realm, public_key, private_key) }; +} + } diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h index 91375caa1dd..319d33042f2 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2024, Andrew Kaster + * Copyright (c) 2024, stelar7 * * SPDX-License-Identifier: BSD-2-Clause */ @@ -439,6 +440,7 @@ private: class X25519 : public AlgorithmMethods { public: virtual WebIDL::ExceptionOr> derive_bits(AlgorithmParams const&, JS::NonnullGCPtr, Optional) override; + virtual WebIDL::ExceptionOr, JS::NonnullGCPtr>> generate_key(AlgorithmParams const&, bool, Vector const&) override; static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new X25519(realm)); } diff --git a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp index 6e15920cdfd..c02742b5de6 100644 --- a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp +++ b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2021-2022, Linus Groh - * Copyright (c) 2023, stelar7 + * Copyright (c) 2023-2024, stelar7 * * SPDX-License-Identifier: BSD-2-Clause */ @@ -813,6 +813,7 @@ SupportedAlgorithmsMap supported_algorithms() // https://wicg.github.io/webcrypto-secure-curves/#x25519 define_an_algorithm("deriveBits"_string, "X25519"_string); + define_an_algorithm("generateKey"_string, "X25519"_string); return internal_object; }