mirror of
https://github.com/servo/servo.git
synced 2025-09-27 15:20:09 +01:00
The WebCryptoAPI spec requires that when we generate crypto keys by the generateKey method of SubtleCrypto interface we have to check whether the usages is empty. If the usages is empty, throw a SyntaxError. FYI, Step 9 of https://w3c.github.io/webcrypto/#SubtleCrypto-method-generateKey We have not yet implemented this logic, and this patch implements it. Testing: Pass WPT tests that were expected to fail. --------- Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
171 lines
4.8 KiB
Rust
171 lines
4.8 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
use std::cell::Cell;
|
|
use std::ptr::NonNull;
|
|
|
|
use dom_struct::dom_struct;
|
|
use js::jsapi::{Heap, JSObject, Value};
|
|
use js::rust::HandleObject;
|
|
use script_bindings::conversions::SafeToJSValConvertible;
|
|
|
|
use crate::dom::bindings::cell::DomRefCell;
|
|
use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
|
|
CryptoKeyMethods, KeyType, KeyUsage,
|
|
};
|
|
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
|
use crate::dom::bindings::root::DomRoot;
|
|
use crate::dom::bindings::str::DOMString;
|
|
use crate::dom::globalscope::GlobalScope;
|
|
use crate::script_runtime::{CanGc, JSContext};
|
|
|
|
pub(crate) enum CryptoKeyOrCryptoKeyPair {
|
|
CryptoKey(DomRoot<CryptoKey>),
|
|
// TODO: CryptoKeyPair(CryptoKeyPair),
|
|
}
|
|
|
|
/// The underlying cryptographic data this key represents
|
|
#[allow(dead_code)]
|
|
#[derive(MallocSizeOf)]
|
|
pub(crate) enum Handle {
|
|
Aes128(Vec<u8>),
|
|
Aes192(Vec<u8>),
|
|
Aes256(Vec<u8>),
|
|
Pbkdf2(Vec<u8>),
|
|
Hkdf(Vec<u8>),
|
|
Hmac(Vec<u8>),
|
|
}
|
|
|
|
/// <https://w3c.github.io/webcrypto/#cryptokey-interface>
|
|
#[dom_struct]
|
|
pub(crate) struct CryptoKey {
|
|
reflector_: Reflector,
|
|
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-type>
|
|
key_type: KeyType,
|
|
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-extractable>
|
|
extractable: Cell<bool>,
|
|
|
|
/// The name of the algorithm used
|
|
///
|
|
/// This is always the same as the `name` of the
|
|
/// [`[[algorithm]]`](https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm)
|
|
/// internal slot, but we store it here again for convenience
|
|
algorithm: DOMString,
|
|
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm>
|
|
#[ignore_malloc_size_of = "Defined in mozjs"]
|
|
algorithm_object: Heap<*mut JSObject>,
|
|
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
|
|
usages: DomRefCell<Vec<KeyUsage>>,
|
|
#[no_trace]
|
|
handle: Handle,
|
|
}
|
|
|
|
impl CryptoKey {
|
|
fn new_inherited(
|
|
key_type: KeyType,
|
|
extractable: bool,
|
|
usages: Vec<KeyUsage>,
|
|
algorithm: DOMString,
|
|
handle: Handle,
|
|
) -> CryptoKey {
|
|
CryptoKey {
|
|
reflector_: Reflector::new(),
|
|
key_type,
|
|
extractable: Cell::new(extractable),
|
|
algorithm,
|
|
algorithm_object: Heap::default(),
|
|
usages: DomRefCell::new(usages),
|
|
handle,
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub(crate) fn new(
|
|
global: &GlobalScope,
|
|
key_type: KeyType,
|
|
extractable: bool,
|
|
algorithm: DOMString,
|
|
algorithm_object: HandleObject,
|
|
usages: Vec<KeyUsage>,
|
|
handle: Handle,
|
|
can_gc: CanGc,
|
|
) -> DomRoot<CryptoKey> {
|
|
let object = reflect_dom_object(
|
|
Box::new(CryptoKey::new_inherited(
|
|
key_type,
|
|
extractable,
|
|
usages,
|
|
algorithm,
|
|
handle,
|
|
)),
|
|
global,
|
|
can_gc,
|
|
);
|
|
|
|
object.algorithm_object.set(algorithm_object.get());
|
|
|
|
object
|
|
}
|
|
|
|
pub(crate) fn algorithm(&self) -> String {
|
|
self.algorithm.to_string()
|
|
}
|
|
|
|
pub(crate) fn usages(&self) -> Vec<KeyUsage> {
|
|
self.usages.borrow().clone()
|
|
}
|
|
|
|
pub(crate) fn handle(&self) -> &Handle {
|
|
&self.handle
|
|
}
|
|
|
|
pub(crate) fn set_extractable(&self, extractable: bool) {
|
|
self.extractable.set(extractable);
|
|
}
|
|
|
|
pub(crate) fn set_usages(&self, usages: &[KeyUsage]) {
|
|
*self.usages.borrow_mut() = usages.to_owned();
|
|
}
|
|
}
|
|
|
|
impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-type>
|
|
fn Type(&self) -> KeyType {
|
|
self.key_type
|
|
}
|
|
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-extractable>
|
|
fn Extractable(&self) -> bool {
|
|
self.extractable.get()
|
|
}
|
|
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm>
|
|
fn Algorithm(&self, _cx: JSContext) -> NonNull<JSObject> {
|
|
NonNull::new(self.algorithm_object.get()).unwrap()
|
|
}
|
|
|
|
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
|
|
fn Usages(&self, cx: JSContext) -> NonNull<JSObject> {
|
|
rooted!(in(*cx) let mut usages: Value);
|
|
self.usages.borrow().safe_to_jsval(cx, usages.handle_mut());
|
|
NonNull::new(usages.to_object()).unwrap()
|
|
}
|
|
}
|
|
|
|
impl Handle {
|
|
pub(crate) fn as_bytes(&self) -> &[u8] {
|
|
match self {
|
|
Self::Aes128(bytes) => bytes,
|
|
Self::Aes192(bytes) => bytes,
|
|
Self::Aes256(bytes) => bytes,
|
|
Self::Pbkdf2(bytes) => bytes,
|
|
Self::Hkdf(bytes) => bytes,
|
|
Self::Hmac(bytes) => bytes,
|
|
}
|
|
}
|
|
}
|