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