mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Implement encapsulateKey method for SubtleCrypto
None of the current algorithms supports the method but the future post quantum algorithms will do so.
This commit is contained in:
parent
42f55c7c97
commit
b36a702ad1
Notes:
github-actions[bot]
2025-11-27 20:51:16 +00:00
Author: https://github.com/tete17
Commit: b36a702ad1
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6961
Reviewed-by: https://github.com/gmta ✅
4 changed files with 108 additions and 0 deletions
|
|
@ -377,6 +377,11 @@ public:
|
|||
return WebIDL::NotSupportedError::create(m_realm, "unwwrapKey is not supported"_utf16);
|
||||
}
|
||||
|
||||
virtual WebIDL::ExceptionOr<GC::Ref<EncapsulatedBits>> encapsulate(AlgorithmParams const&, GC::Ref<CryptoKey>)
|
||||
{
|
||||
return WebIDL::NotSupportedError::create(m_realm, "encapsulate is not supported"_utf16);
|
||||
}
|
||||
|
||||
static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new AlgorithmMethods(realm)); }
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -1040,6 +1040,104 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::unwrap_key(Bindings::KeyFormat format, Ke
|
|||
return promise;
|
||||
}
|
||||
|
||||
// https://wicg.github.io/webcrypto-modern-algos/#dfn-SubtleCrypto-method-encapsulateKey
|
||||
GC::Ref<WebIDL::Promise> SubtleCrypto::encapsulate_key(AlgorithmIdentifier encapsulation_algorithm, GC::Ref<CryptoKey> encapsulation_key, AlgorithmIdentifier shared_key_algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages)
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
|
||||
// 1. Let encapsulationAlgorithm, encapsulationKey, sharedKeyAlgorithm, extractable and usages be the
|
||||
// encapsulationAlgorithm, encapsulationKey, sharedKeyAlgorithm, extractable and keyUsages parameters passed to
|
||||
// the encapsulateKey() method, respectively.
|
||||
|
||||
// 2. Let normalizedEncapsulationAlgorithm be the result of normalizing an algorithm, with alg set to
|
||||
// encapsulationAlgorithm and op set to "encapsulate".
|
||||
auto maybe_normalized_encapsulation_algorithm = normalize_an_algorithm(realm, encapsulation_algorithm, "encapsulate"_string);
|
||||
|
||||
// 3. If an error occurred, return a Promise rejected with normalizedEncapsulationAlgorithm.
|
||||
if (maybe_normalized_encapsulation_algorithm.is_error()) {
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, maybe_normalized_encapsulation_algorithm.exception());
|
||||
}
|
||||
auto normalized_encapsulation_algorithm = maybe_normalized_encapsulation_algorithm.release_value();
|
||||
|
||||
// 4. Let normalizedSharedKeyAlgorithm be the result of normalizing an algorithm, with alg
|
||||
// set to sharedKeyAlgorithm and op set to "importKey".
|
||||
auto maybe_normalized_shared_key_algorithm = normalize_an_algorithm(realm, shared_key_algorithm, "importKey"_string);
|
||||
|
||||
// 5. If an error occurred, return a Promise rejected with normalizedSharedKeyAlgorithm.
|
||||
if (maybe_normalized_shared_key_algorithm.is_error()) {
|
||||
return WebIDL::create_rejected_promise_from_exception(realm, maybe_normalized_shared_key_algorithm.exception());
|
||||
}
|
||||
auto normalized_shared_key_algorithm = maybe_normalized_shared_key_algorithm.release_value();
|
||||
|
||||
// 6. Let realm be the relevant realm of this.
|
||||
|
||||
// 7. Let promise be a new Promise.
|
||||
auto promise = WebIDL::create_promise(realm);
|
||||
|
||||
// 8. Return promise and perform the remaining steps in parallel.
|
||||
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(realm.heap(), [&realm, normalized_encapsulation_algorithm = move(normalized_encapsulation_algorithm), encapsulation_key = encapsulation_key, promise, normalized_shared_key_algorithm = move(normalized_shared_key_algorithm), extractable, usages = move(key_usages)]() mutable -> void {
|
||||
HTML::TemporaryExecutionContext context(realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
|
||||
// 9. If the following steps or referenced procedures say to throw an error, queue a global task on the crypto task
|
||||
// source, given realm's global object, to reject promise with the returned error; and then terminate the algorithm.
|
||||
|
||||
// 10. If the name member of normalizedEncapsulationAlgorithm is not equal to the name attribute of the [[algorithm]]
|
||||
// internal slot of encapsulationKey then throw an InvalidAccessError.
|
||||
if (normalized_encapsulation_algorithm.parameter->name != encapsulation_key->algorithm_name()) {
|
||||
WebIDL::reject_promise(realm, promise, WebIDL::InvalidAccessError::create(realm, "Invalid encapsulation key algorithm"_utf16));
|
||||
return;
|
||||
}
|
||||
|
||||
// 11. If the [[usages]] internal slot of encapsulationKey does not contain an entry that is "encapsulateKey", then
|
||||
// throw an InvalidAccessError.
|
||||
if (encapsulation_key->internal_usages().contains_slow(Bindings::KeyUsage::Encapsulatekey)) {
|
||||
WebIDL::reject_promise(realm, promise, WebIDL::InvalidAccessError::create(realm, "Invalid encapsulation key usage"_utf16));
|
||||
return;
|
||||
}
|
||||
|
||||
// 12. Let encapsulatedBits be the result of performing the encapsulate operation specified by the [[algorithm]]
|
||||
// internal slot of encapsulationKey using encapsulationKey.
|
||||
auto maybe_encapsulated_bits = normalized_encapsulation_algorithm.methods->encapsulate(*normalized_encapsulation_algorithm.parameter, encapsulation_key);
|
||||
if (maybe_encapsulated_bits.is_error()) {
|
||||
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), maybe_encapsulated_bits.release_error()).release_value());
|
||||
return;
|
||||
}
|
||||
auto encapsulated_bits = maybe_encapsulated_bits.release_value();
|
||||
|
||||
// 13. Let sharedKey be the result of performing the import key operation specified by
|
||||
// normalizedSharedKeyAlgorithm using "raw-secret" as format, the sharedKey field of encapsulatedBits as
|
||||
// keyData, sharedKeyAlgorithm as algorithm and using extractable and usages.
|
||||
auto maybe_shared_key = normalized_shared_key_algorithm.methods->import_key(
|
||||
*normalized_shared_key_algorithm.parameter,
|
||||
Bindings::KeyFormat::RawSecret,
|
||||
encapsulated_bits->shared_key.value(),
|
||||
extractable,
|
||||
usages);
|
||||
if (maybe_shared_key.is_error()) {
|
||||
WebIDL::reject_promise(realm, promise, Bindings::exception_to_throw_completion(realm.vm(), maybe_shared_key.release_error()).release_value());
|
||||
return;
|
||||
}
|
||||
auto shared_key = maybe_shared_key.release_value();
|
||||
|
||||
// 14. Let encapsulatedKey be a new EncapsulatedKey dictionary with sharedKey set to sharedKey and ciphertext set
|
||||
// to the ciphertext field of encapsulatedBits.
|
||||
auto encapsulated_key = EncapsulatedKey { shared_key, encapsulated_bits->ciphertext };
|
||||
|
||||
// 15. Queue a global task on the crypto task source, given realm's global object, to perform the remaining steps.
|
||||
// 16. Let result be the result of converting encapsulatedKey to an ECMAScript Object in realm, as defined by [WebIDL].
|
||||
auto maybe_result = encapsulated_key.to_object(realm);
|
||||
if (maybe_result.is_error()) {
|
||||
WebIDL::reject_promise(realm, promise, maybe_result.release_error().value());
|
||||
return;
|
||||
}
|
||||
auto const result = maybe_result.release_value();
|
||||
|
||||
// 17. Resolve promise with result.
|
||||
WebIDL::resolve_promise(realm, promise, result);
|
||||
}));
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
SupportedAlgorithmsMap& supported_algorithms_internal()
|
||||
{
|
||||
static SupportedAlgorithmsMap s_supported_algorithms;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ public:
|
|||
GC::Ref<WebIDL::Promise> wrap_key(Bindings::KeyFormat format, GC::Ref<CryptoKey> key, GC::Ref<CryptoKey> wrapping_key, AlgorithmIdentifier wrap_algorithm);
|
||||
GC::Ref<WebIDL::Promise> unwrap_key(Bindings::KeyFormat format, KeyDataType wrapped_key, GC::Ref<CryptoKey> unwrapping_key, AlgorithmIdentifier unwrap_algorithm, AlgorithmIdentifier unwrapped_key_algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages);
|
||||
|
||||
GC::Ref<WebIDL::Promise> encapsulate_key(AlgorithmIdentifier encapsulation_algorithm, GC::Ref<CryptoKey> encapsulation_key, AlgorithmIdentifier shared_key_algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages);
|
||||
|
||||
private:
|
||||
explicit SubtleCrypto(JS::Realm&);
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
|
|
|||
|
|
@ -74,4 +74,7 @@ interface SubtleCrypto {
|
|||
|
||||
Promise<any> wrapKey(KeyFormat format, CryptoKey key, CryptoKey wrappingKey, AlgorithmIdentifier wrapAlgorithm);
|
||||
Promise<CryptoKey> unwrapKey(KeyFormat format, BufferSource wrappedKey, CryptoKey unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier unwrappedKeyAlgorithm, boolean extractable, sequence<KeyUsage> keyUsages);
|
||||
|
||||
// https://wicg.github.io/webcrypto-modern-algos/#partial-subtlecrypto-interface
|
||||
Promise<EncapsulatedKey> encapsulateKey(AlgorithmIdentifier encapsulationAlgorithm, CryptoKey encapsulationKey, AlgorithmIdentifier sharedKeyAlgorithm, boolean extractable, sequence<KeyUsage> keyUsages);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue