From 29b68a1b10cea9197357595e40ee194ab72c80ae Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Thu, 14 Mar 2024 23:07:13 -0600 Subject: [PATCH] LibWeb: Implement skeleton of RSA-OAEP encrypt for SubtleCrypto The actual Crypto algorithm part isn't implemented yet, so we just copy the plaintext and claim that's the ciphertext :^) --- .../LibWeb/Crypto/CryptoAlgorithms.cpp | 50 +++++++++++++++++++ .../LibWeb/Crypto/CryptoAlgorithms.h | 17 +++++++ .../Libraries/LibWeb/Crypto/SubtleCrypto.cpp | 3 +- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 4aab6f1aa26..0aba4d280ed 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -323,6 +323,56 @@ JS::ThrowCompletionOr> RsaHashedImportParams::fro return adopt_own(*new RsaHashedImportParams { name, hash.get() }); } +RsaOaepParams::~RsaOaepParams() = default; + +JS::ThrowCompletionOr> RsaOaepParams::from_value(JS::VM& vm, JS::Value value) +{ + auto& object = value.as_object(); + + auto name_value = TRY(object.get("name")); + auto name = TRY(name_value.to_string(vm)); + + auto label_value = TRY(object.get("label")); + + ByteBuffer label; + if (!label_value.is_nullish()) { + if (!label_value.is_object() || !(is(label_value.as_object()) || is(label_value.as_object()) || is(label_value.as_object()))) + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "BufferSource"); + + label = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(label_value.as_object())); + } + + return adopt_own(*new RsaOaepParams { name, move(label) }); +} + +// https://w3c.github.io/webcrypto/#rsa-oaep-operations +WebIDL::ExceptionOr> RSAOAEP::encrypt(AlgorithmParams const& params, JS::NonnullGCPtr key, ByteBuffer const& plaintext) +{ + auto& realm = m_realm; + auto& vm = realm.vm(); + auto const& normalized_algorithm = static_cast(params); + + // 1. If the [[type]] internal slot of key is not "public", then throw an InvalidAccessError. + if (key->type() != Bindings::KeyType::Public) + return WebIDL::InvalidAccessError::create(realm, "Key is not a public key"_fly_string); + + // 2. Let label be the contents of the label member of normalizedAlgorithm or the empty octet string if the label member of normalizedAlgorithm is not present. + [[maybe_unused]] auto const& label = normalized_algorithm.label; + + // 3. Perform the encryption operation defined in Section 7.1 of [RFC3447] with the key represented by key as the recipient's RSA public key, + // the contents of plaintext as the message to be encrypted, M and label as the label, L, and with the hash function specified by the hash attribute + // of the [[algorithm]] internal slot of key as the Hash option and MGF1 (defined in Section B.2.1 of [RFC3447]) as the MGF option. + + // 4. If performing the operation results in an error, then throw an OperationError. + + // 5. Let ciphertext be the value C that results from performing the operation. + // FIXME: Actually encrypt the data + auto ciphertext = TRY_OR_THROW_OOM(vm, ByteBuffer::copy(plaintext)); + + // 6. Return the result of creating an ArrayBuffer containing ciphertext. + return JS::ArrayBuffer::create(realm, move(ciphertext)); +} + // https://w3c.github.io/webcrypto/#rsa-oaep-operations WebIDL::ExceptionOr, JS::NonnullGCPtr>> RSAOAEP::generate_key(AlgorithmParams const& params, bool extractable, Vector const& key_usages) { diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h index dbddd6a0f8c..4e621dcb75c 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h @@ -102,6 +102,21 @@ struct RsaHashedImportParams : public AlgorithmParams { static JS::ThrowCompletionOr> from_value(JS::VM&, JS::Value); }; +// https://w3c.github.io/webcrypto/#dfn-RsaOaepParams +struct RsaOaepParams : public AlgorithmParams { + virtual ~RsaOaepParams() override; + + RsaOaepParams(String name, ByteBuffer label) + : AlgorithmParams(move(name)) + , label(move(label)) + { + } + + ByteBuffer label; + + static JS::ThrowCompletionOr> from_value(JS::VM&, JS::Value); +}; + class AlgorithmMethods { public: virtual ~AlgorithmMethods(); @@ -149,6 +164,8 @@ protected: class RSAOAEP : public AlgorithmMethods { public: + virtual WebIDL::ExceptionOr> encrypt(AlgorithmParams const&, JS::NonnullGCPtr, ByteBuffer const&) override; + virtual WebIDL::ExceptionOr, JS::NonnullGCPtr>> generate_key(AlgorithmParams const&, bool, Vector const&) override; virtual WebIDL::ExceptionOr> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector const&) override; diff --git a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp index 950caae269d..a8270a11fc6 100644 --- a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp +++ b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp @@ -515,7 +515,8 @@ SupportedAlgorithmsMap supported_algorithms() define_an_algorithm("generateKey"_string, "RSA-OAEP"_string); define_an_algorithm("exportKey"_string, "RSA-OAEP"_string); define_an_algorithm("importKey"_string, "RSA-OAEP"_string); - // FIXME: encrypt, decrypt + define_an_algorithm("encrypt"_string, "RSA-OAEP"_string); + // FIXME: decrypt return internal_object; }