script/dom/subtlecrypto/
aes_kw_operation.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 aes::{Aes128, Aes192, Aes256};
6use aes_kw::Kek;
7use js::context::JSContext;
8
9use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::KeyUsage;
10use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::KeyFormat;
11use crate::dom::bindings::error::Error;
12use crate::dom::bindings::root::DomRoot;
13use crate::dom::cryptokey::{CryptoKey, Handle};
14use crate::dom::globalscope::GlobalScope;
15use crate::dom::subtlecrypto::aes_common::AesAlgorithm;
16use crate::dom::subtlecrypto::{
17    ExportedKey, SubtleAesDerivedKeyParams, SubtleAesKeyGenParams, aes_common,
18};
19
20/// <https://w3c.github.io/webcrypto/#aes-kw-operations-wrap-key>
21pub(crate) fn wrap_key(key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
22    // Step 1. If plaintext is not a multiple of 64 bits in length, then throw an OperationError.
23    if plaintext.len() % 8 != 0 {
24        return Err(Error::Operation(Some(
25            "The plaintext bit-length is not a multiple of 64".into(),
26        )));
27    }
28
29    // Step 2. Let ciphertext be the result of performing the Key Wrap operation described in
30    // Section 2.2.1 of [RFC3394] with plaintext as the plaintext to be wrapped and using the
31    // default Initial Value defined in Section 2.2.3.1 of the same document.
32    let ciphertext = match key.handle() {
33        Handle::Aes128Key(key) => {
34            let kek = Kek::<Aes128>::new(key);
35            kek.wrap_vec(plaintext).map_err(|_| {
36                Error::Operation(Some(
37                    "AES-KW failed to perform the Key Wrap operation".to_string(),
38                ))
39            })?
40        },
41        Handle::Aes192Key(key) => {
42            let kek = Kek::<Aes192>::new(key);
43            kek.wrap_vec(plaintext).map_err(|_| {
44                Error::Operation(Some(
45                    "AES-KW failed to perform the Key Wrap operation".to_string(),
46                ))
47            })?
48        },
49        Handle::Aes256Key(key) => {
50            let kek = Kek::<Aes256>::new(key);
51            kek.wrap_vec(plaintext).map_err(|_| {
52                Error::Operation(Some(
53                    "AES-KW failed to perform the Key Wrap operation".to_string(),
54                ))
55            })?
56        },
57        _ => {
58            return Err(Error::Operation(Some(
59                "The key handle is not representing an AES key".to_string(),
60            )));
61        },
62    };
63
64    // Step 3. Return ciphertext.
65    Ok(ciphertext)
66}
67
68/// <https://w3c.github.io/webcrypto/#aes-kw-operations-unwrap-key>
69pub(crate) fn unwrap_key(key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
70    // Step 1. Let plaintext be the result of performing the Key Unwrap operation described in
71    // Section 2.2.2 of [RFC3394] with ciphertext as the input ciphertext and using the default
72    // Initial Value defined in Section 2.2.3.1 of the same document.
73    // Step 2. If the Key Unwrap operation returns an error, then throw an OperationError.
74    let plaintext = match key.handle() {
75        Handle::Aes128Key(key) => {
76            let kek = Kek::<Aes128>::new(key);
77            kek.unwrap_vec(ciphertext).map_err(|_| {
78                Error::Operation(Some(
79                    "AES-KW failed to perform the Key Unwrap operation".to_string(),
80                ))
81            })?
82        },
83        Handle::Aes192Key(key) => {
84            let kek = Kek::<Aes192>::new(key);
85            kek.unwrap_vec(ciphertext).map_err(|_| {
86                Error::Operation(Some(
87                    "AES-KW failed to perform the Key Unwrap operation".to_string(),
88                ))
89            })?
90        },
91        Handle::Aes256Key(key) => {
92            let kek = Kek::<Aes256>::new(key);
93            kek.unwrap_vec(ciphertext).map_err(|_| {
94                Error::Operation(Some(
95                    "AES-KW failed to perform the Key Unwrap operation".to_string(),
96                ))
97            })?
98        },
99        _ => {
100            return Err(Error::Operation(Some(
101                "The key handle is not representing an AES key".to_string(),
102            )));
103        },
104    };
105
106    // Step 3. Return plaintext.
107    Ok(plaintext)
108}
109
110/// <https://w3c.github.io/webcrypto/#aes-kw-operations-generate-key>
111pub(crate) fn generate_key(
112    cx: &mut JSContext,
113    global: &GlobalScope,
114    normalized_algorithm: &SubtleAesKeyGenParams,
115    extractable: bool,
116    usages: Vec<KeyUsage>,
117) -> Result<DomRoot<CryptoKey>, Error> {
118    aes_common::generate_key(
119        AesAlgorithm::AesKw,
120        cx,
121        global,
122        normalized_algorithm,
123        extractable,
124        usages,
125    )
126}
127
128/// <https://w3c.github.io/webcrypto/#aes-kw-operations-import-key>
129pub(crate) fn import_key(
130    cx: &mut JSContext,
131    global: &GlobalScope,
132    format: KeyFormat,
133    key_data: &[u8],
134    extractable: bool,
135    usages: Vec<KeyUsage>,
136) -> Result<DomRoot<CryptoKey>, Error> {
137    aes_common::import_key(
138        AesAlgorithm::AesKw,
139        cx,
140        global,
141        format,
142        key_data,
143        extractable,
144        usages,
145    )
146}
147
148/// <https://w3c.github.io/webcrypto/#aes-kw-operations-export-key>
149pub(crate) fn export_key(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
150    aes_common::export_key(AesAlgorithm::AesKw, format, key)
151}
152
153/// <https://w3c.github.io/webcrypto/#aes-kw-operations-get-key-length>
154pub(crate) fn get_key_length(
155    normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
156) -> Result<Option<u32>, Error> {
157    aes_common::get_key_length(normalized_derived_key_algorithm)
158}