diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index e5964508c04..6c6112ba111 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -2107,6 +2107,54 @@ WebIDL::ExceptionOr> AesGcm::decrypt(Algorithm return JS::ArrayBuffer::create(m_realm, plaintext); } +WebIDL::ExceptionOr, JS::NonnullGCPtr>> AesGcm::generate_key(AlgorithmParams const& params, bool extractable, Vector const& key_usages) +{ + // 1. If usages contains any entry which is not one of "encrypt", "decrypt", "wrapKey" or "unwrapKey", then throw a SyntaxError. + for (auto const& usage : key_usages) { + if (usage != Bindings::KeyUsage::Encrypt && usage != Bindings::KeyUsage::Decrypt && usage != Bindings::KeyUsage::Wrapkey && usage != Bindings::KeyUsage::Unwrapkey) { + return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage)))); + } + } + + // 2. If the length member of normalizedAlgorithm is not equal to one of 128, 192 or 256, then throw an OperationError. + auto const& normalized_algorithm = static_cast(params); + auto length = normalized_algorithm.length; + if (length != 128 && length != 192 && length != 256) { + return WebIDL::OperationError::create(m_realm, MUST(String::formatted("Cannot create AES-CTR key with unusual amount of {} bits", length))); + } + + // 3. Generate an AES key of length equal to the length member of normalizedAlgorithm. + // 4. If the key generation step fails, then throw an OperationError. + auto key_buffer = TRY(generate_aes_key(m_realm->vm(), length / 8)); + + // 5. Let key be a new CryptoKey object representing the generated AES key. + auto key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { key_buffer }); + + // 6. Let algorithm be a new AesKeyAlgorithm. + auto algorithm = AesKeyAlgorithm::create(m_realm); + + // 7. Set the name attribute of algorithm to "AES-GCM". + algorithm->set_name("AES-GCM"_string); + + // 8. Set the length attribute of algorithm to equal the length member of normalizedAlgorithm. + algorithm->set_length(length); + + // 9. Set the [[type]] internal slot of key to "secret". + key->set_type(Bindings::KeyType::Secret); + + // 10. Set the [[algorithm]] internal slot of key to algorithm. + key->set_algorithm(algorithm); + + // 11. Set the [[extractable]] internal slot of key to be extractable. + key->set_extractable(extractable); + + // 12. Set the [[usages]] internal slot of key to be usages. + key->set_usages(key_usages); + + // 13. Return key. + return { key }; +} + // https://w3c.github.io/webcrypto/#hkdf-operations WebIDL::ExceptionOr> HKDF::import_key(AlgorithmParams const&, Bindings::KeyFormat format, CryptoKey::InternalKeyData key_data, bool extractable, Vector const& key_usages) { diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h index 8520367d3a5..7daf7ba59fe 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h @@ -387,6 +387,7 @@ public: virtual WebIDL::ExceptionOr> export_key(Bindings::KeyFormat, JS::NonnullGCPtr) override; virtual WebIDL::ExceptionOr> encrypt(AlgorithmParams const&, JS::NonnullGCPtr, ByteBuffer const&) override; virtual WebIDL::ExceptionOr> decrypt(AlgorithmParams const&, JS::NonnullGCPtr, ByteBuffer const&) override; + virtual WebIDL::ExceptionOr, JS::NonnullGCPtr>> generate_key(AlgorithmParams const&, bool, Vector const&) override; static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new AesGcm(realm)); } diff --git a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp index da5c8db7945..3083bffe6fa 100644 --- a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp +++ b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp @@ -788,6 +788,7 @@ SupportedAlgorithmsMap supported_algorithms() define_an_algorithm("get key length"_string, "AES-GCM"_string); define_an_algorithm("importKey"_string, "AES-GCM"_string); define_an_algorithm("exportKey"_string, "AES-GCM"_string); + define_an_algorithm("generateKey"_string, "AES-GCM"_string); define_an_algorithm("encrypt"_string, "AES-GCM"_string); define_an_algorithm("decrypt"_string, "AES-GCM"_string);