diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 64e9bc91f6e..45a77e5cfe6 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -1696,6 +1696,37 @@ WebIDL::ExceptionOr> AesCtr::encrypt(Algorithm return JS::ArrayBuffer::create(m_realm, ciphertext); } +WebIDL::ExceptionOr> AesCtr::decrypt(AlgorithmParams const& params, JS::NonnullGCPtr key, ByteBuffer const& ciphertext) +{ + // 1. If the counter member of normalizedAlgorithm does not have length 16 bytes, then throw an OperationError. + auto const& normalized_algorithm = static_cast(params); + auto const& counter = normalized_algorithm.counter; + if (counter.size() != 16) + return WebIDL::OperationError::create(m_realm, "Invalid counter length"_string); + + // 2. If the length member of normalizedAlgorithm is zero or is greater than 128, then throw an OperationError. + auto const& length = normalized_algorithm.length; + if (length == 0 || length > 128) + return WebIDL::OperationError::create(m_realm, "Invalid length"_string); + + // 3. Let plaintext be the result of performing the CTR Decryption operation described in Section 6.5 of [NIST-SP800-38A] using + // AES as the block cipher, + // the contents of the counter member of normalizedAlgorithm as the initial value of the counter block, + // the length member of normalizedAlgorithm as the input parameter m to the standard counter block incrementing function defined in Appendix B.1 of [NIST-SP800-38A] + // and the contents of ciphertext as the input ciphertext. + auto& aes_algorithm = static_cast(*key->algorithm()); + auto key_length = aes_algorithm.length(); + auto key_bytes = key->handle().get(); + + ::Crypto::Cipher::AESCipher::CTRMode cipher(key_bytes, key_length, ::Crypto::Cipher::Intent::Decryption); + ByteBuffer plaintext = TRY_OR_THROW_OOM(m_realm->vm(), ByteBuffer::create_zeroed(ciphertext.size())); + Bytes plaintext_span = plaintext.bytes(); + cipher.decrypt(ciphertext, plaintext_span, counter); + + // 4. Return the result of creating an ArrayBuffer containing plaintext. + return JS::ArrayBuffer::create(m_realm, plaintext); +} + // 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 d53c045629b..f6920edf1aa 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h @@ -350,6 +350,7 @@ public: virtual WebIDL::ExceptionOr get_key_length(AlgorithmParams const&) override; virtual WebIDL::ExceptionOr, JS::NonnullGCPtr>> generate_key(AlgorithmParams const&, bool, Vector const&) override; virtual WebIDL::ExceptionOr> encrypt(AlgorithmParams const&, JS::NonnullGCPtr, ByteBuffer const&) override; + virtual WebIDL::ExceptionOr> decrypt(AlgorithmParams const&, JS::NonnullGCPtr, ByteBuffer const&) override; static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new AesCtr(realm)); } diff --git a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp index 38e79e882bb..03c9f1a51f1 100644 --- a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp +++ b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp @@ -778,6 +778,7 @@ SupportedAlgorithmsMap supported_algorithms() // https://w3c.github.io/webcrypto/#aes-ctr-registration define_an_algorithm("encrypt"_string, "AES-CTR"_string); + define_an_algorithm("decrypt"_string, "AES-CTR"_string); define_an_algorithm("importKey"_string, "AES-CTR"_string); define_an_algorithm("exportKey"_string, "AES-CTR"_string); define_an_algorithm("get key length"_string, "AES-CTR"_string);