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