script/dom/
cryptokey.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::cell::Cell;
6use std::ptr::NonNull;
7
8use dom_struct::dom_struct;
9use js::jsapi::{Heap, JSObject, Value};
10use js::rust::HandleObject;
11use script_bindings::conversions::SafeToJSValConvertible;
12
13use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
14    CryptoKeyMethods, KeyType, KeyUsage,
15};
16use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
17use crate::dom::bindings::root::DomRoot;
18use crate::dom::bindings::str::DOMString;
19use crate::dom::globalscope::GlobalScope;
20use crate::script_runtime::{CanGc, JSContext};
21
22/// The underlying cryptographic data this key represents
23#[allow(dead_code)]
24#[derive(MallocSizeOf)]
25pub(crate) enum Handle {
26    Aes128(Vec<u8>),
27    Aes192(Vec<u8>),
28    Aes256(Vec<u8>),
29    Pbkdf2(Vec<u8>),
30    Hkdf(Vec<u8>),
31    Hmac(Vec<u8>),
32}
33
34/// <https://w3c.github.io/webcrypto/#cryptokey-interface>
35#[dom_struct]
36pub(crate) struct CryptoKey {
37    reflector_: Reflector,
38
39    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-type>
40    key_type: KeyType,
41
42    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-extractable>
43    extractable: Cell<bool>,
44
45    /// The name of the algorithm used
46    ///
47    /// This is always the same as the `name` of the
48    /// [`[[algorithm]]`](https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm)
49    /// internal slot, but we store it here again for convenience
50    algorithm: DOMString,
51
52    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm>
53    #[ignore_malloc_size_of = "Defined in mozjs"]
54    algorithm_object: Heap<*mut JSObject>,
55
56    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
57    usages: Vec<KeyUsage>,
58    #[no_trace]
59    handle: Handle,
60}
61
62impl CryptoKey {
63    fn new_inherited(
64        key_type: KeyType,
65        extractable: bool,
66        usages: Vec<KeyUsage>,
67        algorithm: DOMString,
68        handle: Handle,
69    ) -> CryptoKey {
70        CryptoKey {
71            reflector_: Reflector::new(),
72            key_type,
73            extractable: Cell::new(extractable),
74            algorithm,
75            algorithm_object: Heap::default(),
76            usages,
77            handle,
78        }
79    }
80
81    #[allow(clippy::too_many_arguments)]
82    pub(crate) fn new(
83        global: &GlobalScope,
84        key_type: KeyType,
85        extractable: bool,
86        algorithm: DOMString,
87        algorithm_object: HandleObject,
88        usages: Vec<KeyUsage>,
89        handle: Handle,
90        can_gc: CanGc,
91    ) -> DomRoot<CryptoKey> {
92        let object = reflect_dom_object(
93            Box::new(CryptoKey::new_inherited(
94                key_type,
95                extractable,
96                usages,
97                algorithm,
98                handle,
99            )),
100            global,
101            can_gc,
102        );
103
104        object.algorithm_object.set(algorithm_object.get());
105
106        object
107    }
108
109    pub(crate) fn algorithm(&self) -> String {
110        self.algorithm.to_string()
111    }
112
113    pub(crate) fn usages(&self) -> &[KeyUsage] {
114        &self.usages
115    }
116
117    pub(crate) fn handle(&self) -> &Handle {
118        &self.handle
119    }
120}
121
122impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
123    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-type>
124    fn Type(&self) -> KeyType {
125        self.key_type
126    }
127
128    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-extractable>
129    fn Extractable(&self) -> bool {
130        self.extractable.get()
131    }
132
133    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm>
134    fn Algorithm(&self, _cx: JSContext) -> NonNull<JSObject> {
135        NonNull::new(self.algorithm_object.get()).unwrap()
136    }
137
138    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
139    fn Usages(&self, cx: JSContext) -> NonNull<JSObject> {
140        rooted!(in(*cx) let mut usages: Value);
141        self.usages.safe_to_jsval(cx, usages.handle_mut());
142        NonNull::new(usages.to_object()).unwrap()
143    }
144}
145
146impl Handle {
147    pub(crate) fn as_bytes(&self) -> &[u8] {
148        match self {
149            Self::Aes128(bytes) => bytes,
150            Self::Aes192(bytes) => bytes,
151            Self::Aes256(bytes) => bytes,
152            Self::Pbkdf2(bytes) => bytes,
153            Self::Hkdf(bytes) => bytes,
154            Self::Hmac(bytes) => bytes,
155        }
156    }
157}