Skip to main content

script/dom/webcrypto/subtlecrypto/
aes_ocb_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::cipher::{BlockCipherDecrypt, BlockCipherEncrypt};
6use aes::{Aes128, Aes192, Aes256};
7use js::context::JSContext;
8use ocb3::aead::array::ArraySize;
9use ocb3::aead::array::typenum::{
10    GrEq, IsGreaterOrEqual, IsLessOrEqual, LeEq, NonZero, U6, U7, U8, U9, U10, U11, U12, U13, U14,
11    U15, U16,
12};
13use ocb3::aead::common::BlockSizeUser;
14use ocb3::aead::{Key, KeySizeUser};
15use ocb3::{AeadInOut, KeyInit, Ocb3};
16
17use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::KeyUsage;
18use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::KeyFormat;
19use crate::dom::bindings::error::Error;
20use crate::dom::bindings::root::DomRoot;
21use crate::dom::cryptokey::{CryptoKey, Handle};
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::subtlecrypto::aes_common::AesAlgorithm;
24use crate::dom::subtlecrypto::{
25    ExportedKey, SubtleAeadParams, SubtleAesDerivedKeyParams, SubtleAesKeyGenParams, aes_common,
26};
27
28/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-encrypt>
29pub(crate) fn encrypt(
30    normalized_algorithm: &SubtleAeadParams,
31    key: &CryptoKey,
32    plaintext: &[u8],
33) -> Result<Vec<u8>, Error> {
34    // Step 1. If the iv member of normalizedAlgorithm has a length greater than 15 bytes, then
35    // throw an OperationError.
36    if normalized_algorithm.iv.len() > 15 {
37        return Err(Error::Operation(Some(
38            "The iv member of normalizedAlgorithm has a length greater than 15 bytes".to_string(),
39        )));
40    }
41
42    // Step 2.
43    // If the tagLength member of normalizedAlgorithm is not present:
44    //     Let tagLength be 128.
45    // If the tagLength member of normalizedAlgorithm is one of 64, 96 or 128:
46    //     Let tagLength be equal to the tagLength member of normalizedAlgorithm
47    // Otherwise:
48    //     throw an OperationError.
49    let tag_length = match normalized_algorithm.tag_length {
50        None => 128,
51        Some(tag_length) if matches!(tag_length, 64 | 96 | 128) => tag_length,
52        _ => {
53            return Err(Error::Operation(Some(
54                "The tagLength member of normalizedAlgorithm is present, \
55                and not one of 64, 96, or 128"
56                    .to_string(),
57            )));
58        },
59    };
60
61    // Step 3. Let additionalData be the additionalData member of normalizedAlgorithm if present or
62    // the empty octet string otherwise.
63    let additional_data = normalized_algorithm
64        .additional_data
65        .as_deref()
66        .unwrap_or_default();
67
68    // Step 4. Let C be the output that results from performing the OCB-ENCRYPT function described
69    // in Section 4.2 of [RFC7253] using AES as the block cipher, using the key represented by
70    // [[handle]] internal slot of key as the K input parameter, the iv member of
71    // normalizedAlgorithm as the N input parameter, additionalData as the A input parameter,
72    // plaintext as the P input parameter, and tagLength as the TAGLEN global parameter.
73    //
74    // NOTE: We only support IV(nonce) size from 6 bytes to 15 bytes because of the restriction
75    // from the `ocb3` crate <https://docs.rs/ocb3/latest/ocb3/struct.Ocb3.html>. This range is
76    // suggested in the paper <https://eprint.iacr.org/2023/326.pdf> to prevent an attack.
77    let iv = &normalized_algorithm.iv;
78    let ciphertext = match key.handle() {
79        Handle::Aes128Key(key) => match (iv.len(), tag_length) {
80            (6, 64) => ocb_encrypt::<Aes128, U6, U8>(key, plaintext, iv, additional_data)?,
81            (7, 64) => ocb_encrypt::<Aes128, U7, U8>(key, plaintext, iv, additional_data)?,
82            (8, 64) => ocb_encrypt::<Aes128, U8, U8>(key, plaintext, iv, additional_data)?,
83            (9, 64) => ocb_encrypt::<Aes128, U9, U8>(key, plaintext, iv, additional_data)?,
84            (10, 64) => ocb_encrypt::<Aes128, U10, U8>(key, plaintext, iv, additional_data)?,
85            (11, 64) => ocb_encrypt::<Aes128, U11, U8>(key, plaintext, iv, additional_data)?,
86            (12, 64) => ocb_encrypt::<Aes128, U12, U8>(key, plaintext, iv, additional_data)?,
87            (13, 64) => ocb_encrypt::<Aes128, U13, U8>(key, plaintext, iv, additional_data)?,
88            (14, 64) => ocb_encrypt::<Aes128, U14, U8>(key, plaintext, iv, additional_data)?,
89            (15, 64) => ocb_encrypt::<Aes128, U15, U8>(key, plaintext, iv, additional_data)?,
90
91            (6, 96) => ocb_encrypt::<Aes128, U6, U12>(key, plaintext, iv, additional_data)?,
92            (7, 96) => ocb_encrypt::<Aes128, U7, U12>(key, plaintext, iv, additional_data)?,
93            (8, 96) => ocb_encrypt::<Aes128, U8, U12>(key, plaintext, iv, additional_data)?,
94            (9, 96) => ocb_encrypt::<Aes128, U9, U12>(key, plaintext, iv, additional_data)?,
95            (10, 96) => ocb_encrypt::<Aes128, U10, U12>(key, plaintext, iv, additional_data)?,
96            (11, 96) => ocb_encrypt::<Aes128, U11, U12>(key, plaintext, iv, additional_data)?,
97            (12, 96) => ocb_encrypt::<Aes128, U12, U12>(key, plaintext, iv, additional_data)?,
98            (13, 96) => ocb_encrypt::<Aes128, U13, U12>(key, plaintext, iv, additional_data)?,
99            (14, 96) => ocb_encrypt::<Aes128, U14, U12>(key, plaintext, iv, additional_data)?,
100            (15, 96) => ocb_encrypt::<Aes128, U15, U12>(key, plaintext, iv, additional_data)?,
101
102            (6, 128) => ocb_encrypt::<Aes128, U6, U16>(key, plaintext, iv, additional_data)?,
103            (7, 128) => ocb_encrypt::<Aes128, U7, U16>(key, plaintext, iv, additional_data)?,
104            (8, 128) => ocb_encrypt::<Aes128, U8, U16>(key, plaintext, iv, additional_data)?,
105            (9, 128) => ocb_encrypt::<Aes128, U9, U16>(key, plaintext, iv, additional_data)?,
106            (10, 128) => ocb_encrypt::<Aes128, U10, U16>(key, plaintext, iv, additional_data)?,
107            (11, 128) => ocb_encrypt::<Aes128, U11, U16>(key, plaintext, iv, additional_data)?,
108            (12, 128) => ocb_encrypt::<Aes128, U12, U16>(key, plaintext, iv, additional_data)?,
109            (13, 128) => ocb_encrypt::<Aes128, U13, U16>(key, plaintext, iv, additional_data)?,
110            (14, 128) => ocb_encrypt::<Aes128, U14, U16>(key, plaintext, iv, additional_data)?,
111            (15, 128) => ocb_encrypt::<Aes128, U15, U16>(key, plaintext, iv, additional_data)?,
112
113            _ => {
114                return Err(Error::Operation(Some(format!(
115                    "Unsupported IV size ({}-bytes) and/or tag length ({}-bit)",
116                    iv.len(),
117                    tag_length
118                ))));
119            },
120        },
121        Handle::Aes192Key(key) => match (iv.len(), tag_length) {
122            (6, 64) => ocb_encrypt::<Aes192, U6, U8>(key, plaintext, iv, additional_data)?,
123            (7, 64) => ocb_encrypt::<Aes192, U7, U8>(key, plaintext, iv, additional_data)?,
124            (8, 64) => ocb_encrypt::<Aes192, U8, U8>(key, plaintext, iv, additional_data)?,
125            (9, 64) => ocb_encrypt::<Aes192, U9, U8>(key, plaintext, iv, additional_data)?,
126            (10, 64) => ocb_encrypt::<Aes192, U10, U8>(key, plaintext, iv, additional_data)?,
127            (11, 64) => ocb_encrypt::<Aes192, U11, U8>(key, plaintext, iv, additional_data)?,
128            (12, 64) => ocb_encrypt::<Aes192, U12, U8>(key, plaintext, iv, additional_data)?,
129            (13, 64) => ocb_encrypt::<Aes192, U13, U8>(key, plaintext, iv, additional_data)?,
130            (14, 64) => ocb_encrypt::<Aes192, U14, U8>(key, plaintext, iv, additional_data)?,
131            (15, 64) => ocb_encrypt::<Aes192, U15, U8>(key, plaintext, iv, additional_data)?,
132
133            (6, 96) => ocb_encrypt::<Aes192, U6, U12>(key, plaintext, iv, additional_data)?,
134            (7, 96) => ocb_encrypt::<Aes192, U7, U12>(key, plaintext, iv, additional_data)?,
135            (8, 96) => ocb_encrypt::<Aes192, U8, U12>(key, plaintext, iv, additional_data)?,
136            (9, 96) => ocb_encrypt::<Aes192, U9, U12>(key, plaintext, iv, additional_data)?,
137            (10, 96) => ocb_encrypt::<Aes192, U10, U12>(key, plaintext, iv, additional_data)?,
138            (11, 96) => ocb_encrypt::<Aes192, U11, U12>(key, plaintext, iv, additional_data)?,
139            (12, 96) => ocb_encrypt::<Aes192, U12, U12>(key, plaintext, iv, additional_data)?,
140            (13, 96) => ocb_encrypt::<Aes192, U13, U12>(key, plaintext, iv, additional_data)?,
141            (14, 96) => ocb_encrypt::<Aes192, U14, U12>(key, plaintext, iv, additional_data)?,
142            (15, 96) => ocb_encrypt::<Aes192, U15, U12>(key, plaintext, iv, additional_data)?,
143
144            (6, 128) => ocb_encrypt::<Aes192, U6, U16>(key, plaintext, iv, additional_data)?,
145            (7, 128) => ocb_encrypt::<Aes192, U7, U16>(key, plaintext, iv, additional_data)?,
146            (8, 128) => ocb_encrypt::<Aes192, U8, U16>(key, plaintext, iv, additional_data)?,
147            (9, 128) => ocb_encrypt::<Aes192, U9, U16>(key, plaintext, iv, additional_data)?,
148            (10, 128) => ocb_encrypt::<Aes192, U10, U16>(key, plaintext, iv, additional_data)?,
149            (11, 128) => ocb_encrypt::<Aes192, U11, U16>(key, plaintext, iv, additional_data)?,
150            (12, 128) => ocb_encrypt::<Aes192, U12, U16>(key, plaintext, iv, additional_data)?,
151            (13, 128) => ocb_encrypt::<Aes192, U13, U16>(key, plaintext, iv, additional_data)?,
152            (14, 128) => ocb_encrypt::<Aes192, U14, U16>(key, plaintext, iv, additional_data)?,
153            (15, 128) => ocb_encrypt::<Aes192, U15, U16>(key, plaintext, iv, additional_data)?,
154
155            _ => {
156                return Err(Error::Operation(Some(format!(
157                    "Unsupported IV size ({}-bytes) and/or tag length ({}-bit)",
158                    iv.len(),
159                    tag_length
160                ))));
161            },
162        },
163        Handle::Aes256Key(key) => match (iv.len(), tag_length) {
164            (6, 64) => ocb_encrypt::<Aes256, U6, U8>(key, plaintext, iv, additional_data)?,
165            (7, 64) => ocb_encrypt::<Aes256, U7, U8>(key, plaintext, iv, additional_data)?,
166            (8, 64) => ocb_encrypt::<Aes256, U8, U8>(key, plaintext, iv, additional_data)?,
167            (9, 64) => ocb_encrypt::<Aes256, U9, U8>(key, plaintext, iv, additional_data)?,
168            (10, 64) => ocb_encrypt::<Aes256, U10, U8>(key, plaintext, iv, additional_data)?,
169            (11, 64) => ocb_encrypt::<Aes256, U11, U8>(key, plaintext, iv, additional_data)?,
170            (12, 64) => ocb_encrypt::<Aes256, U12, U8>(key, plaintext, iv, additional_data)?,
171            (13, 64) => ocb_encrypt::<Aes256, U13, U8>(key, plaintext, iv, additional_data)?,
172            (14, 64) => ocb_encrypt::<Aes256, U14, U8>(key, plaintext, iv, additional_data)?,
173            (15, 64) => ocb_encrypt::<Aes256, U15, U8>(key, plaintext, iv, additional_data)?,
174
175            (6, 96) => ocb_encrypt::<Aes256, U6, U12>(key, plaintext, iv, additional_data)?,
176            (7, 96) => ocb_encrypt::<Aes256, U7, U12>(key, plaintext, iv, additional_data)?,
177            (8, 96) => ocb_encrypt::<Aes256, U8, U12>(key, plaintext, iv, additional_data)?,
178            (9, 96) => ocb_encrypt::<Aes256, U9, U12>(key, plaintext, iv, additional_data)?,
179            (10, 96) => ocb_encrypt::<Aes256, U10, U12>(key, plaintext, iv, additional_data)?,
180            (11, 96) => ocb_encrypt::<Aes256, U11, U12>(key, plaintext, iv, additional_data)?,
181            (12, 96) => ocb_encrypt::<Aes256, U12, U12>(key, plaintext, iv, additional_data)?,
182            (13, 96) => ocb_encrypt::<Aes256, U13, U12>(key, plaintext, iv, additional_data)?,
183            (14, 96) => ocb_encrypt::<Aes256, U14, U12>(key, plaintext, iv, additional_data)?,
184            (15, 96) => ocb_encrypt::<Aes256, U15, U12>(key, plaintext, iv, additional_data)?,
185
186            (6, 128) => ocb_encrypt::<Aes256, U6, U16>(key, plaintext, iv, additional_data)?,
187            (7, 128) => ocb_encrypt::<Aes256, U7, U16>(key, plaintext, iv, additional_data)?,
188            (8, 128) => ocb_encrypt::<Aes256, U8, U16>(key, plaintext, iv, additional_data)?,
189            (9, 128) => ocb_encrypt::<Aes256, U9, U16>(key, plaintext, iv, additional_data)?,
190            (10, 128) => ocb_encrypt::<Aes256, U10, U16>(key, plaintext, iv, additional_data)?,
191            (11, 128) => ocb_encrypt::<Aes256, U11, U16>(key, plaintext, iv, additional_data)?,
192            (12, 128) => ocb_encrypt::<Aes256, U12, U16>(key, plaintext, iv, additional_data)?,
193            (13, 128) => ocb_encrypt::<Aes256, U13, U16>(key, plaintext, iv, additional_data)?,
194            (14, 128) => ocb_encrypt::<Aes256, U14, U16>(key, plaintext, iv, additional_data)?,
195            (15, 128) => ocb_encrypt::<Aes256, U15, U16>(key, plaintext, iv, additional_data)?,
196
197            _ => {
198                return Err(Error::Operation(Some(format!(
199                    "Unsupported IV size ({}-bytes) and/or tag length ({}-bit)",
200                    iv.len(),
201                    tag_length
202                ))));
203            },
204        },
205        _ => {
206            return Err(Error::Operation(Some(
207                "The key handle is not representing an AES key".to_string(),
208            )));
209        },
210    };
211
212    // Step 5. Return C.
213    Ok(ciphertext)
214}
215
216/// Helper for Step 5 of <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-encrypt>
217fn ocb_encrypt<Cipher, NonceSize, TagSize>(
218    key: &Key<Cipher>,
219    plaintext: &[u8],
220    iv: &[u8],
221    additional_data: &[u8],
222) -> Result<Vec<u8>, Error>
223where
224    Cipher: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + BlockCipherDecrypt,
225    Cipher: KeySizeUser,
226    NonceSize: ArraySize + IsGreaterOrEqual<U6> + IsLessOrEqual<U15>,
227    GrEq<NonceSize, U6>: NonZero,
228    LeEq<NonceSize, U15>: NonZero,
229    TagSize: ArraySize + NonZero + IsLessOrEqual<U16>,
230    LeEq<TagSize, U16>: NonZero,
231{
232    let iv = iv
233        .try_into()
234        .map_err(|_| Error::Operation(Some("Invalid AES-OCB IV".into())))?;
235    let mut ciphertext = plaintext.to_vec();
236    let cipher = Ocb3::<Cipher, NonceSize, TagSize>::new(key);
237    cipher
238        .encrypt_in_place(&iv, additional_data, &mut ciphertext)
239        .map_err(|_| {
240            Error::Operation(Some("AES-OCB authenticated encryption failed".to_string()))
241        })?;
242    Ok(ciphertext)
243}
244
245/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-decrypt>
246pub(crate) fn decrypt(
247    normalized_algorithm: &SubtleAeadParams,
248    key: &CryptoKey,
249    ciphertext: &[u8],
250) -> Result<Vec<u8>, Error> {
251    // Step 1. If the iv member of normalizedAlgorithm has a length greater than 15 bytes, then
252    // throw an OperationError.
253    if normalized_algorithm.iv.len() > 15 {
254        return Err(Error::Operation(Some(
255            "The iv member of normalizedAlgorithm has a length greater than 15 bytes".to_string(),
256        )));
257    }
258
259    // Step 2.
260    // If the tagLength member of normalizedAlgorithm is not present:
261    //     Let tagLength be 128.
262    // If the tagLength member of normalizedAlgorithm is one of 64, 96 or 128:
263    //     Let tagLength be equal to the tagLength member of normalizedAlgorithm
264    // Otherwise:
265    //     throw an OperationError.
266    let tag_length = match normalized_algorithm.tag_length {
267        None => 128,
268        Some(tag_length) if matches!(tag_length, 64 | 96 | 128) => tag_length,
269        _ => {
270            return Err(Error::Operation(Some(
271                "The tagLength member of normalizedAlgorithm is present, \
272                and not one of 64, 96, or 128"
273                    .to_string(),
274            )));
275        },
276    };
277
278    // Step 3. If ciphertext has a length less than tagLength bits, then throw an OperationError.
279    if ciphertext.len() * 8 < tag_length as usize {
280        return Err(Error::Operation(Some(
281            "Ciphertext has a length less than tagLength bits".to_string(),
282        )));
283    }
284
285    // Step 4. Let additionalData be the additionalData member of normalizedAlgorithm if present or
286    // the empty octet string otherwise.
287    let additional_data = normalized_algorithm
288        .additional_data
289        .as_deref()
290        .unwrap_or_default();
291
292    // Step 5. Perform the OCB-DECRYPT function described in Section 4.3 of [RFC7253] using AES as
293    // the block cipher, using the key represented by [[handle]] internal slot of key as the K
294    // input parameter, the iv member of normalizedAlgorithm as the N input parameter,
295    // additionalData as the A input parameter, ciphertext as the C input parameter, and tagLength
296    // as the TAGLEN global parameter.
297    //
298    // If the result of the algorithm is the indication of authentication failure, "INVALID":
299    //     throw an OperationError
300    // Otherwise:
301    //     Let plaintext be the output P of OCB-DECRYPT.
302    //
303    // NOTE: We only support IV(nonce) size from 6 bytes to 15 bytes because of the restriction
304    // from the `ocb3` crate <https://docs.rs/ocb3/latest/ocb3/struct.Ocb3.html>. This range is
305    // suggested in the paper <https://eprint.iacr.org/2023/326.pdf> to prevent an attack.
306    let iv = &normalized_algorithm.iv;
307    let plaintext = match key.handle() {
308        Handle::Aes128Key(key) => match (iv.len(), tag_length) {
309            (6, 64) => ocb_decrypt::<Aes128, U6, U8>(key, ciphertext, iv, additional_data)?,
310            (7, 64) => ocb_decrypt::<Aes128, U7, U8>(key, ciphertext, iv, additional_data)?,
311            (8, 64) => ocb_decrypt::<Aes128, U8, U8>(key, ciphertext, iv, additional_data)?,
312            (9, 64) => ocb_decrypt::<Aes128, U9, U8>(key, ciphertext, iv, additional_data)?,
313            (10, 64) => ocb_decrypt::<Aes128, U10, U8>(key, ciphertext, iv, additional_data)?,
314            (11, 64) => ocb_decrypt::<Aes128, U11, U8>(key, ciphertext, iv, additional_data)?,
315            (12, 64) => ocb_decrypt::<Aes128, U12, U8>(key, ciphertext, iv, additional_data)?,
316            (13, 64) => ocb_decrypt::<Aes128, U13, U8>(key, ciphertext, iv, additional_data)?,
317            (14, 64) => ocb_decrypt::<Aes128, U14, U8>(key, ciphertext, iv, additional_data)?,
318            (15, 64) => ocb_decrypt::<Aes128, U15, U8>(key, ciphertext, iv, additional_data)?,
319
320            (6, 96) => ocb_decrypt::<Aes128, U6, U12>(key, ciphertext, iv, additional_data)?,
321            (7, 96) => ocb_decrypt::<Aes128, U7, U12>(key, ciphertext, iv, additional_data)?,
322            (8, 96) => ocb_decrypt::<Aes128, U8, U12>(key, ciphertext, iv, additional_data)?,
323            (9, 96) => ocb_decrypt::<Aes128, U9, U12>(key, ciphertext, iv, additional_data)?,
324            (10, 96) => ocb_decrypt::<Aes128, U10, U12>(key, ciphertext, iv, additional_data)?,
325            (11, 96) => ocb_decrypt::<Aes128, U11, U12>(key, ciphertext, iv, additional_data)?,
326            (12, 96) => ocb_decrypt::<Aes128, U12, U12>(key, ciphertext, iv, additional_data)?,
327            (13, 96) => ocb_decrypt::<Aes128, U13, U12>(key, ciphertext, iv, additional_data)?,
328            (14, 96) => ocb_decrypt::<Aes128, U14, U12>(key, ciphertext, iv, additional_data)?,
329            (15, 96) => ocb_decrypt::<Aes128, U15, U12>(key, ciphertext, iv, additional_data)?,
330
331            (6, 128) => ocb_decrypt::<Aes128, U6, U16>(key, ciphertext, iv, additional_data)?,
332            (7, 128) => ocb_decrypt::<Aes128, U7, U16>(key, ciphertext, iv, additional_data)?,
333            (8, 128) => ocb_decrypt::<Aes128, U8, U16>(key, ciphertext, iv, additional_data)?,
334            (9, 128) => ocb_decrypt::<Aes128, U9, U16>(key, ciphertext, iv, additional_data)?,
335            (10, 128) => ocb_decrypt::<Aes128, U10, U16>(key, ciphertext, iv, additional_data)?,
336            (11, 128) => ocb_decrypt::<Aes128, U11, U16>(key, ciphertext, iv, additional_data)?,
337            (12, 128) => ocb_decrypt::<Aes128, U12, U16>(key, ciphertext, iv, additional_data)?,
338            (13, 128) => ocb_decrypt::<Aes128, U13, U16>(key, ciphertext, iv, additional_data)?,
339            (14, 128) => ocb_decrypt::<Aes128, U14, U16>(key, ciphertext, iv, additional_data)?,
340            (15, 128) => ocb_decrypt::<Aes128, U15, U16>(key, ciphertext, iv, additional_data)?,
341
342            _ => {
343                return Err(Error::Operation(Some(format!(
344                    "Unsupported IV size ({}-bytes) and/or tag length ({}-bit)",
345                    iv.len(),
346                    tag_length
347                ))));
348            },
349        },
350        Handle::Aes192Key(key) => match (iv.len(), tag_length) {
351            (6, 64) => ocb_decrypt::<Aes192, U6, U8>(key, ciphertext, iv, additional_data)?,
352            (7, 64) => ocb_decrypt::<Aes192, U7, U8>(key, ciphertext, iv, additional_data)?,
353            (8, 64) => ocb_decrypt::<Aes192, U8, U8>(key, ciphertext, iv, additional_data)?,
354            (9, 64) => ocb_decrypt::<Aes192, U9, U8>(key, ciphertext, iv, additional_data)?,
355            (10, 64) => ocb_decrypt::<Aes192, U10, U8>(key, ciphertext, iv, additional_data)?,
356            (11, 64) => ocb_decrypt::<Aes192, U11, U8>(key, ciphertext, iv, additional_data)?,
357            (12, 64) => ocb_decrypt::<Aes192, U12, U8>(key, ciphertext, iv, additional_data)?,
358            (13, 64) => ocb_decrypt::<Aes192, U13, U8>(key, ciphertext, iv, additional_data)?,
359            (14, 64) => ocb_decrypt::<Aes192, U14, U8>(key, ciphertext, iv, additional_data)?,
360            (15, 64) => ocb_decrypt::<Aes192, U15, U8>(key, ciphertext, iv, additional_data)?,
361
362            (6, 96) => ocb_decrypt::<Aes192, U6, U12>(key, ciphertext, iv, additional_data)?,
363            (7, 96) => ocb_decrypt::<Aes192, U7, U12>(key, ciphertext, iv, additional_data)?,
364            (8, 96) => ocb_decrypt::<Aes192, U8, U12>(key, ciphertext, iv, additional_data)?,
365            (9, 96) => ocb_decrypt::<Aes192, U9, U12>(key, ciphertext, iv, additional_data)?,
366            (10, 96) => ocb_decrypt::<Aes192, U10, U12>(key, ciphertext, iv, additional_data)?,
367            (11, 96) => ocb_decrypt::<Aes192, U11, U12>(key, ciphertext, iv, additional_data)?,
368            (12, 96) => ocb_decrypt::<Aes192, U12, U12>(key, ciphertext, iv, additional_data)?,
369            (13, 96) => ocb_decrypt::<Aes192, U13, U12>(key, ciphertext, iv, additional_data)?,
370            (14, 96) => ocb_decrypt::<Aes192, U14, U12>(key, ciphertext, iv, additional_data)?,
371            (15, 96) => ocb_decrypt::<Aes192, U15, U12>(key, ciphertext, iv, additional_data)?,
372
373            (6, 128) => ocb_decrypt::<Aes192, U6, U16>(key, ciphertext, iv, additional_data)?,
374            (7, 128) => ocb_decrypt::<Aes192, U7, U16>(key, ciphertext, iv, additional_data)?,
375            (8, 128) => ocb_decrypt::<Aes192, U8, U16>(key, ciphertext, iv, additional_data)?,
376            (9, 128) => ocb_decrypt::<Aes192, U9, U16>(key, ciphertext, iv, additional_data)?,
377            (10, 128) => ocb_decrypt::<Aes192, U10, U16>(key, ciphertext, iv, additional_data)?,
378            (11, 128) => ocb_decrypt::<Aes192, U11, U16>(key, ciphertext, iv, additional_data)?,
379            (12, 128) => ocb_decrypt::<Aes192, U12, U16>(key, ciphertext, iv, additional_data)?,
380            (13, 128) => ocb_decrypt::<Aes192, U13, U16>(key, ciphertext, iv, additional_data)?,
381            (14, 128) => ocb_decrypt::<Aes192, U14, U16>(key, ciphertext, iv, additional_data)?,
382            (15, 128) => ocb_decrypt::<Aes192, U15, U16>(key, ciphertext, iv, additional_data)?,
383
384            _ => {
385                return Err(Error::Operation(Some(format!(
386                    "Unsupported IV size ({}-bytes) and/or tag length ({}-bit)",
387                    iv.len(),
388                    tag_length
389                ))));
390            },
391        },
392        Handle::Aes256Key(key) => match (iv.len(), tag_length) {
393            (6, 64) => ocb_decrypt::<Aes256, U6, U8>(key, ciphertext, iv, additional_data)?,
394            (7, 64) => ocb_decrypt::<Aes256, U7, U8>(key, ciphertext, iv, additional_data)?,
395            (8, 64) => ocb_decrypt::<Aes256, U8, U8>(key, ciphertext, iv, additional_data)?,
396            (9, 64) => ocb_decrypt::<Aes256, U9, U8>(key, ciphertext, iv, additional_data)?,
397            (10, 64) => ocb_decrypt::<Aes256, U10, U8>(key, ciphertext, iv, additional_data)?,
398            (11, 64) => ocb_decrypt::<Aes256, U11, U8>(key, ciphertext, iv, additional_data)?,
399            (12, 64) => ocb_decrypt::<Aes256, U12, U8>(key, ciphertext, iv, additional_data)?,
400            (13, 64) => ocb_decrypt::<Aes256, U13, U8>(key, ciphertext, iv, additional_data)?,
401            (14, 64) => ocb_decrypt::<Aes256, U14, U8>(key, ciphertext, iv, additional_data)?,
402            (15, 64) => ocb_decrypt::<Aes256, U15, U8>(key, ciphertext, iv, additional_data)?,
403
404            (6, 96) => ocb_decrypt::<Aes256, U6, U12>(key, ciphertext, iv, additional_data)?,
405            (7, 96) => ocb_decrypt::<Aes256, U7, U12>(key, ciphertext, iv, additional_data)?,
406            (8, 96) => ocb_decrypt::<Aes256, U8, U12>(key, ciphertext, iv, additional_data)?,
407            (9, 96) => ocb_decrypt::<Aes256, U9, U12>(key, ciphertext, iv, additional_data)?,
408            (10, 96) => ocb_decrypt::<Aes256, U10, U12>(key, ciphertext, iv, additional_data)?,
409            (11, 96) => ocb_decrypt::<Aes256, U11, U12>(key, ciphertext, iv, additional_data)?,
410            (12, 96) => ocb_decrypt::<Aes256, U12, U12>(key, ciphertext, iv, additional_data)?,
411            (13, 96) => ocb_decrypt::<Aes256, U13, U12>(key, ciphertext, iv, additional_data)?,
412            (14, 96) => ocb_decrypt::<Aes256, U14, U12>(key, ciphertext, iv, additional_data)?,
413            (15, 96) => ocb_decrypt::<Aes256, U15, U12>(key, ciphertext, iv, additional_data)?,
414
415            (6, 128) => ocb_decrypt::<Aes256, U6, U16>(key, ciphertext, iv, additional_data)?,
416            (7, 128) => ocb_decrypt::<Aes256, U7, U16>(key, ciphertext, iv, additional_data)?,
417            (8, 128) => ocb_decrypt::<Aes256, U8, U16>(key, ciphertext, iv, additional_data)?,
418            (9, 128) => ocb_decrypt::<Aes256, U9, U16>(key, ciphertext, iv, additional_data)?,
419            (10, 128) => ocb_decrypt::<Aes256, U10, U16>(key, ciphertext, iv, additional_data)?,
420            (11, 128) => ocb_decrypt::<Aes256, U11, U16>(key, ciphertext, iv, additional_data)?,
421            (12, 128) => ocb_decrypt::<Aes256, U12, U16>(key, ciphertext, iv, additional_data)?,
422            (13, 128) => ocb_decrypt::<Aes256, U13, U16>(key, ciphertext, iv, additional_data)?,
423            (14, 128) => ocb_decrypt::<Aes256, U14, U16>(key, ciphertext, iv, additional_data)?,
424            (15, 128) => ocb_decrypt::<Aes256, U15, U16>(key, ciphertext, iv, additional_data)?,
425
426            _ => {
427                return Err(Error::Operation(Some(format!(
428                    "Unsupported IV size ({}-bytes) and/or tag length ({}-bit)",
429                    iv.len(),
430                    tag_length
431                ))));
432            },
433        },
434        _ => {
435            return Err(Error::Operation(Some(
436                "The key handle is not representing an AES key".to_string(),
437            )));
438        },
439    };
440
441    // Step 6. Return plaintext.
442    Ok(plaintext)
443}
444
445/// Helper for Step 5 of <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-decrypt>
446fn ocb_decrypt<Cipher, NonceSize, TagSize>(
447    key: &Key<Cipher>,
448    ciphertext: &[u8],
449    iv: &[u8],
450    additional_data: &[u8],
451) -> Result<Vec<u8>, Error>
452where
453    Cipher: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + BlockCipherDecrypt,
454    Cipher: KeySizeUser,
455    NonceSize: ArraySize + IsGreaterOrEqual<U6> + IsLessOrEqual<U15>,
456    GrEq<NonceSize, U6>: NonZero,
457    LeEq<NonceSize, U15>: NonZero,
458    TagSize: ArraySize + NonZero + IsLessOrEqual<U16>,
459    LeEq<TagSize, U16>: NonZero,
460{
461    let iv = iv
462        .try_into()
463        .map_err(|_| Error::Operation(Some("Invalid AES-OCB IV".into())))?;
464    let mut plaintext = ciphertext.to_vec();
465    let cipher = Ocb3::<Cipher, NonceSize, TagSize>::new(key);
466    cipher
467        .decrypt_in_place(&iv, additional_data, &mut plaintext)
468        .map_err(|_| {
469            Error::Operation(Some("AES-OCB authenticated decryption failed".to_string()))
470        })?;
471    Ok(plaintext)
472}
473
474/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-generate-key>
475pub(crate) fn generate_key(
476    cx: &mut JSContext,
477    global: &GlobalScope,
478    normalized_algorithm: &SubtleAesKeyGenParams,
479    extractable: bool,
480    usages: Vec<KeyUsage>,
481) -> Result<DomRoot<CryptoKey>, Error> {
482    aes_common::generate_key(
483        AesAlgorithm::AesOcb,
484        cx,
485        global,
486        normalized_algorithm,
487        extractable,
488        usages,
489    )
490}
491
492/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-import-key>
493pub(crate) fn import_key(
494    cx: &mut JSContext,
495    global: &GlobalScope,
496    format: KeyFormat,
497    key_data: &[u8],
498    extractable: bool,
499    usages: Vec<KeyUsage>,
500) -> Result<DomRoot<CryptoKey>, Error> {
501    aes_common::import_key(
502        AesAlgorithm::AesOcb,
503        cx,
504        global,
505        format,
506        key_data,
507        extractable,
508        usages,
509    )
510}
511
512/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-export-key>
513pub(crate) fn export_key(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
514    aes_common::export_key(AesAlgorithm::AesOcb, format, key)
515}
516
517/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-get-key-length>
518pub(crate) fn get_key_length(
519    normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
520) -> Result<Option<u32>, Error> {
521    aes_common::get_key_length(normalized_derived_key_algorithm)
522}