Skip to main content

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