mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
subtlecrypto: Replace NormalizedAlgorithm
with specialized variants (#34193)
* Implement specialized normalize_algorithm for "get key length" operation Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Implement specialized normalize_algorithm for "digest" Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Implement specialized normalize_algorithm for "importKey" Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Implement specialized normalize_algorithm for "deriveBits" Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Implement specialized normalize_algorithm for "decrypt" Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Implement specialized normalize_algorithm for "generateKey" Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Implement specialized normalize_algorithm for "encrypt" Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Remove normalize_algorithm Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Update WPT expectations Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Replace obj.get_unsafe() with obj.get() Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Replace BitwiseOr with LogicalOr (typo) Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Update more WPT expectations outside of WebCryptoAPI Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
da462d0fcd
commit
67ac59b809
4 changed files with 393 additions and 9331 deletions
|
@ -26,8 +26,8 @@ use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
|
||||||
CryptoKeyMethods, KeyType, KeyUsage,
|
CryptoKeyMethods, KeyType, KeyUsage,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
|
use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
|
||||||
AesCbcParams, AesCtrParams, AesKeyAlgorithm, AesKeyGenParams, Algorithm, AlgorithmIdentifier,
|
AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesKeyAlgorithm, AesKeyGenParams, Algorithm,
|
||||||
JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params, SubtleCryptoMethods,
|
AlgorithmIdentifier, JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params, SubtleCryptoMethods,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::codegen::UnionTypes::{
|
use crate::dom::bindings::codegen::UnionTypes::{
|
||||||
ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey,
|
ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey,
|
||||||
|
@ -150,8 +150,15 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
comp: InRealm,
|
comp: InRealm,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Rc<Promise> {
|
) -> Rc<Promise> {
|
||||||
let normalized_algorithm = normalize_algorithm(cx, &algorithm, "encrypt");
|
|
||||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||||
|
let normalized_algorithm = match normalize_algorithm_for_encrypt_or_decrypt(cx, &algorithm)
|
||||||
|
{
|
||||||
|
Ok(algorithm) => algorithm,
|
||||||
|
Err(e) => {
|
||||||
|
promise.reject_error(e);
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
};
|
||||||
let data = match data {
|
let data = match data {
|
||||||
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
|
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
|
||||||
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
|
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
|
||||||
|
@ -161,7 +168,6 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
let this = Trusted::new(self);
|
let this = Trusted::new(self);
|
||||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||||
let trusted_key = Trusted::new(key);
|
let trusted_key = Trusted::new(key);
|
||||||
let alg = normalized_algorithm.clone();
|
|
||||||
let key_alg = key.algorithm();
|
let key_alg = key.algorithm();
|
||||||
let valid_usage = key.usages().contains(&KeyUsage::Encrypt);
|
let valid_usage = key.usages().contains(&KeyUsage::Encrypt);
|
||||||
let _ = task_source.queue_with_canceller(
|
let _ = task_source.queue_with_canceller(
|
||||||
|
@ -169,39 +175,20 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
let subtle = this.root();
|
let subtle = this.root();
|
||||||
let promise = trusted_promise.root();
|
let promise = trusted_promise.root();
|
||||||
let key = trusted_key.root();
|
let key = trusted_key.root();
|
||||||
|
|
||||||
|
if !valid_usage || normalized_algorithm.name() != key_alg {
|
||||||
|
promise.reject_error(Error::InvalidAccess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
||||||
let text = match alg {
|
|
||||||
Ok(NormalizedAlgorithm::AesCbcParams(key_gen_params)) => {
|
if let Err(e) = normalized_algorithm.encrypt(&subtle, &key, &data, cx, array_buffer_ptr.handle_mut()) {
|
||||||
if !valid_usage || key_gen_params.name != key_alg {
|
promise.reject_error(e);
|
||||||
Err(Error::InvalidAccess)
|
return;
|
||||||
} else {
|
|
||||||
match subtle.encrypt_aes_cbc(
|
|
||||||
key_gen_params, &key, &data, cx, array_buffer_ptr.handle_mut()
|
|
||||||
) {
|
|
||||||
Ok(_) => Ok(array_buffer_ptr.handle()),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ok(NormalizedAlgorithm::AesCtrParams(key_gen_params)) => {
|
|
||||||
if !valid_usage || key_gen_params.name != key_alg {
|
|
||||||
Err(Error::InvalidAccess)
|
|
||||||
} else {
|
|
||||||
match subtle.encrypt_decrypt_aes_ctr(
|
|
||||||
key_gen_params, &key, &data, cx, array_buffer_ptr.handle_mut()
|
|
||||||
) {
|
|
||||||
Ok(_) => Ok(array_buffer_ptr.handle()),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => Err(Error::NotSupported),
|
|
||||||
};
|
|
||||||
match text {
|
|
||||||
Ok(text) => promise.resolve_native(&*text),
|
|
||||||
Err(e) => promise.reject_error(e),
|
|
||||||
}
|
}
|
||||||
|
promise.resolve_native(&*array_buffer_ptr.handle());
|
||||||
}),
|
}),
|
||||||
&canceller,
|
&canceller,
|
||||||
);
|
);
|
||||||
|
@ -219,8 +206,15 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
comp: InRealm,
|
comp: InRealm,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Rc<Promise> {
|
) -> Rc<Promise> {
|
||||||
let normalized_algorithm = normalize_algorithm(cx, &algorithm, "decrypt");
|
|
||||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||||
|
let normalized_algorithm = match normalize_algorithm_for_encrypt_or_decrypt(cx, &algorithm)
|
||||||
|
{
|
||||||
|
Ok(algorithm) => algorithm,
|
||||||
|
Err(e) => {
|
||||||
|
promise.reject_error(e);
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
};
|
||||||
let data = match data {
|
let data = match data {
|
||||||
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
|
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
|
||||||
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
|
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
|
||||||
|
@ -230,7 +224,6 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
let this = Trusted::new(self);
|
let this = Trusted::new(self);
|
||||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||||
let trusted_key = Trusted::new(key);
|
let trusted_key = Trusted::new(key);
|
||||||
let alg = normalized_algorithm.clone();
|
|
||||||
let key_alg = key.algorithm();
|
let key_alg = key.algorithm();
|
||||||
let valid_usage = key.usages().contains(&KeyUsage::Decrypt);
|
let valid_usage = key.usages().contains(&KeyUsage::Decrypt);
|
||||||
let _ = task_source.queue_with_canceller(
|
let _ = task_source.queue_with_canceller(
|
||||||
|
@ -240,37 +233,18 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
let key = trusted_key.root();
|
let key = trusted_key.root();
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
||||||
let text = match alg {
|
|
||||||
Ok(NormalizedAlgorithm::AesCbcParams(key_gen_params)) => {
|
if !valid_usage || normalized_algorithm.name() != key_alg {
|
||||||
if !valid_usage || key_gen_params.name != key_alg {
|
promise.reject_error(Error::InvalidAccess);
|
||||||
Err(Error::InvalidAccess)
|
return;
|
||||||
} else {
|
|
||||||
match subtle.decrypt_aes_cbc(
|
|
||||||
key_gen_params, &key, &data, cx, array_buffer_ptr.handle_mut()
|
|
||||||
) {
|
|
||||||
Ok(_) => Ok(array_buffer_ptr.handle()),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ok(NormalizedAlgorithm::AesCtrParams(key_gen_params)) => {
|
|
||||||
if !valid_usage || key_gen_params.name != key_alg {
|
|
||||||
Err(Error::InvalidAccess)
|
|
||||||
} else {
|
|
||||||
match subtle.encrypt_decrypt_aes_ctr(
|
|
||||||
key_gen_params, &key, &data, cx, array_buffer_ptr.handle_mut()
|
|
||||||
) {
|
|
||||||
Ok(_) => Ok(array_buffer_ptr.handle()),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => Err(Error::NotSupported),
|
|
||||||
};
|
|
||||||
match text {
|
|
||||||
Ok(text) => promise.resolve_native(&*text),
|
|
||||||
Err(e) => promise.reject_error(e),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Err(e) = normalized_algorithm.decrypt(&subtle, &key, &data, cx, array_buffer_ptr.handle_mut()) {
|
||||||
|
promise.reject_error(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.resolve_native(&*array_buffer_ptr.handle());
|
||||||
}),
|
}),
|
||||||
&canceller,
|
&canceller,
|
||||||
);
|
);
|
||||||
|
@ -299,7 +273,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
// Step 3. Let normalizedAlgorithm be the result of normalizing an algorithm,
|
// Step 3. Let normalizedAlgorithm be the result of normalizing an algorithm,
|
||||||
// with alg set to algorithm and op set to "digest".
|
// with alg set to algorithm and op set to "digest".
|
||||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||||
let normalized_algorithm = match normalize_algorithm(cx, &algorithm, "digest") {
|
let normalized_algorithm = match normalize_algorithm_for_digest(cx, &algorithm) {
|
||||||
Ok(normalized_algorithm) => normalized_algorithm,
|
Ok(normalized_algorithm) => normalized_algorithm,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Step 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
// Step 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
||||||
|
@ -314,7 +288,6 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
// Step 6. Return promise and perform the remaining steps in parallel.
|
// Step 6. Return promise and perform the remaining steps in parallel.
|
||||||
let (task_source, canceller) = self.task_source_with_canceller();
|
let (task_source, canceller) = self.task_source_with_canceller();
|
||||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||||
let alg = normalized_algorithm.clone();
|
|
||||||
|
|
||||||
let _ = task_source.queue_with_canceller(
|
let _ = task_source.queue_with_canceller(
|
||||||
task!(generate_key: move || {
|
task!(generate_key: move || {
|
||||||
|
@ -324,7 +297,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
|
|
||||||
// Step 8. Let result be the result of performing the digest operation specified by
|
// Step 8. Let result be the result of performing the digest operation specified by
|
||||||
// normalizedAlgorithm using algorithm, with data as message.
|
// normalizedAlgorithm using algorithm, with data as message.
|
||||||
let digest = match alg.digest(&data) {
|
let digest = match normalized_algorithm.digest(&data) {
|
||||||
Ok(digest) => digest,
|
Ok(digest) => digest,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
promise.reject_error(e);
|
promise.reject_error(e);
|
||||||
|
@ -357,27 +330,24 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
comp: InRealm,
|
comp: InRealm,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Rc<Promise> {
|
) -> Rc<Promise> {
|
||||||
let normalized_algorithm = normalize_algorithm(cx, &algorithm, "generateKey");
|
|
||||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||||
if let Err(e) = normalized_algorithm {
|
let normalized_algorithm = match normalize_algorithm_for_generate_key(cx, &algorithm) {
|
||||||
promise.reject_error(e);
|
Ok(algorithm) => algorithm,
|
||||||
return promise;
|
Err(e) => {
|
||||||
}
|
promise.reject_error(e);
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let (task_source, canceller) = self.task_source_with_canceller();
|
let (task_source, canceller) = self.task_source_with_canceller();
|
||||||
let this = Trusted::new(self);
|
let this = Trusted::new(self);
|
||||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||||
let alg = normalized_algorithm.clone();
|
|
||||||
let _ = task_source.queue_with_canceller(
|
let _ = task_source.queue_with_canceller(
|
||||||
task!(generate_key: move || {
|
task!(generate_key: move || {
|
||||||
let subtle = this.root();
|
let subtle = this.root();
|
||||||
let promise = trusted_promise.root();
|
let promise = trusted_promise.root();
|
||||||
let key = match alg {
|
let key = normalized_algorithm.generate_key(&subtle, key_usages, extractable);
|
||||||
Ok(NormalizedAlgorithm::AesKeyGenParams(key_gen_params)) => {
|
|
||||||
subtle.generate_key_aes(key_usages, key_gen_params, extractable)
|
|
||||||
},
|
|
||||||
_ => Err(Error::NotSupported),
|
|
||||||
};
|
|
||||||
match key {
|
match key {
|
||||||
Ok(key) => promise.resolve_native(&key),
|
Ok(key) => promise.resolve_native(&key),
|
||||||
Err(e) => promise.reject_error(e),
|
Err(e) => promise.reject_error(e),
|
||||||
|
@ -407,7 +377,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
// Step 2. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm
|
// Step 2. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm
|
||||||
// and op set to "deriveBits".
|
// and op set to "deriveBits".
|
||||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||||
let normalized_algorithm = match normalize_algorithm(cx, &algorithm, "deriveBits") {
|
let normalized_algorithm = match normalize_algorithm_for_derive_bits(cx, &algorithm) {
|
||||||
Ok(algorithm) => algorithm,
|
Ok(algorithm) => algorithm,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
// Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
||||||
|
@ -419,7 +389,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
// Step 4. Let normalizedDerivedKeyAlgorithmImport be the result of normalizing an algorithm,
|
// Step 4. Let normalizedDerivedKeyAlgorithmImport be the result of normalizing an algorithm,
|
||||||
// with alg set to derivedKeyType and op set to "importKey".
|
// with alg set to derivedKeyType and op set to "importKey".
|
||||||
let normalized_derived_key_algorithm_import =
|
let normalized_derived_key_algorithm_import =
|
||||||
match normalize_algorithm(cx, &derived_key_type, "importKey") {
|
match normalize_algorithm_for_import_key(cx, &derived_key_type) {
|
||||||
Ok(algorithm) => algorithm,
|
Ok(algorithm) => algorithm,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Step 5. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmImport.
|
// Step 5. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmImport.
|
||||||
|
@ -431,7 +401,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
// Step 6. Let normalizedDerivedKeyAlgorithmLength be the result of normalizing an algorithm, with alg set
|
// Step 6. Let normalizedDerivedKeyAlgorithmLength be the result of normalizing an algorithm, with alg set
|
||||||
// to derivedKeyType and op set to "get key length".
|
// to derivedKeyType and op set to "get key length".
|
||||||
let normalized_derived_key_algorithm_length =
|
let normalized_derived_key_algorithm_length =
|
||||||
match normalize_algorithm(cx, &derived_key_type, "get key length") {
|
match normalize_algorithm_for_get_key_length(cx, &derived_key_type) {
|
||||||
Ok(algorithm) => algorithm,
|
Ok(algorithm) => algorithm,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Step 7. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmLength.
|
// Step 7. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmLength.
|
||||||
|
@ -536,7 +506,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
// Step 2. Let normalizedAlgorithm be the result of normalizing an algorithm,
|
// Step 2. Let normalizedAlgorithm be the result of normalizing an algorithm,
|
||||||
// with alg set to algorithm and op set to "deriveBits".
|
// with alg set to algorithm and op set to "deriveBits".
|
||||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||||
let normalized_algorithm = match normalize_algorithm(cx, &algorithm, "deriveBits") {
|
let normalized_algorithm = match normalize_algorithm_for_derive_bits(cx, &algorithm) {
|
||||||
Ok(algorithm) => algorithm,
|
Ok(algorithm) => algorithm,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
// Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
||||||
|
@ -607,7 +577,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Rc<Promise> {
|
) -> Rc<Promise> {
|
||||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||||
let normalized_algorithm = match normalize_algorithm(cx, &algorithm, "importKey") {
|
let normalized_algorithm = match normalize_algorithm_for_import_key(cx, &algorithm) {
|
||||||
Ok(algorithm) => algorithm,
|
Ok(algorithm) => algorithm,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
promise.reject_error(e);
|
promise.reject_error(e);
|
||||||
|
@ -718,28 +688,6 @@ impl SubtleCryptoMethods for SubtleCrypto {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum NormalizedAlgorithm {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
Algorithm(SubtleAlgorithm),
|
|
||||||
AesCbcParams(SubtleAesCbcParams),
|
|
||||||
AesCtrParams(SubtleAesCtrParams),
|
|
||||||
AesKeyGenParams(SubtleAesKeyGenParams),
|
|
||||||
Pbkdf2Params(SubtlePbkdf2Params),
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/webcrypto/#sha>
|
|
||||||
Sha1,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/webcrypto/#sha>
|
|
||||||
Sha256,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/webcrypto/#sha>
|
|
||||||
Sha384,
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/webcrypto/#sha>
|
|
||||||
Sha512,
|
|
||||||
}
|
|
||||||
|
|
||||||
// These "subtle" structs are proxies for the codegen'd dicts which don't hold a DOMString
|
// These "subtle" structs are proxies for the codegen'd dicts which don't hold a DOMString
|
||||||
// so they can be sent safely when running steps in parallel.
|
// so they can be sent safely when running steps in parallel.
|
||||||
|
|
||||||
|
@ -823,7 +771,7 @@ pub struct SubtlePbkdf2Params {
|
||||||
iterations: u32,
|
iterations: u32,
|
||||||
|
|
||||||
/// <https://w3c.github.io/webcrypto/#dfn-Pbkdf2Params-hash>
|
/// <https://w3c.github.io/webcrypto/#dfn-Pbkdf2Params-hash>
|
||||||
hash: Box<NormalizedAlgorithm>,
|
hash: DigestAlgorithm,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SubtlePbkdf2Params {
|
impl SubtlePbkdf2Params {
|
||||||
|
@ -836,99 +784,249 @@ impl SubtlePbkdf2Params {
|
||||||
let params = Self {
|
let params = Self {
|
||||||
salt,
|
salt,
|
||||||
iterations: params.iterations,
|
iterations: params.iterations,
|
||||||
hash: Box::new(normalize_algorithm(cx, ¶ms.hash, "digest")?),
|
hash: normalize_algorithm_for_digest(cx, ¶ms.hash)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(params)
|
Ok(params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm>
|
enum GetKeyLengthAlgorithm {
|
||||||
#[allow(unsafe_code)]
|
Aes(u16),
|
||||||
fn normalize_algorithm(
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
enum DigestAlgorithm {
|
||||||
|
/// <https://w3c.github.io/webcrypto/#sha>
|
||||||
|
Sha1,
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#sha>
|
||||||
|
Sha256,
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#sha>
|
||||||
|
Sha384,
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#sha>
|
||||||
|
Sha512,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A normalized algorithm returned by [`normalize_algorithm`] with operation `"importKey"`
|
||||||
|
///
|
||||||
|
/// [`normalize_algorithm`]: https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm
|
||||||
|
enum ImportKeyAlgorithm {
|
||||||
|
AesCbc,
|
||||||
|
AesCtr,
|
||||||
|
Pbkdf2,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A normalized algorithm returned by [`normalize_algorithm`] with operation `"deriveBits"`
|
||||||
|
///
|
||||||
|
/// [`normalize_algorithm`]: https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm
|
||||||
|
enum DeriveBitsAlgorithm {
|
||||||
|
Pbkdf2(SubtlePbkdf2Params),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A normalized algorithm returned by [`normalize_algorithm`] with operation `"encrypt"` or `"decrypt"`
|
||||||
|
///
|
||||||
|
/// [`normalize_algorithm`]: https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm
|
||||||
|
enum EncryptionAlgorithm {
|
||||||
|
AesCbc(SubtleAesCbcParams),
|
||||||
|
AesCtr(SubtleAesCtrParams),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A normalized algorithm returned by [`normalize_algorithm`] with operation `"generateKey"`
|
||||||
|
///
|
||||||
|
/// [`normalize_algorithm`]: https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm
|
||||||
|
enum KeyGenerationAlgorithm {
|
||||||
|
Aes(SubtleAesKeyGenParams),
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! value_from_js_object {
|
||||||
|
($t: ty, $cx: ident, $value: ident) => {{
|
||||||
|
let params_result = <$t>::new($cx, $value.handle()).map_err(|_| Error::Operation)?;
|
||||||
|
let ConversionResult::Success(params) = params_result else {
|
||||||
|
return Err(Error::Syntax);
|
||||||
|
};
|
||||||
|
params
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm> with operation `"get key length"`
|
||||||
|
fn normalize_algorithm_for_get_key_length(
|
||||||
cx: JSContext,
|
cx: JSContext,
|
||||||
algorithm: &AlgorithmIdentifier,
|
algorithm: &AlgorithmIdentifier,
|
||||||
operation: &str,
|
) -> Result<GetKeyLengthAlgorithm, Error> {
|
||||||
) -> Result<NormalizedAlgorithm, Error> {
|
|
||||||
match algorithm {
|
match algorithm {
|
||||||
AlgorithmIdentifier::String(name) => {
|
|
||||||
Ok(NormalizedAlgorithm::Algorithm(name.clone().into()))
|
|
||||||
},
|
|
||||||
AlgorithmIdentifier::Object(obj) => {
|
AlgorithmIdentifier::Object(obj) => {
|
||||||
rooted!(in(*cx) let value = ObjectValue(unsafe { *obj.get_unsafe() }));
|
rooted!(in(*cx) let value = ObjectValue(obj.get()));
|
||||||
let Ok(ConversionResult::Success(algorithm)) = Algorithm::new(cx, value.handle())
|
let Ok(ConversionResult::Success(algorithm)) = Algorithm::new(cx, value.handle())
|
||||||
else {
|
else {
|
||||||
return Err(Error::Syntax);
|
return Err(Error::Syntax);
|
||||||
};
|
};
|
||||||
let normalized_name = algorithm.name.str().to_uppercase();
|
|
||||||
|
|
||||||
// This implements the table from https://w3c.github.io/webcrypto/#algorithm-overview
|
let name = algorithm.name.str();
|
||||||
let normalized_algorithm = match (normalized_name.as_str(), operation) {
|
let normalized_algorithm = if name.eq_ignore_ascii_case(ALG_AES_CBC) ||
|
||||||
(ALG_AES_CBC, "encrypt") | (ALG_AES_CBC, "decrypt") => {
|
name.eq_ignore_ascii_case(ALG_AES_CTR)
|
||||||
let params_result =
|
{
|
||||||
AesCbcParams::new(cx, value.handle()).map_err(|_| Error::Operation)?;
|
let params = value_from_js_object!(AesDerivedKeyParams, cx, value);
|
||||||
let ConversionResult::Success(params) = params_result else {
|
GetKeyLengthAlgorithm::Aes(params.length)
|
||||||
return Err(Error::Syntax);
|
} else {
|
||||||
};
|
return Err(Error::NotSupported);
|
||||||
NormalizedAlgorithm::AesCbcParams(params.into())
|
|
||||||
},
|
|
||||||
(ALG_AES_CTR, "encrypt") | (ALG_AES_CTR, "decrypt") => {
|
|
||||||
let params_result =
|
|
||||||
AesCtrParams::new(cx, value.handle()).map_err(|_| Error::Operation)?;
|
|
||||||
let ConversionResult::Success(params) = params_result else {
|
|
||||||
return Err(Error::Syntax);
|
|
||||||
};
|
|
||||||
NormalizedAlgorithm::AesCtrParams(params.into())
|
|
||||||
},
|
|
||||||
(ALG_AES_CBC, "generateKey") | (ALG_AES_CTR, "generateKey") => {
|
|
||||||
let params_result =
|
|
||||||
AesKeyGenParams::new(cx, value.handle()).map_err(|_| Error::Operation)?;
|
|
||||||
let ConversionResult::Success(params) = params_result else {
|
|
||||||
return Err(Error::Syntax);
|
|
||||||
};
|
|
||||||
NormalizedAlgorithm::AesKeyGenParams(params.into())
|
|
||||||
},
|
|
||||||
(ALG_ECDSA, "deriveBits") => NormalizedAlgorithm::Algorithm(SubtleAlgorithm {
|
|
||||||
name: ALG_ECDSA.to_string(),
|
|
||||||
}),
|
|
||||||
(ALG_HKDF, "deriveBits") => NormalizedAlgorithm::Algorithm(SubtleAlgorithm {
|
|
||||||
name: ALG_HKDF.to_string(),
|
|
||||||
}),
|
|
||||||
(ALG_PBKDF2, "deriveBits") => {
|
|
||||||
let params_result =
|
|
||||||
Pbkdf2Params::new(cx, value.handle()).map_err(|_| Error::Operation)?;
|
|
||||||
let ConversionResult::Success(params) = params_result else {
|
|
||||||
return Err(Error::Syntax);
|
|
||||||
};
|
|
||||||
let subtle_params = SubtlePbkdf2Params::new(cx, params)?;
|
|
||||||
NormalizedAlgorithm::Pbkdf2Params(subtle_params)
|
|
||||||
},
|
|
||||||
(ALG_AES_CBC, "importKey") => NormalizedAlgorithm::Algorithm(SubtleAlgorithm {
|
|
||||||
name: ALG_AES_CBC.to_string(),
|
|
||||||
}),
|
|
||||||
(ALG_AES_CTR, "importKey") => NormalizedAlgorithm::Algorithm(SubtleAlgorithm {
|
|
||||||
name: ALG_AES_CTR.to_string(),
|
|
||||||
}),
|
|
||||||
(ALG_PBKDF2, "importKey") => NormalizedAlgorithm::Algorithm(SubtleAlgorithm {
|
|
||||||
name: ALG_PBKDF2.to_string(),
|
|
||||||
}),
|
|
||||||
(ALG_SHA1, "digest") => NormalizedAlgorithm::Sha1,
|
|
||||||
(ALG_SHA256, "digest") => NormalizedAlgorithm::Sha256,
|
|
||||||
(ALG_SHA384, "digest") => NormalizedAlgorithm::Sha384,
|
|
||||||
(ALG_SHA512, "digest") => NormalizedAlgorithm::Sha512,
|
|
||||||
_ => return Err(Error::NotSupported),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(normalized_algorithm)
|
Ok(normalized_algorithm)
|
||||||
},
|
},
|
||||||
|
AlgorithmIdentifier::String(_) => {
|
||||||
|
// All algorithms that support "get key length" require additional parameters
|
||||||
|
Err(Error::NotSupported)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm> with operation `"digest"`
|
||||||
|
fn normalize_algorithm_for_digest(
|
||||||
|
cx: JSContext,
|
||||||
|
algorithm: &AlgorithmIdentifier,
|
||||||
|
) -> Result<DigestAlgorithm, Error> {
|
||||||
|
let name = match algorithm {
|
||||||
|
AlgorithmIdentifier::Object(obj) => {
|
||||||
|
rooted!(in(*cx) let value = ObjectValue(obj.get()));
|
||||||
|
let Ok(ConversionResult::Success(algorithm)) = Algorithm::new(cx, value.handle())
|
||||||
|
else {
|
||||||
|
return Err(Error::Syntax);
|
||||||
|
};
|
||||||
|
|
||||||
|
algorithm.name.str().to_uppercase()
|
||||||
|
},
|
||||||
|
AlgorithmIdentifier::String(name) => name.str().to_uppercase(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let normalized_algorithm = match name.as_str() {
|
||||||
|
ALG_SHA1 => DigestAlgorithm::Sha1,
|
||||||
|
ALG_SHA256 => DigestAlgorithm::Sha256,
|
||||||
|
ALG_SHA384 => DigestAlgorithm::Sha384,
|
||||||
|
ALG_SHA512 => DigestAlgorithm::Sha512,
|
||||||
|
_ => return Err(Error::NotSupported),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(normalized_algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm> with operation `"importKey"`
|
||||||
|
fn normalize_algorithm_for_import_key(
|
||||||
|
cx: JSContext,
|
||||||
|
algorithm: &AlgorithmIdentifier,
|
||||||
|
) -> Result<ImportKeyAlgorithm, Error> {
|
||||||
|
let name = match algorithm {
|
||||||
|
AlgorithmIdentifier::Object(obj) => {
|
||||||
|
rooted!(in(*cx) let value = ObjectValue(obj.get()));
|
||||||
|
let Ok(ConversionResult::Success(algorithm)) = Algorithm::new(cx, value.handle())
|
||||||
|
else {
|
||||||
|
return Err(Error::Syntax);
|
||||||
|
};
|
||||||
|
|
||||||
|
algorithm.name.str().to_uppercase()
|
||||||
|
},
|
||||||
|
AlgorithmIdentifier::String(name) => name.str().to_uppercase(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let normalized_algorithm = match name.as_str() {
|
||||||
|
ALG_AES_CBC => ImportKeyAlgorithm::AesCbc,
|
||||||
|
ALG_AES_CTR => ImportKeyAlgorithm::AesCtr,
|
||||||
|
ALG_PBKDF2 => ImportKeyAlgorithm::Pbkdf2,
|
||||||
|
_ => return Err(Error::NotSupported),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(normalized_algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm> with operation `"deriveBits"`
|
||||||
|
fn normalize_algorithm_for_derive_bits(
|
||||||
|
cx: JSContext,
|
||||||
|
algorithm: &AlgorithmIdentifier,
|
||||||
|
) -> Result<DeriveBitsAlgorithm, Error> {
|
||||||
|
let AlgorithmIdentifier::Object(obj) = algorithm else {
|
||||||
|
// All algorithms that support "deriveBits" require additional parameters
|
||||||
|
return Err(Error::NotSupported);
|
||||||
|
};
|
||||||
|
|
||||||
|
rooted!(in(*cx) let value = ObjectValue(obj.get()));
|
||||||
|
let Ok(ConversionResult::Success(algorithm)) = Algorithm::new(cx, value.handle()) else {
|
||||||
|
return Err(Error::Syntax);
|
||||||
|
};
|
||||||
|
|
||||||
|
let normalized_algorithm = if algorithm.name.str().eq_ignore_ascii_case(ALG_PBKDF2) {
|
||||||
|
let params = value_from_js_object!(Pbkdf2Params, cx, value);
|
||||||
|
let subtle_params = SubtlePbkdf2Params::new(cx, params)?;
|
||||||
|
DeriveBitsAlgorithm::Pbkdf2(subtle_params)
|
||||||
|
} else {
|
||||||
|
return Err(Error::NotSupported);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(normalized_algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm> with operation `"deriveBits"`
|
||||||
|
fn normalize_algorithm_for_encrypt_or_decrypt(
|
||||||
|
cx: JSContext,
|
||||||
|
algorithm: &AlgorithmIdentifier,
|
||||||
|
) -> Result<EncryptionAlgorithm, Error> {
|
||||||
|
let AlgorithmIdentifier::Object(obj) = algorithm else {
|
||||||
|
// All algorithms that support "encrypt" or "decrypt" require additional parameters
|
||||||
|
return Err(Error::NotSupported);
|
||||||
|
};
|
||||||
|
|
||||||
|
rooted!(in(*cx) let value = ObjectValue(obj.get()));
|
||||||
|
let Ok(ConversionResult::Success(algorithm)) = Algorithm::new(cx, value.handle()) else {
|
||||||
|
return Err(Error::Syntax);
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = algorithm.name.str();
|
||||||
|
let normalized_algorithm = if name.eq_ignore_ascii_case(ALG_AES_CBC) {
|
||||||
|
let params = value_from_js_object!(AesCbcParams, cx, value);
|
||||||
|
EncryptionAlgorithm::AesCbc(params.into())
|
||||||
|
} else if name.eq_ignore_ascii_case(ALG_AES_CTR) {
|
||||||
|
let params = value_from_js_object!(AesCtrParams, cx, value);
|
||||||
|
EncryptionAlgorithm::AesCtr(params.into())
|
||||||
|
} else {
|
||||||
|
return Err(Error::NotSupported);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(normalized_algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm> with operation `"generateKey"`
|
||||||
|
fn normalize_algorithm_for_generate_key(
|
||||||
|
cx: JSContext,
|
||||||
|
algorithm: &AlgorithmIdentifier,
|
||||||
|
) -> Result<KeyGenerationAlgorithm, Error> {
|
||||||
|
let AlgorithmIdentifier::Object(obj) = algorithm else {
|
||||||
|
// All algorithms that support "generateKey" require additional parameters
|
||||||
|
return Err(Error::NotSupported);
|
||||||
|
};
|
||||||
|
|
||||||
|
rooted!(in(*cx) let value = ObjectValue(obj.get()));
|
||||||
|
let Ok(ConversionResult::Success(algorithm)) = Algorithm::new(cx, value.handle()) else {
|
||||||
|
return Err(Error::Syntax);
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = algorithm.name.str();
|
||||||
|
let normalized_algorithm =
|
||||||
|
if name.eq_ignore_ascii_case(ALG_AES_CBC) || name.eq_ignore_ascii_case(ALG_AES_CTR) {
|
||||||
|
let params = value_from_js_object!(AesKeyGenParams, cx, value);
|
||||||
|
KeyGenerationAlgorithm::Aes(params.into())
|
||||||
|
} else {
|
||||||
|
return Err(Error::NotSupported);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(normalized_algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
impl SubtleCrypto {
|
impl SubtleCrypto {
|
||||||
/// <https://w3c.github.io/webcrypto/#aes-cbc-operations>
|
/// <https://w3c.github.io/webcrypto/#aes-cbc-operations>
|
||||||
fn encrypt_aes_cbc(
|
fn encrypt_aes_cbc(
|
||||||
&self,
|
&self,
|
||||||
params: SubtleAesCbcParams,
|
params: &SubtleAesCbcParams,
|
||||||
key: &CryptoKey,
|
key: &CryptoKey,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
cx: JSContext,
|
cx: JSContext,
|
||||||
|
@ -966,7 +1064,7 @@ impl SubtleCrypto {
|
||||||
/// <https://w3c.github.io/webcrypto/#aes-cbc-operations>
|
/// <https://w3c.github.io/webcrypto/#aes-cbc-operations>
|
||||||
fn decrypt_aes_cbc(
|
fn decrypt_aes_cbc(
|
||||||
&self,
|
&self,
|
||||||
params: SubtleAesCbcParams,
|
params: &SubtleAesCbcParams,
|
||||||
key: &CryptoKey,
|
key: &CryptoKey,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
cx: JSContext,
|
cx: JSContext,
|
||||||
|
@ -1010,7 +1108,7 @@ impl SubtleCrypto {
|
||||||
/// <https://w3c.github.io/webcrypto/#aes-ctr-operations>
|
/// <https://w3c.github.io/webcrypto/#aes-ctr-operations>
|
||||||
fn encrypt_decrypt_aes_ctr(
|
fn encrypt_decrypt_aes_ctr(
|
||||||
&self,
|
&self,
|
||||||
params: SubtleAesCtrParams,
|
params: &SubtleAesCtrParams,
|
||||||
key: &CryptoKey,
|
key: &CryptoKey,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
cx: JSContext,
|
cx: JSContext,
|
||||||
|
@ -1051,7 +1149,7 @@ impl SubtleCrypto {
|
||||||
fn generate_key_aes(
|
fn generate_key_aes(
|
||||||
&self,
|
&self,
|
||||||
usages: Vec<KeyUsage>,
|
usages: Vec<KeyUsage>,
|
||||||
key_gen_params: SubtleAesKeyGenParams,
|
key_gen_params: &SubtleAesKeyGenParams,
|
||||||
extractable: bool,
|
extractable: bool,
|
||||||
) -> Result<DomRoot<CryptoKey>, Error> {
|
) -> Result<DomRoot<CryptoKey>, Error> {
|
||||||
let mut rand = vec![0; key_gen_params.length as usize];
|
let mut rand = vec![0; key_gen_params.length as usize];
|
||||||
|
@ -1323,16 +1421,11 @@ impl SubtlePbkdf2Params {
|
||||||
|
|
||||||
// Step 3. Let prf be the MAC Generation function described in Section 4 of [FIPS-198-1]
|
// Step 3. Let prf be the MAC Generation function described in Section 4 of [FIPS-198-1]
|
||||||
// using the hash function described by the hash member of normalizedAlgorithm.
|
// using the hash function described by the hash member of normalizedAlgorithm.
|
||||||
let NormalizedAlgorithm::Algorithm(alg) = &*self.hash else {
|
let prf = match self.hash {
|
||||||
return Err(Error::NotSupported);
|
DigestAlgorithm::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1,
|
||||||
};
|
DigestAlgorithm::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256,
|
||||||
|
DigestAlgorithm::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384,
|
||||||
let prf = match alg.name.as_str() {
|
DigestAlgorithm::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512,
|
||||||
ALG_SHA1 => pbkdf2::PBKDF2_HMAC_SHA1,
|
|
||||||
ALG_SHA256 => pbkdf2::PBKDF2_HMAC_SHA256,
|
|
||||||
ALG_SHA384 => pbkdf2::PBKDF2_HMAC_SHA384,
|
|
||||||
ALG_SHA512 => pbkdf2::PBKDF2_HMAC_SHA512,
|
|
||||||
_ => return Err(Error::NotSupported),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 4. Let result be the result of performing the PBKDF2 operation defined in Section 5.2 of [RFC8018] using
|
// Step 4. Let result be the result of performing the PBKDF2 operation defined in Section 5.2 of [RFC8018] using
|
||||||
|
@ -1358,64 +1451,6 @@ impl SubtlePbkdf2Params {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NormalizedAlgorithm {
|
|
||||||
fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
|
|
||||||
match self {
|
|
||||||
Self::Pbkdf2Params(pbkdf2_params) => pbkdf2_params.derive_bits(key, length),
|
|
||||||
_ => Err(Error::NotSupported),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_key_length(&self) -> Result<u16, Error> {
|
|
||||||
match self {
|
|
||||||
Self::AesCtrParams(aes_ctr_params) => {
|
|
||||||
get_key_length_for_aes(aes_ctr_params.length as u16)
|
|
||||||
},
|
|
||||||
_ => Err(Error::NotSupported),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn import_key(
|
|
||||||
&self,
|
|
||||||
subtle: &SubtleCrypto,
|
|
||||||
format: KeyFormat,
|
|
||||||
secret: &[u8],
|
|
||||||
extractable: bool,
|
|
||||||
key_usages: Vec<KeyUsage>,
|
|
||||||
) -> Result<DomRoot<CryptoKey>, Error> {
|
|
||||||
let alg = match self {
|
|
||||||
Self::Algorithm(name) => name,
|
|
||||||
_ => {
|
|
||||||
return Err(Error::NotSupported);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
match alg.name.as_str() {
|
|
||||||
ALG_AES_CBC => {
|
|
||||||
subtle.import_key_aes(format, secret, extractable, key_usages, ALG_AES_CBC)
|
|
||||||
},
|
|
||||||
ALG_AES_CTR => {
|
|
||||||
subtle.import_key_aes(format, secret, extractable, key_usages, ALG_AES_CTR)
|
|
||||||
},
|
|
||||||
ALG_PBKDF2 => subtle.import_key_pbkdf2(format, secret, extractable, key_usages),
|
|
||||||
_ => Err(Error::NotSupported),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn digest(&self, data: &[u8]) -> Result<impl AsRef<[u8]>, Error> {
|
|
||||||
let algorithm = match self {
|
|
||||||
Self::Sha1 => &digest::SHA1_FOR_LEGACY_USE_ONLY,
|
|
||||||
Self::Sha256 => &digest::SHA256,
|
|
||||||
Self::Sha384 => &digest::SHA384,
|
|
||||||
Self::Sha512 => &digest::SHA512,
|
|
||||||
_ => {
|
|
||||||
return Err(Error::NotSupported);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Ok(digest::digest(algorithm, data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://w3c.github.io/webcrypto/#aes-ctr-operations>
|
/// <https://w3c.github.io/webcrypto/#aes-ctr-operations>
|
||||||
fn get_key_length_for_aes(length: u16) -> Result<u16, Error> {
|
fn get_key_length_for_aes(length: u16) -> Result<u16, Error> {
|
||||||
// Step 1. If the length member of normalizedDerivedKeyAlgorithm is not 128, 192 or 256,
|
// Step 1. If the length member of normalizedDerivedKeyAlgorithm is not 128, 192 or 256,
|
||||||
|
@ -1427,3 +1462,114 @@ fn get_key_length_for_aes(length: u16) -> Result<u16, Error> {
|
||||||
// Step 2. Return the length member of normalizedDerivedKeyAlgorithm.
|
// Step 2. Return the length member of normalizedDerivedKeyAlgorithm.
|
||||||
Ok(length)
|
Ok(length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GetKeyLengthAlgorithm {
|
||||||
|
fn get_key_length(&self) -> Result<u16, Error> {
|
||||||
|
match self {
|
||||||
|
Self::Aes(length) => get_key_length_for_aes(*length),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DigestAlgorithm {
|
||||||
|
fn digest(&self, data: &[u8]) -> Result<impl AsRef<[u8]>, Error> {
|
||||||
|
let algorithm = match self {
|
||||||
|
Self::Sha1 => &digest::SHA1_FOR_LEGACY_USE_ONLY,
|
||||||
|
Self::Sha256 => &digest::SHA256,
|
||||||
|
Self::Sha384 => &digest::SHA384,
|
||||||
|
Self::Sha512 => &digest::SHA512,
|
||||||
|
};
|
||||||
|
Ok(digest::digest(algorithm, data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImportKeyAlgorithm {
|
||||||
|
fn import_key(
|
||||||
|
&self,
|
||||||
|
subtle: &SubtleCrypto,
|
||||||
|
format: KeyFormat,
|
||||||
|
secret: &[u8],
|
||||||
|
extractable: bool,
|
||||||
|
key_usages: Vec<KeyUsage>,
|
||||||
|
) -> Result<DomRoot<CryptoKey>, Error> {
|
||||||
|
match self {
|
||||||
|
Self::AesCbc => {
|
||||||
|
subtle.import_key_aes(format, secret, extractable, key_usages, ALG_AES_CBC)
|
||||||
|
},
|
||||||
|
Self::AesCtr => {
|
||||||
|
subtle.import_key_aes(format, secret, extractable, key_usages, ALG_AES_CTR)
|
||||||
|
},
|
||||||
|
Self::Pbkdf2 => subtle.import_key_pbkdf2(format, secret, extractable, key_usages),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeriveBitsAlgorithm {
|
||||||
|
fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
|
||||||
|
match self {
|
||||||
|
Self::Pbkdf2(pbkdf2_params) => pbkdf2_params.derive_bits(key, length),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EncryptionAlgorithm {
|
||||||
|
/// <https://w3c.github.io/webcrypto/#dom-algorithm-name>
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Self::AesCbc(key_gen_params) => &key_gen_params.name,
|
||||||
|
Self::AesCtr(key_gen_params) => &key_gen_params.name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This doesn't really need the "SubtleCrypto" argument
|
||||||
|
fn encrypt(
|
||||||
|
&self,
|
||||||
|
subtle: &SubtleCrypto,
|
||||||
|
key: &CryptoKey,
|
||||||
|
data: &[u8],
|
||||||
|
cx: JSContext,
|
||||||
|
result: MutableHandleObject,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
match self {
|
||||||
|
Self::AesCbc(key_gen_params) => {
|
||||||
|
subtle.encrypt_aes_cbc(key_gen_params, key, data, cx, result)
|
||||||
|
},
|
||||||
|
Self::AesCtr(key_gen_params) => {
|
||||||
|
subtle.encrypt_decrypt_aes_ctr(key_gen_params, key, data, cx, result)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This doesn't really need the "SubtleCrypto" argument
|
||||||
|
fn decrypt(
|
||||||
|
&self,
|
||||||
|
subtle: &SubtleCrypto,
|
||||||
|
key: &CryptoKey,
|
||||||
|
data: &[u8],
|
||||||
|
cx: JSContext,
|
||||||
|
result: MutableHandleObject,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
match self {
|
||||||
|
Self::AesCbc(key_gen_params) => {
|
||||||
|
subtle.decrypt_aes_cbc(key_gen_params, key, data, cx, result)
|
||||||
|
},
|
||||||
|
Self::AesCtr(key_gen_params) => {
|
||||||
|
subtle.encrypt_decrypt_aes_ctr(key_gen_params, key, data, cx, result)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyGenerationAlgorithm {
|
||||||
|
// FIXME: This doesn't really need the "SubtleCrypto" argument
|
||||||
|
fn generate_key(
|
||||||
|
&self,
|
||||||
|
subtle: &SubtleCrypto,
|
||||||
|
usages: Vec<KeyUsage>,
|
||||||
|
extractable: bool,
|
||||||
|
) -> Result<DomRoot<CryptoKey>, Error> {
|
||||||
|
match self {
|
||||||
|
Self::Aes(params) => subtle.generate_key_aes(usages, params, extractable),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,17 +2,11 @@
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
|
|
||||||
[big-br-body.https.any.html]
|
[big-br-body.https.any.html]
|
||||||
[large br data should be decompressed successfully]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[large br data should be decompressed successfully with byte stream]
|
[large br data should be decompressed successfully with byte stream]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[big-br-body.https.any.worker.html]
|
[big-br-body.https.any.worker.html]
|
||||||
[large br data should be decompressed successfully]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[large br data should be decompressed successfully with byte stream]
|
[large br data should be decompressed successfully with byte stream]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,11 @@
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
|
|
||||||
[big-gzip-body.https.any.worker.html]
|
[big-gzip-body.https.any.worker.html]
|
||||||
[large gzip data should be decompressed successfully]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[large gzip data should be decompressed successfully with byte stream]
|
[large gzip data should be decompressed successfully with byte stream]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[big-gzip-body.https.any.html]
|
[big-gzip-body.https.any.html]
|
||||||
[large gzip data should be decompressed successfully]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[large gzip data should be decompressed successfully with byte stream]
|
[large gzip data should be decompressed successfully with byte stream]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue