mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-12 04:22:28 +00:00
LibWeb: Implement skeleton of SubtleCrypto.encrypt
No algorithms implement this yet, but this is the high level entry point.
This commit is contained in:
parent
ae4d90c88a
commit
df3d0538a9
Notes:
sideshowbarker
2024-07-17 05:41:34 +09:00
Author: https://github.com/ADKaster
Commit: df3d0538a9
Pull-request: https://github.com/SerenityOS/serenity/pull/23596
Reviewed-by: https://github.com/alimpfard
6 changed files with 76 additions and 1 deletions
|
@ -106,6 +106,11 @@ class AlgorithmMethods {
|
|||
public:
|
||||
virtual ~AlgorithmMethods();
|
||||
|
||||
virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&)
|
||||
{
|
||||
return WebIDL::NotSupportedError::create(m_realm, "encrypt is not supported"_fly_string);
|
||||
}
|
||||
|
||||
virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> digest(AlgorithmParams const&, ByteBuffer const&)
|
||||
{
|
||||
return WebIDL::NotSupportedError::create(m_realm, "digest is not supported"_fly_string);
|
||||
|
|
|
@ -70,6 +70,15 @@ void CryptoKey::set_usages(Vector<Bindings::KeyUsage> usages)
|
|||
});
|
||||
}
|
||||
|
||||
String CryptoKey::algorithm_name() const
|
||||
{
|
||||
if (m_algorithm_name.is_empty()) {
|
||||
auto name = MUST(m_algorithm->get("name"));
|
||||
m_algorithm_name = MUST(name.to_string(vm()));
|
||||
}
|
||||
return m_algorithm_name;
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<CryptoKeyPair> CryptoKeyPair::create(JS::Realm& realm, JS::NonnullGCPtr<CryptoKey> public_key, JS::NonnullGCPtr<CryptoKey> private_key)
|
||||
{
|
||||
return realm.heap().allocate<CryptoKeyPair>(realm, realm, public_key, private_key);
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
void set_usages(Vector<Bindings::KeyUsage>);
|
||||
|
||||
InternalKeyData const& handle() const { return m_key_data; }
|
||||
String algorithm_name() const;
|
||||
|
||||
virtual StringView interface_name() const override { return "CryptoKey"sv; }
|
||||
virtual WebIDL::ExceptionOr<void> serialization_steps(HTML::SerializationRecord& record, bool for_storage, HTML::SerializationMemory&) override;
|
||||
|
@ -63,6 +64,7 @@ private:
|
|||
|
||||
Vector<Bindings::KeyUsage> m_key_usages;
|
||||
InternalKeyData m_key_data; // [[handle]]
|
||||
mutable String m_algorithm_name;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webcrypto/#ref-for-dfn-CryptoKeyPair-2
|
||||
|
|
|
@ -119,6 +119,63 @@ WebIDL::ExceptionOr<NormalizedAlgorithmAndParameter> normalize_an_algorithm(JS::
|
|||
return normalized_algorithm;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-encrypt
|
||||
JS::NonnullGCPtr<JS::Promise> SubtleCrypto::encrypt(AlgorithmIdentifier const& algorithm, JS::NonnullGCPtr<CryptoKey> key, JS::Handle<WebIDL::BufferSource> const& data_parameter)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = this->vm();
|
||||
// 1. Let algorithm and key be the algorithm and key parameters passed to the encrypt() method, respectively.
|
||||
|
||||
// 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the encrypt() method.
|
||||
auto data_or_error = WebIDL::get_buffer_source_copy(*data_parameter->raw_object());
|
||||
if (data_or_error.is_error()) {
|
||||
VERIFY(data_or_error.error().code() == ENOMEM);
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, vm.throw_completion<JS::InternalError>(vm.error_message(JS::VM::ErrorMessage::OutOfMemory)));
|
||||
}
|
||||
auto data = data_or_error.release_value();
|
||||
|
||||
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "encrypt".
|
||||
auto normalized_algorithm = normalize_an_algorithm(realm, algorithm, "encrypt"_string);
|
||||
|
||||
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
||||
if (normalized_algorithm.is_error())
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, normalized_algorithm.release_error());
|
||||
|
||||
// 5. Let promise be a new Promise.
|
||||
auto promise = WebIDL::create_promise(realm);
|
||||
|
||||
// 6. Return promise and perform the remaining steps in parallel.
|
||||
|
||||
Platform::EventLoopPlugin::the().deferred_invoke([&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, data = move(data)]() -> void {
|
||||
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
|
||||
// 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
|
||||
|
||||
// 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of key then throw an InvalidAccessError.
|
||||
if (normalized_algorithm.parameter->name != key->algorithm_name()) {
|
||||
WebIDL::reject_promise(realm, promise, WebIDL::InvalidAccessError::create(realm, "Algorithm mismatch"_fly_string));
|
||||
return;
|
||||
}
|
||||
|
||||
// 9. If the [[usages]] internal slot of key does not contain an entry that is "encrypt", then throw an InvalidAccessError.
|
||||
if (!key->internal_usages().contains_slow(Bindings::KeyUsage::Encrypt)) {
|
||||
WebIDL::reject_promise(realm, promise, WebIDL::InvalidAccessError::create(realm, "Key does not support encryption"_fly_string));
|
||||
return;
|
||||
}
|
||||
|
||||
// 10. Let ciphertext be the result of performing the encrypt operation specified by normalizedAlgorithm using algorithm and key and with data as plaintext.
|
||||
auto cipher_text = normalized_algorithm.methods->encrypt(*normalized_algorithm.parameter, key, data);
|
||||
if (cipher_text.is_error()) {
|
||||
WebIDL::reject_promise(realm, promise, Bindings::dom_exception_to_throw_completion(realm.vm(), cipher_text.release_error()).release_value().value());
|
||||
return;
|
||||
}
|
||||
|
||||
// 9. Resolve promise with ciphertext.
|
||||
WebIDL::resolve_promise(realm, promise, cipher_text.release_value());
|
||||
});
|
||||
|
||||
return verify_cast<JS::Promise>(*promise->promise());
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#dfn-SubtleCrypto-method-digest
|
||||
JS::NonnullGCPtr<JS::Promise> SubtleCrypto::digest(AlgorithmIdentifier const& algorithm, JS::Handle<WebIDL::BufferSource> const& data)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,8 @@ public:
|
|||
|
||||
virtual ~SubtleCrypto() override;
|
||||
|
||||
JS::NonnullGCPtr<JS::Promise> encrypt(AlgorithmIdentifier const& algorithm, JS::NonnullGCPtr<CryptoKey> key, JS::Handle<WebIDL::BufferSource> const& data_parameter);
|
||||
|
||||
JS::NonnullGCPtr<JS::Promise> digest(AlgorithmIdentifier const& algorithm, JS::Handle<WebIDL::BufferSource> const& data);
|
||||
|
||||
JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Promise>> generate_key(AlgorithmIdentifier algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages);
|
||||
|
|
|
@ -45,7 +45,7 @@ dictionary JsonWebKey
|
|||
// https://w3c.github.io/webcrypto/#subtlecrypto-interface
|
||||
[SecureContext,Exposed=(Window,Worker)]
|
||||
interface SubtleCrypto {
|
||||
// FIXME: Promise<any> encrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data);
|
||||
Promise<any> encrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data);
|
||||
// FIXME: Promise<any> decrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data);
|
||||
// FIXME: Promise<any> sign(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data);
|
||||
// FIXME: Promise<any> verify(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource signature, BufferSource data);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue